1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * UCS12CM0 illuminance and correlated color temperature sensor
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2022-2025 ROCKCHIP.
6*4882a593Smuzhiyun * Author: Jason Zhang <jason.zhang@rock-chips.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * IIO driver for UCS12CM0 (7-bit I2C slave address 0x38)
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/mutex.h>
14*4882a593Smuzhiyun #include <linux/err.h>
15*4882a593Smuzhiyun #include <linux/of.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/util_macros.h>
18*4882a593Smuzhiyun #include <linux/iio/iio.h>
19*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
20*4882a593Smuzhiyun #include <linux/gpio.h>
21*4882a593Smuzhiyun #include <linux/of_gpio.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/iio/triggered_buffer.h>
24*4882a593Smuzhiyun #include <linux/iio/kfifo_buf.h>
25*4882a593Smuzhiyun #include <linux/iio/buffer.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define UCS12CM0_SYS_CTRL 0x00
28*4882a593Smuzhiyun #define UCS12CM0_INT_CTRL 0x01
29*4882a593Smuzhiyun #define UCS12CM0_INT_FLAG 0x02
30*4882a593Smuzhiyun #define UCS12CM0_WAIT 0x03
31*4882a593Smuzhiyun #define UCS12CM0_ALS_GAIN 0x04
32*4882a593Smuzhiyun #define UCS12CM0_ALS_TIME 0x05
33*4882a593Smuzhiyun #define UCS12CM0_PS_LED 0x06
34*4882a593Smuzhiyun #define UCS12CM0_PS_GAIN 0x07
35*4882a593Smuzhiyun #define UCS12CM0_PS_PULSE 0x08
36*4882a593Smuzhiyun #define UCS12CM0_PS_TIME 0x09
37*4882a593Smuzhiyun #define UCS12CM0_PS_AVERAGE 0x0a
38*4882a593Smuzhiyun #define UCS12CM0_PS_PERSIST 0x0b
39*4882a593Smuzhiyun #define UCS12CM0_ALS_THDLL 0x0c
40*4882a593Smuzhiyun #define UCS12CM0_ALS_THDLH 0x0d
41*4882a593Smuzhiyun #define UCS12CM0_ALS_THDHL 0x0e
42*4882a593Smuzhiyun #define UCS12CM0_ALS_THDHH 0x0f
43*4882a593Smuzhiyun #define UCS12CM0_PS_THDLL 0x10
44*4882a593Smuzhiyun #define UCS12CM0_PS_THDLH 0x11
45*4882a593Smuzhiyun #define UCS12CM0_PS_THDHL 0x12
46*4882a593Smuzhiyun #define UCS12CM0_PS_THDHH 0x13
47*4882a593Smuzhiyun #define UCS12CM0_PS_OFFSET_L 0x14
48*4882a593Smuzhiyun #define UCS12CM0_PS_OFFSET_H 0x15
49*4882a593Smuzhiyun #define UCS12CM0_PS_DATA_L 0x18
50*4882a593Smuzhiyun #define UCS12CM0_PS_DATA_H 0x19
51*4882a593Smuzhiyun #define UCS12CM0_CLS_R_DATA_L 0x1c
52*4882a593Smuzhiyun #define UCS12CM0_CLS_R_DATA_H 0x1d
53*4882a593Smuzhiyun #define UCS12CM0_CLS_G_DATA_L 0x1e
54*4882a593Smuzhiyun #define UCS12CM0_CLS_G_DATA_H 0x1f
55*4882a593Smuzhiyun #define UCS12CM0_CLS_B_DATA_L 0x20
56*4882a593Smuzhiyun #define UCS12CM0_CLS_B_DATA_H 0x21
57*4882a593Smuzhiyun #define UCS12CM0_CLS_W_DATA_L 0x22
58*4882a593Smuzhiyun #define UCS12CM0_CLS_W_DATA_H 0x23
59*4882a593Smuzhiyun #define UCS12CM0_IR_DATA_L 0x24
60*4882a593Smuzhiyun #define UCS12CM0_IR_DATA_H 0x25
61*4882a593Smuzhiyun #define UCS12CM0_ID 0xbc
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /* bis of the SYS_CTRL register */
64*4882a593Smuzhiyun #define UCS12CM0_EN_CLS BIT(0) /* Enables CLS function */
65*4882a593Smuzhiyun #define UCS12CM0_EN_IR BIT(1) /* Enables IR function */
66*4882a593Smuzhiyun #define UCS12CM0_EN_FRST BIT(5) /* Enables Brown Out Reset circuit */
67*4882a593Smuzhiyun #define UCS12CM0_EN_WAIT BIT(6) /* Waiting time will be inserted between two
68*4882a593Smuzhiyun * measurements
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun #define UCS12CM0_SWRST BIT(7) /* Software reset. Reset all register to
71*4882a593Smuzhiyun * default value
72*4882a593Smuzhiyun */
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* bis of the INT_FLAG register */
75*4882a593Smuzhiyun #define UCS12CM0_INT_CLS BIT(0) /* CLS Interrupt flag. It correlation with
76*4882a593Smuzhiyun * sensor data and CLS high/low threshold.
77*4882a593Smuzhiyun * Write zero to clear the flag.
78*4882a593Smuzhiyun */
79*4882a593Smuzhiyun #define UCS12CM0_INT_DATA BIT(6)/* It shows if any data is invalid after
80*4882a593Smuzhiyun * completion of each conversion cycle. This
81*4882a593Smuzhiyun * bit is read-only.
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun #define UCS12CM0_INT_POR BIT(7) /* Power-On-Reset Interrupt flag trigger the
84*4882a593Smuzhiyun * INT pin when the flag sets to one. Write
85*4882a593Smuzhiyun * zero to clear the flag.
86*4882a593Smuzhiyun */
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun #define UCS12CM0_CCT_CHANNEL(_si, _mod) { \
89*4882a593Smuzhiyun .type = IIO_CCT, \
90*4882a593Smuzhiyun .address = _si, \
91*4882a593Smuzhiyun .channel2 = _mod, \
92*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
93*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE) | \
94*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
95*4882a593Smuzhiyun .modified = 1, \
96*4882a593Smuzhiyun .scan_index = _si, \
97*4882a593Smuzhiyun .scan_type = { \
98*4882a593Smuzhiyun .sign = 'u', \
99*4882a593Smuzhiyun .realbits = 16, \
100*4882a593Smuzhiyun .storagebits = 16, \
101*4882a593Smuzhiyun }, \
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun enum {
105*4882a593Smuzhiyun UCS12CM0_CCT_READ,
106*4882a593Smuzhiyun UCS12CM0_CCT_GREEN,
107*4882a593Smuzhiyun UCS12CM0_CCT_BLUE,
108*4882a593Smuzhiyun UCS12CM0_CCT_WHITE,
109*4882a593Smuzhiyun UCS12CM0_CCT_ALL
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun struct ucs12cm0_scan {
113*4882a593Smuzhiyun u16 chans[4];
114*4882a593Smuzhiyun /* Ensure natural alignment of timestamp */
115*4882a593Smuzhiyun s64 timestamp;
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun struct ucs12cm0_data {
119*4882a593Smuzhiyun struct i2c_client *client;
120*4882a593Smuzhiyun int calibrated;
121*4882a593Smuzhiyun u32 raw[UCS12CM0_CCT_ALL];
122*4882a593Smuzhiyun u32 average[UCS12CM0_CCT_ALL];
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun static const u8 ucs12cm0_chan_regs[UCS12CM0_CCT_ALL] = {
126*4882a593Smuzhiyun UCS12CM0_CLS_R_DATA_L,
127*4882a593Smuzhiyun UCS12CM0_CLS_G_DATA_L,
128*4882a593Smuzhiyun UCS12CM0_CLS_B_DATA_L,
129*4882a593Smuzhiyun UCS12CM0_CLS_W_DATA_L
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static const struct iio_chan_spec ucs12cm0_channels[] = {
133*4882a593Smuzhiyun UCS12CM0_CCT_CHANNEL(UCS12CM0_CCT_READ, IIO_MOD_LIGHT_RED),
134*4882a593Smuzhiyun UCS12CM0_CCT_CHANNEL(UCS12CM0_CCT_GREEN, IIO_MOD_LIGHT_GREEN),
135*4882a593Smuzhiyun UCS12CM0_CCT_CHANNEL(UCS12CM0_CCT_BLUE, IIO_MOD_LIGHT_BLUE),
136*4882a593Smuzhiyun UCS12CM0_CCT_CHANNEL(UCS12CM0_CCT_WHITE, IIO_MOD_LIGHT_CLEAR),
137*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(4),
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
ucs12cm0_read(struct i2c_client * client,u8 cmd,void * databuf,u8 len)140*4882a593Smuzhiyun static int ucs12cm0_read(struct i2c_client *client, u8 cmd, void *databuf,
141*4882a593Smuzhiyun u8 len)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun struct i2c_msg msgs[2] = {
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun .addr = client->addr,
146*4882a593Smuzhiyun .len = sizeof(cmd),
147*4882a593Smuzhiyun .buf = (u8 *) &cmd
148*4882a593Smuzhiyun }, {
149*4882a593Smuzhiyun .addr = client->addr,
150*4882a593Smuzhiyun .len = len,
151*4882a593Smuzhiyun .buf = databuf,
152*4882a593Smuzhiyun .flags = I2C_M_RD
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun int ret;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
158*4882a593Smuzhiyun if (ret < 0)
159*4882a593Smuzhiyun dev_err(&client->dev, "failed reading register 0x%04x\n", cmd);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun return ret;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
ucs12cm0_read_byte(struct i2c_client * client,u8 cmd)164*4882a593Smuzhiyun static int ucs12cm0_read_byte(struct i2c_client *client, u8 cmd)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun u8 data;
167*4882a593Smuzhiyun int ret;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun ret = ucs12cm0_read(client, cmd, &data, sizeof(data));
170*4882a593Smuzhiyun if (ret < 0)
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun return data;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
ucs12cm0_read_word(struct i2c_client * client,u8 cmd)176*4882a593Smuzhiyun static int ucs12cm0_read_word(struct i2c_client *client, u8 cmd)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun __le16 data;
179*4882a593Smuzhiyun int ret;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun ret = ucs12cm0_read(client, cmd, &data, sizeof(data));
182*4882a593Smuzhiyun if (ret < 0)
183*4882a593Smuzhiyun return ret;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun return le16_to_cpu(data);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
ucs12cm0_read_average(struct ucs12cm0_data * data,int chan)188*4882a593Smuzhiyun static int ucs12cm0_read_average(struct ucs12cm0_data *data, int chan)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun u8 cmd;
191*4882a593Smuzhiyun int sum = 0;
192*4882a593Smuzhiyun int average;
193*4882a593Smuzhiyun int i;
194*4882a593Smuzhiyun int ret;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun cmd = ucs12cm0_chan_regs[chan];
197*4882a593Smuzhiyun for (i = 0; i < 10; ++i) {
198*4882a593Smuzhiyun ret = ucs12cm0_read_word(data->client, cmd);
199*4882a593Smuzhiyun if (ret < 0)
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun sum += ret;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun average = sum / 10;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun return average;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
ucs12cm0_write_byte(struct i2c_client * client,u8 cmd,u8 val)210*4882a593Smuzhiyun static int ucs12cm0_write_byte(struct i2c_client *client, u8 cmd, u8 val)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun u8 buf[2];
213*4882a593Smuzhiyun struct i2c_msg msgs[1] = {
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun .addr = client->addr,
216*4882a593Smuzhiyun .len = sizeof(buf),
217*4882a593Smuzhiyun .buf = (u8 *) &buf
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun };
220*4882a593Smuzhiyun int ret;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun buf[0] = cmd;
223*4882a593Smuzhiyun buf[1] = val;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
226*4882a593Smuzhiyun if (ret < 0) {
227*4882a593Smuzhiyun dev_err(&client->dev, "failed writing register 0x%04x\n", cmd);
228*4882a593Smuzhiyun return ret;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
ucs12cm0_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)234*4882a593Smuzhiyun static int ucs12cm0_read_raw(struct iio_dev *indio_dev,
235*4882a593Smuzhiyun struct iio_chan_spec const *chan,
236*4882a593Smuzhiyun int *val, int *val2, long mask)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
239*4882a593Smuzhiyun u8 cmd;
240*4882a593Smuzhiyun int ret;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun switch (mask) {
243*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
244*4882a593Smuzhiyun cmd = ucs12cm0_chan_regs[chan->address];
245*4882a593Smuzhiyun ret = ucs12cm0_read_word(data->client, cmd);
246*4882a593Smuzhiyun if (ret < 0)
247*4882a593Smuzhiyun return ret;
248*4882a593Smuzhiyun *val = ret;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun return IIO_VAL_INT;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
253*4882a593Smuzhiyun if (data->calibrated) {
254*4882a593Smuzhiyun *val = data->average[chan->address];
255*4882a593Smuzhiyun *val2 = data->raw[chan->address];
256*4882a593Smuzhiyun } else {
257*4882a593Smuzhiyun *val = 1;
258*4882a593Smuzhiyun *val2 = 1;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun return IIO_VAL_FRACTIONAL;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun case IIO_CHAN_INFO_AVERAGE_RAW:
264*4882a593Smuzhiyun *val = data->average[chan->address];
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun return IIO_VAL_INT;
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun default:
269*4882a593Smuzhiyun return -EINVAL;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
ucs12cm0_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)273*4882a593Smuzhiyun static int ucs12cm0_write_raw(struct iio_dev *indio_dev,
274*4882a593Smuzhiyun struct iio_chan_spec const *chan,
275*4882a593Smuzhiyun int val, int val2, long mask)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun switch (mask) {
280*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
281*4882a593Smuzhiyun data->raw[chan->address] = val;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun return 0;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
286*4882a593Smuzhiyun return -EPERM;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun case IIO_CHAN_INFO_AVERAGE_RAW:
289*4882a593Smuzhiyun return -EPERM;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun default:
292*4882a593Smuzhiyun return -EINVAL;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
ucs12cm0_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long mask)296*4882a593Smuzhiyun static int ucs12cm0_write_raw_get_fmt(struct iio_dev *indio_dev,
297*4882a593Smuzhiyun struct iio_chan_spec const *chan,
298*4882a593Smuzhiyun long mask)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun switch (mask) {
301*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
302*4882a593Smuzhiyun return IIO_VAL_INT;
303*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
304*4882a593Smuzhiyun return IIO_VAL_FRACTIONAL;
305*4882a593Smuzhiyun case IIO_CHAN_INFO_AVERAGE_RAW:
306*4882a593Smuzhiyun return IIO_VAL_INT;
307*4882a593Smuzhiyun default:
308*4882a593Smuzhiyun return -EINVAL;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
start_calibrating_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)312*4882a593Smuzhiyun static ssize_t start_calibrating_store(struct device *dev,
313*4882a593Smuzhiyun struct device_attribute *attr,
314*4882a593Smuzhiyun const char *buf, size_t len)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
317*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
318*4882a593Smuzhiyun int i;
319*4882a593Smuzhiyun long chans = 0;
320*4882a593Smuzhiyun int ret;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if (!strncmp(buf, "red", 3)) {
323*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_READ, &chans);
324*4882a593Smuzhiyun } else if (!strncmp(buf, "green", 5)) {
325*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_GREEN, &chans);
326*4882a593Smuzhiyun } else if (!strncmp(buf, "blue", 4)) {
327*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_BLUE, &chans);
328*4882a593Smuzhiyun } else if (!strncmp(buf, "white", 5)) {
329*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_WHITE, &chans);
330*4882a593Smuzhiyun } else if (!strncmp(buf, "all", 3)) {
331*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_READ, &chans);
332*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_GREEN, &chans);
333*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_BLUE, &chans);
334*4882a593Smuzhiyun set_bit(UCS12CM0_CCT_WHITE, &chans);
335*4882a593Smuzhiyun } else {
336*4882a593Smuzhiyun return -EINVAL;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun for_each_set_bit(i, &chans, UCS12CM0_CCT_ALL) {
340*4882a593Smuzhiyun if (!data->raw[i])
341*4882a593Smuzhiyun return -EPERM;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun dev_info(&data->client->dev, "raw = %d\n",
344*4882a593Smuzhiyun data->raw[i]);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun for_each_set_bit(i, &chans, UCS12CM0_CCT_ALL) {
348*4882a593Smuzhiyun ret = ucs12cm0_read_average(data, i);
349*4882a593Smuzhiyun if (ret < 0)
350*4882a593Smuzhiyun return ret;
351*4882a593Smuzhiyun else if (ret == 0)
352*4882a593Smuzhiyun return -EINVAL;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun data->average[i] = ret;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun dev_info(&data->client->dev, "average = %d\n",
357*4882a593Smuzhiyun data->average[i]);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /*
361*4882a593Smuzhiyun * TODO: store the calibration data in the ROM because UCS12CM0
362*4882a593Smuzhiyun * doesn't have any rom-related register.
363*4882a593Smuzhiyun */
364*4882a593Smuzhiyun data->calibrated = 1;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return len;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun static IIO_DEVICE_ATTR_WO(start_calibrating, 0);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun static struct attribute *ucs12cm0_attributes[] = {
372*4882a593Smuzhiyun &iio_dev_attr_start_calibrating.dev_attr.attr,
373*4882a593Smuzhiyun NULL
374*4882a593Smuzhiyun };
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun static const struct attribute_group ucs12cm0_attribute_group = {
377*4882a593Smuzhiyun .attrs = ucs12cm0_attributes,
378*4882a593Smuzhiyun };
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun static const struct iio_info ucs12cm0_info = {
381*4882a593Smuzhiyun .read_raw = ucs12cm0_read_raw,
382*4882a593Smuzhiyun .write_raw = ucs12cm0_write_raw,
383*4882a593Smuzhiyun .write_raw_get_fmt = ucs12cm0_write_raw_get_fmt,
384*4882a593Smuzhiyun .attrs = &ucs12cm0_attribute_group,
385*4882a593Smuzhiyun };
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /**
388*4882a593Smuzhiyun * ucs12cm0_active - enable or disable the CLS
389*4882a593Smuzhiyun * @client: the i2c client used by the driver.
390*4882a593Smuzhiyun * @enable: enable/disable the CLS of ucs12cm0.
391*4882a593Smuzhiyun *
392*4882a593Smuzhiyun * Returns negative errno, else the number of messages executed.
393*4882a593Smuzhiyun */
ucs12cm0_active(struct i2c_client * client,int enable)394*4882a593Smuzhiyun static int ucs12cm0_active(struct i2c_client *client, int enable)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun u8 val;
397*4882a593Smuzhiyun int ret = 0;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun ret = ucs12cm0_read_byte(client, UCS12CM0_SYS_CTRL);
400*4882a593Smuzhiyun if (ret < 0)
401*4882a593Smuzhiyun goto out;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun val = ret;
404*4882a593Smuzhiyun if (enable)
405*4882a593Smuzhiyun val |= UCS12CM0_EN_CLS;
406*4882a593Smuzhiyun else
407*4882a593Smuzhiyun val &= ~UCS12CM0_EN_CLS;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_SYS_CTRL, val);
410*4882a593Smuzhiyun if (ret < 0)
411*4882a593Smuzhiyun dev_err(&client->dev, "Failed to active sensor\n");
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun out:
414*4882a593Smuzhiyun return ret;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
ucs12cm0_buffer_postenable(struct iio_dev * indio_dev)417*4882a593Smuzhiyun static int ucs12cm0_buffer_postenable(struct iio_dev *indio_dev)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun return ucs12cm0_active(data->client, 1);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
ucs12cm0_buffer_predisable(struct iio_dev * indio_dev)424*4882a593Smuzhiyun static int ucs12cm0_buffer_predisable(struct iio_dev *indio_dev)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return ucs12cm0_active(data->client, 0);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun static const struct iio_buffer_setup_ops ucs12cm0_buffer_setup_ops = {
432*4882a593Smuzhiyun .postenable = ucs12cm0_buffer_postenable,
433*4882a593Smuzhiyun .predisable = ucs12cm0_buffer_predisable,
434*4882a593Smuzhiyun };
435*4882a593Smuzhiyun
ucs12cm0_init(struct ucs12cm0_data * data)436*4882a593Smuzhiyun static int ucs12cm0_init(struct ucs12cm0_data *data)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun int ret;
439*4882a593Smuzhiyun struct i2c_client *client = data->client;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_SYS_CTRL, 0x00);
442*4882a593Smuzhiyun if (ret < 0)
443*4882a593Smuzhiyun goto err;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_INT_CTRL, 0x13);
446*4882a593Smuzhiyun if (ret < 0)
447*4882a593Smuzhiyun goto err;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_INT_FLAG, 0x00);
450*4882a593Smuzhiyun if (ret < 0)
451*4882a593Smuzhiyun goto err;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_WAIT, 0x00);
454*4882a593Smuzhiyun if (ret < 0)
455*4882a593Smuzhiyun goto err;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_GAIN, 0x84);
458*4882a593Smuzhiyun if (ret < 0)
459*4882a593Smuzhiyun goto err;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_TIME, 0x33);
462*4882a593Smuzhiyun if (ret < 0)
463*4882a593Smuzhiyun goto err;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_LED, 0x00);
466*4882a593Smuzhiyun if (ret < 0)
467*4882a593Smuzhiyun goto err;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_GAIN, 0x00);
470*4882a593Smuzhiyun if (ret < 0)
471*4882a593Smuzhiyun goto err;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_PULSE, 0x00);
474*4882a593Smuzhiyun if (ret < 0)
475*4882a593Smuzhiyun goto err;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_TIME, 0x0f);
478*4882a593Smuzhiyun if (ret < 0)
479*4882a593Smuzhiyun goto err;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_AVERAGE, 0x0f);
482*4882a593Smuzhiyun if (ret < 0)
483*4882a593Smuzhiyun goto err;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_PERSIST, 0x00);
486*4882a593Smuzhiyun if (ret < 0)
487*4882a593Smuzhiyun goto err;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_PS_OFFSET_L, 0x0000);
490*4882a593Smuzhiyun if (ret < 0)
491*4882a593Smuzhiyun goto err;
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_THDHL, 0xff);
494*4882a593Smuzhiyun if (ret < 0)
495*4882a593Smuzhiyun goto err;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_THDHH, 0xff);
498*4882a593Smuzhiyun if (ret < 0)
499*4882a593Smuzhiyun goto err;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_THDLL, 0x00);
502*4882a593Smuzhiyun if (ret < 0)
503*4882a593Smuzhiyun goto err;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun ret = ucs12cm0_write_byte(client, UCS12CM0_ALS_THDLH, 0x00);
506*4882a593Smuzhiyun if (ret < 0)
507*4882a593Smuzhiyun goto err;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun return 0;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun err:
512*4882a593Smuzhiyun return ret;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
ucs12cm0_interrupt_handler(int irq,void * priv)515*4882a593Smuzhiyun static irqreturn_t ucs12cm0_interrupt_handler(int irq, void *priv)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun struct iio_dev *indio_dev = priv;
518*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
519*4882a593Smuzhiyun struct i2c_client *client = data->client;
520*4882a593Smuzhiyun struct ucs12cm0_scan scan;
521*4882a593Smuzhiyun int ret;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun ret = ucs12cm0_read_byte(client, UCS12CM0_INT_FLAG);
524*4882a593Smuzhiyun if (ret < 0)
525*4882a593Smuzhiyun goto out;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (ret & UCS12CM0_INT_CLS) {
528*4882a593Smuzhiyun if (ucs12cm0_read(client, UCS12CM0_CLS_R_DATA_L, scan.chans,
529*4882a593Smuzhiyun sizeof(scan.chans)) < 0)
530*4882a593Smuzhiyun goto clear_irq;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun iio_push_to_buffers_with_timestamp(indio_dev, &scan,
533*4882a593Smuzhiyun ktime_get_boottime_ns());
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun clear_irq:
537*4882a593Smuzhiyun if (ret & UCS12CM0_INT_CLS) {
538*4882a593Smuzhiyun ret &= ~UCS12CM0_INT_CLS;
539*4882a593Smuzhiyun ucs12cm0_write_byte(client, UCS12CM0_INT_FLAG, ret);
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun if (ret & UCS12CM0_INT_POR) {
543*4882a593Smuzhiyun ret &= ~UCS12CM0_INT_POR;
544*4882a593Smuzhiyun ucs12cm0_write_byte(client, UCS12CM0_INT_FLAG, ret);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun out:
548*4882a593Smuzhiyun return IRQ_HANDLED;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
ucs12cm0_probe(struct i2c_client * client,const struct i2c_device_id * id)551*4882a593Smuzhiyun static int ucs12cm0_probe(struct i2c_client *client,
552*4882a593Smuzhiyun const struct i2c_device_id *id)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun struct ucs12cm0_data *data;
555*4882a593Smuzhiyun struct iio_dev *indio_dev;
556*4882a593Smuzhiyun struct iio_buffer *buffer;
557*4882a593Smuzhiyun u32 type;
558*4882a593Smuzhiyun int ret;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
561*4882a593Smuzhiyun if (!indio_dev)
562*4882a593Smuzhiyun return -ENOMEM;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun buffer = devm_iio_kfifo_allocate(&client->dev);
565*4882a593Smuzhiyun if (!buffer)
566*4882a593Smuzhiyun return -ENOMEM;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun iio_device_attach_buffer(indio_dev, buffer);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun data = iio_priv(indio_dev);
571*4882a593Smuzhiyun i2c_set_clientdata(client, indio_dev);
572*4882a593Smuzhiyun data->client = client;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun indio_dev->info = &ucs12cm0_info;
575*4882a593Smuzhiyun indio_dev->channels = ucs12cm0_channels;
576*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(ucs12cm0_channels);
577*4882a593Smuzhiyun indio_dev->name = "ucs12cm0";
578*4882a593Smuzhiyun indio_dev->modes = (INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE);
579*4882a593Smuzhiyun indio_dev->setup_ops = &ucs12cm0_buffer_setup_ops;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun ret = ucs12cm0_init(data);
582*4882a593Smuzhiyun if (ret < 0)
583*4882a593Smuzhiyun return ret;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (client->irq <= 0) {
586*4882a593Smuzhiyun dev_err(&client->dev, "no valid irq defined\n");
587*4882a593Smuzhiyun return -EINVAL;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun type = irqd_get_trigger_type(irq_get_irq_data(client->irq));
591*4882a593Smuzhiyun if (type != IRQF_TRIGGER_LOW && type != IRQF_TRIGGER_FALLING) {
592*4882a593Smuzhiyun dev_err(&client->dev,
593*4882a593Smuzhiyun "unsupported IRQ trigger specified (%x)\n", type);
594*4882a593Smuzhiyun return -EINVAL;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun ret = devm_request_threaded_irq(&client->dev, client->irq,
598*4882a593Smuzhiyun NULL, ucs12cm0_interrupt_handler,
599*4882a593Smuzhiyun type | IRQF_ONESHOT, "ucs12cm0_irq",
600*4882a593Smuzhiyun indio_dev);
601*4882a593Smuzhiyun if (ret) {
602*4882a593Smuzhiyun dev_err(&client->dev, "request irq (%d) failed\n",
603*4882a593Smuzhiyun client->irq);
604*4882a593Smuzhiyun return ret;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun return devm_iio_device_register(&client->dev, indio_dev);
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun static const struct of_device_id ucs12cm0_of_match[] = {
611*4882a593Smuzhiyun { .compatible = "ultracapteur,ucs12cm0", },
612*4882a593Smuzhiyun { },
613*4882a593Smuzhiyun };
614*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ucs12cm0_of_match);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun static const struct i2c_device_id ucs12cm0_id[] = {
617*4882a593Smuzhiyun { "ucs12cm0", 0 },
618*4882a593Smuzhiyun { }
619*4882a593Smuzhiyun };
620*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, ucs12cm0_id);
621*4882a593Smuzhiyun
ucs12cm0_resume(struct device * dev)622*4882a593Smuzhiyun static int ucs12cm0_resume(struct device *dev)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
625*4882a593Smuzhiyun struct iio_dev *indio_dev = i2c_get_clientdata(client);
626*4882a593Smuzhiyun struct ucs12cm0_data *data = iio_priv(indio_dev);
627*4882a593Smuzhiyun int ret;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun ret = ucs12cm0_init(data);
630*4882a593Smuzhiyun if (ret < 0)
631*4882a593Smuzhiyun return ret;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun return 0;
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun static const struct dev_pm_ops ucs12cm0_pm_ops = {
637*4882a593Smuzhiyun .resume = ucs12cm0_resume,
638*4882a593Smuzhiyun };
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun static struct i2c_driver ucs12cm0_driver = {
641*4882a593Smuzhiyun .driver = {
642*4882a593Smuzhiyun .name = "ucs12cm0",
643*4882a593Smuzhiyun .of_match_table = ucs12cm0_of_match,
644*4882a593Smuzhiyun .pm = &ucs12cm0_pm_ops,
645*4882a593Smuzhiyun },
646*4882a593Smuzhiyun .probe = ucs12cm0_probe,
647*4882a593Smuzhiyun .id_table = ucs12cm0_id,
648*4882a593Smuzhiyun };
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun module_i2c_driver(ucs12cm0_driver);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun MODULE_AUTHOR("Jason Zhang <jason.zhang@rock-chips.com>");
653*4882a593Smuzhiyun MODULE_DESCRIPTION("UCS12CM0 illuminance and correlated color temperature sensor driver");
654*4882a593Smuzhiyun MODULE_LICENSE("GPL");
655