blob: a687e2acd406669a818f5c716d0b3f5b348b2464 [file] [log] [blame]
Vikas Manocha1b51c932016-02-11 15:47:20 -08001/*
Patrice Chotard789ee0e2017-10-23 09:53:58 +02002 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
3 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
Vikas Manocha1b51c932016-02-11 15:47:20 -08004 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
Patrice Chotard789ee0e2017-10-23 09:53:58 +02007
Vikas Manocha1b51c932016-02-11 15:47:20 -08008#include <common.h>
Vikas Manochadaaeaab2017-02-12 10:25:45 -08009#include <clk-uclass.h>
10#include <dm.h>
Patrice Chotard03f10a12017-11-15 13:14:51 +010011#include <stm32_rcc.h>
Patrice Chotard22768d52017-11-15 13:14:44 +010012
Vikas Manocha1b51c932016-02-11 15:47:20 -080013#include <asm/io.h>
Vikas Manocha1b51c932016-02-11 15:47:20 -080014#include <asm/arch/stm32.h>
Patrice Chotard22768d52017-11-15 13:14:44 +010015#include <asm/arch/stm32_pwr.h>
Vikas Manocha1b51c932016-02-11 15:47:20 -080016
Patrice Chotard7bdf9712017-07-18 09:29:05 +020017#include <dt-bindings/mfd/stm32f7-rcc.h>
18
Michael Kurzc204fb72017-01-22 16:04:24 +010019#define RCC_CR_HSION BIT(0)
20#define RCC_CR_HSEON BIT(16)
21#define RCC_CR_HSERDY BIT(17)
22#define RCC_CR_HSEBYP BIT(18)
23#define RCC_CR_CSSON BIT(19)
24#define RCC_CR_PLLON BIT(24)
25#define RCC_CR_PLLRDY BIT(25)
Patrice Chotard369d4832017-11-15 13:14:52 +010026#define RCC_CR_PLLSAION BIT(28)
27#define RCC_CR_PLLSAIRDY BIT(29)
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090028
Michael Kurzc204fb72017-01-22 16:04:24 +010029#define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0)
30#define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6)
31#define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16)
32#define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24)
33#define RCC_PLLCFGR_PLLSRC BIT(22)
34#define RCC_PLLCFGR_PLLM_SHIFT 0
35#define RCC_PLLCFGR_PLLN_SHIFT 6
36#define RCC_PLLCFGR_PLLP_SHIFT 16
37#define RCC_PLLCFGR_PLLQ_SHIFT 24
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090038
Michael Kurzc204fb72017-01-22 16:04:24 +010039#define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4)
40#define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10)
41#define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13)
42#define RCC_CFGR_SW0 BIT(0)
43#define RCC_CFGR_SW1 BIT(1)
44#define RCC_CFGR_SW_MASK GENMASK(1, 0)
45#define RCC_CFGR_SW_HSI 0
46#define RCC_CFGR_SW_HSE RCC_CFGR_SW0
47#define RCC_CFGR_SW_PLL RCC_CFGR_SW1
48#define RCC_CFGR_SWS0 BIT(2)
49#define RCC_CFGR_SWS1 BIT(3)
50#define RCC_CFGR_SWS_MASK GENMASK(3, 2)
51#define RCC_CFGR_SWS_HSI 0
52#define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0
53#define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1
54#define RCC_CFGR_HPRE_SHIFT 4
55#define RCC_CFGR_PPRE1_SHIFT 10
56#define RCC_CFGR_PPRE2_SHIFT 13
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090057
Patrice Chotard9490aca2018-02-08 17:20:46 +010058#define RCC_PLLSAICFGR_PLLSAIN_MASK GENMASK(14, 6)
59#define RCC_PLLSAICFGR_PLLSAIP_MASK GENMASK(17, 16)
Patrice Chotard8aca2d12018-02-08 17:20:48 +010060#define RCC_PLLSAICFGR_PLLSAIQ_MASK GENMASK(27, 24)
61#define RCC_PLLSAICFGR_PLLSAIR_MASK GENMASK(30, 28)
Patrice Chotard369d4832017-11-15 13:14:52 +010062#define RCC_PLLSAICFGR_PLLSAIN_SHIFT 6
63#define RCC_PLLSAICFGR_PLLSAIP_SHIFT 16
Patrice Chotard8aca2d12018-02-08 17:20:48 +010064#define RCC_PLLSAICFGR_PLLSAIQ_SHIFT 24
65#define RCC_PLLSAICFGR_PLLSAIR_SHIFT 28
Patrice Chotardd5d36552018-01-19 18:02:40 +010066#define RCC_PLLSAICFGR_PLLSAIP_4 BIT(16)
Patrice Chotard369d4832017-11-15 13:14:52 +010067#define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26)
68#define RCC_PLLSAICFGR_PLLSAIR_2 BIT(29)
69
Patrice Chotardef772872018-02-07 10:44:46 +010070#define RCC_DCKCFGRX_TIMPRE BIT(24)
Patrice Chotard369d4832017-11-15 13:14:52 +010071#define RCC_DCKCFGRX_CK48MSEL BIT(27)
72#define RCC_DCKCFGRX_SDMMC1SEL BIT(28)
73#define RCC_DCKCFGR2_SDMMC2SEL BIT(29)
74
Patrice Chotard06fc6482017-11-15 13:14:49 +010075/*
76 * RCC AHB1ENR specific definitions
77 */
78#define RCC_AHB1ENR_ETHMAC_EN BIT(25)
79#define RCC_AHB1ENR_ETHMAC_TX_EN BIT(26)
80#define RCC_AHB1ENR_ETHMAC_RX_EN BIT(27)
81
82/*
83 * RCC APB1ENR specific definitions
84 */
85#define RCC_APB1ENR_TIM2EN BIT(0)
86#define RCC_APB1ENR_PWREN BIT(28)
87
88/*
89 * RCC APB2ENR specific definitions
90 */
91#define RCC_APB2ENR_SYSCFGEN BIT(14)
Patrice Chotarde2d564e2018-01-18 14:10:05 +010092#define RCC_APB2ENR_SAI1EN BIT(22)
Patrice Chotard06fc6482017-11-15 13:14:49 +010093
Patrice Chotard8aca2d12018-02-08 17:20:48 +010094enum pllsai_div {
95 PLLSAIP,
96 PLLSAIQ,
97 PLLSAIR,
98};
99
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100100static const struct stm32_clk_info stm32f4_clk_info = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100101 /* 180 MHz */
102 .sys_pll_psc = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100103 .pll_n = 360,
104 .pll_p = 2,
105 .pll_q = 8,
106 .ahb_psc = AHB_PSC_1,
107 .apb1_psc = APB_PSC_4,
108 .apb2_psc = APB_PSC_2,
109 },
110 .has_overdrive = false,
Patrice Chotard369d4832017-11-15 13:14:52 +0100111 .v2 = false,
Patrice Chotard1509d662017-11-15 13:14:47 +0100112};
113
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100114static const struct stm32_clk_info stm32f7_clk_info = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100115 /* 200 MHz */
116 .sys_pll_psc = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100117 .pll_n = 400,
118 .pll_p = 2,
119 .pll_q = 8,
120 .ahb_psc = AHB_PSC_1,
121 .apb1_psc = APB_PSC_4,
122 .apb2_psc = APB_PSC_2,
123 },
124 .has_overdrive = true,
Patrice Chotard369d4832017-11-15 13:14:52 +0100125 .v2 = true,
Patrice Chotard1509d662017-11-15 13:14:47 +0100126};
127
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200128struct stm32_clk {
129 struct stm32_rcc_regs *base;
Patrice Chotard22768d52017-11-15 13:14:44 +0100130 struct stm32_pwr_regs *pwr_regs;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100131 struct stm32_clk_info info;
132 unsigned long hse_rate;
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900133};
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900134
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200135static int configure_clocks(struct udevice *dev)
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900136{
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200137 struct stm32_clk *priv = dev_get_priv(dev);
138 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotard22768d52017-11-15 13:14:44 +0100139 struct stm32_pwr_regs *pwr = priv->pwr_regs;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100140 struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc;
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200141
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900142 /* Reset RCC configuration */
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200143 setbits_le32(&regs->cr, RCC_CR_HSION);
144 writel(0, &regs->cfgr); /* Reset CFGR */
145 clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
Patrice Chotard369d4832017-11-15 13:14:52 +0100146 | RCC_CR_PLLON | RCC_CR_PLLSAION));
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200147 writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
148 clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
149 writel(0, &regs->cir); /* Disable all interrupts */
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900150
151 /* Configure for HSE+PLL operation */
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200152 setbits_le32(&regs->cr, RCC_CR_HSEON);
153 while (!(readl(&regs->cr) & RCC_CR_HSERDY))
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900154 ;
155
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200156 setbits_le32(&regs->cfgr, ((
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100157 sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT)
158 | (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT)
159 | (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900160
161 /* Configure the main PLL */
Patrice Chotardb6653f62017-10-26 13:23:19 +0200162 setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
163 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100164 sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200165 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100166 sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200167 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100168 ((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200169 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100170 sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900171
Patrice Chotardcb15d282018-02-08 17:20:47 +0100172 /* configure SDMMC clock */
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100173 if (priv->info.v2) { /*stm32f7 case */
Patrice Chotardcb15d282018-02-08 17:20:47 +0100174 /* select PLLQ as 48MHz clock source */
175 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
Patrice Chotard369d4832017-11-15 13:14:52 +0100176
177 /* select 48MHz as SDMMC1 clock source */
178 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
179
180 /* select 48MHz as SDMMC2 clock source */
181 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
182 } else { /* stm32f4 case */
Patrice Chotardcb15d282018-02-08 17:20:47 +0100183 /* select PLLQ as 48MHz clock source */
184 clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
Patrice Chotard369d4832017-11-15 13:14:52 +0100185
186 /* select 48MHz as SDMMC1 clock source */
187 clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
188 }
189
Patrice Chotardcb15d282018-02-08 17:20:47 +0100190 /* Enable the main PLL */
191 setbits_le32(&regs->cr, RCC_CR_PLLON);
192 while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
Patrice Chotard369d4832017-11-15 13:14:52 +0100193 ;
194
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200195 setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
Patrice Chotard1509d662017-11-15 13:14:47 +0100196
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100197 if (priv->info.has_overdrive) {
Patrice Chotard1509d662017-11-15 13:14:47 +0100198 /*
199 * Enable high performance mode
200 * System frequency up to 200 MHz
201 */
202 setbits_le32(&pwr->cr1, PWR_CR1_ODEN);
203 /* Infinite wait! */
204 while (!(readl(&pwr->csr1) & PWR_CSR1_ODRDY))
205 ;
206 /* Enable the Over-drive switch */
207 setbits_le32(&pwr->cr1, PWR_CR1_ODSWEN);
208 /* Infinite wait! */
209 while (!(readl(&pwr->csr1) & PWR_CSR1_ODSWRDY))
210 ;
211 }
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900212
213 stm32_flash_latency_cfg(5);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200214 clrbits_le32(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
215 setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900216
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200217 while ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) !=
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900218 RCC_CFGR_SWS_PLL)
219 ;
220
Patrice Chotarde2d564e2018-01-18 14:10:05 +0100221#ifdef CONFIG_ETH_DESIGNWARE
222 /* gate the SYSCFG clock, needed to set RMII ethernet interface */
223 setbits_le32(&regs->apb2enr, RCC_APB2ENR_SYSCFGEN);
224#endif
225
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900226 return 0;
227}
228
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100229static bool stm32_clk_get_ck48msel(struct stm32_clk *priv)
Patrice Chotard369d4832017-11-15 13:14:52 +0100230{
231 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotard369d4832017-11-15 13:14:52 +0100232
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100233 if (priv->info.v2) /*stm32f7 case */
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100234 return readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
Patrice Chotard369d4832017-11-15 13:14:52 +0100235 else
Patrice Chotard369d4832017-11-15 13:14:52 +0100236
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100237 return readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
238}
239
240static unsigned long stm32_clk_get_pllsai_vco_rate(struct stm32_clk *priv)
241{
242 struct stm32_rcc_regs *regs = priv->base;
243 u16 pllm, pllsain;
244
245 pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
246 pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
247 >> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
248
249 return ((priv->hse_rate / pllm) * pllsain);
250}
251
252static unsigned long stm32_clk_get_pllsai_rate(struct stm32_clk *priv,
253 enum pllsai_div output)
254{
255 struct stm32_rcc_regs *regs = priv->base;
256 u16 pll_div_output;
257
258 switch (output) {
259 case PLLSAIP:
260 pll_div_output = ((((readl(&regs->pllsaicfgr)
261 & RCC_PLLSAICFGR_PLLSAIP_MASK)
262 >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
263 break;
264 case PLLSAIQ:
265 pll_div_output = (readl(&regs->pllsaicfgr)
266 & RCC_PLLSAICFGR_PLLSAIQ_MASK)
267 >> RCC_PLLSAICFGR_PLLSAIQ_SHIFT;
268 break;
269 case PLLSAIR:
270 pll_div_output = (readl(&regs->pllsaicfgr)
271 & RCC_PLLSAICFGR_PLLSAIR_MASK)
272 >> RCC_PLLSAICFGR_PLLSAIR_SHIFT;
273 break;
274 default:
275 pr_err("incorrect PLLSAI output %d\n", output);
276 return -EINVAL;
Patrice Chotard369d4832017-11-15 13:14:52 +0100277 }
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100278
279 return (stm32_clk_get_pllsai_vco_rate(priv) / pll_div_output);
Patrice Chotard369d4832017-11-15 13:14:52 +0100280}
281
Patrice Chotardef772872018-02-07 10:44:46 +0100282static bool stm32_get_timpre(struct stm32_clk *priv)
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200283{
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200284 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotardef772872018-02-07 10:44:46 +0100285 u32 val;
286
287 if (priv->info.v2) /*stm32f7 case */
288 val = readl(&regs->dckcfgr2);
289 else
290 val = readl(&regs->dckcfgr);
291 /* get timer prescaler */
292 return !!(val & RCC_DCKCFGRX_TIMPRE);
293}
294
295static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk)
296{
297 u8 shift;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200298 /* Prescaler table lookups for clock computation */
299 u8 ahb_psc_table[16] = {
300 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
301 };
Patrice Chotardef772872018-02-07 10:44:46 +0100302
303 shift = ahb_psc_table[(
304 (readl(&regs->cfgr) & RCC_CFGR_AHB_PSC_MASK)
305 >> RCC_CFGR_HPRE_SHIFT)];
306
307 return sysclk >> shift;
308};
309
310static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb)
311{
312 /* Prescaler table lookups for clock computation */
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200313 u8 apb_psc_table[8] = {
314 0, 0, 0, 0, 1, 2, 3, 4
315 };
316
Patrice Chotardef772872018-02-07 10:44:46 +0100317 if (apb == APB1)
318 return apb_psc_table[(
319 (readl(&regs->cfgr) & RCC_CFGR_APB1_PSC_MASK)
320 >> RCC_CFGR_PPRE1_SHIFT)];
321 else /* APB2 */
322 return apb_psc_table[(
323 (readl(&regs->cfgr) & RCC_CFGR_APB2_PSC_MASK)
324 >> RCC_CFGR_PPRE2_SHIFT)];
325};
326
327static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk,
328 enum apb apb)
329{
330 struct stm32_rcc_regs *regs = priv->base;
331 u8 shift = stm32_get_apb_shift(regs, apb);
332
333 if (stm32_get_timpre(priv))
334 /*
335 * if APB prescaler is configured to a
336 * division factor of 1, 2 or 4
337 */
338 switch (shift) {
339 case 0:
340 case 1:
341 case 2:
342 return stm32_get_hclk_rate(regs, sysclk);
343 default:
344 return (sysclk >> shift) * 4;
345 }
346 else
347 /*
348 * if APB prescaler is configured to a
349 * division factor of 1
350 */
351 if (shift == 0)
352 return sysclk;
353 else
354 return (sysclk >> shift) * 2;
355};
356
357static ulong stm32_clk_get_rate(struct clk *clk)
358{
359 struct stm32_clk *priv = dev_get_priv(clk->dev);
360 struct stm32_rcc_regs *regs = priv->base;
361 u32 sysclk = 0;
Patrice Chotard81d77652018-02-08 17:20:45 +0100362 u32 vco;
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100363 u32 sdmmcxsel_bit;
364 u16 pllm, plln, pllp, pllq;
Patrice Chotardef772872018-02-07 10:44:46 +0100365
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200366 if ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
367 RCC_CFGR_SWS_PLL) {
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200368 pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
369 plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
370 >> RCC_PLLCFGR_PLLN_SHIFT);
371 pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
372 >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100373 pllq = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
374 >> RCC_PLLCFGR_PLLQ_SHIFT);
Patrice Chotard81d77652018-02-08 17:20:45 +0100375 vco = (priv->hse_rate / pllm) * plln;
376 sysclk = vco / pllp;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200377 } else {
378 return -EINVAL;
379 }
380
381 switch (clk->id) {
382 /*
383 * AHB CLOCK: 3 x 32 bits consecutive registers are used :
384 * AHB1, AHB2 and AHB3
385 */
386 case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
Patrice Chotardef772872018-02-07 10:44:46 +0100387 return stm32_get_hclk_rate(regs, sysclk);
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200388 /* APB1 CLOCK */
389 case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
Patrice Chotardef772872018-02-07 10:44:46 +0100390 /* For timer clock, an additionnal prescaler is used*/
391 switch (clk->id) {
392 case STM32F7_APB1_CLOCK(TIM2):
393 case STM32F7_APB1_CLOCK(TIM3):
394 case STM32F7_APB1_CLOCK(TIM4):
395 case STM32F7_APB1_CLOCK(TIM5):
396 case STM32F7_APB1_CLOCK(TIM6):
397 case STM32F7_APB1_CLOCK(TIM7):
398 case STM32F7_APB1_CLOCK(TIM12):
399 case STM32F7_APB1_CLOCK(TIM13):
400 case STM32F7_APB1_CLOCK(TIM14):
401 return stm32_get_timer_rate(priv, sysclk, APB1);
402 }
403 return (sysclk >> stm32_get_apb_shift(regs, APB1));
404
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200405 /* APB2 CLOCK */
406 case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100407 switch (clk->id) {
Patrice Chotard369d4832017-11-15 13:14:52 +0100408 /*
409 * particular case for SDMMC1 and SDMMC2 :
410 * 48Mhz source clock can be from main PLL or from
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100411 * PLLSAIP
Patrice Chotard369d4832017-11-15 13:14:52 +0100412 */
Patrice Chotard369d4832017-11-15 13:14:52 +0100413 case STM32F7_APB2_CLOCK(SDMMC1):
Patrice Chotard369d4832017-11-15 13:14:52 +0100414 case STM32F7_APB2_CLOCK(SDMMC2):
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100415 if (clk->id == STM32F7_APB2_CLOCK(SDMMC1))
416 sdmmcxsel_bit = RCC_DCKCFGRX_SDMMC1SEL;
417 else
418 sdmmcxsel_bit = RCC_DCKCFGR2_SDMMC2SEL;
419
420 if (readl(&regs->dckcfgr2) & sdmmcxsel_bit)
421 /* System clock is selected as SDMMC1 clock */
Patrice Chotard369d4832017-11-15 13:14:52 +0100422 return sysclk;
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100423 /*
424 * 48 MHz can be generated by either PLLSAIP
425 * or by PLLQ depending of CK48MSEL bit of RCC_DCKCFGR
426 */
427 if (stm32_clk_get_ck48msel(priv))
428 return stm32_clk_get_pllsai_rate(priv, PLLSAIP);
Patrice Chotard369d4832017-11-15 13:14:52 +0100429 else
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100430 return (vco / pllq);
Patrice Chotard369d4832017-11-15 13:14:52 +0100431 break;
Patrice Chotardef772872018-02-07 10:44:46 +0100432
433 /* For timer clock, an additionnal prescaler is used*/
434 case STM32F7_APB2_CLOCK(TIM1):
435 case STM32F7_APB2_CLOCK(TIM8):
436 case STM32F7_APB2_CLOCK(TIM9):
437 case STM32F7_APB2_CLOCK(TIM10):
438 case STM32F7_APB2_CLOCK(TIM11):
439 return stm32_get_timer_rate(priv, sysclk, APB2);
440 break;
Patrice Chotard369d4832017-11-15 13:14:52 +0100441 }
Patrice Chotardef772872018-02-07 10:44:46 +0100442 return (sysclk >> stm32_get_apb_shift(regs, APB2));
Patrice Chotard369d4832017-11-15 13:14:52 +0100443
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200444 default:
Masahiro Yamada81e10422017-09-16 14:10:41 +0900445 pr_err("clock index %ld out of range\n", clk->id);
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200446 return -EINVAL;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200447 }
448}
449
Patrice Chotard24e85782018-01-29 18:14:14 +0100450static ulong stm32_set_rate(struct clk *clk, ulong rate)
451{
452 return 0;
453}
454
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800455static int stm32_clk_enable(struct clk *clk)
456{
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200457 struct stm32_clk *priv = dev_get_priv(clk->dev);
458 struct stm32_rcc_regs *regs = priv->base;
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800459 u32 offset = clk->id / 32;
460 u32 bit_index = clk->id % 32;
461
462 debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
463 __func__, clk->id, offset, bit_index);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200464 setbits_le32(&regs->ahb1enr + offset, BIT(bit_index));
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800465
466 return 0;
467}
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900468
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800469static int stm32_clk_probe(struct udevice *dev)
470{
Patrice Chotard22768d52017-11-15 13:14:44 +0100471 struct ofnode_phandle_args args;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100472 struct udevice *fixed_clock_dev = NULL;
473 struct clk clk;
Patrice Chotard22768d52017-11-15 13:14:44 +0100474 int err;
475
Patrice Chotardd4f2d202017-11-15 13:14:48 +0100476 debug("%s\n", __func__);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200477
478 struct stm32_clk *priv = dev_get_priv(dev);
479 fdt_addr_t addr;
480
Patrice Chotard1509d662017-11-15 13:14:47 +0100481 addr = dev_read_addr(dev);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200482 if (addr == FDT_ADDR_T_NONE)
483 return -EINVAL;
484
485 priv->base = (struct stm32_rcc_regs *)addr;
Patrice Chotard03f10a12017-11-15 13:14:51 +0100486
487 switch (dev_get_driver_data(dev)) {
488 case STM32F4:
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100489 memcpy(&priv->info, &stm32f4_clk_info,
490 sizeof(struct stm32_clk_info));
Patrice Chotard03f10a12017-11-15 13:14:51 +0100491 break;
492 case STM32F7:
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100493 memcpy(&priv->info, &stm32f7_clk_info,
494 sizeof(struct stm32_clk_info));
Patrice Chotard03f10a12017-11-15 13:14:51 +0100495 break;
496 default:
497 return -EINVAL;
498 }
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200499
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100500 /* retrieve HSE frequency (external oscillator) */
501 err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse",
502 &fixed_clock_dev);
503
504 if (err) {
505 pr_err("Can't find fixed clock (%d)", err);
506 return err;
507 }
508
509 err = clk_request(fixed_clock_dev, &clk);
510 if (err) {
511 pr_err("Can't request %s clk (%d)", fixed_clock_dev->name,
512 err);
513 return err;
514 }
515
516 /*
517 * set pllm factor accordingly to the external oscillator
518 * frequency (HSE). For STM32F4 and STM32F7, we want VCO
519 * freq at 1MHz
520 * if input PLL frequency is 25Mhz, divide it by 25
521 */
522 clk.id = 0;
523 priv->hse_rate = clk_get_rate(&clk);
524
525 if (priv->hse_rate < 1000000) {
526 pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__,
527 priv->hse_rate);
528 return -EINVAL;
529 }
530
531 priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000;
532
533 if (priv->info.has_overdrive) {
Patrice Chotard1509d662017-11-15 13:14:47 +0100534 err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
535 &args);
536 if (err) {
537 debug("%s: can't find syscon device (%d)\n", __func__,
538 err);
539 return err;
540 }
Patrice Chotard22768d52017-11-15 13:14:44 +0100541
Patrice Chotard1509d662017-11-15 13:14:47 +0100542 priv->pwr_regs = (struct stm32_pwr_regs *)ofnode_get_addr(args.node);
543 }
Patrice Chotard22768d52017-11-15 13:14:44 +0100544
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200545 configure_clocks(dev);
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800546
547 return 0;
548}
549
Simon Glassb7ae2772017-05-18 20:09:40 -0600550static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800551{
552 debug("%s(clk=%p)\n", __func__, clk);
553
554 if (args->args_count != 2) {
555 debug("Invaild args_count: %d\n", args->args_count);
556 return -EINVAL;
557 }
558
559 if (args->args_count)
560 clk->id = args->args[1];
561 else
562 clk->id = 0;
563
564 return 0;
565}
566
567static struct clk_ops stm32_clk_ops = {
568 .of_xlate = stm32_clk_of_xlate,
569 .enable = stm32_clk_enable,
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200570 .get_rate = stm32_clk_get_rate,
Patrice Chotard24e85782018-01-29 18:14:14 +0100571 .set_rate = stm32_set_rate,
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800572};
573
Patrice Chotardd4f2d202017-11-15 13:14:48 +0100574U_BOOT_DRIVER(stm32fx_clk) = {
Patrice Chotard03f10a12017-11-15 13:14:51 +0100575 .name = "stm32fx_rcc_clock",
Patrice Chotardb323de52017-09-21 10:08:09 +0200576 .id = UCLASS_CLK,
Patrice Chotardb323de52017-09-21 10:08:09 +0200577 .ops = &stm32_clk_ops,
578 .probe = stm32_clk_probe,
579 .priv_auto_alloc_size = sizeof(struct stm32_clk),
580 .flags = DM_FLAG_PRE_RELOC,
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800581};