static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) { int status; unsigned int lsb; unsigned int msb; struct device *dev = regmap_get_device(chip->regmap); /* Set mode */ status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, mode << COMMMAND1_OPMODE_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode err %d\n", status); return status; } msleep(CONVERSION_TIME_MS); status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb); if (status < 0) { dev_err(dev, "Error in reading LSB DATA with err %d\n", status); return status; } status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb); if (status < 0) { dev_err(dev, "Error in reading MSB DATA with error %d\n", status); return status; } dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb); return (msb << 8) | lsb; }
/* Channel IO */ static int isl29028_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct isl29028_chip *chip = iio_priv(indio_dev); struct device *dev = regmap_get_device(chip->regmap); int ret = -EINVAL; mutex_lock(&chip->lock); switch (chan->type) { case IIO_PROXIMITY: if (mask != IIO_CHAN_INFO_SAMP_FREQ) { dev_err(dev, "proximity: mask value 0x%08lx not supported\n", mask); break; } if (val < 1 || val > 100) { dev_err(dev, "Samp_freq %d is not in range[1:100]\n", val); break; } ret = isl29028_set_proxim_sampling(chip, val); if (ret < 0) { dev_err(dev, "Setting proximity samp_freq fail, err %d\n", ret); break; } chip->prox_sampling = val; break; case IIO_LIGHT: if (mask != IIO_CHAN_INFO_SCALE) { dev_err(dev, "light: mask value 0x%08lx not supported\n", mask); break; } if ((val != 125) && (val != 2000)) { dev_err(dev, "lux scale %d is invalid [125, 2000]\n", val); break; } ret = isl29028_set_als_scale(chip, val); if (ret < 0) { dev_err(dev, "Setting lux scale fail with error %d\n", ret); break; } chip->lux_scale = val; break; default: dev_err(dev, "Unsupported channel type\n"); break; } mutex_unlock(&chip->lock); return ret; }
static int isl29028_als_get(struct isl29028_chip *chip, int *als_data) { struct device *dev = regmap_get_device(chip->regmap); int ret; int als_ir_data; if (chip->als_ir_mode != MODE_ALS) { ret = isl29028_set_als_ir_mode(chip, MODE_ALS); if (ret < 0) { dev_err(dev, "Error in enabling ALS mode err %d\n", ret); return ret; } chip->als_ir_mode = MODE_ALS; } ret = isl29028_read_als_ir(chip, &als_ir_data); if (ret < 0) return ret; /* * convert als data count to lux. * if lux_scale = 125, lux = count * 0.031 * if lux_scale = 2000, lux = count * 0.49 */ if (chip->lux_scale == 125) als_ir_data = (als_ir_data * 31) / 1000; else als_ir_data = (als_ir_data * 49) / 100; *als_data = als_ir_data; return 0; }
static int isl29018_chip_init(struct isl29018_chip *chip) { int status; struct device *dev = regmap_get_device(chip->regmap); if (chip->type == isl29035) { unsigned int id; status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id); if (status < 0) { dev_err(dev, "Error reading ID register with error %d\n", status); return status; } id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT; if (id != ISL29035_DEVICE_ID) return -ENODEV; /* Clear brownout bit */ status = regmap_update_bits(chip->regmap, ISL29035_REG_DEVICE_ID, ISL29035_BOUT_MASK, 0); if (status < 0) return status; }
static int isl29028_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct isl29028_chip *chip = iio_priv(indio_dev); struct device *dev = regmap_get_device(chip->regmap); int ret = -EINVAL; mutex_lock(&chip->lock); switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_LIGHT: ret = isl29028_als_get(chip, val); break; case IIO_INTENSITY: ret = isl29028_ir_get(chip, val); break; case IIO_PROXIMITY: ret = isl29028_proxim_get(chip, val); break; default: break; } if (ret < 0) break; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SAMP_FREQ: if (chan->type != IIO_PROXIMITY) break; *val = chip->prox_sampling; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: if (chan->type != IIO_LIGHT) break; *val = chip->lux_scale; ret = IIO_VAL_INT; break; default: dev_err(dev, "mask value 0x%08lx not supported\n", mask); break; } mutex_unlock(&chip->lock); return ret; }
static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox) { struct device *dev = regmap_get_device(chip->regmap); unsigned int data; int ret; ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data); if (ret < 0) { dev_err(dev, "Error in reading register %d, error %d\n", ISL29028_REG_PROX_DATA, ret); return ret; } *prox = data; return 0; }
static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data) { struct device *dev = regmap_get_device(chip->regmap); int ret; if (chip->als_ir_mode != MODE_IR) { ret = isl29028_set_als_ir_mode(chip, MODE_IR); if (ret < 0) { dev_err(dev, "Error in enabling IR mode err %d\n", ret); return ret; } chip->als_ir_mode = MODE_IR; } return isl29028_read_als_ir(chip, ir_data); }
static int isl29028_chip_init(struct isl29028_chip *chip) { struct device *dev = regmap_get_device(chip->regmap); int ret; chip->enable_prox = false; chip->prox_sampling = 20; chip->lux_scale = 2000; chip->als_ir_mode = MODE_NONE; ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0); if (ret < 0) { dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_TEST1_MODE, ret); return ret; } ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0); if (ret < 0) { dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_TEST2_MODE, ret); return ret; } ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0); if (ret < 0) { dev_err(dev, "%s(): write to reg %d failed, err = %d\n", __func__, ISL29028_REG_CONFIGURE, ret); return ret; } ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling); if (ret < 0) { dev_err(dev, "setting the proximity, err = %d\n", ret); return ret; } ret = isl29028_set_als_scale(chip, chip->lux_scale); if (ret < 0) dev_err(dev, "setting als scale failed, err = %d\n", ret); return ret; }
static int mma7455_drdy(struct mma7455_data *mma7455) { struct device *dev = regmap_get_device(mma7455->regmap); unsigned int reg; int tries = 3; int ret; while (tries-- > 0) { ret = regmap_read(mma7455->regmap, MMA7455_REG_STATUS, ®); if (ret) return ret; if (reg & MMA7455_STATUS_DRDY) return 0; msleep(20); } dev_warn(dev, "data not ready\n"); return -EIO; }
static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, int *near_ir) { int status; int prox_data = -1; int ir_data = -1; struct device *dev = regmap_get_device(chip->regmap); /* Do proximity sensing with required scheme */ status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, COMMANDII_SCHEME_MASK, scheme << COMMANDII_SCHEME_SHIFT); if (status) { dev_err(dev, "Error in setting operating mode\n"); return status; } prox_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_PROX_ONCE); if (prox_data < 0) return prox_data; if (scheme == 1) { *near_ir = prox_data; return 0; } ir_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_IR_ONCE); if (ir_data < 0) return ir_data; if (prox_data >= ir_data) *near_ir = prox_data - ir_data; else *near_ir = 0; return 0; }
static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir) { struct device *dev = regmap_get_device(chip->regmap); unsigned int lsb; unsigned int msb; int ret; ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb); if (ret < 0) { dev_err(dev, "Error in reading register ALSIR_L err %d\n", ret); return ret; } ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb); if (ret < 0) { dev_err(dev, "Error in reading register ALSIR_U err %d\n", ret); return ret; } *als_ir = ((msb & 0xF) << 8) | (lsb & 0xFF); return 0; }
static int isl29018_chip_init(struct isl29018_chip *chip) { int status; struct device *dev = regmap_get_device(chip->regmap); if (chip->type == isl29035) { status = isl29035_detect(chip); if (status < 0) return status; } /* 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 = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0); if (status < 0) { dev_err(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 = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0); if (status < 0) { dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n", status); return status; } usleep_range(1000, 2000); /* per data sheet, page 10 */ /* set defaults */ status = isl29018_set_scale(chip, chip->scale.scale, chip->scale.uscale); if (status < 0) { dev_err(dev, "Init of isl29018 fails\n"); return status; } status = isl29018_set_integration_time(chip, isl29018_int_utimes[chip->type][chip->int_time]); if (status < 0) { dev_err(dev, "Init of isl29018 fails\n"); return status; } return 0; }