tsl4531.c (5772B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * tsl4531.c - Support for TAOS TSL4531 ambient light sensor 4 * 5 * Copyright 2013 Peter Meerwald <pmeerw@pmeerw.net> 6 * 7 * IIO driver for the TSL4531x family 8 * TSL45311/TSL45313: 7-bit I2C slave address 0x39 9 * TSL45315/TSL45317: 7-bit I2C slave address 0x29 10 * 11 * TODO: single cycle measurement 12 */ 13 14#include <linux/module.h> 15#include <linux/i2c.h> 16#include <linux/err.h> 17#include <linux/delay.h> 18 19#include <linux/iio/iio.h> 20#include <linux/iio/sysfs.h> 21 22#define TSL4531_DRV_NAME "tsl4531" 23 24#define TSL4531_COMMAND BIT(7) 25 26#define TSL4531_CONTROL (TSL4531_COMMAND | 0x00) 27#define TSL4531_CONFIG (TSL4531_COMMAND | 0x01) 28#define TSL4531_DATA (TSL4531_COMMAND | 0x04) 29#define TSL4531_ID (TSL4531_COMMAND | 0x0a) 30 31/* operating modes in control register */ 32#define TSL4531_MODE_POWERDOWN 0x00 33#define TSL4531_MODE_SINGLE_ADC 0x02 34#define TSL4531_MODE_NORMAL 0x03 35 36/* integration time control in config register */ 37#define TSL4531_TCNTRL_400MS 0x00 38#define TSL4531_TCNTRL_200MS 0x01 39#define TSL4531_TCNTRL_100MS 0x02 40 41/* part number in id register */ 42#define TSL45311_ID 0x8 43#define TSL45313_ID 0x9 44#define TSL45315_ID 0xa 45#define TSL45317_ID 0xb 46#define TSL4531_ID_SHIFT 4 47 48struct tsl4531_data { 49 struct i2c_client *client; 50 struct mutex lock; 51 int int_time; 52}; 53 54static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.2 0.4"); 55 56static struct attribute *tsl4531_attributes[] = { 57 &iio_const_attr_integration_time_available.dev_attr.attr, 58 NULL 59}; 60 61static const struct attribute_group tsl4531_attribute_group = { 62 .attrs = tsl4531_attributes, 63}; 64 65static const struct iio_chan_spec tsl4531_channels[] = { 66 { 67 .type = IIO_LIGHT, 68 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 69 BIT(IIO_CHAN_INFO_SCALE) | 70 BIT(IIO_CHAN_INFO_INT_TIME) 71 } 72}; 73 74static int tsl4531_read_raw(struct iio_dev *indio_dev, 75 struct iio_chan_spec const *chan, 76 int *val, int *val2, long mask) 77{ 78 struct tsl4531_data *data = iio_priv(indio_dev); 79 int ret; 80 81 switch (mask) { 82 case IIO_CHAN_INFO_RAW: 83 ret = i2c_smbus_read_word_data(data->client, 84 TSL4531_DATA); 85 if (ret < 0) 86 return ret; 87 *val = ret; 88 return IIO_VAL_INT; 89 case IIO_CHAN_INFO_SCALE: 90 /* 0.. 1x, 1 .. 2x, 2 .. 4x */ 91 *val = 1 << data->int_time; 92 return IIO_VAL_INT; 93 case IIO_CHAN_INFO_INT_TIME: 94 if (data->int_time == 0) 95 *val2 = 400000; 96 else if (data->int_time == 1) 97 *val2 = 200000; 98 else if (data->int_time == 2) 99 *val2 = 100000; 100 else 101 return -EINVAL; 102 *val = 0; 103 return IIO_VAL_INT_PLUS_MICRO; 104 default: 105 return -EINVAL; 106 } 107} 108 109static int tsl4531_write_raw(struct iio_dev *indio_dev, 110 struct iio_chan_spec const *chan, 111 int val, int val2, long mask) 112{ 113 struct tsl4531_data *data = iio_priv(indio_dev); 114 int int_time, ret; 115 116 switch (mask) { 117 case IIO_CHAN_INFO_INT_TIME: 118 if (val != 0) 119 return -EINVAL; 120 if (val2 == 400000) 121 int_time = 0; 122 else if (val2 == 200000) 123 int_time = 1; 124 else if (val2 == 100000) 125 int_time = 2; 126 else 127 return -EINVAL; 128 mutex_lock(&data->lock); 129 ret = i2c_smbus_write_byte_data(data->client, 130 TSL4531_CONFIG, int_time); 131 if (ret >= 0) 132 data->int_time = int_time; 133 mutex_unlock(&data->lock); 134 return ret; 135 default: 136 return -EINVAL; 137 } 138} 139 140static const struct iio_info tsl4531_info = { 141 .read_raw = tsl4531_read_raw, 142 .write_raw = tsl4531_write_raw, 143 .attrs = &tsl4531_attribute_group, 144}; 145 146static int tsl4531_check_id(struct i2c_client *client) 147{ 148 int ret = i2c_smbus_read_byte_data(client, TSL4531_ID); 149 if (ret < 0) 150 return ret; 151 152 switch (ret >> TSL4531_ID_SHIFT) { 153 case TSL45311_ID: 154 case TSL45313_ID: 155 case TSL45315_ID: 156 case TSL45317_ID: 157 return 0; 158 default: 159 return -ENODEV; 160 } 161} 162 163static int tsl4531_probe(struct i2c_client *client, 164 const struct i2c_device_id *id) 165{ 166 struct tsl4531_data *data; 167 struct iio_dev *indio_dev; 168 int ret; 169 170 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 171 if (!indio_dev) 172 return -ENOMEM; 173 174 data = iio_priv(indio_dev); 175 i2c_set_clientdata(client, indio_dev); 176 data->client = client; 177 mutex_init(&data->lock); 178 179 ret = tsl4531_check_id(client); 180 if (ret) { 181 dev_err(&client->dev, "no TSL4531 sensor\n"); 182 return ret; 183 } 184 185 ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL, 186 TSL4531_MODE_NORMAL); 187 if (ret < 0) 188 return ret; 189 190 ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONFIG, 191 TSL4531_TCNTRL_400MS); 192 if (ret < 0) 193 return ret; 194 195 indio_dev->info = &tsl4531_info; 196 indio_dev->channels = tsl4531_channels; 197 indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels); 198 indio_dev->name = TSL4531_DRV_NAME; 199 indio_dev->modes = INDIO_DIRECT_MODE; 200 201 return iio_device_register(indio_dev); 202} 203 204static int tsl4531_powerdown(struct i2c_client *client) 205{ 206 return i2c_smbus_write_byte_data(client, TSL4531_CONTROL, 207 TSL4531_MODE_POWERDOWN); 208} 209 210static int tsl4531_remove(struct i2c_client *client) 211{ 212 iio_device_unregister(i2c_get_clientdata(client)); 213 tsl4531_powerdown(client); 214 215 return 0; 216} 217 218static int tsl4531_suspend(struct device *dev) 219{ 220 return tsl4531_powerdown(to_i2c_client(dev)); 221} 222 223static int tsl4531_resume(struct device *dev) 224{ 225 return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL, 226 TSL4531_MODE_NORMAL); 227} 228 229static DEFINE_SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, 230 tsl4531_resume); 231 232static const struct i2c_device_id tsl4531_id[] = { 233 { "tsl4531", 0 }, 234 { } 235}; 236MODULE_DEVICE_TABLE(i2c, tsl4531_id); 237 238static struct i2c_driver tsl4531_driver = { 239 .driver = { 240 .name = TSL4531_DRV_NAME, 241 .pm = pm_sleep_ptr(&tsl4531_pm_ops), 242 }, 243 .probe = tsl4531_probe, 244 .remove = tsl4531_remove, 245 .id_table = tsl4531_id, 246}; 247 248module_i2c_driver(tsl4531_driver); 249 250MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 251MODULE_DESCRIPTION("TAOS TSL4531 ambient light sensors driver"); 252MODULE_LICENSE("GPL");