#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)
*/
#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)
*
* @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;
};
/*
bool has_chnl_regs;
unsigned int resolution;
const char *name;
+ const struct regmap_config *regmap_config;
struct meson_sar_adc_reg_diff regs_diff;
};
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);
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);
{
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
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,
}
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);
.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,
},
};
.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,
},
};
.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,
},
};
.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,
},
};
.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,
},
};
.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,
},
};
.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,
},
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);