• 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 	/* Avoid division by 0 and count 1 cannot be greater than count 0 */
152 	if (c1 <= c0)
153 		if (c0) {
154 			/*
155 			 * Calculate ratio.
156 			 * Note: the "128" is a scaling factor
157 			 */
158 			u8 r = c1 * 128 / c0;
159 
160 			/* Calculate LUX */
161 			lux = ((c0 - c1) * ratio_lut[r]) / 256;
162 		} else
163 			lux = 0;
164 	else
165 		return 0;
166 
167 	/* LUX range check */
168 	return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
169 }
170 
171 /*
172  * SysFS support
173  */
174 
tsl2550_show_power_state(struct device * dev,struct device_attribute * attr,char * buf)175 static ssize_t tsl2550_show_power_state(struct device *dev,
176 		struct device_attribute *attr, char *buf)
177 {
178 	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
179 
180 	return sprintf(buf, "%u\n", data->power_state);
181 }
182 
tsl2550_store_power_state(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)183 static ssize_t tsl2550_store_power_state(struct device *dev,
184 		struct device_attribute *attr, const char *buf, size_t count)
185 {
186 	struct i2c_client *client = to_i2c_client(dev);
187 	struct tsl2550_data *data = i2c_get_clientdata(client);
188 	unsigned long val = simple_strtoul(buf, NULL, 10);
189 	int ret;
190 
191 	if (val > 1)
192 		return -EINVAL;
193 
194 	mutex_lock(&data->update_lock);
195 	ret = tsl2550_set_power_state(client, val);
196 	mutex_unlock(&data->update_lock);
197 
198 	if (ret < 0)
199 		return ret;
200 
201 	return count;
202 }
203 
204 static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
205 		   tsl2550_show_power_state, tsl2550_store_power_state);
206 
tsl2550_show_operating_mode(struct device * dev,struct device_attribute * attr,char * buf)207 static ssize_t tsl2550_show_operating_mode(struct device *dev,
208 		struct device_attribute *attr, char *buf)
209 {
210 	struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
211 
212 	return sprintf(buf, "%u\n", data->operating_mode);
213 }
214 
tsl2550_store_operating_mode(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)215 static ssize_t tsl2550_store_operating_mode(struct device *dev,
216 		struct device_attribute *attr, const char *buf, size_t count)
217 {
218 	struct i2c_client *client = to_i2c_client(dev);
219 	struct tsl2550_data *data = i2c_get_clientdata(client);
220 	unsigned long val = simple_strtoul(buf, NULL, 10);
221 	int ret;
222 
223 	if (val > 1)
224 		return -EINVAL;
225 
226 	if (data->power_state == 0)
227 		return -EBUSY;
228 
229 	mutex_lock(&data->update_lock);
230 	ret = tsl2550_set_operating_mode(client, val);
231 	mutex_unlock(&data->update_lock);
232 
233 	if (ret < 0)
234 		return ret;
235 
236 	return count;
237 }
238 
239 static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
240 		   tsl2550_show_operating_mode, tsl2550_store_operating_mode);
241 
__tsl2550_show_lux(struct i2c_client * client,char * buf)242 static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
243 {
244 	struct tsl2550_data *data = i2c_get_clientdata(client);
245 	u8 ch0, ch1;
246 	int ret;
247 
248 	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
249 	if (ret < 0)
250 		return ret;
251 	ch0 = ret;
252 
253 	ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
254 	if (ret < 0)
255 		return ret;
256 	ch1 = ret;
257 
258 	/* Do the job */
259 	ret = tsl2550_calculate_lux(ch0, ch1);
260 	if (ret < 0)
261 		return ret;
262 	if (data->operating_mode == 1)
263 		ret *= 5;
264 
265 	return sprintf(buf, "%d\n", ret);
266 }
267 
tsl2550_show_lux1_input(struct device * dev,struct device_attribute * attr,char * buf)268 static ssize_t tsl2550_show_lux1_input(struct device *dev,
269 			struct device_attribute *attr, char *buf)
270 {
271 	struct i2c_client *client = to_i2c_client(dev);
272 	struct tsl2550_data *data = i2c_get_clientdata(client);
273 	int ret;
274 
275 	/* No LUX data if not operational */
276 	if (!data->power_state)
277 		return -EBUSY;
278 
279 	mutex_lock(&data->update_lock);
280 	ret = __tsl2550_show_lux(client, buf);
281 	mutex_unlock(&data->update_lock);
282 
283 	return ret;
284 }
285 
286 static DEVICE_ATTR(lux1_input, S_IRUGO,
287 		   tsl2550_show_lux1_input, NULL);
288 
289 static struct attribute *tsl2550_attributes[] = {
290 	&dev_attr_power_state.attr,
291 	&dev_attr_operating_mode.attr,
292 	&dev_attr_lux1_input.attr,
293 	NULL
294 };
295 
296 static const struct attribute_group tsl2550_attr_group = {
297 	.attrs = tsl2550_attributes,
298 };
299 
300 /*
301  * Initialization function
302  */
303 
tsl2550_init_client(struct i2c_client * client)304 static int tsl2550_init_client(struct i2c_client *client)
305 {
306 	struct tsl2550_data *data = i2c_get_clientdata(client);
307 	int err;
308 
309 	/*
310 	 * Probe the chip. To do so we try to power up the device and then to
311 	 * read back the 0x03 code
312 	 */
313 	err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP);
314 	if (err < 0)
315 		return err;
316 	if (err != TSL2550_POWER_UP)
317 		return -ENODEV;
318 	data->power_state = 1;
319 
320 	/* Set the default operating mode */
321 	err = i2c_smbus_write_byte(client,
322 				   TSL2550_MODE_RANGE[data->operating_mode]);
323 	if (err < 0)
324 		return err;
325 
326 	return 0;
327 }
328 
329 /*
330  * I2C init/probing/exit functions
331  */
332 
333 static struct i2c_driver tsl2550_driver;
tsl2550_probe(struct i2c_client * client,const struct i2c_device_id * id)334 static int tsl2550_probe(struct i2c_client *client,
335 				   const struct i2c_device_id *id)
336 {
337 	struct i2c_adapter *adapter = client->adapter;
338 	struct tsl2550_data *data;
339 	int *opmode, err = 0;
340 
341 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
342 					    | I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
343 		err = -EIO;
344 		goto exit;
345 	}
346 
347 	data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
348 	if (!data) {
349 		err = -ENOMEM;
350 		goto exit;
351 	}
352 	data->client = client;
353 	i2c_set_clientdata(client, data);
354 
355 	/* Check platform data */
356 	opmode = client->dev.platform_data;
357 	if (opmode) {
358 		if (*opmode < 0 || *opmode > 1) {
359 			dev_err(&client->dev, "invalid operating_mode (%d)\n",
360 					*opmode);
361 			err = -EINVAL;
362 			goto exit_kfree;
363 		}
364 		data->operating_mode = *opmode;
365 	} else
366 		data->operating_mode = 0;	/* default mode is standard */
367 	dev_info(&client->dev, "%s operating mode\n",
368 			data->operating_mode ? "extended" : "standard");
369 
370 	mutex_init(&data->update_lock);
371 
372 	/* Initialize the TSL2550 chip */
373 	err = tsl2550_init_client(client);
374 	if (err)
375 		goto exit_kfree;
376 
377 	/* Register sysfs hooks */
378 	err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
379 	if (err)
380 		goto exit_kfree;
381 
382 	dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
383 
384 	return 0;
385 
386 exit_kfree:
387 	kfree(data);
388 exit:
389 	return err;
390 }
391 
tsl2550_remove(struct i2c_client * client)392 static int tsl2550_remove(struct i2c_client *client)
393 {
394 	sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
395 
396 	/* Power down the device */
397 	tsl2550_set_power_state(client, 0);
398 
399 	kfree(i2c_get_clientdata(client));
400 
401 	return 0;
402 }
403 
404 #ifdef CONFIG_PM_SLEEP
405 
tsl2550_suspend(struct device * dev)406 static int tsl2550_suspend(struct device *dev)
407 {
408 	return tsl2550_set_power_state(to_i2c_client(dev), 0);
409 }
410 
tsl2550_resume(struct device * dev)411 static int tsl2550_resume(struct device *dev)
412 {
413 	return tsl2550_set_power_state(to_i2c_client(dev), 1);
414 }
415 
416 static SIMPLE_DEV_PM_OPS(tsl2550_pm_ops, tsl2550_suspend, tsl2550_resume);
417 #define TSL2550_PM_OPS (&tsl2550_pm_ops)
418 
419 #else
420 
421 #define TSL2550_PM_OPS NULL
422 
423 #endif /* CONFIG_PM_SLEEP */
424 
425 static const struct i2c_device_id tsl2550_id[] = {
426 	{ "tsl2550", 0 },
427 	{ }
428 };
429 MODULE_DEVICE_TABLE(i2c, tsl2550_id);
430 
431 static const struct of_device_id tsl2550_of_match[] = {
432 	{ .compatible = "taos,tsl2550" },
433 	{ }
434 };
435 MODULE_DEVICE_TABLE(of, tsl2550_of_match);
436 
437 static struct i2c_driver tsl2550_driver = {
438 	.driver = {
439 		.name	= TSL2550_DRV_NAME,
440 		.of_match_table = tsl2550_of_match,
441 		.pm	= TSL2550_PM_OPS,
442 	},
443 	.probe	= tsl2550_probe,
444 	.remove	= tsl2550_remove,
445 	.id_table = tsl2550_id,
446 };
447 
448 module_i2c_driver(tsl2550_driver);
449 
450 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
451 MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
452 MODULE_LICENSE("GPL");
453 MODULE_VERSION(DRIVER_VERSION);
454