File Index
Files and directories
Sign in
FILE

tcs3472.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/light/tcs3472.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * tcs3472.c - Support for TAOS TCS3472 color light-to-digital converter
  4 *
  5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
  6 *
  7 * Color light sensor with 16-bit channels for red, green, blue, clear);
  8 * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
  9 * TCS34727)
 10 *
 11 * Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3472_Datasheet_EN_v2.pdf
 12 *
 13 * TODO: wait time
 14 */
 15
 16#include <linux/module.h>
 17#include <linux/i2c.h>
 18#include <linux/delay.h>
 19#include <linux/pm.h>
 20
 21#include <linux/iio/iio.h>
 22#include <linux/iio/sysfs.h>
 23#include <linux/iio/events.h>
 24#include <linux/iio/trigger_consumer.h>
 25#include <linux/iio/buffer.h>
 26#include <linux/iio/triggered_buffer.h>
 27
 28#define TCS3472_DRV_NAME "tcs3472"
 29
 30#define TCS3472_COMMAND BIT(7)
 31#define TCS3472_AUTO_INCR BIT(5)
 32#define TCS3472_SPECIAL_FUNC (BIT(5) | BIT(6))
 33
 34#define TCS3472_INTR_CLEAR (TCS3472_COMMAND | TCS3472_SPECIAL_FUNC | 0x06)
 35
 36#define TCS3472_ENABLE (TCS3472_COMMAND | 0x00)
 37#define TCS3472_ATIME (TCS3472_COMMAND | 0x01)
 38#define TCS3472_WTIME (TCS3472_COMMAND | 0x03)
 39#define TCS3472_AILT (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x04)
 40#define TCS3472_AIHT (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x06)
 41#define TCS3472_PERS (TCS3472_COMMAND | 0x0c)
 42#define TCS3472_CONFIG (TCS3472_COMMAND | 0x0d)
 43#define TCS3472_CONTROL (TCS3472_COMMAND | 0x0f)
 44#define TCS3472_ID (TCS3472_COMMAND | 0x12)
 45#define TCS3472_STATUS (TCS3472_COMMAND | 0x13)
 46#define TCS3472_CDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x14)
 47#define TCS3472_RDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x16)
 48#define TCS3472_GDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x18)
 49#define TCS3472_BDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x1a)
 50
 51#define TCS3472_STATUS_AINT BIT(4)
 52#define TCS3472_STATUS_AVALID BIT(0)
 53#define TCS3472_ENABLE_AIEN BIT(4)
 54#define TCS3472_ENABLE_AEN BIT(1)
 55#define TCS3472_ENABLE_PON BIT(0)
 56#define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1))
 57
 58struct tcs3472_data {
 59	struct i2c_client *client;
 60	struct mutex lock;
 61	u16 low_thresh;
 62	u16 high_thresh;
 63	u8 enable;
 64	u8 control;
 65	u8 atime;
 66	u8 apers;
 67};
 68
 69static const struct iio_event_spec tcs3472_events[] = {
 70	{
 71		.type = IIO_EV_TYPE_THRESH,
 72		.dir = IIO_EV_DIR_RISING,
 73		.mask_separate = BIT(IIO_EV_INFO_VALUE),
 74	}, {
 75		.type = IIO_EV_TYPE_THRESH,
 76		.dir = IIO_EV_DIR_FALLING,
 77		.mask_separate = BIT(IIO_EV_INFO_VALUE),
 78	}, {
 79		.type = IIO_EV_TYPE_THRESH,
 80		.dir = IIO_EV_DIR_EITHER,
 81		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
 82				 BIT(IIO_EV_INFO_PERIOD),
 83	},
 84};
 85
 86#define TCS3472_CHANNEL(_color, _si, _addr) { \
 87	.type = IIO_INTENSITY, \
 88	.modified = 1, \
 89	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 90	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
 91		BIT(IIO_CHAN_INFO_INT_TIME), \
 92	.channel2 = IIO_MOD_LIGHT_##_color, \
 93	.address = _addr, \
 94	.scan_index = _si, \
 95	.scan_type = { \
 96		.sign = 'u', \
 97		.realbits = 16, \
 98		.storagebits = 16, \
 99		.endianness = IIO_CPU, \
100	}, \
101	.event_spec = _si ? NULL : tcs3472_events, \
102	.num_event_specs = _si ? 0 : ARRAY_SIZE(tcs3472_events), \
103}
104
105static const int tcs3472_agains[] = { 1, 4, 16, 60 };
106
107static const struct iio_chan_spec tcs3472_channels[] = {
108	TCS3472_CHANNEL(CLEAR, 0, TCS3472_CDATA),
109	TCS3472_CHANNEL(RED, 1, TCS3472_RDATA),
110	TCS3472_CHANNEL(GREEN, 2, TCS3472_GDATA),
111	TCS3472_CHANNEL(BLUE, 3, TCS3472_BDATA),
112	IIO_CHAN_SOFT_TIMESTAMP(4),
113};
114
115static int tcs3472_req_data(struct tcs3472_data *data)
116{
117	int tries = 50;
118	int ret;
119
120	while (tries--) {
121		ret = i2c_smbus_read_byte_data(data->client, TCS3472_STATUS);
122		if (ret < 0)
123			return ret;
124		if (ret & TCS3472_STATUS_AVALID)
125			break;
126		msleep(20);
127	}
128
129	if (tries < 0) {
130		dev_err(&data->client->dev, "data not ready\n");
131		return -EIO;
132	}
133
134	return 0;
135}
136
137static int tcs3472_read_raw(struct iio_dev *indio_dev,
138			   struct iio_chan_spec const *chan,
139			   int *val, int *val2, long mask)
140{
141	struct tcs3472_data *data = iio_priv(indio_dev);
142	int ret;
143
144	switch (mask) {
145	case IIO_CHAN_INFO_RAW:
146		if (!iio_device_claim_direct(indio_dev))
147			return -EBUSY;
148		ret = tcs3472_req_data(data);
149		if (ret < 0) {
150			iio_device_release_direct(indio_dev);
151			return ret;
152		}
153		ret = i2c_smbus_read_word_data(data->client, chan->address);
154		iio_device_release_direct(indio_dev);
155		if (ret < 0)
156			return ret;
157		*val = ret;
158		return IIO_VAL_INT;
159	case IIO_CHAN_INFO_CALIBSCALE:
160		*val = tcs3472_agains[data->control &
161			TCS3472_CONTROL_AGAIN_MASK];
162		return IIO_VAL_INT;
163	case IIO_CHAN_INFO_INT_TIME:
164		*val = 0;
165		*val2 = (256 - data->atime) * 2400;
166		return IIO_VAL_INT_PLUS_MICRO;
167	}
168	return -EINVAL;
169}
170
171static int tcs3472_write_raw(struct iio_dev *indio_dev,
172			       struct iio_chan_spec const *chan,
173			       int val, int val2, long mask)
174{
175	struct tcs3472_data *data = iio_priv(indio_dev);
176	int i;
177
178	switch (mask) {
179	case IIO_CHAN_INFO_CALIBSCALE:
180		if (val2 != 0)
181			return -EINVAL;
182		for (i = 0; i < ARRAY_SIZE(tcs3472_agains); i++) {
183			if (val == tcs3472_agains[i]) {
184				data->control &= ~TCS3472_CONTROL_AGAIN_MASK;
185				data->control |= i;
186				return i2c_smbus_write_byte_data(
187					data->client, TCS3472_CONTROL,
188					data->control);
189			}
190		}
191		return -EINVAL;
192	case IIO_CHAN_INFO_INT_TIME:
193		if (val != 0)
194			return -EINVAL;
195		for (i = 0; i < 256; i++) {
196			if (val2 == (256 - i) * 2400) {
197				data->atime = i;
198				return i2c_smbus_write_byte_data(
199					data->client, TCS3472_ATIME,
200					data->atime);
201			}
202
203		}
204		return -EINVAL;
205	}
206	return -EINVAL;
207}
208
209/*
210 * Translation from APERS field value to the number of consecutive out-of-range
211 * clear channel values before an interrupt is generated
212 */
213static const int tcs3472_intr_pers[] = {
214	0, 1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60
215};
216
217static int tcs3472_read_event(struct iio_dev *indio_dev,
218	const struct iio_chan_spec *chan, enum iio_event_type type,
219	enum iio_event_direction dir, enum iio_event_info info, int *val,
220	int *val2)
221{
222	struct tcs3472_data *data = iio_priv(indio_dev);
223	int ret;
224	unsigned int period;
225
226	mutex_lock(&data->lock);
227
228	switch (info) {
229	case IIO_EV_INFO_VALUE:
230		*val = (dir == IIO_EV_DIR_RISING) ?
231			data->high_thresh : data->low_thresh;
232		ret = IIO_VAL_INT;
233		break;
234	case IIO_EV_INFO_PERIOD:
235		period = (256 - data->atime) * 2400 *
236			tcs3472_intr_pers[data->apers];
237		*val = period / USEC_PER_SEC;
238		*val2 = period % USEC_PER_SEC;
239		ret = IIO_VAL_INT_PLUS_MICRO;
240		break;
241	default:
242		ret = -EINVAL;
243		break;
244	}
245
246	mutex_unlock(&data->lock);
247
248	return ret;
249}
250
251static int tcs3472_write_event(struct iio_dev *indio_dev,
252	const struct iio_chan_spec *chan, enum iio_event_type type,
253	enum iio_event_direction dir, enum iio_event_info info, int val,
254	int val2)
255{
256	struct tcs3472_data *data = iio_priv(indio_dev);
257	int ret;
258	u8 command;
259	int period;
260	int i;
261
262	mutex_lock(&data->lock);
263	switch (info) {
264	case IIO_EV_INFO_VALUE:
265		switch (dir) {
266		case IIO_EV_DIR_RISING:
267			command = TCS3472_AIHT;
268			break;
269		case IIO_EV_DIR_FALLING:
270			command = TCS3472_AILT;
271			break;
272		default:
273			ret = -EINVAL;
274			goto error;
275		}
276		ret = i2c_smbus_write_word_data(data->client, command, val);
277		if (ret)
278			goto error;
279
280		if (dir == IIO_EV_DIR_RISING)
281			data->high_thresh = val;
282		else
283			data->low_thresh = val;
284		break;
285	case IIO_EV_INFO_PERIOD:
286		period = val * USEC_PER_SEC + val2;
287		for (i = 1; i < ARRAY_SIZE(tcs3472_intr_pers) - 1; i++) {
288			if (period <= (256 - data->atime) * 2400 *
289					tcs3472_intr_pers[i])
290				break;
291		}
292		ret = i2c_smbus_write_byte_data(data->client, TCS3472_PERS, i);
293		if (ret)
294			goto error;
295
296		data->apers = i;
297		break;
298	default:
299		ret = -EINVAL;
300		break;
301	}
302error:
303	mutex_unlock(&data->lock);
304
305	return ret;
306}
307
308static int tcs3472_read_event_config(struct iio_dev *indio_dev,
309	const struct iio_chan_spec *chan, enum iio_event_type type,
310	enum iio_event_direction dir)
311{
312	struct tcs3472_data *data = iio_priv(indio_dev);
313	int ret;
314
315	mutex_lock(&data->lock);
316	ret = !!(data->enable & TCS3472_ENABLE_AIEN);
317	mutex_unlock(&data->lock);
318
319	return ret;
320}
321
322static int tcs3472_write_event_config(struct iio_dev *indio_dev,
323	const struct iio_chan_spec *chan, enum iio_event_type type,
324	enum iio_event_direction dir, bool state)
325{
326	struct tcs3472_data *data = iio_priv(indio_dev);
327	int ret = 0;
328	u8 enable_old;
329
330	mutex_lock(&data->lock);
331
332	enable_old = data->enable;
333
334	if (state)
335		data->enable |= TCS3472_ENABLE_AIEN;
336	else
337		data->enable &= ~TCS3472_ENABLE_AIEN;
338
339	if (enable_old != data->enable) {
340		ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
341						data->enable);
342		if (ret)
343			data->enable = enable_old;
344	}
345	mutex_unlock(&data->lock);
346
347	return ret;
348}
349
350static irqreturn_t tcs3472_event_handler(int irq, void *priv)
351{
352	struct iio_dev *indio_dev = priv;
353	struct tcs3472_data *data = iio_priv(indio_dev);
354	int ret;
355
356	ret = i2c_smbus_read_byte_data(data->client, TCS3472_STATUS);
357	if (ret >= 0 && (ret & TCS3472_STATUS_AINT)) {
358		iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
359						IIO_EV_TYPE_THRESH,
360						IIO_EV_DIR_EITHER),
361				iio_get_time_ns(indio_dev));
362
363		i2c_smbus_read_byte_data(data->client, TCS3472_INTR_CLEAR);
364	}
365
366	return IRQ_HANDLED;
367}
368
369static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
370{
371	struct iio_poll_func *pf = p;
372	struct iio_dev *indio_dev = pf->indio_dev;
373	struct tcs3472_data *data = iio_priv(indio_dev);
374	int i, j = 0;
375	/* Ensure timestamp is naturally aligned */
376	struct {
377		u16 chans[4];
378		aligned_s64 timestamp;
379	} scan = { };
380
381	int ret = tcs3472_req_data(data);
382	if (ret < 0)
383		goto done;
384
385	iio_for_each_active_channel(indio_dev, i) {
386		ret = i2c_smbus_read_word_data(data->client,
387			TCS3472_CDATA + 2*i);
388		if (ret < 0)
389			goto done;
390
391		scan.chans[j++] = ret;
392	}
393
394	iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
395		iio_get_time_ns(indio_dev));
396
397done:
398	iio_trigger_notify_done(indio_dev->trig);
399
400	return IRQ_HANDLED;
401}
402
403static ssize_t tcs3472_show_int_time_available(struct device *dev,
404					struct device_attribute *attr,
405					char *buf)
406{
407	size_t len = 0;
408	int i;
409
410	for (i = 1; i <= 256; i++)
411		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
412			2400 * i);
413
414	/* replace trailing space by newline */
415	buf[len - 1] = '\n';
416
417	return len;
418}
419
420static IIO_CONST_ATTR(calibscale_available, "1 4 16 60");
421static IIO_DEV_ATTR_INT_TIME_AVAIL(tcs3472_show_int_time_available);
422
423static struct attribute *tcs3472_attributes[] = {
424	&iio_const_attr_calibscale_available.dev_attr.attr,
425	&iio_dev_attr_integration_time_available.dev_attr.attr,
426	NULL
427};
428
429static const struct attribute_group tcs3472_attribute_group = {
430	.attrs = tcs3472_attributes,
431};
432
433static const struct iio_info tcs3472_info = {
434	.read_raw = tcs3472_read_raw,
435	.write_raw = tcs3472_write_raw,
436	.read_event_value = tcs3472_read_event,
437	.write_event_value = tcs3472_write_event,
438	.read_event_config = tcs3472_read_event_config,
439	.write_event_config = tcs3472_write_event_config,
440	.attrs = &tcs3472_attribute_group,
441};
442
443static int tcs3472_probe(struct i2c_client *client)
444{
445	struct tcs3472_data *data;
446	struct iio_dev *indio_dev;
447	int ret;
448
449	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
450	if (indio_dev == NULL)
451		return -ENOMEM;
452
453	data = iio_priv(indio_dev);
454	i2c_set_clientdata(client, indio_dev);
455	data->client = client;
456	mutex_init(&data->lock);
457
458	indio_dev->info = &tcs3472_info;
459	indio_dev->name = TCS3472_DRV_NAME;
460	indio_dev->channels = tcs3472_channels;
461	indio_dev->num_channels = ARRAY_SIZE(tcs3472_channels);
462	indio_dev->modes = INDIO_DIRECT_MODE;
463
464	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ID);
465	if (ret < 0)
466		return ret;
467
468	if (ret == 0x44)
469		dev_info(&client->dev, "TCS34721/34725 found\n");
470	else if (ret == 0x4d)
471		dev_info(&client->dev, "TCS34723/34727 found\n");
472	else
473		return -ENODEV;
474
475	ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONTROL);
476	if (ret < 0)
477		return ret;
478	data->control = ret;
479
480	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ATIME);
481	if (ret < 0)
482		return ret;
483	data->atime = ret;
484
485	ret = i2c_smbus_read_word_data(data->client, TCS3472_AILT);
486	if (ret < 0)
487		return ret;
488	data->low_thresh = ret;
489
490	ret = i2c_smbus_read_word_data(data->client, TCS3472_AIHT);
491	if (ret < 0)
492		return ret;
493	data->high_thresh = ret;
494
495	data->apers = 1;
496	ret = i2c_smbus_write_byte_data(data->client, TCS3472_PERS,
497					data->apers);
498	if (ret < 0)
499		return ret;
500
501	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ENABLE);
502	if (ret < 0)
503		return ret;
504
505	/* enable device */
506	data->enable = ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN;
507	data->enable &= ~TCS3472_ENABLE_AIEN;
508	ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
509		data->enable);
510	if (ret < 0)
511		return ret;
512
513	ret = iio_triggered_buffer_setup(indio_dev, NULL,
514		tcs3472_trigger_handler, NULL);
515	if (ret < 0)
516		return ret;
517
518	if (client->irq) {
519		ret = request_threaded_irq(client->irq, NULL,
520					   tcs3472_event_handler,
521					   IRQF_TRIGGER_FALLING | IRQF_SHARED |
522					   IRQF_ONESHOT,
523					   client->name, indio_dev);
524		if (ret)
525			goto buffer_cleanup;
526	}
527
528	ret = iio_device_register(indio_dev);
529	if (ret < 0)
530		goto free_irq;
531
532	return 0;
533
534free_irq:
535	if (client->irq)
536		free_irq(client->irq, indio_dev);
537buffer_cleanup:
538	iio_triggered_buffer_cleanup(indio_dev);
539	return ret;
540}
541
542static int tcs3472_powerdown(struct tcs3472_data *data)
543{
544	int ret;
545	u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON;
546
547	mutex_lock(&data->lock);
548
549	ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
550		data->enable & ~enable_mask);
551	if (!ret)
552		data->enable &= ~enable_mask;
553
554	mutex_unlock(&data->lock);
555
556	return ret;
557}
558
559static void tcs3472_remove(struct i2c_client *client)
560{
561	struct iio_dev *indio_dev = i2c_get_clientdata(client);
562
563	iio_device_unregister(indio_dev);
564	if (client->irq)
565		free_irq(client->irq, indio_dev);
566	iio_triggered_buffer_cleanup(indio_dev);
567	tcs3472_powerdown(iio_priv(indio_dev));
568}
569
570static int tcs3472_suspend(struct device *dev)
571{
572	struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
573		to_i2c_client(dev)));
574	return tcs3472_powerdown(data);
575}
576
577static int tcs3472_resume(struct device *dev)
578{
579	struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
580		to_i2c_client(dev)));
581	int ret;
582	u8 enable_mask = TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON;
583
584	mutex_lock(&data->lock);
585
586	ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
587		data->enable | enable_mask);
588	if (!ret)
589		data->enable |= enable_mask;
590
591	mutex_unlock(&data->lock);
592
593	return ret;
594}
595
596static DEFINE_SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend,
597				tcs3472_resume);
598
599static const struct i2c_device_id tcs3472_id[] = {
600	{ "tcs3472" },
601	{ }
602};
603MODULE_DEVICE_TABLE(i2c, tcs3472_id);
604
605static struct i2c_driver tcs3472_driver = {
606	.driver = {
607		.name	= TCS3472_DRV_NAME,
608		.pm	= pm_sleep_ptr(&tcs3472_pm_ops),
609	},
610	.probe		= tcs3472_probe,
611	.remove		= tcs3472_remove,
612	.id_table	= tcs3472_id,
613};
614module_i2c_driver(tcs3472_driver);
615
616MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
617MODULE_DESCRIPTION("TCS3472 color light sensors driver");
618MODULE_LICENSE("GPL");
~/ Read-only file preview.