blob: 31d22f5591ca665089634a58ff687266127fd723 [file] [log] [blame]
Rhyland Klein94042872010-10-07 15:48:09 -07001/*
2 * A iio driver for the light sensor ISL 29018.
3 *
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.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/i2c.h>
26#include <linux/err.h>
27#include <linux/mutex.h>
28#include <linux/delay.h>
Laxman Dewangan057340e2012-04-20 12:57:38 +053029#include <linux/regmap.h>
Rhyland Klein94042872010-10-07 15:48:09 -070030#include <linux/slab.h>
Jonathan Cameron06458e22012-04-25 15:54:58 +010031#include <linux/iio/iio.h>
32#include <linux/iio/sysfs.h>
Laxman Dewangan057340e2012-04-20 12:57:38 +053033
Rhyland Klein94042872010-10-07 15:48:09 -070034#define CONVERSION_TIME_MS 100
35
36#define ISL29018_REG_ADD_COMMAND1 0x00
37#define COMMMAND1_OPMODE_SHIFT 5
38#define COMMMAND1_OPMODE_MASK (7 << COMMMAND1_OPMODE_SHIFT)
39#define COMMMAND1_OPMODE_POWER_DOWN 0
40#define COMMMAND1_OPMODE_ALS_ONCE 1
41#define COMMMAND1_OPMODE_IR_ONCE 2
42#define COMMMAND1_OPMODE_PROX_ONCE 3
43
44#define ISL29018_REG_ADD_COMMANDII 0x01
45#define COMMANDII_RESOLUTION_SHIFT 2
46#define COMMANDII_RESOLUTION_MASK (0x3 << COMMANDII_RESOLUTION_SHIFT)
47
48#define COMMANDII_RANGE_SHIFT 0
49#define COMMANDII_RANGE_MASK (0x3 << COMMANDII_RANGE_SHIFT)
50
51#define COMMANDII_SCHEME_SHIFT 7
52#define COMMANDII_SCHEME_MASK (0x1 << COMMANDII_SCHEME_SHIFT)
53
54#define ISL29018_REG_ADD_DATA_LSB 0x02
55#define ISL29018_REG_ADD_DATA_MSB 0x03
Rhyland Klein94042872010-10-07 15:48:09 -070056
Grant Grundler176f9f22011-08-09 15:18:14 -070057#define ISL29018_REG_TEST 0x08
58#define ISL29018_TEST_SHIFT 0
59#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
60
Rhyland Klein94042872010-10-07 15:48:09 -070061struct isl29018_chip {
Laxman Dewangan057340e2012-04-20 12:57:38 +053062 struct device *dev;
63 struct regmap *regmap;
Rhyland Klein94042872010-10-07 15:48:09 -070064 struct mutex lock;
Bryan Freed6d1ad0f2011-06-28 16:46:33 -070065 unsigned int lux_scale;
Rhyland Klein94042872010-10-07 15:48:09 -070066 unsigned int range;
67 unsigned int adc_bit;
68 int prox_scheme;
Rhyland Klein94042872010-10-07 15:48:09 -070069};
70
Laxman Dewangan057340e2012-04-20 12:57:38 +053071static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range,
Rhyland Klein94042872010-10-07 15:48:09 -070072 unsigned int *new_range)
73{
74 static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000};
75 int i;
76
77 for (i = 0; i < ARRAY_SIZE(supp_ranges); ++i) {
78 if (range <= supp_ranges[i]) {
79 *new_range = (unsigned int)supp_ranges[i];
80 break;
81 }
82 }
83
84 if (i >= ARRAY_SIZE(supp_ranges))
85 return -EINVAL;
86
Laxman Dewangan057340e2012-04-20 12:57:38 +053087 return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
88 COMMANDII_RANGE_MASK, i << COMMANDII_RANGE_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -070089}
90
Laxman Dewangan057340e2012-04-20 12:57:38 +053091static int isl29018_set_resolution(struct isl29018_chip *chip,
Rhyland Klein94042872010-10-07 15:48:09 -070092 unsigned long adcbit, unsigned int *conf_adc_bit)
93{
94 static const unsigned long supp_adcbit[] = {16, 12, 8, 4};
95 int i;
96
97 for (i = 0; i < ARRAY_SIZE(supp_adcbit); ++i) {
98 if (adcbit >= supp_adcbit[i]) {
99 *conf_adc_bit = (unsigned int)supp_adcbit[i];
100 break;
101 }
102 }
103
104 if (i >= ARRAY_SIZE(supp_adcbit))
105 return -EINVAL;
106
Laxman Dewangan057340e2012-04-20 12:57:38 +0530107 return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
108 COMMANDII_RESOLUTION_MASK,
109 i << COMMANDII_RESOLUTION_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -0700110}
111
Laxman Dewangan057340e2012-04-20 12:57:38 +0530112static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
Rhyland Klein94042872010-10-07 15:48:09 -0700113{
114 int status;
Laxman Dewangan057340e2012-04-20 12:57:38 +0530115 unsigned int lsb;
116 unsigned int msb;
Rhyland Klein94042872010-10-07 15:48:09 -0700117
118 /* Set mode */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530119 status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
120 mode << COMMMAND1_OPMODE_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -0700121 if (status) {
Laxman Dewangan057340e2012-04-20 12:57:38 +0530122 dev_err(chip->dev,
123 "Error in setting operating mode err %d\n", status);
Rhyland Klein94042872010-10-07 15:48:09 -0700124 return status;
125 }
126 msleep(CONVERSION_TIME_MS);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530127 status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
128 if (status < 0) {
129 dev_err(chip->dev,
130 "Error in reading LSB DATA with err %d\n", status);
131 return status;
Rhyland Klein94042872010-10-07 15:48:09 -0700132 }
133
Laxman Dewangan057340e2012-04-20 12:57:38 +0530134 status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
135 if (status < 0) {
136 dev_err(chip->dev,
137 "Error in reading MSB DATA with error %d\n", status);
138 return status;
Rhyland Klein94042872010-10-07 15:48:09 -0700139 }
Laxman Dewangan057340e2012-04-20 12:57:38 +0530140 dev_vdbg(chip->dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
Rhyland Klein94042872010-10-07 15:48:09 -0700141
142 return (msb << 8) | lsb;
143}
144
Laxman Dewangan057340e2012-04-20 12:57:38 +0530145static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
Rhyland Klein94042872010-10-07 15:48:09 -0700146{
147 int lux_data;
Rhyland Klein94042872010-10-07 15:48:09 -0700148
Laxman Dewangan057340e2012-04-20 12:57:38 +0530149 lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700150
151 if (lux_data < 0)
152 return lux_data;
153
Bryan Freed6d1ad0f2011-06-28 16:46:33 -0700154 *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit;
Rhyland Klein94042872010-10-07 15:48:09 -0700155
156 return 0;
157}
158
Laxman Dewangan057340e2012-04-20 12:57:38 +0530159static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
Rhyland Klein94042872010-10-07 15:48:09 -0700160{
161 int ir_data;
162
Laxman Dewangan057340e2012-04-20 12:57:38 +0530163 ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700164
165 if (ir_data < 0)
166 return ir_data;
167
168 *ir = ir_data;
169
170 return 0;
171}
172
Laxman Dewangan057340e2012-04-20 12:57:38 +0530173static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
Rhyland Klein94042872010-10-07 15:48:09 -0700174 int *near_ir)
175{
176 int status;
177 int prox_data = -1;
178 int ir_data = -1;
179
180 /* Do proximity sensing with required scheme */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530181 status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII,
182 COMMANDII_SCHEME_MASK,
183 scheme << COMMANDII_SCHEME_SHIFT);
Rhyland Klein94042872010-10-07 15:48:09 -0700184 if (status) {
Laxman Dewangan057340e2012-04-20 12:57:38 +0530185 dev_err(chip->dev, "Error in setting operating mode\n");
Rhyland Klein94042872010-10-07 15:48:09 -0700186 return status;
187 }
188
Laxman Dewangan057340e2012-04-20 12:57:38 +0530189 prox_data = isl29018_read_sensor_input(chip,
Rhyland Klein94042872010-10-07 15:48:09 -0700190 COMMMAND1_OPMODE_PROX_ONCE);
191 if (prox_data < 0)
192 return prox_data;
193
194 if (scheme == 1) {
195 *near_ir = prox_data;
196 return 0;
197 }
198
Laxman Dewangan057340e2012-04-20 12:57:38 +0530199 ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE);
Rhyland Klein94042872010-10-07 15:48:09 -0700200
201 if (ir_data < 0)
202 return ir_data;
203
204 if (prox_data >= ir_data)
205 *near_ir = prox_data - ir_data;
206 else
207 *near_ir = 0;
208
209 return 0;
210}
211
Rhyland Klein94042872010-10-07 15:48:09 -0700212/* Sysfs interface */
213/* range */
214static ssize_t show_range(struct device *dev,
215 struct device_attribute *attr, char *buf)
216{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200217 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100218 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700219
220 return sprintf(buf, "%u\n", chip->range);
221}
222
223static ssize_t store_range(struct device *dev,
224 struct device_attribute *attr, const char *buf, size_t count)
225{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200226 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100227 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700228 int status;
229 unsigned long lval;
230 unsigned int new_range;
231
232 if (strict_strtoul(buf, 10, &lval))
233 return -EINVAL;
234
235 if (!(lval == 1000UL || lval == 4000UL ||
236 lval == 16000UL || lval == 64000UL)) {
237 dev_err(dev, "The range is not supported\n");
238 return -EINVAL;
239 }
240
241 mutex_lock(&chip->lock);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530242 status = isl29018_set_range(chip, lval, &new_range);
Rhyland Klein94042872010-10-07 15:48:09 -0700243 if (status < 0) {
244 mutex_unlock(&chip->lock);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530245 dev_err(dev,
246 "Error in setting max range with err %d\n", status);
Rhyland Klein94042872010-10-07 15:48:09 -0700247 return status;
248 }
249 chip->range = new_range;
250 mutex_unlock(&chip->lock);
251
252 return count;
253}
254
255/* resolution */
256static ssize_t show_resolution(struct device *dev,
257 struct device_attribute *attr, char *buf)
258{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200259 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100260 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700261
262 return sprintf(buf, "%u\n", chip->adc_bit);
263}
264
265static ssize_t store_resolution(struct device *dev,
266 struct device_attribute *attr, const char *buf, size_t count)
267{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200268 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100269 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700270 int status;
271 unsigned long lval;
272 unsigned int new_adc_bit;
273
274 if (strict_strtoul(buf, 10, &lval))
275 return -EINVAL;
276 if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) {
277 dev_err(dev, "The resolution is not supported\n");
278 return -EINVAL;
279 }
280
281 mutex_lock(&chip->lock);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530282 status = isl29018_set_resolution(chip, lval, &new_adc_bit);
Rhyland Klein94042872010-10-07 15:48:09 -0700283 if (status < 0) {
284 mutex_unlock(&chip->lock);
285 dev_err(dev, "Error in setting resolution\n");
286 return status;
287 }
288 chip->adc_bit = new_adc_bit;
289 mutex_unlock(&chip->lock);
290
291 return count;
292}
293
294/* proximity scheme */
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200295static ssize_t show_prox_infrared_suppression(struct device *dev,
Rhyland Klein94042872010-10-07 15:48:09 -0700296 struct device_attribute *attr, char *buf)
297{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200298 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100299 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700300
301 /* return the "proximity scheme" i.e. if the chip does on chip
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200302 infrared suppression (1 means perform on chip suppression) */
Rhyland Klein94042872010-10-07 15:48:09 -0700303 return sprintf(buf, "%d\n", chip->prox_scheme);
304}
305
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200306static ssize_t store_prox_infrared_suppression(struct device *dev,
Rhyland Klein94042872010-10-07 15:48:09 -0700307 struct device_attribute *attr, const char *buf, size_t count)
308{
Lars-Peter Clausen96f691f2012-05-12 15:39:51 +0200309 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100310 struct isl29018_chip *chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700311 unsigned long lval;
312
313 if (strict_strtoul(buf, 10, &lval))
314 return -EINVAL;
315 if (!(lval == 0UL || lval == 1UL)) {
316 dev_err(dev, "The mode is not supported\n");
317 return -EINVAL;
318 }
319
320 /* get the "proximity scheme" i.e. if the chip does on chip
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200321 infrared suppression (1 means perform on chip suppression) */
Rhyland Klein94042872010-10-07 15:48:09 -0700322 mutex_lock(&chip->lock);
323 chip->prox_scheme = (int)lval;
324 mutex_unlock(&chip->lock);
325
326 return count;
327}
328
Bryan Freed01e57c52011-07-07 12:01:56 -0700329/* Channel IO */
330static int isl29018_write_raw(struct iio_dev *indio_dev,
331 struct iio_chan_spec const *chan,
332 int val,
333 int val2,
334 long mask)
Rhyland Klein94042872010-10-07 15:48:09 -0700335{
Bryan Freed01e57c52011-07-07 12:01:56 -0700336 struct isl29018_chip *chip = iio_priv(indio_dev);
337 int ret = -EINVAL;
338
339 mutex_lock(&chip->lock);
Jonathan Cameronc8a9f802011-10-26 17:41:36 +0100340 if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) {
Bryan Freed01e57c52011-07-07 12:01:56 -0700341 chip->lux_scale = val;
342 ret = 0;
343 }
344 mutex_unlock(&chip->lock);
345
346 return 0;
Rhyland Klein94042872010-10-07 15:48:09 -0700347}
348
Bryan Freed01e57c52011-07-07 12:01:56 -0700349static int isl29018_read_raw(struct iio_dev *indio_dev,
350 struct iio_chan_spec const *chan,
351 int *val,
352 int *val2,
353 long mask)
Rhyland Klein94042872010-10-07 15:48:09 -0700354{
Bryan Freed01e57c52011-07-07 12:01:56 -0700355 int ret = -EINVAL;
356 struct isl29018_chip *chip = iio_priv(indio_dev);
Bryan Freed01e57c52011-07-07 12:01:56 -0700357
358 mutex_lock(&chip->lock);
359 switch (mask) {
Jonathan Cameron90354d02012-04-15 17:41:22 +0100360 case IIO_CHAN_INFO_RAW:
361 case IIO_CHAN_INFO_PROCESSED:
Bryan Freed01e57c52011-07-07 12:01:56 -0700362 switch (chan->type) {
363 case IIO_LIGHT:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530364 ret = isl29018_read_lux(chip, val);
Bryan Freed01e57c52011-07-07 12:01:56 -0700365 break;
366 case IIO_INTENSITY:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530367 ret = isl29018_read_ir(chip, val);
Bryan Freed01e57c52011-07-07 12:01:56 -0700368 break;
369 case IIO_PROXIMITY:
Laxman Dewangan057340e2012-04-20 12:57:38 +0530370 ret = isl29018_read_proximity_ir(chip,
Bryan Freed01e57c52011-07-07 12:01:56 -0700371 chip->prox_scheme, val);
372 break;
373 default:
374 break;
375 }
376 if (!ret)
377 ret = IIO_VAL_INT;
378 break;
Jonathan Cameronc8a9f802011-10-26 17:41:36 +0100379 case IIO_CHAN_INFO_CALIBSCALE:
Bryan Freed01e57c52011-07-07 12:01:56 -0700380 if (chan->type == IIO_LIGHT) {
381 *val = chip->lux_scale;
382 ret = IIO_VAL_INT;
383 }
384 break;
385 default:
386 break;
387 }
388 mutex_unlock(&chip->lock);
389 return ret;
Rhyland Klein94042872010-10-07 15:48:09 -0700390}
391
Bryan Freed01e57c52011-07-07 12:01:56 -0700392static const struct iio_chan_spec isl29018_channels[] = {
393 {
394 .type = IIO_LIGHT,
395 .indexed = 1,
396 .channel = 0,
Jonathan Cameron90354d02012-04-15 17:41:22 +0100397 .info_mask = IIO_CHAN_INFO_PROCESSED_SEPARATE_BIT |
398 IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT,
Bryan Freed01e57c52011-07-07 12:01:56 -0700399 }, {
400 .type = IIO_INTENSITY,
401 .modified = 1,
Jonathan Cameron90354d02012-04-15 17:41:22 +0100402 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
Bryan Freed01e57c52011-07-07 12:01:56 -0700403 .channel2 = IIO_MOD_LIGHT_IR,
404 }, {
405 /* Unindexed in current ABI. But perhaps it should be. */
406 .type = IIO_PROXIMITY,
Jonathan Cameron90354d02012-04-15 17:41:22 +0100407 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
Bryan Freed01e57c52011-07-07 12:01:56 -0700408 }
409};
Rhyland Klein94042872010-10-07 15:48:09 -0700410
Rhyland Klein94042872010-10-07 15:48:09 -0700411static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0);
412static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000");
413static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16");
414static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR,
415 show_resolution, store_resolution, 0);
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200416static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression,
Rhyland Klein94042872010-10-07 15:48:09 -0700417 S_IRUGO | S_IWUSR,
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200418 show_prox_infrared_suppression,
419 store_prox_infrared_suppression, 0);
Rhyland Klein94042872010-10-07 15:48:09 -0700420
421#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
422#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
423static struct attribute *isl29018_attributes[] = {
Rhyland Klein94042872010-10-07 15:48:09 -0700424 ISL29018_DEV_ATTR(range),
425 ISL29018_CONST_ATTR(range_available),
426 ISL29018_DEV_ATTR(adc_resolution),
427 ISL29018_CONST_ATTR(adc_resolution_available),
Peter Meerwald2a1d45e2012-06-18 20:33:07 +0200428 ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression),
Rhyland Klein94042872010-10-07 15:48:09 -0700429 NULL
430};
431
432static const struct attribute_group isl29108_group = {
433 .attrs = isl29018_attributes,
434};
435
Laxman Dewangan057340e2012-04-20 12:57:38 +0530436static int isl29018_chip_init(struct isl29018_chip *chip)
Rhyland Klein94042872010-10-07 15:48:09 -0700437{
Rhyland Klein94042872010-10-07 15:48:09 -0700438 int status;
439 int new_adc_bit;
440 unsigned int new_range;
441
Grant Grundler176f9f22011-08-09 15:18:14 -0700442 /* Code added per Intersil Application Note 1534:
443 * When VDD sinks to approximately 1.8V or below, some of
444 * the part's registers may change their state. When VDD
445 * recovers to 2.25V (or greater), the part may thus be in an
446 * unknown mode of operation. The user can return the part to
447 * a known mode of operation either by (a) setting VDD = 0V for
448 * 1 second or more and then powering back up with a slew rate
449 * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
450 * conversions, clear the test registers, and then rewrite all
451 * registers to the desired values.
452 * ...
453 * FOR ISL29011, ISL29018, ISL29021, ISL29023
454 * 1. Write 0x00 to register 0x08 (TEST)
455 * 2. Write 0x00 to register 0x00 (CMD1)
456 * 3. Rewrite all registers to the desired values
457 *
458 * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
459 * the same thing EXCEPT the data sheet asks for a 1ms delay after
460 * writing the CMD1 register.
461 */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530462 status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
Grant Grundler176f9f22011-08-09 15:18:14 -0700463 if (status < 0) {
Laxman Dewangan057340e2012-04-20 12:57:38 +0530464 dev_err(chip->dev, "Failed to clear isl29018 TEST reg."
Grant Grundler176f9f22011-08-09 15:18:14 -0700465 "(%d)\n", status);
466 return status;
467 }
468
469 /* See Intersil AN1534 comments above.
470 * "Operating Mode" (COMMAND1) register is reprogrammed when
471 * data is read from the device.
472 */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530473 status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
Grant Grundler176f9f22011-08-09 15:18:14 -0700474 if (status < 0) {
Laxman Dewangan057340e2012-04-20 12:57:38 +0530475 dev_err(chip->dev, "Failed to clear isl29018 CMD1 reg."
Grant Grundler176f9f22011-08-09 15:18:14 -0700476 "(%d)\n", status);
477 return status;
478 }
479
480 msleep(1); /* per data sheet, page 10 */
481
Rhyland Klein94042872010-10-07 15:48:09 -0700482 /* set defaults */
Laxman Dewangan057340e2012-04-20 12:57:38 +0530483 status = isl29018_set_range(chip, chip->range, &new_range);
Rhyland Klein94042872010-10-07 15:48:09 -0700484 if (status < 0) {
Laxman Dewangan057340e2012-04-20 12:57:38 +0530485 dev_err(chip->dev, "Init of isl29018 fails\n");
Rhyland Klein94042872010-10-07 15:48:09 -0700486 return status;
487 }
488
Laxman Dewangan057340e2012-04-20 12:57:38 +0530489 status = isl29018_set_resolution(chip, chip->adc_bit,
Rhyland Klein94042872010-10-07 15:48:09 -0700490 &new_adc_bit);
491
492 return 0;
493}
494
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100495static const struct iio_info isl29108_info = {
496 .attrs = &isl29108_group,
497 .driver_module = THIS_MODULE,
Bryan Freed01e57c52011-07-07 12:01:56 -0700498 .read_raw = &isl29018_read_raw,
499 .write_raw = &isl29018_write_raw,
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100500};
501
Laxman Dewangan057340e2012-04-20 12:57:38 +0530502static bool is_volatile_reg(struct device *dev, unsigned int reg)
503{
504 switch (reg) {
505 case ISL29018_REG_ADD_DATA_LSB:
506 case ISL29018_REG_ADD_DATA_MSB:
507 case ISL29018_REG_ADD_COMMAND1:
508 case ISL29018_REG_TEST:
509 return true;
510 default:
511 return false;
512 }
513}
514
515/*
516 * isl29018_regmap_config: regmap configuration.
517 * Use RBTREE mechanism for caching.
518 */
519static const struct regmap_config isl29018_regmap_config = {
520 .reg_bits = 8,
521 .val_bits = 8,
522 .volatile_reg = is_volatile_reg,
523 .max_register = ISL29018_REG_TEST,
524 .num_reg_defaults_raw = ISL29018_REG_TEST + 1,
525 .cache_type = REGCACHE_RBTREE,
526};
527
Rhyland Klein94042872010-10-07 15:48:09 -0700528static int __devinit isl29018_probe(struct i2c_client *client,
529 const struct i2c_device_id *id)
530{
531 struct isl29018_chip *chip;
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100532 struct iio_dev *indio_dev;
Rhyland Klein94042872010-10-07 15:48:09 -0700533 int err;
534
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200535 indio_dev = iio_device_alloc(sizeof(*chip));
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100536 if (indio_dev == NULL) {
537 dev_err(&client->dev, "iio allocation fails\n");
Rhyland Klein94042872010-10-07 15:48:09 -0700538 err = -ENOMEM;
539 goto exit;
540 }
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100541 chip = iio_priv(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700542
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100543 i2c_set_clientdata(client, indio_dev);
Laxman Dewangan057340e2012-04-20 12:57:38 +0530544 chip->dev = &client->dev;
Rhyland Klein94042872010-10-07 15:48:09 -0700545
546 mutex_init(&chip->lock);
547
Bryan Freed6d1ad0f2011-06-28 16:46:33 -0700548 chip->lux_scale = 1;
Rhyland Klein94042872010-10-07 15:48:09 -0700549 chip->range = 1000;
550 chip->adc_bit = 16;
551
Laxman Dewangan057340e2012-04-20 12:57:38 +0530552 chip->regmap = devm_regmap_init_i2c(client, &isl29018_regmap_config);
553 if (IS_ERR(chip->regmap)) {
554 err = PTR_ERR(chip->regmap);
555 dev_err(chip->dev, "regmap initialization failed: %d\n", err);
556 goto exit;
557 }
558
559 err = isl29018_chip_init(chip);
Rhyland Klein94042872010-10-07 15:48:09 -0700560 if (err)
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100561 goto exit_iio_free;
Rhyland Klein94042872010-10-07 15:48:09 -0700562
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100563 indio_dev->info = &isl29108_info;
Bryan Freed01e57c52011-07-07 12:01:56 -0700564 indio_dev->channels = isl29018_channels;
565 indio_dev->num_channels = ARRAY_SIZE(isl29018_channels);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100566 indio_dev->name = id->name;
567 indio_dev->dev.parent = &client->dev;
568 indio_dev->modes = INDIO_DIRECT_MODE;
569 err = iio_device_register(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700570 if (err) {
571 dev_err(&client->dev, "iio registration fails\n");
572 goto exit_iio_free;
573 }
574
575 return 0;
576exit_iio_free:
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200577 iio_device_free(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700578exit:
579 return err;
580}
581
582static int __devexit isl29018_remove(struct i2c_client *client)
583{
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100584 struct iio_dev *indio_dev = i2c_get_clientdata(client);
Rhyland Klein94042872010-10-07 15:48:09 -0700585
586 dev_dbg(&client->dev, "%s()\n", __func__);
Jonathan Cameron927afbe2011-06-27 13:07:57 +0100587 iio_device_unregister(indio_dev);
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200588 iio_device_free(indio_dev);
Rhyland Klein94042872010-10-07 15:48:09 -0700589
590 return 0;
591}
592
593static const struct i2c_device_id isl29018_id[] = {
594 {"isl29018", 0},
595 {}
596};
597
598MODULE_DEVICE_TABLE(i2c, isl29018_id);
599
Olof Johansson4ee19522011-12-22 18:44:43 -0800600static const struct of_device_id isl29018_of_match[] = {
Laxman Dewangan610202d2012-04-24 11:41:38 +0530601 { .compatible = "isil,isl29018", },
Olof Johansson4ee19522011-12-22 18:44:43 -0800602 { },
603};
604MODULE_DEVICE_TABLE(of, isl29018_of_match);
605
Rhyland Klein94042872010-10-07 15:48:09 -0700606static struct i2c_driver isl29018_driver = {
607 .class = I2C_CLASS_HWMON,
608 .driver = {
609 .name = "isl29018",
610 .owner = THIS_MODULE,
Olof Johansson4ee19522011-12-22 18:44:43 -0800611 .of_match_table = isl29018_of_match,
Rhyland Klein94042872010-10-07 15:48:09 -0700612 },
613 .probe = isl29018_probe,
614 .remove = __devexit_p(isl29018_remove),
615 .id_table = isl29018_id,
616};
Lars-Peter Clausen6e5af182011-11-16 10:13:38 +0100617module_i2c_driver(isl29018_driver);
Rhyland Klein94042872010-10-07 15:48:09 -0700618
619MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
620MODULE_LICENSE("GPL");