fxos8700_core.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
  4. *
  5. * IIO core driver for FXOS8700, with support for I2C/SPI busses
  6. *
  7. * TODO: Buffer, trigger, and IRQ support
  8. */
  9. #include <linux/module.h>
  10. #include <linux/regmap.h>
  11. #include <linux/acpi.h>
  12. #include <linux/bitops.h>
  13. #include <linux/bitfield.h>
  14. #include <linux/iio/iio.h>
  15. #include <linux/iio/sysfs.h>
  16. #include "fxos8700.h"
  17. /* Register Definitions */
  18. #define FXOS8700_STATUS 0x00
  19. #define FXOS8700_OUT_X_MSB 0x01
  20. #define FXOS8700_OUT_X_LSB 0x02
  21. #define FXOS8700_OUT_Y_MSB 0x03
  22. #define FXOS8700_OUT_Y_LSB 0x04
  23. #define FXOS8700_OUT_Z_MSB 0x05
  24. #define FXOS8700_OUT_Z_LSB 0x06
  25. #define FXOS8700_F_SETUP 0x09
  26. #define FXOS8700_TRIG_CFG 0x0a
  27. #define FXOS8700_SYSMOD 0x0b
  28. #define FXOS8700_INT_SOURCE 0x0c
  29. #define FXOS8700_WHO_AM_I 0x0d
  30. #define FXOS8700_XYZ_DATA_CFG 0x0e
  31. #define FXOS8700_HP_FILTER_CUTOFF 0x0f
  32. #define FXOS8700_PL_STATUS 0x10
  33. #define FXOS8700_PL_CFG 0x11
  34. #define FXOS8700_PL_COUNT 0x12
  35. #define FXOS8700_PL_BF_ZCOMP 0x13
  36. #define FXOS8700_PL_THS_REG 0x14
  37. #define FXOS8700_A_FFMT_CFG 0x15
  38. #define FXOS8700_A_FFMT_SRC 0x16
  39. #define FXOS8700_A_FFMT_THS 0x17
  40. #define FXOS8700_A_FFMT_COUNT 0x18
  41. #define FXOS8700_TRANSIENT_CFG 0x1d
  42. #define FXOS8700_TRANSIENT_SRC 0x1e
  43. #define FXOS8700_TRANSIENT_THS 0x1f
  44. #define FXOS8700_TRANSIENT_COUNT 0x20
  45. #define FXOS8700_PULSE_CFG 0x21
  46. #define FXOS8700_PULSE_SRC 0x22
  47. #define FXOS8700_PULSE_THSX 0x23
  48. #define FXOS8700_PULSE_THSY 0x24
  49. #define FXOS8700_PULSE_THSZ 0x25
  50. #define FXOS8700_PULSE_TMLT 0x26
  51. #define FXOS8700_PULSE_LTCY 0x27
  52. #define FXOS8700_PULSE_WIND 0x28
  53. #define FXOS8700_ASLP_COUNT 0x29
  54. #define FXOS8700_CTRL_REG1 0x2a
  55. #define FXOS8700_CTRL_REG2 0x2b
  56. #define FXOS8700_CTRL_REG3 0x2c
  57. #define FXOS8700_CTRL_REG4 0x2d
  58. #define FXOS8700_CTRL_REG5 0x2e
  59. #define FXOS8700_OFF_X 0x2f
  60. #define FXOS8700_OFF_Y 0x30
  61. #define FXOS8700_OFF_Z 0x31
  62. #define FXOS8700_M_DR_STATUS 0x32
  63. #define FXOS8700_M_OUT_X_MSB 0x33
  64. #define FXOS8700_M_OUT_X_LSB 0x34
  65. #define FXOS8700_M_OUT_Y_MSB 0x35
  66. #define FXOS8700_M_OUT_Y_LSB 0x36
  67. #define FXOS8700_M_OUT_Z_MSB 0x37
  68. #define FXOS8700_M_OUT_Z_LSB 0x38
  69. #define FXOS8700_CMP_X_MSB 0x39
  70. #define FXOS8700_CMP_X_LSB 0x3a
  71. #define FXOS8700_CMP_Y_MSB 0x3b
  72. #define FXOS8700_CMP_Y_LSB 0x3c
  73. #define FXOS8700_CMP_Z_MSB 0x3d
  74. #define FXOS8700_CMP_Z_LSB 0x3e
  75. #define FXOS8700_M_OFF_X_MSB 0x3f
  76. #define FXOS8700_M_OFF_X_LSB 0x40
  77. #define FXOS8700_M_OFF_Y_MSB 0x41
  78. #define FXOS8700_M_OFF_Y_LSB 0x42
  79. #define FXOS8700_M_OFF_Z_MSB 0x43
  80. #define FXOS8700_M_OFF_Z_LSB 0x44
  81. #define FXOS8700_MAX_X_MSB 0x45
  82. #define FXOS8700_MAX_X_LSB 0x46
  83. #define FXOS8700_MAX_Y_MSB 0x47
  84. #define FXOS8700_MAX_Y_LSB 0x48
  85. #define FXOS8700_MAX_Z_MSB 0x49
  86. #define FXOS8700_MAX_Z_LSB 0x4a
  87. #define FXOS8700_MIN_X_MSB 0x4b
  88. #define FXOS8700_MIN_X_LSB 0x4c
  89. #define FXOS8700_MIN_Y_MSB 0x4d
  90. #define FXOS8700_MIN_Y_LSB 0x4e
  91. #define FXOS8700_MIN_Z_MSB 0x4f
  92. #define FXOS8700_MIN_Z_LSB 0x50
  93. #define FXOS8700_TEMP 0x51
  94. #define FXOS8700_M_THS_CFG 0x52
  95. #define FXOS8700_M_THS_SRC 0x53
  96. #define FXOS8700_M_THS_X_MSB 0x54
  97. #define FXOS8700_M_THS_X_LSB 0x55
  98. #define FXOS8700_M_THS_Y_MSB 0x56
  99. #define FXOS8700_M_THS_Y_LSB 0x57
  100. #define FXOS8700_M_THS_Z_MSB 0x58
  101. #define FXOS8700_M_THS_Z_LSB 0x59
  102. #define FXOS8700_M_THS_COUNT 0x5a
  103. #define FXOS8700_M_CTRL_REG1 0x5b
  104. #define FXOS8700_M_CTRL_REG2 0x5c
  105. #define FXOS8700_M_CTRL_REG3 0x5d
  106. #define FXOS8700_M_INT_SRC 0x5e
  107. #define FXOS8700_A_VECM_CFG 0x5f
  108. #define FXOS8700_A_VECM_THS_MSB 0x60
  109. #define FXOS8700_A_VECM_THS_LSB 0x61
  110. #define FXOS8700_A_VECM_CNT 0x62
  111. #define FXOS8700_A_VECM_INITX_MSB 0x63
  112. #define FXOS8700_A_VECM_INITX_LSB 0x64
  113. #define FXOS8700_A_VECM_INITY_MSB 0x65
  114. #define FXOS8700_A_VECM_INITY_LSB 0x66
  115. #define FXOS8700_A_VECM_INITZ_MSB 0x67
  116. #define FXOS8700_A_VECM_INITZ_LSB 0x68
  117. #define FXOS8700_M_VECM_CFG 0x69
  118. #define FXOS8700_M_VECM_THS_MSB 0x6a
  119. #define FXOS8700_M_VECM_THS_LSB 0x6b
  120. #define FXOS8700_M_VECM_CNT 0x6c
  121. #define FXOS8700_M_VECM_INITX_MSB 0x6d
  122. #define FXOS8700_M_VECM_INITX_LSB 0x6e
  123. #define FXOS8700_M_VECM_INITY_MSB 0x6f
  124. #define FXOS8700_M_VECM_INITY_LSB 0x70
  125. #define FXOS8700_M_VECM_INITZ_MSB 0x71
  126. #define FXOS8700_M_VECM_INITZ_LSB 0x72
  127. #define FXOS8700_A_FFMT_THS_X_MSB 0x73
  128. #define FXOS8700_A_FFMT_THS_X_LSB 0x74
  129. #define FXOS8700_A_FFMT_THS_Y_MSB 0x75
  130. #define FXOS8700_A_FFMT_THS_Y_LSB 0x76
  131. #define FXOS8700_A_FFMT_THS_Z_MSB 0x77
  132. #define FXOS8700_A_FFMT_THS_Z_LSB 0x78
  133. #define FXOS8700_A_TRAN_INIT_MSB 0x79
  134. #define FXOS8700_A_TRAN_INIT_LSB_X 0x7a
  135. #define FXOS8700_A_TRAN_INIT_LSB_Y 0x7b
  136. #define FXOS8700_A_TRAN_INIT_LSB_Z 0x7d
  137. #define FXOS8700_TM_NVM_LOCK 0x7e
  138. #define FXOS8700_NVM_DATA0_35 0x80
  139. #define FXOS8700_NVM_DATA_BNK3 0xa4
  140. #define FXOS8700_NVM_DATA_BNK2 0xa5
  141. #define FXOS8700_NVM_DATA_BNK1 0xa6
  142. #define FXOS8700_NVM_DATA_BNK0 0xa7
  143. /* Bit definitions for FXOS8700_CTRL_REG1 */
  144. #define FXOS8700_CTRL_ODR_MAX 0x00
  145. #define FXOS8700_CTRL_ODR_MSK GENMASK(5, 3)
  146. /* Bit definitions for FXOS8700_M_CTRL_REG1 */
  147. #define FXOS8700_HMS_MASK GENMASK(1, 0)
  148. #define FXOS8700_OS_MASK GENMASK(4, 2)
  149. /* Bit definitions for FXOS8700_M_CTRL_REG2 */
  150. #define FXOS8700_MAXMIN_RST BIT(2)
  151. #define FXOS8700_MAXMIN_DIS_THS BIT(3)
  152. #define FXOS8700_MAXMIN_DIS BIT(4)
  153. #define FXOS8700_ACTIVE 0x01
  154. #define FXOS8700_ACTIVE_MIN_USLEEP 4000 /* from table 6 in datasheet */
  155. #define FXOS8700_DEVICE_ID 0xC7
  156. #define FXOS8700_PRE_DEVICE_ID 0xC4
  157. #define FXOS8700_DATA_BUF_SIZE 3
  158. struct fxos8700_data {
  159. struct regmap *regmap;
  160. struct iio_trigger *trig;
  161. __be16 buf[FXOS8700_DATA_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
  162. };
  163. /* Regmap info */
  164. static const struct regmap_range read_range[] = {
  165. {
  166. .range_min = FXOS8700_STATUS,
  167. .range_max = FXOS8700_A_FFMT_COUNT,
  168. }, {
  169. .range_min = FXOS8700_TRANSIENT_CFG,
  170. .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
  171. },
  172. };
  173. static const struct regmap_range write_range[] = {
  174. {
  175. .range_min = FXOS8700_F_SETUP,
  176. .range_max = FXOS8700_TRIG_CFG,
  177. }, {
  178. .range_min = FXOS8700_XYZ_DATA_CFG,
  179. .range_max = FXOS8700_HP_FILTER_CUTOFF,
  180. }, {
  181. .range_min = FXOS8700_PL_CFG,
  182. .range_max = FXOS8700_A_FFMT_CFG,
  183. }, {
  184. .range_min = FXOS8700_A_FFMT_THS,
  185. .range_max = FXOS8700_TRANSIENT_CFG,
  186. }, {
  187. .range_min = FXOS8700_TRANSIENT_THS,
  188. .range_max = FXOS8700_PULSE_CFG,
  189. }, {
  190. .range_min = FXOS8700_PULSE_THSX,
  191. .range_max = FXOS8700_OFF_Z,
  192. }, {
  193. .range_min = FXOS8700_M_OFF_X_MSB,
  194. .range_max = FXOS8700_M_OFF_Z_LSB,
  195. }, {
  196. .range_min = FXOS8700_M_THS_CFG,
  197. .range_max = FXOS8700_M_THS_CFG,
  198. }, {
  199. .range_min = FXOS8700_M_THS_X_MSB,
  200. .range_max = FXOS8700_M_CTRL_REG3,
  201. }, {
  202. .range_min = FXOS8700_A_VECM_CFG,
  203. .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
  204. },
  205. };
  206. static const struct regmap_access_table driver_read_table = {
  207. .yes_ranges = read_range,
  208. .n_yes_ranges = ARRAY_SIZE(read_range),
  209. };
  210. static const struct regmap_access_table driver_write_table = {
  211. .yes_ranges = write_range,
  212. .n_yes_ranges = ARRAY_SIZE(write_range),
  213. };
  214. const struct regmap_config fxos8700_regmap_config = {
  215. .reg_bits = 8,
  216. .val_bits = 8,
  217. .max_register = FXOS8700_NVM_DATA_BNK0,
  218. .rd_table = &driver_read_table,
  219. .wr_table = &driver_write_table,
  220. };
  221. EXPORT_SYMBOL(fxos8700_regmap_config);
  222. #define FXOS8700_CHANNEL(_type, _axis) { \
  223. .type = _type, \
  224. .modified = 1, \
  225. .channel2 = IIO_MOD_##_axis, \
  226. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  227. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
  228. BIT(IIO_CHAN_INFO_SAMP_FREQ), \
  229. }
  230. enum fxos8700_accel_scale_bits {
  231. MODE_2G = 0,
  232. MODE_4G,
  233. MODE_8G,
  234. };
  235. /* scan indexes follow DATA register order */
  236. enum fxos8700_scan_axis {
  237. FXOS8700_SCAN_ACCEL_X = 0,
  238. FXOS8700_SCAN_ACCEL_Y,
  239. FXOS8700_SCAN_ACCEL_Z,
  240. FXOS8700_SCAN_MAGN_X,
  241. FXOS8700_SCAN_MAGN_Y,
  242. FXOS8700_SCAN_MAGN_Z,
  243. FXOS8700_SCAN_RHALL,
  244. FXOS8700_SCAN_TIMESTAMP,
  245. };
  246. enum fxos8700_sensor {
  247. FXOS8700_ACCEL = 0,
  248. FXOS8700_MAGN,
  249. FXOS8700_NUM_SENSORS /* must be last */
  250. };
  251. enum fxos8700_int_pin {
  252. FXOS8700_PIN_INT1,
  253. FXOS8700_PIN_INT2
  254. };
  255. struct fxos8700_scale {
  256. u8 bits;
  257. int uscale;
  258. };
  259. struct fxos8700_odr {
  260. u8 bits;
  261. int odr;
  262. int uodr;
  263. };
  264. static const struct fxos8700_scale fxos8700_accel_scale[] = {
  265. { MODE_2G, 244},
  266. { MODE_4G, 488},
  267. { MODE_8G, 976},
  268. };
  269. /*
  270. * Accellerometer and magnetometer have the same ODR options, set in the
  271. * CTRL_REG1 register. ODR is halved when using both sensors at once in
  272. * hybrid mode.
  273. */
  274. static const struct fxos8700_odr fxos8700_odr[] = {
  275. {0x00, 800, 0},
  276. {0x01, 400, 0},
  277. {0x02, 200, 0},
  278. {0x03, 100, 0},
  279. {0x04, 50, 0},
  280. {0x05, 12, 500000},
  281. {0x06, 6, 250000},
  282. {0x07, 1, 562500},
  283. };
  284. static const struct iio_chan_spec fxos8700_channels[] = {
  285. FXOS8700_CHANNEL(IIO_ACCEL, X),
  286. FXOS8700_CHANNEL(IIO_ACCEL, Y),
  287. FXOS8700_CHANNEL(IIO_ACCEL, Z),
  288. FXOS8700_CHANNEL(IIO_MAGN, X),
  289. FXOS8700_CHANNEL(IIO_MAGN, Y),
  290. FXOS8700_CHANNEL(IIO_MAGN, Z),
  291. IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
  292. };
  293. static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
  294. {
  295. switch (iio_type) {
  296. case IIO_ACCEL:
  297. return FXOS8700_ACCEL;
  298. case IIO_MAGN:
  299. return FXOS8700_MAGN;
  300. default:
  301. return -EINVAL;
  302. }
  303. }
  304. static int fxos8700_set_active_mode(struct fxos8700_data *data,
  305. enum fxos8700_sensor t, bool mode)
  306. {
  307. int ret;
  308. ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
  309. if (ret)
  310. return ret;
  311. usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
  312. FXOS8700_ACTIVE_MIN_USLEEP + 1000);
  313. return 0;
  314. }
  315. static int fxos8700_set_scale(struct fxos8700_data *data,
  316. enum fxos8700_sensor t, int uscale)
  317. {
  318. int i, ret, val;
  319. bool active_mode;
  320. static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
  321. struct device *dev = regmap_get_device(data->regmap);
  322. if (t == FXOS8700_MAGN) {
  323. dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n");
  324. return -EINVAL;
  325. }
  326. /*
  327. * When device is in active mode, it failed to set an ACCEL
  328. * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
  329. * This is not align with the datasheet, but it is a fxos8700
  330. * chip behavier. Set the device in standby mode before setting
  331. * an ACCEL full-scale range.
  332. */
  333. ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
  334. if (ret)
  335. return ret;
  336. active_mode = val & FXOS8700_ACTIVE;
  337. if (active_mode) {
  338. ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
  339. val & ~FXOS8700_ACTIVE);
  340. if (ret)
  341. return ret;
  342. }
  343. for (i = 0; i < scale_num; i++)
  344. if (fxos8700_accel_scale[i].uscale == uscale)
  345. break;
  346. if (i == scale_num)
  347. return -EINVAL;
  348. ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
  349. fxos8700_accel_scale[i].bits);
  350. if (ret)
  351. return ret;
  352. return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
  353. active_mode);
  354. }
  355. static int fxos8700_get_scale(struct fxos8700_data *data,
  356. enum fxos8700_sensor t, int *uscale)
  357. {
  358. int i, ret, val;
  359. static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
  360. if (t == FXOS8700_MAGN) {
  361. *uscale = 1000; /* Magnetometer is locked at 0.001Gs */
  362. return 0;
  363. }
  364. ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
  365. if (ret)
  366. return ret;
  367. for (i = 0; i < scale_num; i++) {
  368. if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
  369. *uscale = fxos8700_accel_scale[i].uscale;
  370. return 0;
  371. }
  372. }
  373. return -EINVAL;
  374. }
  375. static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
  376. int axis, int *val)
  377. {
  378. u8 base, reg;
  379. s16 tmp;
  380. int ret;
  381. /*
  382. * Different register base addresses varies with channel types.
  383. * This bug hasn't been noticed before because using an enum is
  384. * really hard to read. Use an a switch statement to take over that.
  385. */
  386. switch (chan_type) {
  387. case IIO_ACCEL:
  388. base = FXOS8700_OUT_X_MSB;
  389. break;
  390. case IIO_MAGN:
  391. base = FXOS8700_M_OUT_X_MSB;
  392. break;
  393. default:
  394. return -EINVAL;
  395. }
  396. /* Block read 6 bytes of device output registers to avoid data loss */
  397. ret = regmap_bulk_read(data->regmap, base, data->buf,
  398. sizeof(data->buf));
  399. if (ret)
  400. return ret;
  401. /* Convert axis to buffer index */
  402. reg = axis - IIO_MOD_X;
  403. /*
  404. * Convert to native endianness. The accel data and magn data
  405. * are signed, so a forced type conversion is needed.
  406. */
  407. tmp = be16_to_cpu(data->buf[reg]);
  408. /*
  409. * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis
  410. * 14-bit left-justified sample data and MAGN output data registers
  411. * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply
  412. * a signed 2 bits right shift to the readback raw data from ACCEL
  413. * output data register and keep that from MAGN sensor as the origin.
  414. * Value should be extended to 32 bit.
  415. */
  416. switch (chan_type) {
  417. case IIO_ACCEL:
  418. tmp = tmp >> 2;
  419. break;
  420. case IIO_MAGN:
  421. /* Nothing to do */
  422. break;
  423. default:
  424. return -EINVAL;
  425. }
  426. /* Convert to native endianness */
  427. *val = sign_extend32(tmp, 15);
  428. return 0;
  429. }
  430. static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
  431. int odr, int uodr)
  432. {
  433. int i, ret, val;
  434. bool active_mode;
  435. static const int odr_num = ARRAY_SIZE(fxos8700_odr);
  436. ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
  437. if (ret)
  438. return ret;
  439. active_mode = val & FXOS8700_ACTIVE;
  440. if (active_mode) {
  441. /*
  442. * The device must be in standby mode to change any of the
  443. * other fields within CTRL_REG1
  444. */
  445. ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
  446. val & ~FXOS8700_ACTIVE);
  447. if (ret)
  448. return ret;
  449. }
  450. for (i = 0; i < odr_num; i++)
  451. if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
  452. break;
  453. if (i >= odr_num)
  454. return -EINVAL;
  455. val &= ~FXOS8700_CTRL_ODR_MSK;
  456. val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;
  457. return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);
  458. }
  459. static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
  460. int *odr, int *uodr)
  461. {
  462. int i, val, ret;
  463. static const int odr_num = ARRAY_SIZE(fxos8700_odr);
  464. ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
  465. if (ret)
  466. return ret;
  467. val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);
  468. for (i = 0; i < odr_num; i++)
  469. if (val == fxos8700_odr[i].bits)
  470. break;
  471. if (i >= odr_num)
  472. return -EINVAL;
  473. *odr = fxos8700_odr[i].odr;
  474. *uodr = fxos8700_odr[i].uodr;
  475. return 0;
  476. }
  477. static int fxos8700_read_raw(struct iio_dev *indio_dev,
  478. struct iio_chan_spec const *chan,
  479. int *val, int *val2, long mask)
  480. {
  481. int ret;
  482. struct fxos8700_data *data = iio_priv(indio_dev);
  483. switch (mask) {
  484. case IIO_CHAN_INFO_RAW:
  485. ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
  486. if (ret)
  487. return ret;
  488. return IIO_VAL_INT;
  489. case IIO_CHAN_INFO_SCALE:
  490. *val = 0;
  491. ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
  492. val2);
  493. return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
  494. case IIO_CHAN_INFO_SAMP_FREQ:
  495. ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
  496. val, val2);
  497. return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
  498. default:
  499. return -EINVAL;
  500. }
  501. }
  502. static int fxos8700_write_raw(struct iio_dev *indio_dev,
  503. struct iio_chan_spec const *chan,
  504. int val, int val2, long mask)
  505. {
  506. struct fxos8700_data *data = iio_priv(indio_dev);
  507. switch (mask) {
  508. case IIO_CHAN_INFO_SCALE:
  509. return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
  510. val2);
  511. case IIO_CHAN_INFO_SAMP_FREQ:
  512. return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
  513. val, val2);
  514. default:
  515. return -EINVAL;
  516. }
  517. }
  518. static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
  519. "1.5625 6.25 12.5 50 100 200 400 800");
  520. static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
  521. "1.5625 6.25 12.5 50 100 200 400 800");
  522. static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
  523. static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
  524. static struct attribute *fxos8700_attrs[] = {
  525. &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
  526. &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
  527. &iio_const_attr_in_accel_scale_available.dev_attr.attr,
  528. &iio_const_attr_in_magn_scale_available.dev_attr.attr,
  529. NULL,
  530. };
  531. static const struct attribute_group fxos8700_attrs_group = {
  532. .attrs = fxos8700_attrs,
  533. };
  534. static const struct iio_info fxos8700_info = {
  535. .read_raw = fxos8700_read_raw,
  536. .write_raw = fxos8700_write_raw,
  537. .attrs = &fxos8700_attrs_group,
  538. };
  539. static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
  540. {
  541. int ret;
  542. unsigned int val;
  543. struct device *dev = regmap_get_device(data->regmap);
  544. ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
  545. if (ret) {
  546. dev_err(dev, "Error reading chip id\n");
  547. return ret;
  548. }
  549. if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
  550. dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
  551. val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
  552. return -ENODEV;
  553. }
  554. ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
  555. if (ret)
  556. return ret;
  557. ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
  558. if (ret)
  559. return ret;
  560. /*
  561. * The device must be in standby mode to change any of the other fields
  562. * within CTRL_REG1
  563. */
  564. ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
  565. if (ret)
  566. return ret;
  567. /* Set max oversample ratio (OSR) and both devices active */
  568. ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
  569. FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
  570. if (ret)
  571. return ret;
  572. /* Disable and rst min/max measurements & threshold */
  573. ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
  574. FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
  575. FXOS8700_MAXMIN_DIS);
  576. if (ret)
  577. return ret;
  578. /*
  579. * Set max full-scale range (+/-8G) for ACCEL sensor in chip
  580. * initialization then activate the device.
  581. */
  582. ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
  583. if (ret)
  584. return ret;
  585. /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
  586. return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,
  587. FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,
  588. FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |
  589. FXOS8700_ACTIVE);
  590. }
  591. static void fxos8700_chip_uninit(void *data)
  592. {
  593. struct fxos8700_data *fxos8700_data = data;
  594. fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
  595. fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
  596. }
  597. int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
  598. const char *name, bool use_spi)
  599. {
  600. struct iio_dev *indio_dev;
  601. struct fxos8700_data *data;
  602. int ret;
  603. indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
  604. if (!indio_dev)
  605. return -ENOMEM;
  606. data = iio_priv(indio_dev);
  607. dev_set_drvdata(dev, indio_dev);
  608. data->regmap = regmap;
  609. ret = fxos8700_chip_init(data, use_spi);
  610. if (ret)
  611. return ret;
  612. ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
  613. if (ret)
  614. return ret;
  615. indio_dev->channels = fxos8700_channels;
  616. indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
  617. indio_dev->name = name ? name : "fxos8700";
  618. indio_dev->modes = INDIO_DIRECT_MODE;
  619. indio_dev->info = &fxos8700_info;
  620. return devm_iio_device_register(dev, indio_dev);
  621. }
  622. EXPORT_SYMBOL_GPL(fxos8700_core_probe);
  623. MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
  624. MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
  625. MODULE_LICENSE("GPL v2");