1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * apds9802als.c - apds9802 ALS Driver |
4 | * |
5 | * Copyright (C) 2009 Intel Corp |
6 | * |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
8 | * |
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
10 | */ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/err.h> |
16 | #include <linux/delay.h> |
17 | #include <linux/mutex.h> |
18 | #include <linux/sysfs.h> |
19 | #include <linux/pm_runtime.h> |
20 | |
21 | #define ALS_MIN_RANGE_VAL 1 |
22 | #define ALS_MAX_RANGE_VAL 2 |
23 | #define POWER_STA_ENABLE 1 |
24 | #define POWER_STA_DISABLE 0 |
25 | |
26 | #define DRIVER_NAME "apds9802als" |
27 | |
28 | struct als_data { |
29 | struct mutex mutex; |
30 | }; |
31 | |
32 | static ssize_t als_sensing_range_show(struct device *dev, |
33 | struct device_attribute *attr, char *buf) |
34 | { |
35 | struct i2c_client *client = to_i2c_client(dev); |
36 | int val; |
37 | |
38 | val = i2c_smbus_read_byte_data(client, command: 0x81); |
39 | if (val < 0) |
40 | return val; |
41 | if (val & 1) |
42 | return sprintf(buf, fmt: "4095\n" ); |
43 | else |
44 | return sprintf(buf, fmt: "65535\n" ); |
45 | } |
46 | |
47 | static int als_wait_for_data_ready(struct device *dev) |
48 | { |
49 | struct i2c_client *client = to_i2c_client(dev); |
50 | int ret; |
51 | int retry = 10; |
52 | |
53 | do { |
54 | msleep(msecs: 30); |
55 | ret = i2c_smbus_read_byte_data(client, command: 0x86); |
56 | } while (!(ret & 0x80) && retry--); |
57 | |
58 | if (retry < 0) { |
59 | dev_warn(dev, "timeout waiting for data ready\n" ); |
60 | return -ETIMEDOUT; |
61 | } |
62 | |
63 | return 0; |
64 | } |
65 | |
66 | static ssize_t als_lux0_input_data_show(struct device *dev, |
67 | struct device_attribute *attr, char *buf) |
68 | { |
69 | struct i2c_client *client = to_i2c_client(dev); |
70 | struct als_data *data = i2c_get_clientdata(client); |
71 | int ret_val; |
72 | int temp; |
73 | |
74 | /* Protect against parallel reads */ |
75 | pm_runtime_get_sync(dev); |
76 | mutex_lock(&data->mutex); |
77 | |
78 | /* clear EOC interrupt status */ |
79 | i2c_smbus_write_byte(client, value: 0x40); |
80 | /* start measurement */ |
81 | temp = i2c_smbus_read_byte_data(client, command: 0x81); |
82 | i2c_smbus_write_byte_data(client, command: 0x81, value: temp | 0x08); |
83 | |
84 | ret_val = als_wait_for_data_ready(dev); |
85 | if (ret_val < 0) |
86 | goto failed; |
87 | |
88 | temp = i2c_smbus_read_byte_data(client, command: 0x8C); /* LSB data */ |
89 | if (temp < 0) { |
90 | ret_val = temp; |
91 | goto failed; |
92 | } |
93 | ret_val = i2c_smbus_read_byte_data(client, command: 0x8D); /* MSB data */ |
94 | if (ret_val < 0) |
95 | goto failed; |
96 | |
97 | mutex_unlock(lock: &data->mutex); |
98 | pm_runtime_put_sync(dev); |
99 | |
100 | temp = (ret_val << 8) | temp; |
101 | return sprintf(buf, fmt: "%d\n" , temp); |
102 | failed: |
103 | mutex_unlock(lock: &data->mutex); |
104 | pm_runtime_put_sync(dev); |
105 | return ret_val; |
106 | } |
107 | |
108 | static ssize_t als_sensing_range_store(struct device *dev, |
109 | struct device_attribute *attr, const char *buf, size_t count) |
110 | { |
111 | struct i2c_client *client = to_i2c_client(dev); |
112 | struct als_data *data = i2c_get_clientdata(client); |
113 | int ret_val; |
114 | unsigned long val; |
115 | |
116 | ret_val = kstrtoul(s: buf, base: 10, res: &val); |
117 | if (ret_val) |
118 | return ret_val; |
119 | |
120 | if (val < 4096) |
121 | val = 1; |
122 | else if (val < 65536) |
123 | val = 2; |
124 | else |
125 | return -ERANGE; |
126 | |
127 | pm_runtime_get_sync(dev); |
128 | |
129 | /* Make sure nobody else reads/modifies/writes 0x81 while we |
130 | are active */ |
131 | mutex_lock(&data->mutex); |
132 | |
133 | ret_val = i2c_smbus_read_byte_data(client, command: 0x81); |
134 | if (ret_val < 0) |
135 | goto fail; |
136 | |
137 | /* Reset the bits before setting them */ |
138 | ret_val = ret_val & 0xFA; |
139 | |
140 | if (val == 1) /* Setting detection range up to 4k LUX */ |
141 | ret_val = (ret_val | 0x01); |
142 | else /* Setting detection range up to 64k LUX*/ |
143 | ret_val = (ret_val | 0x00); |
144 | |
145 | ret_val = i2c_smbus_write_byte_data(client, command: 0x81, value: ret_val); |
146 | |
147 | if (ret_val >= 0) { |
148 | /* All OK */ |
149 | mutex_unlock(lock: &data->mutex); |
150 | pm_runtime_put_sync(dev); |
151 | return count; |
152 | } |
153 | fail: |
154 | mutex_unlock(lock: &data->mutex); |
155 | pm_runtime_put_sync(dev); |
156 | return ret_val; |
157 | } |
158 | |
159 | static int als_set_power_state(struct i2c_client *client, bool on_off) |
160 | { |
161 | int ret_val; |
162 | struct als_data *data = i2c_get_clientdata(client); |
163 | |
164 | mutex_lock(&data->mutex); |
165 | ret_val = i2c_smbus_read_byte_data(client, command: 0x80); |
166 | if (ret_val < 0) |
167 | goto fail; |
168 | if (on_off) |
169 | ret_val = ret_val | 0x01; |
170 | else |
171 | ret_val = ret_val & 0xFE; |
172 | ret_val = i2c_smbus_write_byte_data(client, command: 0x80, value: ret_val); |
173 | fail: |
174 | mutex_unlock(lock: &data->mutex); |
175 | return ret_val; |
176 | } |
177 | |
178 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR, |
179 | als_sensing_range_show, als_sensing_range_store); |
180 | static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL); |
181 | |
182 | static struct attribute *mid_att_als[] = { |
183 | &dev_attr_lux0_sensor_range.attr, |
184 | &dev_attr_lux0_input.attr, |
185 | NULL |
186 | }; |
187 | |
188 | static const struct attribute_group m_als_gr = { |
189 | .name = "apds9802als" , |
190 | .attrs = mid_att_als |
191 | }; |
192 | |
193 | static int als_set_default_config(struct i2c_client *client) |
194 | { |
195 | int ret_val; |
196 | /* Write the command and then switch on */ |
197 | ret_val = i2c_smbus_write_byte_data(client, command: 0x80, value: 0x01); |
198 | if (ret_val < 0) { |
199 | dev_err(&client->dev, "failed default switch on write\n" ); |
200 | return ret_val; |
201 | } |
202 | /* detection range: 1~64K Lux, maunal measurement */ |
203 | ret_val = i2c_smbus_write_byte_data(client, command: 0x81, value: 0x08); |
204 | if (ret_val < 0) |
205 | dev_err(&client->dev, "failed default LUX on write\n" ); |
206 | |
207 | /* We always get 0 for the 1st measurement after system power on, |
208 | * so make sure it is finished before user asks for data. |
209 | */ |
210 | als_wait_for_data_ready(dev: &client->dev); |
211 | |
212 | return ret_val; |
213 | } |
214 | |
215 | static int apds9802als_probe(struct i2c_client *client) |
216 | { |
217 | int res; |
218 | struct als_data *data; |
219 | |
220 | data = kzalloc(size: sizeof(struct als_data), GFP_KERNEL); |
221 | if (data == NULL) { |
222 | dev_err(&client->dev, "Memory allocation failed\n" ); |
223 | return -ENOMEM; |
224 | } |
225 | i2c_set_clientdata(client, data); |
226 | res = sysfs_create_group(kobj: &client->dev.kobj, grp: &m_als_gr); |
227 | if (res) { |
228 | dev_err(&client->dev, "device create file failed\n" ); |
229 | goto als_error1; |
230 | } |
231 | dev_info(&client->dev, "ALS chip found\n" ); |
232 | als_set_default_config(client); |
233 | mutex_init(&data->mutex); |
234 | |
235 | pm_runtime_set_active(dev: &client->dev); |
236 | pm_runtime_enable(dev: &client->dev); |
237 | |
238 | return res; |
239 | als_error1: |
240 | kfree(objp: data); |
241 | return res; |
242 | } |
243 | |
244 | static void apds9802als_remove(struct i2c_client *client) |
245 | { |
246 | struct als_data *data = i2c_get_clientdata(client); |
247 | |
248 | pm_runtime_get_sync(dev: &client->dev); |
249 | |
250 | als_set_power_state(client, on_off: false); |
251 | sysfs_remove_group(kobj: &client->dev.kobj, grp: &m_als_gr); |
252 | |
253 | pm_runtime_disable(dev: &client->dev); |
254 | pm_runtime_set_suspended(dev: &client->dev); |
255 | pm_runtime_put_noidle(dev: &client->dev); |
256 | |
257 | kfree(objp: data); |
258 | } |
259 | |
260 | #ifdef CONFIG_PM |
261 | |
262 | static int apds9802als_suspend(struct device *dev) |
263 | { |
264 | struct i2c_client *client = to_i2c_client(dev); |
265 | |
266 | als_set_power_state(client, on_off: false); |
267 | return 0; |
268 | } |
269 | |
270 | static int apds9802als_resume(struct device *dev) |
271 | { |
272 | struct i2c_client *client = to_i2c_client(dev); |
273 | |
274 | als_set_power_state(client, on_off: true); |
275 | return 0; |
276 | } |
277 | |
278 | static UNIVERSAL_DEV_PM_OPS(apds9802als_pm_ops, apds9802als_suspend, |
279 | apds9802als_resume, NULL); |
280 | |
281 | #define APDS9802ALS_PM_OPS (&apds9802als_pm_ops) |
282 | |
283 | #else /* CONFIG_PM */ |
284 | #define APDS9802ALS_PM_OPS NULL |
285 | #endif /* CONFIG_PM */ |
286 | |
287 | static const struct i2c_device_id apds9802als_id[] = { |
288 | { DRIVER_NAME, 0 }, |
289 | { } |
290 | }; |
291 | |
292 | MODULE_DEVICE_TABLE(i2c, apds9802als_id); |
293 | |
294 | static struct i2c_driver apds9802als_driver = { |
295 | .driver = { |
296 | .name = DRIVER_NAME, |
297 | .pm = APDS9802ALS_PM_OPS, |
298 | }, |
299 | .probe = apds9802als_probe, |
300 | .remove = apds9802als_remove, |
301 | .id_table = apds9802als_id, |
302 | }; |
303 | |
304 | module_i2c_driver(apds9802als_driver); |
305 | |
306 | MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com" ); |
307 | MODULE_DESCRIPTION("Avago apds9802als ALS Driver" ); |
308 | MODULE_LICENSE("GPL v2" ); |
309 | |