Merge https://gitlab.denx.de/u-boot/custodians/u-boot-samsung.git
[platform/kernel/u-boot.git] / drivers / adc / stm32-adc-core.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
5  *
6  * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.c.
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/io.h>
12 #include <dm/device_compat.h>
13 #include <linux/bitops.h>
14 #include <power/regulator.h>
15 #include "stm32-adc-core.h"
16
17 /* STM32H7 - common registers for all ADC instances */
18 #define STM32H7_ADC_CCR                 (STM32_ADCX_COMN_OFFSET + 0x08)
19
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)
25
26 /* STM32 H7 maximum analog clock rate (from datasheet) */
27 #define STM32H7_ADC_MAX_CLK_RATE        36000000
28
29 /**
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
34  */
35 struct stm32h7_adc_ck_spec {
36         u32 ckmode;
37         u32 presc;
38         int div;
39 };
40
41 static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
42         /* 00: CK_ADC[1..3]: Asynchronous clock modes */
43         { 0, 0, 1 },
44         { 0, 1, 2 },
45         { 0, 2, 4 },
46         { 0, 3, 6 },
47         { 0, 4, 8 },
48         { 0, 5, 10 },
49         { 0, 6, 12 },
50         { 0, 7, 16 },
51         { 0, 8, 32 },
52         { 0, 9, 64 },
53         { 0, 10, 128 },
54         { 0, 11, 256 },
55         /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
56         { 1, 0, 1 },
57         { 2, 0, 2 },
58         { 3, 0, 4 },
59 };
60
61 static int stm32h7_adc_clk_sel(struct udevice *dev,
62                                struct stm32_adc_common *common)
63 {
64         u32 ckmode, presc;
65         unsigned long rate;
66         unsigned int i;
67         int div;
68
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");
72                 return -ENOENT;
73         }
74
75         /*
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.
79          */
80         if (clk_valid(&common->aclk)) {
81                 /*
82                  * Asynchronous clock modes (e.g. ckmode == 0)
83                  * From spec: PLL output musn't exceed max rate
84                  */
85                 rate = clk_get_rate(&common->aclk);
86                 if (!rate) {
87                         dev_err(dev, "Invalid aclk rate: 0\n");
88                         return -EINVAL;
89                 }
90
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;
95
96                         if (ckmode)
97                                 continue;
98
99                         if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
100                                 goto out;
101                 }
102         }
103
104         /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
105         rate = clk_get_rate(&common->bclk);
106         if (!rate) {
107                 dev_err(dev, "Invalid bus clock rate: 0\n");
108                 return -EINVAL;
109         }
110
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;
115
116                 if (!ckmode)
117                         continue;
118
119                 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
120                         goto out;
121         }
122
123         dev_err(dev, "clk selection failed\n");
124         return -EINVAL;
125
126 out:
127         /* rate used later by each ADC instance to control BOOST mode */
128         common->rate = rate / div;
129
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);
135
136         dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
137                 ckmode ? "bus" : "adc", div, common->rate / 1000);
138
139         return 0;
140 }
141
142 static int stm32_adc_core_probe(struct udevice *dev)
143 {
144         struct stm32_adc_common *common = dev_get_priv(dev);
145         int ret;
146
147         common->base = dev_read_addr_ptr(dev);
148         if (!common->base) {
149                 dev_err(dev, "can't get address\n");
150                 return -ENOENT;
151         }
152
153         ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
154         if (ret) {
155                 dev_err(dev, "can't get vref-supply: %d\n", ret);
156                 return ret;
157         }
158
159         ret = regulator_get_value(common->vref);
160         if (ret < 0) {
161                 dev_err(dev, "can't get vref-supply value: %d\n", ret);
162                 return ret;
163         }
164         common->vref_uv = ret;
165
166         ret = clk_get_by_name(dev, "adc", &common->aclk);
167         if (!ret) {
168                 ret = clk_enable(&common->aclk);
169                 if (ret) {
170                         dev_err(dev, "Can't enable aclk: %d\n", ret);
171                         return ret;
172                 }
173         }
174
175         ret = clk_get_by_name(dev, "bus", &common->bclk);
176         if (!ret) {
177                 ret = clk_enable(&common->bclk);
178                 if (ret) {
179                         dev_err(dev, "Can't enable bclk: %d\n", ret);
180                         goto err_aclk_disable;
181                 }
182         }
183
184         ret = stm32h7_adc_clk_sel(dev, common);
185         if (ret)
186                 goto err_bclk_disable;
187
188         return ret;
189
190 err_bclk_disable:
191         if (clk_valid(&common->bclk))
192                 clk_disable(&common->bclk);
193
194 err_aclk_disable:
195         if (clk_valid(&common->aclk))
196                 clk_disable(&common->aclk);
197
198         return ret;
199 }
200
201 static const struct udevice_id stm32_adc_core_ids[] = {
202         { .compatible = "st,stm32h7-adc-core" },
203         { .compatible = "st,stm32mp1-adc-core" },
204         {}
205 };
206
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),
213 };