gyro_mpu6050.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  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 <linux/kernel.h>
  16. #include "../ssp.h"
  17. /*************************************************************************/
  18. /* factory Sysfs */
  19. /*************************************************************************/
  20. #define VENDOR "INVENSENSE"
  21. #define CHIP_ID "MPU6050"
  22. #define CALIBRATION_FILE_PATH "/efs/gyro_cal_data"
  23. #define VERBOSE_OUT 1
  24. #define CALIBRATION_DATA_AMOUNT 20
  25. #define DEF_GYRO_FULLSCALE 2000
  26. #define DEF_GYRO_SENS (32768 / DEF_GYRO_FULLSCALE)
  27. #define DEF_BIAS_LSB_THRESH_SELF (20 * DEF_GYRO_SENS)
  28. #define DEF_RMS_LSB_TH_SELF (5 * DEF_GYRO_SENS)
  29. #define DEF_RMS_THRESH ((DEF_RMS_LSB_TH_SELF) * (DEF_RMS_LSB_TH_SELF))
  30. #define DEF_SCALE_FOR_FLOAT (1000)
  31. #define DEF_RMS_SCALE_FOR_RMS (10000)
  32. #define DEF_SQRT_SCALE_FOR_RMS (100)
  33. static ssize_t gyro_vendor_show(struct device *dev,
  34. struct device_attribute *attr, char *buf)
  35. {
  36. return sprintf(buf, "%s\n", VENDOR);
  37. }
  38. static ssize_t gyro_name_show(struct device *dev,
  39. struct device_attribute *attr, char *buf)
  40. {
  41. return sprintf(buf, "%s\n", CHIP_ID);
  42. }
  43. int gyro_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->gyrocal.x = 0;
  55. data->gyrocal.y = 0;
  56. data->gyrocal.z = 0;
  57. return iRet;
  58. }
  59. iRet = cal_filp->f_op->read(cal_filp, (char *)&data->gyrocal,
  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 gyro calibration %d, %d, %d\n",
  66. data->gyrocal.x, data->gyrocal.y, data->gyrocal.z);
  67. return iRet;
  68. }
  69. static int save_gyro_caldata(struct ssp_data *data, s16 *iCalData)
  70. {
  71. int iRet = 0;
  72. struct file *cal_filp = NULL;
  73. mm_segment_t old_fs;
  74. data->gyrocal.x = iCalData[0];
  75. data->gyrocal.y = iCalData[1];
  76. data->gyrocal.z = iCalData[2];
  77. ssp_dbg("[SSP]: do gyro calibrate %d, %d, %d\n",
  78. data->gyrocal.x, data->gyrocal.y, data->gyrocal.z);
  79. old_fs = get_fs();
  80. set_fs(KERNEL_DS);
  81. cal_filp = filp_open(CALIBRATION_FILE_PATH,
  82. O_CREAT | O_TRUNC | O_WRONLY, 0666);
  83. if (IS_ERR(cal_filp)) {
  84. pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
  85. set_fs(old_fs);
  86. iRet = PTR_ERR(cal_filp);
  87. return -EIO;
  88. }
  89. iRet = cal_filp->f_op->write(cal_filp, (char *)&data->gyrocal,
  90. 3 * sizeof(int), &cal_filp->f_pos);
  91. if (iRet != 3 * sizeof(int)) {
  92. pr_err("[SSP]: %s - Can't write gyro cal to file\n", __func__);
  93. iRet = -EIO;
  94. }
  95. filp_close(cal_filp, current->files);
  96. set_fs(old_fs);
  97. return iRet;
  98. }
  99. static ssize_t gyro_power_off(struct device *dev,
  100. struct device_attribute *attr, char *buf)
  101. {
  102. ssp_dbg("[SSP]: %s\n", __func__);
  103. return sprintf(buf, "%d\n", 1);
  104. }
  105. static ssize_t gyro_power_on(struct device *dev,
  106. struct device_attribute *attr, char *buf)
  107. {
  108. ssp_dbg("[SSP]: %s\n", __func__);
  109. return sprintf(buf, "%d\n", 1);
  110. }
  111. static ssize_t gyro_get_temp(struct device *dev,
  112. struct device_attribute *attr, char *buf)
  113. {
  114. char chTempBuf[2] = { 0, 10};
  115. unsigned char reg[2];
  116. short temperature = 0;
  117. int iDelayCnt = 0, iRet = 0;
  118. struct ssp_data *data = dev_get_drvdata(dev);
  119. data->uFactorydataReady = 0;
  120. memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
  121. iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_TEMP_FACTORY,
  122. chTempBuf, 2);
  123. while (!(data->uFactorydataReady & (1 << GYROSCOPE_TEMP_FACTORY))
  124. && (iDelayCnt++ < 150)
  125. && (iRet == SUCCESS))
  126. msleep(20);
  127. if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
  128. pr_err("[SSP]: %s - Gyro Temp Timeout!!\n", __func__);
  129. goto exit;
  130. }
  131. reg[0] = data->uFactorydata[1];
  132. reg[1] = data->uFactorydata[0];
  133. temperature = (short) (((reg[0]) << 8) | reg[1]);
  134. temperature = (((temperature + 521) / 340) + 35);
  135. ssp_dbg("[SSP]: %s - %d\n", __func__, temperature);
  136. exit:
  137. return sprintf(buf, "%d\n", temperature);
  138. }
  139. u32 mpu6050_selftest_sqrt(u32 sqsum)
  140. {
  141. u32 sq_rt;
  142. u32 g0, g1, g2, g3, g4;
  143. u32 seed;
  144. u32 next;
  145. u32 step;
  146. g4 = sqsum / 100000000;
  147. g3 = (sqsum - g4 * 100000000) / 1000000;
  148. g2 = (sqsum - g4 * 100000000 - g3 * 1000000) / 10000;
  149. g1 = (sqsum - g4 * 100000000 - g3 * 1000000 - g2 * 10000) / 100;
  150. g0 = (sqsum - g4 * 100000000 - g3 * 1000000 - g2 * 10000 - g1 * 100);
  151. next = g4;
  152. step = 0;
  153. seed = 0;
  154. while (((seed + 1) * (step + 1)) <= next) {
  155. step++;
  156. seed++;
  157. }
  158. sq_rt = seed * 10000;
  159. next = (next - (seed * step)) * 100 + g3;
  160. step = 0;
  161. seed = 2 * seed * 10;
  162. while (((seed + 1) * (step + 1)) <= next) {
  163. step++;
  164. seed++;
  165. }
  166. sq_rt = sq_rt + step * 1000;
  167. next = (next - seed * step) * 100 + g2;
  168. seed = (seed + step) * 10;
  169. step = 0;
  170. while (((seed + 1) * (step + 1)) <= next) {
  171. step++;
  172. seed++;
  173. }
  174. sq_rt = sq_rt + step * 100;
  175. next = (next - seed * step) * 100 + g1;
  176. seed = (seed + step) * 10;
  177. step = 0;
  178. while (((seed + 1) * (step + 1)) <= next) {
  179. step++;
  180. seed++;
  181. }
  182. sq_rt = sq_rt + step * 10;
  183. next = (next - seed * step) * 100 + g0;
  184. seed = (seed + step) * 10;
  185. step = 0;
  186. while (((seed + 1) * (step + 1)) <= next) {
  187. step++;
  188. seed++;
  189. }
  190. sq_rt = sq_rt + step;
  191. return sq_rt;
  192. }
  193. static ssize_t gyro_selftest_show(struct device *dev,
  194. struct device_attribute *attr, char *buf)
  195. {
  196. char chTempBuf[2] = { 3, 200};
  197. u8 initialized = 0;
  198. int i = 0, j = 0, total_count = 0, ret_val = 0;
  199. long avg[3] = {0,}, rms[3] = {0,};
  200. int gyro_bias[3] = {0,}, gyro_rms[3] = {0,};
  201. s16 iCalData[3] = {0,};
  202. char a_name[3][2] = { "X", "Y", "Z" };
  203. int iDelayCnt = 0, iRet = 0;
  204. int dps_rms[3] = { 0, };
  205. u32 temp = 0;
  206. struct ssp_data *data = dev_get_drvdata(dev);
  207. data->uFactorydataReady = 0;
  208. memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
  209. iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_FACTORY,
  210. chTempBuf, 2);
  211. while (!(data->uFactorydataReady & (1 << GYROSCOPE_FACTORY))
  212. && (iDelayCnt++ < 150)
  213. && (iRet == SUCCESS))
  214. msleep(20);
  215. if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
  216. pr_err("[SSP]: %s - Gyro Selftest Timeout!!\n", __func__);
  217. goto exit;
  218. }
  219. for (i = 0; i < 29; i++)
  220. pr_err("[SSP]: %s - uFactorydata[%d] = 0x%x\n", __func__, i,
  221. data->uFactorydata[i]);
  222. initialized = data->uFactorydata[0];
  223. total_count = (int)((data->uFactorydata[4] << 24) +
  224. (data->uFactorydata[3] << 16) +
  225. (data->uFactorydata[2] << 8) +
  226. data->uFactorydata[1]);
  227. avg[0] = (long)((data->uFactorydata[8] << 24) +
  228. (data->uFactorydata[7] << 16) +
  229. (data->uFactorydata[6] << 8) +
  230. data->uFactorydata[5]);
  231. avg[1] = (long)((data->uFactorydata[12] << 24) +
  232. (data->uFactorydata[11] << 16) +
  233. (data->uFactorydata[10] << 8) +
  234. data->uFactorydata[9]);
  235. avg[2] = (long)((data->uFactorydata[16] << 24) +
  236. (data->uFactorydata[15] << 16) +
  237. (data->uFactorydata[14] << 8) +
  238. data->uFactorydata[13]);
  239. rms[0] = (long)((data->uFactorydata[20] << 24) +
  240. (data->uFactorydata[19] << 16) +
  241. (data->uFactorydata[18] << 8) +
  242. data->uFactorydata[17]);
  243. rms[1] = (long)((data->uFactorydata[24] << 24) +
  244. (data->uFactorydata[23] << 16) +
  245. (data->uFactorydata[22] << 8) +
  246. data->uFactorydata[21]);
  247. rms[2] = (long)((data->uFactorydata[28] << 24) +
  248. (data->uFactorydata[27] << 16) +
  249. (data->uFactorydata[26] << 8) +
  250. data->uFactorydata[25]);
  251. pr_err("[SSP] init: %d, total cnt: %d", initialized, total_count);
  252. pr_err("[SSP] avg %+8ld %+8ld %+8ld (LSB)\n", avg[0], avg[1], avg[2]);
  253. pr_err("[SSP] rms %+8ld %+8ld %+8ld (LSB)\n", rms[0], rms[1], rms[2]);
  254. /*
  255. avg[0] /= total_count;
  256. avg[1] /= total_count;
  257. avg[2] /= total_count;
  258. */
  259. pr_info("[SSP] bias : %+8ld %+8ld %+8ld (LSB)\n",
  260. avg[0], avg[1], avg[2]);
  261. gyro_bias[0] = (avg[0] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
  262. gyro_bias[1] = (avg[1] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
  263. gyro_bias[2] = (avg[2] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
  264. iCalData[0] = (s16)avg[0];
  265. iCalData[1] = (s16)avg[1];
  266. iCalData[2] = (s16)avg[2];
  267. if (VERBOSE_OUT) {
  268. pr_info("[SSP] abs bias : %+8d.%03d %+8d.%03d %+8d.%03d (dps)\n",
  269. (int)abs(gyro_bias[0]) / DEF_SCALE_FOR_FLOAT,
  270. (int)abs(gyro_bias[0]) % DEF_SCALE_FOR_FLOAT,
  271. (int)abs(gyro_bias[1]) / DEF_SCALE_FOR_FLOAT,
  272. (int)abs(gyro_bias[1]) % DEF_SCALE_FOR_FLOAT,
  273. (int)abs(gyro_bias[2]) / DEF_SCALE_FOR_FLOAT,
  274. (int)abs(gyro_bias[2]) % DEF_SCALE_FOR_FLOAT);
  275. }
  276. for (j = 0; j < 3; j++) {
  277. if (abs(avg[j]) > DEF_BIAS_LSB_THRESH_SELF) {
  278. pr_info("[SSP] %s-Gyro bias (%ld) exceeded threshold "
  279. "(threshold = %d LSB)\n", a_name[j],
  280. avg[j], DEF_BIAS_LSB_THRESH_SELF);
  281. ret_val |= 1 << (3 + j);
  282. }
  283. }
  284. /* 3rd, check RMS for dead gyros
  285. If any of the RMS noise value returns zero,
  286. then we might have dead gyro or FIFO/register failure,
  287. the part is sleeping, or the part is not responsive */
  288. if (rms[0] == 0 || rms[1] == 0 || rms[2] == 0)
  289. ret_val |= 1 << 6;
  290. if (VERBOSE_OUT) {
  291. pr_info("[SSP] RMS ^ 2 : %+8ld %+8ld %+8ld\n",
  292. (long)rms[0] / total_count,
  293. (long)rms[1] / total_count, (long)rms[2] / total_count);
  294. }
  295. for (j = 0; j < 3; j++) {
  296. if (rms[j] / total_count > DEF_RMS_THRESH) {
  297. pr_info("[SSP] %s-Gyro rms (%ld) exceeded threshold "
  298. "(threshold = %d LSB)\n", a_name[j],
  299. rms[j] / total_count, DEF_RMS_THRESH);
  300. ret_val |= 1 << (7 + j);
  301. }
  302. }
  303. for (i = 0; i < 3; i++) {
  304. if (rms[i] > 10000) {
  305. temp =
  306. ((u32) (rms[i] / total_count)) *
  307. DEF_RMS_SCALE_FOR_RMS;
  308. } else {
  309. temp =
  310. ((u32) (rms[i] * DEF_RMS_SCALE_FOR_RMS)) /
  311. total_count;
  312. }
  313. if (rms[i] < 0)
  314. temp = 1 << 31;
  315. dps_rms[i] = mpu6050_selftest_sqrt(temp) / DEF_GYRO_SENS;
  316. gyro_rms[i] =
  317. dps_rms[i] * DEF_SCALE_FOR_FLOAT / DEF_SQRT_SCALE_FOR_RMS;
  318. }
  319. pr_info("[SSP] RMS : %+8d.%03d %+8d.%03d %+8d.%03d (dps)\n",
  320. (int)abs(gyro_rms[0]) / DEF_SCALE_FOR_FLOAT,
  321. (int)abs(gyro_rms[0]) % DEF_SCALE_FOR_FLOAT,
  322. (int)abs(gyro_rms[1]) / DEF_SCALE_FOR_FLOAT,
  323. (int)abs(gyro_rms[1]) % DEF_SCALE_FOR_FLOAT,
  324. (int)abs(gyro_rms[2]) / DEF_SCALE_FOR_FLOAT,
  325. (int)abs(gyro_rms[2]) % DEF_SCALE_FOR_FLOAT);
  326. if (!ret_val) {
  327. pr_err("[SSP] ret_val == 0\n");
  328. save_gyro_caldata(data, iCalData);
  329. } else {
  330. pr_err("[SSP] ret_val != 0\n");
  331. data->gyrocal.x = 0;
  332. data->gyrocal.y = 0;
  333. data->gyrocal.z = 0;
  334. /*initialized = -1;*/
  335. }
  336. exit:
  337. ssp_dbg("[SSP]: Gyro Selftest - %d,"
  338. "%d.%03d,%d.%03d,%d.%03d,"
  339. "%d.%03d,%d.%03d,%d.%03d,"
  340. "%d,%d,%d\n",
  341. ret_val,
  342. (int)abs(gyro_bias[0]/1000),
  343. (int)abs(gyro_bias[0])%1000,
  344. (int)abs(gyro_bias[1]/1000),
  345. (int)abs(gyro_bias[1])%1000,
  346. (int)abs(gyro_bias[2]/1000),
  347. (int)abs(gyro_bias[2])%1000,
  348. gyro_rms[0]/1000,
  349. (int)abs(gyro_rms[0])%1000,
  350. gyro_rms[1]/1000,
  351. (int)abs(gyro_rms[1])%1000,
  352. gyro_rms[2]/1000,
  353. (int)abs(gyro_rms[2])%1000,
  354. (int)(total_count/3),
  355. (int)(total_count/3),
  356. (int)(total_count/3));
  357. return sprintf(buf, "%d,"
  358. "%d.%03d,%d.%03d,%d.%03d,"
  359. "%d.%03d,%d.%03d,%d.%03d,"
  360. "%d,%d,%d\n",
  361. ret_val,
  362. (int)abs(gyro_bias[0]/1000),
  363. (int)abs(gyro_bias[0])%1000,
  364. (int)abs(gyro_bias[1]/1000),
  365. (int)abs(gyro_bias[1])%1000,
  366. (int)abs(gyro_bias[2]/1000),
  367. (int)abs(gyro_bias[2])%1000,
  368. gyro_rms[0]/1000,
  369. (int)abs(gyro_rms[0])%1000,
  370. gyro_rms[1]/1000,
  371. (int)abs(gyro_rms[1])%1000,
  372. gyro_rms[2]/1000,
  373. (int)abs(gyro_rms[2])%1000,
  374. (int)(total_count/3),
  375. (int)(total_count/3),
  376. (int)(total_count/3));
  377. }
  378. static ssize_t gyro_selftest_dps_store(struct device *dev,
  379. struct device_attribute *attr, const char *buf, size_t count)
  380. {
  381. int iNewDps = 0;
  382. int iDelayCnt = 0, iRet = 0;
  383. char chTempBuf[2] = { 0, 10 };
  384. struct ssp_data *data = dev_get_drvdata(dev);
  385. sscanf(buf, "%d", &iNewDps);
  386. if (iNewDps == GYROSCOPE_DPS250)
  387. chTempBuf[0] = 0;
  388. else if (iNewDps == GYROSCOPE_DPS500)
  389. chTempBuf[0] = 1;
  390. else if (iNewDps == GYROSCOPE_DPS2000)
  391. chTempBuf[0] = 2;
  392. else {
  393. chTempBuf[0] = 1;
  394. iNewDps = GYROSCOPE_DPS500;
  395. }
  396. data->uFactorydataReady = 0;
  397. memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
  398. iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_DPS_FACTORY,
  399. chTempBuf, 2);
  400. while (!(data->uFactorydataReady & (1 << GYROSCOPE_DPS_FACTORY))
  401. && (iDelayCnt++ < 150)
  402. && (iRet == SUCCESS))
  403. msleep(20);
  404. if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
  405. pr_err("[SSP]: %s - Gyro Selftest DPS Timeout!!\n", __func__);
  406. goto exit;
  407. }
  408. mdelay(5);
  409. if (data->uFactorydata[0] != SUCCESS) {
  410. pr_err("[SSP]: %s - Gyro Selftest DPS Error!!\n", __func__);
  411. goto exit;
  412. }
  413. data->uGyroDps = (unsigned int)iNewDps;
  414. pr_err("[SSP]: %s - %u dps stored\n", __func__, data->uGyroDps);
  415. exit:
  416. return count;
  417. }
  418. static ssize_t gyro_selftest_dps_show(struct device *dev,
  419. struct device_attribute *attr, char *buf)
  420. {
  421. struct ssp_data *data = dev_get_drvdata(dev);
  422. return sprintf(buf, "%u\n", data->uGyroDps);
  423. }
  424. static DEVICE_ATTR(name, S_IRUGO, gyro_name_show, NULL);
  425. static DEVICE_ATTR(vendor, S_IRUGO, gyro_vendor_show, NULL);
  426. static DEVICE_ATTR(power_off, S_IRUGO, gyro_power_off, NULL);
  427. static DEVICE_ATTR(power_on, S_IRUGO, gyro_power_on, NULL);
  428. static DEVICE_ATTR(temperature, S_IRUGO, gyro_get_temp, NULL);
  429. static DEVICE_ATTR(selftest, S_IRUGO, gyro_selftest_show, NULL);
  430. static DEVICE_ATTR(selftest_dps, S_IRUGO | S_IWUSR | S_IWGRP,
  431. gyro_selftest_dps_show, gyro_selftest_dps_store);
  432. static struct device_attribute *gyro_attrs[] = {
  433. &dev_attr_name,
  434. &dev_attr_vendor,
  435. &dev_attr_selftest,
  436. &dev_attr_power_on,
  437. &dev_attr_power_off,
  438. &dev_attr_temperature,
  439. &dev_attr_selftest_dps,
  440. NULL,
  441. };
  442. void initialize_gyro_factorytest(struct ssp_data *data)
  443. {
  444. sensors_register(data->gyro_device, data, gyro_attrs, "gyro_sensor");
  445. }
  446. void remove_gyro_factorytest(struct ssp_data *data)
  447. {
  448. sensors_unregister(data->gyro_device, gyro_attrs);
  449. }