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