diff options
author | Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com> | 2024-12-06 13:13:32 +0200 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2024-12-11 19:19:07 +0000 |
commit | 6dd8a7712538a38ddc742adc0fc5c3361560235f (patch) | |
tree | 9d63e73cae1ae95ad2ba3b4190ca049aa4e21a0c /drivers/iio/adc | |
parent | a259a8465d3e9c744f990bda3582b5217562827f (diff) |
iio: adc: rzg2l_adc: Add support for channel 8
The ADC on the Renesas RZ/G3S SoC includes an additional channel (channel
8) dedicated to reading temperature values from the Thermal Sensor Unit
(TSU). There is a direct in-SoC connection between the ADC and TSU IPs.
To read the temperature reported by the TSU, a different sampling rate
(compared to channels 0-7) must be configured in the ADM3 register.
The rzg2l_adc driver has been updated to support reading the TSU
temperature.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://patch.msgid.link/20241206111337.726244-11-claudiu.beznea.uj@bp.renesas.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r-- | drivers/iio/adc/rzg2l_adc.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 4dd7cf3cfa45..d7f65a7b2bb0 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -52,12 +52,13 @@ #define RZG2L_ADCR(n) (0x30 + ((n) * 0x4)) #define RZG2L_ADCR_AD_MASK GENMASK(11, 0) -#define RZG2L_ADC_MAX_CHANNELS 8 +#define RZG2L_ADC_MAX_CHANNELS 9 #define RZG2L_ADC_TIMEOUT usecs_to_jiffies(1 * 4) /** * struct rzg2l_adc_hw_params - ADC hardware specific parameters - * @default_adsmp: default ADC sampling period (see ADM3 register) + * @default_adsmp: default ADC sampling period (see ADM3 register); index 0 is + * used for voltage channels, index 1 is used for temperature channel * @adsmp_mask: ADC sampling period mask (see ADM3 register) * @adint_inten_mask: conversion end interrupt mask (see ADINT register) * @default_adcmp: default ADC cmp (see ADM3 register) @@ -65,7 +66,7 @@ * @adivc: specifies if ADVIC register is available */ struct rzg2l_adc_hw_params { - u16 default_adsmp; + u16 default_adsmp[2]; u16 adsmp_mask; u16 adint_inten_mask; u8 default_adcmp; @@ -89,15 +90,26 @@ struct rzg2l_adc { u16 last_val[RZG2L_ADC_MAX_CHANNELS]; }; -static const char * const rzg2l_adc_channel_name[] = { - "adc0", - "adc1", - "adc2", - "adc3", - "adc4", - "adc5", - "adc6", - "adc7", +/** + * struct rzg2l_adc_channel - ADC channel descriptor + * @name: ADC channel name + * @type: ADC channel type + */ +struct rzg2l_adc_channel { + const char * const name; + enum iio_chan_type type; +}; + +static const struct rzg2l_adc_channel rzg2l_adc_channels[] = { + { "adc0", IIO_VOLTAGE }, + { "adc1", IIO_VOLTAGE }, + { "adc2", IIO_VOLTAGE }, + { "adc3", IIO_VOLTAGE }, + { "adc4", IIO_VOLTAGE }, + { "adc5", IIO_VOLTAGE }, + { "adc6", IIO_VOLTAGE }, + { "adc7", IIO_VOLTAGE }, + { "adc8", IIO_TEMP }, }; static unsigned int rzg2l_adc_readl(struct rzg2l_adc *adc, u32 reg) @@ -163,9 +175,18 @@ static void rzg2l_set_trigger(struct rzg2l_adc *adc) rzg2l_adc_writel(adc, RZG2L_ADM(1), reg); } +static u8 rzg2l_adc_ch_to_adsmp_index(u8 ch) +{ + if (rzg2l_adc_channels[ch].type == IIO_VOLTAGE) + return 0; + + return 1; +} + static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch) { const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; + u8 index = rzg2l_adc_ch_to_adsmp_index(ch); u32 reg; if (rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_ADBSY) @@ -179,6 +200,11 @@ static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch) reg |= BIT(ch); rzg2l_adc_writel(adc, RZG2L_ADM(2), reg); + reg = rzg2l_adc_readl(adc, RZG2L_ADM(3)); + reg &= ~hw_params->adsmp_mask; + reg |= hw_params->default_adsmp[index]; + rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); + /* * Setup ADINT * INTS[31] - Select pulse signal @@ -235,7 +261,7 @@ static int rzg2l_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: { - if (chan->type != IIO_VOLTAGE) + if (chan->type != IIO_VOLTAGE && chan->type != IIO_TEMP) return -EINVAL; guard(mutex)(&adc->lock); @@ -258,7 +284,7 @@ static int rzg2l_adc_read_label(struct iio_dev *iio_dev, const struct iio_chan_spec *chan, char *label) { - return sysfs_emit(label, "%s\n", rzg2l_adc_channel_name[chan->channel]); + return sysfs_emit(label, "%s\n", rzg2l_adc_channels[chan->channel].name); } static const struct iio_info rzg2l_adc_iio_info = { @@ -333,11 +359,11 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l if (channel >= hw_params->num_channels) return -EINVAL; - chan_array[i].type = IIO_VOLTAGE; + chan_array[i].type = rzg2l_adc_channels[channel].type; chan_array[i].indexed = 1; chan_array[i].channel = channel; chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - chan_array[i].datasheet_name = rzg2l_adc_channel_name[channel]; + chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name; i++; } @@ -387,7 +413,7 @@ static int rzg2l_adc_hw_init(struct device *dev, struct rzg2l_adc *adc) reg &= ~RZG2L_ADM3_ADCMP_MASK; reg &= ~hw_params->adsmp_mask; reg |= FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, hw_params->default_adcmp) | - hw_params->default_adsmp; + hw_params->default_adsmp[0]; rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); @@ -471,7 +497,7 @@ static int rzg2l_adc_probe(struct platform_device *pdev) static const struct rzg2l_adc_hw_params rzg2l_hw_params = { .num_channels = 8, .default_adcmp = 0xe, - .default_adsmp = 0x578, + .default_adsmp = { 0x578 }, .adsmp_mask = GENMASK(15, 0), .adint_inten_mask = GENMASK(7, 0), .adivc = true |