vcnl4035.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * VCNL4035 Ambient Light and Proximity Sensor - 7-bit I2C slave address 0x60
  4. *
  5. * Copyright (c) 2018, DENX Software Engineering GmbH
  6. * Author: Parthiban Nallathambi <[email protected]>
  7. *
  8. * TODO: Proximity
  9. */
  10. #include <linux/bitops.h>
  11. #include <linux/bitfield.h>
  12. #include <linux/i2c.h>
  13. #include <linux/module.h>
  14. #include <linux/pm_runtime.h>
  15. #include <linux/regmap.h>
  16. #include <linux/iio/buffer.h>
  17. #include <linux/iio/events.h>
  18. #include <linux/iio/iio.h>
  19. #include <linux/iio/sysfs.h>
  20. #include <linux/iio/trigger.h>
  21. #include <linux/iio/trigger_consumer.h>
  22. #include <linux/iio/triggered_buffer.h>
  23. #define VCNL4035_DRV_NAME "vcnl4035"
  24. #define VCNL4035_IRQ_NAME "vcnl4035_event"
  25. #define VCNL4035_REGMAP_NAME "vcnl4035_regmap"
  26. /* Device registers */
  27. #define VCNL4035_ALS_CONF 0x00
  28. #define VCNL4035_ALS_THDH 0x01
  29. #define VCNL4035_ALS_THDL 0x02
  30. #define VCNL4035_ALS_DATA 0x0B
  31. #define VCNL4035_WHITE_DATA 0x0C
  32. #define VCNL4035_INT_FLAG 0x0D
  33. #define VCNL4035_DEV_ID 0x0E
  34. /* Register masks */
  35. #define VCNL4035_MODE_ALS_MASK BIT(0)
  36. #define VCNL4035_MODE_ALS_WHITE_CHAN BIT(8)
  37. #define VCNL4035_MODE_ALS_INT_MASK BIT(1)
  38. #define VCNL4035_ALS_IT_MASK GENMASK(7, 5)
  39. #define VCNL4035_ALS_PERS_MASK GENMASK(3, 2)
  40. #define VCNL4035_INT_ALS_IF_H_MASK BIT(12)
  41. #define VCNL4035_INT_ALS_IF_L_MASK BIT(13)
  42. #define VCNL4035_DEV_ID_MASK GENMASK(7, 0)
  43. /* Default values */
  44. #define VCNL4035_MODE_ALS_ENABLE BIT(0)
  45. #define VCNL4035_MODE_ALS_DISABLE 0x00
  46. #define VCNL4035_MODE_ALS_INT_ENABLE BIT(1)
  47. #define VCNL4035_MODE_ALS_INT_DISABLE 0
  48. #define VCNL4035_DEV_ID_VAL 0x80
  49. #define VCNL4035_ALS_IT_DEFAULT 0x01
  50. #define VCNL4035_ALS_PERS_DEFAULT 0x00
  51. #define VCNL4035_ALS_THDH_DEFAULT 5000
  52. #define VCNL4035_ALS_THDL_DEFAULT 100
  53. #define VCNL4035_SLEEP_DELAY_MS 2000
  54. struct vcnl4035_data {
  55. struct i2c_client *client;
  56. struct regmap *regmap;
  57. unsigned int als_it_val;
  58. unsigned int als_persistence;
  59. unsigned int als_thresh_low;
  60. unsigned int als_thresh_high;
  61. struct iio_trigger *drdy_trigger0;
  62. };
  63. static inline bool vcnl4035_is_triggered(struct vcnl4035_data *data)
  64. {
  65. int ret;
  66. int reg;
  67. ret = regmap_read(data->regmap, VCNL4035_INT_FLAG, &reg);
  68. if (ret < 0)
  69. return false;
  70. return !!(reg &
  71. (VCNL4035_INT_ALS_IF_H_MASK | VCNL4035_INT_ALS_IF_L_MASK));
  72. }
  73. static irqreturn_t vcnl4035_drdy_irq_thread(int irq, void *private)
  74. {
  75. struct iio_dev *indio_dev = private;
  76. struct vcnl4035_data *data = iio_priv(indio_dev);
  77. if (vcnl4035_is_triggered(data)) {
  78. iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_LIGHT,
  79. 0,
  80. IIO_EV_TYPE_THRESH,
  81. IIO_EV_DIR_EITHER),
  82. iio_get_time_ns(indio_dev));
  83. iio_trigger_poll_chained(data->drdy_trigger0);
  84. return IRQ_HANDLED;
  85. }
  86. return IRQ_NONE;
  87. }
  88. /* Triggered buffer */
  89. static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p)
  90. {
  91. struct iio_poll_func *pf = p;
  92. struct iio_dev *indio_dev = pf->indio_dev;
  93. struct vcnl4035_data *data = iio_priv(indio_dev);
  94. /* Ensure naturally aligned timestamp */
  95. u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8);
  96. int ret;
  97. ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer);
  98. if (ret < 0) {
  99. dev_err(&data->client->dev,
  100. "Trigger consumer can't read from sensor.\n");
  101. goto fail_read;
  102. }
  103. iio_push_to_buffers_with_timestamp(indio_dev, buffer,
  104. iio_get_time_ns(indio_dev));
  105. fail_read:
  106. iio_trigger_notify_done(indio_dev->trig);
  107. return IRQ_HANDLED;
  108. }
  109. static int vcnl4035_als_drdy_set_state(struct iio_trigger *trigger,
  110. bool enable_drdy)
  111. {
  112. struct iio_dev *indio_dev = iio_trigger_get_drvdata(trigger);
  113. struct vcnl4035_data *data = iio_priv(indio_dev);
  114. int val = enable_drdy ? VCNL4035_MODE_ALS_INT_ENABLE :
  115. VCNL4035_MODE_ALS_INT_DISABLE;
  116. return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  117. VCNL4035_MODE_ALS_INT_MASK,
  118. val);
  119. }
  120. static const struct iio_trigger_ops vcnl4035_trigger_ops = {
  121. .validate_device = iio_trigger_validate_own_device,
  122. .set_trigger_state = vcnl4035_als_drdy_set_state,
  123. };
  124. static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on)
  125. {
  126. int ret;
  127. struct device *dev = &data->client->dev;
  128. if (on) {
  129. ret = pm_runtime_resume_and_get(dev);
  130. } else {
  131. pm_runtime_mark_last_busy(dev);
  132. ret = pm_runtime_put_autosuspend(dev);
  133. }
  134. return ret;
  135. }
  136. /*
  137. * Device IT INT Time (ms) Scale (lux/step)
  138. * 000 50 0.064
  139. * 001 100 0.032
  140. * 010 200 0.016
  141. * 100 400 0.008
  142. * 101 - 111 800 0.004
  143. * Values are proportional, so ALS INT is selected for input due to
  144. * simplicity reason. Integration time value and scaling is
  145. * calculated based on device INT value
  146. *
  147. * Raw value needs to be scaled using ALS steps
  148. */
  149. static int vcnl4035_read_raw(struct iio_dev *indio_dev,
  150. struct iio_chan_spec const *chan, int *val,
  151. int *val2, long mask)
  152. {
  153. struct vcnl4035_data *data = iio_priv(indio_dev);
  154. int ret;
  155. int raw_data;
  156. unsigned int reg;
  157. switch (mask) {
  158. case IIO_CHAN_INFO_RAW:
  159. ret = vcnl4035_set_pm_runtime_state(data, true);
  160. if (ret < 0)
  161. return ret;
  162. ret = iio_device_claim_direct_mode(indio_dev);
  163. if (!ret) {
  164. if (chan->channel)
  165. reg = VCNL4035_ALS_DATA;
  166. else
  167. reg = VCNL4035_WHITE_DATA;
  168. ret = regmap_read(data->regmap, reg, &raw_data);
  169. iio_device_release_direct_mode(indio_dev);
  170. if (!ret) {
  171. *val = raw_data;
  172. ret = IIO_VAL_INT;
  173. }
  174. }
  175. vcnl4035_set_pm_runtime_state(data, false);
  176. return ret;
  177. case IIO_CHAN_INFO_INT_TIME:
  178. *val = 50;
  179. if (data->als_it_val)
  180. *val = data->als_it_val * 100;
  181. return IIO_VAL_INT;
  182. case IIO_CHAN_INFO_SCALE:
  183. *val = 64;
  184. if (!data->als_it_val)
  185. *val2 = 1000;
  186. else
  187. *val2 = data->als_it_val * 2 * 1000;
  188. return IIO_VAL_FRACTIONAL;
  189. default:
  190. return -EINVAL;
  191. }
  192. }
  193. static int vcnl4035_write_raw(struct iio_dev *indio_dev,
  194. struct iio_chan_spec const *chan,
  195. int val, int val2, long mask)
  196. {
  197. int ret;
  198. struct vcnl4035_data *data = iio_priv(indio_dev);
  199. switch (mask) {
  200. case IIO_CHAN_INFO_INT_TIME:
  201. if (val <= 0 || val > 800)
  202. return -EINVAL;
  203. ret = vcnl4035_set_pm_runtime_state(data, true);
  204. if (ret < 0)
  205. return ret;
  206. ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  207. VCNL4035_ALS_IT_MASK,
  208. val / 100);
  209. if (!ret)
  210. data->als_it_val = val / 100;
  211. vcnl4035_set_pm_runtime_state(data, false);
  212. return ret;
  213. default:
  214. return -EINVAL;
  215. }
  216. }
  217. /* No direct ABI for persistence and threshold, so eventing */
  218. static int vcnl4035_read_thresh(struct iio_dev *indio_dev,
  219. const struct iio_chan_spec *chan, enum iio_event_type type,
  220. enum iio_event_direction dir, enum iio_event_info info,
  221. int *val, int *val2)
  222. {
  223. struct vcnl4035_data *data = iio_priv(indio_dev);
  224. switch (info) {
  225. case IIO_EV_INFO_VALUE:
  226. switch (dir) {
  227. case IIO_EV_DIR_RISING:
  228. *val = data->als_thresh_high;
  229. return IIO_VAL_INT;
  230. case IIO_EV_DIR_FALLING:
  231. *val = data->als_thresh_low;
  232. return IIO_VAL_INT;
  233. default:
  234. return -EINVAL;
  235. }
  236. break;
  237. case IIO_EV_INFO_PERIOD:
  238. *val = data->als_persistence;
  239. return IIO_VAL_INT;
  240. default:
  241. return -EINVAL;
  242. }
  243. }
  244. static int vcnl4035_write_thresh(struct iio_dev *indio_dev,
  245. const struct iio_chan_spec *chan, enum iio_event_type type,
  246. enum iio_event_direction dir, enum iio_event_info info, int val,
  247. int val2)
  248. {
  249. struct vcnl4035_data *data = iio_priv(indio_dev);
  250. int ret;
  251. switch (info) {
  252. case IIO_EV_INFO_VALUE:
  253. /* 16 bit threshold range 0 - 65535 */
  254. if (val < 0 || val > 65535)
  255. return -EINVAL;
  256. if (dir == IIO_EV_DIR_RISING) {
  257. if (val < data->als_thresh_low)
  258. return -EINVAL;
  259. ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
  260. val);
  261. if (ret)
  262. return ret;
  263. data->als_thresh_high = val;
  264. } else {
  265. if (val > data->als_thresh_high)
  266. return -EINVAL;
  267. ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
  268. val);
  269. if (ret)
  270. return ret;
  271. data->als_thresh_low = val;
  272. }
  273. return ret;
  274. case IIO_EV_INFO_PERIOD:
  275. /* allow only 1 2 4 8 as persistence value */
  276. if (val < 0 || val > 8 || hweight8(val) != 1)
  277. return -EINVAL;
  278. ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  279. VCNL4035_ALS_PERS_MASK, val);
  280. if (!ret)
  281. data->als_persistence = val;
  282. return ret;
  283. default:
  284. return -EINVAL;
  285. }
  286. }
  287. static IIO_CONST_ATTR_INT_TIME_AVAIL("50 100 200 400 800");
  288. static struct attribute *vcnl4035_attributes[] = {
  289. &iio_const_attr_integration_time_available.dev_attr.attr,
  290. NULL,
  291. };
  292. static const struct attribute_group vcnl4035_attribute_group = {
  293. .attrs = vcnl4035_attributes,
  294. };
  295. static const struct iio_info vcnl4035_info = {
  296. .read_raw = vcnl4035_read_raw,
  297. .write_raw = vcnl4035_write_raw,
  298. .read_event_value = vcnl4035_read_thresh,
  299. .write_event_value = vcnl4035_write_thresh,
  300. .attrs = &vcnl4035_attribute_group,
  301. };
  302. static const struct iio_event_spec vcnl4035_event_spec[] = {
  303. {
  304. .type = IIO_EV_TYPE_THRESH,
  305. .dir = IIO_EV_DIR_RISING,
  306. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  307. }, {
  308. .type = IIO_EV_TYPE_THRESH,
  309. .dir = IIO_EV_DIR_FALLING,
  310. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  311. }, {
  312. .type = IIO_EV_TYPE_THRESH,
  313. .dir = IIO_EV_DIR_EITHER,
  314. .mask_separate = BIT(IIO_EV_INFO_PERIOD),
  315. },
  316. };
  317. enum vcnl4035_scan_index_order {
  318. VCNL4035_CHAN_INDEX_LIGHT,
  319. VCNL4035_CHAN_INDEX_WHITE_LED,
  320. };
  321. static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
  322. .validate_scan_mask = &iio_validate_scan_mask_onehot,
  323. };
  324. static const struct iio_chan_spec vcnl4035_channels[] = {
  325. {
  326. .type = IIO_LIGHT,
  327. .channel = 0,
  328. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  329. BIT(IIO_CHAN_INFO_INT_TIME) |
  330. BIT(IIO_CHAN_INFO_SCALE),
  331. .event_spec = vcnl4035_event_spec,
  332. .num_event_specs = ARRAY_SIZE(vcnl4035_event_spec),
  333. .scan_index = VCNL4035_CHAN_INDEX_LIGHT,
  334. .scan_type = {
  335. .sign = 'u',
  336. .realbits = 16,
  337. .storagebits = 16,
  338. .endianness = IIO_LE,
  339. },
  340. },
  341. {
  342. .type = IIO_INTENSITY,
  343. .channel = 1,
  344. .modified = 1,
  345. .channel2 = IIO_MOD_LIGHT_BOTH,
  346. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  347. .scan_index = VCNL4035_CHAN_INDEX_WHITE_LED,
  348. .scan_type = {
  349. .sign = 'u',
  350. .realbits = 16,
  351. .storagebits = 16,
  352. .endianness = IIO_LE,
  353. },
  354. },
  355. };
  356. static int vcnl4035_set_als_power_state(struct vcnl4035_data *data, u8 status)
  357. {
  358. return regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  359. VCNL4035_MODE_ALS_MASK,
  360. status);
  361. }
  362. static int vcnl4035_init(struct vcnl4035_data *data)
  363. {
  364. int ret;
  365. int id;
  366. ret = regmap_read(data->regmap, VCNL4035_DEV_ID, &id);
  367. if (ret < 0) {
  368. dev_err(&data->client->dev, "Failed to read DEV_ID register\n");
  369. return ret;
  370. }
  371. id = FIELD_GET(VCNL4035_DEV_ID_MASK, id);
  372. if (id != VCNL4035_DEV_ID_VAL) {
  373. dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
  374. id, VCNL4035_DEV_ID_VAL);
  375. return -ENODEV;
  376. }
  377. ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
  378. if (ret < 0)
  379. return ret;
  380. /* ALS white channel enable */
  381. ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  382. VCNL4035_MODE_ALS_WHITE_CHAN,
  383. 1);
  384. if (ret) {
  385. dev_err(&data->client->dev, "set white channel enable %d\n",
  386. ret);
  387. return ret;
  388. }
  389. /* set default integration time - 100 ms for ALS */
  390. ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  391. VCNL4035_ALS_IT_MASK,
  392. VCNL4035_ALS_IT_DEFAULT);
  393. if (ret) {
  394. dev_err(&data->client->dev, "set default ALS IT returned %d\n",
  395. ret);
  396. return ret;
  397. }
  398. data->als_it_val = VCNL4035_ALS_IT_DEFAULT;
  399. /* set default persistence time - 1 for ALS */
  400. ret = regmap_update_bits(data->regmap, VCNL4035_ALS_CONF,
  401. VCNL4035_ALS_PERS_MASK,
  402. VCNL4035_ALS_PERS_DEFAULT);
  403. if (ret) {
  404. dev_err(&data->client->dev, "set default PERS returned %d\n",
  405. ret);
  406. return ret;
  407. }
  408. data->als_persistence = VCNL4035_ALS_PERS_DEFAULT;
  409. /* set default HIGH threshold for ALS */
  410. ret = regmap_write(data->regmap, VCNL4035_ALS_THDH,
  411. VCNL4035_ALS_THDH_DEFAULT);
  412. if (ret) {
  413. dev_err(&data->client->dev, "set default THDH returned %d\n",
  414. ret);
  415. return ret;
  416. }
  417. data->als_thresh_high = VCNL4035_ALS_THDH_DEFAULT;
  418. /* set default LOW threshold for ALS */
  419. ret = regmap_write(data->regmap, VCNL4035_ALS_THDL,
  420. VCNL4035_ALS_THDL_DEFAULT);
  421. if (ret) {
  422. dev_err(&data->client->dev, "set default THDL returned %d\n",
  423. ret);
  424. return ret;
  425. }
  426. data->als_thresh_low = VCNL4035_ALS_THDL_DEFAULT;
  427. return 0;
  428. }
  429. static bool vcnl4035_is_volatile_reg(struct device *dev, unsigned int reg)
  430. {
  431. switch (reg) {
  432. case VCNL4035_ALS_CONF:
  433. case VCNL4035_DEV_ID:
  434. return false;
  435. default:
  436. return true;
  437. }
  438. }
  439. static const struct regmap_config vcnl4035_regmap_config = {
  440. .name = VCNL4035_REGMAP_NAME,
  441. .reg_bits = 8,
  442. .val_bits = 16,
  443. .max_register = VCNL4035_DEV_ID,
  444. .cache_type = REGCACHE_RBTREE,
  445. .volatile_reg = vcnl4035_is_volatile_reg,
  446. .val_format_endian = REGMAP_ENDIAN_LITTLE,
  447. };
  448. static int vcnl4035_probe_trigger(struct iio_dev *indio_dev)
  449. {
  450. int ret;
  451. struct vcnl4035_data *data = iio_priv(indio_dev);
  452. data->drdy_trigger0 = devm_iio_trigger_alloc(
  453. indio_dev->dev.parent,
  454. "%s-dev%d", indio_dev->name, iio_device_id(indio_dev));
  455. if (!data->drdy_trigger0)
  456. return -ENOMEM;
  457. data->drdy_trigger0->ops = &vcnl4035_trigger_ops;
  458. iio_trigger_set_drvdata(data->drdy_trigger0, indio_dev);
  459. ret = devm_iio_trigger_register(indio_dev->dev.parent,
  460. data->drdy_trigger0);
  461. if (ret) {
  462. dev_err(&data->client->dev, "iio trigger register failed\n");
  463. return ret;
  464. }
  465. /* Trigger setup */
  466. ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
  467. NULL, vcnl4035_trigger_consumer_handler,
  468. &iio_triggered_buffer_setup_ops);
  469. if (ret < 0) {
  470. dev_err(&data->client->dev, "iio triggered buffer setup failed\n");
  471. return ret;
  472. }
  473. /* IRQ to trigger mapping */
  474. ret = devm_request_threaded_irq(&data->client->dev, data->client->irq,
  475. NULL, vcnl4035_drdy_irq_thread,
  476. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  477. VCNL4035_IRQ_NAME, indio_dev);
  478. if (ret < 0)
  479. dev_err(&data->client->dev, "request irq %d for trigger0 failed\n",
  480. data->client->irq);
  481. return ret;
  482. }
  483. static int vcnl4035_probe(struct i2c_client *client,
  484. const struct i2c_device_id *id)
  485. {
  486. struct vcnl4035_data *data;
  487. struct iio_dev *indio_dev;
  488. struct regmap *regmap;
  489. int ret;
  490. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  491. if (!indio_dev)
  492. return -ENOMEM;
  493. regmap = devm_regmap_init_i2c(client, &vcnl4035_regmap_config);
  494. if (IS_ERR(regmap)) {
  495. dev_err(&client->dev, "regmap_init failed!\n");
  496. return PTR_ERR(regmap);
  497. }
  498. data = iio_priv(indio_dev);
  499. i2c_set_clientdata(client, indio_dev);
  500. data->client = client;
  501. data->regmap = regmap;
  502. indio_dev->info = &vcnl4035_info;
  503. indio_dev->name = VCNL4035_DRV_NAME;
  504. indio_dev->channels = vcnl4035_channels;
  505. indio_dev->num_channels = ARRAY_SIZE(vcnl4035_channels);
  506. indio_dev->modes = INDIO_DIRECT_MODE;
  507. ret = vcnl4035_init(data);
  508. if (ret < 0) {
  509. dev_err(&client->dev, "vcnl4035 chip init failed\n");
  510. return ret;
  511. }
  512. if (client->irq > 0) {
  513. ret = vcnl4035_probe_trigger(indio_dev);
  514. if (ret < 0) {
  515. dev_err(&client->dev, "vcnl4035 unable init trigger\n");
  516. goto fail_poweroff;
  517. }
  518. }
  519. ret = pm_runtime_set_active(&client->dev);
  520. if (ret < 0)
  521. goto fail_poweroff;
  522. ret = iio_device_register(indio_dev);
  523. if (ret < 0)
  524. goto fail_poweroff;
  525. pm_runtime_enable(&client->dev);
  526. pm_runtime_set_autosuspend_delay(&client->dev, VCNL4035_SLEEP_DELAY_MS);
  527. pm_runtime_use_autosuspend(&client->dev);
  528. return 0;
  529. fail_poweroff:
  530. vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
  531. return ret;
  532. }
  533. static void vcnl4035_remove(struct i2c_client *client)
  534. {
  535. struct iio_dev *indio_dev = i2c_get_clientdata(client);
  536. int ret;
  537. pm_runtime_dont_use_autosuspend(&client->dev);
  538. pm_runtime_disable(&client->dev);
  539. iio_device_unregister(indio_dev);
  540. pm_runtime_set_suspended(&client->dev);
  541. ret = vcnl4035_set_als_power_state(iio_priv(indio_dev),
  542. VCNL4035_MODE_ALS_DISABLE);
  543. if (ret)
  544. dev_warn(&client->dev, "Failed to put device into standby (%pe)\n",
  545. ERR_PTR(ret));
  546. }
  547. static int vcnl4035_runtime_suspend(struct device *dev)
  548. {
  549. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  550. struct vcnl4035_data *data = iio_priv(indio_dev);
  551. int ret;
  552. ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_DISABLE);
  553. regcache_mark_dirty(data->regmap);
  554. return ret;
  555. }
  556. static int vcnl4035_runtime_resume(struct device *dev)
  557. {
  558. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  559. struct vcnl4035_data *data = iio_priv(indio_dev);
  560. int ret;
  561. regcache_sync(data->regmap);
  562. ret = vcnl4035_set_als_power_state(data, VCNL4035_MODE_ALS_ENABLE);
  563. if (ret < 0)
  564. return ret;
  565. /* wait for 1 ALS integration cycle */
  566. msleep(data->als_it_val * 100);
  567. return 0;
  568. }
  569. static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4035_pm_ops, vcnl4035_runtime_suspend,
  570. vcnl4035_runtime_resume, NULL);
  571. static const struct i2c_device_id vcnl4035_id[] = {
  572. { "vcnl4035", 0 },
  573. { }
  574. };
  575. MODULE_DEVICE_TABLE(i2c, vcnl4035_id);
  576. static const struct of_device_id vcnl4035_of_match[] = {
  577. { .compatible = "vishay,vcnl4035", },
  578. { }
  579. };
  580. MODULE_DEVICE_TABLE(of, vcnl4035_of_match);
  581. static struct i2c_driver vcnl4035_driver = {
  582. .driver = {
  583. .name = VCNL4035_DRV_NAME,
  584. .pm = pm_ptr(&vcnl4035_pm_ops),
  585. .of_match_table = vcnl4035_of_match,
  586. },
  587. .probe = vcnl4035_probe,
  588. .remove = vcnl4035_remove,
  589. .id_table = vcnl4035_id,
  590. };
  591. module_i2c_driver(vcnl4035_driver);
  592. MODULE_AUTHOR("Parthiban Nallathambi <[email protected]>");
  593. MODULE_DESCRIPTION("VCNL4035 Ambient Light Sensor driver");
  594. MODULE_LICENSE("GPL v2");