mldl_cfg.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740
  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. * @addtogroup MLDL
  18. *
  19. * @{
  20. * @file mldl_cfg.c
  21. * @brief The Motion Library Driver Layer.
  22. */
  23. /* ------------------ */
  24. /* - Include Files. - */
  25. /* ------------------ */
  26. #include <stddef.h>
  27. #include "mldl_cfg.h"
  28. #include "mpu.h"
  29. #include "mlsl.h"
  30. #include "mlos.h"
  31. #include "log.h"
  32. #undef MPL_LOG_TAG
  33. #define MPL_LOG_TAG "mldl_cfg:"
  34. /* --------------------- */
  35. /* - Variables. - */
  36. /* --------------------- */
  37. #ifdef M_HW
  38. #define SLEEP 0
  39. #define WAKE_UP 7
  40. #define RESET 1
  41. #define STANDBY 1
  42. #else
  43. /* licteral significance of all parameters used in MLDLPowerMgmtMPU */
  44. #define SLEEP 1
  45. #define WAKE_UP 0
  46. #define RESET 1
  47. #define STANDBY 1
  48. #endif
  49. /*---------------------*/
  50. /*- Prototypes. -*/
  51. /*---------------------*/
  52. /*----------------------*/
  53. /*- Static Functions. -*/
  54. /*----------------------*/
  55. static int dmp_stop(struct mldl_cfg *mldl_cfg, void *gyro_handle)
  56. {
  57. unsigned char userCtrlReg;
  58. int result;
  59. if (!mldl_cfg->dmp_is_running)
  60. return ML_SUCCESS;
  61. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  62. MPUREG_USER_CTRL, 1, &userCtrlReg);
  63. ERROR_CHECK(result);
  64. userCtrlReg = (userCtrlReg & (~BIT_FIFO_EN)) | BIT_FIFO_RST;
  65. userCtrlReg = (userCtrlReg & (~BIT_DMP_EN)) | BIT_DMP_RST;
  66. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  67. MPUREG_USER_CTRL, userCtrlReg);
  68. ERROR_CHECK(result);
  69. mldl_cfg->dmp_is_running = 0;
  70. return result;
  71. }
  72. /**
  73. * @brief Starts the DMP running
  74. *
  75. * @return ML_SUCCESS or non-zero error code
  76. */
  77. static int dmp_start(struct mldl_cfg *pdata, void *mlsl_handle)
  78. {
  79. unsigned char userCtrlReg;
  80. int result;
  81. if (pdata->dmp_is_running == pdata->dmp_enable)
  82. return ML_SUCCESS;
  83. result = MLSLSerialRead(mlsl_handle, pdata->addr,
  84. MPUREG_USER_CTRL, 1, &userCtrlReg);
  85. ERROR_CHECK(result);
  86. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  87. MPUREG_USER_CTRL,
  88. ((userCtrlReg & (~BIT_FIFO_EN))
  89. | BIT_FIFO_RST));
  90. ERROR_CHECK(result);
  91. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  92. MPUREG_USER_CTRL, userCtrlReg);
  93. ERROR_CHECK(result);
  94. result = MLSLSerialRead(mlsl_handle, pdata->addr,
  95. MPUREG_USER_CTRL, 1, &userCtrlReg);
  96. ERROR_CHECK(result);
  97. if (pdata->dmp_enable)
  98. userCtrlReg |= BIT_DMP_EN;
  99. else
  100. userCtrlReg &= ~BIT_DMP_EN;
  101. if (pdata->fifo_enable)
  102. userCtrlReg |= BIT_FIFO_EN;
  103. else
  104. userCtrlReg &= ~BIT_FIFO_EN;
  105. userCtrlReg |= BIT_DMP_RST;
  106. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  107. MPUREG_USER_CTRL, userCtrlReg);
  108. ERROR_CHECK(result);
  109. pdata->dmp_is_running = pdata->dmp_enable;
  110. return result;
  111. }
  112. /**
  113. * @brief enables/disables the I2C bypass to an external device
  114. * connected to MPU's secondary I2C bus.
  115. * @param enable
  116. * Non-zero to enable pass through.
  117. * @return ML_SUCCESS if successful, a non-zero error code otherwise.
  118. */
  119. static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
  120. void *mlsl_handle,
  121. unsigned char enable)
  122. {
  123. unsigned char b;
  124. int result;
  125. if ((mldl_cfg->gyro_is_bypassed && enable) ||
  126. (!mldl_cfg->gyro_is_bypassed && !enable))
  127. return ML_SUCCESS;
  128. /*---- get current 'USER_CTRL' into b ----*/
  129. result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
  130. MPUREG_USER_CTRL, 1, &b);
  131. ERROR_CHECK(result);
  132. b &= ~BIT_AUX_IF_EN;
  133. if (!enable) {
  134. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  135. MPUREG_USER_CTRL,
  136. (b | BIT_AUX_IF_EN));
  137. ERROR_CHECK(result);
  138. } else {
  139. /* Coming out of I2C is tricky due to several erratta. Do not
  140. * modify this algorithm
  141. */
  142. /*
  143. * 1) wait for the right time and send the command to change
  144. * the aux i2c slave address to an invalid address that will
  145. * get nack'ed
  146. *
  147. * 0x00 is broadcast. 0x7F is unlikely to be used by any aux.
  148. */
  149. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  150. MPUREG_AUX_SLV_ADDR, 0x7F);
  151. ERROR_CHECK(result);
  152. /*
  153. * 2) wait enough time for a nack to occur, then go into
  154. * bypass mode:
  155. */
  156. MLOSSleep(2);
  157. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  158. MPUREG_USER_CTRL, (b));
  159. ERROR_CHECK(result);
  160. /*
  161. * 3) wait for up to one MPU cycle then restore the slave
  162. * address
  163. */
  164. MLOSSleep(SAMPLING_PERIOD_US(mldl_cfg) / 1000);
  165. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  166. MPUREG_AUX_SLV_ADDR,
  167. mldl_cfg->pdata->
  168. accel.address);
  169. ERROR_CHECK(result);
  170. /*
  171. * 4) reset the ime interface
  172. */
  173. #ifdef M_HW
  174. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  175. MPUREG_USER_CTRL,
  176. (b | BIT_I2C_MST_RST));
  177. #else
  178. result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
  179. MPUREG_USER_CTRL,
  180. (b | BIT_AUX_IF_RST));
  181. #endif
  182. ERROR_CHECK(result);
  183. MLOSSleep(2);
  184. }
  185. mldl_cfg->gyro_is_bypassed = enable;
  186. return result;
  187. }
  188. struct tsProdRevMap {
  189. unsigned char siliconRev;
  190. unsigned short sensTrim;
  191. };
  192. #define NUM_OF_PROD_REVS (DIM(prodRevsMap))
  193. /* NOTE : 'npp' is a non production part */
  194. #ifdef M_HW
  195. #define OLDEST_PROD_REV_SUPPORTED 1
  196. static struct tsProdRevMap prodRevsMap[] = {
  197. {0, 0},
  198. {MPU_SILICON_REV_A1, 131}, /* 1 A1 (npp) */
  199. {MPU_SILICON_REV_A1, 131}, /* 2 A1 (npp) */
  200. {MPU_SILICON_REV_A1, 131}, /* 3 A1 (npp) */
  201. {MPU_SILICON_REV_A1, 131}, /* 4 A1 (npp) */
  202. {MPU_SILICON_REV_A1, 131}, /* 5 A1 (npp) */
  203. {MPU_SILICON_REV_A1, 131}, /* 6 A1 (npp) */
  204. {MPU_SILICON_REV_A1, 131}, /* 7 A1 (npp) */
  205. {MPU_SILICON_REV_A1, 131}, /* 8 A1 (npp) */
  206. };
  207. #else /* !M_HW */
  208. #define OLDEST_PROD_REV_SUPPORTED 11
  209. static struct tsProdRevMap prodRevsMap[] = {
  210. {0, 0},
  211. {MPU_SILICON_REV_A4, 131}, /* 1 A? OBSOLETED */
  212. {MPU_SILICON_REV_A4, 131}, /* 2 | */
  213. {MPU_SILICON_REV_A4, 131}, /* 3 V */
  214. {MPU_SILICON_REV_A4, 131}, /* 4 */
  215. {MPU_SILICON_REV_A4, 131}, /* 5 */
  216. {MPU_SILICON_REV_A4, 131}, /* 6 */
  217. {MPU_SILICON_REV_A4, 131}, /* 7 */
  218. {MPU_SILICON_REV_A4, 131}, /* 8 */
  219. {MPU_SILICON_REV_A4, 131}, /* 9 */
  220. {MPU_SILICON_REV_A4, 131}, /* 10 */
  221. {MPU_SILICON_REV_B1, 131}, /* 11 B1 */
  222. {MPU_SILICON_REV_B1, 131}, /* 12 | */
  223. {MPU_SILICON_REV_B1, 131}, /* 13 V */
  224. {MPU_SILICON_REV_B1, 131}, /* 14 B4 */
  225. {MPU_SILICON_REV_B4, 131}, /* 15 | */
  226. {MPU_SILICON_REV_B4, 131}, /* 16 V */
  227. {MPU_SILICON_REV_B4, 131}, /* 17 */
  228. {MPU_SILICON_REV_B4, 131}, /* 18 */
  229. {MPU_SILICON_REV_B4, 115}, /* 19 */
  230. {MPU_SILICON_REV_B4, 115}, /* 20 */
  231. {MPU_SILICON_REV_B6, 131}, /* 21 B6 (B6/A9) */
  232. {MPU_SILICON_REV_B4, 115}, /* 22 B4 (B7/A10) */
  233. {MPU_SILICON_REV_B6, 0}, /* 23 B6 (npp) */
  234. {MPU_SILICON_REV_B6, 0}, /* 24 | (npp) */
  235. {MPU_SILICON_REV_B6, 0}, /* 25 V (npp) */
  236. {MPU_SILICON_REV_B6, 131}, /* 26 (B6/A11) */
  237. };
  238. #endif /* !M_HW */
  239. /**
  240. * @internal
  241. * @brief Get the silicon revision ID from OTP.
  242. * The silicon revision number is in read from OTP bank 0,
  243. * ADDR6[7:2]. The corresponding ID is retrieved by lookup
  244. * in a map.
  245. * @return The silicon revision ID (0 on error).
  246. */
  247. static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
  248. void *mlsl_handle)
  249. {
  250. int result;
  251. unsigned char index = 0x00;
  252. unsigned char bank =
  253. (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0);
  254. unsigned short memAddr = ((bank << 8) | 0x06);
  255. result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
  256. memAddr, 1, &index);
  257. ERROR_CHECK(result);
  258. if (result)
  259. return result;
  260. index >>= 2;
  261. /* clean the prefetch and cfg user bank bits */
  262. result =
  263. MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  264. MPUREG_BANK_SEL, 0);
  265. ERROR_CHECK(result);
  266. if (result)
  267. return result;
  268. if (index < OLDEST_PROD_REV_SUPPORTED || NUM_OF_PROD_REVS <= index) {
  269. pdata->silicon_revision = 0;
  270. pdata->trim = 0;
  271. MPL_LOGE("Unsupported Product Revision Detected : %d\n", index);
  272. return ML_ERROR_INVALID_MODULE;
  273. }
  274. pdata->silicon_revision = prodRevsMap[index].siliconRev;
  275. pdata->trim = prodRevsMap[index].sensTrim;
  276. if (pdata->trim == 0) {
  277. MPL_LOGE("sensitivity trim is 0"
  278. " - unsupported non production part.\n");
  279. return ML_ERROR_INVALID_MODULE;
  280. }
  281. return result;
  282. }
  283. /**
  284. * @brief Enable / Disable the use MPU's secondary I2C interface level
  285. * shifters.
  286. * When enabled the secondary I2C interface to which the external
  287. * device is connected runs at VDD voltage (main supply).
  288. * When disabled the 2nd interface runs at VDDIO voltage.
  289. * See the device specification for more details.
  290. *
  291. * @note using this API may produce unpredictable results, depending on how
  292. * the MPU and slave device are setup on the target platform.
  293. * Use of this API should entirely be restricted to system
  294. * integrators. Once the correct value is found, there should be no
  295. * need to change the level shifter at runtime.
  296. *
  297. * @pre Must be called after MLSerialOpen().
  298. * @note Typically called before MLDmpOpen().
  299. *
  300. * @param[in] enable:
  301. * 0 to run at VDDIO (default),
  302. * 1 to run at VDD.
  303. *
  304. * @return ML_SUCCESS if successfull, a non-zero error code otherwise.
  305. */
  306. static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
  307. void *mlsl_handle,
  308. unsigned char enable)
  309. {
  310. #ifndef M_HW
  311. int result;
  312. unsigned char reg;
  313. unsigned char mask;
  314. unsigned char regval;
  315. if (0 == pdata->silicon_revision)
  316. return ML_ERROR_INVALID_PARAMETER;
  317. /*-- on parts before B6 the VDDIO bit is bit 7 of ACCEL_BURST_ADDR --
  318. NOTE: this is incompatible with ST accelerometers where the VDDIO
  319. bit MUST be set to enable ST's internal logic to autoincrement
  320. the register address on burst reads --*/
  321. if ((pdata->silicon_revision & 0xf) < MPU_SILICON_REV_B6) {
  322. reg = MPUREG_ACCEL_BURST_ADDR;
  323. mask = 0x80;
  324. } else {
  325. /*-- on B6 parts the VDDIO bit was moved to FIFO_EN2 =>
  326. the mask is always 0x04 --*/
  327. reg = MPUREG_FIFO_EN2;
  328. mask = 0x04;
  329. }
  330. result = MLSLSerialRead(mlsl_handle, pdata->addr, reg, 1, &regval);
  331. if (result)
  332. return result;
  333. if (enable)
  334. regval |= mask;
  335. else
  336. regval &= ~mask;
  337. result =
  338. MLSLSerialWriteSingle(mlsl_handle, pdata->addr, reg, regval);
  339. return result;
  340. #else
  341. return ML_SUCCESS;
  342. #endif
  343. }
  344. #ifdef M_HW
  345. /**
  346. * @internal
  347. * @param reset 1 to reset hardware
  348. */
  349. static tMLError mpu60xx_pwr_mgmt(struct mldl_cfg *pdata,
  350. void *mlsl_handle,
  351. unsigned char reset,
  352. unsigned char powerselection)
  353. {
  354. unsigned char b;
  355. tMLError result;
  356. if (powerselection < 0 || powerselection > 7)
  357. return ML_ERROR_INVALID_PARAMETER;
  358. result =
  359. MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_1, 1,
  360. &b);
  361. ERROR_CHECK(result);
  362. b &= ~(BITS_PWRSEL);
  363. if (reset) {
  364. /* Current sillicon has an errata where the reset will get
  365. * nacked. Ignore the error code for now. */
  366. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  367. MPUREG_PWR_MGM, b | BIT_H_RESET);
  368. #define M_HW_RESET_ERRATTA
  369. #ifndef M_HW_RESET_ERRATTA
  370. ERROR_CHECK(result);
  371. #else
  372. MLOSSleep(50);
  373. #endif
  374. }
  375. b |= (powerselection << 4);
  376. if (b & BITS_PWRSEL)
  377. pdata->gyro_is_suspended = FALSE;
  378. else
  379. pdata->gyro_is_suspended = TRUE;
  380. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  381. MPUREG_PWR_MGM, b);
  382. ERROR_CHECK(result);
  383. return ML_SUCCESS;
  384. }
  385. /**
  386. * @internal
  387. */
  388. static tMLError MLDLStandByGyros(struct mldl_cfg *pdata,
  389. void *mlsl_handle,
  390. unsigned char disable_gx,
  391. unsigned char disable_gy,
  392. unsigned char disable_gz)
  393. {
  394. unsigned char b;
  395. tMLError result;
  396. result =
  397. MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
  398. &b);
  399. ERROR_CHECK(result);
  400. b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
  401. b |= (disable_gx << 2 | disable_gy << 1 | disable_gz);
  402. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  403. MPUREG_PWR_MGMT_2, b);
  404. ERROR_CHECK(result);
  405. return ML_SUCCESS;
  406. }
  407. /**
  408. * @internal
  409. */
  410. static tMLError MLDLStandByAccels(struct mldl_cfg *pdata,
  411. void *mlsl_handle,
  412. unsigned char disable_ax,
  413. unsigned char disable_ay,
  414. unsigned char disable_az)
  415. {
  416. unsigned char b;
  417. tMLError result;
  418. result =
  419. MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
  420. &b);
  421. ERROR_CHECK(result);
  422. b &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
  423. b |= (disable_ax << 2 | disable_ay << 1 | disable_az);
  424. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  425. MPUREG_PWR_MGMT_2, b);
  426. ERROR_CHECK(result);
  427. return ML_SUCCESS;
  428. }
  429. #else /* ! M_HW */
  430. /**
  431. * @internal
  432. * @brief This function controls the power management on the MPU device.
  433. * The entire chip can be put to low power sleep mode, or individual
  434. * gyros can be turned on/off.
  435. *
  436. * Putting the device into sleep mode depending upon the changing needs
  437. * of the associated applications is a recommended method for reducing
  438. * power consuption. It is a safe opearation in that sleep/wake up of
  439. * gyros while running will not result in any interruption of data.
  440. *
  441. * Although it is entirely allowed to put the device into full sleep
  442. * while running the DMP, it is not recomended because it will disrupt
  443. * the ongoing calculations carried on inside the DMP and consequently
  444. * the sensor fusion algorithm. Furthermore, while in sleep mode
  445. * read & write operation from the app processor on both registers and
  446. * memory are disabled and can only regained by restoring the MPU in
  447. * normal power mode.
  448. * Disabling any of the gyro axis will reduce the associated power
  449. * consuption from the PLL but will not stop the DMP from running
  450. * state.
  451. *
  452. * @param reset
  453. * Non-zero to reset the device. Note that this setting
  454. * is volatile and the corresponding register bit will
  455. * clear itself right after being applied.
  456. * @param sleep
  457. * Non-zero to put device into full sleep.
  458. * @param disable_gx
  459. * Non-zero to disable gyro X.
  460. * @param disable_gy
  461. * Non-zero to disable gyro Y.
  462. * @param disable_gz
  463. * Non-zero to disable gyro Z.
  464. *
  465. * @return ML_SUCCESS if successfull; a non-zero error code otherwise.
  466. */
  467. static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
  468. void *mlsl_handle,
  469. unsigned char reset,
  470. unsigned char sleep,
  471. unsigned char disable_gx,
  472. unsigned char disable_gy,
  473. unsigned char disable_gz)
  474. {
  475. unsigned char b;
  476. int result;
  477. result =
  478. MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1,
  479. &b);
  480. ERROR_CHECK(result);
  481. /* If we are awake, we need to put it in bypass before resetting */
  482. if ((!(b & BIT_SLEEP)) && reset)
  483. result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
  484. /* If we are awake, we need stop the dmp sleeping */
  485. if ((!(b & BIT_SLEEP)) && sleep)
  486. dmp_stop(pdata, mlsl_handle);
  487. /* Reset if requested */
  488. if (reset) {
  489. MPL_LOGV("Reset MPU3050\n");
  490. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  491. MPUREG_PWR_MGM, b | BIT_H_RESET);
  492. ERROR_CHECK(result);
  493. MLOSSleep(5);
  494. pdata->gyro_needs_reset = FALSE;
  495. /* Some chips are awake after reset and some are asleep,
  496. * check the status */
  497. result = MLSLSerialRead(mlsl_handle, pdata->addr,
  498. MPUREG_PWR_MGM, 1, &b);
  499. ERROR_CHECK(result);
  500. }
  501. /* Update the suspended state just in case we return early */
  502. if (b & BIT_SLEEP)
  503. pdata->gyro_is_suspended = TRUE;
  504. else
  505. pdata->gyro_is_suspended = FALSE;
  506. /* if power status match requested, nothing else's left to do */
  507. if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
  508. (((sleep != 0) * BIT_SLEEP) |
  509. ((disable_gx != 0) * BIT_STBY_XG) |
  510. ((disable_gy != 0) * BIT_STBY_YG) |
  511. ((disable_gz != 0) * BIT_STBY_ZG))) {
  512. return ML_SUCCESS;
  513. }
  514. /*
  515. * This specific transition between states needs to be reinterpreted:
  516. * (1,1,1,1) -> (0,1,1,1) has to become
  517. * (1,1,1,1) -> (1,0,0,0) -> (0,1,1,1)
  518. * where
  519. * (1,1,1,1) is (sleep=1,disable_gx=1,disable_gy=1,disable_gz=1)
  520. */
  521. if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
  522. (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
  523. && ((!sleep) && disable_gx && disable_gy && disable_gz)) {
  524. result = MLDLPowerMgmtMPU(pdata, mlsl_handle, 0, 1, 0, 0, 0);
  525. if (result)
  526. return result;
  527. b |= BIT_SLEEP;
  528. b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
  529. }
  530. if ((b & BIT_SLEEP) != ((sleep != 0) * BIT_SLEEP)) {
  531. if (sleep) {
  532. result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
  533. ERROR_CHECK(result);
  534. b |= BIT_SLEEP;
  535. result =
  536. MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  537. MPUREG_PWR_MGM, b);
  538. ERROR_CHECK(result);
  539. pdata->gyro_is_suspended = TRUE;
  540. } else {
  541. b &= ~BIT_SLEEP;
  542. result =
  543. MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  544. MPUREG_PWR_MGM, b);
  545. ERROR_CHECK(result);
  546. pdata->gyro_is_suspended = FALSE;
  547. MLOSSleep(5);
  548. }
  549. }
  550. /*---
  551. WORKAROUND FOR PUTTING GYRO AXIS in STAND-BY MODE
  552. 1) put one axis at a time in stand-by
  553. ---*/
  554. if ((b & BIT_STBY_XG) != ((disable_gx != 0) * BIT_STBY_XG)) {
  555. b ^= BIT_STBY_XG;
  556. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  557. MPUREG_PWR_MGM, b);
  558. ERROR_CHECK(result);
  559. }
  560. if ((b & BIT_STBY_YG) != ((disable_gy != 0) * BIT_STBY_YG)) {
  561. b ^= BIT_STBY_YG;
  562. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  563. MPUREG_PWR_MGM, b);
  564. ERROR_CHECK(result);
  565. }
  566. if ((b & BIT_STBY_ZG) != ((disable_gz != 0) * BIT_STBY_ZG)) {
  567. b ^= BIT_STBY_ZG;
  568. result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
  569. MPUREG_PWR_MGM, b);
  570. ERROR_CHECK(result);
  571. }
  572. return ML_SUCCESS;
  573. }
  574. #endif /* M_HW */
  575. void mpu_print_cfg(struct mldl_cfg *mldl_cfg)
  576. {
  577. struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
  578. struct ext_slave_platform_data *accel = &mldl_cfg->pdata->accel;
  579. struct ext_slave_platform_data *compass =
  580. &mldl_cfg->pdata->compass;
  581. struct ext_slave_platform_data *pressure =
  582. &mldl_cfg->pdata->pressure;
  583. MPL_LOGD("mldl_cfg.addr = %02x\n", mldl_cfg->addr);
  584. MPL_LOGD("mldl_cfg.int_config = %02x\n",
  585. mldl_cfg->int_config);
  586. MPL_LOGD("mldl_cfg.ext_sync = %02x\n", mldl_cfg->ext_sync);
  587. MPL_LOGD("mldl_cfg.full_scale = %02x\n",
  588. mldl_cfg->full_scale);
  589. MPL_LOGD("mldl_cfg.lpf = %02x\n", mldl_cfg->lpf);
  590. MPL_LOGD("mldl_cfg.clk_src = %02x\n", mldl_cfg->clk_src);
  591. MPL_LOGD("mldl_cfg.divider = %02x\n", mldl_cfg->divider);
  592. MPL_LOGD("mldl_cfg.dmp_enable = %02x\n",
  593. mldl_cfg->dmp_enable);
  594. MPL_LOGD("mldl_cfg.fifo_enable = %02x\n",
  595. mldl_cfg->fifo_enable);
  596. MPL_LOGD("mldl_cfg.dmp_cfg1 = %02x\n", mldl_cfg->dmp_cfg1);
  597. MPL_LOGD("mldl_cfg.dmp_cfg2 = %02x\n", mldl_cfg->dmp_cfg2);
  598. MPL_LOGD("mldl_cfg.offset_tc[0] = %02x\n",
  599. mldl_cfg->offset_tc[0]);
  600. MPL_LOGD("mldl_cfg.offset_tc[1] = %02x\n",
  601. mldl_cfg->offset_tc[1]);
  602. MPL_LOGD("mldl_cfg.offset_tc[2] = %02x\n",
  603. mldl_cfg->offset_tc[2]);
  604. MPL_LOGD("mldl_cfg.silicon_revision = %02x\n",
  605. mldl_cfg->silicon_revision);
  606. MPL_LOGD("mldl_cfg.product_id = %02x\n",
  607. mldl_cfg->product_id);
  608. MPL_LOGD("mldl_cfg.trim = %02x\n", mldl_cfg->trim);
  609. MPL_LOGD("mldl_cfg.requested_sensors= %04lx\n",
  610. mldl_cfg->requested_sensors);
  611. if (mldl_cfg->accel) {
  612. MPL_LOGD("slave_accel->suspend = %02x\n",
  613. (int) mldl_cfg->accel->suspend);
  614. MPL_LOGD("slave_accel->resume = %02x\n",
  615. (int) mldl_cfg->accel->resume);
  616. MPL_LOGD("slave_accel->read = %02x\n",
  617. (int) mldl_cfg->accel->read);
  618. MPL_LOGD("slave_accel->type = %02x\n",
  619. mldl_cfg->accel->type);
  620. MPL_LOGD("slave_accel->reg = %02x\n",
  621. mldl_cfg->accel->reg);
  622. MPL_LOGD("slave_accel->len = %02x\n",
  623. mldl_cfg->accel->len);
  624. MPL_LOGD("slave_accel->endian = %02x\n",
  625. mldl_cfg->accel->endian);
  626. MPL_LOGD("slave_accel->range.mantissa= %02lx\n",
  627. mldl_cfg->accel->range.mantissa);
  628. MPL_LOGD("slave_accel->range.fraction= %02lx\n",
  629. mldl_cfg->accel->range.fraction);
  630. } else {
  631. MPL_LOGD("slave_accel = NULL\n");
  632. }
  633. if (mldl_cfg->compass) {
  634. MPL_LOGD("slave_compass->suspend = %02x\n",
  635. (int) mldl_cfg->compass->suspend);
  636. MPL_LOGD("slave_compass->resume = %02x\n",
  637. (int) mldl_cfg->compass->resume);
  638. MPL_LOGD("slave_compass->read = %02x\n",
  639. (int) mldl_cfg->compass->read);
  640. MPL_LOGD("slave_compass->type = %02x\n",
  641. mldl_cfg->compass->type);
  642. MPL_LOGD("slave_compass->reg = %02x\n",
  643. mldl_cfg->compass->reg);
  644. MPL_LOGD("slave_compass->len = %02x\n",
  645. mldl_cfg->compass->len);
  646. MPL_LOGD("slave_compass->endian = %02x\n",
  647. mldl_cfg->compass->endian);
  648. MPL_LOGD("slave_compass->range.mantissa= %02lx\n",
  649. mldl_cfg->compass->range.mantissa);
  650. MPL_LOGD("slave_compass->range.fraction= %02lx\n",
  651. mldl_cfg->compass->range.fraction);
  652. } else {
  653. MPL_LOGD("slave_compass = NULL\n");
  654. }
  655. if (mldl_cfg->pressure) {
  656. MPL_LOGD("slave_pressure->suspend = %02x\n",
  657. (int) mldl_cfg->pressure->suspend);
  658. MPL_LOGD("slave_pressure->resume = %02x\n",
  659. (int) mldl_cfg->pressure->resume);
  660. MPL_LOGD("slave_pressure->read = %02x\n",
  661. (int) mldl_cfg->pressure->read);
  662. MPL_LOGD("slave_pressure->type = %02x\n",
  663. mldl_cfg->pressure->type);
  664. MPL_LOGD("slave_pressure->reg = %02x\n",
  665. mldl_cfg->pressure->reg);
  666. MPL_LOGD("slave_pressure->len = %02x\n",
  667. mldl_cfg->pressure->len);
  668. MPL_LOGD("slave_pressure->endian = %02x\n",
  669. mldl_cfg->pressure->endian);
  670. MPL_LOGD("slave_pressure->range.mantissa= %02lx\n",
  671. mldl_cfg->pressure->range.mantissa);
  672. MPL_LOGD("slave_pressure->range.fraction= %02lx\n",
  673. mldl_cfg->pressure->range.fraction);
  674. } else {
  675. MPL_LOGD("slave_pressure = NULL\n");
  676. }
  677. MPL_LOGD("accel->get_slave_descr = %x\n",
  678. (unsigned int) accel->get_slave_descr);
  679. MPL_LOGD("accel->irq = %02x\n", accel->irq);
  680. MPL_LOGD("accel->adapt_num = %02x\n", accel->adapt_num);
  681. MPL_LOGD("accel->bus = %02x\n", accel->bus);
  682. MPL_LOGD("accel->address = %02x\n", accel->address);
  683. MPL_LOGD("accel->orientation =\n"
  684. " %2d %2d %2d\n"
  685. " %2d %2d %2d\n"
  686. " %2d %2d %2d\n",
  687. accel->orientation[0], accel->orientation[1],
  688. accel->orientation[2], accel->orientation[3],
  689. accel->orientation[4], accel->orientation[5],
  690. accel->orientation[6], accel->orientation[7],
  691. accel->orientation[8]);
  692. MPL_LOGD("compass->get_slave_descr = %x\n",
  693. (unsigned int) compass->get_slave_descr);
  694. MPL_LOGD("compass->irq = %02x\n", compass->irq);
  695. MPL_LOGD("compass->adapt_num = %02x\n", compass->adapt_num);
  696. MPL_LOGD("compass->bus = %02x\n", compass->bus);
  697. MPL_LOGD("compass->address = %02x\n", compass->address);
  698. MPL_LOGD("compass->orientation =\n"
  699. " %2d %2d %2d\n"
  700. " %2d %2d %2d\n"
  701. " %2d %2d %2d\n",
  702. compass->orientation[0], compass->orientation[1],
  703. compass->orientation[2], compass->orientation[3],
  704. compass->orientation[4], compass->orientation[5],
  705. compass->orientation[6], compass->orientation[7],
  706. compass->orientation[8]);
  707. MPL_LOGD("pressure->get_slave_descr = %x\n",
  708. (unsigned int) pressure->get_slave_descr);
  709. MPL_LOGD("pressure->irq = %02x\n", pressure->irq);
  710. MPL_LOGD("pressure->adapt_num = %02x\n", pressure->adapt_num);
  711. MPL_LOGD("pressure->bus = %02x\n", pressure->bus);
  712. MPL_LOGD("pressure->address = %02x\n", pressure->address);
  713. MPL_LOGD("pressure->orientation =\n"
  714. " %2d %2d %2d\n"
  715. " %2d %2d %2d\n"
  716. " %2d %2d %2d\n",
  717. pressure->orientation[0], pressure->orientation[1],
  718. pressure->orientation[2], pressure->orientation[3],
  719. pressure->orientation[4], pressure->orientation[5],
  720. pressure->orientation[6], pressure->orientation[7],
  721. pressure->orientation[8]);
  722. MPL_LOGD("pdata->int_config = %02x\n", pdata->int_config);
  723. MPL_LOGD("pdata->level_shifter = %02x\n",
  724. pdata->level_shifter);
  725. MPL_LOGD("pdata->orientation =\n"
  726. " %2d %2d %2d\n"
  727. " %2d %2d %2d\n"
  728. " %2d %2d %2d\n",
  729. pdata->orientation[0], pdata->orientation[1],
  730. pdata->orientation[2], pdata->orientation[3],
  731. pdata->orientation[4], pdata->orientation[5],
  732. pdata->orientation[6], pdata->orientation[7],
  733. pdata->orientation[8]);
  734. MPL_LOGD("Struct sizes: mldl_cfg: %d, "
  735. "ext_slave_descr:%d, "
  736. "mpu3050_platform_data:%d: RamOffset: %d\n",
  737. sizeof(struct mldl_cfg), sizeof(struct ext_slave_descr),
  738. sizeof(struct mpu3050_platform_data),
  739. offsetof(struct mldl_cfg, ram));
  740. }
  741. int mpu_set_slave(struct mldl_cfg *mldl_cfg,
  742. void *gyro_handle,
  743. struct ext_slave_descr *slave,
  744. struct ext_slave_platform_data *slave_pdata)
  745. {
  746. int result;
  747. unsigned char reg;
  748. unsigned char slave_reg;
  749. unsigned char slave_len;
  750. unsigned char slave_endian;
  751. unsigned char slave_address;
  752. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
  753. if (NULL == slave || NULL == slave_pdata) {
  754. slave_reg = 0;
  755. slave_len = 0;
  756. slave_endian = 0;
  757. slave_address = 0;
  758. } else {
  759. slave_reg = slave->reg;
  760. slave_len = slave->len;
  761. slave_endian = slave->endian;
  762. slave_address = slave_pdata->address;
  763. }
  764. /* Address */
  765. result = MLSLSerialWriteSingle(gyro_handle,
  766. mldl_cfg->addr,
  767. MPUREG_AUX_SLV_ADDR,
  768. slave_address);
  769. ERROR_CHECK(result);
  770. /* Register */
  771. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  772. MPUREG_ACCEL_BURST_ADDR, 1,
  773. &reg);
  774. ERROR_CHECK(result);
  775. reg = ((reg & 0x80) | slave_reg);
  776. result = MLSLSerialWriteSingle(gyro_handle,
  777. mldl_cfg->addr,
  778. MPUREG_ACCEL_BURST_ADDR,
  779. reg);
  780. ERROR_CHECK(result);
  781. #ifdef M_HW
  782. /* Length, byte swapping, grouping & enable */
  783. if (slave_len > BITS_SLV_LENG) {
  784. MPL_LOGW("Limiting slave burst read length to "
  785. "the allowed maximum (15B, req. %d)\n",
  786. slave_len);
  787. slave_len = BITS_SLV_LENG;
  788. }
  789. reg = slave_len;
  790. if (slave_endian == EXT_SLAVE_LITTLE_ENDIAN)
  791. reg |= BIT_SLV_BYTE_SW;
  792. reg |= BIT_SLV_GRP;
  793. reg |= BIT_SLV_ENABLE;
  794. result = MLSLSerialWriteSingle(gyro_handle,
  795. mldl_cfg->addr,
  796. MPUREG_I2C_SLV0_CTRL,
  797. reg);
  798. #else
  799. /* Length */
  800. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  801. MPUREG_USER_CTRL, 1, &reg);
  802. ERROR_CHECK(result);
  803. reg = (reg & ~BIT_AUX_RD_LENG);
  804. result = MLSLSerialWriteSingle(gyro_handle,
  805. mldl_cfg->addr,
  806. MPUREG_USER_CTRL, reg);
  807. ERROR_CHECK(result);
  808. #endif
  809. if (slave_address) {
  810. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, FALSE);
  811. ERROR_CHECK(result);
  812. }
  813. return result;
  814. }
  815. /**
  816. * Check to see if the gyro was reset by testing a couple of registers known
  817. * to change on reset.
  818. *
  819. * @param mldl_cfg mldl configuration structure
  820. * @param gyro_handle handle used to communicate with the gyro
  821. *
  822. * @return ML_SUCCESS or non-zero error code
  823. */
  824. static int mpu_was_reset(struct mldl_cfg *mldl_cfg, void *gyro_handle)
  825. {
  826. int result = ML_SUCCESS;
  827. unsigned char reg;
  828. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  829. MPUREG_DMP_CFG_2, 1, &reg);
  830. ERROR_CHECK(result);
  831. if (mldl_cfg->dmp_cfg2 != reg)
  832. return TRUE;
  833. if (0 != mldl_cfg->dmp_cfg1)
  834. return FALSE;
  835. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  836. MPUREG_SMPLRT_DIV, 1, &reg);
  837. ERROR_CHECK(result);
  838. if (reg != mldl_cfg->divider)
  839. return TRUE;
  840. if (0 != mldl_cfg->divider)
  841. return FALSE;
  842. /* Inconclusive assume it was reset */
  843. return TRUE;
  844. }
  845. static int gyro_resume(struct mldl_cfg *mldl_cfg, void *gyro_handle)
  846. {
  847. int result;
  848. int ii;
  849. int jj;
  850. unsigned char reg;
  851. unsigned char regs[7];
  852. /* Wake up the part */
  853. #ifdef M_HW
  854. result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, RESET,
  855. WAKE_UP);
  856. ERROR_CHECK(result);
  857. /* Configure the MPU */
  858. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
  859. ERROR_CHECK(result);
  860. /* setting int_config with the propert flag BIT_BYPASS_EN
  861. should be done by the setup functions */
  862. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  863. MPUREG_INT_PIN_CFG,
  864. (mldl_cfg->pdata->int_config |
  865. BIT_BYPASS_EN));
  866. ERROR_CHECK(result);
  867. /* temporary: masking out higher bits to avoid switching
  868. intelligence */
  869. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  870. MPUREG_INT_ENABLE,
  871. (mldl_cfg->int_config));
  872. ERROR_CHECK(result);
  873. #else
  874. result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 0, 0,
  875. mldl_cfg->gyro_power & BIT_STBY_XG,
  876. mldl_cfg->gyro_power & BIT_STBY_YG,
  877. mldl_cfg->gyro_power & BIT_STBY_ZG);
  878. if (!mldl_cfg->gyro_needs_reset &&
  879. !mpu_was_reset(mldl_cfg, gyro_handle)) {
  880. return ML_SUCCESS;
  881. }
  882. result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 1, 0,
  883. mldl_cfg->gyro_power & BIT_STBY_XG,
  884. mldl_cfg->gyro_power & BIT_STBY_YG,
  885. mldl_cfg->gyro_power & BIT_STBY_ZG);
  886. ERROR_CHECK(result);
  887. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  888. MPUREG_INT_CFG,
  889. (mldl_cfg->int_config |
  890. mldl_cfg->pdata->int_config));
  891. ERROR_CHECK(result);
  892. #endif
  893. result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
  894. MPUREG_PWR_MGM, 1, &reg);
  895. ERROR_CHECK(result);
  896. reg &= ~BITS_CLKSEL;
  897. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  898. MPUREG_PWR_MGM,
  899. mldl_cfg->clk_src | reg);
  900. ERROR_CHECK(result);
  901. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  902. MPUREG_SMPLRT_DIV,
  903. mldl_cfg->divider);
  904. ERROR_CHECK(result);
  905. #ifdef M_HW
  906. reg = DLPF_FS_SYNC_VALUE(0, mldl_cfg->full_scale, 0);
  907. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  908. MPUREG_GYRO_CONFIG, reg);
  909. reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync, 0, mldl_cfg->lpf);
  910. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  911. MPUREG_CONFIG, reg);
  912. #else
  913. reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync,
  914. mldl_cfg->full_scale, mldl_cfg->lpf);
  915. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  916. MPUREG_DLPF_FS_SYNC, reg);
  917. #endif
  918. ERROR_CHECK(result);
  919. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  920. MPUREG_DMP_CFG_1,
  921. mldl_cfg->dmp_cfg1);
  922. ERROR_CHECK(result);
  923. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  924. MPUREG_DMP_CFG_2,
  925. mldl_cfg->dmp_cfg2);
  926. ERROR_CHECK(result);
  927. /* Write and verify memory */
  928. for (ii = 0; ii < MPU_MEM_NUM_RAM_BANKS; ii++) {
  929. unsigned char read[MPU_MEM_BANK_SIZE];
  930. result = MLSLSerialWriteMem(gyro_handle,
  931. mldl_cfg->addr,
  932. ((ii << 8) | 0x00),
  933. MPU_MEM_BANK_SIZE,
  934. mldl_cfg->ram[ii]);
  935. ERROR_CHECK(result);
  936. result = MLSLSerialReadMem(gyro_handle, mldl_cfg->addr,
  937. ((ii << 8) | 0x00),
  938. MPU_MEM_BANK_SIZE, read);
  939. ERROR_CHECK(result);
  940. #ifdef M_HW
  941. #define ML_SKIP_CHECK 38
  942. #else
  943. #define ML_SKIP_CHECK 20
  944. #endif
  945. for (jj = 0; jj < MPU_MEM_BANK_SIZE; jj++) {
  946. /* skip the register memory locations */
  947. if (ii == 0 && jj < ML_SKIP_CHECK)
  948. continue;
  949. if (mldl_cfg->ram[ii][jj] != read[jj]) {
  950. result = ML_ERROR_SERIAL_WRITE;
  951. break;
  952. }
  953. }
  954. ERROR_CHECK(result);
  955. }
  956. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  957. MPUREG_XG_OFFS_TC,
  958. mldl_cfg->offset_tc[0]);
  959. ERROR_CHECK(result);
  960. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  961. MPUREG_YG_OFFS_TC,
  962. mldl_cfg->offset_tc[1]);
  963. ERROR_CHECK(result);
  964. result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
  965. MPUREG_ZG_OFFS_TC,
  966. mldl_cfg->offset_tc[2]);
  967. ERROR_CHECK(result);
  968. regs[0] = MPUREG_X_OFFS_USRH;
  969. for (ii = 0; ii < DIM(mldl_cfg->offset); ii++) {
  970. regs[1 + ii * 2] =
  971. (unsigned char)(mldl_cfg->offset[ii] >> 8)
  972. & 0xff;
  973. regs[1 + ii * 2 + 1] =
  974. (unsigned char)(mldl_cfg->offset[ii] & 0xff);
  975. }
  976. result = MLSLSerialWrite(gyro_handle, mldl_cfg->addr, 7, regs);
  977. ERROR_CHECK(result);
  978. /* Configure slaves */
  979. result = MLDLSetLevelShifterBit(mldl_cfg, gyro_handle,
  980. mldl_cfg->pdata->level_shifter);
  981. ERROR_CHECK(result);
  982. return result;
  983. }
  984. /*******************************************************************************
  985. *******************************************************************************
  986. * Exported functions
  987. *******************************************************************************
  988. ******************************************************************************/
  989. /**
  990. * Initializes the pdata structure to defaults.
  991. *
  992. * Opens the device to read silicon revision, product id and whoami.
  993. *
  994. * @param mldl_cfg
  995. * The internal device configuration data structure.
  996. * @param mlsl_handle
  997. * The serial communication handle.
  998. *
  999. * @return ML_SUCCESS if silicon revision, product id and woami are supported
  1000. * by this software.
  1001. */
  1002. int mpu3050_open(struct mldl_cfg *mldl_cfg,
  1003. void *mlsl_handle,
  1004. void *accel_handle,
  1005. void *compass_handle,
  1006. void *pressure_handle)
  1007. {
  1008. int result;
  1009. /* Default is Logic HIGH, pushpull, latch disabled, anyread to clear */
  1010. mldl_cfg->ignore_system_suspend = FALSE;
  1011. mldl_cfg->int_config = BIT_INT_ANYRD_2CLEAR | BIT_DMP_INT_EN;
  1012. mldl_cfg->clk_src = MPU_CLK_SEL_PLLGYROZ;
  1013. mldl_cfg->lpf = MPU_FILTER_42HZ;
  1014. mldl_cfg->full_scale = MPU_FS_2000DPS;
  1015. mldl_cfg->divider = 4;
  1016. mldl_cfg->dmp_enable = 1;
  1017. mldl_cfg->fifo_enable = 1;
  1018. mldl_cfg->ext_sync = 0;
  1019. mldl_cfg->dmp_cfg1 = 0;
  1020. mldl_cfg->dmp_cfg2 = 0;
  1021. mldl_cfg->gyro_power = 0;
  1022. mldl_cfg->gyro_is_bypassed = TRUE;
  1023. mldl_cfg->dmp_is_running = FALSE;
  1024. mldl_cfg->gyro_is_suspended = TRUE;
  1025. mldl_cfg->accel_is_suspended = TRUE;
  1026. mldl_cfg->compass_is_suspended = TRUE;
  1027. mldl_cfg->pressure_is_suspended = TRUE;
  1028. mldl_cfg->gyro_needs_reset = FALSE;
  1029. if (mldl_cfg->addr == 0) {
  1030. #ifdef __KERNEL__
  1031. return ML_ERROR_INVALID_PARAMETER;
  1032. #else
  1033. mldl_cfg->addr = 0x68;
  1034. #endif
  1035. }
  1036. /*
  1037. * Reset,
  1038. * Take the DMP out of sleep, and
  1039. * read the product_id, sillicon rev and whoami
  1040. */
  1041. #ifdef M_HW
  1042. result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
  1043. RESET, WAKE_UP);
  1044. #else
  1045. result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, RESET, 0, 0, 0, 0);
  1046. #endif
  1047. ERROR_CHECK(result);
  1048. result = MLDLGetSiliconRev(mldl_cfg, mlsl_handle);
  1049. ERROR_CHECK(result);
  1050. #ifndef M_HW
  1051. result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
  1052. MPUREG_PRODUCT_ID, 1,
  1053. &mldl_cfg->product_id);
  1054. ERROR_CHECK(result);
  1055. #endif
  1056. /* Get the factory temperature compensation offsets */
  1057. result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
  1058. MPUREG_XG_OFFS_TC, 1,
  1059. &mldl_cfg->offset_tc[0]);
  1060. ERROR_CHECK(result);
  1061. result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
  1062. MPUREG_YG_OFFS_TC, 1,
  1063. &mldl_cfg->offset_tc[1]);
  1064. ERROR_CHECK(result);
  1065. result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
  1066. MPUREG_ZG_OFFS_TC, 1,
  1067. &mldl_cfg->offset_tc[2]);
  1068. ERROR_CHECK(result);
  1069. /* Configure the MPU */
  1070. #ifdef M_HW
  1071. result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
  1072. FALSE, SLEEP);
  1073. #else
  1074. result =
  1075. MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, SLEEP, 0, 0, 0);
  1076. #endif
  1077. ERROR_CHECK(result);
  1078. if (mldl_cfg->accel && mldl_cfg->accel->init) {
  1079. result = mldl_cfg->accel->init(accel_handle,
  1080. mldl_cfg->accel,
  1081. &mldl_cfg->pdata->accel);
  1082. ERROR_CHECK(result);
  1083. }
  1084. if (mldl_cfg->compass && mldl_cfg->compass->init) {
  1085. result = mldl_cfg->compass->init(compass_handle,
  1086. mldl_cfg->compass,
  1087. &mldl_cfg->pdata->compass);
  1088. if (ML_SUCCESS != result) {
  1089. MPL_LOGE("mldl_cfg->compass->init returned %d\n",
  1090. result);
  1091. goto out_accel;
  1092. }
  1093. }
  1094. if (mldl_cfg->pressure && mldl_cfg->pressure->init) {
  1095. result = mldl_cfg->pressure->init(pressure_handle,
  1096. mldl_cfg->pressure,
  1097. &mldl_cfg->pdata->pressure);
  1098. if (ML_SUCCESS != result) {
  1099. MPL_LOGE("mldl_cfg->pressure->init returned %d\n",
  1100. result);
  1101. goto out_compass;
  1102. }
  1103. }
  1104. mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
  1105. if (mldl_cfg->accel && mldl_cfg->accel->resume)
  1106. mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
  1107. if (mldl_cfg->compass && mldl_cfg->compass->resume)
  1108. mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
  1109. if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
  1110. mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
  1111. return result;
  1112. out_compass:
  1113. if (mldl_cfg->compass->init)
  1114. mldl_cfg->compass->exit(compass_handle,
  1115. mldl_cfg->compass,
  1116. &mldl_cfg->pdata->compass);
  1117. out_accel:
  1118. if (mldl_cfg->accel->init)
  1119. mldl_cfg->accel->exit(accel_handle,
  1120. mldl_cfg->accel,
  1121. &mldl_cfg->pdata->accel);
  1122. return result;
  1123. }
  1124. /**
  1125. * Close the mpu3050 interface
  1126. *
  1127. * @param mldl_cfg pointer to the configuration structure
  1128. * @param mlsl_handle pointer to the serial layer handle
  1129. *
  1130. * @return ML_SUCCESS or non-zero error code
  1131. */
  1132. int mpu3050_close(struct mldl_cfg *mldl_cfg,
  1133. void *mlsl_handle,
  1134. void *accel_handle,
  1135. void *compass_handle,
  1136. void *pressure_handle)
  1137. {
  1138. int result = ML_SUCCESS;
  1139. int ret_result = ML_SUCCESS;
  1140. if (mldl_cfg->accel && mldl_cfg->accel->exit) {
  1141. result = mldl_cfg->accel->exit(accel_handle,
  1142. mldl_cfg->accel,
  1143. &mldl_cfg->pdata->accel);
  1144. if (ML_SUCCESS != result)
  1145. MPL_LOGE("Accel exit failed %d\n", result);
  1146. ret_result = result;
  1147. }
  1148. if (ML_SUCCESS == ret_result)
  1149. ret_result = result;
  1150. if (mldl_cfg->compass && mldl_cfg->compass->exit) {
  1151. result = mldl_cfg->compass->exit(compass_handle,
  1152. mldl_cfg->compass,
  1153. &mldl_cfg->pdata->compass);
  1154. if (ML_SUCCESS != result)
  1155. MPL_LOGE("Compass exit failed %d\n", result);
  1156. }
  1157. if (ML_SUCCESS == ret_result)
  1158. ret_result = result;
  1159. if (mldl_cfg->pressure && mldl_cfg->pressure->exit) {
  1160. result = mldl_cfg->pressure->exit(pressure_handle,
  1161. mldl_cfg->pressure,
  1162. &mldl_cfg->pdata->pressure);
  1163. if (ML_SUCCESS != result)
  1164. MPL_LOGE("Pressure exit failed %d\n", result);
  1165. }
  1166. if (ML_SUCCESS == ret_result)
  1167. ret_result = result;
  1168. return ret_result;
  1169. }
  1170. /**
  1171. * @brief resume the MPU3050 device and all the other sensor
  1172. * devices from their low power state.
  1173. *
  1174. * @param mldl_cfg
  1175. * pointer to the configuration structure
  1176. * @param gyro_handle
  1177. * the main file handle to the MPU3050 device.
  1178. * @param accel_handle
  1179. * an handle to the accelerometer device, if sitting
  1180. * onto a separate bus. Can match mlsl_handle if
  1181. * the accelerometer device operates on the same
  1182. * primary bus of MPU.
  1183. * @param compass_handle
  1184. * an handle to the compass device, if sitting
  1185. * onto a separate bus. Can match mlsl_handle if
  1186. * the compass device operates on the same
  1187. * primary bus of MPU.
  1188. * @param pressure_handle
  1189. * an handle to the pressure sensor device, if sitting
  1190. * onto a separate bus. Can match mlsl_handle if
  1191. * the pressure sensor device operates on the same
  1192. * primary bus of MPU.
  1193. * @param resume_gyro
  1194. * whether resuming the gyroscope device is
  1195. * actually needed (if the device supports low power
  1196. * mode of some sort).
  1197. * @param resume_accel
  1198. * whether resuming the accelerometer device is
  1199. * actually needed (if the device supports low power
  1200. * mode of some sort).
  1201. * @param resume_compass
  1202. * whether resuming the compass device is
  1203. * actually needed (if the device supports low power
  1204. * mode of some sort).
  1205. * @param resume_pressure
  1206. * whether resuming the pressure sensor device is
  1207. * actually needed (if the device supports low power
  1208. * mode of some sort).
  1209. * @return ML_SUCCESS or a non-zero error code.
  1210. */
  1211. int mpu3050_resume(struct mldl_cfg *mldl_cfg,
  1212. void *gyro_handle,
  1213. void *accel_handle,
  1214. void *compass_handle,
  1215. void *pressure_handle,
  1216. bool resume_gyro,
  1217. bool resume_accel,
  1218. bool resume_compass,
  1219. bool resume_pressure)
  1220. {
  1221. int result = ML_SUCCESS;
  1222. #ifdef CONFIG_MPU_SENSORS_DEBUG
  1223. mpu_print_cfg(mldl_cfg);
  1224. #endif
  1225. if (resume_accel &&
  1226. ((!mldl_cfg->accel) || (!mldl_cfg->accel->resume)))
  1227. return ML_ERROR_INVALID_PARAMETER;
  1228. if (resume_compass &&
  1229. ((!mldl_cfg->compass) || (!mldl_cfg->compass->resume)))
  1230. return ML_ERROR_INVALID_PARAMETER;
  1231. if (resume_pressure &&
  1232. ((!mldl_cfg->pressure) || (!mldl_cfg->pressure->resume)))
  1233. return ML_ERROR_INVALID_PARAMETER;
  1234. if (resume_gyro && mldl_cfg->gyro_is_suspended) {
  1235. result = gyro_resume(mldl_cfg, gyro_handle);
  1236. ERROR_CHECK(result);
  1237. }
  1238. if (resume_accel && mldl_cfg->accel_is_suspended) {
  1239. if (!mldl_cfg->gyro_is_suspended &&
  1240. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
  1241. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
  1242. ERROR_CHECK(result);
  1243. }
  1244. result = mldl_cfg->accel->resume(accel_handle,
  1245. mldl_cfg->accel,
  1246. &mldl_cfg->pdata->accel);
  1247. ERROR_CHECK(result);
  1248. mldl_cfg->accel_is_suspended = FALSE;
  1249. }
  1250. if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->accel_is_suspended &&
  1251. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
  1252. result = mpu_set_slave(mldl_cfg,
  1253. gyro_handle,
  1254. mldl_cfg->accel,
  1255. &mldl_cfg->pdata->accel);
  1256. ERROR_CHECK(result);
  1257. }
  1258. if (resume_compass && mldl_cfg->compass_is_suspended) {
  1259. if (!mldl_cfg->gyro_is_suspended &&
  1260. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
  1261. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
  1262. ERROR_CHECK(result);
  1263. }
  1264. result = mldl_cfg->compass->resume(compass_handle,
  1265. mldl_cfg->compass,
  1266. &mldl_cfg->pdata->
  1267. compass);
  1268. ERROR_CHECK(result);
  1269. mldl_cfg->compass_is_suspended = FALSE;
  1270. }
  1271. if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->compass_is_suspended &&
  1272. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
  1273. result = mpu_set_slave(mldl_cfg,
  1274. gyro_handle,
  1275. mldl_cfg->compass,
  1276. &mldl_cfg->pdata->compass);
  1277. ERROR_CHECK(result);
  1278. }
  1279. if (resume_pressure && mldl_cfg->pressure_is_suspended) {
  1280. if (!mldl_cfg->gyro_is_suspended &&
  1281. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
  1282. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
  1283. ERROR_CHECK(result);
  1284. }
  1285. result = mldl_cfg->pressure->resume(pressure_handle,
  1286. mldl_cfg->pressure,
  1287. &mldl_cfg->pdata->
  1288. pressure);
  1289. ERROR_CHECK(result);
  1290. mldl_cfg->pressure_is_suspended = FALSE;
  1291. }
  1292. if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->pressure_is_suspended &&
  1293. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
  1294. result = mpu_set_slave(mldl_cfg,
  1295. gyro_handle,
  1296. mldl_cfg->pressure,
  1297. &mldl_cfg->pdata->pressure);
  1298. ERROR_CHECK(result);
  1299. }
  1300. /* Now start */
  1301. if (resume_gyro) {
  1302. result = dmp_start(mldl_cfg, gyro_handle);
  1303. ERROR_CHECK(result);
  1304. }
  1305. return result;
  1306. }
  1307. /**
  1308. * @brief suspend the MPU3050 device and all the other sensor
  1309. * devices into their low power state.
  1310. * @param gyro_handle
  1311. * the main file handle to the MPU3050 device.
  1312. * @param accel_handle
  1313. * an handle to the accelerometer device, if sitting
  1314. * onto a separate bus. Can match gyro_handle if
  1315. * the accelerometer device operates on the same
  1316. * primary bus of MPU.
  1317. * @param compass_handle
  1318. * an handle to the compass device, if sitting
  1319. * onto a separate bus. Can match gyro_handle if
  1320. * the compass device operates on the same
  1321. * primary bus of MPU.
  1322. * @param pressure_handle
  1323. * an handle to the pressure sensor device, if sitting
  1324. * onto a separate bus. Can match gyro_handle if
  1325. * the pressure sensor device operates on the same
  1326. * primary bus of MPU.
  1327. * @param accel
  1328. * whether suspending the accelerometer device is
  1329. * actually needed (if the device supports low power
  1330. * mode of some sort).
  1331. * @param compass
  1332. * whether suspending the compass device is
  1333. * actually needed (if the device supports low power
  1334. * mode of some sort).
  1335. * @param pressure
  1336. * whether suspending the pressure sensor device is
  1337. * actually needed (if the device supports low power
  1338. * mode of some sort).
  1339. * @return ML_SUCCESS or a non-zero error code.
  1340. */
  1341. int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
  1342. void *gyro_handle,
  1343. void *accel_handle,
  1344. void *compass_handle,
  1345. void *pressure_handle,
  1346. bool suspend_gyro,
  1347. bool suspend_accel,
  1348. bool suspend_compass,
  1349. bool suspend_pressure)
  1350. {
  1351. int result = ML_SUCCESS;
  1352. if (suspend_gyro && !mldl_cfg->gyro_is_suspended) {
  1353. #ifdef M_HW
  1354. return ML_SUCCESS;
  1355. /* This puts the bus into bypass mode */
  1356. result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
  1357. ERROR_CHECK(result);
  1358. result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, 0, SLEEP);
  1359. #else
  1360. result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle,
  1361. 0, SLEEP, 0, 0, 0);
  1362. #endif
  1363. ERROR_CHECK(result);
  1364. }
  1365. if (!mldl_cfg->accel_is_suspended && suspend_accel &&
  1366. mldl_cfg->accel && mldl_cfg->accel->suspend) {
  1367. if (!mldl_cfg->gyro_is_suspended &&
  1368. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
  1369. result = mpu_set_slave(mldl_cfg, gyro_handle,
  1370. NULL, NULL);
  1371. ERROR_CHECK(result);
  1372. }
  1373. result = mldl_cfg->accel->suspend(accel_handle,
  1374. mldl_cfg->accel,
  1375. &mldl_cfg->pdata->accel);
  1376. ERROR_CHECK(result);
  1377. mldl_cfg->accel_is_suspended = TRUE;
  1378. }
  1379. if (!mldl_cfg->compass_is_suspended && suspend_compass &&
  1380. mldl_cfg->compass && mldl_cfg->compass->suspend) {
  1381. if (!mldl_cfg->gyro_is_suspended &&
  1382. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
  1383. result = mpu_set_slave(mldl_cfg, gyro_handle,
  1384. NULL, NULL);
  1385. ERROR_CHECK(result);
  1386. }
  1387. result = mldl_cfg->compass->suspend(compass_handle,
  1388. mldl_cfg->compass,
  1389. &mldl_cfg->
  1390. pdata->compass);
  1391. ERROR_CHECK(result);
  1392. mldl_cfg->compass_is_suspended = TRUE;
  1393. }
  1394. if (!mldl_cfg->pressure_is_suspended && suspend_pressure &&
  1395. mldl_cfg->pressure && mldl_cfg->pressure->suspend) {
  1396. if (!mldl_cfg->gyro_is_suspended &&
  1397. EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
  1398. result = mpu_set_slave(mldl_cfg, gyro_handle,
  1399. NULL, NULL);
  1400. ERROR_CHECK(result);
  1401. }
  1402. result = mldl_cfg->pressure->suspend(pressure_handle,
  1403. mldl_cfg->pressure,
  1404. &mldl_cfg->
  1405. pdata->pressure);
  1406. ERROR_CHECK(result);
  1407. mldl_cfg->pressure_is_suspended = TRUE;
  1408. }
  1409. return result;
  1410. }
  1411. /**
  1412. * @brief read raw sensor data from the accelerometer device
  1413. * in use.
  1414. * @param mldl_cfg
  1415. * A pointer to the struct mldl_cfg data structure.
  1416. * @param accel_handle
  1417. * The handle to the device the accelerometer is connected to.
  1418. * @param data
  1419. * a buffer to store the raw sensor data.
  1420. * @return ML_SUCCESS if successful, a non-zero error code otherwise.
  1421. */
  1422. int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
  1423. void *accel_handle, unsigned char *data)
  1424. {
  1425. if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->read)
  1426. if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus)
  1427. && (!mldl_cfg->gyro_is_bypassed))
  1428. return ML_ERROR_FEATURE_NOT_ENABLED;
  1429. else
  1430. return mldl_cfg->accel->read(accel_handle,
  1431. mldl_cfg->accel,
  1432. &mldl_cfg->pdata->accel,
  1433. data);
  1434. else
  1435. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1436. }
  1437. /**
  1438. * @brief read raw sensor data from the compass device
  1439. * in use.
  1440. * @param mldl_cfg
  1441. * A pointer to the struct mldl_cfg data structure.
  1442. * @param compass_handle
  1443. * The handle to the device the compass is connected to.
  1444. * @param data
  1445. * a buffer to store the raw sensor data.
  1446. * @return ML_SUCCESS if successful, a non-zero error code otherwise.
  1447. */
  1448. int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
  1449. void *compass_handle, unsigned char *data)
  1450. {
  1451. if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->read)
  1452. if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus)
  1453. && (!mldl_cfg->gyro_is_bypassed))
  1454. return ML_ERROR_FEATURE_NOT_ENABLED;
  1455. else
  1456. return mldl_cfg->compass->read(compass_handle,
  1457. mldl_cfg->compass,
  1458. &mldl_cfg->pdata->compass,
  1459. data);
  1460. else
  1461. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1462. }
  1463. /**
  1464. * @brief read raw sensor data from the pressure device
  1465. * in use.
  1466. * @param mldl_cfg
  1467. * A pointer to the struct mldl_cfg data structure.
  1468. * @param pressure_handle
  1469. * The handle to the device the pressure sensor is connected to.
  1470. * @param data
  1471. * a buffer to store the raw sensor data.
  1472. * @return ML_SUCCESS if successful, a non-zero error code otherwise.
  1473. */
  1474. int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg,
  1475. void *pressure_handle, unsigned char *data)
  1476. {
  1477. if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->read)
  1478. if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus)
  1479. && (!mldl_cfg->gyro_is_bypassed))
  1480. return ML_ERROR_FEATURE_NOT_ENABLED;
  1481. else
  1482. return mldl_cfg->pressure->read(
  1483. pressure_handle,
  1484. mldl_cfg->pressure,
  1485. &mldl_cfg->pdata->pressure,
  1486. data);
  1487. else
  1488. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1489. }
  1490. int mpu3050_config_accel(struct mldl_cfg *mldl_cfg,
  1491. void *accel_handle,
  1492. struct ext_slave_config *data)
  1493. {
  1494. if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->config)
  1495. return mldl_cfg->accel->config(accel_handle,
  1496. mldl_cfg->accel,
  1497. &mldl_cfg->pdata->accel,
  1498. data);
  1499. else
  1500. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1501. }
  1502. int mpu3050_config_compass(struct mldl_cfg *mldl_cfg,
  1503. void *compass_handle,
  1504. struct ext_slave_config *data)
  1505. {
  1506. if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->config)
  1507. return mldl_cfg->compass->config(compass_handle,
  1508. mldl_cfg->compass,
  1509. &mldl_cfg->pdata->compass,
  1510. data);
  1511. else
  1512. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1513. }
  1514. int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
  1515. void *pressure_handle,
  1516. struct ext_slave_config *data)
  1517. {
  1518. if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->config)
  1519. return mldl_cfg->pressure->config(pressure_handle,
  1520. mldl_cfg->pressure,
  1521. &mldl_cfg->pdata->pressure,
  1522. data);
  1523. else
  1524. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1525. }
  1526. int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
  1527. void *accel_handle,
  1528. struct ext_slave_config *data)
  1529. {
  1530. if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->get_config)
  1531. return mldl_cfg->accel->get_config(accel_handle,
  1532. mldl_cfg->accel,
  1533. &mldl_cfg->pdata->accel,
  1534. data);
  1535. else
  1536. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1537. }
  1538. int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
  1539. void *compass_handle,
  1540. struct ext_slave_config *data)
  1541. {
  1542. if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->get_config)
  1543. return mldl_cfg->compass->get_config(compass_handle,
  1544. mldl_cfg->compass,
  1545. &mldl_cfg->pdata->compass,
  1546. data);
  1547. else
  1548. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1549. }
  1550. int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
  1551. void *pressure_handle,
  1552. struct ext_slave_config *data)
  1553. {
  1554. if (NULL != mldl_cfg->pressure &&
  1555. NULL != mldl_cfg->pressure->get_config)
  1556. return mldl_cfg->pressure->get_config(pressure_handle,
  1557. mldl_cfg->pressure,
  1558. &mldl_cfg->pdata->pressure,
  1559. data);
  1560. else
  1561. return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
  1562. }
  1563. /**
  1564. *@}
  1565. */