accel_lsm330.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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 "STM"
  20. #define CHIP_ID "LSM330"
  21. #define CALIBRATION_FILE_PATH "/efs/calibration_data"
  22. #define CALIBRATION_DATA_AMOUNT 20
  23. static ssize_t accel_vendor_show(struct device *dev,
  24. struct device_attribute *attr, char *buf)
  25. {
  26. return sprintf(buf, "%s\n", VENDOR);
  27. }
  28. static ssize_t accel_name_show(struct device *dev,
  29. struct device_attribute *attr, char *buf)
  30. {
  31. return sprintf(buf, "%s\n", CHIP_ID);
  32. }
  33. int accel_open_calibration(struct ssp_data *data)
  34. {
  35. int iRet = 0;
  36. mm_segment_t old_fs;
  37. struct file *cal_filp = NULL;
  38. old_fs = get_fs();
  39. set_fs(KERNEL_DS);
  40. cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
  41. if (IS_ERR(cal_filp)) {
  42. set_fs(old_fs);
  43. iRet = PTR_ERR(cal_filp);
  44. data->accelcal.x = 0;
  45. data->accelcal.y = 0;
  46. data->accelcal.z = 0;
  47. return iRet;
  48. }
  49. iRet = cal_filp->f_op->read(cal_filp, (char *)&data->accelcal,
  50. 3 * sizeof(int), &cal_filp->f_pos);
  51. if (iRet != 3 * sizeof(int))
  52. iRet = -EIO;
  53. filp_close(cal_filp, current->files);
  54. set_fs(old_fs);
  55. ssp_dbg("[SSP]: open accel calibration %d, %d, %d\n",
  56. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  57. if ((data->accelcal.x == 0) && (data->accelcal.y == 0)
  58. && (data->accelcal.z == 0))
  59. return ERROR;
  60. return iRet;
  61. }
  62. static int enable_accel_for_cal(struct ssp_data *data)
  63. {
  64. u8 uBuf[2] = {0, 10};
  65. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  66. if (get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]) != 10) {
  67. send_instruction(data, CHANGE_DELAY,
  68. ACCELEROMETER_SENSOR, uBuf, 2);
  69. return SUCCESS;
  70. }
  71. } else {
  72. send_instruction(data, ADD_SENSOR,
  73. ACCELEROMETER_SENSOR, uBuf, 2);
  74. }
  75. return FAIL;
  76. }
  77. static void disable_accel_for_cal(struct ssp_data *data, int iDelayChanged)
  78. {
  79. u8 uBuf[2] = {0, 10};
  80. if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
  81. uBuf[1] = get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]);
  82. uBuf[0] = get_delay_cmd(uBuf[1]);
  83. if (iDelayChanged)
  84. send_instruction(data, CHANGE_DELAY,
  85. ACCELEROMETER_SENSOR, uBuf, 2);
  86. } else {
  87. send_instruction(data, REMOVE_SENSOR,
  88. ACCELEROMETER_SENSOR, uBuf, 2);
  89. }
  90. }
  91. static int accel_do_calibrate(struct ssp_data *data, int iEnable)
  92. {
  93. int iSum[3] = { 0, };
  94. int iRet = 0, iCount;
  95. struct file *cal_filp = NULL;
  96. mm_segment_t old_fs;
  97. if (iEnable) {
  98. data->accelcal.x = 0;
  99. data->accelcal.y = 0;
  100. data->accelcal.z = 0;
  101. iRet = enable_accel_for_cal(data);
  102. msleep(300);
  103. for (iCount = 0; iCount < CALIBRATION_DATA_AMOUNT; iCount++) {
  104. iSum[0] += data->buf[ACCELEROMETER_SENSOR].x;
  105. iSum[1] += data->buf[ACCELEROMETER_SENSOR].y;
  106. iSum[2] += (data->buf[ACCELEROMETER_SENSOR].z - 1024);
  107. mdelay(10);
  108. }
  109. disable_accel_for_cal(data, iRet);
  110. data->accelcal.x = (iSum[0] / CALIBRATION_DATA_AMOUNT);
  111. data->accelcal.y = (iSum[1] / CALIBRATION_DATA_AMOUNT);
  112. data->accelcal.z = (iSum[2] / CALIBRATION_DATA_AMOUNT);
  113. } else {
  114. data->accelcal.x = 0;
  115. data->accelcal.y = 0;
  116. data->accelcal.z = 0;
  117. }
  118. ssp_dbg("[SSP]: do accel calibrate %d, %d, %d\n",
  119. data->accelcal.x, data->accelcal.y, data->accelcal.z);
  120. old_fs = get_fs();
  121. set_fs(KERNEL_DS);
  122. cal_filp = filp_open(CALIBRATION_FILE_PATH,
  123. O_CREAT | O_TRUNC | O_WRONLY, 0666);
  124. if (IS_ERR(cal_filp)) {
  125. pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
  126. set_fs(old_fs);
  127. iRet = PTR_ERR(cal_filp);
  128. return iRet;
  129. }
  130. iRet = cal_filp->f_op->write(cal_filp, (char *)&data->accelcal,
  131. 3 * sizeof(int), &cal_filp->f_pos);
  132. if (iRet != 3 * sizeof(int)) {
  133. pr_err("[SSP]: %s - Can't write the accelcal to file\n",
  134. __func__);
  135. iRet = -EIO;
  136. }
  137. filp_close(cal_filp, current->files);
  138. set_fs(old_fs);
  139. return iRet;
  140. }
  141. static ssize_t accel_calibration_show(struct device *dev,
  142. struct device_attribute *attr, char *buf)
  143. {
  144. int iRet;
  145. int iCount = 0;
  146. struct ssp_data *data = dev_get_drvdata(dev);
  147. iRet = accel_open_calibration(data);
  148. if (iRet < 0)
  149. pr_err("[SSP]: %s - calibration open failed\n", __func__);
  150. ssp_dbg("[SSP] Cal data : %d %d %d - %d\n",
  151. data->accelcal.x, data->accelcal.y, data->accelcal.z, iRet);
  152. iCount = sprintf(buf, "%d %d %d %d\n", iRet, data->accelcal.x,
  153. data->accelcal.y, data->accelcal.z);
  154. return iCount;
  155. }
  156. static ssize_t accel_calibration_store(struct device *dev,
  157. struct device_attribute *attr, const char *buf, size_t size)
  158. {
  159. int iRet;
  160. int64_t dEnable;
  161. struct ssp_data *data = dev_get_drvdata(dev);
  162. iRet = strict_strtoll(buf, 10, &dEnable);
  163. if (iRet < 0)
  164. return iRet;
  165. iRet = accel_do_calibrate(data, (int)dEnable);
  166. if (iRet < 0)
  167. pr_err("[SSP]: %s - accel_do_calibrate() failed\n", __func__);
  168. return size;
  169. }
  170. static ssize_t raw_data_read(struct device *dev,
  171. struct device_attribute *attr, char *buf)
  172. {
  173. struct ssp_data *data = dev_get_drvdata(dev);
  174. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  175. data->buf[ACCELEROMETER_SENSOR].x,
  176. data->buf[ACCELEROMETER_SENSOR].y,
  177. data->buf[ACCELEROMETER_SENSOR].z);
  178. }
  179. static ssize_t accel_reactive_alert_store(struct device *dev,
  180. struct device_attribute *attr, const char *buf, size_t size)
  181. {
  182. char chTempBuf[2] = {0, 10};
  183. int iRet, iDelayCnt = 0;
  184. struct ssp_data *data = dev_get_drvdata(dev);
  185. if (sysfs_streq(buf, "1"))
  186. ssp_dbg("[SSP]: %s - on\n", __func__);
  187. else if (sysfs_streq(buf, "0"))
  188. ssp_dbg("[SSP]: %s - off\n", __func__);
  189. else if (sysfs_streq(buf, "2")) {
  190. ssp_dbg("[SSP]: %s - factory\n", __func__);
  191. data->uFactorydataReady = 0;
  192. memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
  193. data->bAccelAlert = false;
  194. iRet = send_instruction(data, FACTORY_MODE,
  195. ACCELEROMETER_FACTORY, chTempBuf, 2);
  196. while (!(data->uFactorydataReady & (1 << ACCELEROMETER_FACTORY))
  197. && (iDelayCnt++ < 150)
  198. && (iRet == SUCCESS))
  199. msleep(20);
  200. if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
  201. pr_err("[SSP]: %s - accel Selftest Timeout!!\n",
  202. __func__);
  203. goto exit;
  204. }
  205. mdelay(5);
  206. data->bAccelAlert = data->uFactorydata[0];
  207. ssp_dbg("[SSP]: %s factory test success!\n", __func__);
  208. } else {
  209. pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
  210. return -EINVAL;
  211. }
  212. exit:
  213. return size;
  214. }
  215. static ssize_t accel_reactive_alert_show(struct device *dev,
  216. struct device_attribute *attr, char *buf)
  217. {
  218. bool bSuccess = false;
  219. struct ssp_data *data = dev_get_drvdata(dev);
  220. if (data->bAccelAlert == true)
  221. bSuccess = true;
  222. else
  223. bSuccess = false;
  224. data->bAccelAlert = false;
  225. return sprintf(buf, "%u\n", bSuccess);
  226. }
  227. static DEVICE_ATTR(name, S_IRUGO, accel_name_show, NULL);
  228. static DEVICE_ATTR(vendor, S_IRUGO, accel_vendor_show, NULL);
  229. static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
  230. accel_calibration_show, accel_calibration_store);
  231. static DEVICE_ATTR(raw_data, S_IRUGO, raw_data_read, NULL);
  232. static DEVICE_ATTR(reactive_alert, S_IRUGO | S_IWUSR | S_IWGRP,
  233. accel_reactive_alert_show, accel_reactive_alert_store);
  234. static struct device_attribute *acc_attrs[] = {
  235. &dev_attr_name,
  236. &dev_attr_vendor,
  237. &dev_attr_calibration,
  238. &dev_attr_raw_data,
  239. &dev_attr_reactive_alert,
  240. NULL,
  241. };
  242. void initialize_accel_factorytest(struct ssp_data *data)
  243. {
  244. sensors_register(data->acc_device, data, acc_attrs,
  245. "accelerometer_sensor");
  246. }
  247. void remove_accel_factorytest(struct ssp_data *data)
  248. {
  249. sensors_unregister(data->acc_device, acc_attrs);
  250. }