• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  tsl2550.c - Linux kernel modules for ambient light sensor
4  *
5  *  Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
6  *  Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
7  */
8 
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/i2c.h>
12 #include <linux/mutex.h>
13 
14 #define TSL2550_DRV_NAME	"tsl2550"
15 #define DRIVER_VERSION		"1.2"
16 
17 /*
18  * Defines
19  */
20 
21 #define TSL2550_POWER_DOWN		0x00
22 #define TSL2550_POWER_UP		0x03
23 #define TSL2550_STANDARD_RANGE		0x18
24 #define TSL2550_EXTENDED_RANGE		0x1d
25 #define TSL2550_READ_ADC0		0x43
26 #define TSL2550_READ_ADC1		0x83
27 
28 /*
29  * Structs
30  */
31 
32 struct tsl2550_data {
33 	struct i2c_client *client;
34 	struct mutex update_lock;
35 
36 	unsigned int power_state:1;
37 	unsigned int operating_mode:1;
38 };
39 
40 /*
41  * Global data
42  */
43 
44 static const u8 TSL2550_MODE_RANGE[2] = {
45 	TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
46 };
47 
48 /*
49  * Management functions
50  */
51 
tsl2550_set_operating_mode(struct i2c_client * client,int mode)52 static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
53 {
54 	struct tsl2550_data *data = i2c_get_clientdata(client);
55 
56 	int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
57 
58 	data->operating_mode = mode;
59 
60 	return ret;
61 }
62 
tsl2550_set_power_state(struct i2c_client * client,int state)63 static int tsl2550_set_power_state(struct i2c_client *client, int state)
64 {
65 	struct tsl2550_data *data = i2c_get_clientdata(client);
66 	int ret;
67 
68 	if (state == 0)
69 		ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
70 	else {
71 		ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
72 
73 		/* On power up we should reset operating mode also... */
74 		tsl2550_set_operating_mode(client, data->operating_mode);
75 	}
76 
77 	data->power_state = state;
78 
79 	return ret;
80 }
81 
tsl2550_get_adc_value(struct i2c_client * client,u8 cmd)82 static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
83 {
84 	int ret;
85 
86 	ret = i2c_smbus_read_byte_data(client, cmd);
87 	if (ret < 0)
88 		return ret;
89 	if (!(ret & 0x80))
90 		return -EAGAIN;
91 	return ret & 0x7f;	/* remove the "valid" bit */
92 }
93 
94 /*
95  * LUX calculation
96  */
97 
98 #define	TSL2550_MAX_LUX		1846
99 
100 static const u8 ratio_lut[] = {
101 	100, 100, 100, 100, 100, 100, 100, 100,
102 	100, 100, 100, 100, 100, 100, 99, 99,
103 	99, 99, 99, 99, 99, 99, 99, 99,
104 	99, 99, 99, 98, 98, 98, 98, 98,
105 	98, 98, 97, 97, 97, 97, 97, 96,
106 	96, 96, 96, 95, 95, 95, 94, 94,
107 	93, 93, 93, 92, 92, 91, 91, 90,
108 	89, 89, 88, 87, 87, 86, 85, 84,
109 	83, 82, 81, 80, 79, 78, 77, 75,
110 	74, 73, 71, 69, 68, 66, 64, 62,
111 	60, 58, 56, 54, 52, 49, 47, 44,
112 	42, 41, 40, 40, 39, 39, 38, 38,
113 	37, 37, 37, 36, 36, 36, 35, 35,
114 	35, 35, 34, 34, 34, 34, 33, 33,
115 	33, 33, 32, 32, 32, 32, 32, 31,
116 	31, 31, 31, 31, 30, 30, 30, 30,
117 	30,
118 };
119 
120 static const u16 count_lut[] = {
121 	0, 1, 2, 3, 4, 5, 6, 7,
122 	8, 9, 10, 11, 12, 13, 14, 15,
123 	16, 18, 20, 22, 24, 26, 28, 30,
124 	32, 34, 36, 38, 40, 42, 44, 46,
125 	49, 53, 57, 61, 65, 69, 73, 77,
126 	81, 85, 89, 93, 97, 101, 105, 109,
127 	115, 123, 131, 139, 147, 155, 163, 171,
128 	179, 187, 195, 203, 211, 219, 227, 235,
129 	247, 263, 279, 295, 311, 327, 343, 359,
130 	375, 391, 407, 423, 439, 455, 471, 487,
131 	511, 543, 575, 607, 639, 671, 703, 735,
132 	767, 799, 831, 863, 895, 927, 959, 991,
133 	1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
134 	1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
135 	2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
136 	3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
137 };
138 
139 /*
140  * This function is described into Taos TSL2550 Designer's Notebook
141  * pages 2, 3.
142  */
tsl2550_calculate_lux(u8 ch0,u8 ch1)143 static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
144 {
145 	unsigned int lux;
146 
147 	/* Look up count from channel values */
148 	u16 c0 = count_lut[ch0];
149 	u16 c1 = count_lut[ch1];
150 
151 	/*
152 	 * Calculate ratio.
153 	 * Note: the "128" is a scaling factor
154 	 */
155 	u8 r = 128;
156 
157 	/* Avoid division by 0 and count 1 cannot be greater than count 0 */
158 	if (c1 <= c0)
159 		if (c0) {
160 			r = c1 * 128 / c0;
161 
162 			/* Calculate LUX */
163 			lux = ((c0 - c1) * ratio_lut[r]) / 256;
164 		} else
165 			lux = 0;
166 	else
167 		return 0;
168 
169 	/* LUX range check */
170 	return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
171 }
172 
173 /*
174  * SysFS support
175  */
176 
tsl2550_show_power_state(struct device * dev,struct device_attribute * attr,char * buf)177 static ssize_t tsl2550_show_power_state(struct device *dev,
178 		struct device_attribute *attr, char *buf)
179 {
180 	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
181 
182 	return sprintf(buf, "%u\n", data->power_state);
183 }
184 
tsl2550_store_power_state(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)185 static ssize_t tsl2550_store_power_state(struct device *dev,
186 		struct device_attribute *attr, const char *buf, size_t count)
187 {
188 	struct i2c_client *client = to_i2c_client(dev);
189 	struct tsl2550_data *data = i2c_get_clientdata(client);
190 	unsigned long val = simple_strtoul(buf, NULL, 10);
191 	int ret;
192 
193 	if (val > 1)
194 		return -EINVAL;
195 
196 	mutex_lock(&data->update_lock);
197 	ret = tsl2550_set_power_state(client, val);
198 	mutex_unlock(&data->update_lock);
199 
200 	if (ret < 0)
201 		return ret;
202 
203 	return count;
204 }
205 
206 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
207 		   tsl2550_show_power_state, tsl2550_store_power_state);
208 
tsl2550_show_operating_mode(struct device * dev,struct device_attribute * attr,char * buf)209 static ssize_t tsl2550_show_operating_mode(struct device *dev,
210 		struct device_attribute *attr, char *buf)
211 {
212 	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
213 
214 	return sprintf(buf, "%u\n", data->operating_mode);
215 }
216 
tsl2550_store_operating_mode(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)217 static ssize_t tsl2550_store_operating_mode(struct device *dev,
218 		struct device_attribute *attr, const char *buf, size_t count)
219 {
220 	struct i2c_client *client = to_i2c_client(dev);
221 	struct tsl2550_data *data = i2c_get_clientdata(client);
222 	unsigned long val = simple_strtoul(buf, NULL, 10);
223 	int ret;
224 
225 	if (val > 1)
226 		return -EINVAL;
227 
228 	if (data->power_state == 0)
229 		return -EBUSY;
230 
231 	mutex_lock(&data->update_lock);
232 	ret = tsl2550_set_operating_mode(client, val);
233 	mutex_unlock(&data->update_lock);
234 
235 	if (ret < 0)
236 		return ret;
237 
238 	return count;
239 }
240 
241 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
242 		   tsl2550_show_operating_mode, tsl2550_store_operating_mode);
243 
__tsl2550_show_lux(struct i2c_client * client,char * buf)244 static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
245 {
246 	struct tsl2550_data *data = i2c_get_clientdata(client);
247 	u8 ch0, ch1;
248 	int ret;
249 
250 	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
251 	if (ret < 0)
252 		return ret;
253 	ch0 = ret;
254 
255 	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
256 	if (ret < 0)
257 		return ret;
258 	ch1 = ret;
259 
260 	/* Do the job */
261 	ret = tsl2550_calculate_lux(ch0, ch1);
262 	if (ret < 0)
263 		return ret;
264 	if (data->operating_mode == 1)
265 		ret *= 5;
266 
267 	return sprintf(buf, "%d\n", ret);
268 }
269 
tsl2550_show_lux1_input(struct device * dev,struct device_attribute * attr,char * buf)270 static ssize_t tsl2550_show_lux1_input(struct device *dev,
271 			struct device_attribute *attr, char *buf)
272 {
273 	struct i2c_client *client = to_i2c_client(dev);
274 	struct tsl2550_data *data = i2c_get_clientdata(client);
275 	int ret;
276 
277 	/* No LUX data if not operational */
278 	if (!data->power_state)
279 		return -EBUSY;
280 
281 	mutex_lock(&data->update_lock);
282 	ret = __tsl2550_show_lux(client, buf);
283 	mutex_unlock(&data->update_lock);
284 
285 	return ret;
286 }
287 
288 static DEVICE_ATTR(lux1_input, S_IRUGO,
289 		   tsl2550_show_lux1_input, NULL);
290 
291 static struct attribute *tsl2550_attributes[] = {
292 	&dev_attr_power_state.attr,
293 	&dev_attr_operating_mode.attr,
294 	&dev_attr_lux1_input.attr,
295 	NULL
296 };
297 
298 static const struct attribute_group tsl2550_attr_group = {
299 	.attrs = tsl2550_attributes,
300 };
301 
302 /*
303  * Initialization function
304  */
305 
tsl2550_init_client(struct i2c_client * client)306 static int tsl2550_init_client(struct i2c_client *client)
307 {
308 	struct tsl2550_data *data = i2c_get_clientdata(client);
309 	int err;
310 
311 	/*
312 	 * Probe the chip. To do so we try to power up the device and then to
313 	 * read back the 0x03 code
314 	 */
315 	err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
316 	if (err < 0)
317 		return err;
318 	if (err != TSL2550_POWER_UP)
319 		return -ENODEV;
320 	data->power_state = 1;
321 
322 	/* Set the default operating mode */
323 	err = i2c_smbus_write_byte(client,
324 				   TSL2550_MODE_RANGE[data->operating_mode]);
325 	if (err < 0)
326 		return err;
327 
328 	return 0;
329 }
330 
331 /*
332  * I2C init/probing/exit functions
333  */
334 
335 static struct i2c_driver tsl2550_driver;
tsl2550_probe(struct i2c_client * client,const struct i2c_device_id * id)336 static int tsl2550_probe(struct i2c_client *client,
337 				   const struct i2c_device_id *id)
338 {
339 	struct i2c_adapter *adapter = client->adapter;
340 	struct tsl2550_data *data;
341 	int *opmode, err = 0;
342 
343 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
344 					    | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
345 		err = -EIO;
346 		goto exit;
347 	}
348 
349 	data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
350 	if (!data) {
351 		err = -ENOMEM;
352 		goto exit;
353 	}
354 	data->client = client;
355 	i2c_set_clientdata(client, data);
356 
357 	/* Check platform data */
358 	opmode = client->dev.platform_data;
359 	if (opmode) {
360 		if (*opmode < 0 || *opmode > 1) {
361 			dev_err(&client->dev, "invalid operating_mode (%d)\n",
362 					*opmode);
363 			err = -EINVAL;
364 			goto exit_kfree;
365 		}
366 		data->operating_mode = *opmode;
367 	} else
368 		data->operating_mode = 0;	/* default mode is standard */
369 	dev_info(&client->dev, "%s operating mode\n",
370 			data->operating_mode ? "extended" : "standard");
371 
372 	mutex_init(&data->update_lock);
373 
374 	/* Initialize the TSL2550 chip */
375 	err = tsl2550_init_client(client);
376 	if (err)
377 		goto exit_kfree;
378 
379 	/* Register sysfs hooks */
380 	err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
381 	if (err)
382 		goto exit_kfree;
383 
384 	dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
385 
386 	return 0;
387 
388 exit_kfree:
389 	kfree(data);
390 exit:
391 	return err;
392 }
393 
tsl2550_remove(struct i2c_client * client)394 static int tsl2550_remove(struct i2c_client *client)
395 {
396 	sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
397 
398 	/* Power down the device */
399 	tsl2550_set_power_state(client, 0);
400 
401 	kfree(i2c_get_clientdata(client));
402 
403 	return 0;
404 }
405 
406 #ifdef CONFIG_PM_SLEEP
407 
tsl2550_suspend(struct device * dev)408 static int tsl2550_suspend(struct device *dev)
409 {
410 	return tsl2550_set_power_state(to_i2c_client(dev), 0);
411 }
412 
tsl2550_resume(struct device * dev)413 static int tsl2550_resume(struct device *dev)
414 {
415 	return tsl2550_set_power_state(to_i2c_client(dev), 1);
416 }
417 
418 static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
419 #define TSL2550_PM_OPS (&tsl2550_pm_ops)
420 
421 #else
422 
423 #define TSL2550_PM_OPS NULL
424 
425 #endif /* CONFIG_PM_SLEEP */
426 
427 static const struct i2c_device_id tsl2550_id[] = {
428 	{ "tsl2550", 0 },
429 	{ }
430 };
431 MODULE_DEVICE_TABLE(i2c, tsl2550_id);
432 
433 static const struct of_device_id tsl2550_of_match[] = {
434 	{ .compatible = "taos,tsl2550" },
435 	{ }
436 };
437 MODULE_DEVICE_TABLE(of, tsl2550_of_match);
438 
439 static struct i2c_driver tsl2550_driver = {
440 	.driver = {
441 		.name	= TSL2550_DRV_NAME,
442 		.of_match_table = tsl2550_of_match,
443 		.pm	= TSL2550_PM_OPS,
444 	},
445 	.probe	= tsl2550_probe,
446 	.remove	= tsl2550_remove,
447 	.id_table = tsl2550_id,
448 };
449 
450 module_i2c_driver(tsl2550_driver);
451 
452 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
453 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
454 MODULE_LICENSE("GPL");
455 MODULE_VERSION(DRIVER_VERSION);
456