summaryrefslogtreecommitdiff
path: root/drivers/adc/stm32-adc.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-12-08 11:25:08 -0500
committerTom Rini <trini@konsulko.com>2022-12-08 11:25:08 -0500
commit8f170408774b30aa4ee91b3cc90ba09b564d4651 (patch)
treeaa824cc20329e70de53c3bcaaa934223631b6553 /drivers/adc/stm32-adc.c
parent573359d14d961a317de276ace16f8151788d1f71 (diff)
parentf708283ab9d984c025f10dbd22f619d1d6cf0175 (diff)
Merge tag 'u-boot-stm32-20221207' of https://source.denx.de/u-boot/custodians/u-boot-stm
- Drop MMCI interrupt-names in STM32H743, STM32MP15 and STM322MP13 DT DHSOM: - Enable assorted ST specific commands - Add version variable - Add boot counter STM32MP13: - Add sdmmc cd-gpios for STM32MP135F-DK - Add clock & reset support STM32 ADC: - Split channel init into several routines - Add support of generic channels binding
Diffstat (limited to 'drivers/adc/stm32-adc.c')
-rw-r--r--drivers/adc/stm32-adc.c83
1 files changed, 73 insertions, 10 deletions
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
index ad8d1a32cdb..85efc119dbf 100644
--- a/drivers/adc/stm32-adc.c
+++ b/drivers/adc/stm32-adc.c
@@ -162,12 +162,8 @@ static int stm32_adc_channel_data(struct udevice *dev, int channel,
return 0;
}
-static int stm32_adc_chan_of_init(struct udevice *dev)
+static int stm32_adc_get_legacy_chan_count(struct udevice *dev)
{
- struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
- struct stm32_adc *adc = dev_get_priv(dev);
- u32 chans[STM32_ADC_CH_MAX];
- unsigned int i, num_channels;
int ret;
/* Retrieve single ended channels listed in device tree */
@@ -176,12 +172,16 @@ static int stm32_adc_chan_of_init(struct udevice *dev)
dev_err(dev, "can't get st,adc-channels: %d\n", ret);
return ret;
}
- num_channels = ret / sizeof(u32);
- if (num_channels > adc->cfg->max_channels) {
- dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
- return -EINVAL;
- }
+ return (ret / sizeof(u32));
+}
+
+static int stm32_adc_legacy_chan_init(struct udevice *dev, unsigned int num_channels)
+{
+ struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
+ struct stm32_adc *adc = dev_get_priv(dev);
+ u32 chans[STM32_ADC_CH_MAX];
+ int i, ret;
ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
if (ret < 0) {
@@ -197,6 +197,69 @@ static int stm32_adc_chan_of_init(struct udevice *dev)
uc_pdata->channel_mask |= 1 << chans[i];
}
+ return ret;
+}
+
+static int stm32_adc_generic_chan_init(struct udevice *dev, unsigned int num_channels)
+{
+ struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
+ struct stm32_adc *adc = dev_get_priv(dev);
+ ofnode child;
+ int val, ret;
+
+ ofnode_for_each_subnode(child, dev_ofnode(dev)) {
+ ret = ofnode_read_u32(child, "reg", &val);
+ if (ret) {
+ dev_err(dev, "Missing channel index %d\n", ret);
+ return ret;
+ }
+
+ if (val >= adc->cfg->max_channels) {
+ dev_err(dev, "Invalid channel %d\n", val);
+ return -EINVAL;
+ }
+
+ uc_pdata->channel_mask |= 1 << val;
+ }
+
+ return 0;
+}
+
+static int stm32_adc_chan_of_init(struct udevice *dev)
+{
+ struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
+ struct stm32_adc *adc = dev_get_priv(dev);
+ unsigned int num_channels;
+ int ret;
+ bool legacy = false;
+
+ num_channels = dev_get_child_count(dev);
+ /* If no channels have been found, fallback to channels legacy properties. */
+ if (!num_channels) {
+ legacy = true;
+
+ ret = stm32_adc_get_legacy_chan_count(dev);
+ if (!ret) {
+ dev_err(dev, "No channel found\n");
+ return -ENODATA;
+ } else if (ret < 0) {
+ return ret;
+ }
+ num_channels = ret;
+ }
+
+ if (num_channels > adc->cfg->max_channels) {
+ dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
+ return -EINVAL;
+ }
+
+ if (legacy)
+ ret = stm32_adc_legacy_chan_init(dev, num_channels);
+ else
+ ret = stm32_adc_generic_chan_init(dev, num_channels);
+ if (ret < 0)
+ return ret;
+
uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
uc_pdata->data_timeout_us = 100000;