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 | |
48 | struct tsl4531_data { |
49 | struct i2c_client *client; |
50 | struct mutex lock; |
51 | int int_time; |
52 | }; |
53 | |
54 | static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.2 0.4" ); |
55 | |
56 | static struct attribute *tsl4531_attributes[] = { |
57 | &iio_const_attr_integration_time_available.dev_attr.attr, |
58 | NULL |
59 | }; |
60 | |
61 | static const struct attribute_group tsl4531_attribute_group = { |
62 | .attrs = tsl4531_attributes, |
63 | }; |
64 | |
65 | static 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 | |
74 | static 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(client: 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 | |
109 | static 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(client: data->client, |
130 | TSL4531_CONFIG, value: int_time); |
131 | if (ret >= 0) |
132 | data->int_time = int_time; |
133 | mutex_unlock(lock: &data->lock); |
134 | return ret; |
135 | default: |
136 | return -EINVAL; |
137 | } |
138 | } |
139 | |
140 | static 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 | |
146 | static 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 | |
163 | static int tsl4531_probe(struct i2c_client *client) |
164 | { |
165 | struct tsl4531_data *data; |
166 | struct iio_dev *indio_dev; |
167 | int ret; |
168 | |
169 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
170 | if (!indio_dev) |
171 | return -ENOMEM; |
172 | |
173 | data = iio_priv(indio_dev); |
174 | i2c_set_clientdata(client, data: indio_dev); |
175 | data->client = client; |
176 | mutex_init(&data->lock); |
177 | |
178 | ret = tsl4531_check_id(client); |
179 | if (ret) { |
180 | dev_err(&client->dev, "no TSL4531 sensor\n" ); |
181 | return ret; |
182 | } |
183 | |
184 | ret = i2c_smbus_write_byte_data(client: data->client, TSL4531_CONTROL, |
185 | TSL4531_MODE_NORMAL); |
186 | if (ret < 0) |
187 | return ret; |
188 | |
189 | ret = i2c_smbus_write_byte_data(client: data->client, TSL4531_CONFIG, |
190 | TSL4531_TCNTRL_400MS); |
191 | if (ret < 0) |
192 | return ret; |
193 | |
194 | indio_dev->info = &tsl4531_info; |
195 | indio_dev->channels = tsl4531_channels; |
196 | indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels); |
197 | indio_dev->name = TSL4531_DRV_NAME; |
198 | indio_dev->modes = INDIO_DIRECT_MODE; |
199 | |
200 | return iio_device_register(indio_dev); |
201 | } |
202 | |
203 | static int tsl4531_powerdown(struct i2c_client *client) |
204 | { |
205 | return i2c_smbus_write_byte_data(client, TSL4531_CONTROL, |
206 | TSL4531_MODE_POWERDOWN); |
207 | } |
208 | |
209 | static void tsl4531_remove(struct i2c_client *client) |
210 | { |
211 | iio_device_unregister(indio_dev: i2c_get_clientdata(client)); |
212 | tsl4531_powerdown(client); |
213 | } |
214 | |
215 | static int tsl4531_suspend(struct device *dev) |
216 | { |
217 | return tsl4531_powerdown(to_i2c_client(dev)); |
218 | } |
219 | |
220 | static int tsl4531_resume(struct device *dev) |
221 | { |
222 | return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL, |
223 | TSL4531_MODE_NORMAL); |
224 | } |
225 | |
226 | static DEFINE_SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, |
227 | tsl4531_resume); |
228 | |
229 | static const struct i2c_device_id tsl4531_id[] = { |
230 | { "tsl4531" , 0 }, |
231 | { } |
232 | }; |
233 | MODULE_DEVICE_TABLE(i2c, tsl4531_id); |
234 | |
235 | static struct i2c_driver tsl4531_driver = { |
236 | .driver = { |
237 | .name = TSL4531_DRV_NAME, |
238 | .pm = pm_sleep_ptr(&tsl4531_pm_ops), |
239 | }, |
240 | .probe = tsl4531_probe, |
241 | .remove = tsl4531_remove, |
242 | .id_table = tsl4531_id, |
243 | }; |
244 | |
245 | module_i2c_driver(tsl4531_driver); |
246 | |
247 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>" ); |
248 | MODULE_DESCRIPTION("TAOS TSL4531 ambient light sensors driver" ); |
249 | MODULE_LICENSE("GPL" ); |
250 | |