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: aspeed: Reserve battery sensing channel for on-demand use

For controllers with battery sensing capability (AST2600/AST2700), the
last channel uses a different circuit design optimized for battery
voltage measurement. This channel should not be enabled by default
along with other channels to avoid potential interference and power
efficiency issues.
This ensures optimal power efficiency for normal ADC operations while
maintaining full functionality when battery sensing is needed.

Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Billy Tsai and committed by
Jonathan Cameron
58b98c66 66ab53c2

+31 -7
+31 -7
drivers/iio/adc/aspeed_adc.c
··· 138 138 139 139 static inline unsigned int aspeed_adc_get_active_channels(const struct aspeed_adc_data *data) 140 140 { 141 + /* 142 + * For controllers with battery sensing capability, the last channel 143 + * is reserved for battery sensing and should not be included in 144 + * normal channel operations. 145 + */ 146 + if (data->model_data->bat_sense_sup) 147 + return data->model_data->num_channels - 1; 141 148 return data->model_data->num_channels; 142 149 } 143 150 ··· 263 256 ASPEED_ADC_CTRL_CHANNEL_ENABLE(0), 264 257 data->base + ASPEED_REG_ENGINE_CONTROL); 265 258 /* 266 - * After enable compensating sensing mode need to wait some time for ADC stable 267 - * Experiment result is 1ms. 259 + * After enable compensating sensing mode need to wait some time for the 260 + * ADC stablize. Experiment result is 1ms. 268 261 */ 269 262 fsleep(1000); 270 263 ··· 312 305 313 306 switch (mask) { 314 307 case IIO_CHAN_INFO_RAW: 308 + adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); 309 + /* 310 + * For battery sensing capable controllers, we need to enable 311 + * the specific channel before reading. This is required because 312 + * the battery channel may not be enabled by default. 313 + */ 314 + if (data->model_data->bat_sense_sup && 315 + chan->channel == ASPEED_ADC_BATTERY_CHANNEL) { 316 + u32 ctrl_reg = adc_engine_control_reg_val & ~ASPEED_ADC_CTRL_CHANNEL; 317 + 318 + ctrl_reg |= ASPEED_ADC_CTRL_CHANNEL_ENABLE(chan->channel); 319 + writel(ctrl_reg, data->base + ASPEED_REG_ENGINE_CONTROL); 320 + /* 321 + * After enable a new channel need to wait some time for ADC stable 322 + * Experiment result is 1ms. 323 + */ 324 + fsleep(1000); 325 + } 326 + 315 327 if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) { 316 - adc_engine_control_reg_val = 317 - readl(data->base + ASPEED_REG_ENGINE_CONTROL); 318 328 writel(adc_engine_control_reg_val | 319 329 FIELD_PREP(ASPEED_ADC_CH7_MODE, 320 330 ASPEED_ADC_CH7_BAT) | ··· 345 321 *val = readw(data->base + chan->address); 346 322 *val = (*val * data->battery_mode_gain.mult) / 347 323 data->battery_mode_gain.div; 348 - /* Restore control register value */ 349 - writel(adc_engine_control_reg_val, 350 - data->base + ASPEED_REG_ENGINE_CONTROL); 351 324 } else 352 325 *val = readw(data->base + chan->address); 326 + /* Restore control register value */ 327 + writel(adc_engine_control_reg_val, 328 + data->base + ASPEED_REG_ENGINE_CONTROL); 353 329 return IIO_VAL_INT; 354 330 355 331 case IIO_CHAN_INFO_OFFSET: