Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * VEML6030 Ambient Light Sensor
0004  *
0005  * Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
0006  *
0007  * Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
0008  * Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/i2c.h>
0013 #include <linux/err.h>
0014 #include <linux/regmap.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/iio/iio.h>
0018 #include <linux/iio/sysfs.h>
0019 #include <linux/iio/events.h>
0020 
0021 /* Device registers */
0022 #define VEML6030_REG_ALS_CONF   0x00
0023 #define VEML6030_REG_ALS_WH     0x01
0024 #define VEML6030_REG_ALS_WL     0x02
0025 #define VEML6030_REG_ALS_PSM    0x03
0026 #define VEML6030_REG_ALS_DATA   0x04
0027 #define VEML6030_REG_WH_DATA    0x05
0028 #define VEML6030_REG_ALS_INT    0x06
0029 
0030 /* Bit masks for specific functionality */
0031 #define VEML6030_ALS_IT       GENMASK(9, 6)
0032 #define VEML6030_PSM          GENMASK(2, 1)
0033 #define VEML6030_ALS_PERS     GENMASK(5, 4)
0034 #define VEML6030_ALS_GAIN     GENMASK(12, 11)
0035 #define VEML6030_PSM_EN       BIT(0)
0036 #define VEML6030_INT_TH_LOW   BIT(15)
0037 #define VEML6030_INT_TH_HIGH  BIT(14)
0038 #define VEML6030_ALS_INT_EN   BIT(1)
0039 #define VEML6030_ALS_SD       BIT(0)
0040 
0041 /*
0042  * The resolution depends on both gain and integration time. The
0043  * cur_resolution stores one of the resolution mentioned in the
0044  * table during startup and gets updated whenever integration time
0045  * or gain is changed.
0046  *
0047  * Table 'resolution and maximum detection range' in appnote 84367
0048  * is visualized as a 2D array. The cur_gain stores index of gain
0049  * in this table (0-3) while the cur_integration_time holds index
0050  * of integration time (0-5).
0051  */
0052 struct veml6030_data {
0053     struct i2c_client *client;
0054     struct regmap *regmap;
0055     int cur_resolution;
0056     int cur_gain;
0057     int cur_integration_time;
0058 };
0059 
0060 /* Integration time available in seconds */
0061 static IIO_CONST_ATTR(in_illuminance_integration_time_available,
0062                 "0.025 0.05 0.1 0.2 0.4 0.8");
0063 
0064 /*
0065  * Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
0066  * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
0067  */
0068 static IIO_CONST_ATTR(in_illuminance_scale_available,
0069                 "0.125 0.25 1.0 2.0");
0070 
0071 static struct attribute *veml6030_attributes[] = {
0072     &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
0073     &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
0074     NULL
0075 };
0076 
0077 static const struct attribute_group veml6030_attr_group = {
0078     .attrs = veml6030_attributes,
0079 };
0080 
0081 /*
0082  * Persistence = 1/2/4/8 x integration time
0083  * Minimum time for which light readings must stay above configured
0084  * threshold to assert the interrupt.
0085  */
0086 static const char * const period_values[] = {
0087         "0.1 0.2 0.4 0.8",
0088         "0.2 0.4 0.8 1.6",
0089         "0.4 0.8 1.6 3.2",
0090         "0.8 1.6 3.2 6.4",
0091         "0.05 0.1 0.2 0.4",
0092         "0.025 0.050 0.1 0.2"
0093 };
0094 
0095 /*
0096  * Return list of valid period values in seconds corresponding to
0097  * the currently active integration time.
0098  */
0099 static ssize_t in_illuminance_period_available_show(struct device *dev,
0100                 struct device_attribute *attr, char *buf)
0101 {
0102     int ret, reg, x;
0103     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0104     struct veml6030_data *data = iio_priv(indio_dev);
0105 
0106     ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
0107     if (ret) {
0108         dev_err(&data->client->dev,
0109                 "can't read als conf register %d\n", ret);
0110         return ret;
0111     }
0112 
0113     ret = ((reg >> 6) & 0xF);
0114     switch (ret) {
0115     case 0:
0116     case 1:
0117     case 2:
0118     case 3:
0119         x = ret;
0120         break;
0121     case 8:
0122         x = 4;
0123         break;
0124     case 12:
0125         x = 5;
0126         break;
0127     default:
0128         return -EINVAL;
0129     }
0130 
0131     return sysfs_emit(buf, "%s\n", period_values[x]);
0132 }
0133 
0134 static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0);
0135 
0136 static struct attribute *veml6030_event_attributes[] = {
0137     &iio_dev_attr_in_illuminance_period_available.dev_attr.attr,
0138     NULL
0139 };
0140 
0141 static const struct attribute_group veml6030_event_attr_group = {
0142     .attrs = veml6030_event_attributes,
0143 };
0144 
0145 static int veml6030_als_pwr_on(struct veml6030_data *data)
0146 {
0147     return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0148                  VEML6030_ALS_SD, 0);
0149 }
0150 
0151 static int veml6030_als_shut_down(struct veml6030_data *data)
0152 {
0153     return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0154                  VEML6030_ALS_SD, 1);
0155 }
0156 
0157 static void veml6030_als_shut_down_action(void *data)
0158 {
0159     veml6030_als_shut_down(data);
0160 }
0161 
0162 static const struct iio_event_spec veml6030_event_spec[] = {
0163     {
0164         .type = IIO_EV_TYPE_THRESH,
0165         .dir = IIO_EV_DIR_RISING,
0166         .mask_separate = BIT(IIO_EV_INFO_VALUE),
0167     }, {
0168         .type = IIO_EV_TYPE_THRESH,
0169         .dir = IIO_EV_DIR_FALLING,
0170         .mask_separate = BIT(IIO_EV_INFO_VALUE),
0171     }, {
0172         .type = IIO_EV_TYPE_THRESH,
0173         .dir = IIO_EV_DIR_EITHER,
0174         .mask_separate = BIT(IIO_EV_INFO_PERIOD) |
0175         BIT(IIO_EV_INFO_ENABLE),
0176     },
0177 };
0178 
0179 /* Channel number */
0180 enum veml6030_chan {
0181     CH_ALS,
0182     CH_WHITE,
0183 };
0184 
0185 static const struct iio_chan_spec veml6030_channels[] = {
0186     {
0187         .type = IIO_LIGHT,
0188         .channel = CH_ALS,
0189         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0190                 BIT(IIO_CHAN_INFO_PROCESSED) |
0191                 BIT(IIO_CHAN_INFO_INT_TIME) |
0192                 BIT(IIO_CHAN_INFO_SCALE),
0193         .event_spec = veml6030_event_spec,
0194         .num_event_specs = ARRAY_SIZE(veml6030_event_spec),
0195     },
0196     {
0197         .type = IIO_INTENSITY,
0198         .channel = CH_WHITE,
0199         .modified = 1,
0200         .channel2 = IIO_MOD_LIGHT_BOTH,
0201         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0202                 BIT(IIO_CHAN_INFO_PROCESSED),
0203     },
0204 };
0205 
0206 static const struct regmap_config veml6030_regmap_config = {
0207     .name = "veml6030_regmap",
0208     .reg_bits = 8,
0209     .val_bits = 16,
0210     .max_register = VEML6030_REG_ALS_INT,
0211     .val_format_endian = REGMAP_ENDIAN_LITTLE,
0212 };
0213 
0214 static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev,
0215                         int *val, int *val2)
0216 {
0217     int ret, reg;
0218     struct veml6030_data *data = iio_priv(indio_dev);
0219 
0220     ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
0221     if (ret) {
0222         dev_err(&data->client->dev,
0223                 "can't read als conf register %d\n", ret);
0224         return ret;
0225     }
0226 
0227     switch ((reg >> 6) & 0xF) {
0228     case 0:
0229         *val2 = 100000;
0230         break;
0231     case 1:
0232         *val2 = 200000;
0233         break;
0234     case 2:
0235         *val2 = 400000;
0236         break;
0237     case 3:
0238         *val2 = 800000;
0239         break;
0240     case 8:
0241         *val2 = 50000;
0242         break;
0243     case 12:
0244         *val2 = 25000;
0245         break;
0246     default:
0247         return -EINVAL;
0248     }
0249 
0250     *val = 0;
0251     return IIO_VAL_INT_PLUS_MICRO;
0252 }
0253 
0254 static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev,
0255                         int val, int val2)
0256 {
0257     int ret, new_int_time, int_idx;
0258     struct veml6030_data *data = iio_priv(indio_dev);
0259 
0260     if (val)
0261         return -EINVAL;
0262 
0263     switch (val2) {
0264     case 25000:
0265         new_int_time = 0x300;
0266         int_idx = 5;
0267         break;
0268     case 50000:
0269         new_int_time = 0x200;
0270         int_idx = 4;
0271         break;
0272     case 100000:
0273         new_int_time = 0x00;
0274         int_idx = 3;
0275         break;
0276     case 200000:
0277         new_int_time = 0x40;
0278         int_idx = 2;
0279         break;
0280     case 400000:
0281         new_int_time = 0x80;
0282         int_idx = 1;
0283         break;
0284     case 800000:
0285         new_int_time = 0xC0;
0286         int_idx = 0;
0287         break;
0288     default:
0289         return -EINVAL;
0290     }
0291 
0292     ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0293                     VEML6030_ALS_IT, new_int_time);
0294     if (ret) {
0295         dev_err(&data->client->dev,
0296                 "can't update als integration time %d\n", ret);
0297         return ret;
0298     }
0299 
0300     /*
0301      * Cache current integration time and update resolution. For every
0302      * increase in integration time to next level, resolution is halved
0303      * and vice-versa.
0304      */
0305     if (data->cur_integration_time < int_idx)
0306         data->cur_resolution <<= int_idx - data->cur_integration_time;
0307     else if (data->cur_integration_time > int_idx)
0308         data->cur_resolution >>= data->cur_integration_time - int_idx;
0309 
0310     data->cur_integration_time = int_idx;
0311 
0312     return ret;
0313 }
0314 
0315 static int veml6030_read_persistence(struct iio_dev *indio_dev,
0316                         int *val, int *val2)
0317 {
0318     int ret, reg, period, x, y;
0319     struct veml6030_data *data = iio_priv(indio_dev);
0320 
0321     ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
0322     if (ret < 0)
0323         return ret;
0324 
0325     ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
0326     if (ret) {
0327         dev_err(&data->client->dev,
0328                 "can't read als conf register %d\n", ret);
0329     }
0330 
0331     /* integration time multiplied by 1/2/4/8 */
0332     period = y * (1 << ((reg >> 4) & 0x03));
0333 
0334     *val = period / 1000000;
0335     *val2 = period % 1000000;
0336 
0337     return IIO_VAL_INT_PLUS_MICRO;
0338 }
0339 
0340 static int veml6030_write_persistence(struct iio_dev *indio_dev,
0341                         int val, int val2)
0342 {
0343     int ret, period, x, y;
0344     struct veml6030_data *data = iio_priv(indio_dev);
0345 
0346     ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
0347     if (ret < 0)
0348         return ret;
0349 
0350     if (!val) {
0351         period = val2 / y;
0352     } else {
0353         if ((val == 1) && (val2 == 600000))
0354             period = 1600000 / y;
0355         else if ((val == 3) && (val2 == 200000))
0356             period = 3200000 / y;
0357         else if ((val == 6) && (val2 == 400000))
0358             period = 6400000 / y;
0359         else
0360             period = -1;
0361     }
0362 
0363     if (period <= 0 || period > 8 || hweight8(period) != 1)
0364         return -EINVAL;
0365 
0366     ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0367                 VEML6030_ALS_PERS, (ffs(period) - 1) << 4);
0368     if (ret)
0369         dev_err(&data->client->dev,
0370                 "can't set persistence value %d\n", ret);
0371 
0372     return ret;
0373 }
0374 
0375 static int veml6030_set_als_gain(struct iio_dev *indio_dev,
0376                         int val, int val2)
0377 {
0378     int ret, new_gain, gain_idx;
0379     struct veml6030_data *data = iio_priv(indio_dev);
0380 
0381     if (val == 0 && val2 == 125000) {
0382         new_gain = 0x1000; /* 0x02 << 11 */
0383         gain_idx = 3;
0384     } else if (val == 0 && val2 == 250000) {
0385         new_gain = 0x1800;
0386         gain_idx = 2;
0387     } else if (val == 1 && val2 == 0) {
0388         new_gain = 0x00;
0389         gain_idx = 1;
0390     } else if (val == 2 && val2 == 0) {
0391         new_gain = 0x800;
0392         gain_idx = 0;
0393     } else {
0394         return -EINVAL;
0395     }
0396 
0397     ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0398                     VEML6030_ALS_GAIN, new_gain);
0399     if (ret) {
0400         dev_err(&data->client->dev,
0401                 "can't set als gain %d\n", ret);
0402         return ret;
0403     }
0404 
0405     /*
0406      * Cache currently set gain & update resolution. For every
0407      * increase in the gain to next level, resolution is halved
0408      * and vice-versa.
0409      */
0410     if (data->cur_gain < gain_idx)
0411         data->cur_resolution <<= gain_idx - data->cur_gain;
0412     else if (data->cur_gain > gain_idx)
0413         data->cur_resolution >>= data->cur_gain - gain_idx;
0414 
0415     data->cur_gain = gain_idx;
0416 
0417     return ret;
0418 }
0419 
0420 static int veml6030_get_als_gain(struct iio_dev *indio_dev,
0421                         int *val, int *val2)
0422 {
0423     int ret, reg;
0424     struct veml6030_data *data = iio_priv(indio_dev);
0425 
0426     ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
0427     if (ret) {
0428         dev_err(&data->client->dev,
0429                 "can't read als conf register %d\n", ret);
0430         return ret;
0431     }
0432 
0433     switch ((reg >> 11) & 0x03) {
0434     case 0:
0435         *val = 1;
0436         *val2 = 0;
0437         break;
0438     case 1:
0439         *val = 2;
0440         *val2 = 0;
0441         break;
0442     case 2:
0443         *val = 0;
0444         *val2 = 125000;
0445         break;
0446     case 3:
0447         *val = 0;
0448         *val2 = 250000;
0449         break;
0450     default:
0451         return -EINVAL;
0452     }
0453 
0454     return IIO_VAL_INT_PLUS_MICRO;
0455 }
0456 
0457 static int veml6030_read_thresh(struct iio_dev *indio_dev,
0458                         int *val, int *val2, int dir)
0459 {
0460     int ret, reg;
0461     struct veml6030_data *data = iio_priv(indio_dev);
0462 
0463     if (dir == IIO_EV_DIR_RISING)
0464         ret = regmap_read(data->regmap, VEML6030_REG_ALS_WH, &reg);
0465     else
0466         ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, &reg);
0467     if (ret) {
0468         dev_err(&data->client->dev,
0469                 "can't read als threshold value %d\n", ret);
0470         return ret;
0471     }
0472 
0473     *val = reg & 0xffff;
0474     return IIO_VAL_INT;
0475 }
0476 
0477 static int veml6030_write_thresh(struct iio_dev *indio_dev,
0478                         int val, int val2, int dir)
0479 {
0480     int ret;
0481     struct veml6030_data *data = iio_priv(indio_dev);
0482 
0483     if (val > 0xFFFF || val < 0 || val2)
0484         return -EINVAL;
0485 
0486     if (dir == IIO_EV_DIR_RISING) {
0487         ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, val);
0488         if (ret)
0489             dev_err(&data->client->dev,
0490                     "can't set high threshold %d\n", ret);
0491     } else {
0492         ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, val);
0493         if (ret)
0494             dev_err(&data->client->dev,
0495                     "can't set low threshold %d\n", ret);
0496     }
0497 
0498     return ret;
0499 }
0500 
0501 /*
0502  * Provide both raw as well as light reading in lux.
0503  * light (in lux) = resolution * raw reading
0504  */
0505 static int veml6030_read_raw(struct iio_dev *indio_dev,
0506                 struct iio_chan_spec const *chan, int *val,
0507                 int *val2, long mask)
0508 {
0509     int ret, reg;
0510     struct veml6030_data *data = iio_priv(indio_dev);
0511     struct regmap *regmap = data->regmap;
0512     struct device *dev = &data->client->dev;
0513 
0514     switch (mask) {
0515     case IIO_CHAN_INFO_RAW:
0516     case IIO_CHAN_INFO_PROCESSED:
0517         switch (chan->type) {
0518         case IIO_LIGHT:
0519             ret = regmap_read(regmap, VEML6030_REG_ALS_DATA, &reg);
0520             if (ret < 0) {
0521                 dev_err(dev, "can't read als data %d\n", ret);
0522                 return ret;
0523             }
0524             if (mask == IIO_CHAN_INFO_PROCESSED) {
0525                 *val = (reg * data->cur_resolution) / 10000;
0526                 *val2 = (reg * data->cur_resolution) % 10000;
0527                 return IIO_VAL_INT_PLUS_MICRO;
0528             }
0529             *val = reg;
0530             return IIO_VAL_INT;
0531         case IIO_INTENSITY:
0532             ret = regmap_read(regmap, VEML6030_REG_WH_DATA, &reg);
0533             if (ret < 0) {
0534                 dev_err(dev, "can't read white data %d\n", ret);
0535                 return ret;
0536             }
0537             if (mask == IIO_CHAN_INFO_PROCESSED) {
0538                 *val = (reg * data->cur_resolution) / 10000;
0539                 *val2 = (reg * data->cur_resolution) % 10000;
0540                 return IIO_VAL_INT_PLUS_MICRO;
0541             }
0542             *val = reg;
0543             return IIO_VAL_INT;
0544         default:
0545             return -EINVAL;
0546         }
0547     case IIO_CHAN_INFO_INT_TIME:
0548         if (chan->type == IIO_LIGHT)
0549             return veml6030_get_intgrn_tm(indio_dev, val, val2);
0550         return -EINVAL;
0551     case IIO_CHAN_INFO_SCALE:
0552         if (chan->type == IIO_LIGHT)
0553             return veml6030_get_als_gain(indio_dev, val, val2);
0554         return -EINVAL;
0555     default:
0556         return -EINVAL;
0557     }
0558 }
0559 
0560 static int veml6030_write_raw(struct iio_dev *indio_dev,
0561                 struct iio_chan_spec const *chan,
0562                 int val, int val2, long mask)
0563 {
0564     switch (mask) {
0565     case IIO_CHAN_INFO_INT_TIME:
0566         switch (chan->type) {
0567         case IIO_LIGHT:
0568             return veml6030_set_intgrn_tm(indio_dev, val, val2);
0569         default:
0570             return -EINVAL;
0571         }
0572     case IIO_CHAN_INFO_SCALE:
0573         switch (chan->type) {
0574         case IIO_LIGHT:
0575             return veml6030_set_als_gain(indio_dev, val, val2);
0576         default:
0577             return -EINVAL;
0578         }
0579     default:
0580         return -EINVAL;
0581     }
0582 }
0583 
0584 static int veml6030_read_event_val(struct iio_dev *indio_dev,
0585         const struct iio_chan_spec *chan, enum iio_event_type type,
0586         enum iio_event_direction dir, enum iio_event_info info,
0587         int *val, int *val2)
0588 {
0589     switch (info) {
0590     case IIO_EV_INFO_VALUE:
0591         switch (dir) {
0592         case IIO_EV_DIR_RISING:
0593         case IIO_EV_DIR_FALLING:
0594             return veml6030_read_thresh(indio_dev, val, val2, dir);
0595         default:
0596             return -EINVAL;
0597         }
0598         break;
0599     case IIO_EV_INFO_PERIOD:
0600         return veml6030_read_persistence(indio_dev, val, val2);
0601     default:
0602         return -EINVAL;
0603     }
0604 }
0605 
0606 static int veml6030_write_event_val(struct iio_dev *indio_dev,
0607         const struct iio_chan_spec *chan, enum iio_event_type type,
0608         enum iio_event_direction dir, enum iio_event_info info,
0609         int val, int val2)
0610 {
0611     switch (info) {
0612     case IIO_EV_INFO_VALUE:
0613         return veml6030_write_thresh(indio_dev, val, val2, dir);
0614     case IIO_EV_INFO_PERIOD:
0615         return veml6030_write_persistence(indio_dev, val, val2);
0616     default:
0617         return -EINVAL;
0618     }
0619 }
0620 
0621 static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
0622         const struct iio_chan_spec *chan, enum iio_event_type type,
0623         enum iio_event_direction dir)
0624 {
0625     int ret, reg;
0626     struct veml6030_data *data = iio_priv(indio_dev);
0627 
0628     ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
0629     if (ret) {
0630         dev_err(&data->client->dev,
0631                 "can't read als conf register %d\n", ret);
0632         return ret;
0633     }
0634 
0635     if (reg & VEML6030_ALS_INT_EN)
0636         return 1;
0637     else
0638         return 0;
0639 }
0640 
0641 /*
0642  * Sensor should not be measuring light when interrupt is configured.
0643  * Therefore correct sequence to configure interrupt functionality is:
0644  * shut down -> enable/disable interrupt -> power on
0645  *
0646  * state = 1 enables interrupt, state = 0 disables interrupt
0647  */
0648 static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
0649         const struct iio_chan_spec *chan, enum iio_event_type type,
0650         enum iio_event_direction dir, int state)
0651 {
0652     int ret;
0653     struct veml6030_data *data = iio_priv(indio_dev);
0654 
0655     if (state < 0 || state > 1)
0656         return -EINVAL;
0657 
0658     ret = veml6030_als_shut_down(data);
0659     if (ret < 0) {
0660         dev_err(&data->client->dev,
0661             "can't disable als to configure interrupt %d\n", ret);
0662         return ret;
0663     }
0664 
0665     /* enable interrupt + power on */
0666     ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
0667             VEML6030_ALS_INT_EN | VEML6030_ALS_SD, state << 1);
0668     if (ret)
0669         dev_err(&data->client->dev,
0670             "can't enable interrupt & poweron als %d\n", ret);
0671 
0672     return ret;
0673 }
0674 
0675 static const struct iio_info veml6030_info = {
0676     .read_raw  = veml6030_read_raw,
0677     .write_raw = veml6030_write_raw,
0678     .read_event_value = veml6030_read_event_val,
0679     .write_event_value  = veml6030_write_event_val,
0680     .read_event_config = veml6030_read_interrupt_config,
0681     .write_event_config = veml6030_write_interrupt_config,
0682     .attrs = &veml6030_attr_group,
0683     .event_attrs = &veml6030_event_attr_group,
0684 };
0685 
0686 static const struct iio_info veml6030_info_no_irq = {
0687     .read_raw  = veml6030_read_raw,
0688     .write_raw = veml6030_write_raw,
0689     .attrs = &veml6030_attr_group,
0690 };
0691 
0692 static irqreturn_t veml6030_event_handler(int irq, void *private)
0693 {
0694     int ret, reg, evtdir;
0695     struct iio_dev *indio_dev = private;
0696     struct veml6030_data *data = iio_priv(indio_dev);
0697 
0698     ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &reg);
0699     if (ret) {
0700         dev_err(&data->client->dev,
0701                 "can't read als interrupt register %d\n", ret);
0702         return IRQ_HANDLED;
0703     }
0704 
0705     /* Spurious interrupt handling */
0706     if (!(reg & (VEML6030_INT_TH_HIGH | VEML6030_INT_TH_LOW)))
0707         return IRQ_NONE;
0708 
0709     if (reg & VEML6030_INT_TH_HIGH)
0710         evtdir = IIO_EV_DIR_RISING;
0711     else
0712         evtdir = IIO_EV_DIR_FALLING;
0713 
0714     iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY,
0715                     0, IIO_EV_TYPE_THRESH, evtdir),
0716                     iio_get_time_ns(indio_dev));
0717 
0718     return IRQ_HANDLED;
0719 }
0720 
0721 /*
0722  * Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
0723  * persistence to 1 x integration time and the threshold
0724  * interrupt disabled by default. First shutdown the sensor,
0725  * update registers and then power on the sensor.
0726  */
0727 static int veml6030_hw_init(struct iio_dev *indio_dev)
0728 {
0729     int ret, val;
0730     struct veml6030_data *data = iio_priv(indio_dev);
0731     struct i2c_client *client = data->client;
0732 
0733     ret = veml6030_als_shut_down(data);
0734     if (ret) {
0735         dev_err(&client->dev, "can't shutdown als %d\n", ret);
0736         return ret;
0737     }
0738 
0739     ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
0740     if (ret) {
0741         dev_err(&client->dev, "can't setup als configs %d\n", ret);
0742         return ret;
0743     }
0744 
0745     ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
0746                  VEML6030_PSM | VEML6030_PSM_EN, 0x03);
0747     if (ret) {
0748         dev_err(&client->dev, "can't setup default PSM %d\n", ret);
0749         return ret;
0750     }
0751 
0752     ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
0753     if (ret) {
0754         dev_err(&client->dev, "can't setup high threshold %d\n", ret);
0755         return ret;
0756     }
0757 
0758     ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
0759     if (ret) {
0760         dev_err(&client->dev, "can't setup low threshold %d\n", ret);
0761         return ret;
0762     }
0763 
0764     ret = veml6030_als_pwr_on(data);
0765     if (ret) {
0766         dev_err(&client->dev, "can't poweron als %d\n", ret);
0767         return ret;
0768     }
0769 
0770     /* Wait 4 ms to let processor & oscillator start correctly */
0771     usleep_range(4000, 4002);
0772 
0773     /* Clear stale interrupt status bits if any during start */
0774     ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
0775     if (ret < 0) {
0776         dev_err(&client->dev,
0777             "can't clear als interrupt status %d\n", ret);
0778         return ret;
0779     }
0780 
0781     /* Cache currently active measurement parameters */
0782     data->cur_gain = 3;
0783     data->cur_resolution = 4608;
0784     data->cur_integration_time = 3;
0785 
0786     return ret;
0787 }
0788 
0789 static int veml6030_probe(struct i2c_client *client,
0790               const struct i2c_device_id *id)
0791 {
0792     int ret;
0793     struct veml6030_data *data;
0794     struct iio_dev *indio_dev;
0795     struct regmap *regmap;
0796 
0797     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0798         dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
0799         return -EOPNOTSUPP;
0800     }
0801 
0802     regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
0803     if (IS_ERR(regmap)) {
0804         dev_err(&client->dev, "can't setup regmap\n");
0805         return PTR_ERR(regmap);
0806     }
0807 
0808     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0809     if (!indio_dev)
0810         return -ENOMEM;
0811 
0812     data = iio_priv(indio_dev);
0813     i2c_set_clientdata(client, indio_dev);
0814     data->client = client;
0815     data->regmap = regmap;
0816 
0817     indio_dev->name = "veml6030";
0818     indio_dev->channels = veml6030_channels;
0819     indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
0820     indio_dev->modes = INDIO_DIRECT_MODE;
0821 
0822     if (client->irq) {
0823         ret = devm_request_threaded_irq(&client->dev, client->irq,
0824                         NULL, veml6030_event_handler,
0825                         IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0826                         "veml6030", indio_dev);
0827         if (ret < 0) {
0828             dev_err(&client->dev,
0829                     "irq %d request failed\n", client->irq);
0830             return ret;
0831         }
0832         indio_dev->info = &veml6030_info;
0833     } else {
0834         indio_dev->info = &veml6030_info_no_irq;
0835     }
0836 
0837     ret = veml6030_hw_init(indio_dev);
0838     if (ret < 0)
0839         return ret;
0840 
0841     ret = devm_add_action_or_reset(&client->dev,
0842                     veml6030_als_shut_down_action, data);
0843     if (ret < 0)
0844         return ret;
0845 
0846     return devm_iio_device_register(&client->dev, indio_dev);
0847 }
0848 
0849 static int veml6030_runtime_suspend(struct device *dev)
0850 {
0851     int ret;
0852     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0853     struct veml6030_data *data = iio_priv(indio_dev);
0854 
0855     ret = veml6030_als_shut_down(data);
0856     if (ret < 0)
0857         dev_err(&data->client->dev, "can't suspend als %d\n", ret);
0858 
0859     return ret;
0860 }
0861 
0862 static int veml6030_runtime_resume(struct device *dev)
0863 {
0864     int ret;
0865     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0866     struct veml6030_data *data = iio_priv(indio_dev);
0867 
0868     ret = veml6030_als_pwr_on(data);
0869     if (ret < 0)
0870         dev_err(&data->client->dev, "can't resume als %d\n", ret);
0871 
0872     return ret;
0873 }
0874 
0875 static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,
0876                  veml6030_runtime_resume, NULL);
0877 
0878 static const struct of_device_id veml6030_of_match[] = {
0879     { .compatible = "vishay,veml6030" },
0880     { }
0881 };
0882 MODULE_DEVICE_TABLE(of, veml6030_of_match);
0883 
0884 static const struct i2c_device_id veml6030_id[] = {
0885     { "veml6030", 0 },
0886     { }
0887 };
0888 MODULE_DEVICE_TABLE(i2c, veml6030_id);
0889 
0890 static struct i2c_driver veml6030_driver = {
0891     .driver = {
0892         .name = "veml6030",
0893         .of_match_table = veml6030_of_match,
0894         .pm = pm_ptr(&veml6030_pm_ops),
0895     },
0896     .probe = veml6030_probe,
0897     .id_table = veml6030_id,
0898 };
0899 module_i2c_driver(veml6030_driver);
0900 
0901 MODULE_AUTHOR("Rishi Gupta <gupt21@gmail.com>");
0902 MODULE_DESCRIPTION("VEML6030 Ambient Light Sensor");
0903 MODULE_LICENSE("GPL v2");