vcnl4000.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4040/4200 combined ambient
  4. * light and proximity sensor
  5. *
  6. * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net>
  7. * Copyright 2019 Pursim SPC
  8. * Copyright 2020 Mathieu Othacehe <m.othacehe@gmail.com>
  9. *
  10. * IIO driver for:
  11. * VCNL4000/10/20 (7-bit I2C slave address 0x13)
  12. * VCNL4040 (7-bit I2C slave address 0x60)
  13. * VCNL4200 (7-bit I2C slave address 0x51)
  14. *
  15. * TODO:
  16. * allow to adjust IR current
  17. * interrupts (VCNL4040, VCNL4200)
  18. */
  19. #include <linux/bitfield.h>
  20. #include <linux/module.h>
  21. #include <linux/i2c.h>
  22. #include <linux/err.h>
  23. #include <linux/delay.h>
  24. #include <linux/pm_runtime.h>
  25. #include <linux/interrupt.h>
  26. #include <linux/units.h>
  27. #include <linux/iio/buffer.h>
  28. #include <linux/iio/events.h>
  29. #include <linux/iio/iio.h>
  30. #include <linux/iio/sysfs.h>
  31. #include <linux/iio/trigger.h>
  32. #include <linux/iio/trigger_consumer.h>
  33. #include <linux/iio/triggered_buffer.h>
  34. #define VCNL4000_DRV_NAME "vcnl4000"
  35. #define VCNL4000_PROD_ID 0x01
  36. #define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */
  37. #define VCNL4040_PROD_ID 0x86
  38. #define VCNL4200_PROD_ID 0x58
  39. #define VCNL4000_COMMAND 0x80 /* Command register */
  40. #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */
  41. #define VCNL4010_PROX_RATE 0x82 /* Proximity rate */
  42. #define VCNL4000_LED_CURRENT 0x83 /* IR LED current for proximity mode */
  43. #define VCNL4000_AL_PARAM 0x84 /* Ambient light parameter register */
  44. #define VCNL4010_ALS_PARAM 0x84 /* ALS rate */
  45. #define VCNL4000_AL_RESULT_HI 0x85 /* Ambient light result register, MSB */
  46. #define VCNL4000_AL_RESULT_LO 0x86 /* Ambient light result register, LSB */
  47. #define VCNL4000_PS_RESULT_HI 0x87 /* Proximity result register, MSB */
  48. #define VCNL4000_PS_RESULT_LO 0x88 /* Proximity result register, LSB */
  49. #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */
  50. #define VCNL4010_INT_CTRL 0x89 /* Interrupt control */
  51. #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */
  52. #define VCNL4010_LOW_THR_HI 0x8a /* Low threshold, MSB */
  53. #define VCNL4010_LOW_THR_LO 0x8b /* Low threshold, LSB */
  54. #define VCNL4010_HIGH_THR_HI 0x8c /* High threshold, MSB */
  55. #define VCNL4010_HIGH_THR_LO 0x8d /* High threshold, LSB */
  56. #define VCNL4010_ISR 0x8e /* Interrupt status */
  57. #define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */
  58. #define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */
  59. #define VCNL4200_PS_CONF3 0x04 /* Proximity configuration */
  60. #define VCNL4040_PS_THDL_LM 0x06 /* Proximity threshold low */
  61. #define VCNL4040_PS_THDH_LM 0x07 /* Proximity threshold high */
  62. #define VCNL4040_ALS_THDL_LM 0x02 /* Ambient light threshold low */
  63. #define VCNL4040_ALS_THDH_LM 0x01 /* Ambient light threshold high */
  64. #define VCNL4200_PS_DATA 0x08 /* Proximity data */
  65. #define VCNL4200_AL_DATA 0x09 /* Ambient light data */
  66. #define VCNL4040_INT_FLAGS 0x0b /* Interrupt register */
  67. #define VCNL4200_INT_FLAGS 0x0d /* Interrupt register */
  68. #define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */
  69. #define VCNL4040_DEV_ID 0x0c /* Device ID and version */
  70. /* Bit masks for COMMAND register */
  71. #define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */
  72. #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */
  73. #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */
  74. #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */
  75. #define VCNL4000_ALS_EN BIT(2) /* start ALS measurement */
  76. #define VCNL4000_PROX_EN BIT(1) /* start proximity measurement */
  77. #define VCNL4000_SELF_TIMED_EN BIT(0) /* start self-timed measurement */
  78. #define VCNL4040_ALS_CONF_ALS_SHUTDOWN BIT(0)
  79. #define VCNL4040_ALS_CONF_IT GENMASK(7, 6) /* Ambient integration time */
  80. #define VCNL4040_ALS_CONF_INT_EN BIT(1) /* Ambient light Interrupt enable */
  81. #define VCNL4040_ALS_CONF_PERS GENMASK(3, 2) /* Ambient interrupt persistence setting */
  82. #define VCNL4040_PS_CONF1_PS_SHUTDOWN BIT(0)
  83. #define VCNL4040_PS_CONF2_PS_IT GENMASK(3, 1) /* Proximity integration time */
  84. #define VCNL4040_CONF1_PS_PERS GENMASK(5, 4) /* Proximity interrupt persistence setting */
  85. #define VCNL4040_PS_CONF2_PS_HD BIT(11) /* Proximity high definition */
  86. #define VCNL4040_PS_CONF2_PS_INT GENMASK(9, 8) /* Proximity interrupt mode */
  87. #define VCNL4040_PS_CONF3_MPS GENMASK(6, 5) /* Proximity multi pulse number */
  88. #define VCNL4040_PS_MS_LED_I GENMASK(10, 8) /* Proximity current */
  89. #define VCNL4040_PS_IF_AWAY BIT(8) /* Proximity event cross low threshold */
  90. #define VCNL4040_PS_IF_CLOSE BIT(9) /* Proximity event cross high threshold */
  91. #define VCNL4040_ALS_RISING BIT(12) /* Ambient Light cross high threshold */
  92. #define VCNL4040_ALS_FALLING BIT(13) /* Ambient Light cross low threshold */
  93. /* Bit masks for interrupt registers. */
  94. #define VCNL4010_INT_THR_SEL BIT(0) /* Select threshold interrupt source */
  95. #define VCNL4010_INT_THR_EN BIT(1) /* Threshold interrupt type */
  96. #define VCNL4010_INT_ALS_EN BIT(2) /* Enable on ALS data ready */
  97. #define VCNL4010_INT_PROX_EN BIT(3) /* Enable on proximity data ready */
  98. #define VCNL4010_INT_THR_HIGH 0 /* High threshold exceeded */
  99. #define VCNL4010_INT_THR_LOW 1 /* Low threshold exceeded */
  100. #define VCNL4010_INT_ALS 2 /* ALS data ready */
  101. #define VCNL4010_INT_PROXIMITY 3 /* Proximity data ready */
  102. #define VCNL4010_INT_THR \
  103. (BIT(VCNL4010_INT_THR_LOW) | BIT(VCNL4010_INT_THR_HIGH))
  104. #define VCNL4010_INT_DRDY \
  105. (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
  106. #define VCNL4040_CONF3_PS_MPS_16BITS 3 /* 8 multi pulses */
  107. #define VCNL4040_CONF3_PS_LED_I_16BITS 3 /* 120 mA */
  108. #define VCNL4040_CONF3_PS_SAMPLE_16BITS \
  109. (FIELD_PREP(VCNL4040_PS_CONF3_MPS, VCNL4040_CONF3_PS_MPS_16BITS) | \
  110. FIELD_PREP(VCNL4040_PS_MS_LED_I, VCNL4040_CONF3_PS_LED_I_16BITS))
  111. static const int vcnl4010_prox_sampling_frequency[][2] = {
  112. {1, 950000},
  113. {3, 906250},
  114. {7, 812500},
  115. {16, 625000},
  116. {31, 250000},
  117. {62, 500000},
  118. {125, 0},
  119. {250, 0},
  120. };
  121. static const int vcnl4040_ps_it_times[][2] = {
  122. {0, 100},
  123. {0, 150},
  124. {0, 200},
  125. {0, 250},
  126. {0, 300},
  127. {0, 350},
  128. {0, 400},
  129. {0, 800},
  130. };
  131. static const int vcnl4200_ps_it_times[][2] = {
  132. {0, 96},
  133. {0, 144},
  134. {0, 192},
  135. {0, 384},
  136. {0, 768},
  137. {0, 864},
  138. };
  139. static const int vcnl4040_als_it_times[][2] = {
  140. {0, 80000},
  141. {0, 160000},
  142. {0, 320000},
  143. {0, 640000},
  144. };
  145. static const int vcnl4200_als_it_times[][2] = {
  146. {0, 50000},
  147. {0, 100000},
  148. {0, 200000},
  149. {0, 400000},
  150. };
  151. static const int vcnl4040_ps_calibbias_ua[][2] = {
  152. {0, 50000},
  153. {0, 75000},
  154. {0, 100000},
  155. {0, 120000},
  156. {0, 140000},
  157. {0, 160000},
  158. {0, 180000},
  159. {0, 200000},
  160. };
  161. static const int vcnl4040_als_persistence[] = {1, 2, 4, 8};
  162. static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4};
  163. static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
  164. #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */
  165. enum vcnl4000_device_ids {
  166. VCNL4000,
  167. VCNL4010,
  168. VCNL4040,
  169. VCNL4200,
  170. };
  171. struct vcnl4200_channel {
  172. u8 reg;
  173. ktime_t last_measurement;
  174. ktime_t sampling_rate;
  175. struct mutex lock;
  176. };
  177. struct vcnl4000_data {
  178. struct i2c_client *client;
  179. enum vcnl4000_device_ids id;
  180. int rev;
  181. int al_scale;
  182. int ps_scale;
  183. u8 ps_int; /* proximity interrupt mode */
  184. u8 als_int; /* ambient light interrupt mode*/
  185. const struct vcnl4000_chip_spec *chip_spec;
  186. struct mutex vcnl4000_lock;
  187. struct vcnl4200_channel vcnl4200_al;
  188. struct vcnl4200_channel vcnl4200_ps;
  189. uint32_t near_level;
  190. };
  191. struct vcnl4000_chip_spec {
  192. const char *prod;
  193. struct iio_chan_spec const *channels;
  194. const int num_channels;
  195. const struct iio_info *info;
  196. const struct iio_buffer_setup_ops *buffer_setup_ops;
  197. int (*init)(struct vcnl4000_data *data);
  198. int (*measure_light)(struct vcnl4000_data *data, int *val);
  199. int (*measure_proximity)(struct vcnl4000_data *data, int *val);
  200. int (*set_power_state)(struct vcnl4000_data *data, bool on);
  201. irqreturn_t (*irq_thread)(int irq, void *priv);
  202. irqreturn_t (*trig_buffer_func)(int irq, void *priv);
  203. u8 int_reg;
  204. const int(*ps_it_times)[][2];
  205. const int num_ps_it_times;
  206. const int(*als_it_times)[][2];
  207. const int num_als_it_times;
  208. const unsigned int ulux_step;
  209. };
  210. static const struct i2c_device_id vcnl4000_id[] = {
  211. { "vcnl4000", VCNL4000 },
  212. { "vcnl4010", VCNL4010 },
  213. { "vcnl4020", VCNL4010 },
  214. { "vcnl4040", VCNL4040 },
  215. { "vcnl4200", VCNL4200 },
  216. { }
  217. };
  218. MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
  219. static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
  220. {
  221. /* no suspend op */
  222. return 0;
  223. }
  224. static int vcnl4000_init(struct vcnl4000_data *data)
  225. {
  226. int ret, prod_id;
  227. ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV);
  228. if (ret < 0)
  229. return ret;
  230. prod_id = ret >> 4;
  231. switch (prod_id) {
  232. case VCNL4000_PROD_ID:
  233. if (data->id != VCNL4000)
  234. dev_warn(&data->client->dev,
  235. "wrong device id, use vcnl4000");
  236. break;
  237. case VCNL4010_PROD_ID:
  238. if (data->id != VCNL4010)
  239. dev_warn(&data->client->dev,
  240. "wrong device id, use vcnl4010/4020");
  241. break;
  242. default:
  243. return -ENODEV;
  244. }
  245. data->rev = ret & 0xf;
  246. data->al_scale = 250000;
  247. return data->chip_spec->set_power_state(data, true);
  248. };
  249. static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en)
  250. {
  251. int ret;
  252. mutex_lock(&data->vcnl4000_lock);
  253. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  254. if (ret < 0)
  255. goto out;
  256. if (en)
  257. ret &= ~VCNL4040_ALS_CONF_ALS_SHUTDOWN;
  258. else
  259. ret |= VCNL4040_ALS_CONF_ALS_SHUTDOWN;
  260. ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, ret);
  261. out:
  262. mutex_unlock(&data->vcnl4000_lock);
  263. return ret;
  264. }
  265. static ssize_t vcnl4000_write_ps_enable(struct vcnl4000_data *data, bool en)
  266. {
  267. int ret;
  268. mutex_lock(&data->vcnl4000_lock);
  269. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  270. if (ret < 0)
  271. goto out;
  272. if (en)
  273. ret &= ~VCNL4040_PS_CONF1_PS_SHUTDOWN;
  274. else
  275. ret |= VCNL4040_PS_CONF1_PS_SHUTDOWN;
  276. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, ret);
  277. out:
  278. mutex_unlock(&data->vcnl4000_lock);
  279. return ret;
  280. }
  281. static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
  282. {
  283. int ret;
  284. /* Do not power down if interrupts are enabled */
  285. if (!on && (data->ps_int || data->als_int))
  286. return 0;
  287. ret = vcnl4000_write_als_enable(data, on);
  288. if (ret < 0)
  289. return ret;
  290. ret = vcnl4000_write_ps_enable(data, on);
  291. if (ret < 0)
  292. return ret;
  293. if (on) {
  294. /* Wait at least one integration cycle before fetching data */
  295. data->vcnl4200_al.last_measurement = ktime_get();
  296. data->vcnl4200_ps.last_measurement = ktime_get();
  297. }
  298. return 0;
  299. }
  300. static int vcnl4200_init(struct vcnl4000_data *data)
  301. {
  302. int ret, id;
  303. u16 regval;
  304. ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
  305. if (ret < 0)
  306. return ret;
  307. id = ret & 0xff;
  308. if (id != VCNL4200_PROD_ID) {
  309. ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
  310. if (ret < 0)
  311. return ret;
  312. id = ret & 0xff;
  313. if (id != VCNL4040_PROD_ID)
  314. return -ENODEV;
  315. }
  316. dev_dbg(&data->client->dev, "device id 0x%x", id);
  317. data->rev = (ret >> 8) & 0xf;
  318. data->ps_int = 0;
  319. data->als_int = 0;
  320. data->vcnl4200_al.reg = VCNL4200_AL_DATA;
  321. data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
  322. switch (id) {
  323. case VCNL4200_PROD_ID:
  324. /* Default wait time is 50ms, add 20% tolerance. */
  325. data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
  326. /* Default wait time is 4.8ms, add 20% tolerance. */
  327. data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
  328. break;
  329. case VCNL4040_PROD_ID:
  330. /* Default wait time is 80ms, add 20% tolerance. */
  331. data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
  332. /* Default wait time is 5ms, add 20% tolerance. */
  333. data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
  334. break;
  335. }
  336. data->al_scale = data->chip_spec->ulux_step;
  337. data->ps_scale = 16;
  338. mutex_init(&data->vcnl4200_al.lock);
  339. mutex_init(&data->vcnl4200_ps.lock);
  340. /* Use 16 bits proximity sensor readings */
  341. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  342. if (ret < 0)
  343. return ret;
  344. regval = ret | VCNL4040_PS_CONF2_PS_HD;
  345. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
  346. regval);
  347. if (ret < 0)
  348. return ret;
  349. /* Align proximity sensor sample rate to 16 bits data width */
  350. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
  351. if (ret < 0)
  352. return ret;
  353. regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;
  354. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
  355. regval);
  356. if (ret < 0)
  357. return ret;
  358. ret = data->chip_spec->set_power_state(data, true);
  359. if (ret < 0)
  360. return ret;
  361. return 0;
  362. };
  363. static int vcnl4000_read_data(struct vcnl4000_data *data, u8 data_reg, int *val)
  364. {
  365. s32 ret;
  366. ret = i2c_smbus_read_word_swapped(data->client, data_reg);
  367. if (ret < 0)
  368. return ret;
  369. *val = ret;
  370. return 0;
  371. }
  372. static int vcnl4000_write_data(struct vcnl4000_data *data, u8 data_reg, int val)
  373. {
  374. if (val > U16_MAX)
  375. return -ERANGE;
  376. return i2c_smbus_write_word_swapped(data->client, data_reg, val);
  377. }
  378. static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask,
  379. u8 rdy_mask, u8 data_reg, int *val)
  380. {
  381. int tries = 20;
  382. int ret;
  383. mutex_lock(&data->vcnl4000_lock);
  384. ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
  385. req_mask);
  386. if (ret < 0)
  387. goto fail;
  388. /* wait for data to become ready */
  389. while (tries--) {
  390. ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
  391. if (ret < 0)
  392. goto fail;
  393. if (ret & rdy_mask)
  394. break;
  395. msleep(20); /* measurement takes up to 100 ms */
  396. }
  397. if (tries < 0) {
  398. dev_err(&data->client->dev,
  399. "vcnl4000_measure() failed, data not ready\n");
  400. ret = -EIO;
  401. goto fail;
  402. }
  403. ret = vcnl4000_read_data(data, data_reg, val);
  404. if (ret < 0)
  405. goto fail;
  406. mutex_unlock(&data->vcnl4000_lock);
  407. return 0;
  408. fail:
  409. mutex_unlock(&data->vcnl4000_lock);
  410. return ret;
  411. }
  412. static int vcnl4200_measure(struct vcnl4000_data *data,
  413. struct vcnl4200_channel *chan, int *val)
  414. {
  415. int ret;
  416. s64 delta;
  417. ktime_t next_measurement;
  418. mutex_lock(&chan->lock);
  419. next_measurement = ktime_add(chan->last_measurement,
  420. chan->sampling_rate);
  421. delta = ktime_us_delta(next_measurement, ktime_get());
  422. if (delta > 0)
  423. usleep_range(delta, delta + 500);
  424. chan->last_measurement = ktime_get();
  425. mutex_unlock(&chan->lock);
  426. ret = i2c_smbus_read_word_data(data->client, chan->reg);
  427. if (ret < 0)
  428. return ret;
  429. *val = ret;
  430. return 0;
  431. }
  432. static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val)
  433. {
  434. return vcnl4000_measure(data,
  435. VCNL4000_AL_OD, VCNL4000_AL_RDY,
  436. VCNL4000_AL_RESULT_HI, val);
  437. }
  438. static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val)
  439. {
  440. return vcnl4200_measure(data, &data->vcnl4200_al, val);
  441. }
  442. static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val)
  443. {
  444. return vcnl4000_measure(data,
  445. VCNL4000_PS_OD, VCNL4000_PS_RDY,
  446. VCNL4000_PS_RESULT_HI, val);
  447. }
  448. static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val)
  449. {
  450. return vcnl4200_measure(data, &data->vcnl4200_ps, val);
  451. }
  452. static int vcnl4010_read_proxy_samp_freq(struct vcnl4000_data *data, int *val,
  453. int *val2)
  454. {
  455. int ret;
  456. ret = i2c_smbus_read_byte_data(data->client, VCNL4010_PROX_RATE);
  457. if (ret < 0)
  458. return ret;
  459. if (ret >= ARRAY_SIZE(vcnl4010_prox_sampling_frequency))
  460. return -EINVAL;
  461. *val = vcnl4010_prox_sampling_frequency[ret][0];
  462. *val2 = vcnl4010_prox_sampling_frequency[ret][1];
  463. return 0;
  464. }
  465. static bool vcnl4010_is_in_periodic_mode(struct vcnl4000_data *data)
  466. {
  467. int ret;
  468. ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND);
  469. if (ret < 0)
  470. return false;
  471. return !!(ret & VCNL4000_SELF_TIMED_EN);
  472. }
  473. static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
  474. {
  475. struct device *dev = &data->client->dev;
  476. int ret;
  477. if (on) {
  478. ret = pm_runtime_resume_and_get(dev);
  479. } else {
  480. pm_runtime_mark_last_busy(dev);
  481. ret = pm_runtime_put_autosuspend(dev);
  482. }
  483. return ret;
  484. }
  485. static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)
  486. {
  487. int ret;
  488. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  489. if (ret < 0)
  490. return ret;
  491. ret = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
  492. if (ret >= data->chip_spec->num_als_it_times)
  493. return -EINVAL;
  494. *val = (*data->chip_spec->als_it_times)[ret][0];
  495. *val2 = (*data->chip_spec->als_it_times)[ret][1];
  496. return 0;
  497. }
  498. static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)
  499. {
  500. unsigned int i;
  501. int ret;
  502. u16 regval;
  503. for (i = 0; i < data->chip_spec->num_als_it_times; i++) {
  504. if (val == (*data->chip_spec->als_it_times)[i][1])
  505. break;
  506. }
  507. if (i == data->chip_spec->num_als_it_times)
  508. return -EINVAL;
  509. data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200);
  510. data->al_scale = div_u64(mul_u32_u32(data->chip_spec->ulux_step,
  511. (*data->chip_spec->als_it_times)[0][1]),
  512. val);
  513. mutex_lock(&data->vcnl4000_lock);
  514. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  515. if (ret < 0)
  516. goto out_unlock;
  517. regval = FIELD_PREP(VCNL4040_ALS_CONF_IT, i);
  518. regval |= (ret & ~VCNL4040_ALS_CONF_IT);
  519. ret = i2c_smbus_write_word_data(data->client,
  520. VCNL4200_AL_CONF,
  521. regval);
  522. out_unlock:
  523. mutex_unlock(&data->vcnl4000_lock);
  524. return ret;
  525. }
  526. static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
  527. {
  528. int ret;
  529. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  530. if (ret < 0)
  531. return ret;
  532. ret = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
  533. if (ret >= data->chip_spec->num_ps_it_times)
  534. return -EINVAL;
  535. *val = (*data->chip_spec->ps_it_times)[ret][0];
  536. *val2 = (*data->chip_spec->ps_it_times)[ret][1];
  537. return 0;
  538. }
  539. static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
  540. {
  541. unsigned int i;
  542. int ret, index = -1;
  543. u16 regval;
  544. for (i = 0; i < data->chip_spec->num_ps_it_times; i++) {
  545. if (val == (*data->chip_spec->ps_it_times)[i][1]) {
  546. index = i;
  547. break;
  548. }
  549. }
  550. if (index < 0)
  551. return -EINVAL;
  552. data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60 * NSEC_PER_USEC);
  553. mutex_lock(&data->vcnl4000_lock);
  554. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  555. if (ret < 0)
  556. goto out;
  557. regval = (ret & ~VCNL4040_PS_CONF2_PS_IT) |
  558. FIELD_PREP(VCNL4040_PS_CONF2_PS_IT, index);
  559. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
  560. regval);
  561. out:
  562. mutex_unlock(&data->vcnl4000_lock);
  563. return ret;
  564. }
  565. static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2)
  566. {
  567. int ret, ret_pers, it;
  568. int64_t val_c;
  569. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  570. if (ret < 0)
  571. return ret;
  572. ret_pers = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);
  573. if (ret_pers >= ARRAY_SIZE(vcnl4040_als_persistence))
  574. return -EINVAL;
  575. it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
  576. if (it >= data->chip_spec->num_als_it_times)
  577. return -EINVAL;
  578. val_c = mul_u32_u32((*data->chip_spec->als_it_times)[it][1],
  579. vcnl4040_als_persistence[ret_pers]);
  580. *val = div_u64_rem(val_c, MICRO, val2);
  581. return IIO_VAL_INT_PLUS_MICRO;
  582. }
  583. static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, int val2)
  584. {
  585. unsigned int i;
  586. int ret, it;
  587. u16 regval;
  588. u64 val_n = mul_u32_u32(val, MICRO) + val2;
  589. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  590. if (ret < 0)
  591. return ret;
  592. it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
  593. if (it >= data->chip_spec->num_als_it_times)
  594. return -EINVAL;
  595. for (i = 0; i < ARRAY_SIZE(vcnl4040_als_persistence) - 1; i++) {
  596. if (val_n < mul_u32_u32(vcnl4040_als_persistence[i],
  597. (*data->chip_spec->als_it_times)[it][1]))
  598. break;
  599. }
  600. mutex_lock(&data->vcnl4000_lock);
  601. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  602. if (ret < 0)
  603. goto out_unlock;
  604. regval = FIELD_PREP(VCNL4040_ALS_CONF_PERS, i);
  605. regval |= (ret & ~VCNL4040_ALS_CONF_PERS);
  606. ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
  607. regval);
  608. out_unlock:
  609. mutex_unlock(&data->vcnl4000_lock);
  610. return ret;
  611. }
  612. static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2)
  613. {
  614. int ret, ret_pers, it;
  615. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  616. if (ret < 0)
  617. return ret;
  618. ret_pers = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);
  619. if (ret_pers >= ARRAY_SIZE(vcnl4040_ps_persistence))
  620. return -EINVAL;
  621. it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
  622. if (it >= data->chip_spec->num_ps_it_times)
  623. return -EINVAL;
  624. *val = (*data->chip_spec->ps_it_times)[it][0];
  625. *val2 = (*data->chip_spec->ps_it_times)[it][1] *
  626. vcnl4040_ps_persistence[ret_pers];
  627. return IIO_VAL_INT_PLUS_MICRO;
  628. }
  629. static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int val2)
  630. {
  631. int ret, it, i;
  632. u16 regval;
  633. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  634. if (ret < 0)
  635. return ret;
  636. it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
  637. if (it >= data->chip_spec->num_ps_it_times)
  638. return -EINVAL;
  639. if (val > 0)
  640. i = ARRAY_SIZE(vcnl4040_ps_persistence) - 1;
  641. else {
  642. for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_persistence) - 1; i++) {
  643. if (val2 <= vcnl4040_ps_persistence[i] *
  644. (*data->chip_spec->ps_it_times)[it][1])
  645. break;
  646. }
  647. }
  648. mutex_lock(&data->vcnl4000_lock);
  649. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  650. if (ret < 0)
  651. goto out_unlock;
  652. regval = FIELD_PREP(VCNL4040_CONF1_PS_PERS, i);
  653. regval |= (ret & ~VCNL4040_CONF1_PS_PERS);
  654. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
  655. regval);
  656. out_unlock:
  657. mutex_unlock(&data->vcnl4000_lock);
  658. return ret;
  659. }
  660. static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
  661. {
  662. int ret;
  663. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
  664. if (ret < 0)
  665. return ret;
  666. ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);
  667. if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
  668. return -EINVAL;
  669. *val = vcnl4040_ps_oversampling_ratio[ret];
  670. return ret;
  671. }
  672. static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
  673. {
  674. unsigned int i;
  675. int ret;
  676. u16 regval;
  677. for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {
  678. if (val == vcnl4040_ps_oversampling_ratio[i])
  679. break;
  680. }
  681. if (i >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
  682. return -EINVAL;
  683. mutex_lock(&data->vcnl4000_lock);
  684. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
  685. if (ret < 0)
  686. goto out_unlock;
  687. regval = FIELD_PREP(VCNL4040_PS_CONF3_MPS, i);
  688. regval |= (ret & ~VCNL4040_PS_CONF3_MPS);
  689. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
  690. regval);
  691. out_unlock:
  692. mutex_unlock(&data->vcnl4000_lock);
  693. return ret;
  694. }
  695. static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)
  696. {
  697. int ret;
  698. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
  699. if (ret < 0)
  700. return ret;
  701. ret = FIELD_GET(VCNL4040_PS_MS_LED_I, ret);
  702. if (ret >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
  703. return -EINVAL;
  704. *val = vcnl4040_ps_calibbias_ua[ret][0];
  705. *val2 = vcnl4040_ps_calibbias_ua[ret][1];
  706. return ret;
  707. }
  708. static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)
  709. {
  710. unsigned int i;
  711. int ret;
  712. u16 regval;
  713. for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) {
  714. if (val == vcnl4040_ps_calibbias_ua[i][1])
  715. break;
  716. }
  717. if (i >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
  718. return -EINVAL;
  719. mutex_lock(&data->vcnl4000_lock);
  720. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
  721. if (ret < 0)
  722. goto out_unlock;
  723. regval = (ret & ~VCNL4040_PS_MS_LED_I);
  724. regval |= FIELD_PREP(VCNL4040_PS_MS_LED_I, i);
  725. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
  726. regval);
  727. out_unlock:
  728. mutex_unlock(&data->vcnl4000_lock);
  729. return ret;
  730. }
  731. static int vcnl4000_read_raw(struct iio_dev *indio_dev,
  732. struct iio_chan_spec const *chan,
  733. int *val, int *val2, long mask)
  734. {
  735. int ret;
  736. struct vcnl4000_data *data = iio_priv(indio_dev);
  737. switch (mask) {
  738. case IIO_CHAN_INFO_RAW:
  739. ret = vcnl4000_set_pm_runtime_state(data, true);
  740. if (ret < 0)
  741. return ret;
  742. switch (chan->type) {
  743. case IIO_LIGHT:
  744. ret = data->chip_spec->measure_light(data, val);
  745. if (!ret)
  746. ret = IIO_VAL_INT;
  747. break;
  748. case IIO_PROXIMITY:
  749. ret = data->chip_spec->measure_proximity(data, val);
  750. *val2 = data->ps_scale;
  751. if (!ret)
  752. ret = IIO_VAL_FRACTIONAL;
  753. break;
  754. default:
  755. ret = -EINVAL;
  756. }
  757. vcnl4000_set_pm_runtime_state(data, false);
  758. return ret;
  759. case IIO_CHAN_INFO_SCALE:
  760. if (chan->type != IIO_LIGHT)
  761. return -EINVAL;
  762. *val = 0;
  763. *val2 = data->al_scale;
  764. return IIO_VAL_INT_PLUS_MICRO;
  765. case IIO_CHAN_INFO_INT_TIME:
  766. switch (chan->type) {
  767. case IIO_LIGHT:
  768. ret = vcnl4040_read_als_it(data, val, val2);
  769. break;
  770. case IIO_PROXIMITY:
  771. ret = vcnl4040_read_ps_it(data, val, val2);
  772. break;
  773. default:
  774. return -EINVAL;
  775. }
  776. if (ret < 0)
  777. return ret;
  778. return IIO_VAL_INT_PLUS_MICRO;
  779. case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
  780. switch (chan->type) {
  781. case IIO_PROXIMITY:
  782. ret = vcnl4040_read_ps_oversampling_ratio(data, val);
  783. if (ret < 0)
  784. return ret;
  785. return IIO_VAL_INT;
  786. default:
  787. return -EINVAL;
  788. }
  789. case IIO_CHAN_INFO_CALIBBIAS:
  790. switch (chan->type) {
  791. case IIO_PROXIMITY:
  792. ret = vcnl4040_read_ps_calibbias(data, val, val2);
  793. if (ret < 0)
  794. return ret;
  795. return IIO_VAL_INT_PLUS_MICRO;
  796. default:
  797. return -EINVAL;
  798. }
  799. default:
  800. return -EINVAL;
  801. }
  802. }
  803. static int vcnl4040_write_raw(struct iio_dev *indio_dev,
  804. struct iio_chan_spec const *chan,
  805. int val, int val2, long mask)
  806. {
  807. struct vcnl4000_data *data = iio_priv(indio_dev);
  808. switch (mask) {
  809. case IIO_CHAN_INFO_INT_TIME:
  810. if (val != 0)
  811. return -EINVAL;
  812. switch (chan->type) {
  813. case IIO_LIGHT:
  814. return vcnl4040_write_als_it(data, val2);
  815. case IIO_PROXIMITY:
  816. return vcnl4040_write_ps_it(data, val2);
  817. default:
  818. return -EINVAL;
  819. }
  820. case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
  821. switch (chan->type) {
  822. case IIO_PROXIMITY:
  823. return vcnl4040_write_ps_oversampling_ratio(data, val);
  824. default:
  825. return -EINVAL;
  826. }
  827. case IIO_CHAN_INFO_CALIBBIAS:
  828. switch (chan->type) {
  829. case IIO_PROXIMITY:
  830. return vcnl4040_write_ps_calibbias(data, val2);
  831. default:
  832. return -EINVAL;
  833. }
  834. default:
  835. return -EINVAL;
  836. }
  837. }
  838. static int vcnl4040_read_avail(struct iio_dev *indio_dev,
  839. struct iio_chan_spec const *chan,
  840. const int **vals, int *type, int *length,
  841. long mask)
  842. {
  843. struct vcnl4000_data *data = iio_priv(indio_dev);
  844. switch (mask) {
  845. case IIO_CHAN_INFO_INT_TIME:
  846. switch (chan->type) {
  847. case IIO_LIGHT:
  848. *vals = (int *)(*data->chip_spec->als_it_times);
  849. *length = 2 * data->chip_spec->num_als_it_times;
  850. break;
  851. case IIO_PROXIMITY:
  852. *vals = (int *)(*data->chip_spec->ps_it_times);
  853. *length = 2 * data->chip_spec->num_ps_it_times;
  854. break;
  855. default:
  856. return -EINVAL;
  857. }
  858. *type = IIO_VAL_INT_PLUS_MICRO;
  859. return IIO_AVAIL_LIST;
  860. case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
  861. switch (chan->type) {
  862. case IIO_PROXIMITY:
  863. *vals = (int *)vcnl4040_ps_oversampling_ratio;
  864. *length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);
  865. *type = IIO_VAL_INT;
  866. return IIO_AVAIL_LIST;
  867. default:
  868. return -EINVAL;
  869. }
  870. case IIO_CHAN_INFO_CALIBBIAS:
  871. switch (chan->type) {
  872. case IIO_PROXIMITY:
  873. *vals = (int *)vcnl4040_ps_calibbias_ua;
  874. *length = 2 * ARRAY_SIZE(vcnl4040_ps_calibbias_ua);
  875. *type = IIO_VAL_INT_PLUS_MICRO;
  876. return IIO_AVAIL_LIST;
  877. default:
  878. return -EINVAL;
  879. }
  880. default:
  881. return -EINVAL;
  882. }
  883. }
  884. static int vcnl4010_read_raw(struct iio_dev *indio_dev,
  885. struct iio_chan_spec const *chan,
  886. int *val, int *val2, long mask)
  887. {
  888. int ret;
  889. struct vcnl4000_data *data = iio_priv(indio_dev);
  890. switch (mask) {
  891. case IIO_CHAN_INFO_RAW:
  892. case IIO_CHAN_INFO_SCALE:
  893. ret = iio_device_claim_direct_mode(indio_dev);
  894. if (ret)
  895. return ret;
  896. /* Protect against event capture. */
  897. if (vcnl4010_is_in_periodic_mode(data)) {
  898. ret = -EBUSY;
  899. } else {
  900. ret = vcnl4000_read_raw(indio_dev, chan, val, val2,
  901. mask);
  902. }
  903. iio_device_release_direct_mode(indio_dev);
  904. return ret;
  905. case IIO_CHAN_INFO_SAMP_FREQ:
  906. switch (chan->type) {
  907. case IIO_PROXIMITY:
  908. ret = vcnl4010_read_proxy_samp_freq(data, val, val2);
  909. if (ret < 0)
  910. return ret;
  911. return IIO_VAL_INT_PLUS_MICRO;
  912. default:
  913. return -EINVAL;
  914. }
  915. default:
  916. return -EINVAL;
  917. }
  918. }
  919. static int vcnl4010_read_avail(struct iio_dev *indio_dev,
  920. struct iio_chan_spec const *chan,
  921. const int **vals, int *type, int *length,
  922. long mask)
  923. {
  924. switch (mask) {
  925. case IIO_CHAN_INFO_SAMP_FREQ:
  926. *vals = (int *)vcnl4010_prox_sampling_frequency;
  927. *type = IIO_VAL_INT_PLUS_MICRO;
  928. *length = 2 * ARRAY_SIZE(vcnl4010_prox_sampling_frequency);
  929. return IIO_AVAIL_LIST;
  930. default:
  931. return -EINVAL;
  932. }
  933. }
  934. static int vcnl4010_write_proxy_samp_freq(struct vcnl4000_data *data, int val,
  935. int val2)
  936. {
  937. unsigned int i;
  938. int index = -1;
  939. for (i = 0; i < ARRAY_SIZE(vcnl4010_prox_sampling_frequency); i++) {
  940. if (val == vcnl4010_prox_sampling_frequency[i][0] &&
  941. val2 == vcnl4010_prox_sampling_frequency[i][1]) {
  942. index = i;
  943. break;
  944. }
  945. }
  946. if (index < 0)
  947. return -EINVAL;
  948. return i2c_smbus_write_byte_data(data->client, VCNL4010_PROX_RATE,
  949. index);
  950. }
  951. static int vcnl4010_write_raw(struct iio_dev *indio_dev,
  952. struct iio_chan_spec const *chan,
  953. int val, int val2, long mask)
  954. {
  955. int ret;
  956. struct vcnl4000_data *data = iio_priv(indio_dev);
  957. ret = iio_device_claim_direct_mode(indio_dev);
  958. if (ret)
  959. return ret;
  960. /* Protect against event capture. */
  961. if (vcnl4010_is_in_periodic_mode(data)) {
  962. ret = -EBUSY;
  963. goto end;
  964. }
  965. switch (mask) {
  966. case IIO_CHAN_INFO_SAMP_FREQ:
  967. switch (chan->type) {
  968. case IIO_PROXIMITY:
  969. ret = vcnl4010_write_proxy_samp_freq(data, val, val2);
  970. goto end;
  971. default:
  972. ret = -EINVAL;
  973. goto end;
  974. }
  975. default:
  976. ret = -EINVAL;
  977. goto end;
  978. }
  979. end:
  980. iio_device_release_direct_mode(indio_dev);
  981. return ret;
  982. }
  983. static int vcnl4010_read_event(struct iio_dev *indio_dev,
  984. const struct iio_chan_spec *chan,
  985. enum iio_event_type type,
  986. enum iio_event_direction dir,
  987. enum iio_event_info info,
  988. int *val, int *val2)
  989. {
  990. int ret;
  991. struct vcnl4000_data *data = iio_priv(indio_dev);
  992. switch (info) {
  993. case IIO_EV_INFO_VALUE:
  994. switch (dir) {
  995. case IIO_EV_DIR_RISING:
  996. ret = vcnl4000_read_data(data, VCNL4010_HIGH_THR_HI,
  997. val);
  998. if (ret < 0)
  999. return ret;
  1000. return IIO_VAL_INT;
  1001. case IIO_EV_DIR_FALLING:
  1002. ret = vcnl4000_read_data(data, VCNL4010_LOW_THR_HI,
  1003. val);
  1004. if (ret < 0)
  1005. return ret;
  1006. return IIO_VAL_INT;
  1007. default:
  1008. return -EINVAL;
  1009. }
  1010. default:
  1011. return -EINVAL;
  1012. }
  1013. }
  1014. static int vcnl4010_write_event(struct iio_dev *indio_dev,
  1015. const struct iio_chan_spec *chan,
  1016. enum iio_event_type type,
  1017. enum iio_event_direction dir,
  1018. enum iio_event_info info,
  1019. int val, int val2)
  1020. {
  1021. int ret;
  1022. struct vcnl4000_data *data = iio_priv(indio_dev);
  1023. switch (info) {
  1024. case IIO_EV_INFO_VALUE:
  1025. switch (dir) {
  1026. case IIO_EV_DIR_RISING:
  1027. ret = vcnl4000_write_data(data, VCNL4010_HIGH_THR_HI,
  1028. val);
  1029. if (ret < 0)
  1030. return ret;
  1031. return IIO_VAL_INT;
  1032. case IIO_EV_DIR_FALLING:
  1033. ret = vcnl4000_write_data(data, VCNL4010_LOW_THR_HI,
  1034. val);
  1035. if (ret < 0)
  1036. return ret;
  1037. return IIO_VAL_INT;
  1038. default:
  1039. return -EINVAL;
  1040. }
  1041. default:
  1042. return -EINVAL;
  1043. }
  1044. }
  1045. static int vcnl4040_read_event(struct iio_dev *indio_dev,
  1046. const struct iio_chan_spec *chan,
  1047. enum iio_event_type type,
  1048. enum iio_event_direction dir,
  1049. enum iio_event_info info,
  1050. int *val, int *val2)
  1051. {
  1052. int ret;
  1053. struct vcnl4000_data *data = iio_priv(indio_dev);
  1054. switch (chan->type) {
  1055. case IIO_LIGHT:
  1056. switch (info) {
  1057. case IIO_EV_INFO_PERIOD:
  1058. return vcnl4040_read_als_period(data, val, val2);
  1059. case IIO_EV_INFO_VALUE:
  1060. switch (dir) {
  1061. case IIO_EV_DIR_RISING:
  1062. ret = i2c_smbus_read_word_data(data->client,
  1063. VCNL4040_ALS_THDH_LM);
  1064. break;
  1065. case IIO_EV_DIR_FALLING:
  1066. ret = i2c_smbus_read_word_data(data->client,
  1067. VCNL4040_ALS_THDL_LM);
  1068. break;
  1069. default:
  1070. return -EINVAL;
  1071. }
  1072. break;
  1073. default:
  1074. return -EINVAL;
  1075. }
  1076. break;
  1077. case IIO_PROXIMITY:
  1078. switch (info) {
  1079. case IIO_EV_INFO_PERIOD:
  1080. return vcnl4040_read_ps_period(data, val, val2);
  1081. case IIO_EV_INFO_VALUE:
  1082. switch (dir) {
  1083. case IIO_EV_DIR_RISING:
  1084. ret = i2c_smbus_read_word_data(data->client,
  1085. VCNL4040_PS_THDH_LM);
  1086. break;
  1087. case IIO_EV_DIR_FALLING:
  1088. ret = i2c_smbus_read_word_data(data->client,
  1089. VCNL4040_PS_THDL_LM);
  1090. break;
  1091. default:
  1092. return -EINVAL;
  1093. }
  1094. break;
  1095. default:
  1096. return -EINVAL;
  1097. }
  1098. break;
  1099. default:
  1100. return -EINVAL;
  1101. }
  1102. if (ret < 0)
  1103. return ret;
  1104. *val = ret;
  1105. return IIO_VAL_INT;
  1106. }
  1107. static int vcnl4040_write_event(struct iio_dev *indio_dev,
  1108. const struct iio_chan_spec *chan,
  1109. enum iio_event_type type,
  1110. enum iio_event_direction dir,
  1111. enum iio_event_info info,
  1112. int val, int val2)
  1113. {
  1114. int ret;
  1115. struct vcnl4000_data *data = iio_priv(indio_dev);
  1116. switch (chan->type) {
  1117. case IIO_LIGHT:
  1118. switch (info) {
  1119. case IIO_EV_INFO_PERIOD:
  1120. return vcnl4040_write_als_period(data, val, val2);
  1121. case IIO_EV_INFO_VALUE:
  1122. switch (dir) {
  1123. case IIO_EV_DIR_RISING:
  1124. ret = i2c_smbus_write_word_data(data->client,
  1125. VCNL4040_ALS_THDH_LM,
  1126. val);
  1127. break;
  1128. case IIO_EV_DIR_FALLING:
  1129. ret = i2c_smbus_write_word_data(data->client,
  1130. VCNL4040_ALS_THDL_LM,
  1131. val);
  1132. break;
  1133. default:
  1134. return -EINVAL;
  1135. }
  1136. break;
  1137. default:
  1138. return -EINVAL;
  1139. }
  1140. break;
  1141. case IIO_PROXIMITY:
  1142. switch (info) {
  1143. case IIO_EV_INFO_PERIOD:
  1144. return vcnl4040_write_ps_period(data, val, val2);
  1145. case IIO_EV_INFO_VALUE:
  1146. switch (dir) {
  1147. case IIO_EV_DIR_RISING:
  1148. ret = i2c_smbus_write_word_data(data->client,
  1149. VCNL4040_PS_THDH_LM,
  1150. val);
  1151. break;
  1152. case IIO_EV_DIR_FALLING:
  1153. ret = i2c_smbus_write_word_data(data->client,
  1154. VCNL4040_PS_THDL_LM,
  1155. val);
  1156. break;
  1157. default:
  1158. return -EINVAL;
  1159. }
  1160. break;
  1161. default:
  1162. return -EINVAL;
  1163. }
  1164. break;
  1165. default:
  1166. return -EINVAL;
  1167. }
  1168. if (ret < 0)
  1169. return ret;
  1170. return IIO_VAL_INT;
  1171. }
  1172. static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
  1173. {
  1174. int ret;
  1175. ret = i2c_smbus_read_byte_data(data->client, VCNL4010_INT_CTRL);
  1176. if (ret < 0)
  1177. return false;
  1178. return !!(ret & VCNL4010_INT_THR_EN);
  1179. }
  1180. static int vcnl4010_read_event_config(struct iio_dev *indio_dev,
  1181. const struct iio_chan_spec *chan,
  1182. enum iio_event_type type,
  1183. enum iio_event_direction dir)
  1184. {
  1185. struct vcnl4000_data *data = iio_priv(indio_dev);
  1186. switch (chan->type) {
  1187. case IIO_PROXIMITY:
  1188. return vcnl4010_is_thr_enabled(data);
  1189. default:
  1190. return -EINVAL;
  1191. }
  1192. }
  1193. static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state)
  1194. {
  1195. struct vcnl4000_data *data = iio_priv(indio_dev);
  1196. int ret;
  1197. int icr;
  1198. int command;
  1199. if (state) {
  1200. ret = iio_device_claim_direct_mode(indio_dev);
  1201. if (ret)
  1202. return ret;
  1203. /* Enable periodic measurement of proximity data. */
  1204. command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
  1205. /*
  1206. * Enable interrupts on threshold, for proximity data by
  1207. * default.
  1208. */
  1209. icr = VCNL4010_INT_THR_EN;
  1210. } else {
  1211. if (!vcnl4010_is_thr_enabled(data))
  1212. return 0;
  1213. command = 0;
  1214. icr = 0;
  1215. }
  1216. ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND,
  1217. command);
  1218. if (ret < 0)
  1219. goto end;
  1220. ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr);
  1221. end:
  1222. if (state)
  1223. iio_device_release_direct_mode(indio_dev);
  1224. return ret;
  1225. }
  1226. static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
  1227. const struct iio_chan_spec *chan,
  1228. enum iio_event_type type,
  1229. enum iio_event_direction dir,
  1230. int state)
  1231. {
  1232. switch (chan->type) {
  1233. case IIO_PROXIMITY:
  1234. return vcnl4010_config_threshold(indio_dev, state);
  1235. default:
  1236. return -EINVAL;
  1237. }
  1238. }
  1239. static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
  1240. const struct iio_chan_spec *chan,
  1241. enum iio_event_type type,
  1242. enum iio_event_direction dir)
  1243. {
  1244. int ret;
  1245. struct vcnl4000_data *data = iio_priv(indio_dev);
  1246. switch (chan->type) {
  1247. case IIO_LIGHT:
  1248. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  1249. if (ret < 0)
  1250. return ret;
  1251. data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);
  1252. return data->als_int;
  1253. case IIO_PROXIMITY:
  1254. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  1255. if (ret < 0)
  1256. return ret;
  1257. data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
  1258. return (dir == IIO_EV_DIR_RISING) ?
  1259. FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
  1260. FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
  1261. default:
  1262. return -EINVAL;
  1263. }
  1264. }
  1265. static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
  1266. const struct iio_chan_spec *chan,
  1267. enum iio_event_type type,
  1268. enum iio_event_direction dir, int state)
  1269. {
  1270. int ret = -EINVAL;
  1271. u16 val, mask;
  1272. struct vcnl4000_data *data = iio_priv(indio_dev);
  1273. mutex_lock(&data->vcnl4000_lock);
  1274. switch (chan->type) {
  1275. case IIO_LIGHT:
  1276. ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
  1277. if (ret < 0)
  1278. goto out;
  1279. mask = VCNL4040_ALS_CONF_INT_EN;
  1280. if (state)
  1281. val = (ret | mask);
  1282. else
  1283. val = (ret & ~mask);
  1284. data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);
  1285. ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
  1286. val);
  1287. break;
  1288. case IIO_PROXIMITY:
  1289. ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
  1290. if (ret < 0)
  1291. goto out;
  1292. if (dir == IIO_EV_DIR_RISING)
  1293. mask = VCNL4040_PS_IF_AWAY;
  1294. else
  1295. mask = VCNL4040_PS_IF_CLOSE;
  1296. val = state ? (ret | mask) : (ret & ~mask);
  1297. data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
  1298. ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
  1299. val);
  1300. break;
  1301. default:
  1302. break;
  1303. }
  1304. out:
  1305. mutex_unlock(&data->vcnl4000_lock);
  1306. return ret;
  1307. }
  1308. static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
  1309. {
  1310. struct iio_dev *indio_dev = p;
  1311. struct vcnl4000_data *data = iio_priv(indio_dev);
  1312. int ret;
  1313. ret = i2c_smbus_read_word_data(data->client, data->chip_spec->int_reg);
  1314. if (ret < 0)
  1315. return IRQ_HANDLED;
  1316. if (ret & VCNL4040_PS_IF_CLOSE) {
  1317. iio_push_event(indio_dev,
  1318. IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
  1319. IIO_EV_TYPE_THRESH,
  1320. IIO_EV_DIR_RISING),
  1321. iio_get_time_ns(indio_dev));
  1322. }
  1323. if (ret & VCNL4040_PS_IF_AWAY) {
  1324. iio_push_event(indio_dev,
  1325. IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
  1326. IIO_EV_TYPE_THRESH,
  1327. IIO_EV_DIR_FALLING),
  1328. iio_get_time_ns(indio_dev));
  1329. }
  1330. if (ret & VCNL4040_ALS_FALLING) {
  1331. iio_push_event(indio_dev,
  1332. IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
  1333. IIO_EV_TYPE_THRESH,
  1334. IIO_EV_DIR_FALLING),
  1335. iio_get_time_ns(indio_dev));
  1336. }
  1337. if (ret & VCNL4040_ALS_RISING) {
  1338. iio_push_event(indio_dev,
  1339. IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
  1340. IIO_EV_TYPE_THRESH,
  1341. IIO_EV_DIR_RISING),
  1342. iio_get_time_ns(indio_dev));
  1343. }
  1344. return IRQ_HANDLED;
  1345. }
  1346. static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
  1347. uintptr_t priv,
  1348. const struct iio_chan_spec *chan,
  1349. char *buf)
  1350. {
  1351. struct vcnl4000_data *data = iio_priv(indio_dev);
  1352. return sprintf(buf, "%u\n", data->near_level);
  1353. }
  1354. static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
  1355. {
  1356. struct iio_dev *indio_dev = p;
  1357. struct vcnl4000_data *data = iio_priv(indio_dev);
  1358. unsigned long isr;
  1359. int ret;
  1360. ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
  1361. if (ret < 0)
  1362. goto end;
  1363. isr = ret;
  1364. if (isr & VCNL4010_INT_THR) {
  1365. if (test_bit(VCNL4010_INT_THR_LOW, &isr)) {
  1366. iio_push_event(indio_dev,
  1367. IIO_UNMOD_EVENT_CODE(
  1368. IIO_PROXIMITY,
  1369. 1,
  1370. IIO_EV_TYPE_THRESH,
  1371. IIO_EV_DIR_FALLING),
  1372. iio_get_time_ns(indio_dev));
  1373. }
  1374. if (test_bit(VCNL4010_INT_THR_HIGH, &isr)) {
  1375. iio_push_event(indio_dev,
  1376. IIO_UNMOD_EVENT_CODE(
  1377. IIO_PROXIMITY,
  1378. 1,
  1379. IIO_EV_TYPE_THRESH,
  1380. IIO_EV_DIR_RISING),
  1381. iio_get_time_ns(indio_dev));
  1382. }
  1383. i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
  1384. isr & VCNL4010_INT_THR);
  1385. }
  1386. if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
  1387. iio_trigger_poll_nested(indio_dev->trig);
  1388. end:
  1389. return IRQ_HANDLED;
  1390. }
  1391. static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
  1392. {
  1393. struct iio_poll_func *pf = p;
  1394. struct iio_dev *indio_dev = pf->indio_dev;
  1395. struct vcnl4000_data *data = iio_priv(indio_dev);
  1396. const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
  1397. u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
  1398. bool data_read = false;
  1399. unsigned long isr;
  1400. int val = 0;
  1401. int ret;
  1402. ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
  1403. if (ret < 0)
  1404. goto end;
  1405. isr = ret;
  1406. if (test_bit(0, active_scan_mask)) {
  1407. if (test_bit(VCNL4010_INT_PROXIMITY, &isr)) {
  1408. ret = vcnl4000_read_data(data,
  1409. VCNL4000_PS_RESULT_HI,
  1410. &val);
  1411. if (ret < 0)
  1412. goto end;
  1413. buffer[0] = val;
  1414. data_read = true;
  1415. }
  1416. }
  1417. ret = i2c_smbus_write_byte_data(data->client, VCNL4010_ISR,
  1418. isr & VCNL4010_INT_DRDY);
  1419. if (ret < 0)
  1420. goto end;
  1421. if (!data_read)
  1422. goto end;
  1423. iio_push_to_buffers_with_timestamp(indio_dev, buffer,
  1424. iio_get_time_ns(indio_dev));
  1425. end:
  1426. iio_trigger_notify_done(indio_dev->trig);
  1427. return IRQ_HANDLED;
  1428. }
  1429. static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev)
  1430. {
  1431. struct vcnl4000_data *data = iio_priv(indio_dev);
  1432. int ret;
  1433. int cmd;
  1434. /* Do not enable the buffer if we are already capturing events. */
  1435. if (vcnl4010_is_in_periodic_mode(data))
  1436. return -EBUSY;
  1437. ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL,
  1438. VCNL4010_INT_PROX_EN);
  1439. if (ret < 0)
  1440. return ret;
  1441. cmd = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN;
  1442. return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, cmd);
  1443. }
  1444. static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
  1445. {
  1446. struct vcnl4000_data *data = iio_priv(indio_dev);
  1447. int ret;
  1448. ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0);
  1449. if (ret < 0)
  1450. return ret;
  1451. return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
  1452. }
  1453. static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
  1454. .postenable = &vcnl4010_buffer_postenable,
  1455. .predisable = &vcnl4010_buffer_predisable,
  1456. };
  1457. static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
  1458. {
  1459. .name = "nearlevel",
  1460. .shared = IIO_SEPARATE,
  1461. .read = vcnl4000_read_near_level,
  1462. },
  1463. { /* sentinel */ }
  1464. };
  1465. static const struct iio_event_spec vcnl4000_event_spec[] = {
  1466. {
  1467. .type = IIO_EV_TYPE_THRESH,
  1468. .dir = IIO_EV_DIR_RISING,
  1469. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  1470. }, {
  1471. .type = IIO_EV_TYPE_THRESH,
  1472. .dir = IIO_EV_DIR_FALLING,
  1473. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  1474. }, {
  1475. .type = IIO_EV_TYPE_THRESH,
  1476. .dir = IIO_EV_DIR_EITHER,
  1477. .mask_separate = BIT(IIO_EV_INFO_ENABLE),
  1478. }
  1479. };
  1480. static const struct iio_event_spec vcnl4040_als_event_spec[] = {
  1481. {
  1482. .type = IIO_EV_TYPE_THRESH,
  1483. .dir = IIO_EV_DIR_RISING,
  1484. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  1485. }, {
  1486. .type = IIO_EV_TYPE_THRESH,
  1487. .dir = IIO_EV_DIR_FALLING,
  1488. .mask_separate = BIT(IIO_EV_INFO_VALUE),
  1489. }, {
  1490. .type = IIO_EV_TYPE_THRESH,
  1491. .dir = IIO_EV_DIR_EITHER,
  1492. .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD),
  1493. },
  1494. };
  1495. static const struct iio_event_spec vcnl4040_event_spec[] = {
  1496. {
  1497. .type = IIO_EV_TYPE_THRESH,
  1498. .dir = IIO_EV_DIR_RISING,
  1499. .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
  1500. }, {
  1501. .type = IIO_EV_TYPE_THRESH,
  1502. .dir = IIO_EV_DIR_FALLING,
  1503. .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
  1504. }, {
  1505. .type = IIO_EV_TYPE_THRESH,
  1506. .dir = IIO_EV_DIR_EITHER,
  1507. .mask_separate = BIT(IIO_EV_INFO_PERIOD),
  1508. },
  1509. };
  1510. static const struct iio_chan_spec vcnl4000_channels[] = {
  1511. {
  1512. .type = IIO_LIGHT,
  1513. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  1514. BIT(IIO_CHAN_INFO_SCALE),
  1515. }, {
  1516. .type = IIO_PROXIMITY,
  1517. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  1518. .ext_info = vcnl4000_ext_info,
  1519. }
  1520. };
  1521. static const struct iio_chan_spec vcnl4010_channels[] = {
  1522. {
  1523. .type = IIO_LIGHT,
  1524. .scan_index = -1,
  1525. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  1526. BIT(IIO_CHAN_INFO_SCALE),
  1527. }, {
  1528. .type = IIO_PROXIMITY,
  1529. .scan_index = 0,
  1530. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  1531. BIT(IIO_CHAN_INFO_SAMP_FREQ),
  1532. .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),
  1533. .event_spec = vcnl4000_event_spec,
  1534. .num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
  1535. .ext_info = vcnl4000_ext_info,
  1536. .scan_type = {
  1537. .sign = 'u',
  1538. .realbits = 16,
  1539. .storagebits = 16,
  1540. .endianness = IIO_CPU,
  1541. },
  1542. },
  1543. IIO_CHAN_SOFT_TIMESTAMP(1),
  1544. };
  1545. static const struct iio_chan_spec vcnl4040_channels[] = {
  1546. {
  1547. .type = IIO_LIGHT,
  1548. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  1549. BIT(IIO_CHAN_INFO_SCALE) |
  1550. BIT(IIO_CHAN_INFO_INT_TIME),
  1551. .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
  1552. .event_spec = vcnl4040_als_event_spec,
  1553. .num_event_specs = ARRAY_SIZE(vcnl4040_als_event_spec),
  1554. }, {
  1555. .type = IIO_PROXIMITY,
  1556. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  1557. BIT(IIO_CHAN_INFO_INT_TIME) |
  1558. BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
  1559. BIT(IIO_CHAN_INFO_CALIBBIAS),
  1560. .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
  1561. BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
  1562. BIT(IIO_CHAN_INFO_CALIBBIAS),
  1563. .ext_info = vcnl4000_ext_info,
  1564. .event_spec = vcnl4040_event_spec,
  1565. .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
  1566. }
  1567. };
  1568. static const struct iio_info vcnl4000_info = {
  1569. .read_raw = vcnl4000_read_raw,
  1570. };
  1571. static const struct iio_info vcnl4010_info = {
  1572. .read_raw = vcnl4010_read_raw,
  1573. .read_avail = vcnl4010_read_avail,
  1574. .write_raw = vcnl4010_write_raw,
  1575. .read_event_value = vcnl4010_read_event,
  1576. .write_event_value = vcnl4010_write_event,
  1577. .read_event_config = vcnl4010_read_event_config,
  1578. .write_event_config = vcnl4010_write_event_config,
  1579. };
  1580. static const struct iio_info vcnl4040_info = {
  1581. .read_raw = vcnl4000_read_raw,
  1582. .write_raw = vcnl4040_write_raw,
  1583. .read_event_value = vcnl4040_read_event,
  1584. .write_event_value = vcnl4040_write_event,
  1585. .read_event_config = vcnl4040_read_event_config,
  1586. .write_event_config = vcnl4040_write_event_config,
  1587. .read_avail = vcnl4040_read_avail,
  1588. };
  1589. static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
  1590. [VCNL4000] = {
  1591. .prod = "VCNL4000",
  1592. .init = vcnl4000_init,
  1593. .measure_light = vcnl4000_measure_light,
  1594. .measure_proximity = vcnl4000_measure_proximity,
  1595. .set_power_state = vcnl4000_set_power_state,
  1596. .channels = vcnl4000_channels,
  1597. .num_channels = ARRAY_SIZE(vcnl4000_channels),
  1598. .info = &vcnl4000_info,
  1599. },
  1600. [VCNL4010] = {
  1601. .prod = "VCNL4010/4020",
  1602. .init = vcnl4000_init,
  1603. .measure_light = vcnl4000_measure_light,
  1604. .measure_proximity = vcnl4000_measure_proximity,
  1605. .set_power_state = vcnl4000_set_power_state,
  1606. .channels = vcnl4010_channels,
  1607. .num_channels = ARRAY_SIZE(vcnl4010_channels),
  1608. .info = &vcnl4010_info,
  1609. .irq_thread = vcnl4010_irq_thread,
  1610. .trig_buffer_func = vcnl4010_trigger_handler,
  1611. .buffer_setup_ops = &vcnl4010_buffer_ops,
  1612. },
  1613. [VCNL4040] = {
  1614. .prod = "VCNL4040",
  1615. .init = vcnl4200_init,
  1616. .measure_light = vcnl4200_measure_light,
  1617. .measure_proximity = vcnl4200_measure_proximity,
  1618. .set_power_state = vcnl4200_set_power_state,
  1619. .channels = vcnl4040_channels,
  1620. .num_channels = ARRAY_SIZE(vcnl4040_channels),
  1621. .info = &vcnl4040_info,
  1622. .irq_thread = vcnl4040_irq_thread,
  1623. .int_reg = VCNL4040_INT_FLAGS,
  1624. .ps_it_times = &vcnl4040_ps_it_times,
  1625. .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times),
  1626. .als_it_times = &vcnl4040_als_it_times,
  1627. .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times),
  1628. .ulux_step = 100000,
  1629. },
  1630. [VCNL4200] = {
  1631. .prod = "VCNL4200",
  1632. .init = vcnl4200_init,
  1633. .measure_light = vcnl4200_measure_light,
  1634. .measure_proximity = vcnl4200_measure_proximity,
  1635. .set_power_state = vcnl4200_set_power_state,
  1636. .channels = vcnl4040_channels,
  1637. .num_channels = ARRAY_SIZE(vcnl4000_channels),
  1638. .info = &vcnl4040_info,
  1639. .irq_thread = vcnl4040_irq_thread,
  1640. .int_reg = VCNL4200_INT_FLAGS,
  1641. .ps_it_times = &vcnl4200_ps_it_times,
  1642. .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times),
  1643. .als_it_times = &vcnl4200_als_it_times,
  1644. .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times),
  1645. .ulux_step = 24000,
  1646. },
  1647. };
  1648. static const struct iio_trigger_ops vcnl4010_trigger_ops = {
  1649. .validate_device = iio_trigger_validate_own_device,
  1650. };
  1651. static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
  1652. {
  1653. struct vcnl4000_data *data = iio_priv(indio_dev);
  1654. struct i2c_client *client = data->client;
  1655. struct iio_trigger *trigger;
  1656. trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
  1657. indio_dev->name,
  1658. iio_device_id(indio_dev));
  1659. if (!trigger)
  1660. return -ENOMEM;
  1661. trigger->ops = &vcnl4010_trigger_ops;
  1662. iio_trigger_set_drvdata(trigger, indio_dev);
  1663. return devm_iio_trigger_register(&client->dev, trigger);
  1664. }
  1665. static int vcnl4000_probe(struct i2c_client *client)
  1666. {
  1667. const struct i2c_device_id *id = i2c_client_get_device_id(client);
  1668. struct vcnl4000_data *data;
  1669. struct iio_dev *indio_dev;
  1670. int ret;
  1671. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  1672. if (!indio_dev)
  1673. return -ENOMEM;
  1674. data = iio_priv(indio_dev);
  1675. i2c_set_clientdata(client, indio_dev);
  1676. data->client = client;
  1677. data->id = id->driver_data;
  1678. data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
  1679. mutex_init(&data->vcnl4000_lock);
  1680. ret = data->chip_spec->init(data);
  1681. if (ret < 0)
  1682. return ret;
  1683. dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
  1684. data->chip_spec->prod, data->rev);
  1685. if (device_property_read_u32(&client->dev, "proximity-near-level",
  1686. &data->near_level))
  1687. data->near_level = 0;
  1688. indio_dev->info = data->chip_spec->info;
  1689. indio_dev->channels = data->chip_spec->channels;
  1690. indio_dev->num_channels = data->chip_spec->num_channels;
  1691. indio_dev->name = VCNL4000_DRV_NAME;
  1692. indio_dev->modes = INDIO_DIRECT_MODE;
  1693. if (data->chip_spec->trig_buffer_func &&
  1694. data->chip_spec->buffer_setup_ops) {
  1695. ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
  1696. NULL,
  1697. data->chip_spec->trig_buffer_func,
  1698. data->chip_spec->buffer_setup_ops);
  1699. if (ret < 0) {
  1700. dev_err(&client->dev,
  1701. "unable to setup iio triggered buffer\n");
  1702. return ret;
  1703. }
  1704. }
  1705. if (client->irq && data->chip_spec->irq_thread) {
  1706. ret = devm_request_threaded_irq(&client->dev, client->irq,
  1707. NULL, data->chip_spec->irq_thread,
  1708. IRQF_TRIGGER_FALLING |
  1709. IRQF_ONESHOT,
  1710. "vcnl4000_irq",
  1711. indio_dev);
  1712. if (ret < 0) {
  1713. dev_err(&client->dev, "irq request failed\n");
  1714. return ret;
  1715. }
  1716. ret = vcnl4010_probe_trigger(indio_dev);
  1717. if (ret < 0)
  1718. return ret;
  1719. }
  1720. ret = pm_runtime_set_active(&client->dev);
  1721. if (ret < 0)
  1722. goto fail_poweroff;
  1723. ret = iio_device_register(indio_dev);
  1724. if (ret < 0)
  1725. goto fail_poweroff;
  1726. pm_runtime_enable(&client->dev);
  1727. pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
  1728. pm_runtime_use_autosuspend(&client->dev);
  1729. return 0;
  1730. fail_poweroff:
  1731. data->chip_spec->set_power_state(data, false);
  1732. return ret;
  1733. }
  1734. static const struct of_device_id vcnl_4000_of_match[] = {
  1735. {
  1736. .compatible = "vishay,vcnl4000",
  1737. .data = (void *)VCNL4000,
  1738. },
  1739. {
  1740. .compatible = "vishay,vcnl4010",
  1741. .data = (void *)VCNL4010,
  1742. },
  1743. {
  1744. .compatible = "vishay,vcnl4020",
  1745. .data = (void *)VCNL4010,
  1746. },
  1747. {
  1748. .compatible = "vishay,vcnl4040",
  1749. .data = (void *)VCNL4040,
  1750. },
  1751. {
  1752. .compatible = "vishay,vcnl4200",
  1753. .data = (void *)VCNL4200,
  1754. },
  1755. {},
  1756. };
  1757. MODULE_DEVICE_TABLE(of, vcnl_4000_of_match);
  1758. static void vcnl4000_remove(struct i2c_client *client)
  1759. {
  1760. struct iio_dev *indio_dev = i2c_get_clientdata(client);
  1761. struct vcnl4000_data *data = iio_priv(indio_dev);
  1762. int ret;
  1763. pm_runtime_dont_use_autosuspend(&client->dev);
  1764. pm_runtime_disable(&client->dev);
  1765. iio_device_unregister(indio_dev);
  1766. pm_runtime_set_suspended(&client->dev);
  1767. ret = data->chip_spec->set_power_state(data, false);
  1768. if (ret)
  1769. dev_warn(&client->dev, "Failed to power down (%pe)\n",
  1770. ERR_PTR(ret));
  1771. }
  1772. static int vcnl4000_runtime_suspend(struct device *dev)
  1773. {
  1774. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  1775. struct vcnl4000_data *data = iio_priv(indio_dev);
  1776. return data->chip_spec->set_power_state(data, false);
  1777. }
  1778. static int vcnl4000_runtime_resume(struct device *dev)
  1779. {
  1780. struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
  1781. struct vcnl4000_data *data = iio_priv(indio_dev);
  1782. return data->chip_spec->set_power_state(data, true);
  1783. }
  1784. static DEFINE_RUNTIME_DEV_PM_OPS(vcnl4000_pm_ops, vcnl4000_runtime_suspend,
  1785. vcnl4000_runtime_resume, NULL);
  1786. static struct i2c_driver vcnl4000_driver = {
  1787. .driver = {
  1788. .name = VCNL4000_DRV_NAME,
  1789. .pm = pm_ptr(&vcnl4000_pm_ops),
  1790. .of_match_table = vcnl_4000_of_match,
  1791. },
  1792. .probe = vcnl4000_probe,
  1793. .id_table = vcnl4000_id,
  1794. .remove = vcnl4000_remove,
  1795. };
  1796. module_i2c_driver(vcnl4000_driver);
  1797. MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
  1798. MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
  1799. MODULE_DESCRIPTION("Vishay VCNL4000 proximity/ambient light sensor driver");
  1800. MODULE_LICENSE("GPL");