1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * These are the two Sharp GP2AP002 variants supported by this driver: |
4 | * GP2AP002A00F Ambient Light and Proximity Sensor |
5 | * GP2AP002S00F Proximity Sensor |
6 | * |
7 | * Copyright (C) 2020 Linaro Ltd. |
8 | * Author: Linus Walleij <linus.walleij@linaro.org> |
9 | * |
10 | * Based partly on the code in Sony Ericssons GP2AP00200F driver by |
11 | * Courtney Cavin and Oskar Andero in drivers/input/misc/gp2ap002a00f.c |
12 | * Based partly on a Samsung misc driver submitted by |
13 | * Donggeun Kim & Minkyu Kang in 2011: |
14 | * https://lore.kernel.org/lkml/1315556546-7445-1-git-send-email-dg77.kim@samsung.com/ |
15 | * Based partly on a submission by |
16 | * Jonathan Bakker and Paweł Chmiel in january 2019: |
17 | * https://lore.kernel.org/linux-input/20190125175045.22576-1-pawel.mikolaj.chmiel@gmail.com/ |
18 | * Based partly on code from the Samsung GT-S7710 by <mjchen@sta.samsung.com> |
19 | * Based partly on the code in LG Electronics GP2AP00200F driver by |
20 | * Kenobi Lee <sungyoung.lee@lge.com> and EunYoung Cho <ey.cho@lge.com> |
21 | */ |
22 | #include <linux/module.h> |
23 | #include <linux/i2c.h> |
24 | #include <linux/regmap.h> |
25 | #include <linux/iio/iio.h> |
26 | #include <linux/iio/sysfs.h> |
27 | #include <linux/iio/events.h> |
28 | #include <linux/iio/consumer.h> /* To get our ADC channel */ |
29 | #include <linux/iio/types.h> /* To deal with our ADC channel */ |
30 | #include <linux/init.h> |
31 | #include <linux/delay.h> |
32 | #include <linux/regulator/consumer.h> |
33 | #include <linux/pm_runtime.h> |
34 | #include <linux/interrupt.h> |
35 | #include <linux/bits.h> |
36 | #include <linux/math64.h> |
37 | #include <linux/pm.h> |
38 | |
39 | #define GP2AP002_PROX_CHANNEL 0 |
40 | #define GP2AP002_ALS_CHANNEL 1 |
41 | |
42 | /* ------------------------------------------------------------------------ */ |
43 | /* ADDRESS SYMBOL DATA Init R/W */ |
44 | /* D7 D6 D5 D4 D3 D2 D1 D0 */ |
45 | /* ------------------------------------------------------------------------ */ |
46 | /* 0 PROX X X X X X X X VO H'00 R */ |
47 | /* 1 GAIN X X X X LED0 X X X H'00 W */ |
48 | /* 2 HYS HYSD HYSC1 HYSC0 X HYSF3 HYSF2 HYSF1 HYSF0 H'00 W */ |
49 | /* 3 CYCLE X X CYCL2 CYCL1 CYCL0 OSC2 X X H'00 W */ |
50 | /* 4 OPMOD X X X ASD X X VCON SSD H'00 W */ |
51 | /* 6 CON X X X OCON1 OCON0 X X X H'00 W */ |
52 | /* ------------------------------------------------------------------------ */ |
53 | /* VO :Proximity sensing result(0: no detection, 1: detection) */ |
54 | /* LED0 :Select switch for LED driver's On-registence(0:2x higher, 1:normal)*/ |
55 | /* HYSD/HYSF :Adjusts the receiver sensitivity */ |
56 | /* OSC :Select switch internal clocl frequency hoppling(0:effective) */ |
57 | /* CYCL :Determine the detection cycle(typically 8ms, up to 128x) */ |
58 | /* SSD :Software Shutdown function(0:shutdown, 1:operating) */ |
59 | /* VCON :VOUT output method control(0:normal, 1:interrupt) */ |
60 | /* ASD :Select switch for analog sleep function(0:ineffective, 1:effective)*/ |
61 | /* OCON :Select switch for enabling/disabling VOUT (00:enable, 11:disable) */ |
62 | |
63 | #define GP2AP002_PROX 0x00 |
64 | #define GP2AP002_GAIN 0x01 |
65 | #define GP2AP002_HYS 0x02 |
66 | #define GP2AP002_CYCLE 0x03 |
67 | #define GP2AP002_OPMOD 0x04 |
68 | #define GP2AP002_CON 0x06 |
69 | |
70 | #define GP2AP002_PROX_VO_DETECT BIT(0) |
71 | |
72 | /* Setting this bit to 0 means 2x higher LED resistance */ |
73 | #define GP2AP002_GAIN_LED_NORMAL BIT(3) |
74 | |
75 | /* |
76 | * These bits adjusts the proximity sensitivity, determining characteristics |
77 | * of the detection distance and its hysteresis. |
78 | */ |
79 | #define GP2AP002_HYS_HYSD_SHIFT 7 |
80 | #define GP2AP002_HYS_HYSD_MASK BIT(7) |
81 | #define GP2AP002_HYS_HYSC_SHIFT 5 |
82 | #define GP2AP002_HYS_HYSC_MASK GENMASK(6, 5) |
83 | #define GP2AP002_HYS_HYSF_SHIFT 0 |
84 | #define GP2AP002_HYS_HYSF_MASK GENMASK(3, 0) |
85 | #define GP2AP002_HYS_MASK (GP2AP002_HYS_HYSD_MASK | \ |
86 | GP2AP002_HYS_HYSC_MASK | \ |
87 | GP2AP002_HYS_HYSF_MASK) |
88 | |
89 | /* |
90 | * These values determine the detection cycle response time |
91 | * 0: 8ms, 1: 16ms, 2: 32ms, 3: 64ms, 4: 128ms, |
92 | * 5: 256ms, 6: 512ms, 7: 1024ms |
93 | */ |
94 | #define GP2AP002_CYCLE_CYCL_SHIFT 3 |
95 | #define GP2AP002_CYCLE_CYCL_MASK GENMASK(5, 3) |
96 | |
97 | /* |
98 | * Select switch for internal clock frequency hopping |
99 | * 0: effective, |
100 | * 1: ineffective |
101 | */ |
102 | #define GP2AP002_CYCLE_OSC_EFFECTIVE 0 |
103 | #define GP2AP002_CYCLE_OSC_INEFFECTIVE BIT(2) |
104 | #define GP2AP002_CYCLE_OSC_MASK BIT(2) |
105 | |
106 | /* Analog sleep effective */ |
107 | #define GP2AP002_OPMOD_ASD BIT(4) |
108 | /* Enable chip */ |
109 | #define GP2AP002_OPMOD_SSD_OPERATING BIT(0) |
110 | /* IRQ mode */ |
111 | #define GP2AP002_OPMOD_VCON_IRQ BIT(1) |
112 | #define GP2AP002_OPMOD_MASK (BIT(0) | BIT(1) | BIT(4)) |
113 | |
114 | /* |
115 | * Select switch for enabling/disabling Vout pin |
116 | * 0: enable |
117 | * 2: force to go Low |
118 | * 3: force to go High |
119 | */ |
120 | #define GP2AP002_CON_OCON_SHIFT 3 |
121 | #define GP2AP002_CON_OCON_ENABLE (0x0 << GP2AP002_CON_OCON_SHIFT) |
122 | #define GP2AP002_CON_OCON_LOW (0x2 << GP2AP002_CON_OCON_SHIFT) |
123 | #define GP2AP002_CON_OCON_HIGH (0x3 << GP2AP002_CON_OCON_SHIFT) |
124 | #define GP2AP002_CON_OCON_MASK (0x3 << GP2AP002_CON_OCON_SHIFT) |
125 | |
126 | /** |
127 | * struct gp2ap002 - GP2AP002 state |
128 | * @map: regmap pointer for the i2c regmap |
129 | * @dev: pointer to parent device |
130 | * @vdd: regulator controlling VDD |
131 | * @vio: regulator controlling VIO |
132 | * @alsout: IIO ADC channel to convert the ALSOUT signal |
133 | * @hys_far: hysteresis control from device tree |
134 | * @hys_close: hysteresis control from device tree |
135 | * @is_gp2ap002s00f: this is the GP2AP002F variant of the chip |
136 | * @irq: the IRQ line used by this device |
137 | * @enabled: we cannot read the status of the hardware so we need to |
138 | * keep track of whether the event is enabled using this state variable |
139 | */ |
140 | struct gp2ap002 { |
141 | struct regmap *map; |
142 | struct device *dev; |
143 | struct regulator *vdd; |
144 | struct regulator *vio; |
145 | struct iio_channel *alsout; |
146 | u8 hys_far; |
147 | u8 hys_close; |
148 | bool is_gp2ap002s00f; |
149 | int irq; |
150 | bool enabled; |
151 | }; |
152 | |
153 | static irqreturn_t gp2ap002_prox_irq(int irq, void *d) |
154 | { |
155 | struct iio_dev *indio_dev = d; |
156 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
157 | u64 ev; |
158 | int val; |
159 | int ret; |
160 | |
161 | if (!gp2ap002->enabled) |
162 | goto err_retrig; |
163 | |
164 | ret = regmap_read(map: gp2ap002->map, GP2AP002_PROX, val: &val); |
165 | if (ret) { |
166 | dev_err(gp2ap002->dev, "error reading proximity\n" ); |
167 | goto err_retrig; |
168 | } |
169 | |
170 | if (val & GP2AP002_PROX_VO_DETECT) { |
171 | /* Close */ |
172 | dev_dbg(gp2ap002->dev, "close\n" ); |
173 | ret = regmap_write(map: gp2ap002->map, GP2AP002_HYS, |
174 | val: gp2ap002->hys_far); |
175 | if (ret) |
176 | dev_err(gp2ap002->dev, |
177 | "error setting up proximity hysteresis\n" ); |
178 | ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, GP2AP002_PROX_CHANNEL, |
179 | IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING); |
180 | } else { |
181 | /* Far */ |
182 | dev_dbg(gp2ap002->dev, "far\n" ); |
183 | ret = regmap_write(map: gp2ap002->map, GP2AP002_HYS, |
184 | val: gp2ap002->hys_close); |
185 | if (ret) |
186 | dev_err(gp2ap002->dev, |
187 | "error setting up proximity hysteresis\n" ); |
188 | ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, GP2AP002_PROX_CHANNEL, |
189 | IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING); |
190 | } |
191 | iio_push_event(indio_dev, ev_code: ev, timestamp: iio_get_time_ns(indio_dev)); |
192 | |
193 | /* |
194 | * After changing hysteresis, we need to wait for one detection |
195 | * cycle to see if anything changed, or we will just trigger the |
196 | * previous interrupt again. A detection cycle depends on the CYCLE |
197 | * register, we are hard-coding ~8 ms in probe() so wait some more |
198 | * than this, 20-30 ms. |
199 | */ |
200 | usleep_range(min: 20000, max: 30000); |
201 | |
202 | err_retrig: |
203 | ret = regmap_write(map: gp2ap002->map, GP2AP002_CON, |
204 | GP2AP002_CON_OCON_ENABLE); |
205 | if (ret) |
206 | dev_err(gp2ap002->dev, "error setting up VOUT control\n" ); |
207 | |
208 | return IRQ_HANDLED; |
209 | } |
210 | |
211 | /* |
212 | * This array maps current and lux. |
213 | * |
214 | * Ambient light sensing range is 3 to 55000 lux. |
215 | * |
216 | * This mapping is based on the following formula. |
217 | * illuminance = 10 ^ (current[mA] / 10) |
218 | * |
219 | * When the ADC measures 0, return 0 lux. |
220 | */ |
221 | static const u16 gp2ap002_illuminance_table[] = { |
222 | 0, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 50, 63, 79, |
223 | 100, 126, 158, 200, 251, 316, 398, 501, 631, 794, 1000, 1259, 1585, |
224 | 1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000, 12589, 15849, 19953, |
225 | 25119, 31623, 39811, 50119, |
226 | }; |
227 | |
228 | static int gp2ap002_get_lux(struct gp2ap002 *gp2ap002) |
229 | { |
230 | int ret, res; |
231 | u16 lux; |
232 | |
233 | ret = iio_read_channel_processed(chan: gp2ap002->alsout, val: &res); |
234 | if (ret < 0) |
235 | return ret; |
236 | |
237 | dev_dbg(gp2ap002->dev, "read %d mA from ADC\n" , res); |
238 | |
239 | /* ensure we don't under/overflow */ |
240 | res = clamp(res, 0, (int)ARRAY_SIZE(gp2ap002_illuminance_table) - 1); |
241 | lux = gp2ap002_illuminance_table[res]; |
242 | |
243 | return (int)lux; |
244 | } |
245 | |
246 | static int gp2ap002_read_raw(struct iio_dev *indio_dev, |
247 | struct iio_chan_spec const *chan, |
248 | int *val, int *val2, long mask) |
249 | { |
250 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
251 | int ret; |
252 | |
253 | pm_runtime_get_sync(dev: gp2ap002->dev); |
254 | |
255 | switch (mask) { |
256 | case IIO_CHAN_INFO_RAW: |
257 | switch (chan->type) { |
258 | case IIO_LIGHT: |
259 | ret = gp2ap002_get_lux(gp2ap002); |
260 | if (ret < 0) |
261 | return ret; |
262 | *val = ret; |
263 | ret = IIO_VAL_INT; |
264 | goto out; |
265 | default: |
266 | ret = -EINVAL; |
267 | goto out; |
268 | } |
269 | default: |
270 | ret = -EINVAL; |
271 | } |
272 | |
273 | out: |
274 | pm_runtime_mark_last_busy(dev: gp2ap002->dev); |
275 | pm_runtime_put_autosuspend(dev: gp2ap002->dev); |
276 | |
277 | return ret; |
278 | } |
279 | |
280 | static int gp2ap002_init(struct gp2ap002 *gp2ap002) |
281 | { |
282 | int ret; |
283 | |
284 | /* Set up the IR LED resistance */ |
285 | ret = regmap_write(map: gp2ap002->map, GP2AP002_GAIN, |
286 | GP2AP002_GAIN_LED_NORMAL); |
287 | if (ret) { |
288 | dev_err(gp2ap002->dev, "error setting up LED gain\n" ); |
289 | return ret; |
290 | } |
291 | ret = regmap_write(map: gp2ap002->map, GP2AP002_HYS, val: gp2ap002->hys_far); |
292 | if (ret) { |
293 | dev_err(gp2ap002->dev, |
294 | "error setting up proximity hysteresis\n" ); |
295 | return ret; |
296 | } |
297 | |
298 | /* Disable internal frequency hopping */ |
299 | ret = regmap_write(map: gp2ap002->map, GP2AP002_CYCLE, |
300 | GP2AP002_CYCLE_OSC_INEFFECTIVE); |
301 | if (ret) { |
302 | dev_err(gp2ap002->dev, |
303 | "error setting up internal frequency hopping\n" ); |
304 | return ret; |
305 | } |
306 | |
307 | /* Enable chip and IRQ, disable analog sleep */ |
308 | ret = regmap_write(map: gp2ap002->map, GP2AP002_OPMOD, |
309 | GP2AP002_OPMOD_SSD_OPERATING | |
310 | GP2AP002_OPMOD_VCON_IRQ); |
311 | if (ret) { |
312 | dev_err(gp2ap002->dev, "error setting up operation mode\n" ); |
313 | return ret; |
314 | } |
315 | |
316 | /* Interrupt on VOUT enabled */ |
317 | ret = regmap_write(map: gp2ap002->map, GP2AP002_CON, |
318 | GP2AP002_CON_OCON_ENABLE); |
319 | if (ret) |
320 | dev_err(gp2ap002->dev, "error setting up VOUT control\n" ); |
321 | |
322 | return ret; |
323 | } |
324 | |
325 | static int gp2ap002_read_event_config(struct iio_dev *indio_dev, |
326 | const struct iio_chan_spec *chan, |
327 | enum iio_event_type type, |
328 | enum iio_event_direction dir) |
329 | { |
330 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
331 | |
332 | /* |
333 | * We just keep track of this internally, as it is not possible to |
334 | * query the hardware. |
335 | */ |
336 | return gp2ap002->enabled; |
337 | } |
338 | |
339 | static int gp2ap002_write_event_config(struct iio_dev *indio_dev, |
340 | const struct iio_chan_spec *chan, |
341 | enum iio_event_type type, |
342 | enum iio_event_direction dir, |
343 | int state) |
344 | { |
345 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
346 | |
347 | if (state) { |
348 | /* |
349 | * This will bring the regulators up (unless they are on |
350 | * already) and reintialize the sensor by using runtime_pm |
351 | * callbacks. |
352 | */ |
353 | pm_runtime_get_sync(dev: gp2ap002->dev); |
354 | gp2ap002->enabled = true; |
355 | } else { |
356 | pm_runtime_mark_last_busy(dev: gp2ap002->dev); |
357 | pm_runtime_put_autosuspend(dev: gp2ap002->dev); |
358 | gp2ap002->enabled = false; |
359 | } |
360 | |
361 | return 0; |
362 | } |
363 | |
364 | static const struct iio_info gp2ap002_info = { |
365 | .read_raw = gp2ap002_read_raw, |
366 | .read_event_config = gp2ap002_read_event_config, |
367 | .write_event_config = gp2ap002_write_event_config, |
368 | }; |
369 | |
370 | static const struct iio_event_spec gp2ap002_events[] = { |
371 | { |
372 | .type = IIO_EV_TYPE_THRESH, |
373 | .dir = IIO_EV_DIR_EITHER, |
374 | .mask_separate = BIT(IIO_EV_INFO_ENABLE), |
375 | }, |
376 | }; |
377 | |
378 | static const struct iio_chan_spec gp2ap002_channels[] = { |
379 | { |
380 | .type = IIO_PROXIMITY, |
381 | .event_spec = gp2ap002_events, |
382 | .num_event_specs = ARRAY_SIZE(gp2ap002_events), |
383 | }, |
384 | { |
385 | .type = IIO_LIGHT, |
386 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), |
387 | .channel = GP2AP002_ALS_CHANNEL, |
388 | }, |
389 | }; |
390 | |
391 | /* |
392 | * We need a special regmap because this hardware expects to |
393 | * write single bytes to registers but read a 16bit word on some |
394 | * variants and discard the lower 8 bits so combine |
395 | * i2c_smbus_read_word_data() with i2c_smbus_write_byte_data() |
396 | * selectively like this. |
397 | */ |
398 | static int gp2ap002_regmap_i2c_read(void *context, unsigned int reg, |
399 | unsigned int *val) |
400 | { |
401 | struct device *dev = context; |
402 | struct i2c_client *i2c = to_i2c_client(dev); |
403 | int ret; |
404 | |
405 | ret = i2c_smbus_read_word_data(client: i2c, command: reg); |
406 | if (ret < 0) |
407 | return ret; |
408 | |
409 | *val = (ret >> 8) & 0xFF; |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | static int gp2ap002_regmap_i2c_write(void *context, unsigned int reg, |
415 | unsigned int val) |
416 | { |
417 | struct device *dev = context; |
418 | struct i2c_client *i2c = to_i2c_client(dev); |
419 | |
420 | return i2c_smbus_write_byte_data(client: i2c, command: reg, value: val); |
421 | } |
422 | |
423 | static struct regmap_bus gp2ap002_regmap_bus = { |
424 | .reg_read = gp2ap002_regmap_i2c_read, |
425 | .reg_write = gp2ap002_regmap_i2c_write, |
426 | }; |
427 | |
428 | static int gp2ap002_probe(struct i2c_client *client) |
429 | { |
430 | struct gp2ap002 *gp2ap002; |
431 | struct iio_dev *indio_dev; |
432 | struct device *dev = &client->dev; |
433 | enum iio_chan_type ch_type; |
434 | static const struct regmap_config config = { |
435 | .reg_bits = 8, |
436 | .val_bits = 8, |
437 | .max_register = GP2AP002_CON, |
438 | }; |
439 | struct regmap *regmap; |
440 | int num_chan; |
441 | const char *compat; |
442 | u8 val; |
443 | int ret; |
444 | |
445 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*gp2ap002)); |
446 | if (!indio_dev) |
447 | return -ENOMEM; |
448 | i2c_set_clientdata(client, data: indio_dev); |
449 | |
450 | gp2ap002 = iio_priv(indio_dev); |
451 | gp2ap002->dev = dev; |
452 | |
453 | /* |
454 | * Check the device compatible like this makes it possible to use |
455 | * ACPI PRP0001 for registering the sensor using device tree |
456 | * properties. |
457 | */ |
458 | ret = device_property_read_string(dev, propname: "compatible" , val: &compat); |
459 | if (ret) { |
460 | dev_err(dev, "cannot check compatible\n" ); |
461 | return ret; |
462 | } |
463 | gp2ap002->is_gp2ap002s00f = !strcmp(compat, "sharp,gp2ap002s00f" ); |
464 | |
465 | regmap = devm_regmap_init(dev, &gp2ap002_regmap_bus, dev, &config); |
466 | if (IS_ERR(ptr: regmap)) { |
467 | dev_err(dev, "Failed to register i2c regmap %ld\n" , PTR_ERR(regmap)); |
468 | return PTR_ERR(ptr: regmap); |
469 | } |
470 | gp2ap002->map = regmap; |
471 | |
472 | /* |
473 | * The hysteresis settings are coded into the device tree as values |
474 | * to be written into the hysteresis register. The datasheet defines |
475 | * modes "A", "B1" and "B2" with fixed values to be use but vendor |
476 | * code trees for actual devices are tweaking these values and refer to |
477 | * modes named things like "B1.5". To be able to support any devices, |
478 | * we allow passing an arbitrary hysteresis setting for "near" and |
479 | * "far". |
480 | */ |
481 | |
482 | /* Check the device tree for the IR LED hysteresis */ |
483 | ret = device_property_read_u8(dev, propname: "sharp,proximity-far-hysteresis" , |
484 | val: &val); |
485 | if (ret) { |
486 | dev_err(dev, "failed to obtain proximity far setting\n" ); |
487 | return ret; |
488 | } |
489 | dev_dbg(dev, "proximity far setting %02x\n" , val); |
490 | gp2ap002->hys_far = val; |
491 | |
492 | ret = device_property_read_u8(dev, propname: "sharp,proximity-close-hysteresis" , |
493 | val: &val); |
494 | if (ret) { |
495 | dev_err(dev, "failed to obtain proximity close setting\n" ); |
496 | return ret; |
497 | } |
498 | dev_dbg(dev, "proximity close setting %02x\n" , val); |
499 | gp2ap002->hys_close = val; |
500 | |
501 | /* The GP2AP002A00F has a light sensor too */ |
502 | if (!gp2ap002->is_gp2ap002s00f) { |
503 | gp2ap002->alsout = devm_iio_channel_get(dev, consumer_channel: "alsout" ); |
504 | if (IS_ERR(ptr: gp2ap002->alsout)) { |
505 | ret = PTR_ERR(ptr: gp2ap002->alsout); |
506 | ret = (ret == -ENODEV) ? -EPROBE_DEFER : ret; |
507 | return dev_err_probe(dev, err: ret, fmt: "failed to get ALSOUT ADC channel\n" ); |
508 | } |
509 | ret = iio_get_channel_type(channel: gp2ap002->alsout, type: &ch_type); |
510 | if (ret < 0) |
511 | return ret; |
512 | if (ch_type != IIO_CURRENT) { |
513 | dev_err(dev, |
514 | "wrong type of IIO channel specified for ALSOUT\n" ); |
515 | return -EINVAL; |
516 | } |
517 | } |
518 | |
519 | gp2ap002->vdd = devm_regulator_get(dev, id: "vdd" ); |
520 | if (IS_ERR(ptr: gp2ap002->vdd)) |
521 | return dev_err_probe(dev, err: PTR_ERR(ptr: gp2ap002->vdd), |
522 | fmt: "failed to get VDD regulator\n" ); |
523 | |
524 | gp2ap002->vio = devm_regulator_get(dev, id: "vio" ); |
525 | if (IS_ERR(ptr: gp2ap002->vio)) |
526 | return dev_err_probe(dev, err: PTR_ERR(ptr: gp2ap002->vio), |
527 | fmt: "failed to get VIO regulator\n" ); |
528 | |
529 | /* Operating voltage 2.4V .. 3.6V according to datasheet */ |
530 | ret = regulator_set_voltage(regulator: gp2ap002->vdd, min_uV: 2400000, max_uV: 3600000); |
531 | if (ret) { |
532 | dev_err(dev, "failed to sett VDD voltage\n" ); |
533 | return ret; |
534 | } |
535 | |
536 | /* VIO should be between 1.65V and VDD */ |
537 | ret = regulator_get_voltage(regulator: gp2ap002->vdd); |
538 | if (ret < 0) { |
539 | dev_err(dev, "failed to get VDD voltage\n" ); |
540 | return ret; |
541 | } |
542 | ret = regulator_set_voltage(regulator: gp2ap002->vio, min_uV: 1650000, max_uV: ret); |
543 | if (ret) { |
544 | dev_err(dev, "failed to set VIO voltage\n" ); |
545 | return ret; |
546 | } |
547 | |
548 | ret = regulator_enable(regulator: gp2ap002->vdd); |
549 | if (ret) { |
550 | dev_err(dev, "failed to enable VDD regulator\n" ); |
551 | return ret; |
552 | } |
553 | ret = regulator_enable(regulator: gp2ap002->vio); |
554 | if (ret) { |
555 | dev_err(dev, "failed to enable VIO regulator\n" ); |
556 | goto out_disable_vdd; |
557 | } |
558 | |
559 | msleep(msecs: 20); |
560 | |
561 | /* |
562 | * Initialize the device and signal to runtime PM that now we are |
563 | * definitely up and using power. |
564 | */ |
565 | ret = gp2ap002_init(gp2ap002); |
566 | if (ret) { |
567 | dev_err(dev, "initialization failed\n" ); |
568 | goto out_disable_vio; |
569 | } |
570 | pm_runtime_get_noresume(dev); |
571 | pm_runtime_set_active(dev); |
572 | pm_runtime_enable(dev); |
573 | gp2ap002->enabled = false; |
574 | |
575 | ret = devm_request_threaded_irq(dev, irq: client->irq, NULL, |
576 | thread_fn: gp2ap002_prox_irq, IRQF_ONESHOT, |
577 | devname: "gp2ap002" , dev_id: indio_dev); |
578 | if (ret) { |
579 | dev_err(dev, "unable to request IRQ\n" ); |
580 | goto out_put_pm; |
581 | } |
582 | gp2ap002->irq = client->irq; |
583 | |
584 | /* |
585 | * As the device takes 20 ms + regulator delay to come up with a fresh |
586 | * measurement after power-on, do not shut it down unnecessarily. |
587 | * Set autosuspend to a one second. |
588 | */ |
589 | pm_runtime_set_autosuspend_delay(dev, delay: 1000); |
590 | pm_runtime_use_autosuspend(dev); |
591 | pm_runtime_put(dev); |
592 | |
593 | indio_dev->info = &gp2ap002_info; |
594 | indio_dev->name = "gp2ap002" ; |
595 | indio_dev->channels = gp2ap002_channels; |
596 | /* Skip light channel for the proximity-only sensor */ |
597 | num_chan = ARRAY_SIZE(gp2ap002_channels); |
598 | if (gp2ap002->is_gp2ap002s00f) |
599 | num_chan--; |
600 | indio_dev->num_channels = num_chan; |
601 | indio_dev->modes = INDIO_DIRECT_MODE; |
602 | |
603 | ret = iio_device_register(indio_dev); |
604 | if (ret) |
605 | goto out_disable_pm; |
606 | dev_dbg(dev, "Sharp GP2AP002 probed successfully\n" ); |
607 | |
608 | return 0; |
609 | |
610 | out_put_pm: |
611 | pm_runtime_put_noidle(dev); |
612 | out_disable_pm: |
613 | pm_runtime_disable(dev); |
614 | out_disable_vio: |
615 | regulator_disable(regulator: gp2ap002->vio); |
616 | out_disable_vdd: |
617 | regulator_disable(regulator: gp2ap002->vdd); |
618 | return ret; |
619 | } |
620 | |
621 | static void gp2ap002_remove(struct i2c_client *client) |
622 | { |
623 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
624 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
625 | struct device *dev = &client->dev; |
626 | |
627 | pm_runtime_get_sync(dev); |
628 | pm_runtime_put_noidle(dev); |
629 | pm_runtime_disable(dev); |
630 | iio_device_unregister(indio_dev); |
631 | regulator_disable(regulator: gp2ap002->vio); |
632 | regulator_disable(regulator: gp2ap002->vdd); |
633 | } |
634 | |
635 | static int gp2ap002_runtime_suspend(struct device *dev) |
636 | { |
637 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
638 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
639 | int ret; |
640 | |
641 | /* Deactivate the IRQ */ |
642 | disable_irq(irq: gp2ap002->irq); |
643 | |
644 | /* Disable chip and IRQ, everything off */ |
645 | ret = regmap_write(map: gp2ap002->map, GP2AP002_OPMOD, val: 0x00); |
646 | if (ret) { |
647 | dev_err(gp2ap002->dev, "error setting up operation mode\n" ); |
648 | return ret; |
649 | } |
650 | /* |
651 | * As these regulators may be shared, at least we are now in |
652 | * sleep even if the regulators aren't really turned off. |
653 | */ |
654 | regulator_disable(regulator: gp2ap002->vio); |
655 | regulator_disable(regulator: gp2ap002->vdd); |
656 | |
657 | return 0; |
658 | } |
659 | |
660 | static int gp2ap002_runtime_resume(struct device *dev) |
661 | { |
662 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
663 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
664 | int ret; |
665 | |
666 | ret = regulator_enable(regulator: gp2ap002->vdd); |
667 | if (ret) { |
668 | dev_err(dev, "failed to enable VDD regulator in resume path\n" ); |
669 | return ret; |
670 | } |
671 | ret = regulator_enable(regulator: gp2ap002->vio); |
672 | if (ret) { |
673 | dev_err(dev, "failed to enable VIO regulator in resume path\n" ); |
674 | return ret; |
675 | } |
676 | |
677 | msleep(msecs: 20); |
678 | |
679 | ret = gp2ap002_init(gp2ap002); |
680 | if (ret) { |
681 | dev_err(dev, "re-initialization failed\n" ); |
682 | return ret; |
683 | } |
684 | |
685 | /* Re-activate the IRQ */ |
686 | enable_irq(irq: gp2ap002->irq); |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static DEFINE_RUNTIME_DEV_PM_OPS(gp2ap002_dev_pm_ops, gp2ap002_runtime_suspend, |
692 | gp2ap002_runtime_resume, NULL); |
693 | |
694 | static const struct i2c_device_id gp2ap002_id_table[] = { |
695 | { "gp2ap002" , 0 }, |
696 | { }, |
697 | }; |
698 | MODULE_DEVICE_TABLE(i2c, gp2ap002_id_table); |
699 | |
700 | static const struct of_device_id gp2ap002_of_match[] = { |
701 | { .compatible = "sharp,gp2ap002a00f" }, |
702 | { .compatible = "sharp,gp2ap002s00f" }, |
703 | { }, |
704 | }; |
705 | MODULE_DEVICE_TABLE(of, gp2ap002_of_match); |
706 | |
707 | static struct i2c_driver gp2ap002_driver = { |
708 | .driver = { |
709 | .name = "gp2ap002" , |
710 | .of_match_table = gp2ap002_of_match, |
711 | .pm = pm_ptr(&gp2ap002_dev_pm_ops), |
712 | }, |
713 | .probe = gp2ap002_probe, |
714 | .remove = gp2ap002_remove, |
715 | .id_table = gp2ap002_id_table, |
716 | }; |
717 | module_i2c_driver(gp2ap002_driver); |
718 | |
719 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>" ); |
720 | MODULE_DESCRIPTION("GP2AP002 ambient light and proximity sensor driver" ); |
721 | MODULE_LICENSE("GPL v2" ); |
722 | |