154359Sroberto// SPDX-License-Identifier: GPL-2.0-only 254359Sroberto/* 354359Sroberto * tsl4531.c - Support for TAOS TSL4531 ambient light sensor 454359Sroberto * 554359Sroberto * Copyright 2013 Peter Meerwald <pmeerw@pmeerw.net> 654359Sroberto * 754359Sroberto * IIO driver for the TSL4531x family 854359Sroberto * TSL45311/TSL45313: 7-bit I2C slave address 0x39 954359Sroberto * TSL45315/TSL45317: 7-bit I2C slave address 0x29 1054359Sroberto * 1154359Sroberto * TODO: single cycle measurement 1254359Sroberto */ 1354359Sroberto 1454359Sroberto#include <linux/module.h> 1554359Sroberto#include <linux/i2c.h> 1654359Sroberto#include <linux/err.h> 1754359Sroberto#include <linux/delay.h> 1854359Sroberto 1954359Sroberto#include <linux/iio/iio.h> 2054359Sroberto#include <linux/iio/sysfs.h> 2154359Sroberto 2254359Sroberto#define TSL4531_DRV_NAME "tsl4531" 2354359Sroberto 2454359Sroberto#define TSL4531_COMMAND BIT(7) 2554359Sroberto 2654359Sroberto#define TSL4531_CONTROL (TSL4531_COMMAND | 0x00) 2754359Sroberto#define TSL4531_CONFIG (TSL4531_COMMAND | 0x01) 2854359Sroberto#define TSL4531_DATA (TSL4531_COMMAND | 0x04) 2954359Sroberto#define TSL4531_ID (TSL4531_COMMAND | 0x0a) 3054359Sroberto 3154359Sroberto/* operating modes in control register */ 3254359Sroberto#define TSL4531_MODE_POWERDOWN 0x00 3354359Sroberto#define TSL4531_MODE_SINGLE_ADC 0x02 3454359Sroberto#define TSL4531_MODE_NORMAL 0x03 35280849Scy 3654359Sroberto/* integration time control in config register */ 3754359Sroberto#define TSL4531_TCNTRL_400MS 0x00 3854359Sroberto#define TSL4531_TCNTRL_200MS 0x01 3954359Sroberto#define TSL4531_TCNTRL_100MS 0x02 4054359Sroberto 4154359Sroberto/* part number in id register */ 4254359Sroberto#define TSL45311_ID 0x8 4354359Sroberto#define TSL45313_ID 0x9 4454359Sroberto#define TSL45315_ID 0xa 4554359Sroberto#define TSL45317_ID 0xb 4654359Sroberto#define TSL4531_ID_SHIFT 4 4754359Sroberto 4854359Srobertostruct tsl4531_data { 4954359Sroberto struct i2c_client *client; 5054359Sroberto struct mutex lock; 5154359Sroberto int int_time; 5254359Sroberto}; 5354359Sroberto 5454359Srobertostatic IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.2 0.4"); 5554359Sroberto 5654359Srobertostatic struct attribute *tsl4531_attributes[] = { 5754359Sroberto &iio_const_attr_integration_time_available.dev_attr.attr, 5854359Sroberto NULL 5954359Sroberto}; 6054359Sroberto 6154359Srobertostatic const struct attribute_group tsl4531_attribute_group = { 6254359Sroberto .attrs = tsl4531_attributes, 6354359Sroberto}; 6454359Sroberto 6554359Srobertostatic const struct iio_chan_spec tsl4531_channels[] = { 6654359Sroberto { 6754359Sroberto .type = IIO_LIGHT, 68280849Scy .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 6954359Sroberto BIT(IIO_CHAN_INFO_SCALE) | 7054359Sroberto BIT(IIO_CHAN_INFO_INT_TIME) 7154359Sroberto } 7254359Sroberto}; 7354359Sroberto 7454359Srobertostatic int tsl4531_read_raw(struct iio_dev *indio_dev, 7554359Sroberto struct iio_chan_spec const *chan, 7654359Sroberto int *val, int *val2, long mask) 7754359Sroberto{ 78280849Scy struct tsl4531_data *data = iio_priv(indio_dev); 79280849Scy int ret; 80280849Scy 81280849Scy switch (mask) { 82280849Scy case IIO_CHAN_INFO_RAW: 8354359Sroberto ret = i2c_smbus_read_word_data(data->client, 84280849Scy TSL4531_DATA); 85280849Scy if (ret < 0) 86280849Scy return ret; 87280849Scy *val = ret; 88280849Scy return IIO_VAL_INT; 89280849Scy case IIO_CHAN_INFO_SCALE: 90280849Scy /* 0.. 1x, 1 .. 2x, 2 .. 4x */ 91280849Scy *val = 1 << data->int_time; 92280849Scy return IIO_VAL_INT; 93280849Scy case IIO_CHAN_INFO_INT_TIME: 94280849Scy if (data->int_time == 0) 95280849Scy *val2 = 400000; 96280849Scy else if (data->int_time == 1) 97280849Scy *val2 = 200000; 98280849Scy else if (data->int_time == 2) 99280849Scy *val2 = 100000; 100280849Scy else 101280849Scy return -EINVAL; 102280849Scy *val = 0; 10354359Sroberto return IIO_VAL_INT_PLUS_MICRO; 10454359Sroberto default: 10554359Sroberto return -EINVAL; 10654359Sroberto } 10754359Sroberto} 10854359Sroberto 109280849Scystatic int tsl4531_write_raw(struct iio_dev *indio_dev, 11054359Sroberto struct iio_chan_spec const *chan, 11154359Sroberto int val, int val2, long mask) 11254359Sroberto{ 11354359Sroberto struct tsl4531_data *data = iio_priv(indio_dev); 114280849Scy int int_time, ret; 115280849Scy 11654359Sroberto switch (mask) { 11754359Sroberto case IIO_CHAN_INFO_INT_TIME: 11854359Sroberto if (val != 0) 11954359Sroberto return -EINVAL; 12054359Sroberto if (val2 == 400000) 12154359Sroberto int_time = 0; 12254359Sroberto else if (val2 == 200000) 123280849Scy int_time = 1; 12454359Sroberto else if (val2 == 100000) 125280849Scy int_time = 2; 126280849Scy else 127280849Scy return -EINVAL; 12854359Sroberto mutex_lock(&data->lock); 129280849Scy ret = i2c_smbus_write_byte_data(data->client, 13054359Sroberto TSL4531_CONFIG, int_time); 131280849Scy if (ret >= 0) 132280849Scy data->int_time = int_time; 133280849Scy mutex_unlock(&data->lock); 13454359Sroberto return ret; 135280849Scy default: 13654359Sroberto return -EINVAL; 137280849Scy } 138280849Scy} 139280849Scy 140280849Scystatic const struct iio_info tsl4531_info = { 14154359Sroberto .read_raw = tsl4531_read_raw, 142280849Scy .write_raw = tsl4531_write_raw, 14354359Sroberto .attrs = &tsl4531_attribute_group, 144280849Scy}; 145280849Scy 146280849Scystatic int tsl4531_check_id(struct i2c_client *client) 147280849Scy{ 148280849Scy int ret = i2c_smbus_read_byte_data(client, TSL4531_ID); 149280849Scy if (ret < 0) 150280849Scy return ret; 151280849Scy 152280849Scy switch (ret >> TSL4531_ID_SHIFT) { 153280849Scy case TSL45311_ID: 154280849Scy case TSL45313_ID: 15554359Sroberto case TSL45315_ID: 15654359Sroberto case TSL45317_ID: 15754359Sroberto return 0; 158280849Scy default: 159280849Scy return -ENODEV; 160280849Scy } 161280849Scy} 16254359Sroberto 16354359Srobertostatic int tsl4531_probe(struct i2c_client *client) 16454359Sroberto{ 165280849Scy struct tsl4531_data *data; 166280849Scy struct iio_dev *indio_dev; 167280849Scy int ret; 16854359Sroberto 16954359Sroberto indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 17054359Sroberto if (!indio_dev) 171280849Scy return -ENOMEM; 172280849Scy 173280849Scy data = iio_priv(indio_dev); 17454359Sroberto i2c_set_clientdata(client, indio_dev); 17554359Sroberto data->client = client; 17654359Sroberto mutex_init(&data->lock); 177280849Scy 178280849Scy ret = tsl4531_check_id(client); 179280849Scy if (ret) { 18054359Sroberto dev_err(&client->dev, "no TSL4531 sensor\n"); 181280849Scy return ret; 18254359Sroberto } 183280849Scy 184280849Scy ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL, 185280849Scy TSL4531_MODE_NORMAL); 186280849Scy if (ret < 0) 18754359Sroberto return ret; 188280849Scy 18954359Sroberto ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONFIG, 19054359Sroberto TSL4531_TCNTRL_400MS); 19154359Sroberto if (ret < 0) 19254359Sroberto return ret; 19354359Sroberto 19454359Sroberto indio_dev->info = &tsl4531_info; 19554359Sroberto indio_dev->channels = tsl4531_channels; 196280849Scy indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels); 197280849Scy indio_dev->name = TSL4531_DRV_NAME; 198280849Scy indio_dev->modes = INDIO_DIRECT_MODE; 199280849Scy 200280849Scy return iio_device_register(indio_dev); 20154359Sroberto} 20254359Sroberto 203280849Scystatic int tsl4531_powerdown(struct i2c_client *client) 20454359Sroberto{ 20554359Sroberto return i2c_smbus_write_byte_data(client, TSL4531_CONTROL, 206280849Scy TSL4531_MODE_POWERDOWN); 207280849Scy} 208280849Scy 209280849Scystatic void tsl4531_remove(struct i2c_client *client) 210280849Scy{ 211280849Scy iio_device_unregister(i2c_get_clientdata(client)); 212280849Scy tsl4531_powerdown(client); 213280849Scy} 21454359Sroberto 21554359Srobertostatic int tsl4531_suspend(struct device *dev) 21654359Sroberto{ 21754359Sroberto return tsl4531_powerdown(to_i2c_client(dev)); 21854359Sroberto} 219280849Scy 220280849Scystatic int tsl4531_resume(struct device *dev) 22154359Sroberto{ 22254359Sroberto return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL, 223280849Scy TSL4531_MODE_NORMAL); 22454359Sroberto} 22554359Sroberto 22654359Srobertostatic DEFINE_SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, 22754359Sroberto tsl4531_resume); 22854359Sroberto 22954359Srobertostatic const struct i2c_device_id tsl4531_id[] = { 23054359Sroberto { "tsl4531", 0 }, 23154359Sroberto { } 23254359Sroberto}; 23354359SrobertoMODULE_DEVICE_TABLE(i2c, tsl4531_id); 23454359Sroberto 235182007Srobertostatic struct i2c_driver tsl4531_driver = { 23654359Sroberto .driver = { 23754359Sroberto .name = TSL4531_DRV_NAME, 23854359Sroberto .pm = pm_sleep_ptr(&tsl4531_pm_ops), 239280849Scy }, 240280849Scy .probe = tsl4531_probe, 241280849Scy .remove = tsl4531_remove, 242280849Scy .id_table = tsl4531_id, 243280849Scy}; 244280849Scy 24554359Srobertomodule_i2c_driver(tsl4531_driver); 24654359Sroberto 24754359SrobertoMODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 24854359SrobertoMODULE_DESCRIPTION("TAOS TSL4531 ambient light sensors driver"); 24954359SrobertoMODULE_LICENSE("GPL"); 250280849Scy