Add support for regfields as well to simplify register operations, taking into account the different fields for the veml6030/veml7700 and veml6035. Signed-off-by: Javier Carrasco <javier.carrasco.cruz@xxxxxxxxx> --- drivers/iio/light/veml6030.c | 95 ++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 25 deletions(-) diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c index 9b71825eea9bee2146be17ed2f30f5a8f7ad37e3..8e4eb8b0c19276635567d4eed74f4d402c3205fa 100644 --- a/drivers/iio/light/veml6030.c +++ b/drivers/iio/light/veml6030.c @@ -59,18 +59,31 @@ #define VEML6035_INT_CHAN BIT(3) #define VEML6035_CHAN_EN BIT(2) +/* Regfields */ +#define VEML6030_GAIN_RF REG_FIELD(VEML6030_REG_ALS_CONF, 11, 12) +#define VEML6030_IT_RF REG_FIELD(VEML6030_REG_ALS_CONF, 6, 9) + +#define VEML6035_GAIN_RF REG_FIELD(VEML6030_REG_ALS_CONF, 10, 12) + enum veml6030_scan { VEML6030_SCAN_ALS, VEML6030_SCAN_WH, VEML6030_SCAN_TIMESTAMP, }; +struct veml6030_rf { + struct regmap_field *it; + struct regmap_field *gain; +}; + struct veml603x_chip { const char *name; const int(*scale_vals)[][2]; const int num_scale_vals; const struct iio_chan_spec *channels; const int num_channels; + const struct reg_field gain_rf; + const struct reg_field it_rf; int (*hw_init)(struct iio_dev *indio_dev, struct device *dev); int (*set_info)(struct iio_dev *indio_dev); int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2); @@ -91,6 +104,7 @@ struct veml603x_chip { struct veml6030_data { struct i2c_client *client; struct regmap *regmap; + struct veml6030_rf rf; int cur_resolution; int cur_gain; int cur_integration_time; @@ -330,17 +344,17 @@ static const struct regmap_config veml6030_regmap_config = { static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev, int *val, int *val2) { - int ret, reg; + int it_idx, ret; struct veml6030_data *data = iio_priv(indio_dev); - ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); + ret = regmap_field_read(data->rf.it, &it_idx); if (ret) { dev_err(&data->client->dev, "can't read als conf register %d\n", ret); return ret; } - switch ((reg >> 6) & 0xF) { + switch (it_idx) { case 0: *val2 = 100000; break; @@ -405,8 +419,7 @@ static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev, return -EINVAL; } - ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, - VEML6030_ALS_IT, new_int_time); + ret = regmap_field_write(data->rf.it, new_int_time); if (ret) { dev_err(&data->client->dev, "can't update als integration time %d\n", ret); @@ -510,23 +523,22 @@ static int veml6030_set_als_gain(struct iio_dev *indio_dev, struct veml6030_data *data = iio_priv(indio_dev); if (val == 0 && val2 == 125000) { - new_gain = 0x1000; /* 0x02 << 11 */ + new_gain = 0x01; gain_idx = 3; } else if (val == 0 && val2 == 250000) { - new_gain = 0x1800; + new_gain = 0x11; gain_idx = 2; } else if (val == 1 && val2 == 0) { new_gain = 0x00; gain_idx = 1; } else if (val == 2 && val2 == 0) { - new_gain = 0x800; + new_gain = 0x01; gain_idx = 0; } else { return -EINVAL; } - ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, - VEML6030_ALS_GAIN, new_gain); + ret = regmap_field_write(data->rf.gain, new_gain); if (ret) { dev_err(&data->client->dev, "can't set als gain %d\n", ret); @@ -544,30 +556,31 @@ static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2) struct veml6030_data *data = iio_priv(indio_dev); if (val == 0 && val2 == 125000) { - new_gain = VEML6035_SENS; + new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS); gain_idx = 5; } else if (val == 0 && val2 == 250000) { - new_gain = VEML6035_SENS | VEML6035_GAIN; + new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | + VEML6035_GAIN); gain_idx = 4; } else if (val == 0 && val2 == 500000) { - new_gain = VEML6035_SENS | VEML6035_GAIN | - VEML6035_DG; + new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_SENS | + VEML6035_GAIN | VEML6035_DG); gain_idx = 3; } else if (val == 1 && val2 == 0) { new_gain = 0x0000; gain_idx = 2; } else if (val == 2 && val2 == 0) { - new_gain = VEML6035_GAIN; + new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN); gain_idx = 1; } else if (val == 4 && val2 == 0) { - new_gain = VEML6035_GAIN | VEML6035_DG; + new_gain = FIELD_GET(VEML6035_GAIN_M, VEML6035_GAIN | + VEML6035_DG); gain_idx = 0; } else { return -EINVAL; } - ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF, - VEML6035_GAIN_M, new_gain); + ret = regmap_field_write(data->rf.gain, new_gain); if (ret) { dev_err(&data->client->dev, "can't set als gain %d\n", ret); return ret; @@ -581,17 +594,17 @@ static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2) static int veml6030_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2) { - int ret, reg; + int gain, ret; struct veml6030_data *data = iio_priv(indio_dev); - ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); + ret = regmap_field_read(data->rf.gain, &gain); if (ret) { dev_err(&data->client->dev, "can't read als conf register %d\n", ret); return ret; } - switch ((reg >> 11) & 0x03) { + switch (gain) { case 0: *val = 1; *val2 = 0; @@ -617,17 +630,17 @@ static int veml6030_get_als_gain(struct iio_dev *indio_dev, static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2) { - int ret, reg; + int gain, ret; struct veml6030_data *data = iio_priv(indio_dev); - ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®); + ret = regmap_field_read(data->rf.gain, &gain); if (ret) { dev_err(&data->client->dev, - "can't read als conf register %d\n", ret); + "can't read als conf register %d\n", ret); return ret; } - switch (FIELD_GET(VEML6035_GAIN_M, reg)) { + switch (gain) { case 0: *val = 1; *val2 = 0; @@ -990,6 +1003,27 @@ static int veml7700_set_info(struct iio_dev *indio_dev) return 0; } +static int veml6030_regfield_init(struct iio_dev *indio_dev) +{ + struct veml6030_data *data = iio_priv(indio_dev); + struct regmap *regmap = data->regmap; + struct device *dev = &data->client->dev; + struct regmap_field *rm_field; + struct veml6030_rf *rf = &data->rf; + + rm_field = devm_regmap_field_alloc(dev, regmap, data->chip->it_rf); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->it = rm_field; + + rm_field = devm_regmap_field_alloc(dev, regmap, data->chip->gain_rf); + if (IS_ERR(rm_field)) + return PTR_ERR(rm_field); + rf->gain = rm_field; + + return 0; +} + /* * Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2, * persistence to 1 x integration time and the threshold @@ -1143,6 +1177,11 @@ static int veml6030_probe(struct i2c_client *client) if (ret < 0) return ret; + ret = veml6030_regfield_init(indio_dev); + if (ret) + return dev_err_probe(&client->dev, ret, + "failed to init regfields\n"); + ret = data->chip->hw_init(indio_dev, &client->dev); if (ret < 0) return ret; @@ -1191,6 +1230,8 @@ static const struct veml603x_chip veml6030_chip = { .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), .channels = veml6030_channels, .num_channels = ARRAY_SIZE(veml6030_channels), + .gain_rf = VEML6030_GAIN_RF, + .it_rf = VEML6030_IT_RF, .hw_init = veml6030_hw_init, .set_info = veml6030_set_info, .set_als_gain = veml6030_set_als_gain, @@ -1203,6 +1244,8 @@ static const struct veml603x_chip veml6035_chip = { .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals), .channels = veml6030_channels, .num_channels = ARRAY_SIZE(veml6030_channels), + .gain_rf = VEML6035_GAIN_RF, + .it_rf = VEML6030_IT_RF, .hw_init = veml6035_hw_init, .set_info = veml6030_set_info, .set_als_gain = veml6035_set_als_gain, @@ -1215,6 +1258,8 @@ static const struct veml603x_chip veml7700_chip = { .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals), .channels = veml7700_channels, .num_channels = ARRAY_SIZE(veml7700_channels), + .gain_rf = VEML6030_GAIN_RF, + .it_rf = VEML6030_IT_RF, .hw_init = veml6030_hw_init, .set_info = veml7700_set_info, .set_als_gain = veml6030_set_als_gain, -- 2.43.0