1362 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * APDS-9306/APDS-9306-065 Ambient Light Sensor4 * I2C Address: 0x525 * Datasheet: https://docs.broadcom.com/doc/AV02-4755EN6 *7 * Copyright (C) 2024 Subhajit Ghosh <subhajit.ghosh@tweaklogic.com>8 */9 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>19#include <linux/pm.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>25 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>30 31#include <linux/unaligned.h>32 33#define APDS9306_MAIN_CTRL_REG 0x0034#define APDS9306_ALS_MEAS_RATE_REG 0x0435#define APDS9306_ALS_GAIN_REG 0x0536#define APDS9306_PART_ID_REG 0x0637#define APDS9306_MAIN_STATUS_REG 0x0738#define APDS9306_CLEAR_DATA_0_REG 0x0A39#define APDS9306_CLEAR_DATA_1_REG 0x0B40#define APDS9306_CLEAR_DATA_2_REG 0x0C41#define APDS9306_ALS_DATA_0_REG 0x0D42#define APDS9306_ALS_DATA_1_REG 0x0E43#define APDS9306_ALS_DATA_2_REG 0x0F44#define APDS9306_INT_CFG_REG 0x1945#define APDS9306_INT_PERSISTENCE_REG 0x1A46#define APDS9306_ALS_THRES_UP_0_REG 0x2147#define APDS9306_ALS_THRES_UP_1_REG 0x2248#define APDS9306_ALS_THRES_UP_2_REG 0x2349#define APDS9306_ALS_THRES_LOW_0_REG 0x2450#define APDS9306_ALS_THRES_LOW_1_REG 0x2551#define APDS9306_ALS_THRES_LOW_2_REG 0x2652#define APDS9306_ALS_THRES_VAR_REG 0x2753 54#define APDS9306_ALS_INT_STAT_MASK BIT(4)55#define APDS9306_ALS_DATA_STAT_MASK BIT(3)56 57#define APDS9306_ALS_THRES_VAL_MAX (BIT(20) - 1)58#define APDS9306_ALS_THRES_VAR_NUM_VALS 859#define APDS9306_ALS_PERSIST_NUM_VALS 1660#define APDS9306_ALS_READ_DATA_DELAY_US (20 * USEC_PER_MSEC)61#define APDS9306_NUM_REPEAT_RATES 762#define APDS9306_INT_SRC_CLEAR 063#define APDS9306_INT_SRC_ALS 164#define APDS9306_SAMP_FREQ_10HZ 065 66/**67 * struct part_id_gts_multiplier - Part no. and corresponding gts multiplier68 *69 * GTS (Gain Time Scale) are helper functions for Light sensors which along70 * with hardware gains also has gains associated with Integration times.71 *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 the74 * datasheet. This multiplier array is used to store the derived Lux per count75 * value for the two variants to be used by the GTS helper functions.76 *77 * @part_id: Part ID of the device78 * @max_scale_int: Multiplier for iio_init_iio_gts()79 * @max_scale_nano: Multiplier for iio_init_iio_gts()80 */81struct part_id_gts_multiplier {82 int part_id;83 int max_scale_int;84 int max_scale_nano;85};86 87/*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.92 *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.96 *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.99 *100 * Lux per ADC count at 3x and 32x for apds9306 = 340.134 / 2000101 * Lux per ADC count at 3x and 32x for apds9306-065 = 293.69 / 2000102 *103 * The Multiplier for the scale table provided to userspace:104 * IIO GTS scale Multiplier for apds9306 = (340.134 / 2000) * 32 * 3 = 16.326432105 * and for apds9306-065 = (293.69 / 2000) * 32 * 3 = 14.09712106 */107static const struct part_id_gts_multiplier apds9306_gts_mul[] = {108 {109 .part_id = 0xB1,110 .max_scale_int = 16,111 .max_scale_nano = 3264320,112 }, {113 .part_id = 0xB3,114 .max_scale_int = 14,115 .max_scale_nano = 9712000,116 },117};118 119static const int apds9306_repeat_rate_freq[APDS9306_NUM_REPEAT_RATES][2] = {120 { 40, 0 },121 { 20, 0 },122 { 10, 0 },123 { 5, 0 },124 { 2, 0 },125 { 1, 0 },126 { 0, 500000 },127};128 129static const int apds9306_repeat_rate_period[APDS9306_NUM_REPEAT_RATES] = {130 25000, 50000, 100000, 200000, 500000, 1000000, 2000000,131};132 133/**134 * struct apds9306_regfields - apds9306 regmap fields definitions135 *136 * @sw_reset: Software reset regfield137 * @en: Enable regfield138 * @intg_time: Resolution regfield139 * @repeat_rate: Measurement Rate regfield140 * @gain: Hardware gain regfield141 * @int_src: Interrupt channel regfield142 * @int_thresh_var_en: Interrupt variance threshold regfield143 * @int_en: Interrupt enable regfield144 * @int_persist_val: Interrupt persistence regfield145 * @int_thresh_var_val: Interrupt threshold variance value regfield146 */147struct 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;158};159 160/**161 * struct apds9306_data - apds9306 private data and registers definitions162 *163 * @dev: Pointer to the device structure164 * @gts: IIO Gain Time Scale structure165 * @mutex: Lock for protecting adc reads, device settings changes where166 * some calculations are required before or after setting or167 * getting the raw settings values from regmap writes or reads168 * respectively.169 * @regmap: Regmap structure pointer170 * @rf: Regmap register fields structure171 * @nlux_per_count: Nano lux per ADC count for a particular model172 * @read_data_available: Flag set by IRQ handler for ADC data available173 */174struct apds9306_data {175 struct device *dev;176 struct iio_gts gts;177 178 struct mutex mutex;179 180 struct regmap *regmap;181 struct apds9306_regfields rf;182 183 int nlux_per_count;184 int read_data_available;185};186 187/*188 * Available scales with gain 1x - 18x, timings 3.125, 25, 50, 100, 200, 400 ms189 * Time impacts to gain: 1x, 8x, 16x, 32x, 64x, 128x190 */191#define APDS9306_GSEL_1X 0x00192#define APDS9306_GSEL_3X 0x01193#define APDS9306_GSEL_6X 0x02194#define APDS9306_GSEL_9X 0x03195#define APDS9306_GSEL_18X 0x04196 197static 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),203};204 205#define APDS9306_MEAS_MODE_400MS 0x00206#define APDS9306_MEAS_MODE_200MS 0x01207#define APDS9306_MEAS_MODE_100MS 0x02208#define APDS9306_MEAS_MODE_50MS 0x03209#define APDS9306_MEAS_MODE_25MS 0x04210#define APDS9306_MEAS_MODE_3125US 0x05211 212static 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)),219};220 221static const struct iio_event_spec apds9306_event_spec[] = {222 {223 .type = IIO_EV_TYPE_THRESH,224 .dir = IIO_EV_DIR_RISING,225 .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE),226 }, {227 .type = IIO_EV_TYPE_THRESH,228 .dir = IIO_EV_DIR_FALLING,229 .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE),230 }, {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),235 }, {236 .type = IIO_EV_TYPE_THRESH_ADAPTIVE,237 .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE) |238 BIT(IIO_EV_INFO_ENABLE),239 },240};241 242static const struct iio_chan_spec apds9306_channels_with_events[] = {243 {244 .type = IIO_LIGHT,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),254 }, {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),262 .modified = 1,263 .event_spec = apds9306_event_spec,264 .num_event_specs = ARRAY_SIZE(apds9306_event_spec),265 },266};267 268static const struct iio_chan_spec apds9306_channels_without_events[] = {269 {270 .type = IIO_LIGHT,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),278 }, {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),285 .modified = 1,286 .channel2 = IIO_MOD_LIGHT_CLEAR,287 },288};289 290/* INT_PERSISTENCE available */291static IIO_CONST_ATTR(thresh_either_period_available, "[0 1 15]");292 293/* ALS_THRESH_VAR available */294static IIO_CONST_ATTR(thresh_adaptive_either_values_available, "[0 1 7]");295 296static 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,299 NULL300};301 302static const struct attribute_group apds9306_event_attr_group = {303 .attrs = apds9306_event_attributes,304};305 306static const struct regmap_range apds9306_readable_ranges[] = {307 regmap_reg_range(APDS9306_MAIN_CTRL_REG, APDS9306_ALS_THRES_VAR_REG)308};309 310static 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)313};314 315static 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)318};319 320static const struct regmap_range apds9306_precious_ranges[] = {321 regmap_reg_range(APDS9306_MAIN_STATUS_REG, APDS9306_MAIN_STATUS_REG)322};323 324static const struct regmap_access_table apds9306_readable_table = {325 .yes_ranges = apds9306_readable_ranges,326 .n_yes_ranges = ARRAY_SIZE(apds9306_readable_ranges)327};328 329static const struct regmap_access_table apds9306_writable_table = {330 .yes_ranges = apds9306_writable_ranges,331 .n_yes_ranges = ARRAY_SIZE(apds9306_writable_ranges)332};333 334static const struct regmap_access_table apds9306_volatile_table = {335 .yes_ranges = apds9306_volatile_ranges,336 .n_yes_ranges = ARRAY_SIZE(apds9306_volatile_ranges)337};338 339static const struct regmap_access_table apds9306_precious_table = {340 .yes_ranges = apds9306_precious_ranges,341 .n_yes_ranges = ARRAY_SIZE(apds9306_precious_ranges)342};343 344static const struct regmap_config apds9306_regmap = {345 .name = "apds9306_regmap",346 .reg_bits = 8,347 .val_bits = 8,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,354};355 356static const struct reg_field apds9306_rf_sw_reset =357 REG_FIELD(APDS9306_MAIN_CTRL_REG, 4, 4);358 359static const struct reg_field apds9306_rf_en =360 REG_FIELD(APDS9306_MAIN_CTRL_REG, 1, 1);361 362static const struct reg_field apds9306_rf_intg_time =363 REG_FIELD(APDS9306_ALS_MEAS_RATE_REG, 4, 6);364 365static const struct reg_field apds9306_rf_repeat_rate =366 REG_FIELD(APDS9306_ALS_MEAS_RATE_REG, 0, 2);367 368static const struct reg_field apds9306_rf_gain =369 REG_FIELD(APDS9306_ALS_GAIN_REG, 0, 2);370 371static const struct reg_field apds9306_rf_int_src =372 REG_FIELD(APDS9306_INT_CFG_REG, 4, 5);373 374static const struct reg_field apds9306_rf_int_thresh_var_en =375 REG_FIELD(APDS9306_INT_CFG_REG, 3, 3);376 377static const struct reg_field apds9306_rf_int_en =378 REG_FIELD(APDS9306_INT_CFG_REG, 2, 2);379 380static const struct reg_field apds9306_rf_int_persist_val =381 REG_FIELD(APDS9306_INT_PERSISTENCE_REG, 4, 7);382 383static const struct reg_field apds9306_rf_int_thresh_var_val =384 REG_FIELD(APDS9306_ALS_THRES_VAR_REG, 0, 2);385 386static int apds9306_regfield_init(struct apds9306_data *data)387{388 struct device *dev = data->dev;389 struct regmap *regmap = data->regmap;390 struct regmap_field *tmp;391 struct apds9306_regfields *rf = &data->rf;392 393 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_sw_reset);394 if (IS_ERR(tmp))395 return PTR_ERR(tmp);396 rf->sw_reset = tmp;397 398 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_en);399 if (IS_ERR(tmp))400 return PTR_ERR(tmp);401 rf->en = tmp;402 403 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_intg_time);404 if (IS_ERR(tmp))405 return PTR_ERR(tmp);406 rf->intg_time = tmp;407 408 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_repeat_rate);409 if (IS_ERR(tmp))410 return PTR_ERR(tmp);411 rf->repeat_rate = tmp;412 413 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_gain);414 if (IS_ERR(tmp))415 return PTR_ERR(tmp);416 rf->gain = tmp;417 418 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_int_src);419 if (IS_ERR(tmp))420 return PTR_ERR(tmp);421 rf->int_src = tmp;422 423 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_int_thresh_var_en);424 if (IS_ERR(tmp))425 return PTR_ERR(tmp);426 rf->int_thresh_var_en = tmp;427 428 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_int_en);429 if (IS_ERR(tmp))430 return PTR_ERR(tmp);431 rf->int_en = tmp;432 433 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_int_persist_val);434 if (IS_ERR(tmp))435 return PTR_ERR(tmp);436 rf->int_persist_val = tmp;437 438 tmp = devm_regmap_field_alloc(dev, regmap, apds9306_rf_int_thresh_var_val);439 if (IS_ERR(tmp))440 return PTR_ERR(tmp);441 rf->int_thresh_var_val = tmp;442 443 return 0;444}445 446static int apds9306_power_state(struct apds9306_data *data, bool state)447{448 struct apds9306_regfields *rf = &data->rf;449 int ret;450 451 /* Reset not included as it causes ugly I2C bus error */452 if (state) {453 ret = regmap_field_write(rf->en, 1);454 if (ret)455 return ret;456 /* 5ms wake up time */457 fsleep(5000);458 return 0;459 }460 461 return regmap_field_write(rf->en, 0);462}463 464static int apds9306_read_data(struct apds9306_data *data, int *val, int reg)465{466 struct device *dev = data->dev;467 struct iio_dev *indio_dev = dev_to_iio_dev(dev);468 struct apds9306_regfields *rf = &data->rf;469 u64 ev_code;470 int ret, delay, intg_time, intg_time_idx, repeat_rate_idx, int_src;471 int status = 0;472 u8 buff[3];473 474 ret = pm_runtime_resume_and_get(data->dev);475 if (ret)476 return ret;477 478 ret = regmap_field_read(rf->intg_time, &intg_time_idx);479 if (ret)480 return ret;481 482 ret = regmap_field_read(rf->repeat_rate, &repeat_rate_idx);483 if (ret)484 return ret;485 486 ret = regmap_field_read(rf->int_src, &int_src);487 if (ret)488 return ret;489 490 intg_time = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);491 if (intg_time < 0)492 return intg_time;493 494 /* Whichever is greater - integration time period or sampling period. */495 delay = max(intg_time, apds9306_repeat_rate_period[repeat_rate_idx]);496 497 /*498 * Clear stale data flag that might have been set by the interrupt499 * handler if it got data available flag set in the status reg.500 */501 data->read_data_available = 0;502 503 /*504 * If this function runs parallel with the interrupt handler, either505 * this reads and clears the status registers or the interrupt handler506 * does. The interrupt handler sets a flag for read data available507 * in our private structure which we read here.508 */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);514 if (ret)515 return ret;516 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,521 IIO_EV_TYPE_THRESH,522 IIO_EV_DIR_EITHER);523 else524 ev_code = IIO_MOD_EVENT_CODE(IIO_INTENSITY, 0,525 IIO_MOD_LIGHT_CLEAR,526 IIO_EV_TYPE_THRESH,527 IIO_EV_DIR_EITHER);528 529 iio_push_event(indio_dev, ev_code, iio_get_time_ns(indio_dev));530 }531 532 ret = regmap_bulk_read(data->regmap, reg, buff, sizeof(buff));533 if (ret) {534 dev_err_ratelimited(dev, "read data failed\n");535 return ret;536 }537 538 *val = get_unaligned_le24(&buff);539 540 pm_runtime_mark_last_busy(data->dev);541 pm_runtime_put_autosuspend(data->dev);542 543 return 0;544}545 546static int apds9306_intg_time_get(struct apds9306_data *data, int *val2)547{548 struct apds9306_regfields *rf = &data->rf;549 int ret, intg_time_idx;550 551 ret = regmap_field_read(rf->intg_time, &intg_time_idx);552 if (ret)553 return ret;554 555 ret = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);556 if (ret < 0)557 return ret;558 559 *val2 = ret;560 561 return 0;562}563 564static int apds9306_intg_time_set(struct apds9306_data *data, int val2)565{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;569 int gain_idx;570 bool ok;571 572 if (!iio_gts_valid_time(&data->gts, val2)) {573 dev_err_ratelimited(dev, "Unsupported integration time %u\n", val2);574 return -EINVAL;575 }576 577 ret = regmap_field_read(rf->intg_time, &intg_time_idx);578 if (ret)579 return ret;580 581 ret = regmap_field_read(rf->gain, &gain_idx);582 if (ret)583 return ret;584 585 intg_old = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);586 if (intg_old < 0)587 return intg_old;588 589 if (intg_old == val2)590 return 0;591 592 gain_old = iio_gts_find_gain_by_sel(&data->gts, gain_idx);593 if (gain_old < 0)594 return gain_old;595 596 iio_gts_find_new_gain_by_old_gain_time(&data->gts, gain_old, intg_old,597 val2, &gain_new);598 599 if (gain_new < 0) {600 dev_err_ratelimited(dev, "Unsupported gain with time\n");601 return gain_new;602 }603 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;609 }610 if (!ok)611 dev_dbg(dev, "Unable to find optimum gain, setting minimum");612 613 ret = iio_gts_find_sel_by_int_time(&data->gts, val2);614 if (ret < 0)615 return ret;616 617 ret = regmap_field_write(rf->intg_time, ret);618 if (ret)619 return ret;620 621 ret = iio_gts_find_sel_by_gain(&data->gts, gain_new_closest);622 if (ret < 0)623 return ret;624 625 return regmap_field_write(rf->gain, ret);626}627 628static int apds9306_sampling_freq_get(struct apds9306_data *data, int *val,629 int *val2)630{631 struct apds9306_regfields *rf = &data->rf;632 int ret, repeat_rate_idx;633 634 ret = regmap_field_read(rf->repeat_rate, &repeat_rate_idx);635 if (ret)636 return ret;637 638 if (repeat_rate_idx >= ARRAY_SIZE(apds9306_repeat_rate_freq))639 return -EINVAL;640 641 *val = apds9306_repeat_rate_freq[repeat_rate_idx][0];642 *val2 = apds9306_repeat_rate_freq[repeat_rate_idx][1];643 644 return 0;645}646 647static int apds9306_sampling_freq_set(struct apds9306_data *data, int val,648 int val2)649{650 struct apds9306_regfields *rf = &data->rf;651 int i;652 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);657 }658 659 return -EINVAL;660}661 662static int apds9306_scale_get(struct apds9306_data *data, int *val, int *val2)663{664 struct apds9306_regfields *rf = &data->rf;665 int gain, intg, ret, intg_time_idx, gain_idx;666 667 ret = regmap_field_read(rf->gain, &gain_idx);668 if (ret)669 return ret;670 671 ret = regmap_field_read(rf->intg_time, &intg_time_idx);672 if (ret)673 return ret;674 675 gain = iio_gts_find_gain_by_sel(&data->gts, gain_idx);676 if (gain < 0)677 return gain;678 679 intg = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx);680 if (intg < 0)681 return intg;682 683 return iio_gts_get_scale(&data->gts, gain, intg, val, val2);684}685 686static int apds9306_scale_set(struct apds9306_data *data, int val, int val2)687{688 struct apds9306_regfields *rf = &data->rf;689 int i, ret, time_sel, gain_sel, intg_time_idx;690 691 ret = regmap_field_read(rf->intg_time, &intg_time_idx);692 if (ret)693 return ret;694 695 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,696 intg_time_idx, val, val2, &gain_sel);697 if (ret) {698 for (i = 0; i < data->gts.num_itime; i++) {699 time_sel = data->gts.itime_table[i].sel;700 701 if (time_sel == intg_time_idx)702 continue;703 704 ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts,705 time_sel, val, val2, &gain_sel);706 if (!ret)707 break;708 }709 if (ret)710 return -EINVAL;711 712 ret = regmap_field_write(rf->intg_time, time_sel);713 if (ret)714 return ret;715 }716 717 return regmap_field_write(rf->gain, gain_sel);718}719 720static int apds9306_event_period_get(struct apds9306_data *data, int *val)721{722 struct apds9306_regfields *rf = &data->rf;723 int period, ret;724 725 ret = regmap_field_read(rf->int_persist_val, &period);726 if (ret)727 return ret;728 729 if (!in_range(period, 0, APDS9306_ALS_PERSIST_NUM_VALS))730 return -EINVAL;731 732 *val = period;733 734 return ret;735}736 737static int apds9306_event_period_set(struct apds9306_data *data, int val)738{739 struct apds9306_regfields *rf = &data->rf;740 741 if (!in_range(val, 0, APDS9306_ALS_PERSIST_NUM_VALS))742 return -EINVAL;743 744 return regmap_field_write(rf->int_persist_val, val);745}746 747static int apds9306_event_thresh_get(struct apds9306_data *data, int dir,748 int *val)749{750 int var, ret;751 u8 buff[3];752 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;757 else758 return -EINVAL;759 760 ret = regmap_bulk_read(data->regmap, var, buff, sizeof(buff));761 if (ret)762 return ret;763 764 *val = get_unaligned_le24(&buff);765 766 return 0;767}768 769static int apds9306_event_thresh_set(struct apds9306_data *data, int dir,770 int val)771{772 int var;773 u8 buff[3];774 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;779 else780 return -EINVAL;781 782 if (!in_range(val, 0, APDS9306_ALS_THRES_VAL_MAX))783 return -EINVAL;784 785 put_unaligned_le24(val, buff);786 787 return regmap_bulk_write(data->regmap, var, buff, sizeof(buff));788}789 790static int apds9306_event_thresh_adaptive_get(struct apds9306_data *data, int *val)791{792 struct apds9306_regfields *rf = &data->rf;793 int thr_adpt, ret;794 795 ret = regmap_field_read(rf->int_thresh_var_val, &thr_adpt);796 if (ret)797 return ret;798 799 if (!in_range(thr_adpt, 0, APDS9306_ALS_THRES_VAR_NUM_VALS))800 return -EINVAL;801 802 *val = thr_adpt;803 804 return ret;805}806 807static int apds9306_event_thresh_adaptive_set(struct apds9306_data *data, int val)808{809 struct apds9306_regfields *rf = &data->rf;810 811 if (!in_range(val, 0, APDS9306_ALS_THRES_VAR_NUM_VALS))812 return -EINVAL;813 814 return regmap_field_write(rf->int_thresh_var_val, val);815}816 817static int apds9306_read_raw(struct iio_dev *indio_dev,818 struct iio_chan_spec const *chan, int *val,819 int *val2, long mask)820{821 struct apds9306_data *data = iio_priv(indio_dev);822 int ret, reg;823 824 switch (mask) {825 case IIO_CHAN_INFO_RAW:826 if (chan->channel2 == IIO_MOD_LIGHT_CLEAR)827 reg = APDS9306_CLEAR_DATA_0_REG;828 else829 reg = APDS9306_ALS_DATA_0_REG;830 /*831 * Changing device parameters during adc operation, resets832 * the ADC which has to avoided.833 */834 ret = iio_device_claim_direct_mode(indio_dev);835 if (ret)836 return ret;837 ret = apds9306_read_data(data, val, reg);838 iio_device_release_direct_mode(indio_dev);839 if (ret)840 return ret;841 842 return IIO_VAL_INT;843 case IIO_CHAN_INFO_INT_TIME:844 ret = apds9306_intg_time_get(data, val2);845 if (ret)846 return ret;847 *val = 0;848 849 return IIO_VAL_INT_PLUS_MICRO;850 case IIO_CHAN_INFO_SAMP_FREQ:851 ret = apds9306_sampling_freq_get(data, val, val2);852 if (ret)853 return ret;854 855 return IIO_VAL_INT_PLUS_MICRO;856 case IIO_CHAN_INFO_SCALE:857 ret = apds9306_scale_get(data, val, val2);858 if (ret)859 return ret;860 861 return IIO_VAL_INT_PLUS_NANO;862 default:863 return -EINVAL;864 }865};866 867static int apds9306_read_avail(struct iio_dev *indio_dev,868 struct iio_chan_spec const *chan,869 const int **vals, int *type, int *length,870 long mask)871{872 struct apds9306_data *data = iio_priv(indio_dev);873 874 switch (mask) {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;883 884 return IIO_AVAIL_LIST;885 default:886 return -EINVAL;887 }888}889 890static int apds9306_write_raw_get_fmt(struct iio_dev *indio_dev,891 struct iio_chan_spec const *chan,892 long mask)893{894 switch (mask) {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;901 default:902 return -EINVAL;903 }904}905 906static int apds9306_write_raw(struct iio_dev *indio_dev,907 struct iio_chan_spec const *chan, int val,908 int val2, long mask)909{910 struct apds9306_data *data = iio_priv(indio_dev);911 912 guard(mutex)(&data->mutex);913 914 switch (mask) {915 case IIO_CHAN_INFO_INT_TIME:916 if (val)917 return -EINVAL;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);923 default:924 return -EINVAL;925 }926}927 928static irqreturn_t apds9306_irq_handler(int irq, void *priv)929{930 struct iio_dev *indio_dev = priv;931 struct apds9306_data *data = iio_priv(indio_dev);932 struct apds9306_regfields *rf = &data->rf;933 u64 ev_code;934 int ret, status, int_src;935 936 /*937 * The interrupt line is released and the interrupt flag is938 * cleared as a result of reading the status register. All the939 * status flags are cleared as a result of this read.940 */941 ret = regmap_read(data->regmap, APDS9306_MAIN_STATUS_REG, &status);942 if (ret < 0) {943 dev_err_ratelimited(data->dev, "status reg read failed\n");944 return IRQ_HANDLED;945 }946 947 ret = regmap_field_read(rf->int_src, &int_src);948 if (ret)949 return ret;950 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,954 IIO_EV_TYPE_THRESH,955 IIO_EV_DIR_EITHER);956 else957 ev_code = IIO_MOD_EVENT_CODE(IIO_INTENSITY, 0,958 IIO_MOD_LIGHT_CLEAR,959 IIO_EV_TYPE_THRESH,960 IIO_EV_DIR_EITHER);961 962 iio_push_event(indio_dev, ev_code, iio_get_time_ns(indio_dev));963 }964 965 /*966 * If a one-shot read through sysfs is underway at the same time967 * as this interrupt handler is executing and a read data available968 * flag was set, this flag is set to inform read_poll_timeout()969 * to exit.970 */971 if ((status & APDS9306_ALS_DATA_STAT_MASK))972 data->read_data_available = 1;973 974 return IRQ_HANDLED;975}976 977static 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,982 int *val, int *val2)983{984 struct apds9306_data *data = iio_priv(indio_dev);985 int ret;986 987 switch (type) {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);991 else992 ret = apds9306_event_thresh_get(data, dir, val);993 if (ret)994 return ret;995 996 return IIO_VAL_INT;997 case IIO_EV_TYPE_THRESH_ADAPTIVE:998 ret = apds9306_event_thresh_adaptive_get(data, val);999 if (ret)1000 return ret;1001 1002 return IIO_VAL_INT;1003 default:1004 return -EINVAL;1005 }1006}1007 1008static 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,1013 int val, int val2)1014{1015 struct apds9306_data *data = iio_priv(indio_dev);1016 1017 switch (type) {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);1021 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);1025 default:1026 return -EINVAL;1027 }1028}1029 1030static 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)1034{1035 struct apds9306_data *data = iio_priv(indio_dev);1036 struct apds9306_regfields *rf = &data->rf;1037 int int_en, int_src, ret;1038 1039 switch (type) {1040 case IIO_EV_TYPE_THRESH: {1041 guard(mutex)(&data->mutex);1042 1043 ret = regmap_field_read(rf->int_src, &int_src);1044 if (ret)1045 return ret;1046 1047 ret = regmap_field_read(rf->int_en, &int_en);1048 if (ret)1049 return ret;1050 1051 if (chan->type == IIO_LIGHT)1052 return int_en && (int_src == APDS9306_INT_SRC_ALS);1053 1054 if (chan->type == IIO_INTENSITY)1055 return int_en && (int_src == APDS9306_INT_SRC_CLEAR);1056 1057 return -EINVAL;1058 }1059 case IIO_EV_TYPE_THRESH_ADAPTIVE:1060 ret = regmap_field_read(rf->int_thresh_var_en, &int_en);1061 if (ret)1062 return ret;1063 1064 return int_en;1065 default:1066 return -EINVAL;1067 }1068}1069 1070static 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,1074 int state)1075{1076 struct apds9306_data *data = iio_priv(indio_dev);1077 struct apds9306_regfields *rf = &data->rf;1078 int ret, enabled;1079 1080 switch (type) {1081 case IIO_EV_TYPE_THRESH: {1082 guard(mutex)(&data->mutex);1083 1084 ret = regmap_field_read(rf->int_en, &enabled);1085 if (ret)1086 return ret;1087 1088 /*1089 * If interrupt is enabled, the channel is set before enabling1090 * the interrupt. In case of disable, no need to switch1091 * channels. In case of different channel is selected while1092 * interrupt in on, just change the channel.1093 */1094 if (state) {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);1099 else1100 return -EINVAL;1101 1102 if (ret)1103 return ret;1104 1105 if (enabled)1106 return 0;1107 1108 ret = regmap_field_write(rf->int_en, 1);1109 if (ret)1110 return ret;1111 1112 return pm_runtime_resume_and_get(data->dev);1113 } else {1114 if (!enabled)1115 return 0;1116 1117 ret = regmap_field_write(rf->int_en, 0);1118 if (ret)1119 return ret;1120 1121 pm_runtime_mark_last_busy(data->dev);1122 pm_runtime_put_autosuspend(data->dev);1123 1124 return 0;1125 }1126 }1127 case IIO_EV_TYPE_THRESH_ADAPTIVE:1128 if (state)1129 return regmap_field_write(rf->int_thresh_var_en, 1);1130 else1131 return regmap_field_write(rf->int_thresh_var_en, 0);1132 default:1133 return -EINVAL;1134 }1135}1136 1137static const struct iio_info apds9306_info_no_events = {1138 .read_avail = apds9306_read_avail,1139 .read_raw = apds9306_read_raw,1140 .write_raw = apds9306_write_raw,1141 .write_raw_get_fmt = apds9306_write_raw_get_fmt,1142};1143 1144static const struct iio_info apds9306_info = {1145 .read_avail = apds9306_read_avail,1146 .read_raw = apds9306_read_raw,1147 .write_raw = apds9306_write_raw,1148 .write_raw_get_fmt = apds9306_write_raw_get_fmt,1149 .read_event_value = apds9306_read_event,1150 .write_event_value = apds9306_write_event,1151 .read_event_config = apds9306_read_event_config,1152 .write_event_config = apds9306_write_event_config,1153 .event_attrs = &apds9306_event_attr_group,1154};1155 1156static int apds9306_init_iio_gts(struct apds9306_data *data)1157{1158 int i, ret, part_id;1159 1160 ret = regmap_read(data->regmap, APDS9306_PART_ID_REG, &part_id);1161 if (ret)1162 return ret;1163 1164 for (i = 0; i < ARRAY_SIZE(apds9306_gts_mul); i++)1165 if (part_id == apds9306_gts_mul[i].part_id)1166 break;1167 1168 if (i == ARRAY_SIZE(apds9306_gts_mul))1169 return -ENOENT;1170 1171 return devm_iio_init_iio_gts(data->dev,1172 apds9306_gts_mul[i].max_scale_int,1173 apds9306_gts_mul[i].max_scale_nano,1174 apds9306_gains, ARRAY_SIZE(apds9306_gains),1175 apds9306_itimes, ARRAY_SIZE(apds9306_itimes),1176 &data->gts);1177}1178 1179static void apds9306_powerdown(void *ptr)1180{1181 struct apds9306_data *data = (struct apds9306_data *)ptr;1182 struct apds9306_regfields *rf = &data->rf;1183 int ret;1184 1185 ret = regmap_field_write(rf->int_thresh_var_en, 0);1186 if (ret)1187 return;1188 1189 ret = regmap_field_write(rf->int_en, 0);1190 if (ret)1191 return;1192 1193 apds9306_power_state(data, false);1194}1195 1196static int apds9306_device_init(struct apds9306_data *data)1197{1198 struct apds9306_regfields *rf = &data->rf;1199 int ret;1200 1201 ret = apds9306_init_iio_gts(data);1202 if (ret)1203 return ret;1204 1205 ret = regmap_field_write(rf->intg_time, APDS9306_MEAS_MODE_100MS);1206 if (ret)1207 return ret;1208 1209 ret = regmap_field_write(rf->repeat_rate, APDS9306_SAMP_FREQ_10HZ);1210 if (ret)1211 return ret;1212 1213 ret = regmap_field_write(rf->gain, APDS9306_GSEL_3X);1214 if (ret)1215 return ret;1216 1217 ret = regmap_field_write(rf->int_src, APDS9306_INT_SRC_ALS);1218 if (ret)1219 return ret;1220 1221 ret = regmap_field_write(rf->int_en, 0);1222 if (ret)1223 return ret;1224 1225 return regmap_field_write(rf->int_thresh_var_en, 0);1226}1227 1228static int apds9306_pm_init(struct apds9306_data *data)1229{1230 struct device *dev = data->dev;1231 int ret;1232 1233 ret = apds9306_power_state(data, true);1234 if (ret)1235 return ret;1236 1237 ret = pm_runtime_set_active(dev);1238 if (ret)1239 return ret;1240 1241 ret = devm_pm_runtime_enable(dev);1242 if (ret)1243 return ret;1244 1245 pm_runtime_set_autosuspend_delay(dev, 5000);1246 pm_runtime_use_autosuspend(dev);1247 pm_runtime_get(dev);1248 1249 return 0;1250}1251 1252static int apds9306_probe(struct i2c_client *client)1253{1254 struct device *dev = &client->dev;1255 struct apds9306_data *data;1256 struct iio_dev *indio_dev;1257 int ret;1258 1259 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));1260 if (!indio_dev)1261 return -ENOMEM;1262 1263 data = iio_priv(indio_dev);1264 1265 mutex_init(&data->mutex);1266 1267 data->regmap = devm_regmap_init_i2c(client, &apds9306_regmap);1268 if (IS_ERR(data->regmap))1269 return dev_err_probe(dev, PTR_ERR(data->regmap),1270 "regmap initialization failed\n");1271 1272 data->dev = dev;1273 i2c_set_clientdata(client, indio_dev);1274 1275 ret = apds9306_regfield_init(data);1276 if (ret)1277 return dev_err_probe(dev, ret, "regfield initialization failed\n");1278 1279 ret = devm_regulator_get_enable(dev, "vdd");1280 if (ret)1281 return dev_err_probe(dev, ret, "Failed to enable regulator\n");1282 1283 indio_dev->name = "apds9306";1284 indio_dev->modes = INDIO_DIRECT_MODE;1285 if (client->irq) {1286 indio_dev->info = &apds9306_info;1287 indio_dev->channels = apds9306_channels_with_events;1288 indio_dev->num_channels = ARRAY_SIZE(apds9306_channels_with_events);1289 ret = devm_request_threaded_irq(dev, client->irq, NULL,1290 apds9306_irq_handler, IRQF_ONESHOT,1291 "apds9306_event", indio_dev);1292 if (ret)1293 return dev_err_probe(dev, ret,1294 "failed to assign interrupt.\n");1295 } else {1296 indio_dev->info = &apds9306_info_no_events;1297 indio_dev->channels = apds9306_channels_without_events;1298 indio_dev->num_channels =1299 ARRAY_SIZE(apds9306_channels_without_events);1300 }1301 1302 ret = apds9306_pm_init(data);1303 if (ret)1304 return dev_err_probe(dev, ret, "failed pm init\n");1305 1306 ret = apds9306_device_init(data);1307 if (ret)1308 return dev_err_probe(dev, ret, "failed to init device\n");1309 1310 ret = devm_add_action_or_reset(dev, apds9306_powerdown, data);1311 if (ret)1312 return dev_err_probe(dev, ret, "failed to add action or reset\n");1313 1314 ret = devm_iio_device_register(dev, indio_dev);1315 if (ret)1316 return dev_err_probe(dev, ret, "failed iio device registration\n");1317 1318 pm_runtime_put_autosuspend(dev);1319 1320 return 0;1321}1322 1323static int apds9306_runtime_suspend(struct device *dev)1324{1325 struct apds9306_data *data = iio_priv(dev_get_drvdata(dev));1326 1327 return apds9306_power_state(data, false);1328}1329 1330static int apds9306_runtime_resume(struct device *dev)1331{1332 struct apds9306_data *data = iio_priv(dev_get_drvdata(dev));1333 1334 return apds9306_power_state(data, true);1335}1336 1337static DEFINE_RUNTIME_DEV_PM_OPS(apds9306_pm_ops,1338 apds9306_runtime_suspend,1339 apds9306_runtime_resume,1340 NULL);1341 1342static const struct of_device_id apds9306_of_match[] = {1343 { .compatible = "avago,apds9306" },1344 { }1345};1346MODULE_DEVICE_TABLE(of, apds9306_of_match);1347 1348static struct i2c_driver apds9306_driver = {1349 .driver = {1350 .name = "apds9306",1351 .pm = pm_ptr(&apds9306_pm_ops),1352 .of_match_table = apds9306_of_match,1353 },1354 .probe = apds9306_probe,1355};1356module_i2c_driver(apds9306_driver);1357 1358MODULE_AUTHOR("Subhajit Ghosh <subhajit.ghosh@tweaklogic.com>");1359MODULE_DESCRIPTION("APDS9306 Ambient Light Sensor driver");1360MODULE_LICENSE("GPL");1361MODULE_IMPORT_NS(IIO_GTS_HELPER);1362