STAGING:iio:light: fix ISL29018 init to handle brownout

After a voltage brownout, sensor will now operate correctly.

Page 10 of ISL29018 data sheet and the Intersil Application Note 1534
describe the required initialization sequence:
1. Write 0x00 to register 0x08 (TEST)
2. Write 0x00 to register 0x00 (CMD1)
3. msleep(1)
4. program remaining registers as before

Signed-off-by: Grant Grundler <grundler@chromium.org>
Reviewed-by: Bryan Freed <bfreed@chromium.org>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Grant Grundler 2011-08-09 15:18:14 -07:00 committed by Greg Kroah-Hartman
parent f94aa354d6
commit 176f9f29ce
1 changed files with 46 additions and 0 deletions

View File

@ -53,6 +53,10 @@
#define ISL29018_REG_ADD_DATA_MSB 0x03
#define ISL29018_MAX_REGS ISL29018_REG_ADD_DATA_MSB
#define ISL29018_REG_TEST 0x08
#define ISL29018_TEST_SHIFT 0
#define ISL29018_TEST_MASK (0xFF << ISL29018_TEST_SHIFT)
struct isl29018_chip {
struct i2c_client *client;
struct mutex lock;
@ -457,6 +461,48 @@ static int isl29018_chip_init(struct i2c_client *client)
memset(chip->reg_cache, 0, sizeof(chip->reg_cache));
/* Code added per Intersil Application Note 1534:
* When VDD sinks to approximately 1.8V or below, some of
* the part's registers may change their state. When VDD
* recovers to 2.25V (or greater), the part may thus be in an
* unknown mode of operation. The user can return the part to
* a known mode of operation either by (a) setting VDD = 0V for
* 1 second or more and then powering back up with a slew rate
* of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
* conversions, clear the test registers, and then rewrite all
* registers to the desired values.
* ...
* FOR ISL29011, ISL29018, ISL29021, ISL29023
* 1. Write 0x00 to register 0x08 (TEST)
* 2. Write 0x00 to register 0x00 (CMD1)
* 3. Rewrite all registers to the desired values
*
* ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
* the same thing EXCEPT the data sheet asks for a 1ms delay after
* writing the CMD1 register.
*/
status = isl29018_write_data(client, ISL29018_REG_TEST, 0,
ISL29018_TEST_MASK, ISL29018_TEST_SHIFT);
if (status < 0) {
dev_err(&client->dev, "Failed to clear isl29018 TEST reg."
"(%d)\n", status);
return status;
}
/* See Intersil AN1534 comments above.
* "Operating Mode" (COMMAND1) register is reprogrammed when
* data is read from the device.
*/
status = isl29018_write_data(client, ISL29018_REG_ADD_COMMAND1, 0,
0xff, 0);
if (status < 0) {
dev_err(&client->dev, "Failed to clear isl29018 CMD1 reg."
"(%d)\n", status);
return status;
}
msleep(1); /* per data sheet, page 10 */
/* set defaults */
status = isl29018_set_range(client, chip->range, &new_range);
if (status < 0) {