]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/iio/light/rpr0521.c
iio: light: rpr0521 poweroff for probe fails
[mirror_ubuntu-bionic-kernel.git] / drivers / iio / light / rpr0521.c
1 /*
2 * RPR-0521 ROHM Ambient Light and Proximity Sensor
3 *
4 * Copyright (c) 2015, Intel Corporation.
5 *
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
9 *
10 * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
11 *
12 * TODO: illuminance channel, PM support, buffer
13 */
14
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/i2c.h>
18 #include <linux/regmap.h>
19 #include <linux/delay.h>
20 #include <linux/acpi.h>
21
22 #include <linux/iio/iio.h>
23 #include <linux/iio/sysfs.h>
24 #include <linux/pm_runtime.h>
25
26 #define RPR0521_REG_SYSTEM_CTRL 0x40
27 #define RPR0521_REG_MODE_CTRL 0x41
28 #define RPR0521_REG_ALS_CTRL 0x42
29 #define RPR0521_REG_PXS_CTRL 0x43
30 #define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */
31 #define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */
32 #define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */
33 #define RPR0521_REG_ID 0x92
34
35 #define RPR0521_MODE_ALS_MASK BIT(7)
36 #define RPR0521_MODE_PXS_MASK BIT(6)
37 #define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0)
38 #define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4)
39 #define RPR0521_ALS_DATA0_GAIN_SHIFT 4
40 #define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2)
41 #define RPR0521_ALS_DATA1_GAIN_SHIFT 2
42 #define RPR0521_PXS_GAIN_MASK GENMASK(5, 4)
43 #define RPR0521_PXS_GAIN_SHIFT 4
44
45 #define RPR0521_MODE_ALS_ENABLE BIT(7)
46 #define RPR0521_MODE_ALS_DISABLE 0x00
47 #define RPR0521_MODE_PXS_ENABLE BIT(6)
48 #define RPR0521_MODE_PXS_DISABLE 0x00
49
50 #define RPR0521_MANUFACT_ID 0xE0
51 #define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */
52
53 #define RPR0521_DRV_NAME "RPR0521"
54 #define RPR0521_REGMAP_NAME "rpr0521_regmap"
55
56 #define RPR0521_SLEEP_DELAY_MS 2000
57
58 #define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1"
59 #define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1"
60
61 struct rpr0521_gain {
62 int scale;
63 int uscale;
64 };
65
66 static const struct rpr0521_gain rpr0521_als_gain[4] = {
67 {1, 0}, /* x1 */
68 {0, 500000}, /* x2 */
69 {0, 15625}, /* x64 */
70 {0, 7812}, /* x128 */
71 };
72
73 static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
74 {1, 0}, /* x1 */
75 {0, 500000}, /* x2 */
76 {0, 125000}, /* x4 */
77 };
78
79 enum rpr0521_channel {
80 RPR0521_CHAN_ALS_DATA0,
81 RPR0521_CHAN_ALS_DATA1,
82 RPR0521_CHAN_PXS,
83 };
84
85 struct rpr0521_reg_desc {
86 u8 address;
87 u8 device_mask;
88 };
89
90 static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
91 [RPR0521_CHAN_ALS_DATA0] = {
92 .address = RPR0521_REG_ALS_DATA0,
93 .device_mask = RPR0521_MODE_ALS_MASK,
94 },
95 [RPR0521_CHAN_ALS_DATA1] = {
96 .address = RPR0521_REG_ALS_DATA1,
97 .device_mask = RPR0521_MODE_ALS_MASK,
98 },
99 [RPR0521_CHAN_PXS] = {
100 .address = RPR0521_REG_PXS_DATA,
101 .device_mask = RPR0521_MODE_PXS_MASK,
102 },
103 };
104
105 static const struct rpr0521_gain_info {
106 u8 reg;
107 u8 mask;
108 u8 shift;
109 const struct rpr0521_gain *gain;
110 int size;
111 } rpr0521_gain[] = {
112 [RPR0521_CHAN_ALS_DATA0] = {
113 .reg = RPR0521_REG_ALS_CTRL,
114 .mask = RPR0521_ALS_DATA0_GAIN_MASK,
115 .shift = RPR0521_ALS_DATA0_GAIN_SHIFT,
116 .gain = rpr0521_als_gain,
117 .size = ARRAY_SIZE(rpr0521_als_gain),
118 },
119 [RPR0521_CHAN_ALS_DATA1] = {
120 .reg = RPR0521_REG_ALS_CTRL,
121 .mask = RPR0521_ALS_DATA1_GAIN_MASK,
122 .shift = RPR0521_ALS_DATA1_GAIN_SHIFT,
123 .gain = rpr0521_als_gain,
124 .size = ARRAY_SIZE(rpr0521_als_gain),
125 },
126 [RPR0521_CHAN_PXS] = {
127 .reg = RPR0521_REG_PXS_CTRL,
128 .mask = RPR0521_PXS_GAIN_MASK,
129 .shift = RPR0521_PXS_GAIN_SHIFT,
130 .gain = rpr0521_pxs_gain,
131 .size = ARRAY_SIZE(rpr0521_pxs_gain),
132 },
133 };
134
135 struct rpr0521_data {
136 struct i2c_client *client;
137
138 /* protect device params updates (e.g state, gain) */
139 struct mutex lock;
140
141 /* device active status */
142 bool als_dev_en;
143 bool pxs_dev_en;
144
145 /* optimize runtime pm ops - enable device only if needed */
146 bool als_ps_need_en;
147 bool pxs_ps_need_en;
148
149 struct regmap *regmap;
150 };
151
152 static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
153 static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
154
155 static struct attribute *rpr0521_attributes[] = {
156 &iio_const_attr_in_intensity_scale_available.dev_attr.attr,
157 &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
158 NULL,
159 };
160
161 static const struct attribute_group rpr0521_attribute_group = {
162 .attrs = rpr0521_attributes,
163 };
164
165 static const struct iio_chan_spec rpr0521_channels[] = {
166 {
167 .type = IIO_INTENSITY,
168 .modified = 1,
169 .address = RPR0521_CHAN_ALS_DATA0,
170 .channel2 = IIO_MOD_LIGHT_BOTH,
171 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
172 BIT(IIO_CHAN_INFO_SCALE),
173 },
174 {
175 .type = IIO_INTENSITY,
176 .modified = 1,
177 .address = RPR0521_CHAN_ALS_DATA1,
178 .channel2 = IIO_MOD_LIGHT_IR,
179 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
180 BIT(IIO_CHAN_INFO_SCALE),
181 },
182 {
183 .type = IIO_PROXIMITY,
184 .address = RPR0521_CHAN_PXS,
185 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
186 BIT(IIO_CHAN_INFO_SCALE),
187 }
188 };
189
190 static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
191 {
192 int ret;
193
194 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
195 RPR0521_MODE_ALS_MASK,
196 status);
197 if (ret < 0)
198 return ret;
199
200 if (status & RPR0521_MODE_ALS_MASK)
201 data->als_dev_en = true;
202 else
203 data->als_dev_en = false;
204
205 return 0;
206 }
207
208 static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
209 {
210 int ret;
211
212 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
213 RPR0521_MODE_PXS_MASK,
214 status);
215 if (ret < 0)
216 return ret;
217
218 if (status & RPR0521_MODE_PXS_MASK)
219 data->pxs_dev_en = true;
220 else
221 data->pxs_dev_en = false;
222
223 return 0;
224 }
225
226 /**
227 * rpr0521_set_power_state - handles runtime PM state and sensors enabled status
228 *
229 * @data: rpr0521 device private data
230 * @on: state to be set for devices in @device_mask
231 * @device_mask: bitmask specifying for which device we need to update @on state
232 *
233 * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but
234 * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to
235 * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable
236 * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not
237 * be called twice.
238 */
239 static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
240 u8 device_mask)
241 {
242 #ifdef CONFIG_PM
243 int ret;
244 u8 update_mask = 0;
245
246 if (device_mask & RPR0521_MODE_ALS_MASK) {
247 if (on && !data->als_ps_need_en && data->pxs_dev_en)
248 update_mask |= RPR0521_MODE_ALS_MASK;
249 else
250 data->als_ps_need_en = on;
251 }
252
253 if (device_mask & RPR0521_MODE_PXS_MASK) {
254 if (on && !data->pxs_ps_need_en && data->als_dev_en)
255 update_mask |= RPR0521_MODE_PXS_MASK;
256 else
257 data->pxs_ps_need_en = on;
258 }
259
260 if (update_mask) {
261 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
262 update_mask, update_mask);
263 if (ret < 0)
264 return ret;
265 }
266
267 if (on) {
268 ret = pm_runtime_get_sync(&data->client->dev);
269 } else {
270 pm_runtime_mark_last_busy(&data->client->dev);
271 ret = pm_runtime_put_autosuspend(&data->client->dev);
272 }
273 if (ret < 0) {
274 dev_err(&data->client->dev,
275 "Failed: rpr0521_set_power_state for %d, ret %d\n",
276 on, ret);
277 if (on)
278 pm_runtime_put_noidle(&data->client->dev);
279
280 return ret;
281 }
282 #endif
283 return 0;
284 }
285
286 static int rpr0521_get_gain(struct rpr0521_data *data, int chan,
287 int *val, int *val2)
288 {
289 int ret, reg, idx;
290
291 ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, &reg);
292 if (ret < 0)
293 return ret;
294
295 idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift;
296 *val = rpr0521_gain[chan].gain[idx].scale;
297 *val2 = rpr0521_gain[chan].gain[idx].uscale;
298
299 return 0;
300 }
301
302 static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
303 int val, int val2)
304 {
305 int i, idx = -EINVAL;
306
307 /* get gain index */
308 for (i = 0; i < rpr0521_gain[chan].size; i++)
309 if (val == rpr0521_gain[chan].gain[i].scale &&
310 val2 == rpr0521_gain[chan].gain[i].uscale) {
311 idx = i;
312 break;
313 }
314
315 if (idx < 0)
316 return idx;
317
318 return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg,
319 rpr0521_gain[chan].mask,
320 idx << rpr0521_gain[chan].shift);
321 }
322
323 static int rpr0521_read_raw(struct iio_dev *indio_dev,
324 struct iio_chan_spec const *chan, int *val,
325 int *val2, long mask)
326 {
327 struct rpr0521_data *data = iio_priv(indio_dev);
328 int ret;
329 u8 device_mask;
330 __le16 raw_data;
331
332 switch (mask) {
333 case IIO_CHAN_INFO_RAW:
334 if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY)
335 return -EINVAL;
336
337 device_mask = rpr0521_data_reg[chan->address].device_mask;
338
339 mutex_lock(&data->lock);
340 ret = rpr0521_set_power_state(data, true, device_mask);
341 if (ret < 0) {
342 mutex_unlock(&data->lock);
343 return ret;
344 }
345
346 ret = regmap_bulk_read(data->regmap,
347 rpr0521_data_reg[chan->address].address,
348 &raw_data, 2);
349 if (ret < 0) {
350 rpr0521_set_power_state(data, false, device_mask);
351 mutex_unlock(&data->lock);
352 return ret;
353 }
354
355 ret = rpr0521_set_power_state(data, false, device_mask);
356 mutex_unlock(&data->lock);
357 if (ret < 0)
358 return ret;
359
360 *val = le16_to_cpu(raw_data);
361
362 return IIO_VAL_INT;
363 case IIO_CHAN_INFO_SCALE:
364 mutex_lock(&data->lock);
365 ret = rpr0521_get_gain(data, chan->address, val, val2);
366 mutex_unlock(&data->lock);
367 if (ret < 0)
368 return ret;
369
370 return IIO_VAL_INT_PLUS_MICRO;
371 default:
372 return -EINVAL;
373 }
374 }
375
376 static int rpr0521_write_raw(struct iio_dev *indio_dev,
377 struct iio_chan_spec const *chan, int val,
378 int val2, long mask)
379 {
380 struct rpr0521_data *data = iio_priv(indio_dev);
381 int ret;
382
383 switch (mask) {
384 case IIO_CHAN_INFO_SCALE:
385 mutex_lock(&data->lock);
386 ret = rpr0521_set_gain(data, chan->address, val, val2);
387 mutex_unlock(&data->lock);
388
389 return ret;
390 default:
391 return -EINVAL;
392 }
393 }
394
395 static const struct iio_info rpr0521_info = {
396 .driver_module = THIS_MODULE,
397 .read_raw = rpr0521_read_raw,
398 .write_raw = rpr0521_write_raw,
399 .attrs = &rpr0521_attribute_group,
400 };
401
402 static int rpr0521_init(struct rpr0521_data *data)
403 {
404 int ret;
405 int id;
406
407 ret = regmap_read(data->regmap, RPR0521_REG_ID, &id);
408 if (ret < 0) {
409 dev_err(&data->client->dev, "Failed to read REG_ID register\n");
410 return ret;
411 }
412
413 if (id != RPR0521_MANUFACT_ID) {
414 dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
415 id, RPR0521_MANUFACT_ID);
416 return -ENODEV;
417 }
418
419 /* set default measurement time - 100 ms for both ALS and PS */
420 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
421 RPR0521_MODE_MEAS_TIME_MASK,
422 RPR0521_DEFAULT_MEAS_TIME);
423 if (ret) {
424 pr_err("regmap_update_bits returned %d\n", ret);
425 return ret;
426 }
427
428 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
429 if (ret < 0)
430 return ret;
431 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
432 if (ret < 0)
433 return ret;
434
435 return 0;
436 }
437
438 static int rpr0521_poweroff(struct rpr0521_data *data)
439 {
440 int ret;
441
442 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
443 RPR0521_MODE_ALS_MASK |
444 RPR0521_MODE_PXS_MASK,
445 RPR0521_MODE_ALS_DISABLE |
446 RPR0521_MODE_PXS_DISABLE);
447 if (ret < 0)
448 return ret;
449
450 data->als_dev_en = false;
451 data->pxs_dev_en = false;
452
453 return 0;
454 }
455
456 static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg)
457 {
458 switch (reg) {
459 case RPR0521_REG_MODE_CTRL:
460 case RPR0521_REG_ALS_CTRL:
461 case RPR0521_REG_PXS_CTRL:
462 return false;
463 default:
464 return true;
465 }
466 }
467
468 static const struct regmap_config rpr0521_regmap_config = {
469 .name = RPR0521_REGMAP_NAME,
470
471 .reg_bits = 8,
472 .val_bits = 8,
473
474 .max_register = RPR0521_REG_ID,
475 .cache_type = REGCACHE_RBTREE,
476 .volatile_reg = rpr0521_is_volatile_reg,
477 };
478
479 static int rpr0521_probe(struct i2c_client *client,
480 const struct i2c_device_id *id)
481 {
482 struct rpr0521_data *data;
483 struct iio_dev *indio_dev;
484 struct regmap *regmap;
485 int ret;
486
487 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
488 if (!indio_dev)
489 return -ENOMEM;
490
491 regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config);
492 if (IS_ERR(regmap)) {
493 dev_err(&client->dev, "regmap_init failed!\n");
494 return PTR_ERR(regmap);
495 }
496
497 data = iio_priv(indio_dev);
498 i2c_set_clientdata(client, indio_dev);
499 data->client = client;
500 data->regmap = regmap;
501
502 mutex_init(&data->lock);
503
504 indio_dev->dev.parent = &client->dev;
505 indio_dev->info = &rpr0521_info;
506 indio_dev->name = RPR0521_DRV_NAME;
507 indio_dev->channels = rpr0521_channels;
508 indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels);
509 indio_dev->modes = INDIO_DIRECT_MODE;
510
511 ret = rpr0521_init(data);
512 if (ret < 0) {
513 dev_err(&client->dev, "rpr0521 chip init failed\n");
514 return ret;
515 }
516
517 ret = pm_runtime_set_active(&client->dev);
518 if (ret < 0)
519 goto err_poweroff;
520
521 pm_runtime_enable(&client->dev);
522 pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
523 pm_runtime_use_autosuspend(&client->dev);
524
525 ret = iio_device_register(indio_dev);
526 if (ret)
527 goto err_pm_disable;
528
529 return 0;
530
531 err_pm_disable:
532 pm_runtime_disable(&client->dev);
533 pm_runtime_set_suspended(&client->dev);
534 pm_runtime_put_noidle(&client->dev);
535 err_poweroff:
536 rpr0521_poweroff(data);
537
538 return ret;
539 }
540
541 static int rpr0521_remove(struct i2c_client *client)
542 {
543 struct iio_dev *indio_dev = i2c_get_clientdata(client);
544
545 iio_device_unregister(indio_dev);
546
547 pm_runtime_disable(&client->dev);
548 pm_runtime_set_suspended(&client->dev);
549 pm_runtime_put_noidle(&client->dev);
550
551 rpr0521_poweroff(iio_priv(indio_dev));
552
553 return 0;
554 }
555
556 #ifdef CONFIG_PM
557 static int rpr0521_runtime_suspend(struct device *dev)
558 {
559 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
560 struct rpr0521_data *data = iio_priv(indio_dev);
561 int ret;
562
563 /* disable channels and sets {als,pxs}_dev_en to false */
564 mutex_lock(&data->lock);
565 ret = rpr0521_poweroff(data);
566 mutex_unlock(&data->lock);
567
568 return ret;
569 }
570
571 static int rpr0521_runtime_resume(struct device *dev)
572 {
573 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
574 struct rpr0521_data *data = iio_priv(indio_dev);
575 int ret;
576
577 if (data->als_ps_need_en) {
578 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
579 if (ret < 0)
580 return ret;
581 data->als_ps_need_en = false;
582 }
583
584 if (data->pxs_ps_need_en) {
585 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
586 if (ret < 0)
587 return ret;
588 data->pxs_ps_need_en = false;
589 }
590
591 return 0;
592 }
593 #endif
594
595 static const struct dev_pm_ops rpr0521_pm_ops = {
596 SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend,
597 rpr0521_runtime_resume, NULL)
598 };
599
600 static const struct acpi_device_id rpr0521_acpi_match[] = {
601 {"RPR0521", 0},
602 { }
603 };
604 MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match);
605
606 static const struct i2c_device_id rpr0521_id[] = {
607 {"rpr0521", 0},
608 { }
609 };
610
611 MODULE_DEVICE_TABLE(i2c, rpr0521_id);
612
613 static struct i2c_driver rpr0521_driver = {
614 .driver = {
615 .name = RPR0521_DRV_NAME,
616 .pm = &rpr0521_pm_ops,
617 .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
618 },
619 .probe = rpr0521_probe,
620 .remove = rpr0521_remove,
621 .id_table = rpr0521_id,
622 };
623
624 module_i2c_driver(rpr0521_driver);
625
626 MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
627 MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver");
628 MODULE_LICENSE("GPL v2");