Merge branch '2020-05-18-reduce-size-of-common.h'
[oweals/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 <asm/io.h>
11 #include <dm/device_compat.h>
12 #include <linux/bitops.h>
13 #include <power/regulator.h>
14 #include "stm32-adc-core.h"
15
16 /* STM32H7 - common registers for all ADC instances */
17 #define STM32H7_ADC_CCR                 (STM32_ADCX_COMN_OFFSET + 0x08)
18
19 /* STM32H7_ADC_CCR - bit fields */
20 #define STM32H7_PRESC_SHIFT             18
21 #define STM32H7_PRESC_MASK              GENMASK(21, 18)
22 #define STM32H7_CKMODE_SHIFT            16
23 #define STM32H7_CKMODE_MASK             GENMASK(17, 16)
24
25 /* STM32 H7 maximum analog clock rate (from datasheet) */
26 #define STM32H7_ADC_MAX_CLK_RATE        36000000
27
28 /**
29  * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
30  * @ckmode: ADC clock mode, Async or sync with prescaler.
31  * @presc: prescaler bitfield for async clock mode
32  * @div: prescaler division ratio
33  */
34 struct stm32h7_adc_ck_spec {
35         u32 ckmode;
36         u32 presc;
37         int div;
38 };
39
40 static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
41         /* 00: CK_ADC[1..3]: Asynchronous clock modes */
42         { 0, 0, 1 },
43         { 0, 1, 2 },
44         { 0, 2, 4 },
45         { 0, 3, 6 },
46         { 0, 4, 8 },
47         { 0, 5, 10 },
48         { 0, 6, 12 },
49         { 0, 7, 16 },
50         { 0, 8, 32 },
51         { 0, 9, 64 },
52         { 0, 10, 128 },
53         { 0, 11, 256 },
54         /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
55         { 1, 0, 1 },
56         { 2, 0, 2 },
57         { 3, 0, 4 },
58 };
59
60 static int stm32h7_adc_clk_sel(struct udevice *dev,
61                                struct stm32_adc_common *common)
62 {
63         u32 ckmode, presc;
64         unsigned long rate;
65         unsigned int i;
66         int div;
67
68         /* stm32h7 bus clock is common for all ADC instances (mandatory) */
69         if (!clk_valid(&common->bclk)) {
70                 dev_err(dev, "No bclk clock found\n");
71                 return -ENOENT;
72         }
73
74         /*
75          * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
76          * So, choice is to have bus clock mandatory and adc clock optional.
77          * If optional 'adc' clock has been found, then try to use it first.
78          */
79         if (clk_valid(&common->aclk)) {
80                 /*
81                  * Asynchronous clock modes (e.g. ckmode == 0)
82                  * From spec: PLL output musn't exceed max rate
83                  */
84                 rate = clk_get_rate(&common->aclk);
85                 if (!rate) {
86                         dev_err(dev, "Invalid aclk rate: 0\n");
87                         return -EINVAL;
88                 }
89
90                 for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
91                         ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
92                         presc = stm32h7_adc_ckmodes_spec[i].presc;
93                         div = stm32h7_adc_ckmodes_spec[i].div;
94
95                         if (ckmode)
96                                 continue;
97
98                         if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
99                                 goto out;
100                 }
101         }
102
103         /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
104         rate = clk_get_rate(&common->bclk);
105         if (!rate) {
106                 dev_err(dev, "Invalid bus clock rate: 0\n");
107                 return -EINVAL;
108         }
109
110         for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
111                 ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
112                 presc = stm32h7_adc_ckmodes_spec[i].presc;
113                 div = stm32h7_adc_ckmodes_spec[i].div;
114
115                 if (!ckmode)
116                         continue;
117
118                 if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
119                         goto out;
120         }
121
122         dev_err(dev, "clk selection failed\n");
123         return -EINVAL;
124
125 out:
126         /* rate used later by each ADC instance to control BOOST mode */
127         common->rate = rate / div;
128
129         /* Set common clock mode and prescaler */
130         clrsetbits_le32(common->base + STM32H7_ADC_CCR,
131                         STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
132                         ckmode << STM32H7_CKMODE_SHIFT |
133                         presc << STM32H7_PRESC_SHIFT);
134
135         dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
136                 ckmode ? "bus" : "adc", div, common->rate / 1000);
137
138         return 0;
139 }
140
141 static int stm32_adc_core_probe(struct udevice *dev)
142 {
143         struct stm32_adc_common *common = dev_get_priv(dev);
144         int ret;
145
146         common->base = dev_read_addr_ptr(dev);
147         if (!common->base) {
148                 dev_err(dev, "can't get address\n");
149                 return -ENOENT;
150         }
151
152         ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
153         if (ret) {
154                 dev_err(dev, "can't get vref-supply: %d\n", ret);
155                 return ret;
156         }
157
158         ret = regulator_get_value(common->vref);
159         if (ret < 0) {
160                 dev_err(dev, "can't get vref-supply value: %d\n", ret);
161                 return ret;
162         }
163         common->vref_uv = ret;
164
165         ret = clk_get_by_name(dev, "adc", &common->aclk);
166         if (!ret) {
167                 ret = clk_enable(&common->aclk);
168                 if (ret) {
169                         dev_err(dev, "Can't enable aclk: %d\n", ret);
170                         return ret;
171                 }
172         }
173
174         ret = clk_get_by_name(dev, "bus", &common->bclk);
175         if (!ret) {
176                 ret = clk_enable(&common->bclk);
177                 if (ret) {
178                         dev_err(dev, "Can't enable bclk: %d\n", ret);
179                         goto err_aclk_disable;
180                 }
181         }
182
183         ret = stm32h7_adc_clk_sel(dev, common);
184         if (ret)
185                 goto err_bclk_disable;
186
187         return ret;
188
189 err_bclk_disable:
190         if (clk_valid(&common->bclk))
191                 clk_disable(&common->bclk);
192
193 err_aclk_disable:
194         if (clk_valid(&common->aclk))
195                 clk_disable(&common->aclk);
196
197         return ret;
198 }
199
200 static const struct udevice_id stm32_adc_core_ids[] = {
201         { .compatible = "st,stm32h7-adc-core" },
202         { .compatible = "st,stm32mp1-adc-core" },
203         {}
204 };
205
206 U_BOOT_DRIVER(stm32_adc_core) = {
207         .name  = "stm32-adc-core",
208         .id = UCLASS_SIMPLE_BUS,
209         .of_match = stm32_adc_core_ids,
210         .probe = stm32_adc_core_probe,
211         .priv_auto_alloc_size = sizeof(struct stm32_adc_common),
212 };