noa1305.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Support for ON Semiconductor NOA1305 ambient light sensor
  4. *
  5. * Copyright (C) 2016 Emcraft Systems
  6. * Copyright (C) 2019 Collabora Ltd.
  7. */
  8. #include <linux/delay.h>
  9. #include <linux/err.h>
  10. #include <linux/i2c.h>
  11. #include <linux/iio/iio.h>
  12. #include <linux/iio/sysfs.h>
  13. #include <linux/module.h>
  14. #include <linux/regmap.h>
  15. #include <linux/regulator/consumer.h>
  16. #define NOA1305_REG_POWER_CONTROL 0x0
  17. #define NOA1305_POWER_CONTROL_DOWN 0x00
  18. #define NOA1305_POWER_CONTROL_ON 0x08
  19. #define NOA1305_REG_RESET 0x1
  20. #define NOA1305_RESET_RESET 0x10
  21. #define NOA1305_REG_INTEGRATION_TIME 0x2
  22. #define NOA1305_INTEGR_TIME_800MS 0x00
  23. #define NOA1305_INTEGR_TIME_400MS 0x01
  24. #define NOA1305_INTEGR_TIME_200MS 0x02
  25. #define NOA1305_INTEGR_TIME_100MS 0x03
  26. #define NOA1305_INTEGR_TIME_50MS 0x04
  27. #define NOA1305_INTEGR_TIME_25MS 0x05
  28. #define NOA1305_INTEGR_TIME_12_5MS 0x06
  29. #define NOA1305_INTEGR_TIME_6_25MS 0x07
  30. #define NOA1305_INTEGR_TIME_MASK 0x07
  31. #define NOA1305_REG_INT_SELECT 0x3
  32. #define NOA1305_INT_SEL_ACTIVE_HIGH 0x01
  33. #define NOA1305_INT_SEL_ACTIVE_LOW 0x02
  34. #define NOA1305_INT_SEL_INACTIVE 0x03
  35. #define NOA1305_REG_INT_THRESH_LSB 0x4
  36. #define NOA1305_REG_INT_THRESH_MSB 0x5
  37. #define NOA1305_REG_ALS_DATA_LSB 0x6
  38. #define NOA1305_REG_ALS_DATA_MSB 0x7
  39. #define NOA1305_REG_DEVICE_ID_LSB 0x8
  40. #define NOA1305_REG_DEVICE_ID_MSB 0x9
  41. #define NOA1305_DEVICE_ID 0x0519
  42. #define NOA1305_DRIVER_NAME "noa1305"
  43. static int noa1305_scale_available[] = {
  44. 100, 8 * 77, /* 800 ms */
  45. 100, 4 * 77, /* 400 ms */
  46. 100, 2 * 77, /* 200 ms */
  47. 100, 1 * 77, /* 100 ms */
  48. 1000, 5 * 77, /* 50 ms */
  49. 10000, 25 * 77, /* 25 ms */
  50. 100000, 125 * 77, /* 12.5 ms */
  51. 1000000, 625 * 77, /* 6.25 ms */
  52. };
  53. static int noa1305_int_time_available[] = {
  54. 0, 800000, /* 800 ms */
  55. 0, 400000, /* 400 ms */
  56. 0, 200000, /* 200 ms */
  57. 0, 100000, /* 100 ms */
  58. 0, 50000, /* 50 ms */
  59. 0, 25000, /* 25 ms */
  60. 0, 12500, /* 12.5 ms */
  61. 0, 6250, /* 6.25 ms */
  62. };
  63. struct noa1305_priv {
  64. struct i2c_client *client;
  65. struct regmap *regmap;
  66. };
  67. static int noa1305_measure(struct noa1305_priv *priv, int *val)
  68. {
  69. __le16 data;
  70. int ret;
  71. ret = regmap_bulk_read(priv->regmap, NOA1305_REG_ALS_DATA_LSB, &data,
  72. 2);
  73. if (ret < 0)
  74. return ret;
  75. *val = le16_to_cpu(data);
  76. return IIO_VAL_INT;
  77. }
  78. static int noa1305_scale(struct noa1305_priv *priv, int *val, int *val2)
  79. {
  80. int data;
  81. int ret;
  82. ret = regmap_read(priv->regmap, NOA1305_REG_INTEGRATION_TIME, &data);
  83. if (ret < 0)
  84. return ret;
  85. /*
  86. * Lux = count / (<Integration Constant> * <Integration Time>)
  87. *
  88. * Integration Constant = 7.7
  89. * Integration Time in Seconds
  90. */
  91. data &= NOA1305_INTEGR_TIME_MASK;
  92. *val = noa1305_scale_available[2 * data + 0];
  93. *val2 = noa1305_scale_available[2 * data + 1];
  94. return IIO_VAL_FRACTIONAL;
  95. }
  96. static int noa1305_int_time(struct noa1305_priv *priv, int *val, int *val2)
  97. {
  98. int data;
  99. int ret;
  100. ret = regmap_read(priv->regmap, NOA1305_REG_INTEGRATION_TIME, &data);
  101. if (ret < 0)
  102. return ret;
  103. data &= NOA1305_INTEGR_TIME_MASK;
  104. *val = noa1305_int_time_available[2 * data + 0];
  105. *val2 = noa1305_int_time_available[2 * data + 1];
  106. return IIO_VAL_INT_PLUS_MICRO;
  107. }
  108. static const struct iio_chan_spec noa1305_channels[] = {
  109. {
  110. .type = IIO_LIGHT,
  111. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  112. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
  113. .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE),
  114. .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
  115. .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
  116. }
  117. };
  118. static int noa1305_read_avail(struct iio_dev *indio_dev,
  119. struct iio_chan_spec const *chan,
  120. const int **vals, int *type,
  121. int *length, long mask)
  122. {
  123. if (chan->type != IIO_LIGHT)
  124. return -EINVAL;
  125. switch (mask) {
  126. case IIO_CHAN_INFO_SCALE:
  127. *vals = noa1305_scale_available;
  128. *length = ARRAY_SIZE(noa1305_scale_available);
  129. *type = IIO_VAL_FRACTIONAL;
  130. return IIO_AVAIL_LIST;
  131. case IIO_CHAN_INFO_INT_TIME:
  132. *vals = noa1305_int_time_available;
  133. *length = ARRAY_SIZE(noa1305_int_time_available);
  134. *type = IIO_VAL_INT_PLUS_MICRO;
  135. return IIO_AVAIL_LIST;
  136. default:
  137. return -EINVAL;
  138. }
  139. }
  140. static int noa1305_read_raw(struct iio_dev *indio_dev,
  141. struct iio_chan_spec const *chan,
  142. int *val, int *val2, long mask)
  143. {
  144. struct noa1305_priv *priv = iio_priv(indio_dev);
  145. if (chan->type != IIO_LIGHT)
  146. return -EINVAL;
  147. switch (mask) {
  148. case IIO_CHAN_INFO_RAW:
  149. return noa1305_measure(priv, val);
  150. case IIO_CHAN_INFO_SCALE:
  151. return noa1305_scale(priv, val, val2);
  152. case IIO_CHAN_INFO_INT_TIME:
  153. return noa1305_int_time(priv, val, val2);
  154. default:
  155. return -EINVAL;
  156. }
  157. }
  158. static int noa1305_write_raw(struct iio_dev *indio_dev,
  159. struct iio_chan_spec const *chan,
  160. int val, int val2, long mask)
  161. {
  162. struct noa1305_priv *priv = iio_priv(indio_dev);
  163. int i;
  164. if (chan->type != IIO_LIGHT)
  165. return -EINVAL;
  166. if (mask != IIO_CHAN_INFO_INT_TIME)
  167. return -EINVAL;
  168. if (val) /* >= 1s integration time not supported */
  169. return -EINVAL;
  170. /* Look up integration time register settings and write it if found. */
  171. for (i = 0; i < ARRAY_SIZE(noa1305_int_time_available) / 2; i++)
  172. if (noa1305_int_time_available[2 * i + 1] == val2)
  173. return regmap_write(priv->regmap, NOA1305_REG_INTEGRATION_TIME, i);
  174. return -EINVAL;
  175. }
  176. static const struct iio_info noa1305_info = {
  177. .read_avail = noa1305_read_avail,
  178. .read_raw = noa1305_read_raw,
  179. .write_raw = noa1305_write_raw,
  180. };
  181. static bool noa1305_writable_reg(struct device *dev, unsigned int reg)
  182. {
  183. switch (reg) {
  184. case NOA1305_REG_POWER_CONTROL:
  185. case NOA1305_REG_RESET:
  186. case NOA1305_REG_INTEGRATION_TIME:
  187. case NOA1305_REG_INT_SELECT:
  188. case NOA1305_REG_INT_THRESH_LSB:
  189. case NOA1305_REG_INT_THRESH_MSB:
  190. return true;
  191. default:
  192. return false;
  193. }
  194. }
  195. static const struct regmap_config noa1305_regmap_config = {
  196. .name = NOA1305_DRIVER_NAME,
  197. .reg_bits = 8,
  198. .val_bits = 8,
  199. .max_register = NOA1305_REG_DEVICE_ID_MSB,
  200. .writeable_reg = noa1305_writable_reg,
  201. };
  202. static int noa1305_probe(struct i2c_client *client)
  203. {
  204. struct noa1305_priv *priv;
  205. struct iio_dev *indio_dev;
  206. struct regmap *regmap;
  207. __le16 data;
  208. unsigned int dev_id;
  209. int ret;
  210. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*priv));
  211. if (!indio_dev)
  212. return -ENOMEM;
  213. regmap = devm_regmap_init_i2c(client, &noa1305_regmap_config);
  214. if (IS_ERR(regmap)) {
  215. dev_err(&client->dev, "Regmap initialization failed.\n");
  216. return PTR_ERR(regmap);
  217. }
  218. priv = iio_priv(indio_dev);
  219. ret = devm_regulator_get_enable(&client->dev, "vin");
  220. if (ret)
  221. return dev_err_probe(&client->dev, ret,
  222. "get regulator vin failed\n");
  223. i2c_set_clientdata(client, indio_dev);
  224. priv->client = client;
  225. priv->regmap = regmap;
  226. ret = regmap_bulk_read(regmap, NOA1305_REG_DEVICE_ID_LSB, &data, 2);
  227. if (ret < 0) {
  228. dev_err(&client->dev, "ID reading failed: %d\n", ret);
  229. return ret;
  230. }
  231. dev_id = le16_to_cpu(data);
  232. if (dev_id != NOA1305_DEVICE_ID) {
  233. dev_err(&client->dev, "Unknown device ID: 0x%x\n", dev_id);
  234. return -ENODEV;
  235. }
  236. ret = regmap_write(regmap, NOA1305_REG_POWER_CONTROL,
  237. NOA1305_POWER_CONTROL_ON);
  238. if (ret < 0) {
  239. dev_err(&client->dev, "Enabling power control failed\n");
  240. return ret;
  241. }
  242. ret = regmap_write(regmap, NOA1305_REG_RESET, NOA1305_RESET_RESET);
  243. if (ret < 0) {
  244. dev_err(&client->dev, "Device reset failed\n");
  245. return ret;
  246. }
  247. ret = regmap_write(regmap, NOA1305_REG_INTEGRATION_TIME,
  248. NOA1305_INTEGR_TIME_800MS);
  249. if (ret < 0) {
  250. dev_err(&client->dev, "Setting integration time failed\n");
  251. return ret;
  252. }
  253. indio_dev->info = &noa1305_info;
  254. indio_dev->channels = noa1305_channels;
  255. indio_dev->num_channels = ARRAY_SIZE(noa1305_channels);
  256. indio_dev->name = NOA1305_DRIVER_NAME;
  257. indio_dev->modes = INDIO_DIRECT_MODE;
  258. ret = devm_iio_device_register(&client->dev, indio_dev);
  259. if (ret)
  260. dev_err(&client->dev, "registering device failed\n");
  261. return ret;
  262. }
  263. static const struct of_device_id noa1305_of_match[] = {
  264. { .compatible = "onnn,noa1305" },
  265. { }
  266. };
  267. MODULE_DEVICE_TABLE(of, noa1305_of_match);
  268. static const struct i2c_device_id noa1305_ids[] = {
  269. { "noa1305" },
  270. { }
  271. };
  272. MODULE_DEVICE_TABLE(i2c, noa1305_ids);
  273. static struct i2c_driver noa1305_driver = {
  274. .driver = {
  275. .name = NOA1305_DRIVER_NAME,
  276. .of_match_table = noa1305_of_match,
  277. },
  278. .probe = noa1305_probe,
  279. .id_table = noa1305_ids,
  280. };
  281. module_i2c_driver(noa1305_driver);
  282. MODULE_AUTHOR("Sergei Miroshnichenko <sergeimir@emcraft.com>");
  283. MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.com");
  284. MODULE_DESCRIPTION("ON Semiconductor NOA1305 ambient light sensor");
  285. MODULE_LICENSE("GPL");