File Index
Files and directories
Sign in
FILE

ltrf216a.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/light/ltrf216a.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * LTRF216A Ambient Light Sensor
  4 *
  5 * Copyright (C) 2022 Collabora, Ltd.
  6 * Author: Shreeya Patel <shreeya.patel@collabora.com>
  7 *
  8 * Copyright (C) 2021 Lite-On Technology Corp (Singapore)
  9 * Author: Shi Zhigang <Zhigang.Shi@liteon.com>
 10 *
 11 * IIO driver for LTRF216A (7-bit I2C slave address 0x53).
 12 */
 13
 14#include <linux/bitfield.h>
 15#include <linux/bits.h>
 16#include <linux/delay.h>
 17#include <linux/i2c.h>
 18#include <linux/init.h>
 19#include <linux/iopoll.h>
 20#include <linux/mod_devicetable.h>
 21#include <linux/module.h>
 22#include <linux/mutex.h>
 23#include <linux/pm.h>
 24#include <linux/pm_runtime.h>
 25#include <linux/regmap.h>
 26
 27#include <linux/iio/iio.h>
 28
 29#include <linux/unaligned.h>
 30
 31#define LTRF216A_ALS_RESET_MASK		BIT(4)
 32#define LTRF216A_ALS_DATA_STATUS	BIT(3)
 33#define LTRF216A_ALS_ENABLE_MASK	BIT(1)
 34#define LTRF216A_MAIN_CTRL		0x00
 35#define LTRF216A_ALS_MEAS_RES		0x04
 36#define LTRF216A_ALS_GAIN		0x05
 37#define LTRF216A_PART_ID		0x06
 38#define LTRF216A_MAIN_STATUS		0x07
 39#define LTRF216A_ALS_CLEAR_DATA_0	0x0a
 40#define LTRF216A_ALS_CLEAR_DATA_1	0x0b
 41#define LTRF216A_ALS_CLEAR_DATA_2	0x0c
 42#define LTRF216A_ALS_DATA_0		0x0d
 43#define LTRF216A_ALS_DATA_1		0x0e
 44#define LTRF216A_ALS_DATA_2		0x0f
 45#define LTRF216A_INT_CFG		0x19
 46#define LTRF216A_INT_PST		0x1a
 47#define LTRF216A_ALS_THRES_UP_0		0x21
 48#define LTRF216A_ALS_THRES_UP_1		0x22
 49#define LTRF216A_ALS_THRES_UP_2		0x23
 50#define LTRF216A_ALS_THRES_LOW_0	0x24
 51#define LTRF216A_ALS_THRES_LOW_1	0x25
 52#define LTRF216A_ALS_THRES_LOW_2	0x26
 53#define LTRF216A_ALS_READ_DATA_DELAY_US	20000
 54
 55static const int ltrf216a_int_time_available[][2] = {
 56	{ 0, 400000 },
 57	{ 0, 200000 },
 58	{ 0, 100000 },
 59	{ 0,  50000 },
 60	{ 0,  25000 },
 61};
 62
 63static const int ltrf216a_int_time_reg[][2] = {
 64	{ 400, 0x03 },
 65	{ 200, 0x13 },
 66	{ 100, 0x22 },
 67	{  50, 0x31 },
 68	{  25, 0x40 },
 69};
 70
 71struct ltr_chip_info {
 72	/* Chip contains CLEAR_DATA_0/1/2 registers at offset 0xa..0xc */
 73	bool		has_clear_data;
 74	/* Lux calculation multiplier for ALS data */
 75	int		lux_multiplier;
 76};
 77
 78/*
 79 * Window Factor is needed when the device is under Window glass
 80 * with coated tinted ink. This is to compensate for the light loss
 81 * due to the lower transmission rate of the window glass and helps
 82 * in calculating lux.
 83 */
 84#define LTRF216A_WIN_FAC	1
 85
 86struct ltrf216a_data {
 87	struct regmap *regmap;
 88	struct i2c_client *client;
 89	const struct ltr_chip_info *info;
 90	u32 int_time;
 91	u16 int_time_fac;
 92	u8 als_gain_fac;
 93	/*
 94	 * Protects regmap accesses and makes sure integration time
 95	 * remains constant during the measurement of lux.
 96	 */
 97	struct mutex lock;
 98};
 99
100static const struct iio_chan_spec ltrf216a_channels[] = {
101	{
102		.type = IIO_LIGHT,
103		.info_mask_separate =
104			BIT(IIO_CHAN_INFO_RAW) |
105			BIT(IIO_CHAN_INFO_PROCESSED) |
106			BIT(IIO_CHAN_INFO_INT_TIME),
107		.info_mask_separate_available =
108			BIT(IIO_CHAN_INFO_INT_TIME),
109	},
110};
111
112static void ltrf216a_reset(struct iio_dev *indio_dev)
113{
114	struct ltrf216a_data *data = iio_priv(indio_dev);
115
116	/* reset sensor, chip fails to respond to this, so ignore any errors */
117	regmap_write(data->regmap, LTRF216A_MAIN_CTRL, LTRF216A_ALS_RESET_MASK);
118
119	/* reset time */
120	usleep_range(1000, 2000);
121}
122
123static int ltrf216a_enable(struct iio_dev *indio_dev)
124{
125	struct ltrf216a_data *data = iio_priv(indio_dev);
126	struct device *dev = &data->client->dev;
127	int ret;
128
129	/* enable sensor */
130	ret = regmap_set_bits(data->regmap,
131			      LTRF216A_MAIN_CTRL, LTRF216A_ALS_ENABLE_MASK);
132	if (ret) {
133		dev_err(dev, "failed to enable sensor: %d\n", ret);
134		return ret;
135	}
136
137	/* sleep for one integration cycle after enabling the device */
138	msleep(ltrf216a_int_time_reg[0][0]);
139
140	return 0;
141}
142
143static int ltrf216a_disable(struct iio_dev *indio_dev)
144{
145	struct ltrf216a_data *data = iio_priv(indio_dev);
146	struct device *dev = &data->client->dev;
147	int ret;
148
149	ret = regmap_write(data->regmap, LTRF216A_MAIN_CTRL, 0);
150	if (ret)
151		dev_err(dev, "failed to disable sensor: %d\n", ret);
152
153	return ret;
154}
155
156static void ltrf216a_cleanup(void *data)
157{
158	struct iio_dev *indio_dev = data;
159
160	ltrf216a_disable(indio_dev);
161}
162
163static int ltrf216a_set_int_time(struct ltrf216a_data *data, int itime)
164{
165	struct device *dev = &data->client->dev;
166	unsigned int i;
167	u8 reg_val;
168	int ret;
169
170	for (i = 0; i < ARRAY_SIZE(ltrf216a_int_time_available); i++) {
171		if (ltrf216a_int_time_available[i][1] == itime)
172			break;
173	}
174	if (i == ARRAY_SIZE(ltrf216a_int_time_available))
175		return -EINVAL;
176
177	reg_val = ltrf216a_int_time_reg[i][1];
178
179	ret = regmap_write(data->regmap, LTRF216A_ALS_MEAS_RES, reg_val);
180	if (ret) {
181		dev_err(dev, "failed to set integration time: %d\n", ret);
182		return ret;
183	}
184
185	data->int_time_fac = ltrf216a_int_time_reg[i][0];
186	data->int_time = itime;
187
188	return 0;
189}
190
191static int ltrf216a_get_int_time(struct ltrf216a_data *data,
192				 int *val, int *val2)
193{
194	*val = 0;
195	*val2 = data->int_time;
196	return IIO_VAL_INT_PLUS_MICRO;
197}
198
199static int ltrf216a_set_power_state(struct ltrf216a_data *data, bool on)
200{
201	struct device *dev = &data->client->dev;
202	int ret = 0;
203
204	if (on) {
205		ret = pm_runtime_resume_and_get(dev);
206		if (ret) {
207			dev_err(dev, "failed to resume runtime PM: %d\n", ret);
208			return ret;
209		}
210	} else {
211		pm_runtime_put_autosuspend(dev);
212	}
213
214	return ret;
215}
216
217static int ltrf216a_read_data(struct ltrf216a_data *data, u8 addr)
218{
219	struct device *dev = &data->client->dev;
220	int ret, val;
221	u8 buf[3];
222
223	ret = regmap_read_poll_timeout(data->regmap, LTRF216A_MAIN_STATUS,
224				       val, val & LTRF216A_ALS_DATA_STATUS,
225				       LTRF216A_ALS_READ_DATA_DELAY_US,
226				       LTRF216A_ALS_READ_DATA_DELAY_US * 50);
227	if (ret) {
228		dev_err(dev, "failed to wait for measurement data: %d\n", ret);
229		return ret;
230	}
231
232	ret = regmap_bulk_read(data->regmap, addr, buf, sizeof(buf));
233	if (ret) {
234		dev_err(dev, "failed to read measurement data: %d\n", ret);
235		return ret;
236	}
237
238	return get_unaligned_le24(&buf[0]);
239}
240
241static int ltrf216a_get_lux(struct ltrf216a_data *data)
242{
243	int ret, greendata;
244	u64 lux;
245
246	ret = ltrf216a_set_power_state(data, true);
247	if (ret)
248		return ret;
249
250	greendata = ltrf216a_read_data(data, LTRF216A_ALS_DATA_0);
251	if (greendata < 0)
252		return greendata;
253
254	ltrf216a_set_power_state(data, false);
255
256	lux = greendata * data->info->lux_multiplier * LTRF216A_WIN_FAC;
257
258	return lux;
259}
260
261static int ltrf216a_read_raw(struct iio_dev *indio_dev,
262			     struct iio_chan_spec const *chan, int *val,
263			     int *val2, long mask)
264{
265	struct ltrf216a_data *data = iio_priv(indio_dev);
266	int ret;
267
268	switch (mask) {
269	case IIO_CHAN_INFO_RAW:
270		ret = ltrf216a_set_power_state(data, true);
271		if (ret)
272			return ret;
273		mutex_lock(&data->lock);
274		ret = ltrf216a_read_data(data, LTRF216A_ALS_DATA_0);
275		mutex_unlock(&data->lock);
276		ltrf216a_set_power_state(data, false);
277		if (ret < 0)
278			return ret;
279		*val = ret;
280		return IIO_VAL_INT;
281	case IIO_CHAN_INFO_PROCESSED:
282		mutex_lock(&data->lock);
283		ret = ltrf216a_get_lux(data);
284		mutex_unlock(&data->lock);
285		if (ret < 0)
286			return ret;
287		*val = ret;
288		*val2 = data->als_gain_fac * data->int_time_fac;
289		return IIO_VAL_FRACTIONAL;
290	case IIO_CHAN_INFO_INT_TIME:
291		mutex_lock(&data->lock);
292		ret = ltrf216a_get_int_time(data, val, val2);
293		mutex_unlock(&data->lock);
294		return ret;
295	default:
296		return -EINVAL;
297	}
298}
299
300static int ltrf216a_write_raw(struct iio_dev *indio_dev,
301			      struct iio_chan_spec const *chan, int val,
302			      int val2, long mask)
303{
304	struct ltrf216a_data *data = iio_priv(indio_dev);
305	int ret;
306
307	switch (mask) {
308	case IIO_CHAN_INFO_INT_TIME:
309		if (val != 0)
310			return -EINVAL;
311		mutex_lock(&data->lock);
312		ret = ltrf216a_set_int_time(data, val2);
313		mutex_unlock(&data->lock);
314		return ret;
315	default:
316		return -EINVAL;
317	}
318}
319
320static int ltrf216a_read_available(struct iio_dev *indio_dev,
321				   struct iio_chan_spec const *chan,
322				   const int **vals, int *type, int *length,
323				   long mask)
324{
325	switch (mask) {
326	case IIO_CHAN_INFO_INT_TIME:
327		*length = ARRAY_SIZE(ltrf216a_int_time_available) * 2;
328		*vals = (const int *)ltrf216a_int_time_available;
329		*type = IIO_VAL_INT_PLUS_MICRO;
330		return IIO_AVAIL_LIST;
331	default:
332		return -EINVAL;
333	}
334}
335
336static const struct iio_info ltrf216a_info = {
337	.read_raw = ltrf216a_read_raw,
338	.write_raw = ltrf216a_write_raw,
339	.read_avail = ltrf216a_read_available,
340};
341
342static bool ltrf216a_readable_reg(struct device *dev, unsigned int reg)
343{
344	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
345	struct ltrf216a_data *data = iio_priv(indio_dev);
346
347	switch (reg) {
348	case LTRF216A_MAIN_CTRL:
349	case LTRF216A_ALS_MEAS_RES:
350	case LTRF216A_ALS_GAIN:
351	case LTRF216A_PART_ID:
352	case LTRF216A_MAIN_STATUS:
353	case LTRF216A_ALS_DATA_0:
354	case LTRF216A_ALS_DATA_1:
355	case LTRF216A_ALS_DATA_2:
356	case LTRF216A_INT_CFG:
357	case LTRF216A_INT_PST:
358	case LTRF216A_ALS_THRES_UP_0:
359	case LTRF216A_ALS_THRES_UP_1:
360	case LTRF216A_ALS_THRES_UP_2:
361	case LTRF216A_ALS_THRES_LOW_0:
362	case LTRF216A_ALS_THRES_LOW_1:
363	case LTRF216A_ALS_THRES_LOW_2:
364		return true;
365	case LTRF216A_ALS_CLEAR_DATA_0:
366	case LTRF216A_ALS_CLEAR_DATA_1:
367	case LTRF216A_ALS_CLEAR_DATA_2:
368		return data->info->has_clear_data;
369	default:
370		return false;
371	}
372}
373
374static bool ltrf216a_writable_reg(struct device *dev, unsigned int reg)
375{
376	switch (reg) {
377	case LTRF216A_MAIN_CTRL:
378	case LTRF216A_ALS_MEAS_RES:
379	case LTRF216A_ALS_GAIN:
380	case LTRF216A_INT_CFG:
381	case LTRF216A_INT_PST:
382	case LTRF216A_ALS_THRES_UP_0:
383	case LTRF216A_ALS_THRES_UP_1:
384	case LTRF216A_ALS_THRES_UP_2:
385	case LTRF216A_ALS_THRES_LOW_0:
386	case LTRF216A_ALS_THRES_LOW_1:
387	case LTRF216A_ALS_THRES_LOW_2:
388		return true;
389	default:
390		return false;
391	}
392}
393
394static bool ltrf216a_volatile_reg(struct device *dev, unsigned int reg)
395{
396	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
397	struct ltrf216a_data *data = iio_priv(indio_dev);
398
399	switch (reg) {
400	case LTRF216A_MAIN_STATUS:
401	case LTRF216A_ALS_DATA_0:
402	case LTRF216A_ALS_DATA_1:
403	case LTRF216A_ALS_DATA_2:
404		return true;
405	/*
406	 * If these registers are not present on a chip (like LTR-308),
407	 * the missing registers are not considered volatile.
408	 */
409	case LTRF216A_ALS_CLEAR_DATA_0:
410	case LTRF216A_ALS_CLEAR_DATA_1:
411	case LTRF216A_ALS_CLEAR_DATA_2:
412		return data->info->has_clear_data;
413	default:
414		return false;
415	}
416}
417
418static bool ltrf216a_precious_reg(struct device *dev, unsigned int reg)
419{
420	return reg == LTRF216A_MAIN_STATUS;
421}
422
423static const struct regmap_config ltrf216a_regmap_config = {
424	.name = "ltrf216a",
425	.reg_bits = 8,
426	.val_bits = 8,
427	.cache_type = REGCACHE_RBTREE,
428	.max_register = LTRF216A_ALS_THRES_LOW_2,
429	.readable_reg = ltrf216a_readable_reg,
430	.writeable_reg = ltrf216a_writable_reg,
431	.volatile_reg = ltrf216a_volatile_reg,
432	.precious_reg = ltrf216a_precious_reg,
433	.disable_locking = true,
434};
435
436static int ltrf216a_probe(struct i2c_client *client)
437{
438	struct ltrf216a_data *data;
439	struct iio_dev *indio_dev;
440	int ret;
441
442	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
443	if (!indio_dev)
444		return -ENOMEM;
445
446	data = iio_priv(indio_dev);
447
448	data->regmap = devm_regmap_init_i2c(client, &ltrf216a_regmap_config);
449	if (IS_ERR(data->regmap))
450		return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
451				     "regmap initialization failed\n");
452
453	i2c_set_clientdata(client, indio_dev);
454	data->client = client;
455	data->info = i2c_get_match_data(client);
456
457	mutex_init(&data->lock);
458
459	indio_dev->info = &ltrf216a_info;
460	indio_dev->name = "ltrf216a";
461	indio_dev->channels = ltrf216a_channels;
462	indio_dev->num_channels = ARRAY_SIZE(ltrf216a_channels);
463	indio_dev->modes = INDIO_DIRECT_MODE;
464
465	ret = pm_runtime_set_active(&client->dev);
466	if (ret)
467		return ret;
468
469	/* reset sensor, chip fails to respond to this, so ignore any errors */
470	ltrf216a_reset(indio_dev);
471
472	ret = regmap_reinit_cache(data->regmap, &ltrf216a_regmap_config);
473	if (ret)
474		return dev_err_probe(&client->dev, ret,
475				     "failed to reinit regmap cache\n");
476
477	ret = ltrf216a_enable(indio_dev);
478	if (ret)
479		return ret;
480
481	ret = devm_add_action_or_reset(&client->dev, ltrf216a_cleanup,
482				       indio_dev);
483	if (ret)
484		return ret;
485
486	ret = devm_pm_runtime_enable(&client->dev);
487	if (ret)
488		return dev_err_probe(&client->dev, ret,
489				     "failed to enable runtime PM\n");
490
491	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
492	pm_runtime_use_autosuspend(&client->dev);
493
494	data->int_time = 100000;
495	data->int_time_fac = 100;
496	data->als_gain_fac = 3;
497
498	return devm_iio_device_register(&client->dev, indio_dev);
499}
500
501static int ltrf216a_runtime_suspend(struct device *dev)
502{
503	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
504	struct ltrf216a_data *data = iio_priv(indio_dev);
505	int ret;
506
507	ret = ltrf216a_disable(indio_dev);
508	if (ret)
509		return ret;
510
511	regcache_cache_only(data->regmap, true);
512
513	return 0;
514}
515
516static int ltrf216a_runtime_resume(struct device *dev)
517{
518	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
519	struct ltrf216a_data *data = iio_priv(indio_dev);
520	int ret;
521
522	regcache_cache_only(data->regmap, false);
523	regcache_mark_dirty(data->regmap);
524	ret = regcache_sync(data->regmap);
525	if (ret)
526		goto cache_only;
527
528	ret = ltrf216a_enable(indio_dev);
529	if (ret)
530		goto cache_only;
531
532	return 0;
533
534cache_only:
535	regcache_cache_only(data->regmap, true);
536
537	return ret;
538}
539
540static DEFINE_RUNTIME_DEV_PM_OPS(ltrf216a_pm_ops, ltrf216a_runtime_suspend,
541				 ltrf216a_runtime_resume, NULL);
542
543static const struct ltr_chip_info ltr308_chip_info = {
544	.has_clear_data		= false,
545	.lux_multiplier		= 60,
546};
547
548static const struct ltr_chip_info ltrf216a_chip_info = {
549	.has_clear_data		= true,
550	.lux_multiplier		= 45,
551};
552
553static const struct i2c_device_id ltrf216a_id[] = {
554	{ "ltr308", .driver_data = (kernel_ulong_t)&ltr308_chip_info },
555	{ "ltrf216a", .driver_data = (kernel_ulong_t)&ltrf216a_chip_info },
556	{ }
557};
558MODULE_DEVICE_TABLE(i2c, ltrf216a_id);
559
560static const struct of_device_id ltrf216a_of_match[] = {
561	{ .compatible = "liteon,ltr308", .data = &ltr308_chip_info },
562	{ .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info },
563	/* For Valve's Steamdeck device, an ACPI platform using PRP0001 */
564	{ .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info },
565	{ }
566};
567MODULE_DEVICE_TABLE(of, ltrf216a_of_match);
568
569static struct i2c_driver ltrf216a_driver = {
570	.driver = {
571		.name = "ltrf216a",
572		.pm = pm_ptr(&ltrf216a_pm_ops),
573		.of_match_table = ltrf216a_of_match,
574	},
575	.probe = ltrf216a_probe,
576	.id_table = ltrf216a_id,
577};
578module_i2c_driver(ltrf216a_driver);
579
580MODULE_AUTHOR("Shreeya Patel <shreeya.patel@collabora.com>");
581MODULE_AUTHOR("Shi Zhigang <Zhigang.Shi@liteon.com>");
582MODULE_DESCRIPTION("LTRF216A ambient light sensor driver");
583MODULE_LICENSE("GPL");
~/ Read-only file preview.