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.
12 #include <dm/device_compat.h>
13 #include <linux/bitops.h>
14 #include <power/regulator.h>
15 #include "stm32-adc-core.h"
17 /* STM32H7 - common registers for all ADC instances */
18 #define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
20 /* STM32H7_ADC_CCR - bit fields */
21 #define STM32H7_PRESC_SHIFT 18
22 #define STM32H7_PRESC_MASK GENMASK(21, 18)
23 #define STM32H7_CKMODE_SHIFT 16
24 #define STM32H7_CKMODE_MASK GENMASK(17, 16)
26 /* STM32 H7 maximum analog clock rate (from datasheet) */
27 #define STM32H7_ADC_MAX_CLK_RATE 36000000
30 * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
31 * @ckmode: ADC clock mode, Async or sync with prescaler.
32 * @presc: prescaler bitfield for async clock mode
33 * @div: prescaler division ratio
35 struct stm32h7_adc_ck_spec {
41 static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
42 /* 00: CK_ADC[1..3]: Asynchronous clock modes */
55 /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
61 static int stm32h7_adc_clk_sel(struct udevice *dev,
62 struct stm32_adc_common *common)
69 /* stm32h7 bus clock is common for all ADC instances (mandatory) */
70 if (!clk_valid(&common->bclk)) {
71 dev_err(dev, "No bclk clock found\n");
76 * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
77 * So, choice is to have bus clock mandatory and adc clock optional.
78 * If optional 'adc' clock has been found, then try to use it first.
80 if (clk_valid(&common->aclk)) {
82 * Asynchronous clock modes (e.g. ckmode == 0)
83 * From spec: PLL output musn't exceed max rate
85 rate = clk_get_rate(&common->aclk);
87 dev_err(dev, "Invalid aclk rate: 0\n");
91 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
92 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
93 presc = stm32h7_adc_ckmodes_spec[i].presc;
94 div = stm32h7_adc_ckmodes_spec[i].div;
99 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
104 /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
105 rate = clk_get_rate(&common->bclk);
107 dev_err(dev, "Invalid bus clock rate: 0\n");
111 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
112 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
113 presc = stm32h7_adc_ckmodes_spec[i].presc;
114 div = stm32h7_adc_ckmodes_spec[i].div;
119 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
123 dev_err(dev, "clk selection failed\n");
127 /* rate used later by each ADC instance to control BOOST mode */
128 common->rate = rate / div;
130 /* Set common clock mode and prescaler */
131 clrsetbits_le32(common->base + STM32H7_ADC_CCR,
132 STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
133 ckmode << STM32H7_CKMODE_SHIFT |
134 presc << STM32H7_PRESC_SHIFT);
136 dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
137 ckmode ? "bus" : "adc", div, common->rate / 1000);
142 static int stm32_adc_core_probe(struct udevice *dev)
144 struct stm32_adc_common *common = dev_get_priv(dev);
147 common->base = dev_read_addr_ptr(dev);
149 dev_err(dev, "can't get address\n");
153 ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
155 dev_err(dev, "can't get vref-supply: %d\n", ret);
159 ret = regulator_get_value(common->vref);
161 dev_err(dev, "can't get vref-supply value: %d\n", ret);
164 common->vref_uv = ret;
166 ret = clk_get_by_name(dev, "adc", &common->aclk);
168 ret = clk_enable(&common->aclk);
170 dev_err(dev, "Can't enable aclk: %d\n", ret);
175 ret = clk_get_by_name(dev, "bus", &common->bclk);
177 ret = clk_enable(&common->bclk);
179 dev_err(dev, "Can't enable bclk: %d\n", ret);
180 goto err_aclk_disable;
184 ret = stm32h7_adc_clk_sel(dev, common);
186 goto err_bclk_disable;
191 if (clk_valid(&common->bclk))
192 clk_disable(&common->bclk);
195 if (clk_valid(&common->aclk))
196 clk_disable(&common->aclk);
201 static const struct udevice_id stm32_adc_core_ids[] = {
202 { .compatible = "st,stm32h7-adc-core" },
203 { .compatible = "st,stm32mp1-adc-core" },
207 U_BOOT_DRIVER(stm32_adc_core) = {
208 .name = "stm32-adc-core",
209 .id = UCLASS_SIMPLE_BUS,
210 .of_match = stm32_adc_core_ids,
211 .probe = stm32_adc_core_probe,
212 .priv_auto = sizeof(struct stm32_adc_common),