yas529-kernel.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. $License:
  3. Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
  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. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. $
  15. */
  16. /**
  17. * @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer)
  18. * @brief Provides the interface to setup and handle an accelerometers
  19. * connected to the secondary I2C interface of the gyroscope.
  20. *
  21. * @{
  22. * @file yas529.c
  23. * @brief Magnetometer setup and handling methods for Yamaha yas529
  24. * compass.
  25. */
  26. /* ------------------ */
  27. /* - Include Files. - */
  28. /* ------------------ */
  29. #ifdef __KERNEL__
  30. #include <linux/module.h>
  31. #include <linux/i2c.h>
  32. #endif
  33. #include "mpu.h"
  34. #include "mlos.h"
  35. #include <log.h>
  36. #undef MPL_LOG_TAG
  37. #define MPL_LOG_TAG "MPL-acc"
  38. /*----- YAMAHA YAS529 Registers ------*/
  39. enum YAS_REG {
  40. YAS_REG_CMDR = 0x00, /* 000 < 5 */
  41. YAS_REG_XOFFSETR = 0x20, /* 001 < 5 */
  42. YAS_REG_Y1OFFSETR = 0x40, /* 010 < 5 */
  43. YAS_REG_Y2OFFSETR = 0x60, /* 011 < 5 */
  44. YAS_REG_ICOILR = 0x80, /* 100 < 5 */
  45. YAS_REG_CAL = 0xA0, /* 101 < 5 */
  46. YAS_REG_CONFR = 0xC0, /* 110 < 5 */
  47. YAS_REG_DOUTR = 0xE0 /* 111 < 5 */
  48. };
  49. /* --------------------- */
  50. /* - Variables. - */
  51. /* --------------------- */
  52. static long a1;
  53. static long a2;
  54. static long a3;
  55. static long a4;
  56. static long a5;
  57. static long a6;
  58. static long a7;
  59. static long a8;
  60. static long a9;
  61. /*****************************************
  62. Yamaha I2C access functions
  63. *****************************************/
  64. static int yas529_sensor_i2c_write(struct i2c_adapter *i2c_adap,
  65. unsigned char address,
  66. unsigned int len, unsigned char *data)
  67. {
  68. struct i2c_msg msgs[1];
  69. int res;
  70. if (NULL == data || NULL == i2c_adap)
  71. return -EINVAL;
  72. msgs[0].addr = address;
  73. msgs[0].flags = 0; /* write */
  74. msgs[0].buf = (unsigned char *) data;
  75. msgs[0].len = len;
  76. res = i2c_transfer(i2c_adap, msgs, 1);
  77. if (res < 1)
  78. return res;
  79. else
  80. return 0;
  81. }
  82. static int yas529_sensor_i2c_read(struct i2c_adapter *i2c_adap,
  83. unsigned char address,
  84. unsigned char reg,
  85. unsigned int len, unsigned char *data)
  86. {
  87. struct i2c_msg msgs[2];
  88. int res;
  89. if (NULL == data || NULL == i2c_adap)
  90. return -EINVAL;
  91. msgs[0].addr = address;
  92. msgs[0].flags = I2C_M_RD;
  93. msgs[0].buf = data;
  94. msgs[0].len = len;
  95. res = i2c_transfer(i2c_adap, msgs, 1);
  96. if (res < 1)
  97. return res;
  98. else
  99. return 0;
  100. }
  101. /*****************************************
  102. Accelerometer Initialization Functions
  103. *****************************************/
  104. int yas529_suspend(void *mlsl_handle,
  105. struct ext_slave_descr *slave,
  106. struct ext_slave_platform_data *pdata)
  107. {
  108. int result = ML_SUCCESS;
  109. return result;
  110. }
  111. int yas529_resume(void *mlsl_handle,
  112. struct ext_slave_descr *slave,
  113. struct ext_slave_platform_data *pdata)
  114. {
  115. int result = ML_SUCCESS;
  116. unsigned char dummyData[1] = { 0 };
  117. unsigned char dummyRegister = 0;
  118. unsigned char rawData[6];
  119. unsigned char calData[9];
  120. short xoffset, y1offset, y2offset;
  121. short d2, d3, d4, d5, d6, d7, d8, d9;
  122. /* YAS529 Application Manual MS-3C - Section 4.4.5 */
  123. /* =============================================== */
  124. /* Step 1 - register initialization */
  125. /* zero initialization coil register - "100 00 000" */
  126. dummyData[0] = YAS_REG_ICOILR | 0x00;
  127. result =
  128. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  129. dummyData);
  130. ERROR_CHECK(result);
  131. /* zero config register - "110 00 000" */
  132. dummyData[0] = YAS_REG_CONFR | 0x00;
  133. result =
  134. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  135. dummyData);
  136. ERROR_CHECK(result);
  137. /* Step 2 - initialization coil operation */
  138. dummyData[0] = YAS_REG_ICOILR | 0x11;
  139. result =
  140. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  141. dummyData);
  142. ERROR_CHECK(result);
  143. dummyData[0] = YAS_REG_ICOILR | 0x01;
  144. result =
  145. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  146. dummyData);
  147. ERROR_CHECK(result);
  148. dummyData[0] = YAS_REG_ICOILR | 0x12;
  149. result =
  150. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  151. dummyData);
  152. ERROR_CHECK(result);
  153. dummyData[0] = YAS_REG_ICOILR | 0x02;
  154. result =
  155. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  156. dummyData);
  157. ERROR_CHECK(result);
  158. dummyData[0] = YAS_REG_ICOILR | 0x13;
  159. result =
  160. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  161. dummyData);
  162. ERROR_CHECK(result);
  163. dummyData[0] = YAS_REG_ICOILR | 0x03;
  164. result =
  165. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  166. dummyData);
  167. ERROR_CHECK(result);
  168. dummyData[0] = YAS_REG_ICOILR | 0x14;
  169. result =
  170. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  171. dummyData);
  172. ERROR_CHECK(result);
  173. dummyData[0] = YAS_REG_ICOILR | 0x04;
  174. result =
  175. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  176. dummyData);
  177. ERROR_CHECK(result);
  178. dummyData[0] = YAS_REG_ICOILR | 0x15;
  179. result =
  180. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  181. dummyData);
  182. ERROR_CHECK(result);
  183. dummyData[0] = YAS_REG_ICOILR | 0x05;
  184. result =
  185. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  186. dummyData);
  187. ERROR_CHECK(result);
  188. dummyData[0] = YAS_REG_ICOILR | 0x16;
  189. result =
  190. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  191. dummyData);
  192. ERROR_CHECK(result);
  193. dummyData[0] = YAS_REG_ICOILR | 0x06;
  194. result =
  195. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  196. dummyData);
  197. ERROR_CHECK(result);
  198. dummyData[0] = YAS_REG_ICOILR | 0x17;
  199. result =
  200. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  201. dummyData);
  202. ERROR_CHECK(result);
  203. dummyData[0] = YAS_REG_ICOILR | 0x07;
  204. result =
  205. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  206. dummyData);
  207. ERROR_CHECK(result);
  208. dummyData[0] = YAS_REG_ICOILR | 0x10;
  209. result =
  210. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  211. dummyData);
  212. ERROR_CHECK(result);
  213. dummyData[0] = YAS_REG_ICOILR | 0x00;
  214. result =
  215. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  216. dummyData);
  217. ERROR_CHECK(result);
  218. /* Step 3 - rough offset measurement */
  219. /* Config register - Measurements results - "110 00 000" */
  220. dummyData[0] = YAS_REG_CONFR | 0x00;
  221. result =
  222. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  223. dummyData);
  224. ERROR_CHECK(result);
  225. /* Measurements command register - Rough offset measurement -
  226. "000 00001" */
  227. dummyData[0] = YAS_REG_CMDR | 0x01;
  228. result =
  229. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  230. dummyData);
  231. ERROR_CHECK(result);
  232. MLOSSleep(2); /* wait at least 1.5ms */
  233. /* Measurement data read */
  234. result =
  235. yas529_sensor_i2c_read(mlsl_handle, pdata->address,
  236. dummyRegister, 6, rawData);
  237. ERROR_CHECK(result);
  238. xoffset =
  239. (short) ((unsigned short) rawData[5] +
  240. ((unsigned short) rawData[4] & 0x7) * 256) - 5;
  241. if (xoffset < 0)
  242. xoffset = 0;
  243. y1offset =
  244. (short) ((unsigned short) rawData[3] +
  245. ((unsigned short) rawData[2] & 0x7) * 256) - 5;
  246. if (y1offset < 0)
  247. y1offset = 0;
  248. y2offset =
  249. (short) ((unsigned short) rawData[1] +
  250. ((unsigned short) rawData[0] & 0x7) * 256) - 5;
  251. if (y2offset < 0)
  252. y2offset = 0;
  253. /* Step 4 - rough offset setting */
  254. /* Set rough offset register values */
  255. dummyData[0] = YAS_REG_XOFFSETR | xoffset;
  256. result =
  257. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  258. dummyData);
  259. ERROR_CHECK(result);
  260. dummyData[0] = YAS_REG_Y1OFFSETR | y1offset;
  261. result =
  262. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  263. dummyData);
  264. ERROR_CHECK(result);
  265. dummyData[0] = YAS_REG_Y2OFFSETR | y2offset;
  266. result =
  267. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  268. dummyData);
  269. ERROR_CHECK(result);
  270. /* CAL matrix read (first read is invalid) */
  271. /* Config register - CAL register read - "110 01 000" */
  272. dummyData[0] = YAS_REG_CONFR | 0x08;
  273. result =
  274. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  275. dummyData);
  276. ERROR_CHECK(result);
  277. /* CAL data read */
  278. result =
  279. yas529_sensor_i2c_read(mlsl_handle, pdata->address,
  280. dummyRegister, 9, calData);
  281. ERROR_CHECK(result);
  282. /* Config register - CAL register read - "110 01 000" */
  283. dummyData[0] = YAS_REG_CONFR | 0x08;
  284. result =
  285. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  286. dummyData);
  287. ERROR_CHECK(result);
  288. /* CAL data read */
  289. result =
  290. yas529_sensor_i2c_read(mlsl_handle, pdata->address,
  291. dummyRegister, 9, calData);
  292. ERROR_CHECK(result);
  293. /* Calculate coefficients of the sensitivity corrcetion matrix */
  294. #if 1 /* production sensor */
  295. a1 = 100;
  296. d2 = (calData[0] & 0xFC) >> 2; /* [71..66] 6bit */
  297. a2 = (short) (d2 - 32);
  298. /* [65..62] 4bit */
  299. d3 = ((calData[0] & 0x03) << 2) | ((calData[1] & 0xC0) >> 6);
  300. a3 = (short) (d3 - 8);
  301. d4 = (calData[1] & 0x3F); /* [61..56] 6bit */
  302. a4 = (short) (d4 - 32);
  303. d5 = (calData[2] & 0xFC) >> 2; /* [55..50] 6bit */
  304. a5 = (short) (d5 - 32) + 70;
  305. /* [49..44] 6bit */
  306. d6 = ((calData[2] & 0x03) << 4) | ((calData[3] & 0xF0) >> 4);
  307. a6 = (short) (d6 - 32);
  308. /* [43..38] 6bit */
  309. d7 = ((calData[3] & 0x0F) << 2) | ((calData[4] & 0xC0) >> 6);
  310. a7 = (short) (d7 - 32);
  311. d8 = (calData[4] & 0x3F); /* [37..32] 6bit */
  312. a8 = (short) (d8 - 32);
  313. d9 = (calData[5] & 0xFE) >> 1; /* [31..25] 7bit */
  314. a9 = (short) (d9 - 64) + 130;
  315. #else /* evaluation sensor */
  316. a1 = 1.0f;
  317. /* [71..66] 6bit */
  318. d2 = (calData[0] & 0xFC) >> 2;
  319. a2 = (short) d2;
  320. /* [65..60] 6bit */
  321. d3 = ((calData[0] & 0x03) << 4) | ((calData[1] & 0xF0) >> 4);
  322. a3 = (short) d3;
  323. /* [59..54] 6bit */
  324. d4 = ((calData[1] & 0x0F) << 2) | ((calData[2] & 0xC0) >> 6);
  325. a4 = (short) d4;
  326. /* [53..48] 6bit */
  327. d5 = (calData[2] & 0x3F);
  328. a5 = (short) (d5 + 70);
  329. /* [47..42] 6bit */
  330. d6 = ((calData[3] & 0xFC) >> 2);
  331. a6 = (short) d6;
  332. /* [41..36] 6bit */
  333. d7 = ((calData[3] & 0x03) << 4) | ((calData[4] & 0xF0) >> 4);
  334. a7 = (short) d7;
  335. /* [35..30] 6bit */
  336. d8 = ((calData[4] & 0x0F) << 2) | ((calData[5] & 0xC0) >> 6);
  337. a8 = (short) d8;
  338. /* [29..24] 6bit */
  339. d9 = (calData[5] & 0x3F);
  340. a9 = (short) (d9 + 150);
  341. #endif
  342. return result;
  343. }
  344. int yas529_read(void *mlsl_handle,
  345. struct ext_slave_descr *slave,
  346. struct ext_slave_platform_data *pdata, unsigned char *data)
  347. {
  348. unsigned char stat;
  349. unsigned char rawData[6];
  350. unsigned char dummyData[1] = { 0 };
  351. unsigned char dummyRegister = 0;
  352. tMLError result = ML_SUCCESS;
  353. short SX, SY1, SY2, SY, SZ;
  354. short row1fixed, row2fixed, row3fixed;
  355. /* Config register - Measurements results - "110 00 000" */
  356. dummyData[0] = YAS_REG_CONFR | 0x00;
  357. result =
  358. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  359. dummyData);
  360. ERROR_CHECK(result);
  361. /* Measurements command register - Normal magnetic field measurement -
  362. "000 00000" */
  363. dummyData[0] = YAS_REG_CMDR | 0x00;
  364. result =
  365. yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
  366. dummyData);
  367. ERROR_CHECK(result);
  368. MLOSSleep(10);
  369. /* Measurement data read */
  370. result =
  371. yas529_sensor_i2c_read(mlsl_handle, pdata->address,
  372. dummyRegister, 6,
  373. (unsigned char *) &rawData);
  374. ERROR_CHECK(result);
  375. stat = rawData[0] & 0x80;
  376. if (stat == 0x00) {
  377. /* Extract raw data */
  378. SX = (short) ((unsigned short) rawData[5] +
  379. ((unsigned short) rawData[4] & 0x7) * 256);
  380. SY1 =
  381. (short) ((unsigned short) rawData[3] +
  382. ((unsigned short) rawData[2] & 0x7) * 256);
  383. SY2 =
  384. (short) ((unsigned short) rawData[1] +
  385. ((unsigned short) rawData[0] & 0x7) * 256);
  386. if ((SX <= 1) || (SY1 <= 1) || (SY2 <= 1))
  387. return ML_ERROR_COMPASS_DATA_UNDERFLOW;
  388. if ((SX >= 1024) || (SY1 >= 1024) || (SY2 >= 1024))
  389. return ML_ERROR_COMPASS_DATA_OVERFLOW;
  390. /* Convert to XYZ axis */
  391. SX = -1 * SX;
  392. SY = SY2 - SY1;
  393. SZ = SY1 + SY2;
  394. /* Apply sensitivity correction matrix */
  395. row1fixed =
  396. (short) ((a1 * SX + a2 * SY + a3 * SZ) >> 7) * 41;
  397. row2fixed =
  398. (short) ((a4 * SX + a5 * SY + a6 * SZ) >> 7) * 41;
  399. row3fixed =
  400. (short) ((a7 * SX + a8 * SY + a9 * SZ) >> 7) * 41;
  401. data[0] = row1fixed >> 8;
  402. data[1] = row1fixed & 0xFF;
  403. data[2] = row2fixed >> 8;
  404. data[3] = row2fixed & 0xFF;
  405. data[4] = row3fixed >> 8;
  406. data[5] = row3fixed & 0xFF;
  407. return ML_SUCCESS;
  408. } else {
  409. return ML_ERROR_COMPASS_DATA_NOT_READY;
  410. }
  411. }
  412. struct ext_slave_descr yas529_descr = {
  413. /*.init = */ NULL,
  414. /*.exit = */ NULL,
  415. /*.suspend = */ yas529_suspend,
  416. /*.resume = */ yas529_resume,
  417. /*.read = */ yas529_read,
  418. /*.config = */ NULL,
  419. /*.get_config = */ NULL,
  420. /*.name = */ "yas529",
  421. /*.type = */ EXT_SLAVE_TYPE_COMPASS,
  422. /*.id = */ COMPASS_ID_YAS529,
  423. /*.reg = */ 0x06,
  424. /*.len = */ 6,
  425. /*.endian = */ EXT_SLAVE_BIG_ENDIAN,
  426. /*.range = */ {19660, 8000},
  427. };
  428. struct ext_slave_descr *yas529_get_slave_descr(void)
  429. {
  430. return &yas529_descr;
  431. }
  432. EXPORT_SYMBOL(yas529_get_slave_descr);
  433. /**
  434. * @}
  435. */