[PATCH v2 1/4] iio: light: veml6030: extend regmap to support regfields

Javier Carrasco
2025-01-19T17:32:04Z

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@gmail.com>
---
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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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