diff --git a/drivers/amlogic/iio/adc/meson_saradc.c b/drivers/amlogic/iio/adc/meson_saradc.c index dc58464eb710..a32565d97f0f 100644 --- a/drivers/amlogic/iio/adc/meson_saradc.c +++ b/drivers/amlogic/iio/adc/meson_saradc.c @@ -110,8 +110,8 @@ #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) #define MESON_SAR_ADC_AUX_SW 0x1c - #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan) \ - (GENMASK(10, 8) << (((_chan) - 2) * 2)) + #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ + (8 + (((_chan) - 2) * 3)) #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) @@ -174,6 +174,9 @@ */ #define MESON_SAR_ADC_REG11 0x2c #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0) + #define MESON_SAR_ADC_REG11_EOC BIT(1) + #define MESON_SAR_ADC_REG11_VREF_EN BIT(5) + #define MESON_SAR_ADC_REG11_CMV_SEL BIT(6) #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) #define MESON_SAR_ADC_REG11_CHNL_REGS_EN BIT(30) #define MESON_SAR_ADC_REG11_FIFO_EN BIT(31) @@ -305,9 +308,15 @@ enum vref_select { * * @reg3_ring_counter_disable: to disable continuous ring counter. * gxl and later: 1; others(gxtvbb etc): 0 + * @reg11_vref_en: g12a and later: 0; others(gxl etc): 1 + * @reg11_cmv_sel: g12a and later: 0; others(gxl etc): 1 + * @reg11_eoc: g12a and later: 1; others(gxl etc): 0 */ struct meson_sar_adc_reg_diff { bool reg3_ring_counter_disable; + bool reg11_vref_en; + bool reg11_cmv_sel; + bool reg11_eoc; }; /* @@ -330,6 +339,7 @@ struct meson_sar_adc_data { bool has_chnl_regs; unsigned int resolution; const char *name; + const struct regmap_config *regmap_config; struct meson_sar_adc_reg_diff regs_diff; }; @@ -351,13 +361,27 @@ struct meson_sar_adc_priv { u8 *datum_buf; }; -static const struct regmap_config meson_sar_adc_regmap_config = { +static const struct regmap_config meson_sar_adc_regmap_config_g12a = { .reg_bits = 8, .val_bits = 32, .reg_stride = 4, .max_register = MESON_SAR_ADC_CHNL67, }; +static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_REG13, +}; + +static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = MESON_SAR_ADC_DELTA_10, +}; + static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); @@ -529,7 +553,7 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); /* map channel index 0 to the channel which we want to read */ - regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx), + regval = chan->channel << MESON_SAR_ADC_CHAN_LIST_ENTRY_SHIFT(idx); regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(idx), regval); @@ -835,6 +859,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); int regval, ret; + int i; /* * make sure we start at CH7 input since the other muxes are only used @@ -895,6 +920,55 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN, priv->data->regs_diff.reg3_ring_counter_disable)); + + /* + * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW + * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) + */ + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); + + regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, + regval); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW, + MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); + /* + * set up the input channel muxes in MESON_SAR_ADC_AUX_SW + * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable + * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and + * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. + */ + regval = 0; + for (i = 2; i <= 7; i++) + regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); + regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; + regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; + regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); + + /* must be set to <1> for g12a and later SoCs */ + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_EOC, + FIELD_PREP(MESON_SAR_ADC_REG11_EOC, + priv->data->regs_diff.reg11_eoc)); + /* select the vref */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_VREF_SEL, @@ -922,9 +996,20 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) return ret; } + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_VREF_EN, + FIELD_PREP(MESON_SAR_ADC_REG11_VREF_EN, + priv->data->regs_diff.reg11_vref_en)); + + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, + MESON_SAR_ADC_REG11_CMV_SEL, + FIELD_PREP(MESON_SAR_ADC_REG11_CMV_SEL, + priv->data->regs_diff.reg11_cmv_sel)); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_BANDGAP_EN, MESON_SAR_ADC_REG11_BANDGAP_EN); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, MESON_SAR_ADC_REG3_ADC_EN, MESON_SAR_ADC_REG3_ADC_EN); @@ -1302,8 +1387,12 @@ struct meson_sar_adc_data meson_sar_adc_g12a_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-g12a-saradc", + .regmap_config = &meson_sar_adc_regmap_config_g12a, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_LOW, + .reg11_cmv_sel = BIT_LOW, + .reg11_eoc = BIT_HIGH, }, }; @@ -1313,8 +1402,12 @@ struct meson_sar_adc_data meson_sar_adc_txlx_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-txlx-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1324,8 +1417,12 @@ struct meson_sar_adc_data meson_sar_adc_axg_data = { .vref_sel = VDDA_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-axg-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1335,8 +1432,12 @@ struct meson_sar_adc_data meson_sar_adc_txl_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-txl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1346,8 +1447,12 @@ struct meson_sar_adc_data meson_sar_adc_gxl_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-gxl-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1357,8 +1462,12 @@ struct meson_sar_adc_data meson_sar_adc_gxm_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_12BIT, .name = "meson-gxm-saradc", + .regmap_config = &meson_sar_adc_regmap_config_gxbb, .regs_diff = { .reg3_ring_counter_disable = BIT_HIGH, + .reg11_vref_en = BIT_HIGH, + .reg11_cmv_sel = BIT_HIGH, + .reg11_eoc = BIT_LOW, }, }; @@ -1368,6 +1477,7 @@ struct meson_sar_adc_data meson_sar_adc_m8b_data = { .vref_sel = CALIB_VOL_AS_VREF, .resolution = SAR_ADC_10BIT, .name = "meson-m8b-saradc", + .regmap_config = &meson_sar_adc_regmap_config_meson8, .regs_diff = { .reg3_ring_counter_disable = BIT_LOW, }, @@ -1443,7 +1553,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return -EINVAL; priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &meson_sar_adc_regmap_config); + priv->data->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap);