us5182d.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. /*
  2. * Copyright (c) 2015 Intel Corporation
  3. *
  4. * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * To do: Interrupt support.
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/module.h>
  19. #include <linux/acpi.h>
  20. #include <linux/delay.h>
  21. #include <linux/i2c.h>
  22. #include <linux/iio/events.h>
  23. #include <linux/iio/iio.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/irq.h>
  26. #include <linux/iio/sysfs.h>
  27. #include <linux/mutex.h>
  28. #include <linux/pm.h>
  29. #include <linux/pm_runtime.h>
  30. #define US5182D_REG_CFG0 0x00
  31. #define US5182D_CFG0_ONESHOT_EN BIT(6)
  32. #define US5182D_CFG0_SHUTDOWN_EN BIT(7)
  33. #define US5182D_CFG0_WORD_ENABLE BIT(0)
  34. #define US5182D_CFG0_PROX BIT(3)
  35. #define US5182D_CFG0_PX_IRQ BIT(2)
  36. #define US5182D_REG_CFG1 0x01
  37. #define US5182D_CFG1_ALS_RES16 BIT(4)
  38. #define US5182D_CFG1_AGAIN_DEFAULT 0x00
  39. #define US5182D_REG_CFG2 0x02
  40. #define US5182D_CFG2_PX_RES16 BIT(4)
  41. #define US5182D_CFG2_PXGAIN_DEFAULT BIT(2)
  42. #define US5182D_REG_CFG3 0x03
  43. #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5))
  44. #define US5182D_CFG3_INT_SOURCE_PX BIT(3)
  45. #define US5182D_REG_CFG4 0x10
  46. /*
  47. * Registers for tuning the auto dark current cancelling feature.
  48. * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling.
  49. * when ALS > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark
  50. * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark
  51. */
  52. #define US5182D_REG_UDARK_TH 0x27
  53. #define US5182D_REG_DARK_AUTO_EN 0x2b
  54. #define US5182D_REG_AUTO_LDARK_GAIN 0x29
  55. #define US5182D_REG_AUTO_HDARK_GAIN 0x2a
  56. /* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */
  57. #define US5182D_REG_PXL_TH 0x08
  58. #define US5182D_REG_PXH_TH 0x0a
  59. #define US5182D_REG_PXL_TH_DEFAULT 1000
  60. #define US5182D_REG_PXH_TH_DEFAULT 30000
  61. #define US5182D_OPMODE_ALS 0x01
  62. #define US5182D_OPMODE_PX 0x02
  63. #define US5182D_OPMODE_SHIFT 4
  64. #define US5182D_REG_DARK_AUTO_EN_DEFAULT 0x80
  65. #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT 0x16
  66. #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT 0x00
  67. #define US5182D_REG_ADL 0x0c
  68. #define US5182D_REG_PDL 0x0e
  69. #define US5182D_REG_MODE_STORE 0x21
  70. #define US5182D_STORE_MODE 0x01
  71. #define US5182D_REG_CHIPID 0xb2
  72. #define US5182D_OPMODE_MASK GENMASK(5, 4)
  73. #define US5182D_AGAIN_MASK 0x07
  74. #define US5182D_RESET_CHIP 0x01
  75. #define US5182D_CHIPID 0x26
  76. #define US5182D_DRV_NAME "us5182d"
  77. #define US5182D_GA_RESOLUTION 1000
  78. #define US5182D_READ_BYTE 1
  79. #define US5182D_READ_WORD 2
  80. #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */
  81. #define US5182D_SLEEP_MS 3000 /* ms */
  82. #define US5182D_PXH_TH_DISABLE 0xffff
  83. #define US5182D_PXL_TH_DISABLE 0x0000
  84. /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
  85. static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
  86. 3900, 2100};
  87. /*
  88. * Experimental thresholds that work with US5182D sensor on evaluation board
  89. * roughly between 12-32 lux
  90. */
  91. static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000,
  92. 8000};
  93. enum mode {
  94. US5182D_ALS_PX,
  95. US5182D_ALS_ONLY,
  96. US5182D_PX_ONLY
  97. };
  98. enum pmode {
  99. US5182D_CONTINUOUS,
  100. US5182D_ONESHOT
  101. };
  102. struct us5182d_data {
  103. struct i2c_client *client;
  104. struct mutex lock;
  105. /* Glass attenuation factor */
  106. u32 ga;
  107. /* Dark gain tuning */
  108. u8 lower_dark_gain;
  109. u8 upper_dark_gain;
  110. u16 *us5182d_dark_ths;
  111. u16 px_low_th;
  112. u16 px_high_th;
  113. int rising_en;
  114. int falling_en;
  115. u8 opmode;
  116. u8 power_mode;
  117. bool als_enabled;
  118. bool px_enabled;
  119. bool default_continuous;
  120. };
  121. static IIO_CONST_ATTR(in_illuminance_scale_available,
  122. "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885");
  123. static struct attribute *us5182d_attrs[] = {
  124. &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
  125. NULL
  126. };
  127. static const struct attribute_group us5182d_attr_group = {
  128. .attrs = us5182d_attrs,
  129. };
  130. static const struct {
  131. u8 reg;
  132. u8 val;
  133. } us5182d_regvals[] = {
  134. {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE},
  135. {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},
  136. {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |
  137. US5182D_CFG2_PXGAIN_DEFAULT)},
  138. {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 |
  139. US5182D_CFG3_INT_SOURCE_PX},
  140. {US5182D_REG_CFG4, 0x00},
  141. };
  142. static const struct iio_event_spec us5182d_events[] = {
  143. {
  144. .type = IIO_EV_TYPE_THRESH,
  145. .dir = IIO_EV_DIR_RISING,
  146. .mask_separate = BIT(IIO_EV_INFO_VALUE) |
  147. BIT(IIO_EV_INFO_ENABLE),
  148. },
  149. {
  150. .type = IIO_EV_TYPE_THRESH,
  151. .dir = IIO_EV_DIR_FALLING,
  152. .mask_separate = BIT(IIO_EV_INFO_VALUE) |
  153. BIT(IIO_EV_INFO_ENABLE),
  154. },
  155. };
  156. static const struct iio_chan_spec us5182d_channels[] = {
  157. {
  158. .type = IIO_LIGHT,
  159. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  160. BIT(IIO_CHAN_INFO_SCALE),
  161. },
  162. {
  163. .type = IIO_PROXIMITY,
  164. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  165. .event_spec = us5182d_events,
  166. .num_event_specs = ARRAY_SIZE(us5182d_events),
  167. }
  168. };
  169. static int us5182d_oneshot_en(struct us5182d_data *data)
  170. {
  171. int ret;
  172. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
  173. if (ret < 0)
  174. return ret;
  175. /*
  176. * In oneshot mode the chip will power itself down after taking the
  177. * required measurement.
  178. */
  179. ret = ret | US5182D_CFG0_ONESHOT_EN;
  180. return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
  181. }
  182. static int us5182d_set_opmode(struct us5182d_data *data, u8 mode)
  183. {
  184. int ret;
  185. if (mode == data->opmode)
  186. return 0;
  187. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
  188. if (ret < 0)
  189. return ret;
  190. /* update mode */
  191. ret = ret & ~US5182D_OPMODE_MASK;
  192. ret = ret | (mode << US5182D_OPMODE_SHIFT);
  193. /*
  194. * After updating the operating mode, the chip requires that
  195. * the operation is stored, by writing 1 in the STORE_MODE
  196. * register (auto-clearing).
  197. */
  198. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
  199. if (ret < 0)
  200. return ret;
  201. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE,
  202. US5182D_STORE_MODE);
  203. if (ret < 0)
  204. return ret;
  205. data->opmode = mode;
  206. msleep(US5182D_OPSTORE_SLEEP_TIME);
  207. return 0;
  208. }
  209. static int us5182d_als_enable(struct us5182d_data *data)
  210. {
  211. int ret;
  212. u8 mode;
  213. if (data->power_mode == US5182D_ONESHOT) {
  214. ret = us5182d_set_opmode(data, US5182D_ALS_ONLY);
  215. if (ret < 0)
  216. return ret;
  217. data->px_enabled = false;
  218. }
  219. if (data->als_enabled)
  220. return 0;
  221. mode = data->px_enabled ? US5182D_ALS_PX : US5182D_ALS_ONLY;
  222. ret = us5182d_set_opmode(data, mode);
  223. if (ret < 0)
  224. return ret;
  225. data->als_enabled = true;
  226. return 0;
  227. }
  228. static int us5182d_px_enable(struct us5182d_data *data)
  229. {
  230. int ret;
  231. u8 mode;
  232. if (data->power_mode == US5182D_ONESHOT) {
  233. ret = us5182d_set_opmode(data, US5182D_PX_ONLY);
  234. if (ret < 0)
  235. return ret;
  236. data->als_enabled = false;
  237. }
  238. if (data->px_enabled)
  239. return 0;
  240. mode = data->als_enabled ? US5182D_ALS_PX : US5182D_PX_ONLY;
  241. ret = us5182d_set_opmode(data, mode);
  242. if (ret < 0)
  243. return ret;
  244. data->px_enabled = true;
  245. return 0;
  246. }
  247. static int us5182d_get_als(struct us5182d_data *data)
  248. {
  249. int ret;
  250. unsigned long result;
  251. ret = us5182d_als_enable(data);
  252. if (ret < 0)
  253. return ret;
  254. ret = i2c_smbus_read_word_data(data->client,
  255. US5182D_REG_ADL);
  256. if (ret < 0)
  257. return ret;
  258. result = ret * data->ga / US5182D_GA_RESOLUTION;
  259. if (result > 0xffff)
  260. result = 0xffff;
  261. return result;
  262. }
  263. static int us5182d_get_px(struct us5182d_data *data)
  264. {
  265. int ret;
  266. ret = us5182d_px_enable(data);
  267. if (ret < 0)
  268. return ret;
  269. return i2c_smbus_read_word_data(data->client,
  270. US5182D_REG_PDL);
  271. }
  272. static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)
  273. {
  274. int ret;
  275. if (data->power_mode == US5182D_ONESHOT)
  276. return 0;
  277. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
  278. if (ret < 0)
  279. return ret;
  280. ret = ret & ~US5182D_CFG0_SHUTDOWN_EN;
  281. ret = ret | state;
  282. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
  283. if (ret < 0)
  284. return ret;
  285. if (state & US5182D_CFG0_SHUTDOWN_EN) {
  286. data->als_enabled = false;
  287. data->px_enabled = false;
  288. }
  289. return ret;
  290. }
  291. static int us5182d_set_power_state(struct us5182d_data *data, bool on)
  292. {
  293. int ret;
  294. if (data->power_mode == US5182D_ONESHOT)
  295. return 0;
  296. if (on) {
  297. ret = pm_runtime_get_sync(&data->client->dev);
  298. if (ret < 0)
  299. pm_runtime_put_noidle(&data->client->dev);
  300. } else {
  301. pm_runtime_mark_last_busy(&data->client->dev);
  302. ret = pm_runtime_put_autosuspend(&data->client->dev);
  303. }
  304. return ret;
  305. }
  306. static int us5182d_read_value(struct us5182d_data *data,
  307. struct iio_chan_spec const *chan)
  308. {
  309. int ret, value;
  310. mutex_lock(&data->lock);
  311. if (data->power_mode == US5182D_ONESHOT) {
  312. ret = us5182d_oneshot_en(data);
  313. if (ret < 0)
  314. goto out_err;
  315. }
  316. ret = us5182d_set_power_state(data, true);
  317. if (ret < 0)
  318. goto out_err;
  319. if (chan->type == IIO_LIGHT)
  320. ret = us5182d_get_als(data);
  321. else
  322. ret = us5182d_get_px(data);
  323. if (ret < 0)
  324. goto out_poweroff;
  325. value = ret;
  326. ret = us5182d_set_power_state(data, false);
  327. if (ret < 0)
  328. goto out_err;
  329. mutex_unlock(&data->lock);
  330. return value;
  331. out_poweroff:
  332. us5182d_set_power_state(data, false);
  333. out_err:
  334. mutex_unlock(&data->lock);
  335. return ret;
  336. }
  337. static int us5182d_read_raw(struct iio_dev *indio_dev,
  338. struct iio_chan_spec const *chan, int *val,
  339. int *val2, long mask)
  340. {
  341. struct us5182d_data *data = iio_priv(indio_dev);
  342. int ret;
  343. switch (mask) {
  344. case IIO_CHAN_INFO_RAW:
  345. ret = us5182d_read_value(data, chan);
  346. if (ret < 0)
  347. return ret;
  348. *val = ret;
  349. return IIO_VAL_INT;
  350. case IIO_CHAN_INFO_SCALE:
  351. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
  352. if (ret < 0)
  353. return ret;
  354. *val = 0;
  355. *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];
  356. return IIO_VAL_INT_PLUS_MICRO;
  357. default:
  358. return -EINVAL;
  359. }
  360. }
  361. /**
  362. * us5182d_update_dark_th - update Darh_Th registers
  363. * @data us5182d_data structure
  364. * @index index in us5182d_dark_ths array to use for the updated value
  365. *
  366. * Function needs to be called with a lock held because it needs two i2c write
  367. * byte operations as these registers (0x27 0x28) don't work in word mode
  368. * accessing.
  369. */
  370. static int us5182d_update_dark_th(struct us5182d_data *data, int index)
  371. {
  372. __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]);
  373. int ret;
  374. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH,
  375. ((u8 *)&dark_th)[0]);
  376. if (ret < 0)
  377. return ret;
  378. return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1,
  379. ((u8 *)&dark_th)[1]);
  380. }
  381. /**
  382. * us5182d_apply_scale - update the ALS scale
  383. * @data us5182d_data structure
  384. * @index index in us5182d_scales array to use for the updated value
  385. *
  386. * Function needs to be called with a lock held as we're having more than one
  387. * i2c operation.
  388. */
  389. static int us5182d_apply_scale(struct us5182d_data *data, int index)
  390. {
  391. int ret;
  392. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
  393. if (ret < 0)
  394. return ret;
  395. ret = ret & (~US5182D_AGAIN_MASK);
  396. ret |= index;
  397. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret);
  398. if (ret < 0)
  399. return ret;
  400. return us5182d_update_dark_th(data, index);
  401. }
  402. static int us5182d_write_raw(struct iio_dev *indio_dev,
  403. struct iio_chan_spec const *chan, int val,
  404. int val2, long mask)
  405. {
  406. struct us5182d_data *data = iio_priv(indio_dev);
  407. int ret, i;
  408. switch (mask) {
  409. case IIO_CHAN_INFO_SCALE:
  410. if (val != 0)
  411. return -EINVAL;
  412. for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++)
  413. if (val2 == us5182d_scales[i]) {
  414. mutex_lock(&data->lock);
  415. ret = us5182d_apply_scale(data, i);
  416. mutex_unlock(&data->lock);
  417. return ret;
  418. }
  419. break;
  420. default:
  421. return -EINVAL;
  422. }
  423. return -EINVAL;
  424. }
  425. static int us5182d_setup_prox(struct iio_dev *indio_dev,
  426. enum iio_event_direction dir, u16 val)
  427. {
  428. struct us5182d_data *data = iio_priv(indio_dev);
  429. if (dir == IIO_EV_DIR_FALLING)
  430. return i2c_smbus_write_word_data(data->client,
  431. US5182D_REG_PXL_TH, val);
  432. else if (dir == IIO_EV_DIR_RISING)
  433. return i2c_smbus_write_word_data(data->client,
  434. US5182D_REG_PXH_TH, val);
  435. return 0;
  436. }
  437. static int us5182d_read_thresh(struct iio_dev *indio_dev,
  438. const struct iio_chan_spec *chan, enum iio_event_type type,
  439. enum iio_event_direction dir, enum iio_event_info info, int *val,
  440. int *val2)
  441. {
  442. struct us5182d_data *data = iio_priv(indio_dev);
  443. switch (dir) {
  444. case IIO_EV_DIR_RISING:
  445. mutex_lock(&data->lock);
  446. *val = data->px_high_th;
  447. mutex_unlock(&data->lock);
  448. break;
  449. case IIO_EV_DIR_FALLING:
  450. mutex_lock(&data->lock);
  451. *val = data->px_low_th;
  452. mutex_unlock(&data->lock);
  453. break;
  454. default:
  455. return -EINVAL;
  456. }
  457. return IIO_VAL_INT;
  458. }
  459. static int us5182d_write_thresh(struct iio_dev *indio_dev,
  460. const struct iio_chan_spec *chan, enum iio_event_type type,
  461. enum iio_event_direction dir, enum iio_event_info info, int val,
  462. int val2)
  463. {
  464. struct us5182d_data *data = iio_priv(indio_dev);
  465. int ret;
  466. if (val < 0 || val > USHRT_MAX || val2 != 0)
  467. return -EINVAL;
  468. switch (dir) {
  469. case IIO_EV_DIR_RISING:
  470. mutex_lock(&data->lock);
  471. if (data->rising_en) {
  472. ret = us5182d_setup_prox(indio_dev, dir, val);
  473. if (ret < 0)
  474. goto err;
  475. }
  476. data->px_high_th = val;
  477. mutex_unlock(&data->lock);
  478. break;
  479. case IIO_EV_DIR_FALLING:
  480. mutex_lock(&data->lock);
  481. if (data->falling_en) {
  482. ret = us5182d_setup_prox(indio_dev, dir, val);
  483. if (ret < 0)
  484. goto err;
  485. }
  486. data->px_low_th = val;
  487. mutex_unlock(&data->lock);
  488. break;
  489. default:
  490. return -EINVAL;
  491. }
  492. return 0;
  493. err:
  494. mutex_unlock(&data->lock);
  495. return ret;
  496. }
  497. static int us5182d_read_event_config(struct iio_dev *indio_dev,
  498. const struct iio_chan_spec *chan, enum iio_event_type type,
  499. enum iio_event_direction dir)
  500. {
  501. struct us5182d_data *data = iio_priv(indio_dev);
  502. int ret;
  503. switch (dir) {
  504. case IIO_EV_DIR_RISING:
  505. mutex_lock(&data->lock);
  506. ret = data->rising_en;
  507. mutex_unlock(&data->lock);
  508. break;
  509. case IIO_EV_DIR_FALLING:
  510. mutex_lock(&data->lock);
  511. ret = data->falling_en;
  512. mutex_unlock(&data->lock);
  513. break;
  514. default:
  515. ret = -EINVAL;
  516. break;
  517. }
  518. return ret;
  519. }
  520. static int us5182d_write_event_config(struct iio_dev *indio_dev,
  521. const struct iio_chan_spec *chan, enum iio_event_type type,
  522. enum iio_event_direction dir, int state)
  523. {
  524. struct us5182d_data *data = iio_priv(indio_dev);
  525. int ret;
  526. u16 new_th;
  527. mutex_lock(&data->lock);
  528. switch (dir) {
  529. case IIO_EV_DIR_RISING:
  530. if (data->rising_en == state) {
  531. mutex_unlock(&data->lock);
  532. return 0;
  533. }
  534. new_th = US5182D_PXH_TH_DISABLE;
  535. if (state) {
  536. data->power_mode = US5182D_CONTINUOUS;
  537. ret = us5182d_set_power_state(data, true);
  538. if (ret < 0)
  539. goto err;
  540. ret = us5182d_px_enable(data);
  541. if (ret < 0)
  542. goto err_poweroff;
  543. new_th = data->px_high_th;
  544. }
  545. ret = us5182d_setup_prox(indio_dev, dir, new_th);
  546. if (ret < 0)
  547. goto err_poweroff;
  548. data->rising_en = state;
  549. break;
  550. case IIO_EV_DIR_FALLING:
  551. if (data->falling_en == state) {
  552. mutex_unlock(&data->lock);
  553. return 0;
  554. }
  555. new_th = US5182D_PXL_TH_DISABLE;
  556. if (state) {
  557. data->power_mode = US5182D_CONTINUOUS;
  558. ret = us5182d_set_power_state(data, true);
  559. if (ret < 0)
  560. goto err;
  561. ret = us5182d_px_enable(data);
  562. if (ret < 0)
  563. goto err_poweroff;
  564. new_th = data->px_low_th;
  565. }
  566. ret = us5182d_setup_prox(indio_dev, dir, new_th);
  567. if (ret < 0)
  568. goto err_poweroff;
  569. data->falling_en = state;
  570. break;
  571. default:
  572. ret = -EINVAL;
  573. goto err;
  574. }
  575. if (!state) {
  576. ret = us5182d_set_power_state(data, false);
  577. if (ret < 0)
  578. goto err;
  579. }
  580. if (!data->falling_en && !data->rising_en && !data->default_continuous)
  581. data->power_mode = US5182D_ONESHOT;
  582. mutex_unlock(&data->lock);
  583. return 0;
  584. err_poweroff:
  585. if (state)
  586. us5182d_set_power_state(data, false);
  587. err:
  588. mutex_unlock(&data->lock);
  589. return ret;
  590. }
  591. static const struct iio_info us5182d_info = {
  592. .read_raw = us5182d_read_raw,
  593. .write_raw = us5182d_write_raw,
  594. .attrs = &us5182d_attr_group,
  595. .read_event_value = &us5182d_read_thresh,
  596. .write_event_value = &us5182d_write_thresh,
  597. .read_event_config = &us5182d_read_event_config,
  598. .write_event_config = &us5182d_write_event_config,
  599. };
  600. static int us5182d_reset(struct iio_dev *indio_dev)
  601. {
  602. struct us5182d_data *data = iio_priv(indio_dev);
  603. return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3,
  604. US5182D_RESET_CHIP);
  605. }
  606. static int us5182d_init(struct iio_dev *indio_dev)
  607. {
  608. struct us5182d_data *data = iio_priv(indio_dev);
  609. int i, ret;
  610. ret = us5182d_reset(indio_dev);
  611. if (ret < 0)
  612. return ret;
  613. data->opmode = 0;
  614. data->power_mode = US5182D_CONTINUOUS;
  615. data->px_low_th = US5182D_REG_PXL_TH_DEFAULT;
  616. data->px_high_th = US5182D_REG_PXH_TH_DEFAULT;
  617. for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {
  618. ret = i2c_smbus_write_byte_data(data->client,
  619. us5182d_regvals[i].reg,
  620. us5182d_regvals[i].val);
  621. if (ret < 0)
  622. return ret;
  623. }
  624. data->als_enabled = true;
  625. data->px_enabled = true;
  626. if (!data->default_continuous) {
  627. ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
  628. if (ret < 0)
  629. return ret;
  630. data->power_mode = US5182D_ONESHOT;
  631. }
  632. return ret;
  633. }
  634. static void us5182d_get_platform_data(struct iio_dev *indio_dev)
  635. {
  636. struct us5182d_data *data = iio_priv(indio_dev);
  637. if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef",
  638. &data->ga))
  639. data->ga = US5182D_GA_RESOLUTION;
  640. if (device_property_read_u16_array(&data->client->dev,
  641. "upisemi,dark-ths",
  642. data->us5182d_dark_ths,
  643. ARRAY_SIZE(us5182d_dark_ths_vals)))
  644. data->us5182d_dark_ths = us5182d_dark_ths_vals;
  645. if (device_property_read_u8(&data->client->dev,
  646. "upisemi,upper-dark-gain",
  647. &data->upper_dark_gain))
  648. data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT;
  649. if (device_property_read_u8(&data->client->dev,
  650. "upisemi,lower-dark-gain",
  651. &data->lower_dark_gain))
  652. data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT;
  653. data->default_continuous = device_property_read_bool(&data->client->dev,
  654. "upisemi,continuous");
  655. }
  656. static int us5182d_dark_gain_config(struct iio_dev *indio_dev)
  657. {
  658. struct us5182d_data *data = iio_priv(indio_dev);
  659. int ret;
  660. ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT);
  661. if (ret < 0)
  662. return ret;
  663. ret = i2c_smbus_write_byte_data(data->client,
  664. US5182D_REG_AUTO_LDARK_GAIN,
  665. data->lower_dark_gain);
  666. if (ret < 0)
  667. return ret;
  668. ret = i2c_smbus_write_byte_data(data->client,
  669. US5182D_REG_AUTO_HDARK_GAIN,
  670. data->upper_dark_gain);
  671. if (ret < 0)
  672. return ret;
  673. return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN,
  674. US5182D_REG_DARK_AUTO_EN_DEFAULT);
  675. }
  676. static irqreturn_t us5182d_irq_thread_handler(int irq, void *private)
  677. {
  678. struct iio_dev *indio_dev = private;
  679. struct us5182d_data *data = iio_priv(indio_dev);
  680. enum iio_event_direction dir;
  681. int ret;
  682. u64 ev;
  683. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
  684. if (ret < 0) {
  685. dev_err(&data->client->dev, "i2c transfer error in irq\n");
  686. return IRQ_HANDLED;
  687. }
  688. dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
  689. ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir);
  690. iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));
  691. ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0,
  692. ret & ~US5182D_CFG0_PX_IRQ);
  693. if (ret < 0)
  694. dev_err(&data->client->dev, "i2c transfer error in irq\n");
  695. return IRQ_HANDLED;
  696. }
  697. static int us5182d_probe(struct i2c_client *client,
  698. const struct i2c_device_id *id)
  699. {
  700. struct us5182d_data *data;
  701. struct iio_dev *indio_dev;
  702. int ret;
  703. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  704. if (!indio_dev)
  705. return -ENOMEM;
  706. data = iio_priv(indio_dev);
  707. i2c_set_clientdata(client, indio_dev);
  708. data->client = client;
  709. mutex_init(&data->lock);
  710. indio_dev->dev.parent = &client->dev;
  711. indio_dev->info = &us5182d_info;
  712. indio_dev->name = US5182D_DRV_NAME;
  713. indio_dev->channels = us5182d_channels;
  714. indio_dev->num_channels = ARRAY_SIZE(us5182d_channels);
  715. indio_dev->modes = INDIO_DIRECT_MODE;
  716. ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID);
  717. if (ret != US5182D_CHIPID) {
  718. dev_err(&data->client->dev,
  719. "Failed to detect US5182 light chip\n");
  720. return (ret < 0) ? ret : -ENODEV;
  721. }
  722. if (client->irq > 0) {
  723. ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
  724. us5182d_irq_thread_handler,
  725. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  726. "us5182d-irq", indio_dev);
  727. if (ret < 0)
  728. return ret;
  729. } else
  730. dev_warn(&client->dev, "no valid irq found\n");
  731. us5182d_get_platform_data(indio_dev);
  732. ret = us5182d_init(indio_dev);
  733. if (ret < 0)
  734. return ret;
  735. ret = us5182d_dark_gain_config(indio_dev);
  736. if (ret < 0)
  737. goto out_err;
  738. if (data->default_continuous) {
  739. ret = pm_runtime_set_active(&client->dev);
  740. if (ret < 0)
  741. goto out_err;
  742. }
  743. pm_runtime_enable(&client->dev);
  744. pm_runtime_set_autosuspend_delay(&client->dev,
  745. US5182D_SLEEP_MS);
  746. pm_runtime_use_autosuspend(&client->dev);
  747. ret = iio_device_register(indio_dev);
  748. if (ret < 0)
  749. goto out_err;
  750. return 0;
  751. out_err:
  752. us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
  753. return ret;
  754. }
  755. static int us5182d_remove(struct i2c_client *client)
  756. {
  757. struct us5182d_data *data = iio_priv(i2c_get_clientdata(client));
  758. iio_device_unregister(i2c_get_clientdata(client));
  759. pm_runtime_disable(&client->dev);
  760. pm_runtime_set_suspended(&client->dev);
  761. return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
  762. }
  763. #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
  764. static int us5182d_suspend(struct device *dev)
  765. {
  766. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  767. struct us5182d_data *data = iio_priv(indio_dev);
  768. if (data->power_mode == US5182D_CONTINUOUS)
  769. return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
  770. return 0;
  771. }
  772. static int us5182d_resume(struct device *dev)
  773. {
  774. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  775. struct us5182d_data *data = iio_priv(indio_dev);
  776. if (data->power_mode == US5182D_CONTINUOUS)
  777. return us5182d_shutdown_en(data,
  778. ~US5182D_CFG0_SHUTDOWN_EN & 0xff);
  779. return 0;
  780. }
  781. #endif
  782. static const struct dev_pm_ops us5182d_pm_ops = {
  783. SET_SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume)
  784. SET_RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL)
  785. };
  786. static const struct acpi_device_id us5182d_acpi_match[] = {
  787. { "USD5182", 0},
  788. {}
  789. };
  790. MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match);
  791. static const struct i2c_device_id us5182d_id[] = {
  792. {"usd5182", 0},
  793. {}
  794. };
  795. MODULE_DEVICE_TABLE(i2c, us5182d_id);
  796. static const struct of_device_id us5182d_of_match[] = {
  797. { .compatible = "upisemi,usd5182" },
  798. {}
  799. };
  800. MODULE_DEVICE_TABLE(of, us5182d_of_match);
  801. static struct i2c_driver us5182d_driver = {
  802. .driver = {
  803. .name = US5182D_DRV_NAME,
  804. .pm = &us5182d_pm_ops,
  805. .of_match_table = us5182d_of_match,
  806. .acpi_match_table = ACPI_PTR(us5182d_acpi_match),
  807. },
  808. .probe = us5182d_probe,
  809. .remove = us5182d_remove,
  810. .id_table = us5182d_id,
  811. };
  812. module_i2c_driver(us5182d_driver);
  813. MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
  814. MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor");
  815. MODULE_LICENSE("GPL v2");