blob: a767a43c995c1ee56dddf0da55a03ce838333175 [file] [log] [blame]
Rhyland Klein94042872010-10-07 15:48:09 -07001/*
Laurentiu Palcu609acef2014-08-29 15:26:00 +01002 * A iio driver for the light sensor ISL 29018/29023/29035.
Rhyland Klein94042872010-10-07 15:48:09 -07003 *
4 * IIO driver for monitoring ambient light intensity in luxi, proximity
5 * sensing and infrared sensing.
6 *
7 * Copyright (c) 2010, NVIDIA Corporation.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
Rhyland Klein94042872010-10-07 15:48:09 -070018 */
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>
Laxman Dewangan057340e2012-04-20 12:57:38 +053025#include <linux/regmap.h>
Rhyland Klein94042872010-10-07 15:48:09 -070026#include <linux/slab.h>
Jonathan Cameron06458e22012-04-25 15:54:58 +010027#include <linux/iio/iio.h>
28#include <linux/iio/sysfs.h>
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +000029#include <linux/acpi.h>
Laxman Dewangan057340e2012-04-20 12:57:38 +053030
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +020031#define ISL29018_CONV_TIME_MS 100
Rhyland Klein94042872010-10-07 15:48:09 -070032
33#define ISL29018_REG_ADD_COMMAND1 0x00
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +020034#define ISL29018_CMD1_OPMODE_SHIFT 5
35#define ISL29018_CMD1_OPMODE_MASK (7 << ISL29018_CMD1_OPMODE_SHIFT)
36#define ISL29018_CMD1_OPMODE_POWER_DOWN 0
37#define ISL29018_CMD1_OPMODE_ALS_ONCE 1
38#define ISL29018_CMD1_OPMODE_IR_ONCE 2
39#define ISL29018_CMD1_OPMODE_PROX_ONCE 3
Rhyland Klein94042872010-10-07 15:48:09 -070040
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +020041#define ISL29018_REG_ADD_COMMAND2 0x01
42#define ISL29018_CMD2_RESOLUTION_SHIFT 2
43#define ISL29018_CMD2_RESOLUTION_MASK (0x3 << ISL29018_CMD2_RESOLUTION_SHIFT)
Rhyland Klein94042872010-10-07 15:48:09 -070044
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +020045#define ISL29018_CMD2_RANGE_SHIFT 0
46#define ISL29018_CMD2_RANGE_MASK (0x3 << ISL29018_CMD2_RANGE_SHIFT)
Rhyland Klein94042872010-10-07 15:48:09 -070047
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +020048#define ISL29018_CMD2_SCHEME_SHIFT 7
49#define ISL29018_CMD2_SCHEME_MASK (0x1 << ISL29018_CMD2_SCHEME_SHIFT)
Rhyland Klein94042872010-10-07 15:48:09 -070050
51#define ISL29018_REG_ADD_DATA_LSB 0x02
52#define ISL29018_REG_ADD_DATA_MSB 0x03
Rhyland Klein94042872010-10-07 15:48:09 -070053
Grant Grundler176f9f22011-08-09 15:18:14 -070054#define ISL29018_REG_TEST 0x08
55#define ISL29018_TEST_SHIFT 0
56#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
57
Laurentiu Palcu609acef2014-08-29 15:26:00 +010058#define ISL29035_REG_DEVICE_ID 0x0F
59#define ISL29035_DEVICE_ID_SHIFT 0x03
60#define ISL29035_DEVICE_ID_MASK (0x7 << ISL29035_DEVICE_ID_SHIFT)
61#define ISL29035_DEVICE_ID 0x5
62#define ISL29035_BOUT_SHIFT 0x07
63#define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT)
64
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +030065#define ISL29018_INT_TIME_AVAIL "0.090000 0.005630 0.000351 0.000021"
66#define ISL29023_INT_TIME_AVAIL "0.090000 0.005600 0.000352 0.000022"
67#define ISL29035_INT_TIME_AVAIL "0.105000 0.006500 0.000410 0.000025"
68
69static const char * const int_time_avail[] = {
70 ISL29018_INT_TIME_AVAIL,
71 ISL29023_INT_TIME_AVAIL,
72 ISL29035_INT_TIME_AVAIL,
73};
74
75enum isl29018_int_time {
76 ISL29018_INT_TIME_16,
77 ISL29018_INT_TIME_12,
78 ISL29018_INT_TIME_8,
79 ISL29018_INT_TIME_4,
80};
81
82static const unsigned int isl29018_int_utimes[3][4] = {
83 {90000, 5630, 351, 21},
84 {90000, 5600, 352, 22},
85 {105000, 6500, 410, 25},
86};
87
88static const struct isl29018_scale {
89 unsigned int scale;
90 unsigned int uscale;
91} isl29018_scales[4][4] = {
92 { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} },
93 { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} },
94 { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} },
95 { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} }
96};
97
Rhyland Klein94042872010-10-07 15:48:09 -070098struct isl29018_chip {
Laxman Dewangan057340e2012-04-20 12:57:38 +053099 struct regmap *regmap;
Rhyland Klein94042872010-10-07 15:48:09 -0700100 struct mutex lock;
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100101 int type;
Roberta Dobrescu809a5912015-04-16 22:20:58 +0300102 unsigned int calibscale;
103 unsigned int ucalibscale;
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300104 unsigned int int_time;
105 struct isl29018_scale scale;
Rhyland Klein94042872010-10-07 15:48:09 -0700106 int prox_scheme;
Bryan Freed1e45cf32012-10-25 00:39:00 +0100107 bool suspended;
Rhyland Klein94042872010-10-07 15:48:09 -0700108};
109
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300110static int isl29018_set_integration_time(struct isl29018_chip *chip,
111 unsigned int utime)
Rhyland Klein94042872010-10-07 15:48:09 -0700112{
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300113 int i, ret;
114 unsigned int int_time, new_int_time;
Rhyland Klein94042872010-10-07 15:48:09 -0700115
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300116 for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) {
117 if (utime == isl29018_int_utimes[chip->type][i]) {
118 new_int_time = i;
Rhyland Klein94042872010-10-07 15:48:09 -0700119 break;
120 }
121 }
122
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300123 if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type]))
Rhyland Klein94042872010-10-07 15:48:09 -0700124 return -EINVAL;
125
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200126 ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
127 ISL29018_CMD2_RESOLUTION_MASK,
128 i << ISL29018_CMD2_RESOLUTION_SHIFT);
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300129 if (ret < 0)
130 return ret;
131
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200132 /* Keep the same range when integration time changes */
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300133 int_time = chip->int_time;
134 for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) {
135 if (chip->scale.scale == isl29018_scales[int_time][i].scale &&
136 chip->scale.uscale == isl29018_scales[int_time][i].uscale) {
137 chip->scale = isl29018_scales[new_int_time][i];
138 break;
139 }
140 }
141 chip->int_time = new_int_time;
142
143 return 0;
Rhyland Klein94042872010-10-07 15:48:09 -0700144}
145
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300146static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale)
Rhyland Klein94042872010-10-07 15:48:09 -0700147{
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300148 int i, ret;
149 struct isl29018_scale new_scale;
Rhyland Klein94042872010-10-07 15:48:09 -0700150
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300151 for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) {
152 if (scale == isl29018_scales[chip->int_time][i].scale &&
153 uscale == isl29018_scales[chip->int_time][i].uscale) {
154 new_scale = isl29018_scales[chip->int_time][i];
Rhyland Klein94042872010-10-07 15:48:09 -0700155 break;
156 }
157 }
158
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300159 if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time]))
Rhyland Klein94042872010-10-07 15:48:09 -0700160 return -EINVAL;
161
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200162 ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
163 ISL29018_CMD2_RANGE_MASK,
164 i << ISL29018_CMD2_RANGE_SHIFT);
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300165 if (ret < 0)
166 return ret;
167
168 chip->scale = new_scale;
169
170 return 0;
Rhyland Klein94042872010-10-07 15:48:09 -0700171}
172
Laxman Dewangan057340e2012-04-20 12:57:38 +0530173static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
Rhyland Klein94042872010-10-07 15:48:09 -0700174{
175 int status;
Laxman Dewangan057340e2012-04-20 12:57:38 +0530176 unsigned int lsb;
177 unsigned int msb;
Alison Schofield64670862016-02-22 12:34:32 -0800178 struct device *dev = regmap_get_device(chip->regmap);
Rhyland Klein94042872010-10-07 15:48:09 -0700179
180 /* Set mode */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530181 status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200182 mode << ISL29018_CMD1_OPMODE_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -0700183 if (status) {
Alison Schofield64670862016-02-22 12:34:32 -0800184 dev_err(dev,
Laxman Dewangan057340e2012-04-20 12:57:38 +0530185 "Error in setting operating mode err %d\n", status);
Rhyland Klein94042872010-10-07 15:48:09 -0700186 return status;
187 }
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200188 msleep(ISL29018_CONV_TIME_MS);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530189 status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
190 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800191 dev_err(dev,
Laxman Dewangan057340e2012-04-20 12:57:38 +0530192 "Error in reading LSB DATA with err %d\n", status);
193 return status;
Rhyland Klein94042872010-10-07 15:48:09 -0700194 }
195
Laxman Dewangan057340e2012-04-20 12:57:38 +0530196 status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
197 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800198 dev_err(dev,
Laxman Dewangan057340e2012-04-20 12:57:38 +0530199 "Error in reading MSB DATA with error %d\n", status);
200 return status;
Rhyland Klein94042872010-10-07 15:48:09 -0700201 }
Alison Schofield64670862016-02-22 12:34:32 -0800202 dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
Rhyland Klein94042872010-10-07 15:48:09 -0700203
204 return (msb << 8) | lsb;
205}
206
Laxman Dewangan057340e2012-04-20 12:57:38 +0530207static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
Rhyland Klein94042872010-10-07 15:48:09 -0700208{
209 int lux_data;
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300210 unsigned int data_x_range;
Rhyland Klein94042872010-10-07 15:48:09 -0700211
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200212 lux_data = isl29018_read_sensor_input(chip,
213 ISL29018_CMD1_OPMODE_ALS_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700214 if (lux_data < 0)
215 return lux_data;
216
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300217 data_x_range = lux_data * chip->scale.scale +
218 lux_data * chip->scale.uscale / 1000000;
219 *lux = data_x_range * chip->calibscale +
220 data_x_range * chip->ucalibscale / 1000000;
Rhyland Klein94042872010-10-07 15:48:09 -0700221
222 return 0;
223}
224
Laxman Dewangan057340e2012-04-20 12:57:38 +0530225static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
Rhyland Klein94042872010-10-07 15:48:09 -0700226{
227 int ir_data;
228
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200229 ir_data = isl29018_read_sensor_input(chip,
230 ISL29018_CMD1_OPMODE_IR_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700231 if (ir_data < 0)
232 return ir_data;
233
234 *ir = ir_data;
235
236 return 0;
237}
238
Laxman Dewangan057340e2012-04-20 12:57:38 +0530239static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800240 int *near_ir)
Rhyland Klein94042872010-10-07 15:48:09 -0700241{
242 int status;
243 int prox_data = -1;
244 int ir_data = -1;
Alison Schofield64670862016-02-22 12:34:32 -0800245 struct device *dev = regmap_get_device(chip->regmap);
Rhyland Klein94042872010-10-07 15:48:09 -0700246
247 /* Do proximity sensing with required scheme */
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200248 status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
249 ISL29018_CMD2_SCHEME_MASK,
250 scheme << ISL29018_CMD2_SCHEME_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -0700251 if (status) {
Alison Schofield64670862016-02-22 12:34:32 -0800252 dev_err(dev, "Error in setting operating mode\n");
Rhyland Klein94042872010-10-07 15:48:09 -0700253 return status;
254 }
255
Laxman Dewangan057340e2012-04-20 12:57:38 +0530256 prox_data = isl29018_read_sensor_input(chip,
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200257 ISL29018_CMD1_OPMODE_PROX_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700258 if (prox_data < 0)
259 return prox_data;
260
261 if (scheme == 1) {
262 *near_ir = prox_data;
263 return 0;
264 }
265
Peter Meerwald-Stadler13e6d632016-07-05 13:55:36 +0200266 ir_data = isl29018_read_sensor_input(chip,
267 ISL29018_CMD1_OPMODE_IR_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700268 if (ir_data < 0)
269 return ir_data;
270
271 if (prox_data >= ir_data)
272 *near_ir = prox_data - ir_data;
273 else
274 *near_ir = 0;
275
276 return 0;
277}
278
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200279static ssize_t isl29018_show_scale_available(struct device *dev,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800280 struct device_attribute *attr, char *buf)
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300281{
282 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
283 struct isl29018_chip *chip = iio_priv(indio_dev);
284 int i, len = 0;
285
286 for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i)
287 len += sprintf(buf + len, "%d.%06d ",
288 isl29018_scales[chip->int_time][i].scale,
289 isl29018_scales[chip->int_time][i].uscale);
290
291 buf[len - 1] = '\n';
292
293 return len;
294}
295
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200296static ssize_t isl29018_show_int_time_available(struct device *dev,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800297 struct device_attribute *attr, char *buf)
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300298{
299 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
300 struct isl29018_chip *chip = iio_priv(indio_dev);
301 int i, len = 0;
302
303 for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i)
304 len += sprintf(buf + len, "0.%06d ",
305 isl29018_int_utimes[chip->type][i]);
306
307 buf[len - 1] = '\n';
308
309 return len;
310}
311
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200312static ssize_t isl29018_show_prox_infrared_suppression(struct device *dev,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800313 struct device_attribute *attr,
314 char *buf)
Rhyland Klein94042872010-10-07 15:48:09 -0700315{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200316 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100317 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700318
Eva Rachel Retuya7f3829a2016-02-18 15:35:38 +0800319 /*
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200320 * Return the "proximity scheme" i.e. if the chip does on chip
Eva Rachel Retuya7f3829a2016-02-18 15:35:38 +0800321 * infrared suppression (1 means perform on chip suppression)
322 */
Rhyland Klein94042872010-10-07 15:48:09 -0700323 return sprintf(buf, "%d\n", chip->prox_scheme);
324}
325
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200326static ssize_t isl29018_store_prox_infrared_suppression(struct device *dev,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800327 struct device_attribute *attr,
328 const char *buf, size_t count)
Rhyland Klein94042872010-10-07 15:48:09 -0700329{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200330 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100331 struct isl29018_chip *chip = iio_priv(indio_dev);
Jingoo Hane5e26dd2013-08-20 03:31:00 +0100332 int val;
Rhyland Klein94042872010-10-07 15:48:09 -0700333
Jingoo Hane5e26dd2013-08-20 03:31:00 +0100334 if (kstrtoint(buf, 10, &val))
Rhyland Klein94042872010-10-07 15:48:09 -0700335 return -EINVAL;
Peter Meerwald-Stadlerab5b9492016-07-05 13:55:37 +0200336 if (!(val == 0 || val == 1))
Rhyland Klein94042872010-10-07 15:48:09 -0700337 return -EINVAL;
Rhyland Klein94042872010-10-07 15:48:09 -0700338
Eva Rachel Retuya7f3829a2016-02-18 15:35:38 +0800339 /*
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200340 * Get the "proximity scheme" i.e. if the chip does on chip
Eva Rachel Retuya7f3829a2016-02-18 15:35:38 +0800341 * infrared suppression (1 means perform on chip suppression)
342 */
Rhyland Klein94042872010-10-07 15:48:09 -0700343 mutex_lock(&chip->lock);
Jingoo Hane5e26dd2013-08-20 03:31:00 +0100344 chip->prox_scheme = val;
Rhyland Klein94042872010-10-07 15:48:09 -0700345 mutex_unlock(&chip->lock);
346
347 return count;
348}
349
Bryan Freed01e57c52011-07-07 12:01:56 -0700350static int isl29018_write_raw(struct iio_dev *indio_dev,
351 struct iio_chan_spec const *chan,
352 int val,
353 int val2,
354 long mask)
Rhyland Klein94042872010-10-07 15:48:09 -0700355{
Bryan Freed01e57c52011-07-07 12:01:56 -0700356 struct isl29018_chip *chip = iio_priv(indio_dev);
357 int ret = -EINVAL;
358
359 mutex_lock(&chip->lock);
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300360 switch (mask) {
361 case IIO_CHAN_INFO_CALIBSCALE:
362 if (chan->type == IIO_LIGHT) {
363 chip->calibscale = val;
364 chip->ucalibscale = val2;
365 ret = 0;
366 }
367 break;
368 case IIO_CHAN_INFO_INT_TIME:
Jonathan Cameronb91617e2015-05-02 12:05:05 +0100369 if (chan->type == IIO_LIGHT) {
Cristina Morarud59b7b62015-10-20 22:55:40 +0300370 if (val) {
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300371 mutex_unlock(&chip->lock);
372 return -EINVAL;
373 }
374 ret = isl29018_set_integration_time(chip, val2);
Jonathan Cameronb91617e2015-05-02 12:05:05 +0100375 }
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300376 break;
377 case IIO_CHAN_INFO_SCALE:
378 if (chan->type == IIO_LIGHT)
379 ret = isl29018_set_scale(chip, val, val2);
380 break;
381 default:
382 break;
Bryan Freed01e57c52011-07-07 12:01:56 -0700383 }
384 mutex_unlock(&chip->lock);
385
Wei Yongjun6dc973d2012-11-08 09:05:00 +0000386 return ret;
Rhyland Klein94042872010-10-07 15:48:09 -0700387}
388
Bryan Freed01e57c52011-07-07 12:01:56 -0700389static int isl29018_read_raw(struct iio_dev *indio_dev,
390 struct iio_chan_spec const *chan,
391 int *val,
392 int *val2,
393 long mask)
Rhyland Klein94042872010-10-07 15:48:09 -0700394{
Bryan Freed01e57c52011-07-07 12:01:56 -0700395 int ret = -EINVAL;
396 struct isl29018_chip *chip = iio_priv(indio_dev);
Bryan Freed01e57c52011-07-07 12:01:56 -0700397
398 mutex_lock(&chip->lock);
Bryan Freed1e45cf32012-10-25 00:39:00 +0100399 if (chip->suspended) {
400 mutex_unlock(&chip->lock);
401 return -EBUSY;
402 }
Bryan Freed01e57c52011-07-07 12:01:56 -0700403 switch (mask) {
Jonathan Cameron90354d02012-04-15 17:41:22 +0100404 case IIO_CHAN_INFO_RAW:
405 case IIO_CHAN_INFO_PROCESSED:
Bryan Freed01e57c52011-07-07 12:01:56 -0700406 switch (chan->type) {
407 case IIO_LIGHT:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530408 ret = isl29018_read_lux(chip, val);
Bryan Freed01e57c52011-07-07 12:01:56 -0700409 break;
410 case IIO_INTENSITY:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530411 ret = isl29018_read_ir(chip, val);
Bryan Freed01e57c52011-07-07 12:01:56 -0700412 break;
413 case IIO_PROXIMITY:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530414 ret = isl29018_read_proximity_ir(chip,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800415 chip->prox_scheme,
416 val);
Bryan Freed01e57c52011-07-07 12:01:56 -0700417 break;
418 default:
419 break;
420 }
421 if (!ret)
422 ret = IIO_VAL_INT;
423 break;
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300424 case IIO_CHAN_INFO_INT_TIME:
425 if (chan->type == IIO_LIGHT) {
426 *val = 0;
427 *val2 = isl29018_int_utimes[chip->type][chip->int_time];
428 ret = IIO_VAL_INT_PLUS_MICRO;
429 }
430 break;
431 case IIO_CHAN_INFO_SCALE:
432 if (chan->type == IIO_LIGHT) {
433 *val = chip->scale.scale;
434 *val2 = chip->scale.uscale;
435 ret = IIO_VAL_INT_PLUS_MICRO;
436 }
437 break;
Jonathan Cameronc8a9f802011-10-26 17:41:36 +0100438 case IIO_CHAN_INFO_CALIBSCALE:
Bryan Freed01e57c52011-07-07 12:01:56 -0700439 if (chan->type == IIO_LIGHT) {
Roberta Dobrescu809a5912015-04-16 22:20:58 +0300440 *val = chip->calibscale;
441 *val2 = chip->ucalibscale;
Bryan Freed932323b2012-09-05 20:55:00 +0100442 ret = IIO_VAL_INT_PLUS_MICRO;
Bryan Freed01e57c52011-07-07 12:01:56 -0700443 }
444 break;
445 default:
446 break;
447 }
448 mutex_unlock(&chip->lock);
449 return ret;
Rhyland Klein94042872010-10-07 15:48:09 -0700450}
451
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100452#define ISL29018_LIGHT_CHANNEL { \
453 .type = IIO_LIGHT, \
454 .indexed = 1, \
455 .channel = 0, \
456 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300457 BIT(IIO_CHAN_INFO_CALIBSCALE) | \
458 BIT(IIO_CHAN_INFO_SCALE) | \
459 BIT(IIO_CHAN_INFO_INT_TIME), \
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100460}
461
462#define ISL29018_IR_CHANNEL { \
463 .type = IIO_INTENSITY, \
464 .modified = 1, \
465 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
466 .channel2 = IIO_MOD_LIGHT_IR, \
467}
468
469#define ISL29018_PROXIMITY_CHANNEL { \
470 .type = IIO_PROXIMITY, \
471 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
472}
473
Bryan Freed01e57c52011-07-07 12:01:56 -0700474static const struct iio_chan_spec isl29018_channels[] = {
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100475 ISL29018_LIGHT_CHANNEL,
476 ISL29018_IR_CHANNEL,
477 ISL29018_PROXIMITY_CHANNEL,
478};
479
480static const struct iio_chan_spec isl29023_channels[] = {
481 ISL29018_LIGHT_CHANNEL,
482 ISL29018_IR_CHANNEL,
Bryan Freed01e57c52011-07-07 12:01:56 -0700483};
Rhyland Klein94042872010-10-07 15:48:09 -0700484
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300485static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200486 isl29018_show_int_time_available, NULL, 0);
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300487static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200488 isl29018_show_scale_available, NULL, 0);
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200489static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression,
Rhyland Klein94042872010-10-07 15:48:09 -0700490 S_IRUGO | S_IWUSR,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200491 isl29018_show_prox_infrared_suppression,
492 isl29018_store_prox_infrared_suppression, 0);
Rhyland Klein94042872010-10-07 15:48:09 -0700493
494#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300495
Rhyland Klein94042872010-10-07 15:48:09 -0700496static struct attribute *isl29018_attributes[] = {
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300497 ISL29018_DEV_ATTR(in_illuminance_scale_available),
498 ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200499 ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression),
Rhyland Klein94042872010-10-07 15:48:09 -0700500 NULL
501};
502
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100503static struct attribute *isl29023_attributes[] = {
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300504 ISL29018_DEV_ATTR(in_illuminance_scale_available),
505 ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100506 NULL
507};
508
Laurentiu Palcu5b4b5b9c2014-08-29 15:26:00 +0100509static const struct attribute_group isl29018_group = {
Rhyland Klein94042872010-10-07 15:48:09 -0700510 .attrs = isl29018_attributes,
511};
512
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100513static const struct attribute_group isl29023_group = {
514 .attrs = isl29023_attributes,
515};
516
517static int isl29035_detect(struct isl29018_chip *chip)
518{
519 int status;
520 unsigned int id;
Alison Schofield64670862016-02-22 12:34:32 -0800521 struct device *dev = regmap_get_device(chip->regmap);
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100522
523 status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id);
524 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800525 dev_err(dev,
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100526 "Error reading ID register with error %d\n",
527 status);
528 return status;
529 }
530
531 id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT;
532
533 if (id != ISL29035_DEVICE_ID)
534 return -ENODEV;
535
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200536 /* Clear brownout bit */
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100537 return regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID,
538 ISL29035_BOUT_MASK, 0);
539}
540
541enum {
542 isl29018,
543 isl29023,
544 isl29035,
545};
546
Laxman Dewangan057340e2012-04-20 12:57:38 +0530547static int isl29018_chip_init(struct isl29018_chip *chip)
Rhyland Klein94042872010-10-07 15:48:09 -0700548{
Rhyland Klein94042872010-10-07 15:48:09 -0700549 int status;
Alison Schofield64670862016-02-22 12:34:32 -0800550 struct device *dev = regmap_get_device(chip->regmap);
Rhyland Klein94042872010-10-07 15:48:09 -0700551
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100552 if (chip->type == isl29035) {
553 status = isl29035_detect(chip);
554 if (status < 0)
555 return status;
556 }
557
Grant Grundler176f9f22011-08-09 15:18:14 -0700558 /* Code added per Intersil Application Note 1534:
559 * When VDD sinks to approximately 1.8V or below, some of
560 * the part's registers may change their state. When VDD
561 * recovers to 2.25V (or greater), the part may thus be in an
562 * unknown mode of operation. The user can return the part to
563 * a known mode of operation either by (a) setting VDD = 0V for
564 * 1 second or more and then powering back up with a slew rate
565 * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
566 * conversions, clear the test registers, and then rewrite all
567 * registers to the desired values.
568 * ...
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200569 * For ISL29011, ISL29018, ISL29021, ISL29023
Grant Grundler176f9f22011-08-09 15:18:14 -0700570 * 1. Write 0x00 to register 0x08 (TEST)
571 * 2. Write 0x00 to register 0x00 (CMD1)
572 * 3. Rewrite all registers to the desired values
573 *
574 * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
575 * the same thing EXCEPT the data sheet asks for a 1ms delay after
576 * writing the CMD1 register.
577 */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530578 status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
Grant Grundler176f9f22011-08-09 15:18:14 -0700579 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800580 dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n",
Roberta Dobrescuad3e6462014-09-25 20:09:09 +0300581 status);
Grant Grundler176f9f22011-08-09 15:18:14 -0700582 return status;
583 }
584
585 /* See Intersil AN1534 comments above.
586 * "Operating Mode" (COMMAND1) register is reprogrammed when
587 * data is read from the device.
588 */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530589 status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
Grant Grundler176f9f22011-08-09 15:18:14 -0700590 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800591 dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n",
Roberta Dobrescuad3e6462014-09-25 20:09:09 +0300592 status);
Grant Grundler176f9f22011-08-09 15:18:14 -0700593 return status;
594 }
595
Vaishali Thakkar890d2282014-09-23 09:22:30 +0530596 usleep_range(1000, 2000); /* per data sheet, page 10 */
Grant Grundler176f9f22011-08-09 15:18:14 -0700597
Peter Meerwald-Stadler96273f432016-07-05 13:55:39 +0200598 /* Set defaults */
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300599 status = isl29018_set_scale(chip, chip->scale.scale,
600 chip->scale.uscale);
Rhyland Klein94042872010-10-07 15:48:09 -0700601 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800602 dev_err(dev, "Init of isl29018 fails\n");
Rhyland Klein94042872010-10-07 15:48:09 -0700603 return status;
604 }
605
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300606 status = isl29018_set_integration_time(chip,
607 isl29018_int_utimes[chip->type][chip->int_time]);
608 if (status < 0) {
Alison Schofield64670862016-02-22 12:34:32 -0800609 dev_err(dev, "Init of isl29018 fails\n");
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300610 return status;
611 }
Rhyland Klein94042872010-10-07 15:48:09 -0700612
613 return 0;
614}
615
Laurentiu Palcu5b4b5b9c2014-08-29 15:26:00 +0100616static const struct iio_info isl29018_info = {
617 .attrs = &isl29018_group,
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100618 .driver_module = THIS_MODULE,
Bhumika Goyal6d9b10c2016-02-12 20:40:27 +0530619 .read_raw = isl29018_read_raw,
620 .write_raw = isl29018_write_raw,
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100621};
622
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100623static const struct iio_info isl29023_info = {
624 .attrs = &isl29023_group,
625 .driver_module = THIS_MODULE,
Bhumika Goyal6d9b10c2016-02-12 20:40:27 +0530626 .read_raw = isl29018_read_raw,
627 .write_raw = isl29018_write_raw,
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100628};
629
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200630static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg)
Laxman Dewangan057340e2012-04-20 12:57:38 +0530631{
632 switch (reg) {
633 case ISL29018_REG_ADD_DATA_LSB:
634 case ISL29018_REG_ADD_DATA_MSB:
635 case ISL29018_REG_ADD_COMMAND1:
636 case ISL29018_REG_TEST:
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100637 case ISL29035_REG_DEVICE_ID:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530638 return true;
639 default:
640 return false;
641 }
642}
643
Laxman Dewangan057340e2012-04-20 12:57:38 +0530644static const struct regmap_config isl29018_regmap_config = {
645 .reg_bits = 8,
646 .val_bits = 8,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200647 .volatile_reg = isl29018_is_volatile_reg,
Laxman Dewangan057340e2012-04-20 12:57:38 +0530648 .max_register = ISL29018_REG_TEST,
649 .num_reg_defaults_raw = ISL29018_REG_TEST + 1,
650 .cache_type = REGCACHE_RBTREE,
651};
652
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100653static const struct regmap_config isl29035_regmap_config = {
654 .reg_bits = 8,
655 .val_bits = 8,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200656 .volatile_reg = isl29018_is_volatile_reg,
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100657 .max_register = ISL29035_REG_DEVICE_ID,
658 .num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1,
659 .cache_type = REGCACHE_RBTREE,
660};
661
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200662struct isl29018_chip_info {
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100663 const struct iio_chan_spec *channels;
664 int num_channels;
665 const struct iio_info *indio_info;
666 const struct regmap_config *regmap_cfg;
667};
668
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200669static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100670 [isl29018] = {
671 .channels = isl29018_channels,
672 .num_channels = ARRAY_SIZE(isl29018_channels),
673 .indio_info = &isl29018_info,
674 .regmap_cfg = &isl29018_regmap_config,
675 },
676 [isl29023] = {
677 .channels = isl29023_channels,
678 .num_channels = ARRAY_SIZE(isl29023_channels),
679 .indio_info = &isl29023_info,
680 .regmap_cfg = &isl29018_regmap_config,
681 },
682 [isl29035] = {
683 .channels = isl29023_channels,
684 .num_channels = ARRAY_SIZE(isl29023_channels),
685 .indio_info = &isl29023_info,
686 .regmap_cfg = &isl29035_regmap_config,
687 },
688};
689
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000690static const char *isl29018_match_acpi_device(struct device *dev, int *data)
691{
692 const struct acpi_device_id *id;
693
694 id = acpi_match_device(dev->driver->acpi_match_table, dev);
695
696 if (!id)
697 return NULL;
698
Eva Rachel Retuya79783b32016-02-18 15:35:37 +0800699 *data = (int)id->driver_data;
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000700
701 return dev_name(dev);
702}
703
Bill Pemberton4ae1c612012-11-19 13:21:57 -0500704static int isl29018_probe(struct i2c_client *client,
Eva Rachel Retuyaca52c882016-02-18 15:35:36 +0800705 const struct i2c_device_id *id)
Rhyland Klein94042872010-10-07 15:48:09 -0700706{
707 struct isl29018_chip *chip;
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100708 struct iio_dev *indio_dev;
Rhyland Klein94042872010-10-07 15:48:09 -0700709 int err;
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000710 const char *name = NULL;
711 int dev_id = 0;
Rhyland Klein94042872010-10-07 15:48:09 -0700712
Sachin Kamate434dcf2013-07-22 12:03:00 +0100713 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
Peter Meerwald-Stadlerab5b9492016-07-05 13:55:37 +0200714 if (!indio_dev)
Sachin Kamate434dcf2013-07-22 12:03:00 +0100715 return -ENOMEM;
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100716 chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700717
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100718 i2c_set_clientdata(client, indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700719
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000720 if (id) {
721 name = id->name;
722 dev_id = id->driver_data;
723 }
724
725 if (ACPI_HANDLE(&client->dev))
726 name = isl29018_match_acpi_device(&client->dev, &dev_id);
727
Rhyland Klein94042872010-10-07 15:48:09 -0700728 mutex_init(&chip->lock);
729
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000730 chip->type = dev_id;
Roberta Dobrescu809a5912015-04-16 22:20:58 +0300731 chip->calibscale = 1;
732 chip->ucalibscale = 0;
Roberta Dobrescu6920ccf2015-04-16 22:20:59 +0300733 chip->int_time = ISL29018_INT_TIME_16;
734 chip->scale = isl29018_scales[chip->int_time][0];
Bryan Freed1e45cf32012-10-25 00:39:00 +0100735 chip->suspended = false;
Rhyland Klein94042872010-10-07 15:48:09 -0700736
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100737 chip->regmap = devm_regmap_init_i2c(client,
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200738 isl29018_chip_info_tbl[dev_id].regmap_cfg);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530739 if (IS_ERR(chip->regmap)) {
740 err = PTR_ERR(chip->regmap);
Alison Schofield64670862016-02-22 12:34:32 -0800741 dev_err(&client->dev, "regmap initialization fails: %d\n", err);
Sachin Kamate434dcf2013-07-22 12:03:00 +0100742 return err;
Laxman Dewangan057340e2012-04-20 12:57:38 +0530743 }
744
745 err = isl29018_chip_init(chip);
Rhyland Klein94042872010-10-07 15:48:09 -0700746 if (err)
Sachin Kamate434dcf2013-07-22 12:03:00 +0100747 return err;
Rhyland Klein94042872010-10-07 15:48:09 -0700748
Peter Meerwald-Stadler92193762016-07-05 13:55:40 +0200749 indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info;
750 indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
751 indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000752 indio_dev->name = name;
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100753 indio_dev->dev.parent = &client->dev;
754 indio_dev->modes = INDIO_DIRECT_MODE;
Peter Meerwald-Stadlerab5b9492016-07-05 13:55:37 +0200755 return devm_iio_device_register(&client->dev, indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700756}
757
Bryan Freed1e45cf32012-10-25 00:39:00 +0100758#ifdef CONFIG_PM_SLEEP
759static int isl29018_suspend(struct device *dev)
760{
761 struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
762
763 mutex_lock(&chip->lock);
764
765 /* Since this driver uses only polling commands, we are by default in
766 * auto shutdown (ie, power-down) mode.
767 * So we do not have much to do here.
768 */
769 chip->suspended = true;
770
771 mutex_unlock(&chip->lock);
772 return 0;
773}
774
775static int isl29018_resume(struct device *dev)
776{
777 struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
778 int err;
779
780 mutex_lock(&chip->lock);
781
782 err = isl29018_chip_init(chip);
783 if (!err)
784 chip->suspended = false;
785
786 mutex_unlock(&chip->lock);
787 return err;
788}
789
790static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
791#define ISL29018_PM_OPS (&isl29018_pm_ops)
792#else
793#define ISL29018_PM_OPS NULL
794#endif
795
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000796static const struct acpi_device_id isl29018_acpi_match[] = {
797 {"ISL29018", isl29018},
798 {"ISL29023", isl29023},
799 {"ISL29035", isl29035},
800 {},
801};
802MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
803
Rhyland Klein94042872010-10-07 15:48:09 -0700804static const struct i2c_device_id isl29018_id[] = {
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100805 {"isl29018", isl29018},
806 {"isl29023", isl29023},
807 {"isl29035", isl29035},
Rhyland Klein94042872010-10-07 15:48:09 -0700808 {}
809};
810
811MODULE_DEVICE_TABLE(i2c, isl29018_id);
812
Olof Johansson4ee19522011-12-22 18:44:43 -0800813static const struct of_device_id isl29018_of_match[] = {
Laxman Dewangan610202d2012-04-24 11:41:38 +0530814 { .compatible = "isil,isl29018", },
Laurentiu Palcu609acef2014-08-29 15:26:00 +0100815 { .compatible = "isil,isl29023", },
816 { .compatible = "isil,isl29035", },
Olof Johansson4ee19522011-12-22 18:44:43 -0800817 { },
818};
819MODULE_DEVICE_TABLE(of, isl29018_of_match);
820
Rhyland Klein94042872010-10-07 15:48:09 -0700821static struct i2c_driver isl29018_driver = {
Rhyland Klein94042872010-10-07 15:48:09 -0700822 .driver = {
823 .name = "isl29018",
Laurentiu Palcudc4ecaf2014-01-09 10:20:00 +0000824 .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
Bryan Freed1e45cf32012-10-25 00:39:00 +0100825 .pm = ISL29018_PM_OPS,
Olof Johansson4ee19522011-12-22 18:44:43 -0800826 .of_match_table = isl29018_of_match,
Rhyland Klein94042872010-10-07 15:48:09 -0700827 },
828 .probe = isl29018_probe,
Rhyland Klein94042872010-10-07 15:48:09 -0700829 .id_table = isl29018_id,
830};
Lars-Peter Clausen6e5af182011-11-16 10:13:38 +0100831module_i2c_driver(isl29018_driver);
Rhyland Klein94042872010-10-07 15:48:09 -0700832
833MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
834MODULE_LICENSE("GPL");