accel_mpu6500.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include "../ssp.h"
  16. /*************************************************************************/
  17. /* factory Sysfs */
  18. /*************************************************************************/
  19. #define VENDOR "INVENSENSE"
  20. #define CHIP_ID "MPU6500"
  21. #define VENDOR_K330 "STM"
  22. #define CHIP_ID_K330 "K330"
  23. #define CALIBRATION_FILE_PATH "/efs/calibration_data"
  24. #define CALIBRATION_DATA_AMOUNT 20
  25. static ssize_t accel_vendor_show(struct device *dev,
  26. struct device_attribute *attr, char *buf)
  27. {
  28. struct ssp_data *data = dev_get_drvdata(dev);
  29. if (data->sns_combination == STM_K330_AG)
  30. return sprintf(buf, "%s\n", VENDOR_K330);
  31. else
  32. return sprintf(buf, "%s\n", VENDOR);
  33. }
  34. static ssize_t accel_name_show(struct device *dev,
  35. struct device_attribute *attr, char *buf)
  36. {
  37. struct ssp_data *data = dev_get_drvdata(dev);
  38. if (data->sns_combination == STM_K330_AG)
  39. return sprintf(buf, "%s\n", CHIP_ID_K330);
  40. else
  41. return sprintf(buf, "%s\n", CHIP_ID);
  42. }
  43. int accel_open_calibration(struct ssp_data *data)
  44. {
  45. int iRet = 0;
  46. mm_segment_t old_fs;
  47. struct file *cal_filp = NULL;
  48. old_fs = get_fs();
  49. set_fs(KERNEL_DS);
  50. cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
  51. if (IS_ERR(cal_filp)) {
  52. set_fs(old_fs);
  53. iRet = PTR_ERR(cal_filp);
  54. data->accelcal.x = 0;
  55. data->accelcal.y = 0;
  56. data->accelcal.z = 0;
  57. return iRet;
  58. }
  59. iRet = cal_filp->f_op->read(cal_filp, (char *)&data->accelcal,
  60. 3 * sizeof(int), &cal_filp->f_pos);
  61. if (iRet != 3 * sizeof(int))
  62. iRet = -EIO;
  63. filp_close(cal_filp, current->files);
  64. set_fs(old_fs);
  65. ssp_dbg("[SSP]: open accel calibration %d, %d, %d\n",
  66. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  67. if ((data->accelcal.x == 0) && (data->accelcal.y == 0)
  68. && (data->accelcal.z == 0))
  69. return ERROR;
  70. return iRet;
  71. }
  72. static int enable_accel_for_cal(struct ssp_data *data)
  73. {
  74. u8 uBuf[2] = {0, 10};
  75. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  76. if (get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]) != 10) {
  77. send_instruction(data, CHANGE_DELAY,
  78. ACCELEROMETER_SENSOR, uBuf, 2);
  79. return SUCCESS;
  80. }
  81. } else {
  82. send_instruction(data, ADD_SENSOR,
  83. ACCELEROMETER_SENSOR, uBuf, 2);
  84. }
  85. return FAIL;
  86. }
  87. static void disable_accel_for_cal(struct ssp_data *data, int iDelayChanged)
  88. {
  89. u8 uBuf[2] = {0, 10};
  90. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  91. uBuf[1] = get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]);
  92. uBuf[0] = get_delay_cmd(uBuf[1]);
  93. if (iDelayChanged)
  94. send_instruction(data, CHANGE_DELAY,
  95. ACCELEROMETER_SENSOR, uBuf, 2);
  96. } else {
  97. send_instruction(data, REMOVE_SENSOR,
  98. ACCELEROMETER_SENSOR, uBuf, 2);
  99. }
  100. }
  101. static int accel_do_calibrate(struct ssp_data *data, int iEnable)
  102. {
  103. int iSum[3] = { 0, };
  104. int iRet = 0, iCount;
  105. struct file *cal_filp = NULL;
  106. mm_segment_t old_fs;
  107. if (iEnable) {
  108. data->accelcal.x = 0;
  109. data->accelcal.y = 0;
  110. data->accelcal.z = 0;
  111. iRet = enable_accel_for_cal(data);
  112. msleep(300);
  113. for (iCount = 0; iCount < CALIBRATION_DATA_AMOUNT; iCount++) {
  114. iSum[0] += data->buf[ACCELEROMETER_SENSOR].x;
  115. iSum[1] += data->buf[ACCELEROMETER_SENSOR].y;
  116. iSum[2] += data->buf[ACCELEROMETER_SENSOR].z;
  117. mdelay(10);
  118. }
  119. disable_accel_for_cal(data, iRet);
  120. data->accelcal.x = (iSum[0] / CALIBRATION_DATA_AMOUNT);
  121. data->accelcal.y = (iSum[1] / CALIBRATION_DATA_AMOUNT);
  122. data->accelcal.z = (iSum[2] / CALIBRATION_DATA_AMOUNT);
  123. if (data->accelcal.z > 0)
  124. data->accelcal.z -= MAX_ACCEL_1G;
  125. else if (data->accelcal.z < 0)
  126. data->accelcal.z += MAX_ACCEL_1G;
  127. } else {
  128. data->accelcal.x = 0;
  129. data->accelcal.y = 0;
  130. data->accelcal.z = 0;
  131. }
  132. ssp_dbg("[SSP]: do accel calibrate %d, %d, %d\n",
  133. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  134. old_fs = get_fs();
  135. set_fs(KERNEL_DS);
  136. cal_filp = filp_open(CALIBRATION_FILE_PATH,
  137. O_CREAT | O_TRUNC | O_WRONLY, 0666);
  138. if (IS_ERR(cal_filp)) {
  139. pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
  140. set_fs(old_fs);
  141. iRet = PTR_ERR(cal_filp);
  142. return iRet;
  143. }
  144. iRet = cal_filp->f_op->write(cal_filp, (char *)&data->accelcal,
  145. 3 * sizeof(int), &cal_filp->f_pos);
  146. if (iRet != 3 * sizeof(int)) {
  147. pr_err("[SSP]: %s - Can't write the accelcal to file\n",
  148. __func__);
  149. iRet = -EIO;
  150. }
  151. filp_close(cal_filp, current->files);
  152. set_fs(old_fs);
  153. return iRet;
  154. }
  155. static ssize_t accel_calibration_show(struct device *dev,
  156. struct device_attribute *attr, char *buf)
  157. {
  158. int iRet;
  159. int iCount = 0;
  160. struct ssp_data *data = dev_get_drvdata(dev);
  161. iRet = accel_open_calibration(data);
  162. if (iRet < 0)
  163. pr_err("[SSP]: %s - calibration open failed(%d)\n", __func__, iRet);
  164. ssp_dbg("[SSP] Cal data : %d %d %d - %d\n",
  165. data->accelcal.x, data->accelcal.y, data->accelcal.z, iRet);
  166. iCount = sprintf(buf, "%d %d %d %d\n", iRet, data->accelcal.x,
  167. data->accelcal.y, data->accelcal.z);
  168. return iCount;
  169. }
  170. static ssize_t accel_calibration_store(struct device *dev,
  171. struct device_attribute *attr, const char *buf, size_t size)
  172. {
  173. int iRet;
  174. int64_t dEnable;
  175. struct ssp_data *data = dev_get_drvdata(dev);
  176. iRet = kstrtoll(buf, 10, &dEnable);
  177. if (iRet < 0)
  178. return iRet;
  179. iRet = accel_do_calibrate(data, (int)dEnable);
  180. if (iRet < 0)
  181. pr_err("[SSP]: %s - accel_do_calibrate() failed\n", __func__);
  182. return size;
  183. }
  184. static ssize_t raw_data_read(struct device *dev,
  185. struct device_attribute *attr, char *buf)
  186. {
  187. struct ssp_data *data = dev_get_drvdata(dev);
  188. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  189. data->buf[ACCELEROMETER_SENSOR].x,
  190. data->buf[ACCELEROMETER_SENSOR].y,
  191. data->buf[ACCELEROMETER_SENSOR].z);
  192. }
  193. static ssize_t accel_reactive_alert_store(struct device *dev,
  194. struct device_attribute *attr, const char *buf, size_t size)
  195. {
  196. char chTempBuf[2] = {0, 10};
  197. int iRet, iDelayCnt = 0;
  198. struct ssp_data *data = dev_get_drvdata(dev);
  199. if (sysfs_streq(buf, "1"))
  200. ssp_dbg("[SSP]: %s - on\n", __func__);
  201. else if (sysfs_streq(buf, "0"))
  202. ssp_dbg("[SSP]: %s - off\n", __func__);
  203. else if (sysfs_streq(buf, "2")) {
  204. ssp_dbg("[SSP]: %s - factory\n", __func__);
  205. data->uFactorydataReady = 0;
  206. memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
  207. data->bAccelAlert = false;
  208. iRet = send_instruction(data, FACTORY_MODE,
  209. ACCELEROMETER_FACTORY, chTempBuf, 2);
  210. while (!(data->uFactorydataReady & (1 << ACCELEROMETER_FACTORY))
  211. && (iDelayCnt++ < 150)
  212. && (iRet == SUCCESS))
  213. msleep(20);
  214. if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
  215. pr_err("[SSP]: %s - accel Selftest Timeout!!\n",
  216. __func__);
  217. goto exit;
  218. }
  219. mdelay(5);
  220. data->bAccelAlert = data->uFactorydata[0];
  221. ssp_dbg("[SSP]: %s factory test success!\n", __func__);
  222. } else {
  223. pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
  224. return -EINVAL;
  225. }
  226. exit:
  227. return size;
  228. }
  229. static ssize_t accel_reactive_alert_show(struct device *dev,
  230. struct device_attribute *attr, char *buf)
  231. {
  232. bool bSuccess = false;
  233. struct ssp_data *data = dev_get_drvdata(dev);
  234. if (data->bAccelAlert == true)
  235. bSuccess = true;
  236. else
  237. bSuccess = false;
  238. data->bAccelAlert = false;
  239. return sprintf(buf, "%u\n", bSuccess);
  240. }
  241. static DEVICE_ATTR(name, S_IRUGO, accel_name_show, NULL);
  242. static DEVICE_ATTR(vendor, S_IRUGO, accel_vendor_show, NULL);
  243. static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
  244. accel_calibration_show, accel_calibration_store);
  245. static DEVICE_ATTR(raw_data, S_IRUGO, raw_data_read, NULL);
  246. static DEVICE_ATTR(reactive_alert, S_IRUGO | S_IWUSR | S_IWGRP,
  247. accel_reactive_alert_show, accel_reactive_alert_store);
  248. static struct device_attribute *acc_attrs[] = {
  249. &dev_attr_name,
  250. &dev_attr_vendor,
  251. &dev_attr_calibration,
  252. &dev_attr_raw_data,
  253. &dev_attr_reactive_alert,
  254. NULL,
  255. };
  256. void initialize_accel_factorytest(struct ssp_data *data)
  257. {
  258. sensors_register(data->acc_device, data, acc_attrs,
  259. "accelerometer_sensor");
  260. }
  261. void remove_accel_factorytest(struct ssp_data *data)
  262. {
  263. sensors_unregister(data->acc_device, acc_attrs);
  264. }