1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * A iio driver for the light sensor ISL 29018/29023/29035.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * IIO driver for monitoring ambient light intensity in luxi, proximity
6*4882a593Smuzhiyun * sensing and infrared sensing.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (c) 2010, NVIDIA Corporation.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/err.h>
14*4882a593Smuzhiyun #include <linux/mutex.h>
15*4882a593Smuzhiyun #include <linux/delay.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/iio/iio.h>
20*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
21*4882a593Smuzhiyun #include <linux/acpi.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define ISL29018_CONV_TIME_MS 100
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define ISL29018_REG_ADD_COMMAND1 0x00
26*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_SHIFT 5
27*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT)
28*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_POWER_DOWN 0
29*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_ALS_ONCE 1
30*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_IR_ONCE 2
31*4882a593Smuzhiyun #define ISL29018_CMD1_OPMODE_PROX_ONCE 3
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define ISL29018_REG_ADD_COMMAND2 0x01
34*4882a593Smuzhiyun #define ISL29018_CMD2_RESOLUTION_SHIFT 2
35*4882a593Smuzhiyun #define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define ISL29018_CMD2_RANGE_SHIFT 0
38*4882a593Smuzhiyun #define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define ISL29018_CMD2_SCHEME_SHIFT 7
41*4882a593Smuzhiyun #define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define ISL29018_REG_ADD_DATA_LSB 0x02
44*4882a593Smuzhiyun #define ISL29018_REG_ADD_DATA_MSB 0x03
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define ISL29018_REG_TEST 0x08
47*4882a593Smuzhiyun #define ISL29018_TEST_SHIFT 0
48*4882a593Smuzhiyun #define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define ISL29035_REG_DEVICE_ID 0x0F
51*4882a593Smuzhiyun #define ISL29035_DEVICE_ID_SHIFT 0x03
52*4882a593Smuzhiyun #define ISL29035_DEVICE_ID_MASK (0x7 << ISL29035_DEVICE_ID_SHIFT)
53*4882a593Smuzhiyun #define ISL29035_DEVICE_ID 0x5
54*4882a593Smuzhiyun #define ISL29035_BOUT_SHIFT 0x07
55*4882a593Smuzhiyun #define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT)
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun enum isl29018_int_time {
58*4882a593Smuzhiyun ISL29018_INT_TIME_16,
59*4882a593Smuzhiyun ISL29018_INT_TIME_12,
60*4882a593Smuzhiyun ISL29018_INT_TIME_8,
61*4882a593Smuzhiyun ISL29018_INT_TIME_4,
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun static const unsigned int isl29018_int_utimes[3][4] = {
65*4882a593Smuzhiyun {90000, 5630, 351, 21},
66*4882a593Smuzhiyun {90000, 5600, 352, 22},
67*4882a593Smuzhiyun {105000, 6500, 410, 25},
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun static const struct isl29018_scale {
71*4882a593Smuzhiyun unsigned int scale;
72*4882a593Smuzhiyun unsigned int uscale;
73*4882a593Smuzhiyun } isl29018_scales[4][4] = {
74*4882a593Smuzhiyun { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} },
75*4882a593Smuzhiyun { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} },
76*4882a593Smuzhiyun { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} },
77*4882a593Smuzhiyun { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} }
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun struct isl29018_chip {
81*4882a593Smuzhiyun struct regmap *regmap;
82*4882a593Smuzhiyun struct mutex lock;
83*4882a593Smuzhiyun int type;
84*4882a593Smuzhiyun unsigned int calibscale;
85*4882a593Smuzhiyun unsigned int ucalibscale;
86*4882a593Smuzhiyun unsigned int int_time;
87*4882a593Smuzhiyun struct isl29018_scale scale;
88*4882a593Smuzhiyun int prox_scheme;
89*4882a593Smuzhiyun bool suspended;
90*4882a593Smuzhiyun struct regulator *vcc_reg;
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
isl29018_set_integration_time(struct isl29018_chip * chip,unsigned int utime)93*4882a593Smuzhiyun static int isl29018_set_integration_time(struct isl29018_chip *chip,
94*4882a593Smuzhiyun unsigned int utime)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun unsigned int i;
97*4882a593Smuzhiyun int ret;
98*4882a593Smuzhiyun unsigned int int_time, new_int_time;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) {
101*4882a593Smuzhiyun if (utime == isl29018_int_utimes[chip->type][i]) {
102*4882a593Smuzhiyun new_int_time = i;
103*4882a593Smuzhiyun break;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type]))
108*4882a593Smuzhiyun return -EINVAL;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
111*4882a593Smuzhiyun ISL29018_CMD2_RESOLUTION_MASK,
112*4882a593Smuzhiyun i << ISL29018_CMD2_RESOLUTION_SHIFT);
113*4882a593Smuzhiyun if (ret < 0)
114*4882a593Smuzhiyun return ret;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* Keep the same range when integration time changes */
117*4882a593Smuzhiyun int_time = chip->int_time;
118*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) {
119*4882a593Smuzhiyun if (chip->scale.scale == isl29018_scales[int_time][i].scale &&
120*4882a593Smuzhiyun chip->scale.uscale == isl29018_scales[int_time][i].uscale) {
121*4882a593Smuzhiyun chip->scale = isl29018_scales[new_int_time][i];
122*4882a593Smuzhiyun break;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun chip->int_time = new_int_time;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun return 0;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
isl29018_set_scale(struct isl29018_chip * chip,int scale,int uscale)130*4882a593Smuzhiyun static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun unsigned int i;
133*4882a593Smuzhiyun int ret;
134*4882a593Smuzhiyun struct isl29018_scale new_scale;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) {
137*4882a593Smuzhiyun if (scale == isl29018_scales[chip->int_time][i].scale &&
138*4882a593Smuzhiyun uscale == isl29018_scales[chip->int_time][i].uscale) {
139*4882a593Smuzhiyun new_scale = isl29018_scales[chip->int_time][i];
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time]))
145*4882a593Smuzhiyun return -EINVAL;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
148*4882a593Smuzhiyun ISL29018_CMD2_RANGE_MASK,
149*4882a593Smuzhiyun i << ISL29018_CMD2_RANGE_SHIFT);
150*4882a593Smuzhiyun if (ret < 0)
151*4882a593Smuzhiyun return ret;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun chip->scale = new_scale;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
isl29018_read_sensor_input(struct isl29018_chip * chip,int mode)158*4882a593Smuzhiyun static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun int status;
161*4882a593Smuzhiyun unsigned int lsb;
162*4882a593Smuzhiyun unsigned int msb;
163*4882a593Smuzhiyun struct device *dev = regmap_get_device(chip->regmap);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* Set mode */
166*4882a593Smuzhiyun status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
167*4882a593Smuzhiyun mode << ISL29018_CMD1_OPMODE_SHIFT);
168*4882a593Smuzhiyun if (status) {
169*4882a593Smuzhiyun dev_err(dev,
170*4882a593Smuzhiyun "Error in setting operating mode err %d\n", status);
171*4882a593Smuzhiyun return status;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun msleep(ISL29018_CONV_TIME_MS);
174*4882a593Smuzhiyun status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
175*4882a593Smuzhiyun if (status < 0) {
176*4882a593Smuzhiyun dev_err(dev,
177*4882a593Smuzhiyun "Error in reading LSB DATA with err %d\n", status);
178*4882a593Smuzhiyun return status;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
182*4882a593Smuzhiyun if (status < 0) {
183*4882a593Smuzhiyun dev_err(dev,
184*4882a593Smuzhiyun "Error in reading MSB DATA with error %d\n", status);
185*4882a593Smuzhiyun return status;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return (msb << 8) | lsb;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
isl29018_read_lux(struct isl29018_chip * chip,int * lux)192*4882a593Smuzhiyun static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun int lux_data;
195*4882a593Smuzhiyun unsigned int data_x_range;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun lux_data = isl29018_read_sensor_input(chip,
198*4882a593Smuzhiyun ISL29018_CMD1_OPMODE_ALS_ONCE);
199*4882a593Smuzhiyun if (lux_data < 0)
200*4882a593Smuzhiyun return lux_data;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun data_x_range = lux_data * chip->scale.scale +
203*4882a593Smuzhiyun lux_data * chip->scale.uscale / 1000000;
204*4882a593Smuzhiyun *lux = data_x_range * chip->calibscale +
205*4882a593Smuzhiyun data_x_range * chip->ucalibscale / 1000000;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun return 0;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
isl29018_read_ir(struct isl29018_chip * chip,int * ir)210*4882a593Smuzhiyun static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun int ir_data;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun ir_data = isl29018_read_sensor_input(chip,
215*4882a593Smuzhiyun ISL29018_CMD1_OPMODE_IR_ONCE);
216*4882a593Smuzhiyun if (ir_data < 0)
217*4882a593Smuzhiyun return ir_data;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun *ir = ir_data;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return 0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
isl29018_read_proximity_ir(struct isl29018_chip * chip,int scheme,int * near_ir)224*4882a593Smuzhiyun static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
225*4882a593Smuzhiyun int *near_ir)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun int status;
228*4882a593Smuzhiyun int prox_data = -1;
229*4882a593Smuzhiyun int ir_data = -1;
230*4882a593Smuzhiyun struct device *dev = regmap_get_device(chip->regmap);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /* Do proximity sensing with required scheme */
233*4882a593Smuzhiyun status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
234*4882a593Smuzhiyun ISL29018_CMD2_SCHEME_MASK,
235*4882a593Smuzhiyun scheme << ISL29018_CMD2_SCHEME_SHIFT);
236*4882a593Smuzhiyun if (status) {
237*4882a593Smuzhiyun dev_err(dev, "Error in setting operating mode\n");
238*4882a593Smuzhiyun return status;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun prox_data = isl29018_read_sensor_input(chip,
242*4882a593Smuzhiyun ISL29018_CMD1_OPMODE_PROX_ONCE);
243*4882a593Smuzhiyun if (prox_data < 0)
244*4882a593Smuzhiyun return prox_data;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (scheme == 1) {
247*4882a593Smuzhiyun *near_ir = prox_data;
248*4882a593Smuzhiyun return 0;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun ir_data = isl29018_read_sensor_input(chip,
252*4882a593Smuzhiyun ISL29018_CMD1_OPMODE_IR_ONCE);
253*4882a593Smuzhiyun if (ir_data < 0)
254*4882a593Smuzhiyun return ir_data;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (prox_data >= ir_data)
257*4882a593Smuzhiyun *near_ir = prox_data - ir_data;
258*4882a593Smuzhiyun else
259*4882a593Smuzhiyun *near_ir = 0;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun return 0;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
in_illuminance_scale_available_show(struct device * dev,struct device_attribute * attr,char * buf)264*4882a593Smuzhiyun static ssize_t in_illuminance_scale_available_show
265*4882a593Smuzhiyun (struct device *dev, struct device_attribute *attr,
266*4882a593Smuzhiyun char *buf)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
269*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
270*4882a593Smuzhiyun unsigned int i;
271*4882a593Smuzhiyun int len = 0;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun mutex_lock(&chip->lock);
274*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i)
275*4882a593Smuzhiyun len += sprintf(buf + len, "%d.%06d ",
276*4882a593Smuzhiyun isl29018_scales[chip->int_time][i].scale,
277*4882a593Smuzhiyun isl29018_scales[chip->int_time][i].uscale);
278*4882a593Smuzhiyun mutex_unlock(&chip->lock);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun buf[len - 1] = '\n';
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun return len;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
in_illuminance_integration_time_available_show(struct device * dev,struct device_attribute * attr,char * buf)285*4882a593Smuzhiyun static ssize_t in_illuminance_integration_time_available_show
286*4882a593Smuzhiyun (struct device *dev, struct device_attribute *attr,
287*4882a593Smuzhiyun char *buf)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
290*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
291*4882a593Smuzhiyun unsigned int i;
292*4882a593Smuzhiyun int len = 0;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i)
295*4882a593Smuzhiyun len += sprintf(buf + len, "0.%06d ",
296*4882a593Smuzhiyun isl29018_int_utimes[chip->type][i]);
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun buf[len - 1] = '\n';
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun return len;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /*
304*4882a593Smuzhiyun * From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the
305*4882a593Smuzhiyun * infrared suppression:
306*4882a593Smuzhiyun *
307*4882a593Smuzhiyun * Proximity Sensing Scheme: Bit 7. This bit programs the function
308*4882a593Smuzhiyun * of the proximity detection. Logic 0 of this bit, Scheme 0, makes
309*4882a593Smuzhiyun * full n (4, 8, 12, 16) bits (unsigned) proximity detection. The range
310*4882a593Smuzhiyun * of Scheme 0 proximity count is from 0 to 2^n. Logic 1 of this bit,
311*4882a593Smuzhiyun * Scheme 1, makes n-1 (3, 7, 11, 15) bits (2's complementary)
312*4882a593Smuzhiyun * proximity_less_ambient detection. The range of Scheme 1
313*4882a593Smuzhiyun * proximity count is from -2^(n-1) to 2^(n-1) . The sign bit is extended
314*4882a593Smuzhiyun * for resolutions less than 16. While Scheme 0 has wider dynamic
315*4882a593Smuzhiyun * range, Scheme 1 proximity detection is less affected by the
316*4882a593Smuzhiyun * ambient IR noise variation.
317*4882a593Smuzhiyun *
318*4882a593Smuzhiyun * 0 Sensing IR from LED and ambient
319*4882a593Smuzhiyun * 1 Sensing IR from LED with ambient IR rejection
320*4882a593Smuzhiyun */
proximity_on_chip_ambient_infrared_suppression_show(struct device * dev,struct device_attribute * attr,char * buf)321*4882a593Smuzhiyun static ssize_t proximity_on_chip_ambient_infrared_suppression_show
322*4882a593Smuzhiyun (struct device *dev, struct device_attribute *attr,
323*4882a593Smuzhiyun char *buf)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
326*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun /*
329*4882a593Smuzhiyun * Return the "proximity scheme" i.e. if the chip does on chip
330*4882a593Smuzhiyun * infrared suppression (1 means perform on chip suppression)
331*4882a593Smuzhiyun */
332*4882a593Smuzhiyun return sprintf(buf, "%d\n", chip->prox_scheme);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
proximity_on_chip_ambient_infrared_suppression_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)335*4882a593Smuzhiyun static ssize_t proximity_on_chip_ambient_infrared_suppression_store
336*4882a593Smuzhiyun (struct device *dev, struct device_attribute *attr,
337*4882a593Smuzhiyun const char *buf, size_t count)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun struct iio_dev *indio_dev = dev_to_iio_dev(dev);
340*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
341*4882a593Smuzhiyun int val;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun if (kstrtoint(buf, 10, &val))
344*4882a593Smuzhiyun return -EINVAL;
345*4882a593Smuzhiyun if (!(val == 0 || val == 1))
346*4882a593Smuzhiyun return -EINVAL;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /*
349*4882a593Smuzhiyun * Get the "proximity scheme" i.e. if the chip does on chip
350*4882a593Smuzhiyun * infrared suppression (1 means perform on chip suppression)
351*4882a593Smuzhiyun */
352*4882a593Smuzhiyun mutex_lock(&chip->lock);
353*4882a593Smuzhiyun chip->prox_scheme = val;
354*4882a593Smuzhiyun mutex_unlock(&chip->lock);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return count;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun
isl29018_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)359*4882a593Smuzhiyun static int isl29018_write_raw(struct iio_dev *indio_dev,
360*4882a593Smuzhiyun struct iio_chan_spec const *chan,
361*4882a593Smuzhiyun int val,
362*4882a593Smuzhiyun int val2,
363*4882a593Smuzhiyun long mask)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
366*4882a593Smuzhiyun int ret = -EINVAL;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun mutex_lock(&chip->lock);
369*4882a593Smuzhiyun if (chip->suspended) {
370*4882a593Smuzhiyun ret = -EBUSY;
371*4882a593Smuzhiyun goto write_done;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun switch (mask) {
374*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBSCALE:
375*4882a593Smuzhiyun if (chan->type == IIO_LIGHT) {
376*4882a593Smuzhiyun chip->calibscale = val;
377*4882a593Smuzhiyun chip->ucalibscale = val2;
378*4882a593Smuzhiyun ret = 0;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun break;
381*4882a593Smuzhiyun case IIO_CHAN_INFO_INT_TIME:
382*4882a593Smuzhiyun if (chan->type == IIO_LIGHT && !val)
383*4882a593Smuzhiyun ret = isl29018_set_integration_time(chip, val2);
384*4882a593Smuzhiyun break;
385*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
386*4882a593Smuzhiyun if (chan->type == IIO_LIGHT)
387*4882a593Smuzhiyun ret = isl29018_set_scale(chip, val, val2);
388*4882a593Smuzhiyun break;
389*4882a593Smuzhiyun default:
390*4882a593Smuzhiyun break;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun write_done:
394*4882a593Smuzhiyun mutex_unlock(&chip->lock);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun return ret;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
isl29018_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)399*4882a593Smuzhiyun static int isl29018_read_raw(struct iio_dev *indio_dev,
400*4882a593Smuzhiyun struct iio_chan_spec const *chan,
401*4882a593Smuzhiyun int *val,
402*4882a593Smuzhiyun int *val2,
403*4882a593Smuzhiyun long mask)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun int ret = -EINVAL;
406*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(indio_dev);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun mutex_lock(&chip->lock);
409*4882a593Smuzhiyun if (chip->suspended) {
410*4882a593Smuzhiyun ret = -EBUSY;
411*4882a593Smuzhiyun goto read_done;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun switch (mask) {
414*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
415*4882a593Smuzhiyun case IIO_CHAN_INFO_PROCESSED:
416*4882a593Smuzhiyun switch (chan->type) {
417*4882a593Smuzhiyun case IIO_LIGHT:
418*4882a593Smuzhiyun ret = isl29018_read_lux(chip, val);
419*4882a593Smuzhiyun break;
420*4882a593Smuzhiyun case IIO_INTENSITY:
421*4882a593Smuzhiyun ret = isl29018_read_ir(chip, val);
422*4882a593Smuzhiyun break;
423*4882a593Smuzhiyun case IIO_PROXIMITY:
424*4882a593Smuzhiyun ret = isl29018_read_proximity_ir(chip,
425*4882a593Smuzhiyun chip->prox_scheme,
426*4882a593Smuzhiyun val);
427*4882a593Smuzhiyun break;
428*4882a593Smuzhiyun default:
429*4882a593Smuzhiyun break;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun if (!ret)
432*4882a593Smuzhiyun ret = IIO_VAL_INT;
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun case IIO_CHAN_INFO_INT_TIME:
435*4882a593Smuzhiyun if (chan->type == IIO_LIGHT) {
436*4882a593Smuzhiyun *val = 0;
437*4882a593Smuzhiyun *val2 = isl29018_int_utimes[chip->type][chip->int_time];
438*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
442*4882a593Smuzhiyun if (chan->type == IIO_LIGHT) {
443*4882a593Smuzhiyun *val = chip->scale.scale;
444*4882a593Smuzhiyun *val2 = chip->scale.uscale;
445*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun break;
448*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBSCALE:
449*4882a593Smuzhiyun if (chan->type == IIO_LIGHT) {
450*4882a593Smuzhiyun *val = chip->calibscale;
451*4882a593Smuzhiyun *val2 = chip->ucalibscale;
452*4882a593Smuzhiyun ret = IIO_VAL_INT_PLUS_MICRO;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun break;
455*4882a593Smuzhiyun default:
456*4882a593Smuzhiyun break;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun read_done:
460*4882a593Smuzhiyun mutex_unlock(&chip->lock);
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun return ret;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun #define ISL29018_LIGHT_CHANNEL { \
466*4882a593Smuzhiyun .type = IIO_LIGHT, \
467*4882a593Smuzhiyun .indexed = 1, \
468*4882a593Smuzhiyun .channel = 0, \
469*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \
470*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBSCALE) | \
471*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE) | \
472*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_INT_TIME), \
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun #define ISL29018_IR_CHANNEL { \
476*4882a593Smuzhiyun .type = IIO_INTENSITY, \
477*4882a593Smuzhiyun .modified = 1, \
478*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
479*4882a593Smuzhiyun .channel2 = IIO_MOD_LIGHT_IR, \
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun #define ISL29018_PROXIMITY_CHANNEL { \
483*4882a593Smuzhiyun .type = IIO_PROXIMITY, \
484*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun static const struct iio_chan_spec isl29018_channels[] = {
488*4882a593Smuzhiyun ISL29018_LIGHT_CHANNEL,
489*4882a593Smuzhiyun ISL29018_IR_CHANNEL,
490*4882a593Smuzhiyun ISL29018_PROXIMITY_CHANNEL,
491*4882a593Smuzhiyun };
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun static const struct iio_chan_spec isl29023_channels[] = {
494*4882a593Smuzhiyun ISL29018_LIGHT_CHANNEL,
495*4882a593Smuzhiyun ISL29018_IR_CHANNEL,
496*4882a593Smuzhiyun };
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0);
499*4882a593Smuzhiyun static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0);
500*4882a593Smuzhiyun static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun static struct attribute *isl29018_attributes[] = {
505*4882a593Smuzhiyun ISL29018_DEV_ATTR(in_illuminance_scale_available),
506*4882a593Smuzhiyun ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
507*4882a593Smuzhiyun ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression),
508*4882a593Smuzhiyun NULL
509*4882a593Smuzhiyun };
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun static struct attribute *isl29023_attributes[] = {
512*4882a593Smuzhiyun ISL29018_DEV_ATTR(in_illuminance_scale_available),
513*4882a593Smuzhiyun ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
514*4882a593Smuzhiyun NULL
515*4882a593Smuzhiyun };
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun static const struct attribute_group isl29018_group = {
518*4882a593Smuzhiyun .attrs = isl29018_attributes,
519*4882a593Smuzhiyun };
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun static const struct attribute_group isl29023_group = {
522*4882a593Smuzhiyun .attrs = isl29023_attributes,
523*4882a593Smuzhiyun };
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun enum {
526*4882a593Smuzhiyun isl29018,
527*4882a593Smuzhiyun isl29023,
528*4882a593Smuzhiyun isl29035,
529*4882a593Smuzhiyun };
530*4882a593Smuzhiyun
isl29018_chip_init(struct isl29018_chip * chip)531*4882a593Smuzhiyun static int isl29018_chip_init(struct isl29018_chip *chip)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun int status;
534*4882a593Smuzhiyun struct device *dev = regmap_get_device(chip->regmap);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (chip->type == isl29035) {
537*4882a593Smuzhiyun unsigned int id;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id);
540*4882a593Smuzhiyun if (status < 0) {
541*4882a593Smuzhiyun dev_err(dev,
542*4882a593Smuzhiyun "Error reading ID register with error %d\n",
543*4882a593Smuzhiyun status);
544*4882a593Smuzhiyun return status;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (id != ISL29035_DEVICE_ID)
550*4882a593Smuzhiyun return -ENODEV;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun /* Clear brownout bit */
553*4882a593Smuzhiyun status = regmap_update_bits(chip->regmap,
554*4882a593Smuzhiyun ISL29035_REG_DEVICE_ID,
555*4882a593Smuzhiyun ISL29035_BOUT_MASK, 0);
556*4882a593Smuzhiyun if (status < 0)
557*4882a593Smuzhiyun return status;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun /*
561*4882a593Smuzhiyun * Code added per Intersil Application Note 1534:
562*4882a593Smuzhiyun * When VDD sinks to approximately 1.8V or below, some of
563*4882a593Smuzhiyun * the part's registers may change their state. When VDD
564*4882a593Smuzhiyun * recovers to 2.25V (or greater), the part may thus be in an
565*4882a593Smuzhiyun * unknown mode of operation. The user can return the part to
566*4882a593Smuzhiyun * a known mode of operation either by (a) setting VDD = 0V for
567*4882a593Smuzhiyun * 1 second or more and then powering back up with a slew rate
568*4882a593Smuzhiyun * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
569*4882a593Smuzhiyun * conversions, clear the test registers, and then rewrite all
570*4882a593Smuzhiyun * registers to the desired values.
571*4882a593Smuzhiyun * ...
572*4882a593Smuzhiyun * For ISL29011, ISL29018, ISL29021, ISL29023
573*4882a593Smuzhiyun * 1. Write 0x00 to register 0x08 (TEST)
574*4882a593Smuzhiyun * 2. Write 0x00 to register 0x00 (CMD1)
575*4882a593Smuzhiyun * 3. Rewrite all registers to the desired values
576*4882a593Smuzhiyun *
577*4882a593Smuzhiyun * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
578*4882a593Smuzhiyun * the same thing EXCEPT the data sheet asks for a 1ms delay after
579*4882a593Smuzhiyun * writing the CMD1 register.
580*4882a593Smuzhiyun */
581*4882a593Smuzhiyun status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
582*4882a593Smuzhiyun if (status < 0) {
583*4882a593Smuzhiyun dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n",
584*4882a593Smuzhiyun status);
585*4882a593Smuzhiyun return status;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun /*
589*4882a593Smuzhiyun * See Intersil AN1534 comments above.
590*4882a593Smuzhiyun * "Operating Mode" (COMMAND1) register is reprogrammed when
591*4882a593Smuzhiyun * data is read from the device.
592*4882a593Smuzhiyun */
593*4882a593Smuzhiyun status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
594*4882a593Smuzhiyun if (status < 0) {
595*4882a593Smuzhiyun dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n",
596*4882a593Smuzhiyun status);
597*4882a593Smuzhiyun return status;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun usleep_range(1000, 2000); /* per data sheet, page 10 */
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* Set defaults */
603*4882a593Smuzhiyun status = isl29018_set_scale(chip, chip->scale.scale,
604*4882a593Smuzhiyun chip->scale.uscale);
605*4882a593Smuzhiyun if (status < 0) {
606*4882a593Smuzhiyun dev_err(dev, "Init of isl29018 fails\n");
607*4882a593Smuzhiyun return status;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun status = isl29018_set_integration_time(chip,
611*4882a593Smuzhiyun isl29018_int_utimes[chip->type][chip->int_time]);
612*4882a593Smuzhiyun if (status < 0)
613*4882a593Smuzhiyun dev_err(dev, "Init of isl29018 fails\n");
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun return status;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun static const struct iio_info isl29018_info = {
619*4882a593Smuzhiyun .attrs = &isl29018_group,
620*4882a593Smuzhiyun .read_raw = isl29018_read_raw,
621*4882a593Smuzhiyun .write_raw = isl29018_write_raw,
622*4882a593Smuzhiyun };
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun static const struct iio_info isl29023_info = {
625*4882a593Smuzhiyun .attrs = &isl29023_group,
626*4882a593Smuzhiyun .read_raw = isl29018_read_raw,
627*4882a593Smuzhiyun .write_raw = isl29018_write_raw,
628*4882a593Smuzhiyun };
629*4882a593Smuzhiyun
isl29018_is_volatile_reg(struct device * dev,unsigned int reg)630*4882a593Smuzhiyun static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun switch (reg) {
633*4882a593Smuzhiyun case ISL29018_REG_ADD_DATA_LSB:
634*4882a593Smuzhiyun case ISL29018_REG_ADD_DATA_MSB:
635*4882a593Smuzhiyun case ISL29018_REG_ADD_COMMAND1:
636*4882a593Smuzhiyun case ISL29018_REG_TEST:
637*4882a593Smuzhiyun case ISL29035_REG_DEVICE_ID:
638*4882a593Smuzhiyun return true;
639*4882a593Smuzhiyun default:
640*4882a593Smuzhiyun return false;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun static const struct regmap_config isl29018_regmap_config = {
645*4882a593Smuzhiyun .reg_bits = 8,
646*4882a593Smuzhiyun .val_bits = 8,
647*4882a593Smuzhiyun .volatile_reg = isl29018_is_volatile_reg,
648*4882a593Smuzhiyun .max_register = ISL29018_REG_TEST,
649*4882a593Smuzhiyun .num_reg_defaults_raw = ISL29018_REG_TEST + 1,
650*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
651*4882a593Smuzhiyun };
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun static const struct regmap_config isl29035_regmap_config = {
654*4882a593Smuzhiyun .reg_bits = 8,
655*4882a593Smuzhiyun .val_bits = 8,
656*4882a593Smuzhiyun .volatile_reg = isl29018_is_volatile_reg,
657*4882a593Smuzhiyun .max_register = ISL29035_REG_DEVICE_ID,
658*4882a593Smuzhiyun .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1,
659*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
660*4882a593Smuzhiyun };
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun struct isl29018_chip_info {
663*4882a593Smuzhiyun const struct iio_chan_spec *channels;
664*4882a593Smuzhiyun int num_channels;
665*4882a593Smuzhiyun const struct iio_info *indio_info;
666*4882a593Smuzhiyun const struct regmap_config *regmap_cfg;
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
670*4882a593Smuzhiyun [isl29018] = {
671*4882a593Smuzhiyun .channels = isl29018_channels,
672*4882a593Smuzhiyun .num_channels = ARRAY_SIZE(isl29018_channels),
673*4882a593Smuzhiyun .indio_info = &isl29018_info,
674*4882a593Smuzhiyun .regmap_cfg = &isl29018_regmap_config,
675*4882a593Smuzhiyun },
676*4882a593Smuzhiyun [isl29023] = {
677*4882a593Smuzhiyun .channels = isl29023_channels,
678*4882a593Smuzhiyun .num_channels = ARRAY_SIZE(isl29023_channels),
679*4882a593Smuzhiyun .indio_info = &isl29023_info,
680*4882a593Smuzhiyun .regmap_cfg = &isl29018_regmap_config,
681*4882a593Smuzhiyun },
682*4882a593Smuzhiyun [isl29035] = {
683*4882a593Smuzhiyun .channels = isl29023_channels,
684*4882a593Smuzhiyun .num_channels = ARRAY_SIZE(isl29023_channels),
685*4882a593Smuzhiyun .indio_info = &isl29023_info,
686*4882a593Smuzhiyun .regmap_cfg = &isl29035_regmap_config,
687*4882a593Smuzhiyun },
688*4882a593Smuzhiyun };
689*4882a593Smuzhiyun
isl29018_match_acpi_device(struct device * dev,int * data)690*4882a593Smuzhiyun static const char *isl29018_match_acpi_device(struct device *dev, int *data)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun const struct acpi_device_id *id;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun id = acpi_match_device(dev->driver->acpi_match_table, dev);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (!id)
697*4882a593Smuzhiyun return NULL;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun *data = (int)id->driver_data;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun return dev_name(dev);
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun
isl29018_disable_regulator_action(void * _data)704*4882a593Smuzhiyun static void isl29018_disable_regulator_action(void *_data)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun struct isl29018_chip *chip = _data;
707*4882a593Smuzhiyun int err;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun err = regulator_disable(chip->vcc_reg);
710*4882a593Smuzhiyun if (err)
711*4882a593Smuzhiyun pr_err("failed to disable isl29018's VCC regulator!\n");
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
isl29018_probe(struct i2c_client * client,const struct i2c_device_id * id)714*4882a593Smuzhiyun static int isl29018_probe(struct i2c_client *client,
715*4882a593Smuzhiyun const struct i2c_device_id *id)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun struct isl29018_chip *chip;
718*4882a593Smuzhiyun struct iio_dev *indio_dev;
719*4882a593Smuzhiyun int err;
720*4882a593Smuzhiyun const char *name = NULL;
721*4882a593Smuzhiyun int dev_id = 0;
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
724*4882a593Smuzhiyun if (!indio_dev)
725*4882a593Smuzhiyun return -ENOMEM;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun chip = iio_priv(indio_dev);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun i2c_set_clientdata(client, indio_dev);
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun if (id) {
732*4882a593Smuzhiyun name = id->name;
733*4882a593Smuzhiyun dev_id = id->driver_data;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun if (ACPI_HANDLE(&client->dev))
737*4882a593Smuzhiyun name = isl29018_match_acpi_device(&client->dev, &dev_id);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun mutex_init(&chip->lock);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun chip->type = dev_id;
742*4882a593Smuzhiyun chip->calibscale = 1;
743*4882a593Smuzhiyun chip->ucalibscale = 0;
744*4882a593Smuzhiyun chip->int_time = ISL29018_INT_TIME_16;
745*4882a593Smuzhiyun chip->scale = isl29018_scales[chip->int_time][0];
746*4882a593Smuzhiyun chip->suspended = false;
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun chip->vcc_reg = devm_regulator_get(&client->dev, "vcc");
749*4882a593Smuzhiyun if (IS_ERR(chip->vcc_reg))
750*4882a593Smuzhiyun return dev_err_probe(&client->dev, PTR_ERR(chip->vcc_reg),
751*4882a593Smuzhiyun "failed to get VCC regulator!\n");
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun err = regulator_enable(chip->vcc_reg);
754*4882a593Smuzhiyun if (err) {
755*4882a593Smuzhiyun dev_err(&client->dev, "failed to enable VCC regulator!\n");
756*4882a593Smuzhiyun return err;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun err = devm_add_action_or_reset(&client->dev, isl29018_disable_regulator_action,
760*4882a593Smuzhiyun chip);
761*4882a593Smuzhiyun if (err) {
762*4882a593Smuzhiyun dev_err(&client->dev, "failed to setup regulator cleanup action!\n");
763*4882a593Smuzhiyun return err;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun chip->regmap = devm_regmap_init_i2c(client,
767*4882a593Smuzhiyun isl29018_chip_info_tbl[dev_id].regmap_cfg);
768*4882a593Smuzhiyun if (IS_ERR(chip->regmap)) {
769*4882a593Smuzhiyun err = PTR_ERR(chip->regmap);
770*4882a593Smuzhiyun dev_err(&client->dev, "regmap initialization fails: %d\n", err);
771*4882a593Smuzhiyun return err;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun err = isl29018_chip_init(chip);
775*4882a593Smuzhiyun if (err)
776*4882a593Smuzhiyun return err;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info;
779*4882a593Smuzhiyun indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
780*4882a593Smuzhiyun indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
781*4882a593Smuzhiyun indio_dev->name = name;
782*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun return devm_iio_device_register(&client->dev, indio_dev);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
isl29018_suspend(struct device * dev)788*4882a593Smuzhiyun static int isl29018_suspend(struct device *dev)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
791*4882a593Smuzhiyun int ret;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun mutex_lock(&chip->lock);
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun /*
796*4882a593Smuzhiyun * Since this driver uses only polling commands, we are by default in
797*4882a593Smuzhiyun * auto shutdown (ie, power-down) mode.
798*4882a593Smuzhiyun * So we do not have much to do here.
799*4882a593Smuzhiyun */
800*4882a593Smuzhiyun chip->suspended = true;
801*4882a593Smuzhiyun ret = regulator_disable(chip->vcc_reg);
802*4882a593Smuzhiyun if (ret)
803*4882a593Smuzhiyun dev_err(dev, "failed to disable VCC regulator\n");
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun mutex_unlock(&chip->lock);
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun return ret;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun
isl29018_resume(struct device * dev)810*4882a593Smuzhiyun static int isl29018_resume(struct device *dev)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
813*4882a593Smuzhiyun int err;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun mutex_lock(&chip->lock);
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun err = regulator_enable(chip->vcc_reg);
818*4882a593Smuzhiyun if (err) {
819*4882a593Smuzhiyun dev_err(dev, "failed to enable VCC regulator\n");
820*4882a593Smuzhiyun mutex_unlock(&chip->lock);
821*4882a593Smuzhiyun return err;
822*4882a593Smuzhiyun }
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun err = isl29018_chip_init(chip);
825*4882a593Smuzhiyun if (!err)
826*4882a593Smuzhiyun chip->suspended = false;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun mutex_unlock(&chip->lock);
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun return err;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
834*4882a593Smuzhiyun #define ISL29018_PM_OPS (&isl29018_pm_ops)
835*4882a593Smuzhiyun #else
836*4882a593Smuzhiyun #define ISL29018_PM_OPS NULL
837*4882a593Smuzhiyun #endif
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun #ifdef CONFIG_ACPI
840*4882a593Smuzhiyun static const struct acpi_device_id isl29018_acpi_match[] = {
841*4882a593Smuzhiyun {"ISL29018", isl29018},
842*4882a593Smuzhiyun {"ISL29023", isl29023},
843*4882a593Smuzhiyun {"ISL29035", isl29035},
844*4882a593Smuzhiyun {},
845*4882a593Smuzhiyun };
846*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
847*4882a593Smuzhiyun #endif
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun static const struct i2c_device_id isl29018_id[] = {
850*4882a593Smuzhiyun {"isl29018", isl29018},
851*4882a593Smuzhiyun {"isl29023", isl29023},
852*4882a593Smuzhiyun {"isl29035", isl29035},
853*4882a593Smuzhiyun {}
854*4882a593Smuzhiyun };
855*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, isl29018_id);
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun static const struct of_device_id isl29018_of_match[] = {
858*4882a593Smuzhiyun { .compatible = "isil,isl29018", },
859*4882a593Smuzhiyun { .compatible = "isil,isl29023", },
860*4882a593Smuzhiyun { .compatible = "isil,isl29035", },
861*4882a593Smuzhiyun { },
862*4882a593Smuzhiyun };
863*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, isl29018_of_match);
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun static struct i2c_driver isl29018_driver = {
866*4882a593Smuzhiyun .driver = {
867*4882a593Smuzhiyun .name = "isl29018",
868*4882a593Smuzhiyun .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
869*4882a593Smuzhiyun .pm = ISL29018_PM_OPS,
870*4882a593Smuzhiyun .of_match_table = isl29018_of_match,
871*4882a593Smuzhiyun },
872*4882a593Smuzhiyun .probe = isl29018_probe,
873*4882a593Smuzhiyun .id_table = isl29018_id,
874*4882a593Smuzhiyun };
875*4882a593Smuzhiyun module_i2c_driver(isl29018_driver);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
878*4882a593Smuzhiyun MODULE_LICENSE("GPL");
879