Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 Intel Corporation
0004  *
0005  * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor.
0006  *
0007  * To do: Interrupt support.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/acpi.h>
0013 #include <linux/delay.h>
0014 #include <linux/i2c.h>
0015 #include <linux/iio/events.h>
0016 #include <linux/iio/iio.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/irq.h>
0019 #include <linux/iio/sysfs.h>
0020 #include <linux/mutex.h>
0021 #include <linux/pm.h>
0022 #include <linux/pm_runtime.h>
0023 
0024 #define US5182D_REG_CFG0                0x00
0025 #define US5182D_CFG0_ONESHOT_EN             BIT(6)
0026 #define US5182D_CFG0_SHUTDOWN_EN            BIT(7)
0027 #define US5182D_CFG0_WORD_ENABLE            BIT(0)
0028 #define US5182D_CFG0_PROX               BIT(3)
0029 #define US5182D_CFG0_PX_IRQ             BIT(2)
0030 
0031 #define US5182D_REG_CFG1                0x01
0032 #define US5182D_CFG1_ALS_RES16              BIT(4)
0033 #define US5182D_CFG1_AGAIN_DEFAULT          0x00
0034 
0035 #define US5182D_REG_CFG2                0x02
0036 #define US5182D_CFG2_PX_RES16               BIT(4)
0037 #define US5182D_CFG2_PXGAIN_DEFAULT         BIT(2)
0038 
0039 #define US5182D_REG_CFG3                0x03
0040 #define US5182D_CFG3_LED_CURRENT100         (BIT(4) | BIT(5))
0041 #define US5182D_CFG3_INT_SOURCE_PX          BIT(3)
0042 
0043 #define US5182D_REG_CFG4                0x10
0044 
0045 /*
0046  * Registers for tuning the auto dark current cancelling feature.
0047  * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling.
0048  * when ALS  > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark
0049  * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark
0050  */
0051 #define US5182D_REG_UDARK_TH            0x27
0052 #define US5182D_REG_DARK_AUTO_EN        0x2b
0053 #define US5182D_REG_AUTO_LDARK_GAIN     0x29
0054 #define US5182D_REG_AUTO_HDARK_GAIN     0x2a
0055 
0056 /* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */
0057 #define US5182D_REG_PXL_TH          0x08
0058 #define US5182D_REG_PXH_TH          0x0a
0059 
0060 #define US5182D_REG_PXL_TH_DEFAULT      1000
0061 #define US5182D_REG_PXH_TH_DEFAULT      30000
0062 
0063 #define US5182D_OPMODE_ALS          0x01
0064 #define US5182D_OPMODE_PX           0x02
0065 #define US5182D_OPMODE_SHIFT            4
0066 
0067 #define US5182D_REG_DARK_AUTO_EN_DEFAULT    0x80
0068 #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT 0x16
0069 #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT 0x00
0070 
0071 #define US5182D_REG_ADL             0x0c
0072 #define US5182D_REG_PDL             0x0e
0073 
0074 #define US5182D_REG_MODE_STORE          0x21
0075 #define US5182D_STORE_MODE          0x01
0076 
0077 #define US5182D_REG_CHIPID          0xb2
0078 
0079 #define US5182D_OPMODE_MASK         GENMASK(5, 4)
0080 #define US5182D_AGAIN_MASK          0x07
0081 #define US5182D_RESET_CHIP          0x01
0082 
0083 #define US5182D_CHIPID              0x26
0084 #define US5182D_DRV_NAME            "us5182d"
0085 
0086 #define US5182D_GA_RESOLUTION           1000
0087 
0088 #define US5182D_READ_BYTE           1
0089 #define US5182D_READ_WORD           2
0090 #define US5182D_OPSTORE_SLEEP_TIME      20 /* ms */
0091 #define US5182D_SLEEP_MS            3000 /* ms */
0092 #define US5182D_PXH_TH_DISABLE          0xffff
0093 #define US5182D_PXL_TH_DISABLE          0x0000
0094 
0095 /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
0096 static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
0097                      3900, 2100};
0098 
0099 /*
0100  * Experimental thresholds that work with US5182D sensor on evaluation board
0101  * roughly between 12-32 lux
0102  */
0103 static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000,
0104                       8000};
0105 
0106 enum mode {
0107     US5182D_ALS_PX,
0108     US5182D_ALS_ONLY,
0109     US5182D_PX_ONLY
0110 };
0111 
0112 enum pmode {
0113     US5182D_CONTINUOUS,
0114     US5182D_ONESHOT
0115 };
0116 
0117 struct us5182d_data {
0118     struct i2c_client *client;
0119     struct mutex lock;
0120 
0121     /* Glass attenuation factor */
0122     u32 ga;
0123 
0124     /* Dark gain tuning */
0125     u8 lower_dark_gain;
0126     u8 upper_dark_gain;
0127     u16 *us5182d_dark_ths;
0128 
0129     u16 px_low_th;
0130     u16 px_high_th;
0131 
0132     int rising_en;
0133     int falling_en;
0134 
0135     u8 opmode;
0136     u8 power_mode;
0137 
0138     bool als_enabled;
0139     bool px_enabled;
0140 
0141     bool default_continuous;
0142 };
0143 
0144 static IIO_CONST_ATTR(in_illuminance_scale_available,
0145               "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885");
0146 
0147 static struct attribute *us5182d_attrs[] = {
0148     &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
0149     NULL
0150 };
0151 
0152 static const struct attribute_group us5182d_attr_group = {
0153     .attrs = us5182d_attrs,
0154 };
0155 
0156 static const struct {
0157     u8 reg;
0158     u8 val;
0159 } us5182d_regvals[] = {
0160     {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE},
0161     {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},
0162     {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |
0163                 US5182D_CFG2_PXGAIN_DEFAULT)},
0164     {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 |
0165                US5182D_CFG3_INT_SOURCE_PX},
0166     {US5182D_REG_CFG4, 0x00},
0167 };
0168 
0169 static const struct iio_event_spec us5182d_events[] = {
0170     {
0171         .type = IIO_EV_TYPE_THRESH,
0172         .dir = IIO_EV_DIR_RISING,
0173         .mask_separate = BIT(IIO_EV_INFO_VALUE) |
0174                 BIT(IIO_EV_INFO_ENABLE),
0175     },
0176     {
0177         .type = IIO_EV_TYPE_THRESH,
0178         .dir = IIO_EV_DIR_FALLING,
0179         .mask_separate = BIT(IIO_EV_INFO_VALUE) |
0180                 BIT(IIO_EV_INFO_ENABLE),
0181     },
0182 };
0183 
0184 static const struct iio_chan_spec us5182d_channels[] = {
0185     {
0186         .type = IIO_LIGHT,
0187         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0188                       BIT(IIO_CHAN_INFO_SCALE),
0189     },
0190     {
0191         .type = IIO_PROXIMITY,
0192         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
0193         .event_spec = us5182d_events,
0194         .num_event_specs = ARRAY_SIZE(us5182d_events),
0195     }
0196 };
0197 
0198 static int us5182d_oneshot_en(struct us5182d_data *data)
0199 {
0200     int ret;
0201 
0202     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
0203     if (ret < 0)
0204         return ret;
0205 
0206     /*
0207      * In oneshot mode the chip will power itself down after taking the
0208      * required measurement.
0209      */
0210     ret = ret | US5182D_CFG0_ONESHOT_EN;
0211 
0212     return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
0213 }
0214 
0215 static int us5182d_set_opmode(struct us5182d_data *data, u8 mode)
0216 {
0217     int ret;
0218 
0219     if (mode == data->opmode)
0220         return 0;
0221 
0222     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
0223     if (ret < 0)
0224         return ret;
0225 
0226     /* update mode */
0227     ret = ret & ~US5182D_OPMODE_MASK;
0228     ret = ret | (mode << US5182D_OPMODE_SHIFT);
0229 
0230     /*
0231      * After updating the operating mode, the chip requires that
0232      * the operation is stored, by writing 1 in the STORE_MODE
0233      * register (auto-clearing).
0234      */
0235     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
0236     if (ret < 0)
0237         return ret;
0238 
0239     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE,
0240                     US5182D_STORE_MODE);
0241     if (ret < 0)
0242         return ret;
0243 
0244     data->opmode = mode;
0245     msleep(US5182D_OPSTORE_SLEEP_TIME);
0246 
0247     return 0;
0248 }
0249 
0250 static int us5182d_als_enable(struct us5182d_data *data)
0251 {
0252     int ret;
0253     u8 mode;
0254 
0255     if (data->power_mode == US5182D_ONESHOT) {
0256         ret = us5182d_set_opmode(data, US5182D_ALS_ONLY);
0257         if (ret < 0)
0258             return ret;
0259         data->px_enabled = false;
0260     }
0261 
0262     if (data->als_enabled)
0263         return 0;
0264 
0265     mode = data->px_enabled ? US5182D_ALS_PX : US5182D_ALS_ONLY;
0266 
0267     ret = us5182d_set_opmode(data, mode);
0268     if (ret < 0)
0269         return ret;
0270 
0271     data->als_enabled = true;
0272 
0273     return 0;
0274 }
0275 
0276 static int us5182d_px_enable(struct us5182d_data *data)
0277 {
0278     int ret;
0279     u8 mode;
0280 
0281     if (data->power_mode == US5182D_ONESHOT) {
0282         ret = us5182d_set_opmode(data, US5182D_PX_ONLY);
0283         if (ret < 0)
0284             return ret;
0285         data->als_enabled = false;
0286     }
0287 
0288     if (data->px_enabled)
0289         return 0;
0290 
0291     mode = data->als_enabled ? US5182D_ALS_PX : US5182D_PX_ONLY;
0292 
0293     ret = us5182d_set_opmode(data, mode);
0294     if (ret < 0)
0295         return ret;
0296 
0297     data->px_enabled = true;
0298 
0299     return 0;
0300 }
0301 
0302 static int us5182d_get_als(struct us5182d_data *data)
0303 {
0304     int ret;
0305     unsigned long result;
0306 
0307     ret = us5182d_als_enable(data);
0308     if (ret < 0)
0309         return ret;
0310 
0311     ret = i2c_smbus_read_word_data(data->client,
0312                        US5182D_REG_ADL);
0313     if (ret < 0)
0314         return ret;
0315 
0316     result = ret * data->ga / US5182D_GA_RESOLUTION;
0317     if (result > 0xffff)
0318         result = 0xffff;
0319 
0320     return result;
0321 }
0322 
0323 static int us5182d_get_px(struct us5182d_data *data)
0324 {
0325     int ret;
0326 
0327     ret = us5182d_px_enable(data);
0328     if (ret < 0)
0329         return ret;
0330 
0331     return i2c_smbus_read_word_data(data->client,
0332                     US5182D_REG_PDL);
0333 }
0334 
0335 static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)
0336 {
0337     int ret;
0338 
0339     if (data->power_mode == US5182D_ONESHOT)
0340         return 0;
0341 
0342     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
0343     if (ret < 0)
0344         return ret;
0345 
0346     ret = ret & ~US5182D_CFG0_SHUTDOWN_EN;
0347     ret = ret | state;
0348 
0349     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
0350     if (ret < 0)
0351         return ret;
0352 
0353     if (state & US5182D_CFG0_SHUTDOWN_EN) {
0354         data->als_enabled = false;
0355         data->px_enabled = false;
0356     }
0357 
0358     return ret;
0359 }
0360 
0361 
0362 static int us5182d_set_power_state(struct us5182d_data *data, bool on)
0363 {
0364     int ret;
0365 
0366     if (data->power_mode == US5182D_ONESHOT)
0367         return 0;
0368 
0369     if (on) {
0370         ret = pm_runtime_resume_and_get(&data->client->dev);
0371     } else {
0372         pm_runtime_mark_last_busy(&data->client->dev);
0373         ret = pm_runtime_put_autosuspend(&data->client->dev);
0374     }
0375 
0376     return ret;
0377 }
0378 
0379 static int us5182d_read_value(struct us5182d_data *data,
0380                   struct iio_chan_spec const *chan)
0381 {
0382     int ret, value;
0383 
0384     mutex_lock(&data->lock);
0385 
0386     if (data->power_mode == US5182D_ONESHOT) {
0387         ret = us5182d_oneshot_en(data);
0388         if (ret < 0)
0389             goto out_err;
0390     }
0391 
0392     ret = us5182d_set_power_state(data, true);
0393     if (ret < 0)
0394         goto out_err;
0395 
0396     if (chan->type == IIO_LIGHT)
0397         ret = us5182d_get_als(data);
0398     else
0399         ret = us5182d_get_px(data);
0400     if (ret < 0)
0401         goto out_poweroff;
0402 
0403     value = ret;
0404 
0405     ret = us5182d_set_power_state(data, false);
0406     if (ret < 0)
0407         goto out_err;
0408 
0409     mutex_unlock(&data->lock);
0410     return value;
0411 
0412 out_poweroff:
0413     us5182d_set_power_state(data, false);
0414 out_err:
0415     mutex_unlock(&data->lock);
0416     return ret;
0417 }
0418 
0419 static int us5182d_read_raw(struct iio_dev *indio_dev,
0420                 struct iio_chan_spec const *chan, int *val,
0421                 int *val2, long mask)
0422 {
0423     struct us5182d_data *data = iio_priv(indio_dev);
0424     int ret;
0425 
0426     switch (mask) {
0427     case IIO_CHAN_INFO_RAW:
0428         ret = us5182d_read_value(data, chan);
0429         if (ret < 0)
0430             return ret;
0431         *val = ret;
0432         return IIO_VAL_INT;
0433     case IIO_CHAN_INFO_SCALE:
0434         ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
0435         if (ret < 0)
0436             return ret;
0437         *val = 0;
0438         *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];
0439         return IIO_VAL_INT_PLUS_MICRO;
0440     default:
0441         return -EINVAL;
0442     }
0443 }
0444 
0445 /**
0446  * us5182d_update_dark_th - update Darh_Th registers
0447  * @data:   us5182d_data structure
0448  * @index:  index in us5182d_dark_ths array to use for the updated value
0449  *
0450  * Function needs to be called with a lock held because it needs two i2c write
0451  * byte operations as these registers (0x27 0x28) don't work in word mode
0452  * accessing.
0453  */
0454 static int us5182d_update_dark_th(struct us5182d_data *data, int index)
0455 {
0456     __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]);
0457     int ret;
0458 
0459     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH,
0460                     ((u8 *)&dark_th)[0]);
0461     if (ret < 0)
0462         return ret;
0463 
0464     return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1,
0465                     ((u8 *)&dark_th)[1]);
0466 }
0467 
0468 /**
0469  * us5182d_apply_scale - update the ALS scale
0470  * @data:   us5182d_data structure
0471  * @index:  index in us5182d_scales array to use for the updated value
0472  *
0473  * Function needs to be called with a lock held as we're having more than one
0474  * i2c operation.
0475  */
0476 static int us5182d_apply_scale(struct us5182d_data *data, int index)
0477 {
0478     int ret;
0479 
0480     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
0481     if (ret < 0)
0482         return ret;
0483 
0484     ret = ret & (~US5182D_AGAIN_MASK);
0485     ret |= index;
0486 
0487     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret);
0488     if (ret < 0)
0489         return ret;
0490 
0491     return us5182d_update_dark_th(data, index);
0492 }
0493 
0494 static int us5182d_write_raw(struct iio_dev *indio_dev,
0495                  struct iio_chan_spec const *chan, int val,
0496                  int val2, long mask)
0497 {
0498     struct us5182d_data *data = iio_priv(indio_dev);
0499     int ret, i;
0500 
0501     switch (mask) {
0502     case IIO_CHAN_INFO_SCALE:
0503         if (val != 0)
0504             return -EINVAL;
0505         for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++)
0506             if (val2 == us5182d_scales[i]) {
0507                 mutex_lock(&data->lock);
0508                 ret = us5182d_apply_scale(data, i);
0509                 mutex_unlock(&data->lock);
0510                 return ret;
0511             }
0512         break;
0513     default:
0514         return -EINVAL;
0515     }
0516 
0517     return -EINVAL;
0518 }
0519 
0520 static int us5182d_setup_prox(struct iio_dev *indio_dev,
0521                   enum iio_event_direction dir, u16 val)
0522 {
0523     struct us5182d_data *data = iio_priv(indio_dev);
0524 
0525     if (dir == IIO_EV_DIR_FALLING)
0526         return i2c_smbus_write_word_data(data->client,
0527                          US5182D_REG_PXL_TH, val);
0528     else if (dir == IIO_EV_DIR_RISING)
0529         return i2c_smbus_write_word_data(data->client,
0530                          US5182D_REG_PXH_TH, val);
0531 
0532     return 0;
0533 }
0534 
0535 static int us5182d_read_thresh(struct iio_dev *indio_dev,
0536     const struct iio_chan_spec *chan, enum iio_event_type type,
0537     enum iio_event_direction dir, enum iio_event_info info, int *val,
0538     int *val2)
0539 {
0540     struct us5182d_data *data = iio_priv(indio_dev);
0541 
0542     switch (dir) {
0543     case IIO_EV_DIR_RISING:
0544         mutex_lock(&data->lock);
0545         *val = data->px_high_th;
0546         mutex_unlock(&data->lock);
0547         break;
0548     case IIO_EV_DIR_FALLING:
0549         mutex_lock(&data->lock);
0550         *val = data->px_low_th;
0551         mutex_unlock(&data->lock);
0552         break;
0553     default:
0554         return -EINVAL;
0555     }
0556 
0557     return IIO_VAL_INT;
0558 }
0559 
0560 static int us5182d_write_thresh(struct iio_dev *indio_dev,
0561     const struct iio_chan_spec *chan, enum iio_event_type type,
0562     enum iio_event_direction dir, enum iio_event_info info, int val,
0563     int val2)
0564 {
0565     struct us5182d_data *data = iio_priv(indio_dev);
0566     int ret;
0567 
0568     if (val < 0 || val > USHRT_MAX || val2 != 0)
0569         return -EINVAL;
0570 
0571     switch (dir) {
0572     case IIO_EV_DIR_RISING:
0573         mutex_lock(&data->lock);
0574         if (data->rising_en) {
0575             ret = us5182d_setup_prox(indio_dev, dir, val);
0576             if (ret < 0)
0577                 goto err;
0578         }
0579         data->px_high_th = val;
0580         mutex_unlock(&data->lock);
0581         break;
0582     case IIO_EV_DIR_FALLING:
0583         mutex_lock(&data->lock);
0584         if (data->falling_en) {
0585             ret = us5182d_setup_prox(indio_dev, dir, val);
0586             if (ret < 0)
0587                 goto err;
0588         }
0589         data->px_low_th = val;
0590         mutex_unlock(&data->lock);
0591         break;
0592     default:
0593         return -EINVAL;
0594     }
0595 
0596     return 0;
0597 err:
0598     mutex_unlock(&data->lock);
0599     return ret;
0600 }
0601 
0602 static int us5182d_read_event_config(struct iio_dev *indio_dev,
0603     const struct iio_chan_spec *chan, enum iio_event_type type,
0604     enum iio_event_direction dir)
0605 {
0606     struct us5182d_data *data = iio_priv(indio_dev);
0607     int ret;
0608 
0609     switch (dir) {
0610     case IIO_EV_DIR_RISING:
0611         mutex_lock(&data->lock);
0612         ret = data->rising_en;
0613         mutex_unlock(&data->lock);
0614         break;
0615     case IIO_EV_DIR_FALLING:
0616         mutex_lock(&data->lock);
0617         ret = data->falling_en;
0618         mutex_unlock(&data->lock);
0619         break;
0620     default:
0621         ret = -EINVAL;
0622         break;
0623     }
0624 
0625     return ret;
0626 }
0627 
0628 static int us5182d_write_event_config(struct iio_dev *indio_dev,
0629     const struct iio_chan_spec *chan, enum iio_event_type type,
0630     enum iio_event_direction dir, int state)
0631 {
0632     struct us5182d_data *data = iio_priv(indio_dev);
0633     int ret;
0634     u16 new_th;
0635 
0636     mutex_lock(&data->lock);
0637 
0638     switch (dir) {
0639     case IIO_EV_DIR_RISING:
0640         if (data->rising_en == state) {
0641             mutex_unlock(&data->lock);
0642             return 0;
0643         }
0644         new_th = US5182D_PXH_TH_DISABLE;
0645         if (state) {
0646             data->power_mode = US5182D_CONTINUOUS;
0647             ret = us5182d_set_power_state(data, true);
0648             if (ret < 0)
0649                 goto err;
0650             ret = us5182d_px_enable(data);
0651             if (ret < 0)
0652                 goto err_poweroff;
0653             new_th = data->px_high_th;
0654         }
0655         ret = us5182d_setup_prox(indio_dev, dir, new_th);
0656         if (ret < 0)
0657             goto err_poweroff;
0658         data->rising_en = state;
0659         break;
0660     case IIO_EV_DIR_FALLING:
0661         if (data->falling_en == state) {
0662             mutex_unlock(&data->lock);
0663             return 0;
0664         }
0665         new_th =  US5182D_PXL_TH_DISABLE;
0666         if (state) {
0667             data->power_mode = US5182D_CONTINUOUS;
0668             ret = us5182d_set_power_state(data, true);
0669             if (ret < 0)
0670                 goto err;
0671             ret = us5182d_px_enable(data);
0672             if (ret < 0)
0673                 goto err_poweroff;
0674             new_th = data->px_low_th;
0675         }
0676         ret = us5182d_setup_prox(indio_dev, dir, new_th);
0677         if (ret < 0)
0678             goto err_poweroff;
0679         data->falling_en = state;
0680         break;
0681     default:
0682         ret = -EINVAL;
0683         goto err;
0684     }
0685 
0686     if (!state) {
0687         ret = us5182d_set_power_state(data, false);
0688         if (ret < 0)
0689             goto err;
0690     }
0691 
0692     if (!data->falling_en && !data->rising_en && !data->default_continuous)
0693         data->power_mode = US5182D_ONESHOT;
0694 
0695     mutex_unlock(&data->lock);
0696     return 0;
0697 
0698 err_poweroff:
0699     if (state)
0700         us5182d_set_power_state(data, false);
0701 err:
0702     mutex_unlock(&data->lock);
0703     return ret;
0704 }
0705 
0706 static const struct iio_info us5182d_info = {
0707     .read_raw = us5182d_read_raw,
0708     .write_raw = us5182d_write_raw,
0709     .attrs = &us5182d_attr_group,
0710     .read_event_value = &us5182d_read_thresh,
0711     .write_event_value = &us5182d_write_thresh,
0712     .read_event_config = &us5182d_read_event_config,
0713     .write_event_config = &us5182d_write_event_config,
0714 };
0715 
0716 static int us5182d_reset(struct iio_dev *indio_dev)
0717 {
0718     struct us5182d_data *data = iio_priv(indio_dev);
0719 
0720     return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3,
0721                      US5182D_RESET_CHIP);
0722 }
0723 
0724 static int us5182d_init(struct iio_dev *indio_dev)
0725 {
0726     struct us5182d_data *data = iio_priv(indio_dev);
0727     int i, ret;
0728 
0729     ret = us5182d_reset(indio_dev);
0730     if (ret < 0)
0731         return ret;
0732 
0733     data->opmode = 0;
0734     data->power_mode = US5182D_CONTINUOUS;
0735     data->px_low_th = US5182D_REG_PXL_TH_DEFAULT;
0736     data->px_high_th = US5182D_REG_PXH_TH_DEFAULT;
0737 
0738     for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {
0739         ret = i2c_smbus_write_byte_data(data->client,
0740                         us5182d_regvals[i].reg,
0741                         us5182d_regvals[i].val);
0742         if (ret < 0)
0743             return ret;
0744     }
0745 
0746     data->als_enabled = true;
0747     data->px_enabled = true;
0748 
0749     if (!data->default_continuous) {
0750         ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
0751         if (ret < 0)
0752             return ret;
0753         data->power_mode = US5182D_ONESHOT;
0754     }
0755 
0756     return ret;
0757 }
0758 
0759 static void us5182d_get_platform_data(struct iio_dev *indio_dev)
0760 {
0761     struct us5182d_data *data = iio_priv(indio_dev);
0762 
0763     if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef",
0764                      &data->ga))
0765         data->ga = US5182D_GA_RESOLUTION;
0766     if (device_property_read_u16_array(&data->client->dev,
0767                        "upisemi,dark-ths",
0768                        data->us5182d_dark_ths,
0769                        ARRAY_SIZE(us5182d_dark_ths_vals)))
0770         data->us5182d_dark_ths = us5182d_dark_ths_vals;
0771     if (device_property_read_u8(&data->client->dev,
0772                     "upisemi,upper-dark-gain",
0773                     &data->upper_dark_gain))
0774         data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT;
0775     if (device_property_read_u8(&data->client->dev,
0776                     "upisemi,lower-dark-gain",
0777                     &data->lower_dark_gain))
0778         data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT;
0779     data->default_continuous = device_property_read_bool(&data->client->dev,
0780                                  "upisemi,continuous");
0781 }
0782 
0783 static int  us5182d_dark_gain_config(struct iio_dev *indio_dev)
0784 {
0785     struct us5182d_data *data = iio_priv(indio_dev);
0786     int ret;
0787 
0788     ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT);
0789     if (ret < 0)
0790         return ret;
0791 
0792     ret = i2c_smbus_write_byte_data(data->client,
0793                     US5182D_REG_AUTO_LDARK_GAIN,
0794                     data->lower_dark_gain);
0795     if (ret < 0)
0796         return ret;
0797 
0798     ret = i2c_smbus_write_byte_data(data->client,
0799                     US5182D_REG_AUTO_HDARK_GAIN,
0800                     data->upper_dark_gain);
0801     if (ret < 0)
0802         return ret;
0803 
0804     return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN,
0805                      US5182D_REG_DARK_AUTO_EN_DEFAULT);
0806 }
0807 
0808 static irqreturn_t us5182d_irq_thread_handler(int irq, void *private)
0809 {
0810     struct iio_dev *indio_dev = private;
0811     struct us5182d_data *data = iio_priv(indio_dev);
0812     enum iio_event_direction dir;
0813     int ret;
0814     u64 ev;
0815 
0816     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
0817     if (ret < 0) {
0818         dev_err(&data->client->dev, "i2c transfer error in irq\n");
0819         return IRQ_HANDLED;
0820     }
0821 
0822     dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
0823     ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir);
0824 
0825     iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));
0826 
0827     ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0,
0828                     ret & ~US5182D_CFG0_PX_IRQ);
0829     if (ret < 0)
0830         dev_err(&data->client->dev, "i2c transfer error in irq\n");
0831 
0832     return IRQ_HANDLED;
0833 }
0834 
0835 static int us5182d_probe(struct i2c_client *client,
0836              const struct i2c_device_id *id)
0837 {
0838     struct us5182d_data *data;
0839     struct iio_dev *indio_dev;
0840     int ret;
0841 
0842     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0843     if (!indio_dev)
0844         return -ENOMEM;
0845 
0846     data = iio_priv(indio_dev);
0847     i2c_set_clientdata(client, indio_dev);
0848     data->client = client;
0849 
0850     mutex_init(&data->lock);
0851 
0852     indio_dev->info = &us5182d_info;
0853     indio_dev->name = US5182D_DRV_NAME;
0854     indio_dev->channels = us5182d_channels;
0855     indio_dev->num_channels = ARRAY_SIZE(us5182d_channels);
0856     indio_dev->modes = INDIO_DIRECT_MODE;
0857 
0858     ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID);
0859     if (ret != US5182D_CHIPID) {
0860         dev_err(&data->client->dev,
0861             "Failed to detect US5182 light chip\n");
0862         return (ret < 0) ? ret : -ENODEV;
0863     }
0864 
0865     if (client->irq > 0) {
0866         ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
0867                         us5182d_irq_thread_handler,
0868                         IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0869                         "us5182d-irq", indio_dev);
0870         if (ret < 0)
0871             return ret;
0872     } else
0873         dev_warn(&client->dev, "no valid irq found\n");
0874 
0875     us5182d_get_platform_data(indio_dev);
0876     ret = us5182d_init(indio_dev);
0877     if (ret < 0)
0878         return ret;
0879 
0880     ret = us5182d_dark_gain_config(indio_dev);
0881     if (ret < 0)
0882         goto out_err;
0883 
0884     if (data->default_continuous) {
0885         ret = pm_runtime_set_active(&client->dev);
0886         if (ret < 0)
0887             goto out_err;
0888     }
0889 
0890     pm_runtime_enable(&client->dev);
0891     pm_runtime_set_autosuspend_delay(&client->dev,
0892                      US5182D_SLEEP_MS);
0893     pm_runtime_use_autosuspend(&client->dev);
0894 
0895     ret = iio_device_register(indio_dev);
0896     if (ret < 0)
0897         goto out_err;
0898 
0899     return 0;
0900 
0901 out_err:
0902     us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
0903     return ret;
0904 
0905 }
0906 
0907 static int us5182d_remove(struct i2c_client *client)
0908 {
0909     struct us5182d_data *data = iio_priv(i2c_get_clientdata(client));
0910     int ret;
0911 
0912     iio_device_unregister(i2c_get_clientdata(client));
0913 
0914     pm_runtime_disable(&client->dev);
0915     pm_runtime_set_suspended(&client->dev);
0916 
0917     ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
0918     if (ret)
0919         dev_warn(&client->dev, "Failed to shut down (%pe)\n",
0920              ERR_PTR(ret));
0921 
0922     return 0;
0923 }
0924 
0925 static int us5182d_suspend(struct device *dev)
0926 {
0927     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0928     struct us5182d_data *data = iio_priv(indio_dev);
0929 
0930     if (data->power_mode == US5182D_CONTINUOUS)
0931         return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);
0932 
0933     return 0;
0934 }
0935 
0936 static int us5182d_resume(struct device *dev)
0937 {
0938     struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
0939     struct us5182d_data *data = iio_priv(indio_dev);
0940 
0941     if (data->power_mode == US5182D_CONTINUOUS)
0942         return us5182d_shutdown_en(data,
0943                        ~US5182D_CFG0_SHUTDOWN_EN & 0xff);
0944 
0945     return 0;
0946 }
0947 
0948 static const struct dev_pm_ops us5182d_pm_ops = {
0949     SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume)
0950     RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL)
0951 };
0952 
0953 static const struct acpi_device_id us5182d_acpi_match[] = {
0954     { "USD5182", 0 },
0955     {}
0956 };
0957 
0958 MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match);
0959 
0960 static const struct i2c_device_id us5182d_id[] = {
0961     { "usd5182", 0 },
0962     {}
0963 };
0964 
0965 MODULE_DEVICE_TABLE(i2c, us5182d_id);
0966 
0967 static const struct of_device_id us5182d_of_match[] = {
0968     { .compatible = "upisemi,usd5182" },
0969     {}
0970 };
0971 MODULE_DEVICE_TABLE(of, us5182d_of_match);
0972 
0973 static struct i2c_driver us5182d_driver = {
0974     .driver = {
0975         .name = US5182D_DRV_NAME,
0976         .pm = pm_ptr(&us5182d_pm_ops),
0977         .of_match_table = us5182d_of_match,
0978         .acpi_match_table = ACPI_PTR(us5182d_acpi_match),
0979     },
0980     .probe = us5182d_probe,
0981     .remove = us5182d_remove,
0982     .id_table = us5182d_id,
0983 
0984 };
0985 module_i2c_driver(us5182d_driver);
0986 
0987 MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
0988 MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor");
0989 MODULE_LICENSE("GPL v2");