1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * JSA1212 Ambient Light & Proximity Sensor Driver |
4 | * |
5 | * Copyright (c) 2014, Intel Corporation. |
6 | * |
7 | * JSA1212 I2C slave address: 0x44(ADDR tied to GND), 0x45(ADDR tied to VDD) |
8 | * |
9 | * TODO: Interrupt support, thresholds, range support. |
10 | */ |
11 | |
12 | #include <linux/kernel.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/module.h> |
15 | #include <linux/delay.h> |
16 | #include <linux/i2c.h> |
17 | #include <linux/mutex.h> |
18 | #include <linux/acpi.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/iio/iio.h> |
21 | #include <linux/iio/sysfs.h> |
22 | |
23 | /* JSA1212 reg address */ |
24 | #define JSA1212_CONF_REG 0x01 |
25 | #define JSA1212_INT_REG 0x02 |
26 | #define JSA1212_PXS_LT_REG 0x03 |
27 | #define JSA1212_PXS_HT_REG 0x04 |
28 | #define JSA1212_ALS_TH1_REG 0x05 |
29 | #define JSA1212_ALS_TH2_REG 0x06 |
30 | #define JSA1212_ALS_TH3_REG 0x07 |
31 | #define JSA1212_PXS_DATA_REG 0x08 |
32 | #define JSA1212_ALS_DT1_REG 0x09 |
33 | #define JSA1212_ALS_DT2_REG 0x0A |
34 | #define JSA1212_ALS_RNG_REG 0x0B |
35 | #define JSA1212_MAX_REG 0x0C |
36 | |
37 | /* JSA1212 reg masks */ |
38 | #define JSA1212_CONF_MASK 0xFF |
39 | #define JSA1212_INT_MASK 0xFF |
40 | #define JSA1212_PXS_LT_MASK 0xFF |
41 | #define JSA1212_PXS_HT_MASK 0xFF |
42 | #define JSA1212_ALS_TH1_MASK 0xFF |
43 | #define JSA1212_ALS_TH2_LT_MASK 0x0F |
44 | #define JSA1212_ALS_TH2_HT_MASK 0xF0 |
45 | #define JSA1212_ALS_TH3_MASK 0xFF |
46 | #define JSA1212_PXS_DATA_MASK 0xFF |
47 | #define JSA1212_ALS_DATA_MASK 0x0FFF |
48 | #define JSA1212_ALS_DT1_MASK 0xFF |
49 | #define JSA1212_ALS_DT2_MASK 0x0F |
50 | #define JSA1212_ALS_RNG_MASK 0x07 |
51 | |
52 | /* JSA1212 CONF REG bits */ |
53 | #define JSA1212_CONF_PXS_MASK 0x80 |
54 | #define JSA1212_CONF_PXS_ENABLE 0x80 |
55 | #define JSA1212_CONF_PXS_DISABLE 0x00 |
56 | #define JSA1212_CONF_ALS_MASK 0x04 |
57 | #define JSA1212_CONF_ALS_ENABLE 0x04 |
58 | #define JSA1212_CONF_ALS_DISABLE 0x00 |
59 | #define JSA1212_CONF_IRDR_MASK 0x08 |
60 | /* Proxmity sensing IRDR current sink settings */ |
61 | #define JSA1212_CONF_IRDR_200MA 0x08 |
62 | #define JSA1212_CONF_IRDR_100MA 0x00 |
63 | #define JSA1212_CONF_PXS_SLP_MASK 0x70 |
64 | #define JSA1212_CONF_PXS_SLP_0MS 0x70 |
65 | #define JSA1212_CONF_PXS_SLP_12MS 0x60 |
66 | #define JSA1212_CONF_PXS_SLP_50MS 0x50 |
67 | #define JSA1212_CONF_PXS_SLP_75MS 0x40 |
68 | #define JSA1212_CONF_PXS_SLP_100MS 0x30 |
69 | #define JSA1212_CONF_PXS_SLP_200MS 0x20 |
70 | #define JSA1212_CONF_PXS_SLP_400MS 0x10 |
71 | #define JSA1212_CONF_PXS_SLP_800MS 0x00 |
72 | |
73 | /* JSA1212 INT REG bits */ |
74 | #define JSA1212_INT_CTRL_MASK 0x01 |
75 | #define JSA1212_INT_CTRL_EITHER 0x00 |
76 | #define JSA1212_INT_CTRL_BOTH 0x01 |
77 | #define JSA1212_INT_ALS_PRST_MASK 0x06 |
78 | #define JSA1212_INT_ALS_PRST_1CONV 0x00 |
79 | #define JSA1212_INT_ALS_PRST_4CONV 0x02 |
80 | #define JSA1212_INT_ALS_PRST_8CONV 0x04 |
81 | #define JSA1212_INT_ALS_PRST_16CONV 0x06 |
82 | #define JSA1212_INT_ALS_FLAG_MASK 0x08 |
83 | #define JSA1212_INT_ALS_FLAG_CLR 0x00 |
84 | #define JSA1212_INT_PXS_PRST_MASK 0x60 |
85 | #define JSA1212_INT_PXS_PRST_1CONV 0x00 |
86 | #define JSA1212_INT_PXS_PRST_4CONV 0x20 |
87 | #define JSA1212_INT_PXS_PRST_8CONV 0x40 |
88 | #define JSA1212_INT_PXS_PRST_16CONV 0x60 |
89 | #define JSA1212_INT_PXS_FLAG_MASK 0x80 |
90 | #define JSA1212_INT_PXS_FLAG_CLR 0x00 |
91 | |
92 | /* JSA1212 ALS RNG REG bits */ |
93 | #define JSA1212_ALS_RNG_0_2048 0x00 |
94 | #define JSA1212_ALS_RNG_0_1024 0x01 |
95 | #define JSA1212_ALS_RNG_0_512 0x02 |
96 | #define JSA1212_ALS_RNG_0_256 0x03 |
97 | #define JSA1212_ALS_RNG_0_128 0x04 |
98 | |
99 | /* JSA1212 INT threshold range */ |
100 | #define JSA1212_ALS_TH_MIN 0x0000 |
101 | #define JSA1212_ALS_TH_MAX 0x0FFF |
102 | #define JSA1212_PXS_TH_MIN 0x00 |
103 | #define JSA1212_PXS_TH_MAX 0xFF |
104 | |
105 | #define JSA1212_ALS_DELAY_MS 200 |
106 | #define JSA1212_PXS_DELAY_MS 100 |
107 | |
108 | #define JSA1212_DRIVER_NAME "jsa1212" |
109 | #define JSA1212_REGMAP_NAME "jsa1212_regmap" |
110 | |
111 | enum jsa1212_op_mode { |
112 | JSA1212_OPMODE_ALS_EN, |
113 | JSA1212_OPMODE_PXS_EN, |
114 | }; |
115 | |
116 | struct jsa1212_data { |
117 | struct i2c_client *client; |
118 | struct mutex lock; |
119 | u8 als_rng_idx; |
120 | bool als_en; /* ALS enable status */ |
121 | bool pxs_en; /* proximity enable status */ |
122 | struct regmap *regmap; |
123 | }; |
124 | |
125 | /* ALS range idx to val mapping */ |
126 | static const int jsa1212_als_range_val[] = {2048, 1024, 512, 256, 128, |
127 | 128, 128, 128}; |
128 | |
129 | /* Enables or disables ALS function based on status */ |
130 | static int jsa1212_als_enable(struct jsa1212_data *data, u8 status) |
131 | { |
132 | int ret; |
133 | |
134 | ret = regmap_update_bits(map: data->regmap, JSA1212_CONF_REG, |
135 | JSA1212_CONF_ALS_MASK, |
136 | val: status); |
137 | if (ret < 0) |
138 | return ret; |
139 | |
140 | data->als_en = !!status; |
141 | |
142 | return 0; |
143 | } |
144 | |
145 | /* Enables or disables PXS function based on status */ |
146 | static int jsa1212_pxs_enable(struct jsa1212_data *data, u8 status) |
147 | { |
148 | int ret; |
149 | |
150 | ret = regmap_update_bits(map: data->regmap, JSA1212_CONF_REG, |
151 | JSA1212_CONF_PXS_MASK, |
152 | val: status); |
153 | if (ret < 0) |
154 | return ret; |
155 | |
156 | data->pxs_en = !!status; |
157 | |
158 | return 0; |
159 | } |
160 | |
161 | static int jsa1212_read_als_data(struct jsa1212_data *data, |
162 | unsigned int *val) |
163 | { |
164 | int ret; |
165 | __le16 als_data; |
166 | |
167 | ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); |
168 | if (ret < 0) |
169 | return ret; |
170 | |
171 | /* Delay for data output */ |
172 | msleep(JSA1212_ALS_DELAY_MS); |
173 | |
174 | /* Read 12 bit data */ |
175 | ret = regmap_bulk_read(map: data->regmap, JSA1212_ALS_DT1_REG, val: &als_data, val_count: 2); |
176 | if (ret < 0) { |
177 | dev_err(&data->client->dev, "als data read err\n" ); |
178 | goto als_data_read_err; |
179 | } |
180 | |
181 | *val = le16_to_cpu(als_data); |
182 | |
183 | als_data_read_err: |
184 | return jsa1212_als_enable(data, JSA1212_CONF_ALS_DISABLE); |
185 | } |
186 | |
187 | static int jsa1212_read_pxs_data(struct jsa1212_data *data, |
188 | unsigned int *val) |
189 | { |
190 | int ret; |
191 | unsigned int pxs_data; |
192 | |
193 | ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); |
194 | if (ret < 0) |
195 | return ret; |
196 | |
197 | /* Delay for data output */ |
198 | msleep(JSA1212_PXS_DELAY_MS); |
199 | |
200 | /* Read out all data */ |
201 | ret = regmap_read(map: data->regmap, JSA1212_PXS_DATA_REG, val: &pxs_data); |
202 | if (ret < 0) { |
203 | dev_err(&data->client->dev, "pxs data read err\n" ); |
204 | goto pxs_data_read_err; |
205 | } |
206 | |
207 | *val = pxs_data & JSA1212_PXS_DATA_MASK; |
208 | |
209 | pxs_data_read_err: |
210 | return jsa1212_pxs_enable(data, JSA1212_CONF_PXS_DISABLE); |
211 | } |
212 | |
213 | static int jsa1212_read_raw(struct iio_dev *indio_dev, |
214 | struct iio_chan_spec const *chan, |
215 | int *val, int *val2, long mask) |
216 | { |
217 | int ret; |
218 | struct jsa1212_data *data = iio_priv(indio_dev); |
219 | |
220 | switch (mask) { |
221 | case IIO_CHAN_INFO_RAW: |
222 | mutex_lock(&data->lock); |
223 | switch (chan->type) { |
224 | case IIO_LIGHT: |
225 | ret = jsa1212_read_als_data(data, val); |
226 | break; |
227 | case IIO_PROXIMITY: |
228 | ret = jsa1212_read_pxs_data(data, val); |
229 | break; |
230 | default: |
231 | ret = -EINVAL; |
232 | break; |
233 | } |
234 | mutex_unlock(lock: &data->lock); |
235 | return ret < 0 ? ret : IIO_VAL_INT; |
236 | case IIO_CHAN_INFO_SCALE: |
237 | switch (chan->type) { |
238 | case IIO_LIGHT: |
239 | *val = jsa1212_als_range_val[data->als_rng_idx]; |
240 | *val2 = BIT(12); /* Max 12 bit value */ |
241 | return IIO_VAL_FRACTIONAL; |
242 | default: |
243 | break; |
244 | } |
245 | break; |
246 | default: |
247 | break; |
248 | } |
249 | |
250 | return -EINVAL; |
251 | } |
252 | |
253 | static const struct iio_chan_spec jsa1212_channels[] = { |
254 | { |
255 | .type = IIO_LIGHT, |
256 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
257 | BIT(IIO_CHAN_INFO_SCALE), |
258 | }, |
259 | { |
260 | .type = IIO_PROXIMITY, |
261 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
262 | } |
263 | }; |
264 | |
265 | static const struct iio_info jsa1212_info = { |
266 | .read_raw = &jsa1212_read_raw, |
267 | }; |
268 | |
269 | static int jsa1212_chip_init(struct jsa1212_data *data) |
270 | { |
271 | int ret; |
272 | |
273 | ret = regmap_write(map: data->regmap, JSA1212_CONF_REG, |
274 | val: (JSA1212_CONF_PXS_SLP_50MS | |
275 | JSA1212_CONF_IRDR_200MA)); |
276 | if (ret < 0) |
277 | return ret; |
278 | |
279 | ret = regmap_write(map: data->regmap, JSA1212_INT_REG, |
280 | JSA1212_INT_ALS_PRST_4CONV); |
281 | if (ret < 0) |
282 | return ret; |
283 | |
284 | data->als_rng_idx = JSA1212_ALS_RNG_0_2048; |
285 | |
286 | return 0; |
287 | } |
288 | |
289 | static bool jsa1212_is_volatile_reg(struct device *dev, unsigned int reg) |
290 | { |
291 | switch (reg) { |
292 | case JSA1212_PXS_DATA_REG: |
293 | case JSA1212_ALS_DT1_REG: |
294 | case JSA1212_ALS_DT2_REG: |
295 | case JSA1212_INT_REG: |
296 | return true; |
297 | default: |
298 | return false; |
299 | } |
300 | } |
301 | |
302 | static const struct regmap_config jsa1212_regmap_config = { |
303 | .name = JSA1212_REGMAP_NAME, |
304 | .reg_bits = 8, |
305 | .val_bits = 8, |
306 | .max_register = JSA1212_MAX_REG, |
307 | .cache_type = REGCACHE_RBTREE, |
308 | .volatile_reg = jsa1212_is_volatile_reg, |
309 | }; |
310 | |
311 | static int jsa1212_probe(struct i2c_client *client) |
312 | { |
313 | struct jsa1212_data *data; |
314 | struct iio_dev *indio_dev; |
315 | struct regmap *regmap; |
316 | int ret; |
317 | |
318 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
319 | if (!indio_dev) |
320 | return -ENOMEM; |
321 | |
322 | regmap = devm_regmap_init_i2c(client, &jsa1212_regmap_config); |
323 | if (IS_ERR(ptr: regmap)) { |
324 | dev_err(&client->dev, "Regmap initialization failed.\n" ); |
325 | return PTR_ERR(ptr: regmap); |
326 | } |
327 | |
328 | data = iio_priv(indio_dev); |
329 | |
330 | i2c_set_clientdata(client, data: indio_dev); |
331 | data->client = client; |
332 | data->regmap = regmap; |
333 | |
334 | mutex_init(&data->lock); |
335 | |
336 | ret = jsa1212_chip_init(data); |
337 | if (ret < 0) |
338 | return ret; |
339 | |
340 | indio_dev->channels = jsa1212_channels; |
341 | indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels); |
342 | indio_dev->name = JSA1212_DRIVER_NAME; |
343 | indio_dev->modes = INDIO_DIRECT_MODE; |
344 | |
345 | indio_dev->info = &jsa1212_info; |
346 | |
347 | ret = iio_device_register(indio_dev); |
348 | if (ret < 0) |
349 | dev_err(&client->dev, "%s: register device failed\n" , __func__); |
350 | |
351 | return ret; |
352 | } |
353 | |
354 | /* power off the device */ |
355 | static int jsa1212_power_off(struct jsa1212_data *data) |
356 | { |
357 | int ret; |
358 | |
359 | mutex_lock(&data->lock); |
360 | |
361 | ret = regmap_update_bits(map: data->regmap, JSA1212_CONF_REG, |
362 | JSA1212_CONF_ALS_MASK | |
363 | JSA1212_CONF_PXS_MASK, |
364 | JSA1212_CONF_ALS_DISABLE | |
365 | JSA1212_CONF_PXS_DISABLE); |
366 | |
367 | if (ret < 0) |
368 | dev_err(&data->client->dev, "power off cmd failed\n" ); |
369 | |
370 | mutex_unlock(lock: &data->lock); |
371 | |
372 | return ret; |
373 | } |
374 | |
375 | static void jsa1212_remove(struct i2c_client *client) |
376 | { |
377 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
378 | struct jsa1212_data *data = iio_priv(indio_dev); |
379 | |
380 | iio_device_unregister(indio_dev); |
381 | |
382 | jsa1212_power_off(data); |
383 | } |
384 | |
385 | static int jsa1212_suspend(struct device *dev) |
386 | { |
387 | struct jsa1212_data *data; |
388 | |
389 | data = iio_priv(indio_dev: i2c_get_clientdata(to_i2c_client(dev))); |
390 | |
391 | return jsa1212_power_off(data); |
392 | } |
393 | |
394 | static int jsa1212_resume(struct device *dev) |
395 | { |
396 | int ret = 0; |
397 | struct jsa1212_data *data; |
398 | |
399 | data = iio_priv(indio_dev: i2c_get_clientdata(to_i2c_client(dev))); |
400 | |
401 | mutex_lock(&data->lock); |
402 | |
403 | if (data->als_en) { |
404 | ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); |
405 | if (ret < 0) { |
406 | dev_err(dev, "als resume failed\n" ); |
407 | goto unlock_and_ret; |
408 | } |
409 | } |
410 | |
411 | if (data->pxs_en) { |
412 | ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); |
413 | if (ret < 0) |
414 | dev_err(dev, "pxs resume failed\n" ); |
415 | } |
416 | |
417 | unlock_and_ret: |
418 | mutex_unlock(lock: &data->lock); |
419 | return ret; |
420 | } |
421 | |
422 | static DEFINE_SIMPLE_DEV_PM_OPS(jsa1212_pm_ops, jsa1212_suspend, |
423 | jsa1212_resume); |
424 | |
425 | static const struct acpi_device_id jsa1212_acpi_match[] = { |
426 | {"JSA1212" , 0}, |
427 | { }, |
428 | }; |
429 | MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); |
430 | |
431 | static const struct i2c_device_id jsa1212_id[] = { |
432 | { JSA1212_DRIVER_NAME, 0 }, |
433 | { } |
434 | }; |
435 | MODULE_DEVICE_TABLE(i2c, jsa1212_id); |
436 | |
437 | static struct i2c_driver jsa1212_driver = { |
438 | .driver = { |
439 | .name = JSA1212_DRIVER_NAME, |
440 | .pm = pm_sleep_ptr(&jsa1212_pm_ops), |
441 | .acpi_match_table = ACPI_PTR(jsa1212_acpi_match), |
442 | }, |
443 | .probe = jsa1212_probe, |
444 | .remove = jsa1212_remove, |
445 | .id_table = jsa1212_id, |
446 | }; |
447 | module_i2c_driver(jsa1212_driver); |
448 | |
449 | MODULE_AUTHOR("Sathya Kuppuswamy <sathyanarayanan.kuppuswamy@linux.intel.com>" ); |
450 | MODULE_DESCRIPTION("JSA1212 proximity/ambient light sensor driver" ); |
451 | MODULE_LICENSE("GPL v2" ); |
452 | |