* [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use
@ 2026-03-20 5:46 Billy Tsai
2026-03-20 5:46 ` [PATCH v3 1/4] iio: adc: Add battery channel definition for ADC Billy Tsai
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Billy Tsai @ 2026-03-20 5:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery
Cc: linux-iio, linux-arm-kernel, linux-aspeed, linux-kernel,
morris_mao, Billy Tsai, Andy Shevchenko
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.
Changes made:
- Introduce aspeed_adc_get_active_channels() to return the number of
channels that should be enabled by default
- For battery sensing capable controllers, exclude the last channel
from the default channel enable mask
- Enable the battery sensing channel only when explicitly accessed
via read_raw()
- Replace hardcoded channel numbers with ASPEED_ADC_BATTERY_CHANNEL macro
- Add helper functions for cleaner channel management
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>
---
Changes in v3:
- Simplify channel mask helper as suggested by Andy
- Use FIELD_MODIFY() when updating ADC channel field instead of open-coded OR
- Move unrelated blank line change to the previous patch
- Replace mdelay(1) with fsleep(1000) since the delay is in sleepable context
- Fix comment typo ("adc" -> "ADC")
- Link to v2: https://lore.kernel.org/r/20260316-adc-v2-0-21475a217b09@aspeedtech.com
Changes in v2:
- Split the changes into a series of patches for better clarity and
review
- Link to v1: https://lore.kernel.org/r/20260313-adc-v1-1-7a2edb4e5664@aspeedtech.com
---
Billy Tsai (4):
iio: adc: Add battery channel definition for ADC
iio: adc: Enable multiple consecutive channels based on model data
iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay
iio: adc: aspeed: Reserve battery sensing channel for on-demand use
drivers/iio/adc/aspeed_adc.c | 68 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 57 insertions(+), 11 deletions(-)
---
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
change-id: 20260313-adc-479b0ab09bae
Best regards,
--
Billy Tsai <billy_tsai@aspeedtech.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 1/4] iio: adc: Add battery channel definition for ADC
2026-03-20 5:46 [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
@ 2026-03-20 5:46 ` Billy Tsai
2026-03-20 5:46 ` [PATCH v3 2/4] iio: adc: Enable multiple consecutive channels based on model data Billy Tsai
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Billy Tsai @ 2026-03-20 5:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery
Cc: linux-iio, linux-arm-kernel, linux-aspeed, linux-kernel,
morris_mao, Billy Tsai
Defines a constant for the battery sensing channel, typically the last
channel of the ADC. Clarifies channel usage and improves code
readability.
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
drivers/iio/adc/aspeed_adc.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 4be44c524b4d..8eebaa3dc534 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -75,6 +75,8 @@
#define ASPEED_ADC_INIT_POLLING_TIME 500
#define ASPEED_ADC_INIT_TIMEOUT 500000
+/* Battery sensing is typically on the last channel */
+#define ASPEED_ADC_BATTERY_CHANNEL 7
/*
* When the sampling rate is too high, the ADC may not have enough charging
* time, resulting in a low voltage value. Thus, the default uses a slow
@@ -285,7 +287,7 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- if (data->battery_sensing && chan->channel == 7) {
+ if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) {
adc_engine_control_reg_val =
readl(data->base + ASPEED_REG_ENGINE_CONTROL);
writel(adc_engine_control_reg_val |
@@ -309,7 +311,7 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
- if (data->battery_sensing && chan->channel == 7)
+ if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL)
*val = (data->cv * data->battery_mode_gain.mult) /
data->battery_mode_gain.div;
else
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/4] iio: adc: Enable multiple consecutive channels based on model data
2026-03-20 5:46 [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
2026-03-20 5:46 ` [PATCH v3 1/4] iio: adc: Add battery channel definition for ADC Billy Tsai
@ 2026-03-20 5:46 ` Billy Tsai
2026-03-20 5:46 ` [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay Billy Tsai
2026-03-20 5:46 ` [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
3 siblings, 0 replies; 9+ messages in thread
From: Billy Tsai @ 2026-03-20 5:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery
Cc: linux-iio, linux-arm-kernel, linux-aspeed, linux-kernel,
morris_mao, Billy Tsai
Add helpers to generate channel masks and enable multiple ADC channels
according to the device model's channel count.
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
drivers/iio/adc/aspeed_adc.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 8eebaa3dc534..3ff24474f394 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -123,6 +123,24 @@ struct aspeed_adc_data {
struct adc_gain battery_mode_gain;
};
+/*
+ * Enable multiple consecutive channels starting from channel 0.
+ * This creates a bitmask for channels 0 to (num_channels - 1).
+ * For example: num_channels=3 creates mask 0x0007 (channels 0,1,2)
+ */
+static inline u32 aspeed_adc_channels_mask(unsigned int num_channels)
+{
+ if (num_channels > 16)
+ return GENMASK(15, 0);
+
+ return BIT(num_channels) - 1;
+}
+
+static inline unsigned int aspeed_adc_get_active_channels(const struct aspeed_adc_data *data)
+{
+ return data->model_data->num_channels;
+}
+
#define ASPEED_CHAN(_idx, _data_reg_addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -612,7 +630,9 @@ static int aspeed_adc_probe(struct platform_device *pdev)
/* Start all channels in normal mode. */
adc_engine_control_reg_val =
readl(data->base + ASPEED_REG_ENGINE_CONTROL);
- adc_engine_control_reg_val |= ASPEED_ADC_CTRL_CHANNEL;
+ FIELD_MODIFY(ASPEED_ADC_CTRL_CHANNEL, &adc_engine_control_reg_val,
+ aspeed_adc_channels_mask(aspeed_adc_get_active_channels(data)));
+
writel(adc_engine_control_reg_val,
data->base + ASPEED_REG_ENGINE_CONTROL);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay
2026-03-20 5:46 [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
2026-03-20 5:46 ` [PATCH v3 1/4] iio: adc: Add battery channel definition for ADC Billy Tsai
2026-03-20 5:46 ` [PATCH v3 2/4] iio: adc: Enable multiple consecutive channels based on model data Billy Tsai
@ 2026-03-20 5:46 ` Billy Tsai
2026-03-20 10:31 ` Andy Shevchenko
2026-03-20 5:46 ` [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
3 siblings, 1 reply; 9+ messages in thread
From: Billy Tsai @ 2026-03-20 5:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery
Cc: linux-iio, linux-arm-kernel, linux-aspeed, linux-kernel,
morris_mao, Billy Tsai, Andy Shevchenko
The ADC stabilization delays in compensation mode and battery sensing
mode do not require atomic context. Using mdelay() here results in
unnecessary busy waiting.
Replace mdelay(1) with fsleep(1000) to allow the scheduler to run other
tasks while waiting for the ADC to stabilize.
Also fix a minor typo in the comment ("adc" -> "ADC").
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
drivers/iio/adc/aspeed_adc.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 3ff24474f394..a1a6296d3003 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -259,7 +259,7 @@ static int aspeed_adc_compensation(struct iio_dev *indio_dev)
* After enable compensating sensing mode need to wait some time for ADC stable
* Experiment result is 1ms.
*/
- mdelay(1);
+ fsleep(1000);
for (index = 0; index < 16; index++) {
/*
@@ -314,10 +314,10 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
ASPEED_ADC_BAT_SENSING_ENABLE,
data->base + ASPEED_REG_ENGINE_CONTROL);
/*
- * After enable battery sensing mode need to wait some time for adc stable
+ * After enable battery sensing mode need to wait some time for ADC stable
* Experiment result is 1ms.
*/
- mdelay(1);
+ fsleep(1000);
*val = readw(data->base + chan->address);
*val = (*val * data->battery_mode_gain.mult) /
data->battery_mode_gain.div;
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use
2026-03-20 5:46 [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
` (2 preceding siblings ...)
2026-03-20 5:46 ` [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay Billy Tsai
@ 2026-03-20 5:46 ` Billy Tsai
2026-03-20 10:33 ` Andy Shevchenko
3 siblings, 1 reply; 9+ messages in thread
From: Billy Tsai @ 2026-03-20 5:46 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery
Cc: linux-iio, linux-arm-kernel, linux-aspeed, linux-kernel,
morris_mao, Billy Tsai
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>
---
drivers/iio/adc/aspeed_adc.c | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index a1a6296d3003..b3dee172adbf 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -138,6 +138,13 @@ static inline u32 aspeed_adc_channels_mask(unsigned int num_channels)
static inline unsigned int aspeed_adc_get_active_channels(const struct aspeed_adc_data *data)
{
+ /*
+ * For controllers with battery sensing capability, the last channel
+ * is reserved for battery sensing and should not be included in
+ * normal channel operations.
+ */
+ if (data->model_data->bat_sense_sup)
+ return data->model_data->num_channels - 1;
return data->model_data->num_channels;
}
@@ -305,9 +312,26 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+ /*
+ * For battery sensing capable controllers, we need to enable
+ * the specific channel before reading. This is required because
+ * the battery channel may not be enabled by default.
+ */
+ if (data->model_data->bat_sense_sup &&
+ chan->channel == ASPEED_ADC_BATTERY_CHANNEL) {
+ u32 ctrl_reg = adc_engine_control_reg_val & ~ASPEED_ADC_CTRL_CHANNEL;
+
+ ctrl_reg |= ASPEED_ADC_CTRL_CHANNEL_ENABLE(chan->channel);
+ writel(ctrl_reg, data->base + ASPEED_REG_ENGINE_CONTROL);
+ /*
+ * After enable a new channel need to wait some time for ADC stable
+ * Experiment result is 1ms.
+ */
+ fsleep(1000);
+ }
+
if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) {
- adc_engine_control_reg_val =
- readl(data->base + ASPEED_REG_ENGINE_CONTROL);
writel(adc_engine_control_reg_val |
FIELD_PREP(ASPEED_ADC_CH7_MODE,
ASPEED_ADC_CH7_BAT) |
@@ -321,11 +345,11 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
*val = readw(data->base + chan->address);
*val = (*val * data->battery_mode_gain.mult) /
data->battery_mode_gain.div;
- /* Restore control register value */
- writel(adc_engine_control_reg_val,
- data->base + ASPEED_REG_ENGINE_CONTROL);
} else
*val = readw(data->base + chan->address);
+ /* Restore control register value */
+ writel(adc_engine_control_reg_val,
+ data->base + ASPEED_REG_ENGINE_CONTROL);
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay
2026-03-20 5:46 ` [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay Billy Tsai
@ 2026-03-20 10:31 ` Andy Shevchenko
2026-03-21 15:49 ` Jonathan Cameron
0 siblings, 1 reply; 9+ messages in thread
From: Andy Shevchenko @ 2026-03-20 10:31 UTC (permalink / raw)
To: Billy Tsai
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery, linux-iio, linux-arm-kernel,
linux-aspeed, linux-kernel, morris_mao
On Fri, Mar 20, 2026 at 01:46:37PM +0800, Billy Tsai wrote:
> The ADC stabilization delays in compensation mode and battery sensing
> mode do not require atomic context. Using mdelay() here results in
> unnecessary busy waiting.
>
> Replace mdelay(1) with fsleep(1000) to allow the scheduler to run other
> tasks while waiting for the ADC to stabilize.
>
> Also fix a minor typo in the comment ("adc" -> "ADC").
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
I haven't suggested the idea, I only suggested to use fsleep() for the purpose.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use
2026-03-20 5:46 ` [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
@ 2026-03-20 10:33 ` Andy Shevchenko
2026-03-21 15:51 ` Jonathan Cameron
0 siblings, 1 reply; 9+ messages in thread
From: Andy Shevchenko @ 2026-03-20 10:33 UTC (permalink / raw)
To: Billy Tsai
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery, linux-iio, linux-arm-kernel,
linux-aspeed, linux-kernel, morris_mao
On Fri, Mar 20, 2026 at 01:46:38PM +0800, Billy Tsai wrote:
> 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.
...
> + /*
> + * After enable a new channel need to wait some time for ADC stable
Missed period at the end. And you probably wanted to say
"...for ADC to stabilize."
> + * Experiment result is 1ms.
> + */
> + fsleep(1000);
> + }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay
2026-03-20 10:31 ` Andy Shevchenko
@ 2026-03-21 15:49 ` Jonathan Cameron
0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2026-03-21 15:49 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Billy Tsai, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery, linux-iio, linux-arm-kernel,
linux-aspeed, linux-kernel, morris_mao
On Fri, 20 Mar 2026 12:31:41 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> On Fri, Mar 20, 2026 at 01:46:37PM +0800, Billy Tsai wrote:
> > The ADC stabilization delays in compensation mode and battery sensing
> > mode do not require atomic context. Using mdelay() here results in
> > unnecessary busy waiting.
> >
> > Replace mdelay(1) with fsleep(1000) to allow the scheduler to run other
> > tasks while waiting for the ADC to stabilize.
> >
> > Also fix a minor typo in the comment ("adc" -> "ADC").
>
> > Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> I haven't suggested the idea, I only suggested to use fsleep() for the purpose.
Dropped the tag.
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use
2026-03-20 10:33 ` Andy Shevchenko
@ 2026-03-21 15:51 ` Jonathan Cameron
0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2026-03-21 15:51 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Billy Tsai, David Lechner, Nuno Sá, Andy Shevchenko,
Joel Stanley, Andrew Jeffery, linux-iio, linux-arm-kernel,
linux-aspeed, linux-kernel, morris_mao
On Fri, 20 Mar 2026 12:33:32 +0200
Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
> On Fri, Mar 20, 2026 at 01:46:38PM +0800, Billy Tsai wrote:
> > 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.
>
>
> ...
>
> > + /*
> > + * After enable a new channel need to wait some time for ADC stable
>
> Missed period at the end. And you probably wanted to say
> "...for ADC to stabilize."
Tweaked and tidied up line wrap.
Series applied to the togreg branch of iio.git.
thanks,
Jonathan
>
> > + * Experiment result is 1ms.
> > + */
> > + fsleep(1000);
> > + }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-03-21 15:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-20 5:46 [PATCH v3 0/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
2026-03-20 5:46 ` [PATCH v3 1/4] iio: adc: Add battery channel definition for ADC Billy Tsai
2026-03-20 5:46 ` [PATCH v3 2/4] iio: adc: Enable multiple consecutive channels based on model data Billy Tsai
2026-03-20 5:46 ` [PATCH v3 3/4] iio: adc: aspeed: Replace mdelay() with fsleep() for ADC stabilization delay Billy Tsai
2026-03-20 10:31 ` Andy Shevchenko
2026-03-21 15:49 ` Jonathan Cameron
2026-03-20 5:46 ` [PATCH v3 4/4] iio: adc: aspeed: Reserve battery sensing channel for on-demand use Billy Tsai
2026-03-20 10:33 ` Andy Shevchenko
2026-03-21 15:51 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox