[PATCH linux dev-5.15 v1 2/7] iio: adc: npcm: Add NPCM8XX support
Tomer Maimon
tmaimon77 at gmail.com
Tue Aug 2 00:49:09 AEST 2022
Adding ADC NPCM8XX support to NPCM ADC driver.
ADC NPCM8XX uses a different resolution and voltage reference.
As part of adding NPCM8XX support:
- Add NPCM8XX specific compatible string.
- Add data to handle architecture-specific ADC parameters.
Signed-off-by: Tomer Maimon <tmaimon77 at gmail.com>
---
drivers/iio/adc/npcm_adc.c | 147 ++++++++++++++++++++++---------------
1 file changed, 87 insertions(+), 60 deletions(-)
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 62c1ef40b519..d1828e6f630c 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -16,6 +16,16 @@
#include <linux/uaccess.h>
#include <linux/reset.h>
+struct npcm_adc_info {
+ u32 data_mask;
+ u32 internal_vref;
+ u32 res_bits;
+ u32 min_val;
+ u32 max_val;
+ u32 const_r1;
+ u32 const_r2;
+};
+
struct npcm_adc {
u32 R05;
u32 R15;
@@ -36,6 +46,7 @@ struct npcm_adc {
* has finished.
*/
struct mutex lock;
+ const struct npcm_adc_info *data;
};
/* ADC registers */
@@ -54,49 +65,59 @@ struct npcm_adc {
#define NPCM_ADCCON_CH(x) ((x) << 24)
#define NPCM_ADCCON_DIV_SHIFT 1
#define NPCM_ADCCON_DIV_MASK GENMASK(8, 1)
-#define NPCM_ADC_DATA_MASK(x) ((x) & GENMASK(9, 0))
#define NPCM_ADC_ENABLE (NPCM_ADCCON_ADC_EN | NPCM_ADCCON_ADC_INT_EN)
-/* ADC General Definition */
-#define NPCM_RESOLUTION_BITS 10
-#define NPCM_INT_VREF_MV 2000
-
/* FUSE registers */
-#define NPCM7XX_FST 0x00
-#define NPCM7XX_FADDR 0x04
-#define NPCM7XX_FDATA 0x08
-#define NPCM7XX_FCFG 0x0C
-#define NPCM7XX_FCTL 0x14
+#define NPCM_FUSE_FST 0x00
+#define NPCM_FUSE_FADDR 0x04
+#define NPCM_FUSE_FDATA 0x08
+#define NPCM_FUSE_FCFG 0x0C
+#define NPCM_FUSE_FCTL 0x14
/* FST Register Bits */
-#define NPCM7XX_FST_RDY BIT(0)
-#define NPCM7XX_FST_RDST BIT(1)
+#define NPCM_FUSE_FST_RDY BIT(0)
+#define NPCM_FUSE_FST_RDST BIT(1)
/* FADDR Register Bits */
-#define NPCM7XX_FADDR_BYTEADDR BIT(0)
-#define NPCM7XX_FADDR_BYTEADDR_MASK GENMASK(9, 0)
+#define NPCM_FUSE_FADDR_BYTEADDR BIT(0)
+#define NPCM_FUSE_FADDR_BYTEADDR_MASK GENMASK(9, 0)
/* FADDR Register Bits */
-#define NPCM7XX_FDATA_DATA BIT(0)
-#define NPCM7XX_FDATA_CLEAN_VALUE BIT(1)
-#define NPCM7XX_FDATA_DATA_MASK GENMASK(7, 0)
+#define NPCM_FUSE_FDATA_DATA BIT(0)
+#define NPCM_FUSE_FDATA_CLEAN_VALUE BIT(1)
+#define NPCM_FUSE_FDATA_DATA_MASK GENMASK(7, 0)
/* FCTL Register Bits */
-#define NPCM7XX_FCTL_RDST BIT(1)
+#define NPCM_FUSE_FCTL_RDST BIT(1)
/* ADC Calibration Definition */
-#define NPCM_INT_1500MV 768
-#define NPCM_INT_1000MV 512
-#define NPCM_ADC_MIN_VAL 0
-#define NPCM_ADC_MAX_VAL 1023
-
#define FUSE_CALIB_ADDR 24
#define FUSE_CALIB_SIZE 8
#define DATA_CALIB_SIZE 4
#define FUSE_READ_SLEEP 500
#define FUSE_READ_TIMEOUT 1000000
+static const struct npcm_adc_info npxm7xx_adc_info = {
+ .data_mask = GENMASK(9, 0),
+ .internal_vref = 2048,
+ .res_bits = 10,
+ .min_val = 0,
+ .max_val = 1023,
+ .const_r1 = 512,
+ .const_r2 = 768
+};
+
+static const struct npcm_adc_info npxm8xx_adc_info = {
+ .data_mask = GENMASK(11, 0),
+ .internal_vref = 1229,
+ .res_bits = 12,
+ .min_val = 0,
+ .max_val = 4095,
+ .const_r1 = 1024,
+ .const_r2 = 3072
+};
+
#define NPCM_ADC_CHAN(ch) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -117,36 +138,36 @@ static const struct iio_chan_spec npcm_adc_iio_channels[] = {
NPCM_ADC_CHAN(7),
};
-static void npcm750_fuse_read(struct regmap *fuse_regmap, u32 addr, u8 *data)
+static void npcm_fuse_read(struct regmap *fuse_regmap, u32 addr, u8 *data)
{
u32 val;
u32 fstreg;
- regmap_read_poll_timeout(fuse_regmap, NPCM7XX_FST, fstreg,
- fstreg & NPCM7XX_FST_RDY, FUSE_READ_SLEEP,
+ regmap_read_poll_timeout(fuse_regmap, NPCM_FUSE_FST, fstreg,
+ fstreg & NPCM_FUSE_FST_RDY, FUSE_READ_SLEEP,
FUSE_READ_TIMEOUT);
- regmap_write_bits(fuse_regmap, NPCM7XX_FST,
- NPCM7XX_FST_RDST, NPCM7XX_FST_RDST);
+ regmap_write_bits(fuse_regmap, NPCM_FUSE_FST,
+ NPCM_FUSE_FST_RDST, NPCM_FUSE_FST_RDST);
- regmap_write_bits(fuse_regmap, NPCM7XX_FADDR,
- NPCM7XX_FADDR_BYTEADDR_MASK, addr);
- regmap_read(fuse_regmap, NPCM7XX_FADDR, &val);
- regmap_write(fuse_regmap, NPCM7XX_FCTL, NPCM7XX_FCTL_RDST);
+ regmap_write_bits(fuse_regmap, NPCM_FUSE_FADDR,
+ NPCM_FUSE_FADDR_BYTEADDR_MASK, addr);
+ regmap_read(fuse_regmap, NPCM_FUSE_FADDR, &val);
+ regmap_write(fuse_regmap, NPCM_FUSE_FCTL, NPCM_FUSE_FCTL_RDST);
- regmap_read_poll_timeout(fuse_regmap, NPCM7XX_FST, fstreg,
- fstreg & NPCM7XX_FST_RDY, FUSE_READ_SLEEP,
+ regmap_read_poll_timeout(fuse_regmap, NPCM_FUSE_FST, fstreg,
+ fstreg & NPCM_FUSE_FST_RDY, FUSE_READ_SLEEP,
FUSE_READ_TIMEOUT);
- regmap_write_bits(fuse_regmap, NPCM7XX_FST,
- NPCM7XX_FST_RDST, NPCM7XX_FST_RDST);
+ regmap_write_bits(fuse_regmap, NPCM_FUSE_FST,
+ NPCM_FUSE_FST_RDST, NPCM_FUSE_FST_RDST);
- regmap_read(fuse_regmap, NPCM7XX_FDATA, &val);
+ regmap_read(fuse_regmap, NPCM_FUSE_FDATA, &val);
*data = (u8)val;
- regmap_write_bits(fuse_regmap, NPCM7XX_FDATA, NPCM7XX_FDATA_DATA_MASK,
- NPCM7XX_FDATA_CLEAN_VALUE);
+ regmap_write_bits(fuse_regmap, NPCM_FUSE_FDATA, NPCM_FUSE_FDATA_DATA_MASK,
+ NPCM_FUSE_FDATA_CLEAN_VALUE);
}
-static int npcm750_ECC_to_nibble(u8 ECC, u8 nibble)
+static int npcm_ECC_to_nibble(u8 ECC, u8 nibble)
{
u8 nibble_b0 = (nibble >> 0) & BIT(0);
u8 nibble_b1 = (nibble >> 1) & BIT(0);
@@ -163,7 +184,7 @@ static int npcm750_ECC_to_nibble(u8 ECC, u8 nibble)
return 0;
}
-static int npcm750_ECC_to_byte(u16 ECC, u8 *Byte)
+static int npcm_ECC_to_byte(u16 ECC, u8 *Byte)
{
u8 nibble_L, nibble_H;
u8 ECC_L, ECC_H;
@@ -173,8 +194,8 @@ static int npcm750_ECC_to_byte(u16 ECC, u8 *Byte)
ECC_L = ECC >> 0;
nibble_L = ECC_L & 0x0F;
- if (npcm750_ECC_to_nibble(ECC_H, nibble_H) != 0 ||
- npcm750_ECC_to_nibble(ECC_L, nibble_L) != 0)
+ if (npcm_ECC_to_nibble(ECC_H, nibble_H) != 0 ||
+ npcm_ECC_to_nibble(ECC_L, nibble_L) != 0)
return -EINVAL;
*Byte = nibble_H << 4 | nibble_L << 0;
@@ -182,21 +203,21 @@ static int npcm750_ECC_to_byte(u16 ECC, u8 *Byte)
return 0;
}
-static int npcm750_read_nibble_parity(u8 *block_ECC, u8 *ADC_calib)
+static int npcm_read_nibble_parity(u8 *block_ECC, u8 *ADC_calib)
{
int i;
u16 ECC;
for (i = 0; i < DATA_CALIB_SIZE; i++) {
memcpy(&ECC, block_ECC + (i * 2), 2);
- if (npcm750_ECC_to_byte(ECC, &ADC_calib[i]) != 0)
+ if (npcm_ECC_to_byte(ECC, &ADC_calib[i]) != 0)
return -EINVAL;
}
return 0;
}
-static int npcm750_fuse_calibration_read(struct platform_device *pdev,
+static int npcm_fuse_calibration_read(struct platform_device *pdev,
struct npcm_adc *info)
{
struct device_node *np = pdev->dev.of_node;
@@ -213,13 +234,13 @@ static int npcm750_fuse_calibration_read(struct platform_device *pdev,
}
while (bytes_read < FUSE_CALIB_SIZE) {
- npcm750_fuse_read(fuse_regmap, addr,
+ npcm_fuse_read(fuse_regmap, addr,
&read_buf[bytes_read]);
bytes_read++;
addr++;
}
- if (npcm750_read_nibble_parity(read_buf, (u8 *)&ADC_calib)) {
+ if (npcm_read_nibble_parity(read_buf, (u8 *)&ADC_calib)) {
dev_warn(info->dev, "FUSE Calibration read failed\n");
return -EINVAL;
}
@@ -279,7 +300,8 @@ static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
if (ret < 0)
return ret;
- *val = NPCM_ADC_DATA_MASK(ioread32(info->regs + NPCM_ADCDATA));
+ *val = ioread32(info->regs + NPCM_ADCDATA);
+ *val &= info->data->data_mask;
return 0;
}
@@ -289,22 +311,22 @@ static void npcm_adc_calibration(int *val, struct npcm_adc *info)
int mul_val;
int offset_val;
- mul_val = NPCM_INT_1000MV * (*val - info->R15);
+ mul_val = info->data->const_r1 * (*val - info->R15);
if (mul_val < 0) {
mul_val = mul_val * -1;
offset_val = DIV_ROUND_CLOSEST(mul_val,
(info->R15 - info->R05));
- *val = NPCM_INT_1500MV - offset_val;
+ *val = info->data->const_r2 - offset_val;
} else {
offset_val = DIV_ROUND_CLOSEST(mul_val,
(info->R15 - info->R05));
- *val = NPCM_INT_1500MV + offset_val;
+ *val = info->data->const_r2 + offset_val;
}
- if (*val < NPCM_ADC_MIN_VAL)
- *val = NPCM_ADC_MIN_VAL;
- if (*val > NPCM_ADC_MAX_VAL)
- *val = NPCM_ADC_MAX_VAL;
+ if (*val < info->data->min_val)
+ *val = info->data->min_val;
+ if (*val > info->data->max_val)
+ *val = info->data->max_val;
}
static int npcm_adc_read_raw(struct iio_dev *indio_dev,
@@ -334,9 +356,9 @@ static int npcm_adc_read_raw(struct iio_dev *indio_dev,
vref_uv = regulator_get_voltage(info->vref);
*val = vref_uv / 1000;
} else {
- *val = NPCM_INT_VREF_MV;
+ *val = info->data->internal_vref;
}
- *val2 = NPCM_RESOLUTION_BITS;
+ *val2 = info->data->res_bits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = info->adc_sample_hz;
@@ -353,7 +375,8 @@ static const struct iio_info npcm_adc_iio_info = {
};
static const struct of_device_id npcm_adc_match[] = {
- { .compatible = "nuvoton,npcm750-adc", },
+ { .compatible = "nuvoton,npcm750-adc", .data = &npxm7xx_adc_info},
+ { .compatible = "nuvoton,npcm845-adc", .data = &npxm8xx_adc_info},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, npcm_adc_match);
@@ -373,6 +396,10 @@ static int npcm_adc_probe(struct platform_device *pdev)
return -ENOMEM;
info = iio_priv(indio_dev);
+ info->data = device_get_match_data(dev);
+ if (!info->data)
+ return -EINVAL;
+
mutex_init(&info->lock);
info->dev = &pdev->dev;
@@ -436,7 +463,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
info->regs + NPCM_ADCCON);
}
- npcm750_fuse_calibration_read(pdev, info);
+ npcm_fuse_calibration_read(pdev, info);
init_waitqueue_head(&info->wq);
reg_con = ioread32(info->regs + NPCM_ADCCON);
--
2.33.0
More information about the openbmc
mailing list