1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
6 * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.c.
11 #include <power/regulator.h>
12 #include "stm32-adc-core.h"
14 /* STM32H7 - common registers for all ADC instances */
15 #define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
17 /* STM32H7_ADC_CCR - bit fields */
18 #define STM32H7_PRESC_SHIFT 18
19 #define STM32H7_PRESC_MASK GENMASK(21, 18)
20 #define STM32H7_CKMODE_SHIFT 16
21 #define STM32H7_CKMODE_MASK GENMASK(17, 16)
23 /* STM32 H7 maximum analog clock rate (from datasheet) */
24 #define STM32H7_ADC_MAX_CLK_RATE 36000000
27 * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
28 * @ckmode: ADC clock mode, Async or sync with prescaler.
29 * @presc: prescaler bitfield for async clock mode
30 * @div: prescaler division ratio
32 struct stm32h7_adc_ck_spec {
38 static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
39 /* 00: CK_ADC[1..3]: Asynchronous clock modes */
52 /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
58 static int stm32h7_adc_clk_sel(struct udevice *dev,
59 struct stm32_adc_common *common)
66 /* stm32h7 bus clock is common for all ADC instances (mandatory) */
67 if (!clk_valid(&common->bclk)) {
68 dev_err(dev, "No bclk clock found\n");
73 * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
74 * So, choice is to have bus clock mandatory and adc clock optional.
75 * If optional 'adc' clock has been found, then try to use it first.
77 if (clk_valid(&common->aclk)) {
79 * Asynchronous clock modes (e.g. ckmode == 0)
80 * From spec: PLL output musn't exceed max rate
82 rate = clk_get_rate(&common->aclk);
84 dev_err(dev, "Invalid aclk rate: 0\n");
88 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
89 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
90 presc = stm32h7_adc_ckmodes_spec[i].presc;
91 div = stm32h7_adc_ckmodes_spec[i].div;
96 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
101 /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
102 rate = clk_get_rate(&common->bclk);
104 dev_err(dev, "Invalid bus clock rate: 0\n");
108 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
109 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
110 presc = stm32h7_adc_ckmodes_spec[i].presc;
111 div = stm32h7_adc_ckmodes_spec[i].div;
116 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
120 dev_err(dev, "clk selection failed\n");
124 /* rate used later by each ADC instance to control BOOST mode */
125 common->rate = rate / div;
127 /* Set common clock mode and prescaler */
128 clrsetbits_le32(common->base + STM32H7_ADC_CCR,
129 STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
130 ckmode << STM32H7_CKMODE_SHIFT |
131 presc << STM32H7_PRESC_SHIFT);
133 dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
134 ckmode ? "bus" : "adc", div, common->rate / 1000);
139 static int stm32_adc_core_probe(struct udevice *dev)
141 struct stm32_adc_common *common = dev_get_priv(dev);
144 common->base = dev_read_addr_ptr(dev);
146 dev_err(dev, "can't get address\n");
150 ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
152 dev_err(dev, "can't get vref-supply: %d\n", ret);
156 ret = regulator_get_value(common->vref);
158 dev_err(dev, "can't get vref-supply value: %d\n", ret);
161 common->vref_uv = ret;
163 ret = clk_get_by_name(dev, "adc", &common->aclk);
165 ret = clk_enable(&common->aclk);
167 dev_err(dev, "Can't enable aclk: %d\n", ret);
172 ret = clk_get_by_name(dev, "bus", &common->bclk);
174 ret = clk_enable(&common->bclk);
176 dev_err(dev, "Can't enable bclk: %d\n", ret);
177 goto err_aclk_disable;
181 ret = stm32h7_adc_clk_sel(dev, common);
183 goto err_bclk_disable;
188 if (clk_valid(&common->bclk))
189 clk_disable(&common->bclk);
192 if (clk_valid(&common->aclk))
193 clk_disable(&common->aclk);
198 static const struct udevice_id stm32_adc_core_ids[] = {
199 { .compatible = "st,stm32h7-adc-core" },
200 { .compatible = "st,stm32mp1-adc-core" },
204 U_BOOT_DRIVER(stm32_adc_core) = {
205 .name = "stm32-adc-core",
206 .id = UCLASS_SIMPLE_BUS,
207 .of_match = stm32_adc_core_ids,
208 .probe = stm32_adc_core_probe,
209 .priv_auto_alloc_size = sizeof(struct stm32_adc_common),