1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/module.h>
21#include <linux/i2c.h>
22#include <linux/err.h>
23#include <linux/mutex.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/regmap.h>
27#include <linux/iio/iio.h>
28#include <linux/iio/sysfs.h>
29
30#define CONVERSION_TIME_MS 100
31
32#define ISL29028_REG_CONFIGURE 0x01
33
34#define CONFIGURE_ALS_IR_MODE_ALS 0
35#define CONFIGURE_ALS_IR_MODE_IR BIT(0)
36#define CONFIGURE_ALS_IR_MODE_MASK BIT(0)
37
38#define CONFIGURE_ALS_RANGE_LOW_LUX 0
39#define CONFIGURE_ALS_RANGE_HIGH_LUX BIT(1)
40#define CONFIGURE_ALS_RANGE_MASK BIT(1)
41
42#define CONFIGURE_ALS_DIS 0
43#define CONFIGURE_ALS_EN BIT(2)
44#define CONFIGURE_ALS_EN_MASK BIT(2)
45
46#define CONFIGURE_PROX_DRIVE BIT(3)
47
48#define CONFIGURE_PROX_SLP_SH 4
49#define CONFIGURE_PROX_SLP_MASK (7 << CONFIGURE_PROX_SLP_SH)
50
51#define CONFIGURE_PROX_EN BIT(7)
52#define CONFIGURE_PROX_EN_MASK BIT(7)
53
54#define ISL29028_REG_INTERRUPT 0x02
55
56#define ISL29028_REG_PROX_DATA 0x08
57#define ISL29028_REG_ALSIR_L 0x09
58#define ISL29028_REG_ALSIR_U 0x0A
59
60#define ISL29028_REG_TEST1_MODE 0x0E
61#define ISL29028_REG_TEST2_MODE 0x0F
62
63#define ISL29028_NUM_REGS (ISL29028_REG_TEST2_MODE + 1)
64
65enum als_ir_mode {
66 MODE_NONE = 0,
67 MODE_ALS,
68 MODE_IR
69};
70
71struct isl29028_chip {
72 struct device *dev;
73 struct mutex lock;
74 struct regmap *regmap;
75
76 unsigned int prox_sampling;
77 bool enable_prox;
78
79 int lux_scale;
80 int als_ir_mode;
81};
82
83static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
84 unsigned int sampling)
85{
86 static unsigned int prox_period[] = {800, 400, 200, 100, 75, 50, 12, 0};
87 int sel;
88 unsigned int period = DIV_ROUND_UP(1000, sampling);
89
90 for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) {
91 if (period >= prox_period[sel])
92 break;
93 }
94 return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
95 CONFIGURE_PROX_SLP_MASK, sel << CONFIGURE_PROX_SLP_SH);
96}
97
98static int isl29028_enable_proximity(struct isl29028_chip *chip, bool enable)
99{
100 int ret;
101 int val = 0;
102
103 if (enable)
104 val = CONFIGURE_PROX_EN;
105 ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
106 CONFIGURE_PROX_EN_MASK, val);
107 if (ret < 0)
108 return ret;
109
110
111 mdelay(DIV_ROUND_UP(1000, chip->prox_sampling));
112 return 0;
113}
114
115static int isl29028_set_als_scale(struct isl29028_chip *chip, int lux_scale)
116{
117 int val = (lux_scale == 2000) ? CONFIGURE_ALS_RANGE_HIGH_LUX :
118 CONFIGURE_ALS_RANGE_LOW_LUX;
119
120 return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
121 CONFIGURE_ALS_RANGE_MASK, val);
122}
123
124static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
125 enum als_ir_mode mode)
126{
127 int ret = 0;
128
129 switch (mode) {
130 case MODE_ALS:
131 ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
132 CONFIGURE_ALS_IR_MODE_MASK,
133 CONFIGURE_ALS_IR_MODE_ALS);
134 if (ret < 0)
135 return ret;
136
137 ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
138 CONFIGURE_ALS_RANGE_MASK,
139 CONFIGURE_ALS_RANGE_HIGH_LUX);
140 break;
141
142 case MODE_IR:
143 ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
144 CONFIGURE_ALS_IR_MODE_MASK,
145 CONFIGURE_ALS_IR_MODE_IR);
146 break;
147
148 case MODE_NONE:
149 return regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
150 CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_DIS);
151 }
152
153 if (ret < 0)
154 return ret;
155
156
157 ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
158 CONFIGURE_ALS_EN_MASK, CONFIGURE_ALS_EN);
159 if (ret < 0)
160 return ret;
161
162
163 mdelay(CONVERSION_TIME_MS);
164 return 0;
165}
166
167static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
168{
169 unsigned int lsb;
170 unsigned int msb;
171 int ret;
172
173 ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
174 if (ret < 0) {
175 dev_err(chip->dev,
176 "Error in reading register ALSIR_L err %d\n", ret);
177 return ret;
178 }
179
180 ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
181 if (ret < 0) {
182 dev_err(chip->dev,
183 "Error in reading register ALSIR_U err %d\n", ret);
184 return ret;
185 }
186
187 *als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF);
188 return 0;
189}
190
191static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
192{
193 unsigned int data;
194 int ret;
195
196 ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
197 if (ret < 0) {
198 dev_err(chip->dev, "Error in reading register %d, error %d\n",
199 ISL29028_REG_PROX_DATA, ret);
200 return ret;
201 }
202 *prox = data;
203 return 0;
204}
205
206static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data)
207{
208 int ret;
209
210 if (!chip->enable_prox) {
211 ret = isl29028_enable_proximity(chip, true);
212 if (ret < 0)
213 return ret;
214 chip->enable_prox = true;
215 }
216 return isl29028_read_proxim(chip, prox_data);
217}
218
219static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
220{
221 int ret;
222 int als_ir_data;
223
224 if (chip->als_ir_mode != MODE_ALS) {
225 ret = isl29028_set_als_ir_mode(chip, MODE_ALS);
226 if (ret < 0) {
227 dev_err(chip->dev,
228 "Error in enabling ALS mode err %d\n", ret);
229 return ret;
230 }
231 chip->als_ir_mode = MODE_ALS;
232 }
233
234 ret = isl29028_read_als_ir(chip, &als_ir_data);
235 if (ret < 0)
236 return ret;
237
238
239
240
241
242
243 if (chip->lux_scale == 125)
244 als_ir_data = (als_ir_data * 31) / 1000;
245 else
246 als_ir_data = (als_ir_data * 49) / 100;
247
248 *als_data = als_ir_data;
249 return 0;
250}
251
252static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
253{
254 int ret;
255
256 if (chip->als_ir_mode != MODE_IR) {
257 ret = isl29028_set_als_ir_mode(chip, MODE_IR);
258 if (ret < 0) {
259 dev_err(chip->dev,
260 "Error in enabling IR mode err %d\n", ret);
261 return ret;
262 }
263 chip->als_ir_mode = MODE_IR;
264 }
265 return isl29028_read_als_ir(chip, ir_data);
266}
267
268
269static int isl29028_write_raw(struct iio_dev *indio_dev,
270 struct iio_chan_spec const *chan,
271 int val, int val2, long mask)
272{
273 struct isl29028_chip *chip = iio_priv(indio_dev);
274 int ret = -EINVAL;
275
276 mutex_lock(&chip->lock);
277 switch (chan->type) {
278 case IIO_PROXIMITY:
279 if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
280 dev_err(chip->dev,
281 "proximity: mask value 0x%08lx not supported\n",
282 mask);
283 break;
284 }
285 if (val < 1 || val > 100) {
286 dev_err(chip->dev,
287 "Samp_freq %d is not in range[1:100]\n", val);
288 break;
289 }
290 ret = isl29028_set_proxim_sampling(chip, val);
291 if (ret < 0) {
292 dev_err(chip->dev,
293 "Setting proximity samp_freq fail, err %d\n",
294 ret);
295 break;
296 }
297 chip->prox_sampling = val;
298 break;
299
300 case IIO_LIGHT:
301 if (mask != IIO_CHAN_INFO_SCALE) {
302 dev_err(chip->dev,
303 "light: mask value 0x%08lx not supported\n",
304 mask);
305 break;
306 }
307 if ((val != 125) && (val != 2000)) {
308 dev_err(chip->dev,
309 "lux scale %d is invalid [125, 2000]\n", val);
310 break;
311 }
312 ret = isl29028_set_als_scale(chip, val);
313 if (ret < 0) {
314 dev_err(chip->dev,
315 "Setting lux scale fail with error %d\n", ret);
316 break;
317 }
318 chip->lux_scale = val;
319 break;
320
321 default:
322 dev_err(chip->dev, "Unsupported channel type\n");
323 break;
324 }
325 mutex_unlock(&chip->lock);
326 return ret;
327}
328
329static int isl29028_read_raw(struct iio_dev *indio_dev,
330 struct iio_chan_spec const *chan,
331 int *val, int *val2, long mask)
332{
333 struct isl29028_chip *chip = iio_priv(indio_dev);
334 int ret = -EINVAL;
335
336 mutex_lock(&chip->lock);
337 switch (mask) {
338 case IIO_CHAN_INFO_RAW:
339 case IIO_CHAN_INFO_PROCESSED:
340 switch (chan->type) {
341 case IIO_LIGHT:
342 ret = isl29028_als_get(chip, val);
343 break;
344 case IIO_INTENSITY:
345 ret = isl29028_ir_get(chip, val);
346 break;
347 case IIO_PROXIMITY:
348 ret = isl29028_proxim_get(chip, val);
349 break;
350 default:
351 break;
352 }
353 if (ret < 0)
354 break;
355 ret = IIO_VAL_INT;
356 break;
357
358 case IIO_CHAN_INFO_SAMP_FREQ:
359 if (chan->type != IIO_PROXIMITY)
360 break;
361 *val = chip->prox_sampling;
362 ret = IIO_VAL_INT;
363 break;
364
365 case IIO_CHAN_INFO_SCALE:
366 if (chan->type != IIO_LIGHT)
367 break;
368 *val = chip->lux_scale;
369 ret = IIO_VAL_INT;
370 break;
371
372 default:
373 dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask);
374 break;
375 }
376 mutex_unlock(&chip->lock);
377 return ret;
378}
379
380static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
381 "1, 3, 5, 10, 13, 20, 83, 100");
382static IIO_CONST_ATTR(in_illuminance_scale_available, "125, 2000");
383
384#define ISL29028_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
385#define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
386static struct attribute *isl29028_attributes[] = {
387 ISL29028_CONST_ATTR(in_proximity_sampling_frequency_available),
388 ISL29028_CONST_ATTR(in_illuminance_scale_available),
389 NULL,
390};
391
392static const struct attribute_group isl29108_group = {
393 .attrs = isl29028_attributes,
394};
395
396static const struct iio_chan_spec isl29028_channels[] = {
397 {
398 .type = IIO_LIGHT,
399 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
400 BIT(IIO_CHAN_INFO_SCALE),
401 }, {
402 .type = IIO_INTENSITY,
403 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
404 }, {
405 .type = IIO_PROXIMITY,
406 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
407 BIT(IIO_CHAN_INFO_SAMP_FREQ),
408 }
409};
410
411static const struct iio_info isl29028_info = {
412 .attrs = &isl29108_group,
413 .driver_module = THIS_MODULE,
414 .read_raw = isl29028_read_raw,
415 .write_raw = isl29028_write_raw,
416};
417
418static int isl29028_chip_init(struct isl29028_chip *chip)
419{
420 int ret;
421
422 chip->enable_prox = false;
423 chip->prox_sampling = 20;
424 chip->lux_scale = 2000;
425 chip->als_ir_mode = MODE_NONE;
426
427 ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
428 if (ret < 0) {
429 dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
430 __func__, ISL29028_REG_TEST1_MODE, ret);
431 return ret;
432 }
433 ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
434 if (ret < 0) {
435 dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
436 __func__, ISL29028_REG_TEST2_MODE, ret);
437 return ret;
438 }
439
440 ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
441 if (ret < 0) {
442 dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
443 __func__, ISL29028_REG_CONFIGURE, ret);
444 return ret;
445 }
446
447 ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
448 if (ret < 0) {
449 dev_err(chip->dev, "setting the proximity, err = %d\n",
450 ret);
451 return ret;
452 }
453
454 ret = isl29028_set_als_scale(chip, chip->lux_scale);
455 if (ret < 0)
456 dev_err(chip->dev,
457 "setting als scale failed, err = %d\n", ret);
458 return ret;
459}
460
461static bool is_volatile_reg(struct device *dev, unsigned int reg)
462{
463 switch (reg) {
464 case ISL29028_REG_INTERRUPT:
465 case ISL29028_REG_PROX_DATA:
466 case ISL29028_REG_ALSIR_L:
467 case ISL29028_REG_ALSIR_U:
468 return true;
469 default:
470 return false;
471 }
472}
473
474static const struct regmap_config isl29028_regmap_config = {
475 .reg_bits = 8,
476 .val_bits = 8,
477 .volatile_reg = is_volatile_reg,
478 .max_register = ISL29028_NUM_REGS - 1,
479 .num_reg_defaults_raw = ISL29028_NUM_REGS,
480 .cache_type = REGCACHE_RBTREE,
481};
482
483static int isl29028_probe(struct i2c_client *client,
484 const struct i2c_device_id *id)
485{
486 struct isl29028_chip *chip;
487 struct iio_dev *indio_dev;
488 int ret;
489
490 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
491 if (!indio_dev) {
492 dev_err(&client->dev, "iio allocation fails\n");
493 return -ENOMEM;
494 }
495
496 chip = iio_priv(indio_dev);
497
498 i2c_set_clientdata(client, indio_dev);
499 chip->dev = &client->dev;
500 mutex_init(&chip->lock);
501
502 chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
503 if (IS_ERR(chip->regmap)) {
504 ret = PTR_ERR(chip->regmap);
505 dev_err(chip->dev, "regmap initialization failed: %d\n", ret);
506 return ret;
507 }
508
509 ret = isl29028_chip_init(chip);
510 if (ret < 0) {
511 dev_err(chip->dev, "chip initialization failed: %d\n", ret);
512 return ret;
513 }
514
515 indio_dev->info = &isl29028_info;
516 indio_dev->channels = isl29028_channels;
517 indio_dev->num_channels = ARRAY_SIZE(isl29028_channels);
518 indio_dev->name = id->name;
519 indio_dev->dev.parent = &client->dev;
520 indio_dev->modes = INDIO_DIRECT_MODE;
521 ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
522 if (ret < 0) {
523 dev_err(chip->dev, "iio registration fails with error %d\n",
524 ret);
525 return ret;
526 }
527 return 0;
528}
529
530static const struct i2c_device_id isl29028_id[] = {
531 {"isl29028", 0},
532 {}
533};
534MODULE_DEVICE_TABLE(i2c, isl29028_id);
535
536static const struct of_device_id isl29028_of_match[] = {
537 { .compatible = "isl,isl29028", },
538 { .compatible = "isil,isl29028", },
539 { },
540};
541MODULE_DEVICE_TABLE(of, isl29028_of_match);
542
543static struct i2c_driver isl29028_driver = {
544 .class = I2C_CLASS_HWMON,
545 .driver = {
546 .name = "isl29028",
547 .of_match_table = isl29028_of_match,
548 },
549 .probe = isl29028_probe,
550 .id_table = isl29028_id,
551};
552
553module_i2c_driver(isl29028_driver);
554
555MODULE_DESCRIPTION("ISL29028 Ambient Light and Proximity Sensor driver");
556MODULE_LICENSE("GPL v2");
557MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
558