accel_mpu6500.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. #ifdef CONFIG_MACH_KACTIVELTE_KOR
  22. #define CALIBRATION_FILE_PATH "/efs/FactoryApp/calibration_data"
  23. #else
  24. #define CALIBRATION_FILE_PATH "/efs/calibration_data"
  25. #endif
  26. #define CALIBRATION_DATA_AMOUNT 20
  27. static ssize_t accel_vendor_show(struct device *dev,
  28. struct device_attribute *attr, char *buf)
  29. {
  30. return sprintf(buf, "%s\n", VENDOR);
  31. }
  32. static ssize_t accel_name_show(struct device *dev,
  33. struct device_attribute *attr, char *buf)
  34. {
  35. return sprintf(buf, "%s\n", CHIP_ID);
  36. }
  37. int accel_open_calibration(struct ssp_data *data)
  38. {
  39. int iRet = 0;
  40. mm_segment_t old_fs;
  41. struct file *cal_filp = NULL;
  42. old_fs = get_fs();
  43. set_fs(KERNEL_DS);
  44. cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY | O_NOFOLLOW | O_NONBLOCK, 0660);
  45. if (IS_ERR(cal_filp)) {
  46. set_fs(old_fs);
  47. iRet = PTR_ERR(cal_filp);
  48. data->accelcal.x = 0;
  49. data->accelcal.y = 0;
  50. data->accelcal.z = 0;
  51. return iRet;
  52. }
  53. iRet = cal_filp->f_op->read(cal_filp, (char *)&data->accelcal,
  54. 3 * sizeof(int), &cal_filp->f_pos);
  55. if (iRet != 3 * sizeof(int))
  56. iRet = -EIO;
  57. filp_close(cal_filp, current->files);
  58. set_fs(old_fs);
  59. ssp_dbg("[SSP]: open accel calibration %d, %d, %d\n",
  60. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  61. if ((data->accelcal.x == 0) && (data->accelcal.y == 0)
  62. && (data->accelcal.z == 0))
  63. return ERROR;
  64. return iRet;
  65. }
  66. int set_accel_cal(struct ssp_data *data)
  67. {
  68. int iRet = 0;
  69. struct ssp_msg *msg;
  70. s16 accel_cal[3];
  71. if (!(data->uSensorState & (1 << ACCELEROMETER_SENSOR))) {
  72. pr_info("[SSP]: %s - Skip this function!!!"\
  73. ", accel sensor is not connected(0x%x)\n",
  74. __func__, data->uSensorState);
  75. return iRet;
  76. }
  77. accel_cal[0] = data->accelcal.x;
  78. accel_cal[1] = data->accelcal.y;
  79. accel_cal[2] = data->accelcal.z;
  80. msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  81. msg->cmd = MSG2SSP_AP_MCU_SET_ACCEL_CAL;
  82. msg->length = 6;
  83. msg->options = AP2HUB_WRITE;
  84. msg->buffer = (char*) kzalloc(6, GFP_KERNEL);
  85. msg->free_buffer = 1;
  86. memcpy(msg->buffer, accel_cal, 6);
  87. iRet = ssp_spi_async(data, msg);
  88. if (iRet != SUCCESS) {
  89. pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
  90. iRet = ERROR;
  91. }
  92. pr_info("[SSP] Set accel cal data %d, %d, %d\n", accel_cal[0], accel_cal[1], accel_cal[2]);
  93. return iRet;
  94. }
  95. static int enable_accel_for_cal(struct ssp_data *data)
  96. {
  97. u8 uBuf[9] = { 0, };
  98. s32 dMsDelay = get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]);
  99. memcpy(&uBuf[0], &dMsDelay, 4);
  100. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  101. if (get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]) != 10) {
  102. send_instruction(data, CHANGE_DELAY,
  103. ACCELEROMETER_SENSOR, uBuf, 9);
  104. return SUCCESS;
  105. }
  106. } else {
  107. send_instruction(data, ADD_SENSOR,
  108. ACCELEROMETER_SENSOR, uBuf, 9);
  109. }
  110. return FAIL;
  111. }
  112. static void disable_accel_for_cal(struct ssp_data *data, int iDelayChanged)
  113. {
  114. u8 uBuf[9] = { 0, };
  115. s32 dMsDelay = get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]);
  116. memcpy(&uBuf[0], &dMsDelay, 4);
  117. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  118. if (iDelayChanged)
  119. send_instruction(data, CHANGE_DELAY,
  120. ACCELEROMETER_SENSOR, uBuf, 9);
  121. } else {
  122. send_instruction(data, REMOVE_SENSOR,
  123. ACCELEROMETER_SENSOR, uBuf, 4);
  124. }
  125. }
  126. static int accel_do_calibrate(struct ssp_data *data, int iEnable)
  127. {
  128. int iSum[3] = { 0, };
  129. int iRet = 0, iCount;
  130. struct file *cal_filp = NULL;
  131. mm_segment_t old_fs;
  132. if (iEnable) {
  133. data->accelcal.x = 0;
  134. data->accelcal.y = 0;
  135. data->accelcal.z = 0;
  136. set_accel_cal(data);
  137. iRet = enable_accel_for_cal(data);
  138. msleep(300);
  139. for (iCount = 0; iCount < CALIBRATION_DATA_AMOUNT; iCount++) {
  140. iSum[0] += data->buf[ACCELEROMETER_SENSOR].x;
  141. iSum[1] += data->buf[ACCELEROMETER_SENSOR].y;
  142. iSum[2] += data->buf[ACCELEROMETER_SENSOR].z;
  143. mdelay(10);
  144. }
  145. disable_accel_for_cal(data, iRet);
  146. data->accelcal.x = (iSum[0] / CALIBRATION_DATA_AMOUNT);
  147. data->accelcal.y = (iSum[1] / CALIBRATION_DATA_AMOUNT);
  148. data->accelcal.z = (iSum[2] / CALIBRATION_DATA_AMOUNT);
  149. if (data->accelcal.z > 0)
  150. data->accelcal.z -= MAX_ACCEL_1G;
  151. else if (data->accelcal.z < 0)
  152. data->accelcal.z += MAX_ACCEL_1G;
  153. } else {
  154. data->accelcal.x = 0;
  155. data->accelcal.y = 0;
  156. data->accelcal.z = 0;
  157. }
  158. ssp_dbg("[SSP]: do accel calibrate %d, %d, %d\n",
  159. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  160. old_fs = get_fs();
  161. set_fs(KERNEL_DS);
  162. cal_filp = filp_open(CALIBRATION_FILE_PATH,
  163. O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_NONBLOCK, 0660);
  164. if (IS_ERR(cal_filp)) {
  165. pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
  166. set_fs(old_fs);
  167. iRet = PTR_ERR(cal_filp);
  168. return iRet;
  169. }
  170. iRet = cal_filp->f_op->write(cal_filp, (char *)&data->accelcal,
  171. 3 * sizeof(int), &cal_filp->f_pos);
  172. if (iRet != 3 * sizeof(int)) {
  173. pr_err("[SSP]: %s - Can't write the accelcal to file\n",
  174. __func__);
  175. iRet = -EIO;
  176. }
  177. filp_close(cal_filp, current->files);
  178. set_fs(old_fs);
  179. set_accel_cal(data);
  180. return iRet;
  181. }
  182. static ssize_t accel_calibration_show(struct device *dev,
  183. struct device_attribute *attr, char *buf)
  184. {
  185. int iRet;
  186. int iCount = 0;
  187. struct ssp_data *data = dev_get_drvdata(dev);
  188. iRet = accel_open_calibration(data);
  189. if (iRet < 0)
  190. pr_err("[SSP]: %s - calibration open failed(%d)\n", __func__, iRet);
  191. ssp_dbg("[SSP] Cal data : %d %d %d - %d\n",
  192. data->accelcal.x, data->accelcal.y, data->accelcal.z, iRet);
  193. iCount = sprintf(buf, "%d %d %d %d\n", iRet, data->accelcal.x,
  194. data->accelcal.y, data->accelcal.z);
  195. return iCount;
  196. }
  197. static ssize_t accel_calibration_store(struct device *dev,
  198. struct device_attribute *attr, const char *buf, size_t size)
  199. {
  200. int iRet;
  201. int64_t dEnable;
  202. struct ssp_data *data = dev_get_drvdata(dev);
  203. iRet = kstrtoll(buf, 10, &dEnable);
  204. if (iRet < 0)
  205. return iRet;
  206. iRet = accel_do_calibrate(data, (int)dEnable);
  207. if (iRet < 0)
  208. pr_err("[SSP]: %s - accel_do_calibrate() failed\n", __func__);
  209. return size;
  210. }
  211. static ssize_t raw_data_read(struct device *dev,
  212. struct device_attribute *attr, char *buf)
  213. {
  214. struct ssp_data *data = dev_get_drvdata(dev);
  215. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  216. data->buf[ACCELEROMETER_SENSOR].x,
  217. data->buf[ACCELEROMETER_SENSOR].y,
  218. data->buf[ACCELEROMETER_SENSOR].z);
  219. }
  220. static ssize_t accel_reactive_alert_store(struct device *dev,
  221. struct device_attribute *attr, const char *buf, size_t size)
  222. {
  223. int iRet = 0;
  224. char chTempBuf = 1;
  225. struct ssp_data *data = dev_get_drvdata(dev);
  226. struct ssp_msg *msg;
  227. if (sysfs_streq(buf, "1"))
  228. ssp_dbg("[SSP]: %s - on\n", __func__);
  229. else if (sysfs_streq(buf, "0"))
  230. ssp_dbg("[SSP]: %s - off\n", __func__);
  231. else if (sysfs_streq(buf, "2")) {
  232. ssp_dbg("[SSP]: %s - factory\n", __func__);
  233. data->bAccelAlert = 0;
  234. msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  235. msg->cmd = ACCELEROMETER_FACTORY;
  236. msg->length = 1;
  237. msg->options = AP2HUB_READ;
  238. msg->data = chTempBuf;
  239. msg->buffer = &chTempBuf;
  240. msg->free_buffer = 0;
  241. iRet = ssp_spi_sync(data, msg, 3000);
  242. data->bAccelAlert = chTempBuf;
  243. if (iRet != SUCCESS) {
  244. pr_err("[SSP]: %s - accel Selftest Timeout!!\n", __func__);
  245. goto exit;
  246. }
  247. ssp_dbg("[SSP]: %s factory test success!\n", __func__);
  248. } else {
  249. pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
  250. return -EINVAL;
  251. }
  252. exit: return size;
  253. }
  254. static ssize_t accel_reactive_alert_show(struct device *dev,
  255. struct device_attribute *attr, char *buf)
  256. {
  257. bool bSuccess = false;
  258. struct ssp_data *data = dev_get_drvdata(dev);
  259. if (data->bAccelAlert == true)
  260. bSuccess = true;
  261. else
  262. bSuccess = false;
  263. data->bAccelAlert = false;
  264. return sprintf(buf, "%u\n", bSuccess);
  265. }
  266. static ssize_t accel_hw_selftest_show(struct device *dev,
  267. struct device_attribute *attr, char *buf)
  268. {
  269. char chTempBuf[8] = { 2, 0, };
  270. s8 init_status = 0, result = -1;
  271. s16 shift_ratio[3] = { 0, };
  272. int iRet;
  273. struct ssp_data *data = dev_get_drvdata(dev);
  274. struct ssp_msg *msg;
  275. msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  276. msg->cmd = ACCELEROMETER_FACTORY;
  277. msg->length = 8;
  278. msg->options = AP2HUB_READ;
  279. msg->data = chTempBuf[0];
  280. msg->buffer = chTempBuf;
  281. msg->free_buffer = 0;
  282. iRet = ssp_spi_sync(data, msg, 3000);
  283. if (iRet != SUCCESS) {
  284. pr_err("[SSP] %s - accel hw selftest Timeout!!\n", __func__);
  285. return sprintf(buf, "%d,%d,%d,%d\n", -5, 0, 0, 0);
  286. }
  287. init_status = chTempBuf[0];
  288. shift_ratio[0] = (s16)((chTempBuf[2] << 8) + chTempBuf[1]);
  289. shift_ratio[1] = (s16)((chTempBuf[4] << 8) + chTempBuf[3]);
  290. shift_ratio[2] = (s16)((chTempBuf[6] << 8) + chTempBuf[5]);
  291. result = chTempBuf[7];
  292. pr_info("[SSP] %s - %d, %d, %d, %d, %d\n", __func__,
  293. init_status, result, shift_ratio[0], shift_ratio[1], shift_ratio[2]);
  294. return sprintf(buf, "%d,%d.%d,%d.%d,%d.%d\n", result,
  295. shift_ratio[0] / 10, shift_ratio[0] % 10,
  296. shift_ratio[1] / 10, shift_ratio[1] % 10,
  297. shift_ratio[2] / 10, shift_ratio[2] % 10);
  298. }
  299. static ssize_t accel_lowpassfilter_store(struct device *dev,
  300. struct device_attribute *attr, const char *buf, size_t size)
  301. {
  302. int iRet = 0, new_enable = 1;
  303. struct ssp_data *data = dev_get_drvdata(dev);
  304. struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  305. if (msg == NULL) {
  306. pr_err("[SSP] %s, failed to alloc memory\n", __func__);
  307. goto exit;
  308. }
  309. if (sysfs_streq(buf, "1"))
  310. new_enable = 1;
  311. else if (sysfs_streq(buf, "0"))
  312. new_enable = 0;
  313. else
  314. ssp_dbg("[SSP]: %s - invalid value!\n", __func__);
  315. msg->cmd = MSG2SSP_AP_SENSOR_LPF;
  316. msg->length = 1;
  317. msg->options = AP2HUB_WRITE;
  318. msg->buffer = (char*) kzalloc(1, GFP_KERNEL);
  319. if (msg->buffer == NULL) {
  320. pr_err("[SSP] %s, failed to alloc memory\n", __func__);
  321. kfree(msg);
  322. goto exit;
  323. }
  324. *msg->buffer = new_enable;
  325. msg->free_buffer = 1;
  326. iRet = ssp_spi_async(data, msg);
  327. if (iRet != SUCCESS)
  328. pr_err("[SSP] %s - fail %d\n", __func__, iRet);
  329. else
  330. pr_info("[SSP] %s - %d\n", __func__, new_enable);
  331. exit:
  332. return size;
  333. }
  334. static DEVICE_ATTR(name, S_IRUGO, accel_name_show, NULL);
  335. static DEVICE_ATTR(vendor, S_IRUGO, accel_vendor_show, NULL);
  336. static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
  337. accel_calibration_show, accel_calibration_store);
  338. static DEVICE_ATTR(raw_data, S_IRUGO, raw_data_read, NULL);
  339. static DEVICE_ATTR(reactive_alert, S_IRUGO | S_IWUSR | S_IWGRP,
  340. accel_reactive_alert_show, accel_reactive_alert_store);
  341. static DEVICE_ATTR(selftest, S_IRUGO, accel_hw_selftest_show, NULL);
  342. static DEVICE_ATTR(lowpassfilter, S_IWUSR | S_IWGRP,
  343. NULL, accel_lowpassfilter_store);
  344. static struct device_attribute *acc_attrs[] = {
  345. &dev_attr_name,
  346. &dev_attr_vendor,
  347. &dev_attr_calibration,
  348. &dev_attr_raw_data,
  349. &dev_attr_reactive_alert,
  350. &dev_attr_selftest,
  351. &dev_attr_lowpassfilter,
  352. NULL,
  353. };
  354. void initialize_accel_factorytest(struct ssp_data *data)
  355. {
  356. sensors_register(data->acc_device, data, acc_attrs,
  357. "accelerometer_sensor");
  358. }
  359. void remove_accel_factorytest(struct ssp_data *data)
  360. {
  361. sensors_unregister(data->acc_device, acc_attrs);
  362. }