1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * MAX44000 Ambient and Infrared Proximity Sensor
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2016, Intel Corporation.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Data sheet: https://datasheets.maximintegrated.com/en/ds/MAX44000.pdf
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * 7-bit I2C slave address 0x4a
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/i2c.h>
15*4882a593Smuzhiyun #include <linux/regmap.h>
16*4882a593Smuzhiyun #include <linux/util_macros.h>
17*4882a593Smuzhiyun #include <linux/iio/iio.h>
18*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
19*4882a593Smuzhiyun #include <linux/iio/buffer.h>
20*4882a593Smuzhiyun #include <linux/iio/trigger_consumer.h>
21*4882a593Smuzhiyun #include <linux/iio/triggered_buffer.h>
22*4882a593Smuzhiyun #include <linux/acpi.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define MAX44000_DRV_NAME "max44000"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* Registers in datasheet order */
27*4882a593Smuzhiyun #define MAX44000_REG_STATUS 0x00
28*4882a593Smuzhiyun #define MAX44000_REG_CFG_MAIN 0x01
29*4882a593Smuzhiyun #define MAX44000_REG_CFG_RX 0x02
30*4882a593Smuzhiyun #define MAX44000_REG_CFG_TX 0x03
31*4882a593Smuzhiyun #define MAX44000_REG_ALS_DATA_HI 0x04
32*4882a593Smuzhiyun #define MAX44000_REG_ALS_DATA_LO 0x05
33*4882a593Smuzhiyun #define MAX44000_REG_PRX_DATA 0x16
34*4882a593Smuzhiyun #define MAX44000_REG_ALS_UPTHR_HI 0x06
35*4882a593Smuzhiyun #define MAX44000_REG_ALS_UPTHR_LO 0x07
36*4882a593Smuzhiyun #define MAX44000_REG_ALS_LOTHR_HI 0x08
37*4882a593Smuzhiyun #define MAX44000_REG_ALS_LOTHR_LO 0x09
38*4882a593Smuzhiyun #define MAX44000_REG_PST 0x0a
39*4882a593Smuzhiyun #define MAX44000_REG_PRX_IND 0x0b
40*4882a593Smuzhiyun #define MAX44000_REG_PRX_THR 0x0c
41*4882a593Smuzhiyun #define MAX44000_REG_TRIM_GAIN_GREEN 0x0f
42*4882a593Smuzhiyun #define MAX44000_REG_TRIM_GAIN_IR 0x10
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* REG_CFG bits */
45*4882a593Smuzhiyun #define MAX44000_CFG_ALSINTE 0x01
46*4882a593Smuzhiyun #define MAX44000_CFG_PRXINTE 0x02
47*4882a593Smuzhiyun #define MAX44000_CFG_MASK 0x1c
48*4882a593Smuzhiyun #define MAX44000_CFG_MODE_SHUTDOWN 0x00
49*4882a593Smuzhiyun #define MAX44000_CFG_MODE_ALS_GIR 0x04
50*4882a593Smuzhiyun #define MAX44000_CFG_MODE_ALS_G 0x08
51*4882a593Smuzhiyun #define MAX44000_CFG_MODE_ALS_IR 0x0c
52*4882a593Smuzhiyun #define MAX44000_CFG_MODE_ALS_PRX 0x10
53*4882a593Smuzhiyun #define MAX44000_CFG_MODE_PRX 0x14
54*4882a593Smuzhiyun #define MAX44000_CFG_TRIM 0x20
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * Upper 4 bits are not documented but start as 1 on powerup
58*4882a593Smuzhiyun * Setting them to 0 causes proximity to misbehave so set them to 1
59*4882a593Smuzhiyun */
60*4882a593Smuzhiyun #define MAX44000_REG_CFG_RX_DEFAULT 0xf0
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* REG_RX bits */
63*4882a593Smuzhiyun #define MAX44000_CFG_RX_ALSTIM_MASK 0x0c
64*4882a593Smuzhiyun #define MAX44000_CFG_RX_ALSTIM_SHIFT 2
65*4882a593Smuzhiyun #define MAX44000_CFG_RX_ALSPGA_MASK 0x03
66*4882a593Smuzhiyun #define MAX44000_CFG_RX_ALSPGA_SHIFT 0
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* REG_TX bits */
69*4882a593Smuzhiyun #define MAX44000_LED_CURRENT_MASK 0xf
70*4882a593Smuzhiyun #define MAX44000_LED_CURRENT_MAX 11
71*4882a593Smuzhiyun #define MAX44000_LED_CURRENT_DEFAULT 6
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun #define MAX44000_ALSDATA_OVERFLOW 0x4000
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun struct max44000_data {
76*4882a593Smuzhiyun struct mutex lock;
77*4882a593Smuzhiyun struct regmap *regmap;
78*4882a593Smuzhiyun /* Ensure naturally aligned timestamp */
79*4882a593Smuzhiyun struct {
80*4882a593Smuzhiyun u16 channels[2];
81*4882a593Smuzhiyun s64 ts __aligned(8);
82*4882a593Smuzhiyun } scan;
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */
86*4882a593Smuzhiyun #define MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 5
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /* Scale can be multiplied by up to 128x via ALSPGA for measurement gain */
89*4882a593Smuzhiyun static const int max44000_alspga_shift[] = {0, 2, 4, 7};
90*4882a593Smuzhiyun #define MAX44000_ALSPGA_MAX_SHIFT 7
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * Scale can be multiplied by up to 64x via ALSTIM because of lost resolution
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun * This scaling factor is hidden from userspace and instead accounted for when
96*4882a593Smuzhiyun * reading raw values from the device.
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun * This makes it possible to cleanly expose ALSPGA as IIO_CHAN_INFO_SCALE and
99*4882a593Smuzhiyun * ALSTIM as IIO_CHAN_INFO_INT_TIME without the values affecting each other.
100*4882a593Smuzhiyun *
101*4882a593Smuzhiyun * Handling this internally is also required for buffer support because the
102*4882a593Smuzhiyun * channel's scan_type can't be modified dynamically.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun #define MAX44000_ALSTIM_SHIFT(alstim) (2 * (alstim))
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* Available integration times with pretty manual alignment: */
107*4882a593Smuzhiyun static const int max44000_int_time_avail_ns_array[] = {
108*4882a593Smuzhiyun 100000000,
109*4882a593Smuzhiyun 25000000,
110*4882a593Smuzhiyun 6250000,
111*4882a593Smuzhiyun 1562500,
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun static const char max44000_int_time_avail_str[] =
114*4882a593Smuzhiyun "0.100 "
115*4882a593Smuzhiyun "0.025 "
116*4882a593Smuzhiyun "0.00625 "
117*4882a593Smuzhiyun "0.0015625";
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* Available scales (internal to ulux) with pretty manual alignment: */
120*4882a593Smuzhiyun static const int max44000_scale_avail_ulux_array[] = {
121*4882a593Smuzhiyun 31250,
122*4882a593Smuzhiyun 125000,
123*4882a593Smuzhiyun 500000,
124*4882a593Smuzhiyun 4000000,
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun static const char max44000_scale_avail_str[] =
127*4882a593Smuzhiyun "0.03125 "
128*4882a593Smuzhiyun "0.125 "
129*4882a593Smuzhiyun "0.5 "
130*4882a593Smuzhiyun "4";
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #define MAX44000_SCAN_INDEX_ALS 0
133*4882a593Smuzhiyun #define MAX44000_SCAN_INDEX_PRX 1
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun static const struct iio_chan_spec max44000_channels[] = {
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun .type = IIO_LIGHT,
138*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
139*4882a593Smuzhiyun .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
140*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_INT_TIME),
141*4882a593Smuzhiyun .scan_index = MAX44000_SCAN_INDEX_ALS,
142*4882a593Smuzhiyun .scan_type = {
143*4882a593Smuzhiyun .sign = 'u',
144*4882a593Smuzhiyun .realbits = 14,
145*4882a593Smuzhiyun .storagebits = 16,
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun },
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun .type = IIO_PROXIMITY,
150*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
151*4882a593Smuzhiyun .scan_index = MAX44000_SCAN_INDEX_PRX,
152*4882a593Smuzhiyun .scan_type = {
153*4882a593Smuzhiyun .sign = 'u',
154*4882a593Smuzhiyun .realbits = 8,
155*4882a593Smuzhiyun .storagebits = 16,
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun },
158*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(2),
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun .type = IIO_CURRENT,
161*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
162*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE),
163*4882a593Smuzhiyun .extend_name = "led",
164*4882a593Smuzhiyun .output = 1,
165*4882a593Smuzhiyun .scan_index = -1,
166*4882a593Smuzhiyun },
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
max44000_read_alstim(struct max44000_data * data)169*4882a593Smuzhiyun static int max44000_read_alstim(struct max44000_data *data)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun unsigned int val;
172*4882a593Smuzhiyun int ret;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val);
175*4882a593Smuzhiyun if (ret < 0)
176*4882a593Smuzhiyun return ret;
177*4882a593Smuzhiyun return (val & MAX44000_CFG_RX_ALSTIM_MASK) >> MAX44000_CFG_RX_ALSTIM_SHIFT;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
max44000_write_alstim(struct max44000_data * data,int val)180*4882a593Smuzhiyun static int max44000_write_alstim(struct max44000_data *data, int val)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX,
183*4882a593Smuzhiyun MAX44000_CFG_RX_ALSTIM_MASK,
184*4882a593Smuzhiyun val << MAX44000_CFG_RX_ALSTIM_SHIFT);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
max44000_read_alspga(struct max44000_data * data)187*4882a593Smuzhiyun static int max44000_read_alspga(struct max44000_data *data)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun unsigned int val;
190*4882a593Smuzhiyun int ret;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val);
193*4882a593Smuzhiyun if (ret < 0)
194*4882a593Smuzhiyun return ret;
195*4882a593Smuzhiyun return (val & MAX44000_CFG_RX_ALSPGA_MASK) >> MAX44000_CFG_RX_ALSPGA_SHIFT;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
max44000_write_alspga(struct max44000_data * data,int val)198*4882a593Smuzhiyun static int max44000_write_alspga(struct max44000_data *data, int val)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX,
201*4882a593Smuzhiyun MAX44000_CFG_RX_ALSPGA_MASK,
202*4882a593Smuzhiyun val << MAX44000_CFG_RX_ALSPGA_SHIFT);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
max44000_read_alsval(struct max44000_data * data)205*4882a593Smuzhiyun static int max44000_read_alsval(struct max44000_data *data)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun u16 regval;
208*4882a593Smuzhiyun __be16 val;
209*4882a593Smuzhiyun int alstim, ret;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI,
212*4882a593Smuzhiyun &val, sizeof(val));
213*4882a593Smuzhiyun if (ret < 0)
214*4882a593Smuzhiyun return ret;
215*4882a593Smuzhiyun alstim = ret = max44000_read_alstim(data);
216*4882a593Smuzhiyun if (ret < 0)
217*4882a593Smuzhiyun return ret;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun regval = be16_to_cpu(val);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun * Overflow is explained on datasheet page 17.
223*4882a593Smuzhiyun *
224*4882a593Smuzhiyun * It's a warning that either the G or IR channel has become saturated
225*4882a593Smuzhiyun * and that the value in the register is likely incorrect.
226*4882a593Smuzhiyun *
227*4882a593Smuzhiyun * The recommendation is to change the scale (ALSPGA).
228*4882a593Smuzhiyun * The driver just returns the max representable value.
229*4882a593Smuzhiyun */
230*4882a593Smuzhiyun if (regval & MAX44000_ALSDATA_OVERFLOW)
231*4882a593Smuzhiyun return 0x3FFF;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun return regval << MAX44000_ALSTIM_SHIFT(alstim);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
max44000_write_led_current_raw(struct max44000_data * data,int val)236*4882a593Smuzhiyun static int max44000_write_led_current_raw(struct max44000_data *data, int val)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun /* Maybe we should clamp the value instead? */
239*4882a593Smuzhiyun if (val < 0 || val > MAX44000_LED_CURRENT_MAX)
240*4882a593Smuzhiyun return -ERANGE;
241*4882a593Smuzhiyun if (val >= 8)
242*4882a593Smuzhiyun val += 4;
243*4882a593Smuzhiyun return regmap_write_bits(data->regmap, MAX44000_REG_CFG_TX,
244*4882a593Smuzhiyun MAX44000_LED_CURRENT_MASK, val);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
max44000_read_led_current_raw(struct max44000_data * data)247*4882a593Smuzhiyun static int max44000_read_led_current_raw(struct max44000_data *data)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun unsigned int regval;
250*4882a593Smuzhiyun int ret;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_CFG_TX, ®val);
253*4882a593Smuzhiyun if (ret < 0)
254*4882a593Smuzhiyun return ret;
255*4882a593Smuzhiyun regval &= MAX44000_LED_CURRENT_MASK;
256*4882a593Smuzhiyun if (regval >= 8)
257*4882a593Smuzhiyun regval -= 4;
258*4882a593Smuzhiyun return regval;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
max44000_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)261*4882a593Smuzhiyun static int max44000_read_raw(struct iio_dev *indio_dev,
262*4882a593Smuzhiyun struct iio_chan_spec const *chan,
263*4882a593Smuzhiyun int *val, int *val2, long mask)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun struct max44000_data *data = iio_priv(indio_dev);
266*4882a593Smuzhiyun int alstim, alspga;
267*4882a593Smuzhiyun unsigned int regval;
268*4882a593Smuzhiyun int ret;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun switch (mask) {
271*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
272*4882a593Smuzhiyun switch (chan->type) {
273*4882a593Smuzhiyun case IIO_LIGHT:
274*4882a593Smuzhiyun mutex_lock(&data->lock);
275*4882a593Smuzhiyun ret = max44000_read_alsval(data);
276*4882a593Smuzhiyun mutex_unlock(&data->lock);
277*4882a593Smuzhiyun if (ret < 0)
278*4882a593Smuzhiyun return ret;
279*4882a593Smuzhiyun *val = ret;
280*4882a593Smuzhiyun return IIO_VAL_INT;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun case IIO_PROXIMITY:
283*4882a593Smuzhiyun mutex_lock(&data->lock);
284*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val);
285*4882a593Smuzhiyun mutex_unlock(&data->lock);
286*4882a593Smuzhiyun if (ret < 0)
287*4882a593Smuzhiyun return ret;
288*4882a593Smuzhiyun *val = regval;
289*4882a593Smuzhiyun return IIO_VAL_INT;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun case IIO_CURRENT:
292*4882a593Smuzhiyun mutex_lock(&data->lock);
293*4882a593Smuzhiyun ret = max44000_read_led_current_raw(data);
294*4882a593Smuzhiyun mutex_unlock(&data->lock);
295*4882a593Smuzhiyun if (ret < 0)
296*4882a593Smuzhiyun return ret;
297*4882a593Smuzhiyun *val = ret;
298*4882a593Smuzhiyun return IIO_VAL_INT;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun default:
301*4882a593Smuzhiyun return -EINVAL;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
305*4882a593Smuzhiyun switch (chan->type) {
306*4882a593Smuzhiyun case IIO_CURRENT:
307*4882a593Smuzhiyun /* Output register is in 10s of miliamps */
308*4882a593Smuzhiyun *val = 10;
309*4882a593Smuzhiyun return IIO_VAL_INT;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun case IIO_LIGHT:
312*4882a593Smuzhiyun mutex_lock(&data->lock);
313*4882a593Smuzhiyun alspga = ret = max44000_read_alspga(data);
314*4882a593Smuzhiyun mutex_unlock(&data->lock);
315*4882a593Smuzhiyun if (ret < 0)
316*4882a593Smuzhiyun return ret;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* Avoid negative shifts */
319*4882a593Smuzhiyun *val = (1 << MAX44000_ALSPGA_MAX_SHIFT);
320*4882a593Smuzhiyun *val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2
321*4882a593Smuzhiyun + MAX44000_ALSPGA_MAX_SHIFT
322*4882a593Smuzhiyun - max44000_alspga_shift[alspga];
323*4882a593Smuzhiyun return IIO_VAL_FRACTIONAL_LOG2;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun default:
326*4882a593Smuzhiyun return -EINVAL;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun case IIO_CHAN_INFO_INT_TIME:
330*4882a593Smuzhiyun mutex_lock(&data->lock);
331*4882a593Smuzhiyun alstim = ret = max44000_read_alstim(data);
332*4882a593Smuzhiyun mutex_unlock(&data->lock);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (ret < 0)
335*4882a593Smuzhiyun return ret;
336*4882a593Smuzhiyun *val = 0;
337*4882a593Smuzhiyun *val2 = max44000_int_time_avail_ns_array[alstim];
338*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_NANO;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun default:
341*4882a593Smuzhiyun return -EINVAL;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
max44000_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)345*4882a593Smuzhiyun static int max44000_write_raw(struct iio_dev *indio_dev,
346*4882a593Smuzhiyun struct iio_chan_spec const *chan,
347*4882a593Smuzhiyun int val, int val2, long mask)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun struct max44000_data *data = iio_priv(indio_dev);
350*4882a593Smuzhiyun int ret;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) {
353*4882a593Smuzhiyun mutex_lock(&data->lock);
354*4882a593Smuzhiyun ret = max44000_write_led_current_raw(data, val);
355*4882a593Smuzhiyun mutex_unlock(&data->lock);
356*4882a593Smuzhiyun return ret;
357*4882a593Smuzhiyun } else if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) {
358*4882a593Smuzhiyun s64 valns = val * NSEC_PER_SEC + val2;
359*4882a593Smuzhiyun int alstim = find_closest_descending(valns,
360*4882a593Smuzhiyun max44000_int_time_avail_ns_array,
361*4882a593Smuzhiyun ARRAY_SIZE(max44000_int_time_avail_ns_array));
362*4882a593Smuzhiyun mutex_lock(&data->lock);
363*4882a593Smuzhiyun ret = max44000_write_alstim(data, alstim);
364*4882a593Smuzhiyun mutex_unlock(&data->lock);
365*4882a593Smuzhiyun return ret;
366*4882a593Smuzhiyun } else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) {
367*4882a593Smuzhiyun s64 valus = val * USEC_PER_SEC + val2;
368*4882a593Smuzhiyun int alspga = find_closest(valus,
369*4882a593Smuzhiyun max44000_scale_avail_ulux_array,
370*4882a593Smuzhiyun ARRAY_SIZE(max44000_scale_avail_ulux_array));
371*4882a593Smuzhiyun mutex_lock(&data->lock);
372*4882a593Smuzhiyun ret = max44000_write_alspga(data, alspga);
373*4882a593Smuzhiyun mutex_unlock(&data->lock);
374*4882a593Smuzhiyun return ret;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun return -EINVAL;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
max44000_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long mask)380*4882a593Smuzhiyun static int max44000_write_raw_get_fmt(struct iio_dev *indio_dev,
381*4882a593Smuzhiyun struct iio_chan_spec const *chan,
382*4882a593Smuzhiyun long mask)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT)
385*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_NANO;
386*4882a593Smuzhiyun else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT)
387*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_MICRO;
388*4882a593Smuzhiyun else
389*4882a593Smuzhiyun return IIO_VAL_INT;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun static IIO_CONST_ATTR(illuminance_integration_time_available, max44000_int_time_avail_str);
393*4882a593Smuzhiyun static IIO_CONST_ATTR(illuminance_scale_available, max44000_scale_avail_str);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun static struct attribute *max44000_attributes[] = {
396*4882a593Smuzhiyun &iio_const_attr_illuminance_integration_time_available.dev_attr.attr,
397*4882a593Smuzhiyun &iio_const_attr_illuminance_scale_available.dev_attr.attr,
398*4882a593Smuzhiyun NULL
399*4882a593Smuzhiyun };
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun static const struct attribute_group max44000_attribute_group = {
402*4882a593Smuzhiyun .attrs = max44000_attributes,
403*4882a593Smuzhiyun };
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun static const struct iio_info max44000_info = {
406*4882a593Smuzhiyun .read_raw = max44000_read_raw,
407*4882a593Smuzhiyun .write_raw = max44000_write_raw,
408*4882a593Smuzhiyun .write_raw_get_fmt = max44000_write_raw_get_fmt,
409*4882a593Smuzhiyun .attrs = &max44000_attribute_group,
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
max44000_readable_reg(struct device * dev,unsigned int reg)412*4882a593Smuzhiyun static bool max44000_readable_reg(struct device *dev, unsigned int reg)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun switch (reg) {
415*4882a593Smuzhiyun case MAX44000_REG_STATUS:
416*4882a593Smuzhiyun case MAX44000_REG_CFG_MAIN:
417*4882a593Smuzhiyun case MAX44000_REG_CFG_RX:
418*4882a593Smuzhiyun case MAX44000_REG_CFG_TX:
419*4882a593Smuzhiyun case MAX44000_REG_ALS_DATA_HI:
420*4882a593Smuzhiyun case MAX44000_REG_ALS_DATA_LO:
421*4882a593Smuzhiyun case MAX44000_REG_PRX_DATA:
422*4882a593Smuzhiyun case MAX44000_REG_ALS_UPTHR_HI:
423*4882a593Smuzhiyun case MAX44000_REG_ALS_UPTHR_LO:
424*4882a593Smuzhiyun case MAX44000_REG_ALS_LOTHR_HI:
425*4882a593Smuzhiyun case MAX44000_REG_ALS_LOTHR_LO:
426*4882a593Smuzhiyun case MAX44000_REG_PST:
427*4882a593Smuzhiyun case MAX44000_REG_PRX_IND:
428*4882a593Smuzhiyun case MAX44000_REG_PRX_THR:
429*4882a593Smuzhiyun case MAX44000_REG_TRIM_GAIN_GREEN:
430*4882a593Smuzhiyun case MAX44000_REG_TRIM_GAIN_IR:
431*4882a593Smuzhiyun return true;
432*4882a593Smuzhiyun default:
433*4882a593Smuzhiyun return false;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
max44000_writeable_reg(struct device * dev,unsigned int reg)437*4882a593Smuzhiyun static bool max44000_writeable_reg(struct device *dev, unsigned int reg)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun switch (reg) {
440*4882a593Smuzhiyun case MAX44000_REG_CFG_MAIN:
441*4882a593Smuzhiyun case MAX44000_REG_CFG_RX:
442*4882a593Smuzhiyun case MAX44000_REG_CFG_TX:
443*4882a593Smuzhiyun case MAX44000_REG_ALS_UPTHR_HI:
444*4882a593Smuzhiyun case MAX44000_REG_ALS_UPTHR_LO:
445*4882a593Smuzhiyun case MAX44000_REG_ALS_LOTHR_HI:
446*4882a593Smuzhiyun case MAX44000_REG_ALS_LOTHR_LO:
447*4882a593Smuzhiyun case MAX44000_REG_PST:
448*4882a593Smuzhiyun case MAX44000_REG_PRX_IND:
449*4882a593Smuzhiyun case MAX44000_REG_PRX_THR:
450*4882a593Smuzhiyun case MAX44000_REG_TRIM_GAIN_GREEN:
451*4882a593Smuzhiyun case MAX44000_REG_TRIM_GAIN_IR:
452*4882a593Smuzhiyun return true;
453*4882a593Smuzhiyun default:
454*4882a593Smuzhiyun return false;
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
max44000_volatile_reg(struct device * dev,unsigned int reg)458*4882a593Smuzhiyun static bool max44000_volatile_reg(struct device *dev, unsigned int reg)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun switch (reg) {
461*4882a593Smuzhiyun case MAX44000_REG_STATUS:
462*4882a593Smuzhiyun case MAX44000_REG_ALS_DATA_HI:
463*4882a593Smuzhiyun case MAX44000_REG_ALS_DATA_LO:
464*4882a593Smuzhiyun case MAX44000_REG_PRX_DATA:
465*4882a593Smuzhiyun return true;
466*4882a593Smuzhiyun default:
467*4882a593Smuzhiyun return false;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
max44000_precious_reg(struct device * dev,unsigned int reg)471*4882a593Smuzhiyun static bool max44000_precious_reg(struct device *dev, unsigned int reg)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun return reg == MAX44000_REG_STATUS;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun static const struct regmap_config max44000_regmap_config = {
477*4882a593Smuzhiyun .reg_bits = 8,
478*4882a593Smuzhiyun .val_bits = 8,
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun .max_register = MAX44000_REG_PRX_DATA,
481*4882a593Smuzhiyun .readable_reg = max44000_readable_reg,
482*4882a593Smuzhiyun .writeable_reg = max44000_writeable_reg,
483*4882a593Smuzhiyun .volatile_reg = max44000_volatile_reg,
484*4882a593Smuzhiyun .precious_reg = max44000_precious_reg,
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun .use_single_read = true,
487*4882a593Smuzhiyun .use_single_write = true,
488*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
max44000_trigger_handler(int irq,void * p)491*4882a593Smuzhiyun static irqreturn_t max44000_trigger_handler(int irq, void *p)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun struct iio_poll_func *pf = p;
494*4882a593Smuzhiyun struct iio_dev *indio_dev = pf->indio_dev;
495*4882a593Smuzhiyun struct max44000_data *data = iio_priv(indio_dev);
496*4882a593Smuzhiyun int index = 0;
497*4882a593Smuzhiyun unsigned int regval;
498*4882a593Smuzhiyun int ret;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun mutex_lock(&data->lock);
501*4882a593Smuzhiyun if (test_bit(MAX44000_SCAN_INDEX_ALS, indio_dev->active_scan_mask)) {
502*4882a593Smuzhiyun ret = max44000_read_alsval(data);
503*4882a593Smuzhiyun if (ret < 0)
504*4882a593Smuzhiyun goto out_unlock;
505*4882a593Smuzhiyun data->scan.channels[index++] = ret;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) {
508*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, ®val);
509*4882a593Smuzhiyun if (ret < 0)
510*4882a593Smuzhiyun goto out_unlock;
511*4882a593Smuzhiyun data->scan.channels[index] = regval;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun mutex_unlock(&data->lock);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
516*4882a593Smuzhiyun iio_get_time_ns(indio_dev));
517*4882a593Smuzhiyun iio_trigger_notify_done(indio_dev->trig);
518*4882a593Smuzhiyun return IRQ_HANDLED;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun out_unlock:
521*4882a593Smuzhiyun mutex_unlock(&data->lock);
522*4882a593Smuzhiyun iio_trigger_notify_done(indio_dev->trig);
523*4882a593Smuzhiyun return IRQ_HANDLED;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
max44000_probe(struct i2c_client * client,const struct i2c_device_id * id)526*4882a593Smuzhiyun static int max44000_probe(struct i2c_client *client,
527*4882a593Smuzhiyun const struct i2c_device_id *id)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun struct max44000_data *data;
530*4882a593Smuzhiyun struct iio_dev *indio_dev;
531*4882a593Smuzhiyun int ret, reg;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
534*4882a593Smuzhiyun if (!indio_dev)
535*4882a593Smuzhiyun return -ENOMEM;
536*4882a593Smuzhiyun data = iio_priv(indio_dev);
537*4882a593Smuzhiyun data->regmap = devm_regmap_init_i2c(client, &max44000_regmap_config);
538*4882a593Smuzhiyun if (IS_ERR(data->regmap)) {
539*4882a593Smuzhiyun dev_err(&client->dev, "regmap_init failed!\n");
540*4882a593Smuzhiyun return PTR_ERR(data->regmap);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun i2c_set_clientdata(client, indio_dev);
544*4882a593Smuzhiyun mutex_init(&data->lock);
545*4882a593Smuzhiyun indio_dev->info = &max44000_info;
546*4882a593Smuzhiyun indio_dev->name = MAX44000_DRV_NAME;
547*4882a593Smuzhiyun indio_dev->channels = max44000_channels;
548*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(max44000_channels);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /*
551*4882a593Smuzhiyun * The device doesn't have a reset function so we just clear some
552*4882a593Smuzhiyun * important bits at probe time to ensure sane operation.
553*4882a593Smuzhiyun *
554*4882a593Smuzhiyun * Since we don't support interrupts/events the threshold values are
555*4882a593Smuzhiyun * not important. We also don't touch trim values.
556*4882a593Smuzhiyun */
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun /* Reset ALS scaling bits */
559*4882a593Smuzhiyun ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX,
560*4882a593Smuzhiyun MAX44000_REG_CFG_RX_DEFAULT);
561*4882a593Smuzhiyun if (ret < 0) {
562*4882a593Smuzhiyun dev_err(&client->dev, "failed to write default CFG_RX: %d\n",
563*4882a593Smuzhiyun ret);
564*4882a593Smuzhiyun return ret;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /*
568*4882a593Smuzhiyun * By default the LED pulse used for the proximity sensor is disabled.
569*4882a593Smuzhiyun * Set a middle value so that we get some sort of valid data by default.
570*4882a593Smuzhiyun */
571*4882a593Smuzhiyun ret = max44000_write_led_current_raw(data, MAX44000_LED_CURRENT_DEFAULT);
572*4882a593Smuzhiyun if (ret < 0) {
573*4882a593Smuzhiyun dev_err(&client->dev, "failed to write init config: %d\n", ret);
574*4882a593Smuzhiyun return ret;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun /* Reset CFG bits to ALS_PRX mode which allows easy reading of both values. */
578*4882a593Smuzhiyun reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_PRX;
579*4882a593Smuzhiyun ret = regmap_write(data->regmap, MAX44000_REG_CFG_MAIN, reg);
580*4882a593Smuzhiyun if (ret < 0) {
581*4882a593Smuzhiyun dev_err(&client->dev, "failed to write init config: %d\n", ret);
582*4882a593Smuzhiyun return ret;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* Read status at least once to clear any stale interrupt bits. */
586*4882a593Smuzhiyun ret = regmap_read(data->regmap, MAX44000_REG_STATUS, ®);
587*4882a593Smuzhiyun if (ret < 0) {
588*4882a593Smuzhiyun dev_err(&client->dev, "failed to read init status: %d\n", ret);
589*4882a593Smuzhiyun return ret;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun ret = iio_triggered_buffer_setup(indio_dev, NULL, max44000_trigger_handler, NULL);
593*4882a593Smuzhiyun if (ret < 0) {
594*4882a593Smuzhiyun dev_err(&client->dev, "iio triggered buffer setup failed\n");
595*4882a593Smuzhiyun return ret;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun return iio_device_register(indio_dev);
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
max44000_remove(struct i2c_client * client)601*4882a593Smuzhiyun static int max44000_remove(struct i2c_client *client)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun struct iio_dev *indio_dev = i2c_get_clientdata(client);
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun iio_device_unregister(indio_dev);
606*4882a593Smuzhiyun iio_triggered_buffer_cleanup(indio_dev);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun return 0;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun static const struct i2c_device_id max44000_id[] = {
612*4882a593Smuzhiyun {"max44000", 0},
613*4882a593Smuzhiyun { }
614*4882a593Smuzhiyun };
615*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, max44000_id);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun #ifdef CONFIG_ACPI
618*4882a593Smuzhiyun static const struct acpi_device_id max44000_acpi_match[] = {
619*4882a593Smuzhiyun {"MAX44000", 0},
620*4882a593Smuzhiyun { }
621*4882a593Smuzhiyun };
622*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, max44000_acpi_match);
623*4882a593Smuzhiyun #endif
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun static struct i2c_driver max44000_driver = {
626*4882a593Smuzhiyun .driver = {
627*4882a593Smuzhiyun .name = MAX44000_DRV_NAME,
628*4882a593Smuzhiyun .acpi_match_table = ACPI_PTR(max44000_acpi_match),
629*4882a593Smuzhiyun },
630*4882a593Smuzhiyun .probe = max44000_probe,
631*4882a593Smuzhiyun .remove = max44000_remove,
632*4882a593Smuzhiyun .id_table = max44000_id,
633*4882a593Smuzhiyun };
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun module_i2c_driver(max44000_driver);
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun MODULE_AUTHOR("Crestez Dan Leonard <leonard.crestez@intel.com>");
638*4882a593Smuzhiyun MODULE_DESCRIPTION("MAX44000 Ambient and Infrared Proximity Sensor");
639*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
640