Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  tsl2550.c - Linux kernel modules for ambient light sensor
0004  *
0005  *  Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
0006  *  Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/slab.h>
0011 #include <linux/i2c.h>
0012 #include <linux/mutex.h>
0013 
0014 #define TSL2550_DRV_NAME    "tsl2550"
0015 #define DRIVER_VERSION      "1.2"
0016 
0017 /*
0018  * Defines
0019  */
0020 
0021 #define TSL2550_POWER_DOWN      0x00
0022 #define TSL2550_POWER_UP        0x03
0023 #define TSL2550_STANDARD_RANGE      0x18
0024 #define TSL2550_EXTENDED_RANGE      0x1d
0025 #define TSL2550_READ_ADC0       0x43
0026 #define TSL2550_READ_ADC1       0x83
0027 
0028 /*
0029  * Structs
0030  */
0031 
0032 struct tsl2550_data {
0033     struct i2c_client *client;
0034     struct mutex update_lock;
0035 
0036     unsigned int power_state:1;
0037     unsigned int operating_mode:1;
0038 };
0039 
0040 /*
0041  * Global data
0042  */
0043 
0044 static const u8 TSL2550_MODE_RANGE[2] = {
0045     TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
0046 };
0047 
0048 /*
0049  * Management functions
0050  */
0051 
0052 static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
0053 {
0054     struct tsl2550_data *data = i2c_get_clientdata(client);
0055 
0056     int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
0057 
0058     data->operating_mode = mode;
0059 
0060     return ret;
0061 }
0062 
0063 static int tsl2550_set_power_state(struct i2c_client *client, int state)
0064 {
0065     struct tsl2550_data *data = i2c_get_clientdata(client);
0066     int ret;
0067 
0068     if (state == 0)
0069         ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
0070     else {
0071         ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
0072 
0073         /* On power up we should reset operating mode also... */
0074         tsl2550_set_operating_mode(client, data->operating_mode);
0075     }
0076 
0077     data->power_state = state;
0078 
0079     return ret;
0080 }
0081 
0082 static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
0083 {
0084     int ret;
0085 
0086     ret = i2c_smbus_read_byte_data(client, cmd);
0087     if (ret < 0)
0088         return ret;
0089     if (!(ret & 0x80))
0090         return -EAGAIN;
0091     return ret & 0x7f;  /* remove the "valid" bit */
0092 }
0093 
0094 /*
0095  * LUX calculation
0096  */
0097 
0098 #define TSL2550_MAX_LUX     1846
0099 
0100 static const u8 ratio_lut[] = {
0101     100, 100, 100, 100, 100, 100, 100, 100,
0102     100, 100, 100, 100, 100, 100, 99, 99,
0103     99, 99, 99, 99, 99, 99, 99, 99,
0104     99, 99, 99, 98, 98, 98, 98, 98,
0105     98, 98, 97, 97, 97, 97, 97, 96,
0106     96, 96, 96, 95, 95, 95, 94, 94,
0107     93, 93, 93, 92, 92, 91, 91, 90,
0108     89, 89, 88, 87, 87, 86, 85, 84,
0109     83, 82, 81, 80, 79, 78, 77, 75,
0110     74, 73, 71, 69, 68, 66, 64, 62,
0111     60, 58, 56, 54, 52, 49, 47, 44,
0112     42, 41, 40, 40, 39, 39, 38, 38,
0113     37, 37, 37, 36, 36, 36, 35, 35,
0114     35, 35, 34, 34, 34, 34, 33, 33,
0115     33, 33, 32, 32, 32, 32, 32, 31,
0116     31, 31, 31, 31, 30, 30, 30, 30,
0117     30,
0118 };
0119 
0120 static const u16 count_lut[] = {
0121     0, 1, 2, 3, 4, 5, 6, 7,
0122     8, 9, 10, 11, 12, 13, 14, 15,
0123     16, 18, 20, 22, 24, 26, 28, 30,
0124     32, 34, 36, 38, 40, 42, 44, 46,
0125     49, 53, 57, 61, 65, 69, 73, 77,
0126     81, 85, 89, 93, 97, 101, 105, 109,
0127     115, 123, 131, 139, 147, 155, 163, 171,
0128     179, 187, 195, 203, 211, 219, 227, 235,
0129     247, 263, 279, 295, 311, 327, 343, 359,
0130     375, 391, 407, 423, 439, 455, 471, 487,
0131     511, 543, 575, 607, 639, 671, 703, 735,
0132     767, 799, 831, 863, 895, 927, 959, 991,
0133     1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
0134     1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
0135     2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
0136     3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
0137 };
0138 
0139 /*
0140  * This function is described into Taos TSL2550 Designer's Notebook
0141  * pages 2, 3.
0142  */
0143 static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
0144 {
0145     unsigned int lux;
0146 
0147     /* Look up count from channel values */
0148     u16 c0 = count_lut[ch0];
0149     u16 c1 = count_lut[ch1];
0150 
0151     /* Avoid division by 0 and count 1 cannot be greater than count 0 */
0152     if (c1 <= c0)
0153         if (c0) {
0154             /*
0155              * Calculate ratio.
0156              * Note: the "128" is a scaling factor
0157              */
0158             u8 r = c1 * 128 / c0;
0159 
0160             /* Calculate LUX */
0161             lux = ((c0 - c1) * ratio_lut[r]) / 256;
0162         } else
0163             lux = 0;
0164     else
0165         return 0;
0166 
0167     /* LUX range check */
0168     return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
0169 }
0170 
0171 /*
0172  * SysFS support
0173  */
0174 
0175 static ssize_t tsl2550_show_power_state(struct device *dev,
0176         struct device_attribute *attr, char *buf)
0177 {
0178     struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
0179 
0180     return sprintf(buf, "%u\n", data->power_state);
0181 }
0182 
0183 static ssize_t tsl2550_store_power_state(struct device *dev,
0184         struct device_attribute *attr, const char *buf, size_t count)
0185 {
0186     struct i2c_client *client = to_i2c_client(dev);
0187     struct tsl2550_data *data = i2c_get_clientdata(client);
0188     unsigned long val = simple_strtoul(buf, NULL, 10);
0189     int ret;
0190 
0191     if (val > 1)
0192         return -EINVAL;
0193 
0194     mutex_lock(&data->update_lock);
0195     ret = tsl2550_set_power_state(client, val);
0196     mutex_unlock(&data->update_lock);
0197 
0198     if (ret < 0)
0199         return ret;
0200 
0201     return count;
0202 }
0203 
0204 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
0205            tsl2550_show_power_state, tsl2550_store_power_state);
0206 
0207 static ssize_t tsl2550_show_operating_mode(struct device *dev,
0208         struct device_attribute *attr, char *buf)
0209 {
0210     struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
0211 
0212     return sprintf(buf, "%u\n", data->operating_mode);
0213 }
0214 
0215 static ssize_t tsl2550_store_operating_mode(struct device *dev,
0216         struct device_attribute *attr, const char *buf, size_t count)
0217 {
0218     struct i2c_client *client = to_i2c_client(dev);
0219     struct tsl2550_data *data = i2c_get_clientdata(client);
0220     unsigned long val = simple_strtoul(buf, NULL, 10);
0221     int ret;
0222 
0223     if (val > 1)
0224         return -EINVAL;
0225 
0226     if (data->power_state == 0)
0227         return -EBUSY;
0228 
0229     mutex_lock(&data->update_lock);
0230     ret = tsl2550_set_operating_mode(client, val);
0231     mutex_unlock(&data->update_lock);
0232 
0233     if (ret < 0)
0234         return ret;
0235 
0236     return count;
0237 }
0238 
0239 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
0240            tsl2550_show_operating_mode, tsl2550_store_operating_mode);
0241 
0242 static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
0243 {
0244     struct tsl2550_data *data = i2c_get_clientdata(client);
0245     u8 ch0, ch1;
0246     int ret;
0247 
0248     ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
0249     if (ret < 0)
0250         return ret;
0251     ch0 = ret;
0252 
0253     ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
0254     if (ret < 0)
0255         return ret;
0256     ch1 = ret;
0257 
0258     /* Do the job */
0259     ret = tsl2550_calculate_lux(ch0, ch1);
0260     if (ret < 0)
0261         return ret;
0262     if (data->operating_mode == 1)
0263         ret *= 5;
0264 
0265     return sprintf(buf, "%d\n", ret);
0266 }
0267 
0268 static ssize_t tsl2550_show_lux1_input(struct device *dev,
0269             struct device_attribute *attr, char *buf)
0270 {
0271     struct i2c_client *client = to_i2c_client(dev);
0272     struct tsl2550_data *data = i2c_get_clientdata(client);
0273     int ret;
0274 
0275     /* No LUX data if not operational */
0276     if (!data->power_state)
0277         return -EBUSY;
0278 
0279     mutex_lock(&data->update_lock);
0280     ret = __tsl2550_show_lux(client, buf);
0281     mutex_unlock(&data->update_lock);
0282 
0283     return ret;
0284 }
0285 
0286 static DEVICE_ATTR(lux1_input, S_IRUGO,
0287            tsl2550_show_lux1_input, NULL);
0288 
0289 static struct attribute *tsl2550_attributes[] = {
0290     &dev_attr_power_state.attr,
0291     &dev_attr_operating_mode.attr,
0292     &dev_attr_lux1_input.attr,
0293     NULL
0294 };
0295 
0296 static const struct attribute_group tsl2550_attr_group = {
0297     .attrs = tsl2550_attributes,
0298 };
0299 
0300 /*
0301  * Initialization function
0302  */
0303 
0304 static int tsl2550_init_client(struct i2c_client *client)
0305 {
0306     struct tsl2550_data *data = i2c_get_clientdata(client);
0307     int err;
0308 
0309     /*
0310      * Probe the chip. To do so we try to power up the device and then to
0311      * read back the 0x03 code
0312      */
0313     err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
0314     if (err < 0)
0315         return err;
0316     if (err != TSL2550_POWER_UP)
0317         return -ENODEV;
0318     data->power_state = 1;
0319 
0320     /* Set the default operating mode */
0321     err = i2c_smbus_write_byte(client,
0322                    TSL2550_MODE_RANGE[data->operating_mode]);
0323     if (err < 0)
0324         return err;
0325 
0326     return 0;
0327 }
0328 
0329 /*
0330  * I2C init/probing/exit functions
0331  */
0332 
0333 static struct i2c_driver tsl2550_driver;
0334 static int tsl2550_probe(struct i2c_client *client,
0335                    const struct i2c_device_id *id)
0336 {
0337     struct i2c_adapter *adapter = client->adapter;
0338     struct tsl2550_data *data;
0339     int *opmode, err = 0;
0340 
0341     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
0342                         | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
0343         err = -EIO;
0344         goto exit;
0345     }
0346 
0347     data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
0348     if (!data) {
0349         err = -ENOMEM;
0350         goto exit;
0351     }
0352     data->client = client;
0353     i2c_set_clientdata(client, data);
0354 
0355     /* Check platform data */
0356     opmode = client->dev.platform_data;
0357     if (opmode) {
0358         if (*opmode < 0 || *opmode > 1) {
0359             dev_err(&client->dev, "invalid operating_mode (%d)\n",
0360                     *opmode);
0361             err = -EINVAL;
0362             goto exit_kfree;
0363         }
0364         data->operating_mode = *opmode;
0365     } else
0366         data->operating_mode = 0;   /* default mode is standard */
0367     dev_info(&client->dev, "%s operating mode\n",
0368             data->operating_mode ? "extended" : "standard");
0369 
0370     mutex_init(&data->update_lock);
0371 
0372     /* Initialize the TSL2550 chip */
0373     err = tsl2550_init_client(client);
0374     if (err)
0375         goto exit_kfree;
0376 
0377     /* Register sysfs hooks */
0378     err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
0379     if (err)
0380         goto exit_kfree;
0381 
0382     dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
0383 
0384     return 0;
0385 
0386 exit_kfree:
0387     kfree(data);
0388 exit:
0389     return err;
0390 }
0391 
0392 static int tsl2550_remove(struct i2c_client *client)
0393 {
0394     sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
0395 
0396     /* Power down the device */
0397     tsl2550_set_power_state(client, 0);
0398 
0399     kfree(i2c_get_clientdata(client));
0400 
0401     return 0;
0402 }
0403 
0404 #ifdef CONFIG_PM_SLEEP
0405 
0406 static int tsl2550_suspend(struct device *dev)
0407 {
0408     return tsl2550_set_power_state(to_i2c_client(dev), 0);
0409 }
0410 
0411 static int tsl2550_resume(struct device *dev)
0412 {
0413     return tsl2550_set_power_state(to_i2c_client(dev), 1);
0414 }
0415 
0416 static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
0417 #define TSL2550_PM_OPS (&tsl2550_pm_ops)
0418 
0419 #else
0420 
0421 #define TSL2550_PM_OPS NULL
0422 
0423 #endif /* CONFIG_PM_SLEEP */
0424 
0425 static const struct i2c_device_id tsl2550_id[] = {
0426     { "tsl2550", 0 },
0427     { }
0428 };
0429 MODULE_DEVICE_TABLE(i2c, tsl2550_id);
0430 
0431 static const struct of_device_id tsl2550_of_match[] = {
0432     { .compatible = "taos,tsl2550" },
0433     { }
0434 };
0435 MODULE_DEVICE_TABLE(of, tsl2550_of_match);
0436 
0437 static struct i2c_driver tsl2550_driver = {
0438     .driver = {
0439         .name   = TSL2550_DRV_NAME,
0440         .of_match_table = tsl2550_of_match,
0441         .pm = TSL2550_PM_OPS,
0442     },
0443     .probe  = tsl2550_probe,
0444     .remove = tsl2550_remove,
0445     .id_table = tsl2550_id,
0446 };
0447 
0448 module_i2c_driver(tsl2550_driver);
0449 
0450 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
0451 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
0452 MODULE_LICENSE("GPL");
0453 MODULE_VERSION(DRIVER_VERSION);