Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * max44009.c - Support for MAX44009 Ambient Light Sensor
0004  *
0005  * Copyright (c) 2019 Robert Eshleman <bobbyeshleman@gmail.com>
0006  *
0007  * Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX44009.pdf
0008  *
0009  * TODO: Support continuous mode and configuring from manual mode to
0010  *   automatic mode.
0011  *
0012  * Default I2C address: 0x4a
0013  */
0014 
0015 #include <linux/init.h>
0016 #include <linux/kernel.h>
0017 #include <linux/bits.h>
0018 #include <linux/i2c.h>
0019 #include <linux/iio/events.h>
0020 #include <linux/iio/iio.h>
0021 #include <linux/iio/sysfs.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/module.h>
0024 #include <linux/util_macros.h>
0025 
0026 #define MAX44009_DRV_NAME "max44009"
0027 
0028 /* Registers in datasheet order */
0029 #define MAX44009_REG_INT_STATUS 0x0
0030 #define MAX44009_REG_INT_EN 0x1
0031 #define MAX44009_REG_CFG 0x2
0032 #define MAX44009_REG_LUX_HI 0x3
0033 #define MAX44009_REG_LUX_LO 0x4
0034 #define MAX44009_REG_UPPER_THR 0x5
0035 #define MAX44009_REG_LOWER_THR 0x6
0036 #define MAX44009_REG_THR_TIMER 0x7
0037 
0038 #define MAX44009_CFG_TIM_MASK GENMASK(2, 0)
0039 #define MAX44009_CFG_MAN_MODE_MASK BIT(6)
0040 
0041 /* The maximum rising threshold for the max44009 */
0042 #define MAX44009_MAXIMUM_THRESHOLD 7520256
0043 
0044 #define MAX44009_THRESH_EXP_MASK (0xf << 4)
0045 #define MAX44009_THRESH_EXP_RSHIFT 4
0046 #define MAX44009_THRESH_MANT_LSHIFT 4
0047 #define MAX44009_THRESH_MANT_MASK 0xf
0048 
0049 #define MAX44009_UPPER_THR_MINIMUM 15
0050 
0051 /* The max44009 always scales raw readings by 0.045 and is non-configurable */
0052 #define MAX44009_SCALE_NUMERATOR 45
0053 #define MAX44009_SCALE_DENOMINATOR 1000
0054 
0055 /* The fixed-point fractional multiplier for de-scaling threshold values */
0056 #define MAX44009_FRACT_MULT 1000000
0057 
0058 static const u32 max44009_int_time_ns_array[] = {
0059     800000000,
0060     400000000,
0061     200000000,
0062     100000000,
0063     50000000, /* Manual mode only */
0064     25000000, /* Manual mode only */
0065     12500000, /* Manual mode only */
0066     6250000,  /* Manual mode only */
0067 };
0068 
0069 static const char max44009_int_time_str[] =
0070     "0.8 "
0071     "0.4 "
0072     "0.2 "
0073     "0.1 "
0074     "0.05 "
0075     "0.025 "
0076     "0.0125 "
0077     "0.00625";
0078 
0079 struct max44009_data {
0080     struct i2c_client *client;
0081     struct mutex lock;
0082 };
0083 
0084 static const struct iio_event_spec max44009_event_spec[] = {
0085     {
0086         .type = IIO_EV_TYPE_THRESH,
0087         .dir = IIO_EV_DIR_RISING,
0088         .mask_separate = BIT(IIO_EV_INFO_VALUE) |
0089                  BIT(IIO_EV_INFO_ENABLE),
0090     },
0091     {
0092         .type = IIO_EV_TYPE_THRESH,
0093         .dir = IIO_EV_DIR_FALLING,
0094         .mask_separate = BIT(IIO_EV_INFO_VALUE) |
0095                  BIT(IIO_EV_INFO_ENABLE),
0096     },
0097 };
0098 
0099 static const struct iio_chan_spec max44009_channels[] = {
0100     {
0101         .type = IIO_LIGHT,
0102         .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
0103                       BIT(IIO_CHAN_INFO_INT_TIME),
0104         .event_spec = max44009_event_spec,
0105         .num_event_specs = ARRAY_SIZE(max44009_event_spec),
0106     },
0107 };
0108 
0109 static int max44009_read_int_time(struct max44009_data *data)
0110 {
0111 
0112     int ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_CFG);
0113 
0114     if (ret < 0)
0115         return ret;
0116 
0117     return max44009_int_time_ns_array[ret & MAX44009_CFG_TIM_MASK];
0118 }
0119 
0120 static int max44009_write_int_time(struct max44009_data *data,
0121                    int val, int val2)
0122 {
0123     struct i2c_client *client = data->client;
0124     int ret, int_time, config;
0125     s64 ns;
0126 
0127     ns = val * NSEC_PER_SEC + val2;
0128     int_time = find_closest_descending(
0129             ns,
0130             max44009_int_time_ns_array,
0131             ARRAY_SIZE(max44009_int_time_ns_array));
0132 
0133     ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG);
0134     if (ret < 0)
0135         return ret;
0136 
0137     config = ret;
0138     config &= int_time;
0139 
0140     /*
0141      * To set the integration time, the device must also be in manual
0142      * mode.
0143      */
0144     config |= MAX44009_CFG_MAN_MODE_MASK;
0145 
0146     return i2c_smbus_write_byte_data(client, MAX44009_REG_CFG, config);
0147 }
0148 
0149 static int max44009_write_raw(struct iio_dev *indio_dev,
0150                   struct iio_chan_spec const *chan, int val,
0151                   int val2, long mask)
0152 {
0153     struct max44009_data *data = iio_priv(indio_dev);
0154     int ret;
0155 
0156     if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) {
0157         mutex_lock(&data->lock);
0158         ret = max44009_write_int_time(data, val, val2);
0159         mutex_unlock(&data->lock);
0160         return ret;
0161     }
0162     return -EINVAL;
0163 }
0164 
0165 static int max44009_write_raw_get_fmt(struct iio_dev *indio_dev,
0166                       struct iio_chan_spec const *chan,
0167                       long mask)
0168 {
0169     return IIO_VAL_INT_PLUS_NANO;
0170 }
0171 
0172 static int max44009_lux_raw(u8 hi, u8 lo)
0173 {
0174     int mantissa;
0175     int exponent;
0176 
0177     /*
0178      * The mantissa consists of the low nibble of the Lux High Byte
0179      * and the low nibble of the Lux Low Byte.
0180      */
0181     mantissa = ((hi & 0xf) << 4) | (lo & 0xf);
0182 
0183     /* The exponent byte is just the upper nibble of the Lux High Byte */
0184     exponent = (hi >> 4) & 0xf;
0185 
0186     /*
0187      * The exponent value is base 2 to the power of the raw exponent byte.
0188      */
0189     exponent = 1 << exponent;
0190 
0191     return exponent * mantissa;
0192 }
0193 
0194 #define MAX44009_READ_LUX_XFER_LEN (4)
0195 
0196 static int max44009_read_lux_raw(struct max44009_data *data)
0197 {
0198     int ret;
0199     u8 hireg = MAX44009_REG_LUX_HI;
0200     u8 loreg = MAX44009_REG_LUX_LO;
0201     u8 lo = 0;
0202     u8 hi = 0;
0203 
0204     struct i2c_msg msgs[] = {
0205         {
0206             .addr = data->client->addr,
0207             .flags = 0,
0208             .len = sizeof(hireg),
0209             .buf = &hireg,
0210         },
0211         {
0212             .addr = data->client->addr,
0213             .flags = I2C_M_RD,
0214             .len = sizeof(hi),
0215             .buf = &hi,
0216         },
0217         {
0218             .addr = data->client->addr,
0219             .flags = 0,
0220             .len = sizeof(loreg),
0221             .buf = &loreg,
0222         },
0223         {
0224             .addr = data->client->addr,
0225             .flags = I2C_M_RD,
0226             .len = sizeof(lo),
0227             .buf = &lo,
0228         }
0229     };
0230 
0231     /*
0232      * Use i2c_transfer instead of smbus read because i2c_transfer
0233      * does NOT use a stop bit between address write and data read.
0234      * Using a stop bit causes disjoint upper/lower byte reads and
0235      * reduces accuracy.
0236      */
0237     ret = i2c_transfer(data->client->adapter,
0238                msgs, MAX44009_READ_LUX_XFER_LEN);
0239 
0240     if (ret != MAX44009_READ_LUX_XFER_LEN)
0241         return -EIO;
0242 
0243     return max44009_lux_raw(hi, lo);
0244 }
0245 
0246 static int max44009_read_raw(struct iio_dev *indio_dev,
0247                  struct iio_chan_spec const *chan, int *val,
0248                  int *val2, long mask)
0249 {
0250     struct max44009_data *data = iio_priv(indio_dev);
0251     int lux_raw;
0252     int ret;
0253 
0254     switch (mask) {
0255     case IIO_CHAN_INFO_PROCESSED:
0256         switch (chan->type) {
0257         case IIO_LIGHT:
0258             ret = max44009_read_lux_raw(data);
0259             if (ret < 0)
0260                 return ret;
0261             lux_raw = ret;
0262 
0263             *val = lux_raw * MAX44009_SCALE_NUMERATOR;
0264             *val2 = MAX44009_SCALE_DENOMINATOR;
0265             return IIO_VAL_FRACTIONAL;
0266         default:
0267             return -EINVAL;
0268         }
0269     case IIO_CHAN_INFO_INT_TIME:
0270         switch (chan->type) {
0271         case IIO_LIGHT:
0272             ret = max44009_read_int_time(data);
0273             if (ret < 0)
0274                 return ret;
0275 
0276             *val2 = ret;
0277             *val = 0;
0278             return IIO_VAL_INT_PLUS_NANO;
0279         default:
0280             return -EINVAL;
0281         }
0282     default:
0283         return -EINVAL;
0284     }
0285 }
0286 
0287 static IIO_CONST_ATTR(illuminance_integration_time_available,
0288               max44009_int_time_str);
0289 
0290 static struct attribute *max44009_attributes[] = {
0291     &iio_const_attr_illuminance_integration_time_available.dev_attr.attr,
0292     NULL,
0293 };
0294 
0295 static const struct attribute_group max44009_attribute_group = {
0296     .attrs = max44009_attributes,
0297 };
0298 
0299 static int max44009_threshold_byte_from_fraction(int integral, int fractional)
0300 {
0301     int mantissa, exp;
0302 
0303     if ((integral <= 0 && fractional <= 0) ||
0304          integral > MAX44009_MAXIMUM_THRESHOLD ||
0305          (integral == MAX44009_MAXIMUM_THRESHOLD && fractional != 0))
0306         return -EINVAL;
0307 
0308     /* Reverse scaling of fixed-point integral */
0309     mantissa = integral * MAX44009_SCALE_DENOMINATOR;
0310     mantissa /= MAX44009_SCALE_NUMERATOR;
0311 
0312     /* Reverse scaling of fixed-point fractional */
0313     mantissa += fractional / MAX44009_FRACT_MULT *
0314             (MAX44009_SCALE_DENOMINATOR / MAX44009_SCALE_NUMERATOR);
0315 
0316     for (exp = 0; mantissa > 0xff; exp++)
0317         mantissa >>= 1;
0318 
0319     mantissa >>= 4;
0320     mantissa &= 0xf;
0321     exp <<= 4;
0322 
0323     return exp | mantissa;
0324 }
0325 
0326 static int max44009_get_thr_reg(enum iio_event_direction dir)
0327 {
0328     switch (dir) {
0329     case IIO_EV_DIR_RISING:
0330         return MAX44009_REG_UPPER_THR;
0331     case IIO_EV_DIR_FALLING:
0332         return MAX44009_REG_LOWER_THR;
0333     default:
0334         return -EINVAL;
0335     }
0336 }
0337 
0338 static int max44009_write_event_value(struct iio_dev *indio_dev,
0339                       const struct iio_chan_spec *chan,
0340                       enum iio_event_type type,
0341                       enum iio_event_direction dir,
0342                       enum iio_event_info info,
0343                       int val, int val2)
0344 {
0345     struct max44009_data *data = iio_priv(indio_dev);
0346     int reg, threshold;
0347 
0348     if (info != IIO_EV_INFO_VALUE || chan->type != IIO_LIGHT)
0349         return -EINVAL;
0350 
0351     threshold = max44009_threshold_byte_from_fraction(val, val2);
0352     if (threshold < 0)
0353         return threshold;
0354 
0355     reg = max44009_get_thr_reg(dir);
0356     if (reg < 0)
0357         return reg;
0358 
0359     return i2c_smbus_write_byte_data(data->client, reg, threshold);
0360 }
0361 
0362 static int max44009_read_threshold(struct iio_dev *indio_dev,
0363                    enum iio_event_direction dir)
0364 {
0365     struct max44009_data *data = iio_priv(indio_dev);
0366     int byte, reg;
0367     int mantissa, exponent;
0368 
0369     reg = max44009_get_thr_reg(dir);
0370     if (reg < 0)
0371         return reg;
0372 
0373     byte = i2c_smbus_read_byte_data(data->client, reg);
0374     if (byte < 0)
0375         return byte;
0376 
0377     mantissa = byte & MAX44009_THRESH_MANT_MASK;
0378     mantissa <<= MAX44009_THRESH_MANT_LSHIFT;
0379 
0380     /*
0381      * To get the upper threshold, always adds the minimum upper threshold
0382      * value to the shifted byte value (see datasheet).
0383      */
0384     if (dir == IIO_EV_DIR_RISING)
0385         mantissa += MAX44009_UPPER_THR_MINIMUM;
0386 
0387     /*
0388      * Exponent is base 2 to the power of the threshold exponent byte
0389      * value
0390      */
0391     exponent = byte & MAX44009_THRESH_EXP_MASK;
0392     exponent >>= MAX44009_THRESH_EXP_RSHIFT;
0393 
0394     return (1 << exponent) * mantissa;
0395 }
0396 
0397 static int max44009_read_event_value(struct iio_dev *indio_dev,
0398                      const struct iio_chan_spec *chan,
0399                      enum iio_event_type type,
0400                      enum iio_event_direction dir,
0401                      enum iio_event_info info,
0402                      int *val, int *val2)
0403 {
0404     int ret;
0405     int threshold;
0406 
0407     if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
0408         return -EINVAL;
0409 
0410     ret = max44009_read_threshold(indio_dev, dir);
0411     if (ret < 0)
0412         return ret;
0413     threshold = ret;
0414 
0415     *val = threshold * MAX44009_SCALE_NUMERATOR;
0416     *val2 = MAX44009_SCALE_DENOMINATOR;
0417 
0418     return IIO_VAL_FRACTIONAL;
0419 }
0420 
0421 static int max44009_write_event_config(struct iio_dev *indio_dev,
0422                        const struct iio_chan_spec *chan,
0423                        enum iio_event_type type,
0424                        enum iio_event_direction dir,
0425                        int state)
0426 {
0427     struct max44009_data *data = iio_priv(indio_dev);
0428     int ret;
0429 
0430     if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
0431         return -EINVAL;
0432 
0433     ret = i2c_smbus_write_byte_data(data->client,
0434                     MAX44009_REG_INT_EN, state);
0435     if (ret < 0)
0436         return ret;
0437 
0438     /*
0439      * Set device to trigger interrupt immediately upon exceeding
0440      * the threshold limit.
0441      */
0442     return i2c_smbus_write_byte_data(data->client,
0443                      MAX44009_REG_THR_TIMER, 0);
0444 }
0445 
0446 static int max44009_read_event_config(struct iio_dev *indio_dev,
0447                       const struct iio_chan_spec *chan,
0448                       enum iio_event_type type,
0449                       enum iio_event_direction dir)
0450 {
0451     struct max44009_data *data = iio_priv(indio_dev);
0452 
0453     if (chan->type != IIO_LIGHT || type != IIO_EV_TYPE_THRESH)
0454         return -EINVAL;
0455 
0456     return i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_EN);
0457 }
0458 
0459 static const struct iio_info max44009_info = {
0460     .read_raw = max44009_read_raw,
0461     .write_raw = max44009_write_raw,
0462     .write_raw_get_fmt = max44009_write_raw_get_fmt,
0463     .read_event_value = max44009_read_event_value,
0464     .read_event_config = max44009_read_event_config,
0465     .write_event_value = max44009_write_event_value,
0466     .write_event_config = max44009_write_event_config,
0467     .attrs = &max44009_attribute_group,
0468 };
0469 
0470 static irqreturn_t max44009_threaded_irq_handler(int irq, void *p)
0471 {
0472     struct iio_dev *indio_dev = p;
0473     struct max44009_data *data = iio_priv(indio_dev);
0474     int ret;
0475 
0476     ret = i2c_smbus_read_byte_data(data->client, MAX44009_REG_INT_STATUS);
0477     if (ret) {
0478         iio_push_event(indio_dev,
0479                    IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
0480                             IIO_EV_TYPE_THRESH,
0481                             IIO_EV_DIR_EITHER),
0482                    iio_get_time_ns(indio_dev));
0483 
0484         return IRQ_HANDLED;
0485     }
0486 
0487     return IRQ_NONE;
0488 }
0489 
0490 static int max44009_probe(struct i2c_client *client,
0491               const struct i2c_device_id *id)
0492 {
0493     struct max44009_data *data;
0494     struct iio_dev *indio_dev;
0495     int ret;
0496 
0497     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0498     if (!indio_dev)
0499         return -ENOMEM;
0500 
0501     data = iio_priv(indio_dev);
0502     i2c_set_clientdata(client, indio_dev);
0503     data->client = client;
0504     indio_dev->info = &max44009_info;
0505     indio_dev->modes = INDIO_DIRECT_MODE;
0506     indio_dev->name = MAX44009_DRV_NAME;
0507     indio_dev->channels = max44009_channels;
0508     indio_dev->num_channels = ARRAY_SIZE(max44009_channels);
0509     mutex_init(&data->lock);
0510 
0511     /* Clear any stale interrupt bit */
0512     ret = i2c_smbus_read_byte_data(client, MAX44009_REG_CFG);
0513     if (ret < 0)
0514         return ret;
0515 
0516     if (client->irq > 0) {
0517         ret = devm_request_threaded_irq(&client->dev, client->irq,
0518                         NULL,
0519                         max44009_threaded_irq_handler,
0520                         IRQF_TRIGGER_FALLING |
0521                         IRQF_ONESHOT | IRQF_SHARED,
0522                         "max44009_event",
0523                         indio_dev);
0524         if (ret < 0)
0525             return ret;
0526     }
0527 
0528     return devm_iio_device_register(&client->dev, indio_dev);
0529 }
0530 
0531 static const struct i2c_device_id max44009_id[] = {
0532     { "max44009", 0 },
0533     { }
0534 };
0535 MODULE_DEVICE_TABLE(i2c, max44009_id);
0536 
0537 static struct i2c_driver max44009_driver = {
0538     .driver = {
0539         .name = MAX44009_DRV_NAME,
0540     },
0541     .probe = max44009_probe,
0542     .id_table = max44009_id,
0543 };
0544 module_i2c_driver(max44009_driver);
0545 
0546 static const struct of_device_id max44009_of_match[] = {
0547     { .compatible = "maxim,max44009" },
0548     { }
0549 };
0550 MODULE_DEVICE_TABLE(of, max44009_of_match);
0551 
0552 MODULE_AUTHOR("Robert Eshleman <bobbyeshleman@gmail.com>");
0553 MODULE_LICENSE("GPL v2");
0554 MODULE_DESCRIPTION("MAX44009 ambient light sensor driver");