Commit 3a06b284 authored by George Stark's avatar George Stark Committed by Jonathan Cameron
Browse files

iio: adc: meson: support reading from channel 7 mux inputs



Add IIO channel for all muxed inputs of channel 7.
Meson saradc channel 7 is connected to a mux that can switch input
to well-known sources like Vdd, GND and several Vdd dividers.

Signed-off-by: default avatarGeorge Stark <GNStark@sberdevices.ru>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20230714114010.293440-7-gnstark@sberdevices.ru


Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent b593ce5d
Loading
Loading
Loading
Loading
+75 −2
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@
#define MESON_SAR_ADC_MAX_FIFO_SIZE				32
#define MESON_SAR_ADC_TIMEOUT					100 /* ms */
#define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL			6
#define MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL			7
#define MESON_SAR_ADC_TEMP_OFFSET				27

/* temperature sensor calibration information in eFuse */
@@ -202,6 +203,19 @@
	.datasheet_name = "TEMP_SENSOR",				\
}

#define MESON_SAR_ADC_MUX(_chan, _sel) {				\
	.type = IIO_VOLTAGE,						\
	.channel = _chan,						\
	.indexed = 1,							\
	.address = MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL,		\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
				BIT(IIO_CHAN_INFO_AVERAGE_RAW),		\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) |	\
				BIT(IIO_CHAN_INFO_CALIBSCALE),		\
	.datasheet_name = "SAR_ADC_MUX_"#_sel,				\
}

enum meson_sar_adc_avg_mode {
	NO_AVERAGING = 0x0,
	MEAN_AVERAGING = 0x1,
@@ -234,6 +248,27 @@ enum meson_sar_adc_channel_index {
	NUM_CHAN_6,
	NUM_CHAN_7,
	NUM_CHAN_TEMP,
	NUM_MUX_0_VSS,
	NUM_MUX_1_VDD_DIV4,
	NUM_MUX_2_VDD_DIV2,
	NUM_MUX_3_VDD_MUL3_DIV4,
	NUM_MUX_4_VDD,
};

static enum meson_sar_adc_chan7_mux_sel chan7_mux_values[] = {
	CHAN7_MUX_VSS,
	CHAN7_MUX_VDD_DIV4,
	CHAN7_MUX_VDD_DIV2,
	CHAN7_MUX_VDD_MUL3_DIV4,
	CHAN7_MUX_VDD,
};

static const char * const chan7_mux_names[] = {
	[CHAN7_MUX_VSS] = "gnd",
	[CHAN7_MUX_VDD_DIV4] = "0.25vdd",
	[CHAN7_MUX_VDD_DIV2] = "0.5vdd",
	[CHAN7_MUX_VDD_MUL3_DIV4] = "0.75vdd",
	[CHAN7_MUX_VDD] = "vdd",
};

static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
@@ -245,6 +280,11 @@ static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
	MESON_SAR_ADC_CHAN(NUM_CHAN_5),
	MESON_SAR_ADC_CHAN(NUM_CHAN_6),
	MESON_SAR_ADC_CHAN(NUM_CHAN_7),
	MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
	MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
	MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
	MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
	MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
};

static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = {
@@ -257,6 +297,11 @@ static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = {
	MESON_SAR_ADC_CHAN(NUM_CHAN_6),
	MESON_SAR_ADC_CHAN(NUM_CHAN_7),
	MESON_SAR_ADC_TEMP_CHAN(NUM_CHAN_TEMP),
	MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
	MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
	MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
	MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
	MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
};

struct meson_sar_adc_param {
@@ -295,6 +340,7 @@ struct meson_sar_adc_priv {
	bool					temperature_sensor_calibrated;
	u8					temperature_sensor_coefficient;
	u16					temperature_sensor_adc_val;
	enum meson_sar_adc_chan7_mux_sel	chan7_mux_sel;
};

static const struct regmap_config meson_sar_adc_regmap_config_gxbb = {
@@ -311,6 +357,17 @@ static const struct regmap_config meson_sar_adc_regmap_config_meson8 = {
	.max_register = MESON_SAR_ADC_DELTA_10,
};

static const struct iio_chan_spec *
find_channel_by_num(struct iio_dev *indio_dev, int num)
{
	int i;

	for (i = 0; i < indio_dev->num_channels; i++)
		if (indio_dev->channels[i].channel == num)
			return &indio_dev->channels[i];
	return NULL;
}

static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
{
	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
@@ -359,6 +416,8 @@ static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev,
			   MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);

	usleep_range(10, 20);

	priv->chan7_mux_sel = sel;
}

static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
@@ -454,6 +513,15 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
		regmap_update_bits(priv->regmap,
				   MESON_SAR_ADC_DELTA_10,
				   MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval);
	} else if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL) {
		enum meson_sar_adc_chan7_mux_sel sel;

		if (chan->channel == NUM_CHAN_7)
			sel = CHAN7_MUX_CH7_INPUT;
		else
			sel = chan7_mux_values[chan->channel - NUM_MUX_0_VSS];
		if (sel != priv->chan7_mux_sel)
			meson_sar_adc_set_chan7_mux(indio_dev, sel);
	}
}

@@ -1026,7 +1094,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
	meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
	usleep_range(10, 20);
	ret = meson_sar_adc_get_sample(indio_dev,
				       &indio_dev->channels[7],
				       find_channel_by_num(indio_dev,
							   NUM_MUX_1_VDD_DIV4),
				       MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
	if (ret < 0)
		goto out;
@@ -1034,7 +1103,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
	meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
	usleep_range(10, 20);
	ret = meson_sar_adc_get_sample(indio_dev,
				       &indio_dev->channels[7],
				       find_channel_by_num(indio_dev,
							   NUM_MUX_3_VDD_MUL3_DIV4),
				       MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
	if (ret < 0)
		goto out;
@@ -1061,6 +1131,9 @@ static int read_label(struct iio_dev *indio_dev,
{
	if (chan->type == IIO_TEMP)
		return sprintf(label, "temp-sensor\n");
	if (chan->type == IIO_VOLTAGE && chan->channel >= NUM_MUX_0_VSS)
		return sprintf(label, "%s\n",
			       chan7_mux_names[chan->channel - NUM_MUX_0_VSS]);
	if (chan->type == IIO_VOLTAGE)
		return sprintf(label, "channel-%d\n", chan->channel);
	return 0;