si7210.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Silicon Labs Si7210 Hall Effect sensor driver
  4. *
  5. * Copyright (c) 2024 Antoni Pokusinski <apokusinski01@gmail.com>
  6. *
  7. * Datasheet:
  8. * https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf
  9. */
  10. #include <linux/array_size.h>
  11. #include <linux/bitfield.h>
  12. #include <linux/bits.h>
  13. #include <linux/cleanup.h>
  14. #include <linux/err.h>
  15. #include <linux/i2c.h>
  16. #include <linux/iio/iio.h>
  17. #include <linux/math64.h>
  18. #include <linux/mod_devicetable.h>
  19. #include <linux/mutex.h>
  20. #include <linux/regmap.h>
  21. #include <linux/regulator/consumer.h>
  22. #include <linux/types.h>
  23. #include <linux/units.h>
  24. #include <asm/byteorder.h>
  25. /* Registers offsets and masks */
  26. #define SI7210_REG_DSPSIGM 0xC1
  27. #define SI7210_REG_DSPSIGL 0xC2
  28. #define SI7210_MASK_DSPSIGSEL GENMASK(2, 0)
  29. #define SI7210_REG_DSPSIGSEL 0xC3
  30. #define SI7210_MASK_STOP BIT(1)
  31. #define SI7210_MASK_ONEBURST BIT(2)
  32. #define SI7210_REG_POWER_CTRL 0xC4
  33. #define SI7210_MASK_ARAUTOINC BIT(0)
  34. #define SI7210_REG_ARAUTOINC 0xC5
  35. #define SI7210_REG_A0 0xCA
  36. #define SI7210_REG_A1 0xCB
  37. #define SI7210_REG_A2 0xCC
  38. #define SI7210_REG_A3 0xCE
  39. #define SI7210_REG_A4 0xCF
  40. #define SI7210_REG_A5 0xD0
  41. #define SI7210_REG_OTP_ADDR 0xE1
  42. #define SI7210_REG_OTP_DATA 0xE2
  43. #define SI7210_MASK_OTP_READ_EN BIT(1)
  44. #define SI7210_REG_OTP_CTRL 0xE3
  45. /* OTP data registers offsets */
  46. #define SI7210_OTPREG_TMP_OFF 0x1D
  47. #define SI7210_OTPREG_TMP_GAIN 0x1E
  48. #define SI7210_OTPREG_A0_20 0x21
  49. #define SI7210_OTPREG_A1_20 0x22
  50. #define SI7210_OTPREG_A2_20 0x23
  51. #define SI7210_OTPREG_A3_20 0x24
  52. #define SI7210_OTPREG_A4_20 0x25
  53. #define SI7210_OTPREG_A5_20 0x26
  54. #define SI7210_OTPREG_A0_200 0x27
  55. #define SI7210_OTPREG_A1_200 0x28
  56. #define SI7210_OTPREG_A2_200 0x29
  57. #define SI7210_OTPREG_A3_200 0x2A
  58. #define SI7210_OTPREG_A4_200 0x2B
  59. #define SI7210_OTPREG_A5_200 0x2C
  60. #define A_REGS_COUNT 6
  61. static const unsigned int a20_otp_regs[A_REGS_COUNT] = {
  62. SI7210_OTPREG_A0_20, SI7210_OTPREG_A1_20, SI7210_OTPREG_A2_20,
  63. SI7210_OTPREG_A3_20, SI7210_OTPREG_A4_20, SI7210_OTPREG_A5_20,
  64. };
  65. static const unsigned int a200_otp_regs[A_REGS_COUNT] = {
  66. SI7210_OTPREG_A0_200, SI7210_OTPREG_A1_200, SI7210_OTPREG_A2_200,
  67. SI7210_OTPREG_A3_200, SI7210_OTPREG_A4_200, SI7210_OTPREG_A5_200,
  68. };
  69. static const struct regmap_range si7210_read_reg_ranges[] = {
  70. regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_ARAUTOINC),
  71. regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2),
  72. regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5),
  73. regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL),
  74. };
  75. static const struct regmap_access_table si7210_readable_regs = {
  76. .yes_ranges = si7210_read_reg_ranges,
  77. .n_yes_ranges = ARRAY_SIZE(si7210_read_reg_ranges),
  78. };
  79. static const struct regmap_range si7210_write_reg_ranges[] = {
  80. regmap_reg_range(SI7210_REG_DSPSIGSEL, SI7210_REG_ARAUTOINC),
  81. regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2),
  82. regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5),
  83. regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL),
  84. };
  85. static const struct regmap_access_table si7210_writeable_regs = {
  86. .yes_ranges = si7210_write_reg_ranges,
  87. .n_yes_ranges = ARRAY_SIZE(si7210_write_reg_ranges),
  88. };
  89. static const struct regmap_range si7210_volatile_reg_ranges[] = {
  90. regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_DSPSIGL),
  91. regmap_reg_range(SI7210_REG_POWER_CTRL, SI7210_REG_POWER_CTRL),
  92. };
  93. static const struct regmap_access_table si7210_volatile_regs = {
  94. .yes_ranges = si7210_volatile_reg_ranges,
  95. .n_yes_ranges = ARRAY_SIZE(si7210_volatile_reg_ranges),
  96. };
  97. static const struct regmap_config si7210_regmap_conf = {
  98. .reg_bits = 8,
  99. .val_bits = 8,
  100. .max_register = SI7210_REG_OTP_CTRL,
  101. .rd_table = &si7210_readable_regs,
  102. .wr_table = &si7210_writeable_regs,
  103. .volatile_table = &si7210_volatile_regs,
  104. };
  105. struct si7210_data {
  106. struct regmap *regmap;
  107. struct i2c_client *client;
  108. struct regulator *vdd;
  109. struct mutex fetch_lock; /* lock for a single measurement fetch */
  110. s8 temp_offset;
  111. s8 temp_gain;
  112. s8 scale_20_a[A_REGS_COUNT];
  113. s8 scale_200_a[A_REGS_COUNT];
  114. u8 curr_scale;
  115. };
  116. static const struct iio_chan_spec si7210_channels[] = {
  117. {
  118. .type = IIO_MAGN,
  119. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  120. BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
  121. }, {
  122. .type = IIO_TEMP,
  123. .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
  124. },
  125. };
  126. static int si7210_fetch_measurement(struct si7210_data *data,
  127. struct iio_chan_spec const *chan,
  128. u16 *buf)
  129. {
  130. u8 dspsigsel = chan->type == IIO_MAGN ? 0 : 1;
  131. int ret;
  132. __be16 result;
  133. guard(mutex)(&data->fetch_lock);
  134. ret = regmap_update_bits(data->regmap, SI7210_REG_DSPSIGSEL,
  135. SI7210_MASK_DSPSIGSEL, dspsigsel);
  136. if (ret)
  137. return ret;
  138. ret = regmap_update_bits(data->regmap, SI7210_REG_POWER_CTRL,
  139. SI7210_MASK_ONEBURST | SI7210_MASK_STOP,
  140. SI7210_MASK_ONEBURST & ~SI7210_MASK_STOP);
  141. if (ret)
  142. return ret;
  143. /*
  144. * Read the contents of the
  145. * registers containing the result: DSPSIGM, DSPSIGL
  146. */
  147. ret = regmap_bulk_read(data->regmap, SI7210_REG_DSPSIGM,
  148. &result, sizeof(result));
  149. if (ret)
  150. return ret;
  151. *buf = be16_to_cpu(result);
  152. return 0;
  153. }
  154. static int si7210_read_raw(struct iio_dev *indio_dev,
  155. struct iio_chan_spec const *chan,
  156. int *val, int *val2, long mask)
  157. {
  158. struct si7210_data *data = iio_priv(indio_dev);
  159. long long temp;
  160. u16 dspsig;
  161. int ret;
  162. switch (mask) {
  163. case IIO_CHAN_INFO_RAW:
  164. ret = si7210_fetch_measurement(data, chan, &dspsig);
  165. if (ret)
  166. return ret;
  167. *val = dspsig & GENMASK(14, 0);
  168. return IIO_VAL_INT;
  169. case IIO_CHAN_INFO_SCALE:
  170. *val = 0;
  171. if (data->curr_scale == 20)
  172. *val2 = 12500;
  173. else /* data->curr_scale == 200 */
  174. *val2 = 125000;
  175. return IIO_VAL_INT_PLUS_MICRO;
  176. case IIO_CHAN_INFO_OFFSET:
  177. *val = -16384;
  178. return IIO_VAL_INT;
  179. case IIO_CHAN_INFO_PROCESSED:
  180. ret = si7210_fetch_measurement(data, chan, &dspsig);
  181. if (ret)
  182. return ret;
  183. /* temp = 32 * Dspsigm[6:0] + (Dspsigl[7:0] >> 3) */
  184. temp = FIELD_GET(GENMASK(14, 3), dspsig);
  185. temp = div_s64(-383 * temp * temp, 100) + 160940 * temp - 279800000;
  186. temp *= (1 + (data->temp_gain / 2048));
  187. temp += (int)(MICRO / 16) * data->temp_offset;
  188. ret = regulator_get_voltage(data->vdd);
  189. if (ret < 0)
  190. return ret;
  191. /* temp -= 0.222 * VDD */
  192. temp -= 222 * div_s64(ret, MILLI);
  193. *val = div_s64(temp, MILLI);
  194. return IIO_VAL_INT;
  195. default:
  196. return -EINVAL;
  197. }
  198. }
  199. static int si7210_set_scale(struct si7210_data *data, unsigned int scale)
  200. {
  201. s8 *a_otp_values;
  202. int ret;
  203. if (scale == 20)
  204. a_otp_values = data->scale_20_a;
  205. else if (scale == 200)
  206. a_otp_values = data->scale_200_a;
  207. else
  208. return -EINVAL;
  209. guard(mutex)(&data->fetch_lock);
  210. /* Write the registers 0xCA - 0xCC */
  211. ret = regmap_bulk_write(data->regmap, SI7210_REG_A0, a_otp_values, 3);
  212. if (ret)
  213. return ret;
  214. /* Write the registers 0xCE - 0xD0 */
  215. ret = regmap_bulk_write(data->regmap, SI7210_REG_A3, &a_otp_values[3], 3);
  216. if (ret)
  217. return ret;
  218. data->curr_scale = scale;
  219. return 0;
  220. }
  221. static int si7210_write_raw(struct iio_dev *indio_dev,
  222. struct iio_chan_spec const *chan,
  223. int val, int val2, long mask)
  224. {
  225. struct si7210_data *data = iio_priv(indio_dev);
  226. unsigned int scale;
  227. switch (mask) {
  228. case IIO_CHAN_INFO_SCALE:
  229. if (val == 0 && val2 == 12500)
  230. scale = 20;
  231. else if (val == 0 && val2 == 125000)
  232. scale = 200;
  233. else
  234. return -EINVAL;
  235. return si7210_set_scale(data, scale);
  236. default:
  237. return -EINVAL;
  238. }
  239. }
  240. static int si7210_read_otpreg_val(struct si7210_data *data, unsigned int otpreg, u8 *val)
  241. {
  242. int ret;
  243. unsigned int otpdata;
  244. ret = regmap_write(data->regmap, SI7210_REG_OTP_ADDR, otpreg);
  245. if (ret)
  246. return ret;
  247. ret = regmap_update_bits(data->regmap, SI7210_REG_OTP_CTRL,
  248. SI7210_MASK_OTP_READ_EN, SI7210_MASK_OTP_READ_EN);
  249. if (ret)
  250. return ret;
  251. ret = regmap_read(data->regmap, SI7210_REG_OTP_DATA, &otpdata);
  252. if (ret)
  253. return ret;
  254. *val = otpdata;
  255. return 0;
  256. }
  257. /*
  258. * According to the datasheet, the primary method to wake up a
  259. * device is to send an empty write. However this is not feasible
  260. * using the current API so we use the other method i.e. read a single
  261. * byte. The device should respond with 0xFF.
  262. */
  263. static int si7210_device_wake(struct si7210_data *data)
  264. {
  265. int ret;
  266. ret = i2c_smbus_read_byte(data->client);
  267. if (ret < 0)
  268. return ret;
  269. if (ret != 0xFF)
  270. return -EIO;
  271. return 0;
  272. }
  273. static int si7210_device_init(struct si7210_data *data)
  274. {
  275. int ret;
  276. unsigned int i;
  277. ret = si7210_device_wake(data);
  278. if (ret)
  279. return ret;
  280. fsleep(1000);
  281. ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_GAIN, &data->temp_gain);
  282. if (ret)
  283. return ret;
  284. ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_OFF, &data->temp_offset);
  285. if (ret)
  286. return ret;
  287. for (i = 0; i < A_REGS_COUNT; i++) {
  288. ret = si7210_read_otpreg_val(data, a20_otp_regs[i], &data->scale_20_a[i]);
  289. if (ret)
  290. return ret;
  291. }
  292. for (i = 0; i < A_REGS_COUNT; i++) {
  293. ret = si7210_read_otpreg_val(data, a200_otp_regs[i], &data->scale_200_a[i]);
  294. if (ret)
  295. return ret;
  296. }
  297. ret = regmap_update_bits(data->regmap, SI7210_REG_ARAUTOINC,
  298. SI7210_MASK_ARAUTOINC, SI7210_MASK_ARAUTOINC);
  299. if (ret)
  300. return ret;
  301. return si7210_set_scale(data, 20);
  302. }
  303. static const struct iio_info si7210_info = {
  304. .read_raw = si7210_read_raw,
  305. .write_raw = si7210_write_raw,
  306. };
  307. static int si7210_probe(struct i2c_client *client)
  308. {
  309. struct si7210_data *data;
  310. struct iio_dev *indio_dev;
  311. int ret;
  312. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  313. if (!indio_dev)
  314. return -ENOMEM;
  315. data = iio_priv(indio_dev);
  316. data->client = client;
  317. ret = devm_mutex_init(&client->dev, &data->fetch_lock);
  318. if (ret)
  319. return ret;
  320. data->regmap = devm_regmap_init_i2c(client, &si7210_regmap_conf);
  321. if (IS_ERR(data->regmap))
  322. return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
  323. "failed to register regmap\n");
  324. data->vdd = devm_regulator_get(&client->dev, "vdd");
  325. if (IS_ERR(data->vdd))
  326. return dev_err_probe(&client->dev, PTR_ERR(data->vdd),
  327. "failed to get VDD regulator\n");
  328. ret = regulator_enable(data->vdd);
  329. if (ret)
  330. return ret;
  331. indio_dev->name = dev_name(&client->dev);
  332. indio_dev->modes = INDIO_DIRECT_MODE;
  333. indio_dev->info = &si7210_info;
  334. indio_dev->channels = si7210_channels;
  335. indio_dev->num_channels = ARRAY_SIZE(si7210_channels);
  336. ret = si7210_device_init(data);
  337. if (ret)
  338. return dev_err_probe(&client->dev, ret,
  339. "device initialization failed\n");
  340. return devm_iio_device_register(&client->dev, indio_dev);
  341. }
  342. static const struct i2c_device_id si7210_id[] = {
  343. { "si7210" },
  344. { }
  345. };
  346. MODULE_DEVICE_TABLE(i2c, si7210_id);
  347. static const struct of_device_id si7210_dt_ids[] = {
  348. { .compatible = "silabs,si7210" },
  349. { }
  350. };
  351. MODULE_DEVICE_TABLE(of, si7210_dt_ids);
  352. static struct i2c_driver si7210_driver = {
  353. .driver = {
  354. .name = "si7210",
  355. .of_match_table = si7210_dt_ids,
  356. },
  357. .probe = si7210_probe,
  358. .id_table = si7210_id,
  359. };
  360. module_i2c_driver(si7210_driver);
  361. MODULE_AUTHOR("Antoni Pokusinski <apokusinski01@gmail.com>");
  362. MODULE_DESCRIPTION("Silicon Labs Si7210 Hall Effect sensor I2C driver");
  363. MODULE_LICENSE("GPL");