1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * APDS-9306/APDS-9306-065 Ambient Light Sensor
5 * Datasheet: https://docs.broadcom.com/doc/AV02-4755EN
7 * Copyright (C) 2024 Subhajit Ghosh <subhajit.ghosh@tweaklogic.com>
10 #include <linux/bits.h>
11 #include <linux/cleanup.h>
12 #include <linux/delay.h>
13 #include <linux/err.h>
14 #include <linux/i2c.h>
15 #include <linux/interrupt.h>
16 #include <linux/minmax.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/types.h>
24 #include <linux/units.h>
26 #include <linux/iio/iio.h>
27 #include <linux/iio/iio-gts-helper.h>
28 #include <linux/iio/events.h>
29 #include <linux/iio/sysfs.h>
31 #include <linux/unaligned.h>
33 #define APDS9306_MAIN_CTRL_REG 0x00
34 #define APDS9306_ALS_MEAS_RATE_REG 0x04
35 #define APDS9306_ALS_GAIN_REG 0x05
36 #define APDS9306_PART_ID_REG 0x06
37 #define APDS9306_MAIN_STATUS_REG 0x07
38 #define APDS9306_CLEAR_DATA_0_REG 0x0A
39 #define APDS9306_CLEAR_DATA_1_REG 0x0B
40 #define APDS9306_CLEAR_DATA_2_REG 0x0C
41 #define APDS9306_ALS_DATA_0_REG 0x0D
42 #define APDS9306_ALS_DATA_1_REG 0x0E
43 #define APDS9306_ALS_DATA_2_REG 0x0F
44 #define APDS9306_INT_CFG_REG 0x19
45 #define APDS9306_INT_PERSISTENCE_REG 0x1A
46 #define APDS9306_ALS_THRES_UP_0_REG 0x21
47 #define APDS9306_ALS_THRES_UP_1_REG 0x22
48 #define APDS9306_ALS_THRES_UP_2_REG 0x23
49 #define APDS9306_ALS_THRES_LOW_0_REG 0x24
50 #define APDS9306_ALS_THRES_LOW_1_REG 0x25
51 #define APDS9306_ALS_THRES_LOW_2_REG 0x26
52 #define APDS9306_ALS_THRES_VAR_REG 0x27
54 #define APDS9306_ALS_INT_STAT_MASK BIT(4)
55 #define APDS9306_ALS_DATA_STAT_MASK BIT(3)
57 #define APDS9306_ALS_THRES_VAL_MAX (BIT(20) - 1)
58 #define APDS9306_ALS_THRES_VAR_NUM_VALS 8
59 #define APDS9306_ALS_PERSIST_NUM_VALS 16
60 #define APDS9306_ALS_READ_DATA_DELAY_US (20 * USEC_PER_MSEC)
61 #define APDS9306_NUM_REPEAT_RATES 7
62 #define APDS9306_INT_SRC_CLEAR 0
63 #define APDS9306_INT_SRC_ALS 1
64 #define APDS9306_SAMP_FREQ_10HZ 0
67 * struct part_id_gts_multiplier - Part no. and corresponding gts multiplier
69 * GTS (Gain Time Scale) are helper functions for Light sensors which along
70 * with hardware gains also has gains associated with Integration times.
72 * There are two variants of the device with slightly different characteristics,
73 * they have same ADC count for different Lux levels as mentioned in the
74 * datasheet. This multiplier array is used to store the derived Lux per count
75 * value for the two variants to be used by the GTS helper functions.
77 * @part_id: Part ID of the device
78 * @max_scale_int: Multiplier for iio_init_iio_gts()
79 * @max_scale_nano: Multiplier for iio_init_iio_gts()
81 struct part_id_gts_multiplier
{
88 * As per the datasheet, at HW Gain = 3x, Integration time 100mS (32x),
89 * typical 2000 ADC counts are observed for 49.8 uW per sq cm (340.134 lux)
90 * for apds9306 and 43 uW per sq cm (293.69 lux) for apds9306-065.
91 * Assuming lux per count is linear across all integration time ranges.
93 * Lux = (raw + offset) * scale; offset can be any value by userspace.
94 * HG = Hardware Gain; ITG = Gain by changing integration time.
95 * Scale table by IIO GTS Helpers = (1 / HG) * (1 / ITG) * Multiplier.
97 * The Lux values provided in the datasheet are at ITG=32x and HG=3x,
98 * at typical 2000 count for both variants of the device.
100 * Lux per ADC count at 3x and 32x for apds9306 = 340.134 / 2000
101 * Lux per ADC count at 3x and 32x for apds9306-065 = 293.69 / 2000
103 * The Multiplier for the scale table provided to userspace:
104 * IIO GTS scale Multiplier for apds9306 = (340.134 / 2000) * 32 * 3 = 16.326432
105 * and for apds9306-065 = (293.69 / 2000) * 32 * 3 = 14.09712
107 static const struct part_id_gts_multiplier apds9306_gts_mul
[] = {
111 .max_scale_nano
= 3264320,
115 .max_scale_nano
= 9712000,
119 static const int apds9306_repeat_rate_freq
[APDS9306_NUM_REPEAT_RATES
][2] = {
129 static const int apds9306_repeat_rate_period
[APDS9306_NUM_REPEAT_RATES
] = {
130 25000, 50000, 100000, 200000, 500000, 1000000, 2000000,
134 * struct apds9306_regfields - apds9306 regmap fields definitions
136 * @sw_reset: Software reset regfield
137 * @en: Enable regfield
138 * @intg_time: Resolution regfield
139 * @repeat_rate: Measurement Rate regfield
140 * @gain: Hardware gain regfield
141 * @int_src: Interrupt channel regfield
142 * @int_thresh_var_en: Interrupt variance threshold regfield
143 * @int_en: Interrupt enable regfield
144 * @int_persist_val: Interrupt persistence regfield
145 * @int_thresh_var_val: Interrupt threshold variance value regfield
147 struct apds9306_regfields
{
148 struct regmap_field
*sw_reset
;
149 struct regmap_field
*en
;
150 struct regmap_field
*intg_time
;
151 struct regmap_field
*repeat_rate
;
152 struct regmap_field
*gain
;
153 struct regmap_field
*int_src
;
154 struct regmap_field
*int_thresh_var_en
;
155 struct regmap_field
*int_en
;
156 struct regmap_field
*int_persist_val
;
157 struct regmap_field
*int_thresh_var_val
;
161 * struct apds9306_data - apds9306 private data and registers definitions
163 * @dev: Pointer to the device structure
164 * @gts: IIO Gain Time Scale structure
165 * @mutex: Lock for protecting adc reads, device settings changes where
166 * some calculations are required before or after setting or
167 * getting the raw settings values from regmap writes or reads
169 * @regmap: Regmap structure pointer
170 * @rf: Regmap register fields structure
171 * @nlux_per_count: Nano lux per ADC count for a particular model
172 * @read_data_available: Flag set by IRQ handler for ADC data available
174 struct apds9306_data
{
180 struct regmap
*regmap
;
181 struct apds9306_regfields rf
;
184 int read_data_available
;
188 * Available scales with gain 1x - 18x, timings 3.125, 25, 50, 100, 200, 400 ms
189 * Time impacts to gain: 1x, 8x, 16x, 32x, 64x, 128x
191 #define APDS9306_GSEL_1X 0x00
192 #define APDS9306_GSEL_3X 0x01
193 #define APDS9306_GSEL_6X 0x02
194 #define APDS9306_GSEL_9X 0x03
195 #define APDS9306_GSEL_18X 0x04
197 static const struct iio_gain_sel_pair apds9306_gains
[] = {
198 GAIN_SCALE_GAIN(1, APDS9306_GSEL_1X
),
199 GAIN_SCALE_GAIN(3, APDS9306_GSEL_3X
),
200 GAIN_SCALE_GAIN(6, APDS9306_GSEL_6X
),
201 GAIN_SCALE_GAIN(9, APDS9306_GSEL_9X
),
202 GAIN_SCALE_GAIN(18, APDS9306_GSEL_18X
),
205 #define APDS9306_MEAS_MODE_400MS 0x00
206 #define APDS9306_MEAS_MODE_200MS 0x01
207 #define APDS9306_MEAS_MODE_100MS 0x02
208 #define APDS9306_MEAS_MODE_50MS 0x03
209 #define APDS9306_MEAS_MODE_25MS 0x04
210 #define APDS9306_MEAS_MODE_3125US 0x05
212 static const struct iio_itime_sel_mul apds9306_itimes
[] = {
213 GAIN_SCALE_ITIME_US(400000, APDS9306_MEAS_MODE_400MS
, BIT(7)),
214 GAIN_SCALE_ITIME_US(200000, APDS9306_MEAS_MODE_200MS
, BIT(6)),
215 GAIN_SCALE_ITIME_US(100000, APDS9306_MEAS_MODE_100MS
, BIT(5)),
216 GAIN_SCALE_ITIME_US(50000, APDS9306_MEAS_MODE_50MS
, BIT(4)),
217 GAIN_SCALE_ITIME_US(25000, APDS9306_MEAS_MODE_25MS
, BIT(3)),
218 GAIN_SCALE_ITIME_US(3125, APDS9306_MEAS_MODE_3125US
, BIT(0)),
221 static const struct iio_event_spec apds9306_event_spec
[] = {
223 .type
= IIO_EV_TYPE_THRESH
,
224 .dir
= IIO_EV_DIR_RISING
,
225 .mask_shared_by_all
= BIT(IIO_EV_INFO_VALUE
),
227 .type
= IIO_EV_TYPE_THRESH
,
228 .dir
= IIO_EV_DIR_FALLING
,
229 .mask_shared_by_all
= BIT(IIO_EV_INFO_VALUE
),
231 .type
= IIO_EV_TYPE_THRESH
,
232 .dir
= IIO_EV_DIR_EITHER
,
233 .mask_shared_by_all
= BIT(IIO_EV_INFO_PERIOD
),
234 .mask_separate
= BIT(IIO_EV_INFO_ENABLE
),
236 .type
= IIO_EV_TYPE_THRESH_ADAPTIVE
,
237 .mask_shared_by_all
= BIT(IIO_EV_INFO_VALUE
) |
238 BIT(IIO_EV_INFO_ENABLE
),
242 static const struct iio_chan_spec apds9306_channels_with_events
[] = {
245 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) |
246 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
247 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
248 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
249 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) |
250 BIT(IIO_CHAN_INFO_SCALE
),
251 .info_mask_separate_available
= BIT(IIO_CHAN_INFO_SCALE
),
252 .event_spec
= apds9306_event_spec
,
253 .num_event_specs
= ARRAY_SIZE(apds9306_event_spec
),
255 .type
= IIO_INTENSITY
,
256 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) |
257 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
258 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
259 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
260 .channel2
= IIO_MOD_LIGHT_CLEAR
,
261 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
263 .event_spec
= apds9306_event_spec
,
264 .num_event_specs
= ARRAY_SIZE(apds9306_event_spec
),
268 static const struct iio_chan_spec apds9306_channels_without_events
[] = {
271 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) |
272 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
273 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
274 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
275 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
) |
276 BIT(IIO_CHAN_INFO_SCALE
),
277 .info_mask_separate_available
= BIT(IIO_CHAN_INFO_SCALE
),
279 .type
= IIO_INTENSITY
,
280 .info_mask_shared_by_all
= BIT(IIO_CHAN_INFO_INT_TIME
) |
281 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
282 .info_mask_shared_by_all_available
= BIT(IIO_CHAN_INFO_INT_TIME
) |
283 BIT(IIO_CHAN_INFO_SAMP_FREQ
),
284 .info_mask_separate
= BIT(IIO_CHAN_INFO_RAW
),
286 .channel2
= IIO_MOD_LIGHT_CLEAR
,
290 /* INT_PERSISTENCE available */
291 static IIO_CONST_ATTR(thresh_either_period_available
, "[0 1 15]");
293 /* ALS_THRESH_VAR available */
294 static IIO_CONST_ATTR(thresh_adaptive_either_values_available
, "[0 1 7]");
296 static struct attribute
*apds9306_event_attributes
[] = {
297 &iio_const_attr_thresh_either_period_available
.dev_attr
.attr
,
298 &iio_const_attr_thresh_adaptive_either_values_available
.dev_attr
.attr
,
302 static const struct attribute_group apds9306_event_attr_group
= {
303 .attrs
= apds9306_event_attributes
,
306 static const struct regmap_range apds9306_readable_ranges
[] = {
307 regmap_reg_range(APDS9306_MAIN_CTRL_REG
, APDS9306_ALS_THRES_VAR_REG
)
310 static const struct regmap_range apds9306_writable_ranges
[] = {
311 regmap_reg_range(APDS9306_MAIN_CTRL_REG
, APDS9306_ALS_GAIN_REG
),
312 regmap_reg_range(APDS9306_INT_CFG_REG
, APDS9306_ALS_THRES_VAR_REG
)
315 static const struct regmap_range apds9306_volatile_ranges
[] = {
316 regmap_reg_range(APDS9306_MAIN_STATUS_REG
, APDS9306_MAIN_STATUS_REG
),
317 regmap_reg_range(APDS9306_CLEAR_DATA_0_REG
, APDS9306_ALS_DATA_2_REG
)
320 static const struct regmap_range apds9306_precious_ranges
[] = {
321 regmap_reg_range(APDS9306_MAIN_STATUS_REG
, APDS9306_MAIN_STATUS_REG
)
324 static const struct regmap_access_table apds9306_readable_table
= {
325 .yes_ranges
= apds9306_readable_ranges
,
326 .n_yes_ranges
= ARRAY_SIZE(apds9306_readable_ranges
)
329 static const struct regmap_access_table apds9306_writable_table
= {
330 .yes_ranges
= apds9306_writable_ranges
,
331 .n_yes_ranges
= ARRAY_SIZE(apds9306_writable_ranges
)
334 static const struct regmap_access_table apds9306_volatile_table
= {
335 .yes_ranges
= apds9306_volatile_ranges
,
336 .n_yes_ranges
= ARRAY_SIZE(apds9306_volatile_ranges
)
339 static const struct regmap_access_table apds9306_precious_table
= {
340 .yes_ranges
= apds9306_precious_ranges
,
341 .n_yes_ranges
= ARRAY_SIZE(apds9306_precious_ranges
)
344 static const struct regmap_config apds9306_regmap
= {
345 .name
= "apds9306_regmap",
348 .rd_table
= &apds9306_readable_table
,
349 .wr_table
= &apds9306_writable_table
,
350 .volatile_table
= &apds9306_volatile_table
,
351 .precious_table
= &apds9306_precious_table
,
352 .max_register
= APDS9306_ALS_THRES_VAR_REG
,
353 .cache_type
= REGCACHE_RBTREE
,
356 static const struct reg_field apds9306_rf_sw_reset
=
357 REG_FIELD(APDS9306_MAIN_CTRL_REG
, 4, 4);
359 static const struct reg_field apds9306_rf_en
=
360 REG_FIELD(APDS9306_MAIN_CTRL_REG
, 1, 1);
362 static const struct reg_field apds9306_rf_intg_time
=
363 REG_FIELD(APDS9306_ALS_MEAS_RATE_REG
, 4, 6);
365 static const struct reg_field apds9306_rf_repeat_rate
=
366 REG_FIELD(APDS9306_ALS_MEAS_RATE_REG
, 0, 2);
368 static const struct reg_field apds9306_rf_gain
=
369 REG_FIELD(APDS9306_ALS_GAIN_REG
, 0, 2);
371 static const struct reg_field apds9306_rf_int_src
=
372 REG_FIELD(APDS9306_INT_CFG_REG
, 4, 5);
374 static const struct reg_field apds9306_rf_int_thresh_var_en
=
375 REG_FIELD(APDS9306_INT_CFG_REG
, 3, 3);
377 static const struct reg_field apds9306_rf_int_en
=
378 REG_FIELD(APDS9306_INT_CFG_REG
, 2, 2);
380 static const struct reg_field apds9306_rf_int_persist_val
=
381 REG_FIELD(APDS9306_INT_PERSISTENCE_REG
, 4, 7);
383 static const struct reg_field apds9306_rf_int_thresh_var_val
=
384 REG_FIELD(APDS9306_ALS_THRES_VAR_REG
, 0, 2);
386 static int apds9306_regfield_init(struct apds9306_data
*data
)
388 struct device
*dev
= data
->dev
;
389 struct regmap
*regmap
= data
->regmap
;
390 struct regmap_field
*tmp
;
391 struct apds9306_regfields
*rf
= &data
->rf
;
393 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_sw_reset
);
398 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_en
);
403 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_intg_time
);
408 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_repeat_rate
);
411 rf
->repeat_rate
= tmp
;
413 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_gain
);
418 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_int_src
);
423 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_int_thresh_var_en
);
426 rf
->int_thresh_var_en
= tmp
;
428 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_int_en
);
433 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_int_persist_val
);
436 rf
->int_persist_val
= tmp
;
438 tmp
= devm_regmap_field_alloc(dev
, regmap
, apds9306_rf_int_thresh_var_val
);
441 rf
->int_thresh_var_val
= tmp
;
446 static int apds9306_power_state(struct apds9306_data
*data
, bool state
)
448 struct apds9306_regfields
*rf
= &data
->rf
;
451 /* Reset not included as it causes ugly I2C bus error */
453 ret
= regmap_field_write(rf
->en
, 1);
456 /* 5ms wake up time */
461 return regmap_field_write(rf
->en
, 0);
464 static int apds9306_read_data(struct apds9306_data
*data
, int *val
, int reg
)
466 struct device
*dev
= data
->dev
;
467 struct iio_dev
*indio_dev
= dev_to_iio_dev(dev
);
468 struct apds9306_regfields
*rf
= &data
->rf
;
470 int ret
, delay
, intg_time
, intg_time_idx
, repeat_rate_idx
, int_src
;
474 ret
= pm_runtime_resume_and_get(data
->dev
);
478 ret
= regmap_field_read(rf
->intg_time
, &intg_time_idx
);
482 ret
= regmap_field_read(rf
->repeat_rate
, &repeat_rate_idx
);
486 ret
= regmap_field_read(rf
->int_src
, &int_src
);
490 intg_time
= iio_gts_find_int_time_by_sel(&data
->gts
, intg_time_idx
);
494 /* Whichever is greater - integration time period or sampling period. */
495 delay
= max(intg_time
, apds9306_repeat_rate_period
[repeat_rate_idx
]);
498 * Clear stale data flag that might have been set by the interrupt
499 * handler if it got data available flag set in the status reg.
501 data
->read_data_available
= 0;
504 * If this function runs parallel with the interrupt handler, either
505 * this reads and clears the status registers or the interrupt handler
506 * does. The interrupt handler sets a flag for read data available
507 * in our private structure which we read here.
509 ret
= regmap_read_poll_timeout(data
->regmap
, APDS9306_MAIN_STATUS_REG
,
510 status
, data
->read_data_available
||
511 (status
& (APDS9306_ALS_DATA_STAT_MASK
|
512 APDS9306_ALS_INT_STAT_MASK
)),
513 APDS9306_ALS_READ_DATA_DELAY_US
, delay
* 2);
517 /* If we reach here before the interrupt handler we push an event */
518 if ((status
& APDS9306_ALS_INT_STAT_MASK
)) {
519 if (int_src
== APDS9306_INT_SRC_ALS
)
520 ev_code
= IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
524 ev_code
= IIO_MOD_EVENT_CODE(IIO_INTENSITY
, 0,
529 iio_push_event(indio_dev
, ev_code
, iio_get_time_ns(indio_dev
));
532 ret
= regmap_bulk_read(data
->regmap
, reg
, buff
, sizeof(buff
));
534 dev_err_ratelimited(dev
, "read data failed\n");
538 *val
= get_unaligned_le24(&buff
);
540 pm_runtime_mark_last_busy(data
->dev
);
541 pm_runtime_put_autosuspend(data
->dev
);
546 static int apds9306_intg_time_get(struct apds9306_data
*data
, int *val2
)
548 struct apds9306_regfields
*rf
= &data
->rf
;
549 int ret
, intg_time_idx
;
551 ret
= regmap_field_read(rf
->intg_time
, &intg_time_idx
);
555 ret
= iio_gts_find_int_time_by_sel(&data
->gts
, intg_time_idx
);
564 static int apds9306_intg_time_set(struct apds9306_data
*data
, int val2
)
566 struct device
*dev
= data
->dev
;
567 struct apds9306_regfields
*rf
= &data
->rf
;
568 int ret
, intg_old
, gain_old
, gain_new
, gain_new_closest
, intg_time_idx
;
572 if (!iio_gts_valid_time(&data
->gts
, val2
)) {
573 dev_err_ratelimited(dev
, "Unsupported integration time %u\n", val2
);
577 ret
= regmap_field_read(rf
->intg_time
, &intg_time_idx
);
581 ret
= regmap_field_read(rf
->gain
, &gain_idx
);
585 intg_old
= iio_gts_find_int_time_by_sel(&data
->gts
, intg_time_idx
);
589 if (intg_old
== val2
)
592 gain_old
= iio_gts_find_gain_by_sel(&data
->gts
, gain_idx
);
596 iio_gts_find_new_gain_by_old_gain_time(&data
->gts
, gain_old
, intg_old
,
600 dev_err_ratelimited(dev
, "Unsupported gain with time\n");
604 gain_new_closest
= iio_find_closest_gain_low(&data
->gts
, gain_new
, &ok
);
605 if (gain_new_closest
< 0) {
606 gain_new_closest
= iio_gts_get_min_gain(&data
->gts
);
607 if (gain_new_closest
< 0)
608 return gain_new_closest
;
611 dev_dbg(dev
, "Unable to find optimum gain, setting minimum");
613 ret
= iio_gts_find_sel_by_int_time(&data
->gts
, val2
);
617 ret
= regmap_field_write(rf
->intg_time
, ret
);
621 ret
= iio_gts_find_sel_by_gain(&data
->gts
, gain_new_closest
);
625 return regmap_field_write(rf
->gain
, ret
);
628 static int apds9306_sampling_freq_get(struct apds9306_data
*data
, int *val
,
631 struct apds9306_regfields
*rf
= &data
->rf
;
632 int ret
, repeat_rate_idx
;
634 ret
= regmap_field_read(rf
->repeat_rate
, &repeat_rate_idx
);
638 if (repeat_rate_idx
>= ARRAY_SIZE(apds9306_repeat_rate_freq
))
641 *val
= apds9306_repeat_rate_freq
[repeat_rate_idx
][0];
642 *val2
= apds9306_repeat_rate_freq
[repeat_rate_idx
][1];
647 static int apds9306_sampling_freq_set(struct apds9306_data
*data
, int val
,
650 struct apds9306_regfields
*rf
= &data
->rf
;
653 for (i
= 0; i
< ARRAY_SIZE(apds9306_repeat_rate_freq
); i
++) {
654 if (apds9306_repeat_rate_freq
[i
][0] == val
&&
655 apds9306_repeat_rate_freq
[i
][1] == val2
)
656 return regmap_field_write(rf
->repeat_rate
, i
);
662 static int apds9306_scale_get(struct apds9306_data
*data
, int *val
, int *val2
)
664 struct apds9306_regfields
*rf
= &data
->rf
;
665 int gain
, intg
, ret
, intg_time_idx
, gain_idx
;
667 ret
= regmap_field_read(rf
->gain
, &gain_idx
);
671 ret
= regmap_field_read(rf
->intg_time
, &intg_time_idx
);
675 gain
= iio_gts_find_gain_by_sel(&data
->gts
, gain_idx
);
679 intg
= iio_gts_find_int_time_by_sel(&data
->gts
, intg_time_idx
);
683 return iio_gts_get_scale(&data
->gts
, gain
, intg
, val
, val2
);
686 static int apds9306_scale_set(struct apds9306_data
*data
, int val
, int val2
)
688 struct apds9306_regfields
*rf
= &data
->rf
;
689 int i
, ret
, time_sel
, gain_sel
, intg_time_idx
;
691 ret
= regmap_field_read(rf
->intg_time
, &intg_time_idx
);
695 ret
= iio_gts_find_gain_sel_for_scale_using_time(&data
->gts
,
696 intg_time_idx
, val
, val2
, &gain_sel
);
698 for (i
= 0; i
< data
->gts
.num_itime
; i
++) {
699 time_sel
= data
->gts
.itime_table
[i
].sel
;
701 if (time_sel
== intg_time_idx
)
704 ret
= iio_gts_find_gain_sel_for_scale_using_time(&data
->gts
,
705 time_sel
, val
, val2
, &gain_sel
);
712 ret
= regmap_field_write(rf
->intg_time
, time_sel
);
717 return regmap_field_write(rf
->gain
, gain_sel
);
720 static int apds9306_event_period_get(struct apds9306_data
*data
, int *val
)
722 struct apds9306_regfields
*rf
= &data
->rf
;
725 ret
= regmap_field_read(rf
->int_persist_val
, &period
);
729 if (!in_range(period
, 0, APDS9306_ALS_PERSIST_NUM_VALS
))
737 static int apds9306_event_period_set(struct apds9306_data
*data
, int val
)
739 struct apds9306_regfields
*rf
= &data
->rf
;
741 if (!in_range(val
, 0, APDS9306_ALS_PERSIST_NUM_VALS
))
744 return regmap_field_write(rf
->int_persist_val
, val
);
747 static int apds9306_event_thresh_get(struct apds9306_data
*data
, int dir
,
753 if (dir
== IIO_EV_DIR_RISING
)
754 var
= APDS9306_ALS_THRES_UP_0_REG
;
755 else if (dir
== IIO_EV_DIR_FALLING
)
756 var
= APDS9306_ALS_THRES_LOW_0_REG
;
760 ret
= regmap_bulk_read(data
->regmap
, var
, buff
, sizeof(buff
));
764 *val
= get_unaligned_le24(&buff
);
769 static int apds9306_event_thresh_set(struct apds9306_data
*data
, int dir
,
775 if (dir
== IIO_EV_DIR_RISING
)
776 var
= APDS9306_ALS_THRES_UP_0_REG
;
777 else if (dir
== IIO_EV_DIR_FALLING
)
778 var
= APDS9306_ALS_THRES_LOW_0_REG
;
782 if (!in_range(val
, 0, APDS9306_ALS_THRES_VAL_MAX
))
785 put_unaligned_le24(val
, buff
);
787 return regmap_bulk_write(data
->regmap
, var
, buff
, sizeof(buff
));
790 static int apds9306_event_thresh_adaptive_get(struct apds9306_data
*data
, int *val
)
792 struct apds9306_regfields
*rf
= &data
->rf
;
795 ret
= regmap_field_read(rf
->int_thresh_var_val
, &thr_adpt
);
799 if (!in_range(thr_adpt
, 0, APDS9306_ALS_THRES_VAR_NUM_VALS
))
807 static int apds9306_event_thresh_adaptive_set(struct apds9306_data
*data
, int val
)
809 struct apds9306_regfields
*rf
= &data
->rf
;
811 if (!in_range(val
, 0, APDS9306_ALS_THRES_VAR_NUM_VALS
))
814 return regmap_field_write(rf
->int_thresh_var_val
, val
);
817 static int apds9306_read_raw(struct iio_dev
*indio_dev
,
818 struct iio_chan_spec
const *chan
, int *val
,
819 int *val2
, long mask
)
821 struct apds9306_data
*data
= iio_priv(indio_dev
);
825 case IIO_CHAN_INFO_RAW
:
826 if (chan
->channel2
== IIO_MOD_LIGHT_CLEAR
)
827 reg
= APDS9306_CLEAR_DATA_0_REG
;
829 reg
= APDS9306_ALS_DATA_0_REG
;
831 * Changing device parameters during adc operation, resets
832 * the ADC which has to avoided.
834 ret
= iio_device_claim_direct_mode(indio_dev
);
837 ret
= apds9306_read_data(data
, val
, reg
);
838 iio_device_release_direct_mode(indio_dev
);
843 case IIO_CHAN_INFO_INT_TIME
:
844 ret
= apds9306_intg_time_get(data
, val2
);
849 return IIO_VAL_INT_PLUS_MICRO
;
850 case IIO_CHAN_INFO_SAMP_FREQ
:
851 ret
= apds9306_sampling_freq_get(data
, val
, val2
);
855 return IIO_VAL_INT_PLUS_MICRO
;
856 case IIO_CHAN_INFO_SCALE
:
857 ret
= apds9306_scale_get(data
, val
, val2
);
861 return IIO_VAL_INT_PLUS_NANO
;
867 static int apds9306_read_avail(struct iio_dev
*indio_dev
,
868 struct iio_chan_spec
const *chan
,
869 const int **vals
, int *type
, int *length
,
872 struct apds9306_data
*data
= iio_priv(indio_dev
);
875 case IIO_CHAN_INFO_INT_TIME
:
876 return iio_gts_avail_times(&data
->gts
, vals
, type
, length
);
877 case IIO_CHAN_INFO_SCALE
:
878 return iio_gts_all_avail_scales(&data
->gts
, vals
, type
, length
);
879 case IIO_CHAN_INFO_SAMP_FREQ
:
880 *length
= ARRAY_SIZE(apds9306_repeat_rate_freq
) * 2;
881 *vals
= (const int *)apds9306_repeat_rate_freq
;
882 *type
= IIO_VAL_INT_PLUS_MICRO
;
884 return IIO_AVAIL_LIST
;
890 static int apds9306_write_raw_get_fmt(struct iio_dev
*indio_dev
,
891 struct iio_chan_spec
const *chan
,
895 case IIO_CHAN_INFO_SCALE
:
896 return IIO_VAL_INT_PLUS_NANO
;
897 case IIO_CHAN_INFO_INT_TIME
:
898 return IIO_VAL_INT_PLUS_MICRO
;
899 case IIO_CHAN_INFO_SAMP_FREQ
:
900 return IIO_VAL_INT_PLUS_MICRO
;
906 static int apds9306_write_raw(struct iio_dev
*indio_dev
,
907 struct iio_chan_spec
const *chan
, int val
,
910 struct apds9306_data
*data
= iio_priv(indio_dev
);
912 guard(mutex
)(&data
->mutex
);
915 case IIO_CHAN_INFO_INT_TIME
:
918 return apds9306_intg_time_set(data
, val2
);
919 case IIO_CHAN_INFO_SCALE
:
920 return apds9306_scale_set(data
, val
, val2
);
921 case IIO_CHAN_INFO_SAMP_FREQ
:
922 return apds9306_sampling_freq_set(data
, val
, val2
);
928 static irqreturn_t
apds9306_irq_handler(int irq
, void *priv
)
930 struct iio_dev
*indio_dev
= priv
;
931 struct apds9306_data
*data
= iio_priv(indio_dev
);
932 struct apds9306_regfields
*rf
= &data
->rf
;
934 int ret
, status
, int_src
;
937 * The interrupt line is released and the interrupt flag is
938 * cleared as a result of reading the status register. All the
939 * status flags are cleared as a result of this read.
941 ret
= regmap_read(data
->regmap
, APDS9306_MAIN_STATUS_REG
, &status
);
943 dev_err_ratelimited(data
->dev
, "status reg read failed\n");
947 ret
= regmap_field_read(rf
->int_src
, &int_src
);
951 if ((status
& APDS9306_ALS_INT_STAT_MASK
)) {
952 if (int_src
== APDS9306_INT_SRC_ALS
)
953 ev_code
= IIO_UNMOD_EVENT_CODE(IIO_LIGHT
, 0,
957 ev_code
= IIO_MOD_EVENT_CODE(IIO_INTENSITY
, 0,
962 iio_push_event(indio_dev
, ev_code
, iio_get_time_ns(indio_dev
));
966 * If a one-shot read through sysfs is underway at the same time
967 * as this interrupt handler is executing and a read data available
968 * flag was set, this flag is set to inform read_poll_timeout()
971 if ((status
& APDS9306_ALS_DATA_STAT_MASK
))
972 data
->read_data_available
= 1;
977 static int apds9306_read_event(struct iio_dev
*indio_dev
,
978 const struct iio_chan_spec
*chan
,
979 enum iio_event_type type
,
980 enum iio_event_direction dir
,
981 enum iio_event_info info
,
984 struct apds9306_data
*data
= iio_priv(indio_dev
);
988 case IIO_EV_TYPE_THRESH
:
989 if (dir
== IIO_EV_DIR_EITHER
&& info
== IIO_EV_INFO_PERIOD
)
990 ret
= apds9306_event_period_get(data
, val
);
992 ret
= apds9306_event_thresh_get(data
, dir
, val
);
997 case IIO_EV_TYPE_THRESH_ADAPTIVE
:
998 ret
= apds9306_event_thresh_adaptive_get(data
, val
);
1008 static int apds9306_write_event(struct iio_dev
*indio_dev
,
1009 const struct iio_chan_spec
*chan
,
1010 enum iio_event_type type
,
1011 enum iio_event_direction dir
,
1012 enum iio_event_info info
,
1015 struct apds9306_data
*data
= iio_priv(indio_dev
);
1018 case IIO_EV_TYPE_THRESH
:
1019 if (dir
== IIO_EV_DIR_EITHER
&& info
== IIO_EV_INFO_PERIOD
)
1020 return apds9306_event_period_set(data
, val
);
1022 return apds9306_event_thresh_set(data
, dir
, val
);
1023 case IIO_EV_TYPE_THRESH_ADAPTIVE
:
1024 return apds9306_event_thresh_adaptive_set(data
, val
);
1030 static int apds9306_read_event_config(struct iio_dev
*indio_dev
,
1031 const struct iio_chan_spec
*chan
,
1032 enum iio_event_type type
,
1033 enum iio_event_direction dir
)
1035 struct apds9306_data
*data
= iio_priv(indio_dev
);
1036 struct apds9306_regfields
*rf
= &data
->rf
;
1037 int int_en
, int_src
, ret
;
1040 case IIO_EV_TYPE_THRESH
: {
1041 guard(mutex
)(&data
->mutex
);
1043 ret
= regmap_field_read(rf
->int_src
, &int_src
);
1047 ret
= regmap_field_read(rf
->int_en
, &int_en
);
1051 if (chan
->type
== IIO_LIGHT
)
1052 return int_en
&& (int_src
== APDS9306_INT_SRC_ALS
);
1054 if (chan
->type
== IIO_INTENSITY
)
1055 return int_en
&& (int_src
== APDS9306_INT_SRC_CLEAR
);
1059 case IIO_EV_TYPE_THRESH_ADAPTIVE
:
1060 ret
= regmap_field_read(rf
->int_thresh_var_en
, &int_en
);
1070 static int apds9306_write_event_config(struct iio_dev
*indio_dev
,
1071 const struct iio_chan_spec
*chan
,
1072 enum iio_event_type type
,
1073 enum iio_event_direction dir
,
1076 struct apds9306_data
*data
= iio_priv(indio_dev
);
1077 struct apds9306_regfields
*rf
= &data
->rf
;
1081 case IIO_EV_TYPE_THRESH
: {
1082 guard(mutex
)(&data
->mutex
);
1084 ret
= regmap_field_read(rf
->int_en
, &enabled
);
1089 * If interrupt is enabled, the channel is set before enabling
1090 * the interrupt. In case of disable, no need to switch
1091 * channels. In case of different channel is selected while
1092 * interrupt in on, just change the channel.
1095 if (chan
->type
== IIO_LIGHT
)
1096 ret
= regmap_field_write(rf
->int_src
, 1);
1097 else if (chan
->type
== IIO_INTENSITY
)
1098 ret
= regmap_field_write(rf
->int_src
, 0);
1108 ret
= regmap_field_write(rf
->int_en
, 1);
1112 return pm_runtime_resume_and_get(data
->dev
);
1117 ret
= regmap_field_write(rf
->int_en
, 0);
1121 pm_runtime_mark_last_busy(data
->dev
);
1122 pm_runtime_put_autosuspend(data
->dev
);
1127 case IIO_EV_TYPE_THRESH_ADAPTIVE
:
1128 return regmap_field_write(rf
->int_thresh_var_en
, state
);
1134 static const struct iio_info apds9306_info_no_events
= {
1135 .read_avail
= apds9306_read_avail
,
1136 .read_raw
= apds9306_read_raw
,
1137 .write_raw
= apds9306_write_raw
,
1138 .write_raw_get_fmt
= apds9306_write_raw_get_fmt
,
1141 static const struct iio_info apds9306_info
= {
1142 .read_avail
= apds9306_read_avail
,
1143 .read_raw
= apds9306_read_raw
,
1144 .write_raw
= apds9306_write_raw
,
1145 .write_raw_get_fmt
= apds9306_write_raw_get_fmt
,
1146 .read_event_value
= apds9306_read_event
,
1147 .write_event_value
= apds9306_write_event
,
1148 .read_event_config
= apds9306_read_event_config
,
1149 .write_event_config
= apds9306_write_event_config
,
1150 .event_attrs
= &apds9306_event_attr_group
,
1153 static int apds9306_init_iio_gts(struct apds9306_data
*data
)
1155 int i
, ret
, part_id
;
1157 ret
= regmap_read(data
->regmap
, APDS9306_PART_ID_REG
, &part_id
);
1161 for (i
= 0; i
< ARRAY_SIZE(apds9306_gts_mul
); i
++)
1162 if (part_id
== apds9306_gts_mul
[i
].part_id
)
1165 if (i
== ARRAY_SIZE(apds9306_gts_mul
))
1168 return devm_iio_init_iio_gts(data
->dev
,
1169 apds9306_gts_mul
[i
].max_scale_int
,
1170 apds9306_gts_mul
[i
].max_scale_nano
,
1171 apds9306_gains
, ARRAY_SIZE(apds9306_gains
),
1172 apds9306_itimes
, ARRAY_SIZE(apds9306_itimes
),
1176 static void apds9306_powerdown(void *ptr
)
1178 struct apds9306_data
*data
= (struct apds9306_data
*)ptr
;
1179 struct apds9306_regfields
*rf
= &data
->rf
;
1182 ret
= regmap_field_write(rf
->int_thresh_var_en
, 0);
1186 ret
= regmap_field_write(rf
->int_en
, 0);
1190 apds9306_power_state(data
, false);
1193 static int apds9306_device_init(struct apds9306_data
*data
)
1195 struct apds9306_regfields
*rf
= &data
->rf
;
1198 ret
= apds9306_init_iio_gts(data
);
1202 ret
= regmap_field_write(rf
->intg_time
, APDS9306_MEAS_MODE_100MS
);
1206 ret
= regmap_field_write(rf
->repeat_rate
, APDS9306_SAMP_FREQ_10HZ
);
1210 ret
= regmap_field_write(rf
->gain
, APDS9306_GSEL_3X
);
1214 ret
= regmap_field_write(rf
->int_src
, APDS9306_INT_SRC_ALS
);
1218 ret
= regmap_field_write(rf
->int_en
, 0);
1222 return regmap_field_write(rf
->int_thresh_var_en
, 0);
1225 static int apds9306_pm_init(struct apds9306_data
*data
)
1227 struct device
*dev
= data
->dev
;
1230 ret
= apds9306_power_state(data
, true);
1234 ret
= pm_runtime_set_active(dev
);
1238 ret
= devm_pm_runtime_enable(dev
);
1242 pm_runtime_set_autosuspend_delay(dev
, 5000);
1243 pm_runtime_use_autosuspend(dev
);
1244 pm_runtime_get(dev
);
1249 static int apds9306_probe(struct i2c_client
*client
)
1251 struct device
*dev
= &client
->dev
;
1252 struct apds9306_data
*data
;
1253 struct iio_dev
*indio_dev
;
1256 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
1260 data
= iio_priv(indio_dev
);
1262 mutex_init(&data
->mutex
);
1264 data
->regmap
= devm_regmap_init_i2c(client
, &apds9306_regmap
);
1265 if (IS_ERR(data
->regmap
))
1266 return dev_err_probe(dev
, PTR_ERR(data
->regmap
),
1267 "regmap initialization failed\n");
1270 i2c_set_clientdata(client
, indio_dev
);
1272 ret
= apds9306_regfield_init(data
);
1274 return dev_err_probe(dev
, ret
, "regfield initialization failed\n");
1276 ret
= devm_regulator_get_enable(dev
, "vdd");
1278 return dev_err_probe(dev
, ret
, "Failed to enable regulator\n");
1280 indio_dev
->name
= "apds9306";
1281 indio_dev
->modes
= INDIO_DIRECT_MODE
;
1283 indio_dev
->info
= &apds9306_info
;
1284 indio_dev
->channels
= apds9306_channels_with_events
;
1285 indio_dev
->num_channels
= ARRAY_SIZE(apds9306_channels_with_events
);
1286 ret
= devm_request_threaded_irq(dev
, client
->irq
, NULL
,
1287 apds9306_irq_handler
, IRQF_ONESHOT
,
1288 "apds9306_event", indio_dev
);
1290 return dev_err_probe(dev
, ret
,
1291 "failed to assign interrupt.\n");
1293 indio_dev
->info
= &apds9306_info_no_events
;
1294 indio_dev
->channels
= apds9306_channels_without_events
;
1295 indio_dev
->num_channels
=
1296 ARRAY_SIZE(apds9306_channels_without_events
);
1299 ret
= apds9306_pm_init(data
);
1301 return dev_err_probe(dev
, ret
, "failed pm init\n");
1303 ret
= apds9306_device_init(data
);
1305 return dev_err_probe(dev
, ret
, "failed to init device\n");
1307 ret
= devm_add_action_or_reset(dev
, apds9306_powerdown
, data
);
1309 return dev_err_probe(dev
, ret
, "failed to add action or reset\n");
1311 ret
= devm_iio_device_register(dev
, indio_dev
);
1313 return dev_err_probe(dev
, ret
, "failed iio device registration\n");
1315 pm_runtime_put_autosuspend(dev
);
1320 static int apds9306_runtime_suspend(struct device
*dev
)
1322 struct apds9306_data
*data
= iio_priv(dev_get_drvdata(dev
));
1324 return apds9306_power_state(data
, false);
1327 static int apds9306_runtime_resume(struct device
*dev
)
1329 struct apds9306_data
*data
= iio_priv(dev_get_drvdata(dev
));
1331 return apds9306_power_state(data
, true);
1334 static DEFINE_RUNTIME_DEV_PM_OPS(apds9306_pm_ops
,
1335 apds9306_runtime_suspend
,
1336 apds9306_runtime_resume
,
1339 static const struct of_device_id apds9306_of_match
[] = {
1340 { .compatible
= "avago,apds9306" },
1343 MODULE_DEVICE_TABLE(of
, apds9306_of_match
);
1345 static struct i2c_driver apds9306_driver
= {
1348 .pm
= pm_ptr(&apds9306_pm_ops
),
1349 .of_match_table
= apds9306_of_match
,
1351 .probe
= apds9306_probe
,
1353 module_i2c_driver(apds9306_driver
);
1355 MODULE_AUTHOR("Subhajit Ghosh <subhajit.ghosh@tweaklogic.com>");
1356 MODULE_DESCRIPTION("APDS9306 Ambient Light Sensor driver");
1357 MODULE_LICENSE("GPL");
1358 MODULE_IMPORT_NS("IIO_GTS_HELPER");