magnetic_yas532.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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. #include "magnetic_yas532.h"
  17. /*************************************************************************/
  18. /* factory Sysfs */
  19. /*************************************************************************/
  20. #define VENDOR "YAMAHA"
  21. #define CHIP_ID "YAS532"
  22. #define MAG_HW_OFFSET_FILE_PATH "/efs/hw_offset"
  23. int mag_open_hwoffset(struct ssp_data *data)
  24. {
  25. int iRet = 0;
  26. mm_segment_t old_fs;
  27. struct file *cal_filp = NULL;
  28. old_fs = get_fs();
  29. set_fs(KERNEL_DS);
  30. cal_filp = filp_open(MAG_HW_OFFSET_FILE_PATH, O_RDONLY, 0666);
  31. if (IS_ERR(cal_filp)) {
  32. pr_err("[SSP] %s: filp_open failed\n", __func__);
  33. set_fs(old_fs);
  34. iRet = PTR_ERR(cal_filp);
  35. data->magoffset.x = 0;
  36. data->magoffset.y = 0;
  37. data->magoffset.z = 0;
  38. return iRet;
  39. }
  40. iRet = cal_filp->f_op->read(cal_filp, (char *)&data->magoffset,
  41. 3 * sizeof(char), &cal_filp->f_pos);
  42. if (iRet != 3 * sizeof(char)) {
  43. pr_err("[SSP] %s: filp_open failed\n", __func__);
  44. iRet = -EIO;
  45. }
  46. filp_close(cal_filp, current->files);
  47. set_fs(old_fs);
  48. ssp_dbg("[SSP]: %s: %d, %d, %d\n", __func__,
  49. (s8)data->magoffset.x,
  50. (s8)data->magoffset.y,
  51. (s8)data->magoffset.z);
  52. if ((data->magoffset.x == 0) && (data->magoffset.y == 0)
  53. && (data->magoffset.z == 0))
  54. return ERROR;
  55. return iRet;
  56. }
  57. int mag_store_hwoffset(struct ssp_data *data)
  58. {
  59. int iRet = 0;
  60. struct file *cal_filp = NULL;
  61. mm_segment_t old_fs;
  62. if (!(data->uSensorState & (1 << GEOMAGNETIC_SENSOR))) {
  63. pr_info("[SSP]: %s - Skip this function!!!"\
  64. ", magnetic sensor is not connected(0x%x)\n",
  65. __func__, data->uSensorState);
  66. return iRet;
  67. }
  68. if (get_hw_offset(data) < 0) {
  69. pr_err("[SSP]: %s - get_hw_offset failed\n", __func__);
  70. return ERROR;
  71. } else {
  72. old_fs = get_fs();
  73. set_fs(KERNEL_DS);
  74. cal_filp = filp_open(MAG_HW_OFFSET_FILE_PATH,
  75. O_CREAT | O_TRUNC | O_WRONLY, 0666);
  76. if (IS_ERR(cal_filp)) {
  77. pr_err("[SSP]: %s - Can't open hw_offset file\n",
  78. __func__);
  79. set_fs(old_fs);
  80. iRet = PTR_ERR(cal_filp);
  81. return iRet;
  82. }
  83. iRet = cal_filp->f_op->write(cal_filp,
  84. (char *)&data->magoffset,
  85. 3 * sizeof(char), &cal_filp->f_pos);
  86. if (iRet != 3 * sizeof(char)) {
  87. pr_err("[SSP]: %s - Can't write the hw_offset"
  88. " to file\n", __func__);
  89. iRet = -EIO;
  90. }
  91. filp_close(cal_filp, current->files);
  92. set_fs(old_fs);
  93. return iRet;
  94. }
  95. }
  96. int set_hw_offset(struct ssp_data *data)
  97. {
  98. int iRet = 0;
  99. struct ssp_msg *msg;
  100. if (!(data->uSensorState & (1 << GEOMAGNETIC_SENSOR))) {
  101. pr_info("[SSP]: %s - Skip this function!!!"\
  102. ", magnetic sensor is not connected(0x%x)\n",
  103. __func__, data->uSensorState);
  104. return iRet;
  105. }
  106. msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  107. msg->cmd = MSG2SSP_AP_SET_MAGNETIC_HWOFFSET;
  108. msg->length = 3;
  109. msg->options = AP2HUB_WRITE;
  110. msg->buffer = (char*) kzalloc(3, GFP_KERNEL);
  111. msg->free_buffer = 1;
  112. msg->buffer[0] = data->magoffset.x;
  113. msg->buffer[1] = data->magoffset.y;
  114. msg->buffer[2] = data->magoffset.z;
  115. iRet = ssp_spi_async(data, msg);
  116. if (iRet != SUCCESS) {
  117. pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
  118. iRet = ERROR;
  119. }
  120. pr_info("[SSP]: %s: x: %d, y: %d, z: %d\n", __func__,
  121. (s8)data->magoffset.x, (s8)data->magoffset.y, (s8)data->magoffset.z);
  122. return iRet;
  123. }
  124. int set_static_matrix(struct ssp_data *data)
  125. {
  126. int iRet = 0;
  127. struct ssp_msg *msg;
  128. s16 static_matrix[9] = YAS_STATIC_ELLIPSOID_MATRIX;
  129. if (!(data->uSensorState & (1 << GEOMAGNETIC_SENSOR))) {
  130. pr_info("[SSP]: %s - Skip this function!!!"\
  131. ", magnetic sensor is not connected(0x%x)\n",
  132. __func__, data->uSensorState);
  133. return iRet;
  134. }
  135. msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  136. msg->cmd = MSG2SSP_AP_MCU_SET_STATIC_MATRIX;
  137. msg->length = 18;
  138. msg->options = AP2HUB_WRITE;
  139. msg->buffer = (char*) kzalloc(18, GFP_KERNEL);
  140. msg->free_buffer = 1;
  141. memcpy(msg->buffer, static_matrix, 18);
  142. iRet = ssp_spi_async(data, msg);
  143. if (iRet != SUCCESS) {
  144. pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
  145. iRet = ERROR;
  146. }
  147. return iRet;
  148. }
  149. int get_hw_offset(struct ssp_data *data)
  150. {
  151. int iRet = 0;
  152. char buffer[3] = { 0, };
  153. struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  154. msg->cmd = MSG2SSP_AP_GET_MAGNETIC_HWOFFSET;
  155. msg->length = 3;
  156. msg->options = AP2HUB_READ;
  157. msg->buffer = buffer;
  158. msg->free_buffer = 0;
  159. data->magoffset.x = 0;
  160. data->magoffset.y = 0;
  161. data->magoffset.z = 0;
  162. iRet = ssp_spi_sync(data, msg, 1000);
  163. if (iRet != SUCCESS) {
  164. pr_err("[SSP]: %s - i2c fail %d\n", __func__, iRet);
  165. iRet = ERROR;
  166. }
  167. data->magoffset.x = buffer[0];
  168. data->magoffset.y = buffer[1];
  169. data->magoffset.z = buffer[2];
  170. pr_info("[SSP]: %s: x: %d, y: %d, z: %d\n", __func__,
  171. (s8)data->magoffset.x,
  172. (s8)data->magoffset.y,
  173. (s8)data->magoffset.z);
  174. return iRet;
  175. }
  176. static ssize_t magnetic_vendor_show(struct device *dev,
  177. struct device_attribute *attr, char *buf)
  178. {
  179. return sprintf(buf, "%s\n", VENDOR);
  180. }
  181. static ssize_t magnetic_name_show(struct device *dev,
  182. struct device_attribute *attr, char *buf)
  183. {
  184. return sprintf(buf, "%s\n", CHIP_ID);
  185. }
  186. static int check_rawdata_spec(struct ssp_data *data)
  187. {
  188. if ((data->buf[GEOMAGNETIC_RAW].x == 0) &&
  189. (data->buf[GEOMAGNETIC_RAW].y == 0) &&
  190. (data->buf[GEOMAGNETIC_RAW].z == 0))
  191. return FAIL;
  192. else
  193. return SUCCESS;
  194. }
  195. static ssize_t raw_data_show(struct device *dev,
  196. struct device_attribute *attr, char *buf)
  197. {
  198. struct ssp_data *data = dev_get_drvdata(dev);
  199. pr_info("[SSP] %s - %d,%d,%d\n", __func__,
  200. data->buf[GEOMAGNETIC_RAW].x,
  201. data->buf[GEOMAGNETIC_RAW].y,
  202. data->buf[GEOMAGNETIC_RAW].z);
  203. if (data->bGeomagneticRawEnabled == false) {
  204. data->buf[GEOMAGNETIC_RAW].x = -1;
  205. data->buf[GEOMAGNETIC_RAW].y = -1;
  206. data->buf[GEOMAGNETIC_RAW].z = -1;
  207. } else {
  208. if (data->buf[GEOMAGNETIC_RAW].x > 18000)
  209. data->buf[GEOMAGNETIC_RAW].x = 18000;
  210. else if (data->buf[GEOMAGNETIC_RAW].x < -18000)
  211. data->buf[GEOMAGNETIC_RAW].x = -18000;
  212. if (data->buf[GEOMAGNETIC_RAW].y > 18000)
  213. data->buf[GEOMAGNETIC_RAW].y = 18000;
  214. else if (data->buf[GEOMAGNETIC_RAW].y < -18000)
  215. data->buf[GEOMAGNETIC_RAW].y = -18000;
  216. if (data->buf[GEOMAGNETIC_RAW].z > 18000)
  217. data->buf[GEOMAGNETIC_RAW].z = 18000;
  218. else if (data->buf[GEOMAGNETIC_RAW].z < -18000)
  219. data->buf[GEOMAGNETIC_RAW].z = -18000;
  220. }
  221. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  222. data->buf[GEOMAGNETIC_RAW].x,
  223. data->buf[GEOMAGNETIC_RAW].y,
  224. data->buf[GEOMAGNETIC_RAW].z);
  225. }
  226. static ssize_t raw_data_store(struct device *dev,
  227. struct device_attribute *attr, const char *buf, size_t size)
  228. {
  229. char chTempbuf[4] = { 0 };
  230. int iRet;
  231. int64_t dEnable;
  232. int iRetries = 50;
  233. struct ssp_data *data = dev_get_drvdata(dev);
  234. s32 dMsDelay = 20;
  235. memcpy(&chTempbuf[0], &dMsDelay, 4);
  236. iRet = kstrtoll(buf, 10, &dEnable);
  237. if (iRet < 0)
  238. return iRet;
  239. if (dEnable) {
  240. data->buf[GEOMAGNETIC_RAW].x = 0;
  241. data->buf[GEOMAGNETIC_RAW].y = 0;
  242. data->buf[GEOMAGNETIC_RAW].z = 0;
  243. send_instruction(data, ADD_SENSOR, GEOMAGNETIC_RAW,
  244. chTempbuf, 4);
  245. do {
  246. msleep(20);
  247. if (check_rawdata_spec(data) == SUCCESS)
  248. break;
  249. } while (--iRetries);
  250. if (iRetries > 0) {
  251. pr_info("[SSP] %s - success, %d\n", __func__, iRetries);
  252. data->bGeomagneticRawEnabled = true;
  253. } else {
  254. pr_err("[SSP] %s - wait timeout, %d\n", __func__,
  255. iRetries);
  256. data->bGeomagneticRawEnabled = false;
  257. }
  258. } else {
  259. send_instruction(data, REMOVE_SENSOR, GEOMAGNETIC_RAW,
  260. chTempbuf, 4);
  261. data->bGeomagneticRawEnabled = false;
  262. }
  263. return size;
  264. }
  265. static int check_data_spec(struct ssp_data *data)
  266. {
  267. if ((data->buf[GEOMAGNETIC_SENSOR].x == 0) &&
  268. (data->buf[GEOMAGNETIC_SENSOR].y == 0) &&
  269. (data->buf[GEOMAGNETIC_SENSOR].z == 0))
  270. return FAIL;
  271. else if ((data->buf[GEOMAGNETIC_SENSOR].x > 6500) ||
  272. (data->buf[GEOMAGNETIC_SENSOR].x < -6500) ||
  273. (data->buf[GEOMAGNETIC_SENSOR].y > 6500) ||
  274. (data->buf[GEOMAGNETIC_SENSOR].y < -6500) ||
  275. (data->buf[GEOMAGNETIC_SENSOR].z > 6500) ||
  276. (data->buf[GEOMAGNETIC_SENSOR].z < -6500))
  277. return FAIL;
  278. else
  279. return SUCCESS;
  280. }
  281. static ssize_t adc_data_read(struct device *dev,
  282. struct device_attribute *attr, char *buf)
  283. {
  284. bool bSuccess = false;
  285. u8 chTempbuf[4] = { 0 };
  286. s16 iSensorBuf[3] = {0, };
  287. int iRetries = 10;
  288. struct ssp_data *data = dev_get_drvdata(dev);
  289. s32 dMsDelay = 20;
  290. memcpy(&chTempbuf[0], &dMsDelay, 4);
  291. data->buf[GEOMAGNETIC_SENSOR].x = 0;
  292. data->buf[GEOMAGNETIC_SENSOR].y = 0;
  293. data->buf[GEOMAGNETIC_SENSOR].z = 0;
  294. if (!(atomic_read(&data->aSensorEnable) & (1 << GEOMAGNETIC_SENSOR)))
  295. send_instruction(data, ADD_SENSOR, GEOMAGNETIC_SENSOR,
  296. chTempbuf, 4);
  297. do {
  298. msleep(60);
  299. if (check_data_spec(data) == SUCCESS)
  300. break;
  301. } while (--iRetries);
  302. if (iRetries > 0)
  303. bSuccess = true;
  304. iSensorBuf[0] = data->buf[GEOMAGNETIC_SENSOR].x;
  305. iSensorBuf[1] = data->buf[GEOMAGNETIC_SENSOR].y;
  306. iSensorBuf[2] = data->buf[GEOMAGNETIC_SENSOR].z;
  307. if (!(atomic_read(&data->aSensorEnable) & (1 << GEOMAGNETIC_SENSOR)))
  308. send_instruction(data, REMOVE_SENSOR, GEOMAGNETIC_SENSOR,
  309. chTempbuf, 4);
  310. pr_info("[SSP]: %s - x = %d, y = %d, z = %d\n", __func__,
  311. iSensorBuf[0], iSensorBuf[1], iSensorBuf[2]);
  312. return sprintf(buf, "%s,%d,%d,%d\n", (bSuccess ? "OK" : "NG"),
  313. iSensorBuf[0], iSensorBuf[1], iSensorBuf[2]);
  314. }
  315. static ssize_t magnetic_get_selftest(struct device *dev,
  316. struct device_attribute *attr, char *buf)
  317. {
  318. char chTempBuf[22] = { 0, };
  319. int iRet = 0;
  320. s8 id = 0, x = 0, y1 = 0, y2 = 0, dir = 0;
  321. s16 sx = 0, sy = 0, ohx = 0, ohy = 0, ohz = 0;
  322. s8 err[7] = {-1, };
  323. struct ssp_data *data = dev_get_drvdata(dev);
  324. struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
  325. msg->cmd = GEOMAGNETIC_FACTORY;
  326. msg->length = 22;
  327. msg->options = AP2HUB_READ;
  328. msg->buffer = chTempBuf;
  329. msg->free_buffer = 0;
  330. iRet = ssp_spi_sync(data, msg, 1000);
  331. if (iRet != SUCCESS) {
  332. pr_err("[SSP]: %s - Magnetic Selftest Timeout!! %d\n", __func__, iRet);
  333. goto exit;
  334. }
  335. id = (s8)(chTempBuf[0]);
  336. err[0] = (s8)(chTempBuf[1]);
  337. err[1] = (s8)(chTempBuf[2]);
  338. err[2] = (s8)(chTempBuf[3]);
  339. x = (s8)(chTempBuf[4]);
  340. y1 = (s8)(chTempBuf[5]);
  341. y2 = (s8)(chTempBuf[6]);
  342. err[3] = (s8)(chTempBuf[7]);
  343. dir = (s8)(chTempBuf[8]);
  344. err[4] = (s8)(chTempBuf[9]);
  345. ohx = (s16)((chTempBuf[10] << 8) + chTempBuf[11]);
  346. ohy = (s16)((chTempBuf[12] << 8) + chTempBuf[13]);
  347. ohz = (s16)((chTempBuf[14] << 8) + chTempBuf[15]);
  348. err[6] = (s8)(chTempBuf[16]);
  349. sx = (s16)((chTempBuf[17] << 8) + chTempBuf[18]);
  350. sy = (s16)((chTempBuf[19] << 8) + chTempBuf[20]);
  351. err[5] = (s8)(chTempBuf[21]);
  352. if (unlikely(id != 0x2))
  353. err[0] = -1;
  354. if (unlikely(x < -30 || x > 30))
  355. err[3] = -1;
  356. if (unlikely(y1 < -30 || y1 > 30))
  357. err[3] = -1;
  358. if (unlikely(y2 < -30 || y2 > 30))
  359. err[3] = -1;
  360. if (unlikely(sx < 17 || sy < 22))
  361. err[5] = -1;
  362. if (unlikely(ohx < -600 || ohx > 600))
  363. err[6] = -1;
  364. if (unlikely(ohy < -600 || ohy > 600))
  365. err[6] = -1;
  366. if (unlikely(ohz < -600 || ohz > 600))
  367. err[6] = -1;
  368. pr_info("[SSP] %s\n"
  369. "[SSP] Test1 - err = %d, id = %d\n"
  370. "[SSP] Test3 - err = %d\n"
  371. "[SSP] Test4 - err = %d, offset = %d,%d,%d\n"
  372. "[SSP] Test5 - err = %d, direction = %d\n"
  373. "[SSP] Test6 - err = %d, sensitivity = %d,%d\n"
  374. "[SSP] Test7 - err = %d, offset = %d,%d,%d\n"
  375. "[SSP] Test2 - err = %d\n",
  376. __func__, err[0], id, err[2], err[3], x, y1, y2, err[4], dir,
  377. err[5], sx, sy, err[6], ohx, ohy, ohz, err[1]);
  378. exit:
  379. return sprintf(buf,
  380. "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  381. err[0], id, err[2], err[3], x, y1, y2, err[4], dir,
  382. err[5], sx, sy, err[6], ohx, ohy, ohz, err[1]);
  383. }
  384. static ssize_t hw_offset_show(struct device *dev,
  385. struct device_attribute *attr, char *buf)
  386. {
  387. struct ssp_data *data = dev_get_drvdata(dev);
  388. mag_open_hwoffset(data);
  389. pr_info("[SSP] %s: %d %d %d\n", __func__,
  390. (s8)data->magoffset.x,
  391. (s8)data->magoffset.y,
  392. (s8)data->magoffset.z);
  393. return sprintf(buf, "%d %d %d\n",
  394. (s8)data->magoffset.x,
  395. (s8)data->magoffset.y,
  396. (s8)data->magoffset.z);
  397. }
  398. static DEVICE_ATTR(name, S_IRUGO, magnetic_name_show, NULL);
  399. static DEVICE_ATTR(vendor, S_IRUGO, magnetic_vendor_show, NULL);
  400. static DEVICE_ATTR(raw_data, S_IRUGO | S_IWUSR | S_IWGRP,
  401. raw_data_show, raw_data_store);
  402. static DEVICE_ATTR(adc, S_IRUGO, adc_data_read, NULL);
  403. static DEVICE_ATTR(selftest, S_IRUSR|S_IRGRP, magnetic_get_selftest, NULL);
  404. static DEVICE_ATTR(hw_offset, S_IRUGO, hw_offset_show, NULL);
  405. static struct device_attribute *mag_attrs[] = {
  406. &dev_attr_name,
  407. &dev_attr_vendor,
  408. &dev_attr_adc,
  409. &dev_attr_raw_data,
  410. &dev_attr_selftest,
  411. &dev_attr_hw_offset,
  412. NULL,
  413. };
  414. void initialize_magnetic_factorytest(struct ssp_data *data)
  415. {
  416. sensors_register(data->mag_device, data, mag_attrs, "magnetic_sensor");
  417. }
  418. void remove_magnetic_factorytest(struct ssp_data *data)
  419. {
  420. sensors_unregister(data->mag_device, mag_attrs);
  421. }