1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/i2c.h>
28#include <linux/err.h>
29#include <linux/delay.h>
30#include <linux/mutex.h>
31#include <linux/sysfs.h>
32#include <linux/pm_runtime.h>
33
34#define ALS_MIN_RANGE_VAL 1
35#define ALS_MAX_RANGE_VAL 2
36#define POWER_STA_ENABLE 1
37#define POWER_STA_DISABLE 0
38
39#define DRIVER_NAME "apds9802als"
40
41struct als_data {
42 struct mutex mutex;
43};
44
45static ssize_t als_sensing_range_show(struct device *dev,
46 struct device_attribute *attr, char *buf)
47{
48 struct i2c_client *client = to_i2c_client(dev);
49 int val;
50
51 val = i2c_smbus_read_byte_data(client, 0x81);
52 if (val < 0)
53 return val;
54 if (val & 1)
55 return sprintf(buf, "4095\n");
56 else
57 return sprintf(buf, "65535\n");
58}
59
60static int als_wait_for_data_ready(struct device *dev)
61{
62 struct i2c_client *client = to_i2c_client(dev);
63 int ret;
64 int retry = 10;
65
66 do {
67 msleep(30);
68 ret = i2c_smbus_read_byte_data(client, 0x86);
69 } while (!(ret & 0x80) && retry--);
70
71 if (!retry) {
72 dev_warn(dev, "timeout waiting for data ready\n");
73 return -ETIMEDOUT;
74 }
75
76 return 0;
77}
78
79static ssize_t als_lux0_input_data_show(struct device *dev,
80 struct device_attribute *attr, char *buf)
81{
82 struct i2c_client *client = to_i2c_client(dev);
83 struct als_data *data = i2c_get_clientdata(client);
84 int ret_val;
85 int temp;
86
87
88 pm_runtime_get_sync(dev);
89 mutex_lock(&data->mutex);
90
91
92 i2c_smbus_write_byte(client, 0x40);
93
94 temp = i2c_smbus_read_byte_data(client, 0x81);
95 i2c_smbus_write_byte_data(client, 0x81, temp | 0x08);
96
97 ret_val = als_wait_for_data_ready(dev);
98 if (ret_val < 0)
99 goto failed;
100
101 temp = i2c_smbus_read_byte_data(client, 0x8C);
102 if (temp < 0) {
103 ret_val = temp;
104 goto failed;
105 }
106 ret_val = i2c_smbus_read_byte_data(client, 0x8D);
107 if (ret_val < 0)
108 goto failed;
109
110 mutex_unlock(&data->mutex);
111 pm_runtime_put_sync(dev);
112
113 temp = (ret_val << 8) | temp;
114 return sprintf(buf, "%d\n", temp);
115failed:
116 mutex_unlock(&data->mutex);
117 pm_runtime_put_sync(dev);
118 return ret_val;
119}
120
121static ssize_t als_sensing_range_store(struct device *dev,
122 struct device_attribute *attr, const char *buf, size_t count)
123{
124 struct i2c_client *client = to_i2c_client(dev);
125 struct als_data *data = i2c_get_clientdata(client);
126 int ret_val;
127 unsigned long val;
128
129 if (strict_strtoul(buf, 10, &val))
130 return -EINVAL;
131
132 if (val < 4096)
133 val = 1;
134 else if (val < 65536)
135 val = 2;
136 else
137 return -ERANGE;
138
139 pm_runtime_get_sync(dev);
140
141
142
143 mutex_lock(&data->mutex);
144
145 ret_val = i2c_smbus_read_byte_data(client, 0x81);
146 if (ret_val < 0)
147 goto fail;
148
149
150 ret_val = ret_val & 0xFA;
151
152 if (val == 1)
153 ret_val = (ret_val | 0x01);
154 else
155 ret_val = (ret_val | 0x00);
156
157 ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val);
158
159 if (ret_val >= 0) {
160
161 mutex_unlock(&data->mutex);
162 pm_runtime_put_sync(dev);
163 return count;
164 }
165fail:
166 mutex_unlock(&data->mutex);
167 pm_runtime_put_sync(dev);
168 return ret_val;
169}
170
171static int als_set_power_state(struct i2c_client *client, bool on_off)
172{
173 int ret_val;
174 struct als_data *data = i2c_get_clientdata(client);
175
176 mutex_lock(&data->mutex);
177 ret_val = i2c_smbus_read_byte_data(client, 0x80);
178 if (ret_val < 0)
179 goto fail;
180 if (on_off)
181 ret_val = ret_val | 0x01;
182 else
183 ret_val = ret_val & 0xFE;
184 ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val);
185fail:
186 mutex_unlock(&data->mutex);
187 return ret_val;
188}
189
190static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
191 als_sensing_range_show, als_sensing_range_store);
192static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
193
194static struct attribute *mid_att_als[] = {
195 &dev_attr_lux0_sensor_range.attr,
196 &dev_attr_lux0_input.attr,
197 NULL
198};
199
200static struct attribute_group m_als_gr = {
201 .name = "apds9802als",
202 .attrs = mid_att_als
203};
204
205static int als_set_default_config(struct i2c_client *client)
206{
207 int ret_val;
208
209 ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01);
210 if (ret_val < 0) {
211 dev_err(&client->dev, "failed default switch on write\n");
212 return ret_val;
213 }
214
215 ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08);
216 if (ret_val < 0)
217 dev_err(&client->dev, "failed default LUX on write\n");
218
219
220
221
222 als_wait_for_data_ready(&client->dev);
223
224 return ret_val;
225}
226
227static int apds9802als_probe(struct i2c_client *client,
228 const struct i2c_device_id *id)
229{
230 int res;
231 struct als_data *data;
232
233 data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
234 if (data == NULL) {
235 dev_err(&client->dev, "Memory allocation failed\n");
236 return -ENOMEM;
237 }
238 i2c_set_clientdata(client, data);
239 res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
240 if (res) {
241 dev_err(&client->dev, "device create file failed\n");
242 goto als_error1;
243 }
244 dev_info(&client->dev, "ALS chip found\n");
245 als_set_default_config(client);
246 mutex_init(&data->mutex);
247
248 pm_runtime_enable(&client->dev);
249 pm_runtime_get(&client->dev);
250 pm_runtime_put(&client->dev);
251
252 return res;
253als_error1:
254 kfree(data);
255 return res;
256}
257
258static int apds9802als_remove(struct i2c_client *client)
259{
260 struct als_data *data = i2c_get_clientdata(client);
261
262 als_set_power_state(client, false);
263 sysfs_remove_group(&client->dev.kobj, &m_als_gr);
264 kfree(data);
265 return 0;
266}
267
268#ifdef CONFIG_PM
269static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg)
270{
271 als_set_power_state(client, false);
272 return 0;
273}
274
275static int apds9802als_resume(struct i2c_client *client)
276{
277 als_set_default_config(client);
278
279 pm_runtime_get(&client->dev);
280 pm_runtime_put(&client->dev);
281 return 0;
282}
283
284static int apds9802als_runtime_suspend(struct device *dev)
285{
286 struct i2c_client *client = to_i2c_client(dev);
287
288 als_set_power_state(client, false);
289 return 0;
290}
291
292static int apds9802als_runtime_resume(struct device *dev)
293{
294 struct i2c_client *client = to_i2c_client(dev);
295
296 als_set_power_state(client, true);
297 return 0;
298}
299
300static const struct dev_pm_ops apds9802als_pm_ops = {
301 .runtime_suspend = apds9802als_runtime_suspend,
302 .runtime_resume = apds9802als_runtime_resume,
303};
304
305#define APDS9802ALS_PM_OPS (&apds9802als_pm_ops)
306
307#else
308#define apds9802als_suspend NULL
309#define apds9802als_resume NULL
310#define APDS9802ALS_PM_OPS NULL
311#endif
312
313static struct i2c_device_id apds9802als_id[] = {
314 { DRIVER_NAME, 0 },
315 { }
316};
317
318MODULE_DEVICE_TABLE(i2c, apds9802als_id);
319
320static struct i2c_driver apds9802als_driver = {
321 .driver = {
322 .name = DRIVER_NAME,
323 .pm = APDS9802ALS_PM_OPS,
324 },
325 .probe = apds9802als_probe,
326 .remove = apds9802als_remove,
327 .suspend = apds9802als_suspend,
328 .resume = apds9802als_resume,
329 .id_table = apds9802als_id,
330};
331
332static int __init sensor_apds9802als_init(void)
333{
334 return i2c_add_driver(&apds9802als_driver);
335}
336
337static void __exit sensor_apds9802als_exit(void)
338{
339 i2c_del_driver(&apds9802als_driver);
340}
341module_init(sensor_apds9802als_init);
342module_exit(sensor_apds9802als_exit);
343
344MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
345MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
346MODULE_LICENSE("GPL v2");
347