rpr0521.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * RPR-0521 ROHM Ambient Light and Proximity Sensor
  3. *
  4. * Copyright (c) 2015, Intel Corporation.
  5. *
  6. * This file is subject to the terms and conditions of version 2 of
  7. * the GNU General Public License. See the file COPYING in the main
  8. * directory of this archive for more details.
  9. *
  10. * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
  11. *
  12. * TODO: illuminance channel, PM support, buffer
  13. */
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/i2c.h>
  17. #include <linux/regmap.h>
  18. #include <linux/delay.h>
  19. #include <linux/acpi.h>
  20. #include <linux/iio/iio.h>
  21. #include <linux/iio/sysfs.h>
  22. #include <linux/pm_runtime.h>
  23. #define RPR0521_REG_SYSTEM_CTRL 0x40
  24. #define RPR0521_REG_MODE_CTRL 0x41
  25. #define RPR0521_REG_ALS_CTRL 0x42
  26. #define RPR0521_REG_PXS_CTRL 0x43
  27. #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */
  28. #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */
  29. #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */
  30. #define RPR0521_REG_ID 0x92
  31. #define RPR0521_MODE_ALS_MASK BIT(7)
  32. #define RPR0521_MODE_PXS_MASK BIT(6)
  33. #define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0)
  34. #define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4)
  35. #define RPR0521_ALS_DATA0_GAIN_SHIFT 4
  36. #define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2)
  37. #define RPR0521_ALS_DATA1_GAIN_SHIFT 2
  38. #define RPR0521_PXS_GAIN_MASK GENMASK(5, 4)
  39. #define RPR0521_PXS_GAIN_SHIFT 4
  40. #define RPR0521_MODE_ALS_ENABLE BIT(7)
  41. #define RPR0521_MODE_ALS_DISABLE 0x00
  42. #define RPR0521_MODE_PXS_ENABLE BIT(6)
  43. #define RPR0521_MODE_PXS_DISABLE 0x00
  44. #define RPR0521_MANUFACT_ID 0xE0
  45. #define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */
  46. #define RPR0521_DRV_NAME "RPR0521"
  47. #define RPR0521_REGMAP_NAME "rpr0521_regmap"
  48. #define RPR0521_SLEEP_DELAY_MS 2000
  49. #define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1"
  50. #define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1"
  51. struct rpr0521_gain {
  52. int scale;
  53. int uscale;
  54. };
  55. static const struct rpr0521_gain rpr0521_als_gain[4] = {
  56. {1, 0}, /* x1 */
  57. {0, 500000}, /* x2 */
  58. {0, 15625}, /* x64 */
  59. {0, 7812}, /* x128 */
  60. };
  61. static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
  62. {1, 0}, /* x1 */
  63. {0, 500000}, /* x2 */
  64. {0, 125000}, /* x4 */
  65. };
  66. enum rpr0521_channel {
  67. RPR0521_CHAN_ALS_DATA0,
  68. RPR0521_CHAN_ALS_DATA1,
  69. RPR0521_CHAN_PXS,
  70. };
  71. struct rpr0521_reg_desc {
  72. u8 address;
  73. u8 device_mask;
  74. };
  75. static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
  76. [RPR0521_CHAN_ALS_DATA0] = {
  77. .address = RPR0521_REG_ALS_DATA0,
  78. .device_mask = RPR0521_MODE_ALS_MASK,
  79. },
  80. [RPR0521_CHAN_ALS_DATA1] = {
  81. .address = RPR0521_REG_ALS_DATA1,
  82. .device_mask = RPR0521_MODE_ALS_MASK,
  83. },
  84. [RPR0521_CHAN_PXS] = {
  85. .address = RPR0521_REG_PXS_DATA,
  86. .device_mask = RPR0521_MODE_PXS_MASK,
  87. },
  88. };
  89. static const struct rpr0521_gain_info {
  90. u8 reg;
  91. u8 mask;
  92. u8 shift;
  93. const struct rpr0521_gain *gain;
  94. int size;
  95. } rpr0521_gain[] = {
  96. [RPR0521_CHAN_ALS_DATA0] = {
  97. .reg = RPR0521_REG_ALS_CTRL,
  98. .mask = RPR0521_ALS_DATA0_GAIN_MASK,
  99. .shift = RPR0521_ALS_DATA0_GAIN_SHIFT,
  100. .gain = rpr0521_als_gain,
  101. .size = ARRAY_SIZE(rpr0521_als_gain),
  102. },
  103. [RPR0521_CHAN_ALS_DATA1] = {
  104. .reg = RPR0521_REG_ALS_CTRL,
  105. .mask = RPR0521_ALS_DATA1_GAIN_MASK,
  106. .shift = RPR0521_ALS_DATA1_GAIN_SHIFT,
  107. .gain = rpr0521_als_gain,
  108. .size = ARRAY_SIZE(rpr0521_als_gain),
  109. },
  110. [RPR0521_CHAN_PXS] = {
  111. .reg = RPR0521_REG_PXS_CTRL,
  112. .mask = RPR0521_PXS_GAIN_MASK,
  113. .shift = RPR0521_PXS_GAIN_SHIFT,
  114. .gain = rpr0521_pxs_gain,
  115. .size = ARRAY_SIZE(rpr0521_pxs_gain),
  116. },
  117. };
  118. struct rpr0521_data {
  119. struct i2c_client *client;
  120. /* protect device params updates (e.g state, gain) */
  121. struct mutex lock;
  122. /* device active status */
  123. bool als_dev_en;
  124. bool pxs_dev_en;
  125. /* optimize runtime pm ops - enable device only if needed */
  126. bool als_ps_need_en;
  127. bool pxs_ps_need_en;
  128. struct regmap *regmap;
  129. };
  130. static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
  131. static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
  132. static struct attribute *rpr0521_attributes[] = {
  133. &iio_const_attr_in_intensity_scale_available.dev_attr.attr,
  134. &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
  135. NULL,
  136. };
  137. static const struct attribute_group rpr0521_attribute_group = {
  138. .attrs = rpr0521_attributes,
  139. };
  140. static const struct iio_chan_spec rpr0521_channels[] = {
  141. {
  142. .type = IIO_INTENSITY,
  143. .modified = 1,
  144. .address = RPR0521_CHAN_ALS_DATA0,
  145. .channel2 = IIO_MOD_LIGHT_BOTH,
  146. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  147. BIT(IIO_CHAN_INFO_SCALE),
  148. },
  149. {
  150. .type = IIO_INTENSITY,
  151. .modified = 1,
  152. .address = RPR0521_CHAN_ALS_DATA1,
  153. .channel2 = IIO_MOD_LIGHT_IR,
  154. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  155. BIT(IIO_CHAN_INFO_SCALE),
  156. },
  157. {
  158. .type = IIO_PROXIMITY,
  159. .address = RPR0521_CHAN_PXS,
  160. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  161. BIT(IIO_CHAN_INFO_SCALE),
  162. }
  163. };
  164. static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
  165. {
  166. int ret;
  167. ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
  168. RPR0521_MODE_ALS_MASK,
  169. status);
  170. if (ret < 0)
  171. return ret;
  172. data->als_dev_en = true;
  173. return 0;
  174. }
  175. static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
  176. {
  177. int ret;
  178. ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
  179. RPR0521_MODE_PXS_MASK,
  180. status);
  181. if (ret < 0)
  182. return ret;
  183. data->pxs_dev_en = true;
  184. return 0;
  185. }
  186. /**
  187. * rpr0521_set_power_state - handles runtime PM state and sensors enabled status
  188. *
  189. * @data: rpr0521 device private data
  190. * @on: state to be set for devices in @device_mask
  191. * @device_mask: bitmask specifying for which device we need to update @on state
  192. *
  193. * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but
  194. * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to
  195. * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable
  196. * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not
  197. * be called twice.
  198. */
  199. static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
  200. u8 device_mask)
  201. {
  202. #ifdef CONFIG_PM
  203. int ret;
  204. u8 update_mask = 0;
  205. if (device_mask & RPR0521_MODE_ALS_MASK) {
  206. if (on && !data->als_ps_need_en && data->pxs_dev_en)
  207. update_mask |= RPR0521_MODE_ALS_MASK;
  208. else
  209. data->als_ps_need_en = on;
  210. }
  211. if (device_mask & RPR0521_MODE_PXS_MASK) {
  212. if (on && !data->pxs_ps_need_en && data->als_dev_en)
  213. update_mask |= RPR0521_MODE_PXS_MASK;
  214. else
  215. data->pxs_ps_need_en = on;
  216. }
  217. if (update_mask) {
  218. ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
  219. update_mask, update_mask);
  220. if (ret < 0)
  221. return ret;
  222. }
  223. if (on) {
  224. ret = pm_runtime_get_sync(&data->client->dev);
  225. } else {
  226. pm_runtime_mark_last_busy(&data->client->dev);
  227. ret = pm_runtime_put_autosuspend(&data->client->dev);
  228. }
  229. if (ret < 0) {
  230. dev_err(&data->client->dev,
  231. "Failed: rpr0521_set_power_state for %d, ret %d\n",
  232. on, ret);
  233. if (on)
  234. pm_runtime_put_noidle(&data->client->dev);
  235. return ret;
  236. }
  237. #endif
  238. return 0;
  239. }
  240. static int rpr0521_get_gain(struct rpr0521_data *data, int chan,
  241. int *val, int *val2)
  242. {
  243. int ret, reg, idx;
  244. ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, &reg);
  245. if (ret < 0)
  246. return ret;
  247. idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift;
  248. *val = rpr0521_gain[chan].gain[idx].scale;
  249. *val2 = rpr0521_gain[chan].gain[idx].uscale;
  250. return 0;
  251. }
  252. static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
  253. int val, int val2)
  254. {
  255. int i, idx = -EINVAL;
  256. /* get gain index */
  257. for (i = 0; i < rpr0521_gain[chan].size; i++)
  258. if (val == rpr0521_gain[chan].gain[i].scale &&
  259. val2 == rpr0521_gain[chan].gain[i].uscale) {
  260. idx = i;
  261. break;
  262. }
  263. if (idx < 0)
  264. return idx;
  265. return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg,
  266. rpr0521_gain[chan].mask,
  267. idx << rpr0521_gain[chan].shift);
  268. }
  269. static int rpr0521_read_raw(struct iio_dev *indio_dev,
  270. struct iio_chan_spec const *chan, int *val,
  271. int *val2, long mask)
  272. {
  273. struct rpr0521_data *data = iio_priv(indio_dev);
  274. int ret;
  275. u8 device_mask;
  276. __le16 raw_data;
  277. switch (mask) {
  278. case IIO_CHAN_INFO_RAW:
  279. if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY)
  280. return -EINVAL;
  281. device_mask = rpr0521_data_reg[chan->address].device_mask;
  282. mutex_lock(&data->lock);
  283. ret = rpr0521_set_power_state(data, true, device_mask);
  284. if (ret < 0) {
  285. mutex_unlock(&data->lock);
  286. return ret;
  287. }
  288. ret = regmap_bulk_read(data->regmap,
  289. rpr0521_data_reg[chan->address].address,
  290. &raw_data, 2);
  291. if (ret < 0) {
  292. rpr0521_set_power_state(data, false, device_mask);
  293. mutex_unlock(&data->lock);
  294. return ret;
  295. }
  296. ret = rpr0521_set_power_state(data, false, device_mask);
  297. mutex_unlock(&data->lock);
  298. if (ret < 0)
  299. return ret;
  300. *val = le16_to_cpu(raw_data);
  301. return IIO_VAL_INT;
  302. case IIO_CHAN_INFO_SCALE:
  303. mutex_lock(&data->lock);
  304. ret = rpr0521_get_gain(data, chan->address, val, val2);
  305. mutex_unlock(&data->lock);
  306. if (ret < 0)
  307. return ret;
  308. return IIO_VAL_INT_PLUS_MICRO;
  309. default:
  310. return -EINVAL;
  311. }
  312. }
  313. static int rpr0521_write_raw(struct iio_dev *indio_dev,
  314. struct iio_chan_spec const *chan, int val,
  315. int val2, long mask)
  316. {
  317. struct rpr0521_data *data = iio_priv(indio_dev);
  318. int ret;
  319. switch (mask) {
  320. case IIO_CHAN_INFO_SCALE:
  321. mutex_lock(&data->lock);
  322. ret = rpr0521_set_gain(data, chan->address, val, val2);
  323. mutex_unlock(&data->lock);
  324. return ret;
  325. default:
  326. return -EINVAL;
  327. }
  328. }
  329. static const struct iio_info rpr0521_info = {
  330. .driver_module = THIS_MODULE,
  331. .read_raw = rpr0521_read_raw,
  332. .write_raw = rpr0521_write_raw,
  333. .attrs = &rpr0521_attribute_group,
  334. };
  335. static int rpr0521_init(struct rpr0521_data *data)
  336. {
  337. int ret;
  338. int id;
  339. ret = regmap_read(data->regmap, RPR0521_REG_ID, &id);
  340. if (ret < 0) {
  341. dev_err(&data->client->dev, "Failed to read REG_ID register\n");
  342. return ret;
  343. }
  344. if (id != RPR0521_MANUFACT_ID) {
  345. dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
  346. id, RPR0521_MANUFACT_ID);
  347. return -ENODEV;
  348. }
  349. /* set default measurement time - 100 ms for both ALS and PS */
  350. ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
  351. RPR0521_MODE_MEAS_TIME_MASK,
  352. RPR0521_DEFAULT_MEAS_TIME);
  353. if (ret) {
  354. pr_err("regmap_update_bits returned %d\n", ret);
  355. return ret;
  356. }
  357. ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
  358. if (ret < 0)
  359. return ret;
  360. ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
  361. if (ret < 0)
  362. return ret;
  363. return 0;
  364. }
  365. static int rpr0521_poweroff(struct rpr0521_data *data)
  366. {
  367. int ret;
  368. ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
  369. RPR0521_MODE_ALS_MASK |
  370. RPR0521_MODE_PXS_MASK,
  371. RPR0521_MODE_ALS_DISABLE |
  372. RPR0521_MODE_PXS_DISABLE);
  373. if (ret < 0)
  374. return ret;
  375. data->als_dev_en = false;
  376. data->pxs_dev_en = false;
  377. return 0;
  378. }
  379. static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg)
  380. {
  381. switch (reg) {
  382. case RPR0521_REG_MODE_CTRL:
  383. case RPR0521_REG_ALS_CTRL:
  384. case RPR0521_REG_PXS_CTRL:
  385. return false;
  386. default:
  387. return true;
  388. }
  389. }
  390. static const struct regmap_config rpr0521_regmap_config = {
  391. .name = RPR0521_REGMAP_NAME,
  392. .reg_bits = 8,
  393. .val_bits = 8,
  394. .max_register = RPR0521_REG_ID,
  395. .cache_type = REGCACHE_RBTREE,
  396. .volatile_reg = rpr0521_is_volatile_reg,
  397. };
  398. static int rpr0521_probe(struct i2c_client *client,
  399. const struct i2c_device_id *id)
  400. {
  401. struct rpr0521_data *data;
  402. struct iio_dev *indio_dev;
  403. struct regmap *regmap;
  404. int ret;
  405. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  406. if (!indio_dev)
  407. return -ENOMEM;
  408. regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config);
  409. if (IS_ERR(regmap)) {
  410. dev_err(&client->dev, "regmap_init failed!\n");
  411. return PTR_ERR(regmap);
  412. }
  413. data = iio_priv(indio_dev);
  414. i2c_set_clientdata(client, indio_dev);
  415. data->client = client;
  416. data->regmap = regmap;
  417. mutex_init(&data->lock);
  418. indio_dev->dev.parent = &client->dev;
  419. indio_dev->info = &rpr0521_info;
  420. indio_dev->name = RPR0521_DRV_NAME;
  421. indio_dev->channels = rpr0521_channels;
  422. indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels);
  423. indio_dev->modes = INDIO_DIRECT_MODE;
  424. ret = rpr0521_init(data);
  425. if (ret < 0) {
  426. dev_err(&client->dev, "rpr0521 chip init failed\n");
  427. return ret;
  428. }
  429. ret = pm_runtime_set_active(&client->dev);
  430. if (ret < 0)
  431. goto err_poweroff;
  432. pm_runtime_enable(&client->dev);
  433. pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
  434. pm_runtime_use_autosuspend(&client->dev);
  435. ret = iio_device_register(indio_dev);
  436. if (ret)
  437. goto err_pm_disable;
  438. return 0;
  439. err_pm_disable:
  440. pm_runtime_disable(&client->dev);
  441. pm_runtime_set_suspended(&client->dev);
  442. pm_runtime_put_noidle(&client->dev);
  443. err_poweroff:
  444. rpr0521_poweroff(data);
  445. return ret;
  446. }
  447. static int rpr0521_remove(struct i2c_client *client)
  448. {
  449. struct iio_dev *indio_dev = i2c_get_clientdata(client);
  450. iio_device_unregister(indio_dev);
  451. pm_runtime_disable(&client->dev);
  452. pm_runtime_set_suspended(&client->dev);
  453. pm_runtime_put_noidle(&client->dev);
  454. rpr0521_poweroff(iio_priv(indio_dev));
  455. return 0;
  456. }
  457. #ifdef CONFIG_PM
  458. static int rpr0521_runtime_suspend(struct device *dev)
  459. {
  460. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  461. struct rpr0521_data *data = iio_priv(indio_dev);
  462. int ret;
  463. /* disable channels and sets {als,pxs}_dev_en to false */
  464. mutex_lock(&data->lock);
  465. ret = rpr0521_poweroff(data);
  466. mutex_unlock(&data->lock);
  467. return ret;
  468. }
  469. static int rpr0521_runtime_resume(struct device *dev)
  470. {
  471. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  472. struct rpr0521_data *data = iio_priv(indio_dev);
  473. int ret;
  474. if (data->als_ps_need_en) {
  475. ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
  476. if (ret < 0)
  477. return ret;
  478. data->als_ps_need_en = false;
  479. }
  480. if (data->pxs_ps_need_en) {
  481. ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
  482. if (ret < 0)
  483. return ret;
  484. data->pxs_ps_need_en = false;
  485. }
  486. return 0;
  487. }
  488. #endif
  489. static const struct dev_pm_ops rpr0521_pm_ops = {
  490. SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend,
  491. rpr0521_runtime_resume, NULL)
  492. };
  493. static const struct acpi_device_id rpr0521_acpi_match[] = {
  494. {"RPR0521", 0},
  495. { }
  496. };
  497. MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match);
  498. static const struct i2c_device_id rpr0521_id[] = {
  499. {"rpr0521", 0},
  500. { }
  501. };
  502. MODULE_DEVICE_TABLE(i2c, rpr0521_id);
  503. static struct i2c_driver rpr0521_driver = {
  504. .driver = {
  505. .name = RPR0521_DRV_NAME,
  506. .pm = &rpr0521_pm_ops,
  507. .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
  508. },
  509. .probe = rpr0521_probe,
  510. .remove = rpr0521_remove,
  511. .id_table = rpr0521_id,
  512. };
  513. module_i2c_driver(rpr0521_driver);
  514. MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
  515. MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver");
  516. MODULE_LICENSE("GPL v2");