Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Claudiu Beznea and committed by
Jonathan Cameron
6dd8a771 a259a846

+44 -18
+44 -18
drivers/iio/adc/rzg2l_adc.c
··· 52 52 #define RZG2L_ADCR(n) (0x30 + ((n) * 0x4)) 53 53 #define RZG2L_ADCR_AD_MASK GENMASK(11, 0) 54 54 55 - #define RZG2L_ADC_MAX_CHANNELS 8 55 + #define RZG2L_ADC_MAX_CHANNELS 9 56 56 #define RZG2L_ADC_TIMEOUT usecs_to_jiffies(1 * 4) 57 57 58 58 /** 59 59 * struct rzg2l_adc_hw_params - ADC hardware specific parameters 60 - * @default_adsmp: default ADC sampling period (see ADM3 register) 60 + * @default_adsmp: default ADC sampling period (see ADM3 register); index 0 is 61 + * used for voltage channels, index 1 is used for temperature channel 61 62 * @adsmp_mask: ADC sampling period mask (see ADM3 register) 62 63 * @adint_inten_mask: conversion end interrupt mask (see ADINT register) 63 64 * @default_adcmp: default ADC cmp (see ADM3 register) ··· 66 65 * @adivc: specifies if ADVIC register is available 67 66 */ 68 67 struct rzg2l_adc_hw_params { 69 - u16 default_adsmp; 68 + u16 default_adsmp[2]; 70 69 u16 adsmp_mask; 71 70 u16 adint_inten_mask; 72 71 u8 default_adcmp; ··· 90 89 u16 last_val[RZG2L_ADC_MAX_CHANNELS]; 91 90 }; 92 91 93 - static const char * const rzg2l_adc_channel_name[] = { 94 - "adc0", 95 - "adc1", 96 - "adc2", 97 - "adc3", 98 - "adc4", 99 - "adc5", 100 - "adc6", 101 - "adc7", 92 + /** 93 + * struct rzg2l_adc_channel - ADC channel descriptor 94 + * @name: ADC channel name 95 + * @type: ADC channel type 96 + */ 97 + struct rzg2l_adc_channel { 98 + const char * const name; 99 + enum iio_chan_type type; 100 + }; 101 + 102 + static const struct rzg2l_adc_channel rzg2l_adc_channels[] = { 103 + { "adc0", IIO_VOLTAGE }, 104 + { "adc1", IIO_VOLTAGE }, 105 + { "adc2", IIO_VOLTAGE }, 106 + { "adc3", IIO_VOLTAGE }, 107 + { "adc4", IIO_VOLTAGE }, 108 + { "adc5", IIO_VOLTAGE }, 109 + { "adc6", IIO_VOLTAGE }, 110 + { "adc7", IIO_VOLTAGE }, 111 + { "adc8", IIO_TEMP }, 102 112 }; 103 113 104 114 static unsigned int rzg2l_adc_readl(struct rzg2l_adc *adc, u32 reg) ··· 175 163 rzg2l_adc_writel(adc, RZG2L_ADM(1), reg); 176 164 } 177 165 166 + static u8 rzg2l_adc_ch_to_adsmp_index(u8 ch) 167 + { 168 + if (rzg2l_adc_channels[ch].type == IIO_VOLTAGE) 169 + return 0; 170 + 171 + return 1; 172 + } 173 + 178 174 static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch) 179 175 { 180 176 const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; 177 + u8 index = rzg2l_adc_ch_to_adsmp_index(ch); 181 178 u32 reg; 182 179 183 180 if (rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_ADBSY) ··· 199 178 reg &= ~GENMASK(hw_params->num_channels - 1, 0); 200 179 reg |= BIT(ch); 201 180 rzg2l_adc_writel(adc, RZG2L_ADM(2), reg); 181 + 182 + reg = rzg2l_adc_readl(adc, RZG2L_ADM(3)); 183 + reg &= ~hw_params->adsmp_mask; 184 + reg |= hw_params->default_adsmp[index]; 185 + rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); 202 186 203 187 /* 204 188 * Setup ADINT ··· 261 235 262 236 switch (mask) { 263 237 case IIO_CHAN_INFO_RAW: { 264 - if (chan->type != IIO_VOLTAGE) 238 + if (chan->type != IIO_VOLTAGE && chan->type != IIO_TEMP) 265 239 return -EINVAL; 266 240 267 241 guard(mutex)(&adc->lock); ··· 284 258 const struct iio_chan_spec *chan, 285 259 char *label) 286 260 { 287 - return sysfs_emit(label, "%s\n", rzg2l_adc_channel_name[chan->channel]); 261 + return sysfs_emit(label, "%s\n", rzg2l_adc_channels[chan->channel].name); 288 262 } 289 263 290 264 static const struct iio_info rzg2l_adc_iio_info = { ··· 359 333 if (channel >= hw_params->num_channels) 360 334 return -EINVAL; 361 335 362 - chan_array[i].type = IIO_VOLTAGE; 336 + chan_array[i].type = rzg2l_adc_channels[channel].type; 363 337 chan_array[i].indexed = 1; 364 338 chan_array[i].channel = channel; 365 339 chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 366 - chan_array[i].datasheet_name = rzg2l_adc_channel_name[channel]; 340 + chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name; 367 341 i++; 368 342 } 369 343 ··· 413 387 reg &= ~RZG2L_ADM3_ADCMP_MASK; 414 388 reg &= ~hw_params->adsmp_mask; 415 389 reg |= FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, hw_params->default_adcmp) | 416 - hw_params->default_adsmp; 390 + hw_params->default_adsmp[0]; 417 391 418 392 rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); 419 393 ··· 497 471 static const struct rzg2l_adc_hw_params rzg2l_hw_params = { 498 472 .num_channels = 8, 499 473 .default_adcmp = 0xe, 500 - .default_adsmp = 0x578, 474 + .default_adsmp = { 0x578 }, 501 475 .adsmp_mask = GENMASK(15, 0), 502 476 .adint_inten_mask = GENMASK(7, 0), 503 477 .adivc = true