blob: 6c1e2575ff84686321cb21601e41b2346eeee109 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Vikas Manocha1b51c932016-02-11 15:47:20 -08002/*
Patrice Chotard789ee0e2017-10-23 09:53:58 +02003 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
4 * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
Vikas Manocha1b51c932016-02-11 15:47:20 -08005 */
Patrice Chotard789ee0e2017-10-23 09:53:58 +02006
Vikas Manocha1b51c932016-02-11 15:47:20 -08007#include <common.h>
Vikas Manochadaaeaab2017-02-12 10:25:45 -08008#include <clk-uclass.h>
9#include <dm.h>
Patrice Chotard03f10a12017-11-15 13:14:51 +010010#include <stm32_rcc.h>
Patrice Chotard22768d52017-11-15 13:14:44 +010011
Vikas Manocha1b51c932016-02-11 15:47:20 -080012#include <asm/io.h>
Vikas Manocha1b51c932016-02-11 15:47:20 -080013#include <asm/arch/stm32.h>
Patrice Chotard22768d52017-11-15 13:14:44 +010014#include <asm/arch/stm32_pwr.h>
Vikas Manocha1b51c932016-02-11 15:47:20 -080015
Patrice Chotard7bdf9712017-07-18 09:29:05 +020016#include <dt-bindings/mfd/stm32f7-rcc.h>
17
Michael Kurzc204fb72017-01-22 16:04:24 +010018#define RCC_CR_HSION BIT(0)
19#define RCC_CR_HSEON BIT(16)
20#define RCC_CR_HSERDY BIT(17)
21#define RCC_CR_HSEBYP BIT(18)
22#define RCC_CR_CSSON BIT(19)
23#define RCC_CR_PLLON BIT(24)
24#define RCC_CR_PLLRDY BIT(25)
Patrice Chotard369d4832017-11-15 13:14:52 +010025#define RCC_CR_PLLSAION BIT(28)
26#define RCC_CR_PLLSAIRDY BIT(29)
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090027
Michael Kurzc204fb72017-01-22 16:04:24 +010028#define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0)
29#define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6)
30#define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16)
31#define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24)
32#define RCC_PLLCFGR_PLLSRC BIT(22)
33#define RCC_PLLCFGR_PLLM_SHIFT 0
34#define RCC_PLLCFGR_PLLN_SHIFT 6
35#define RCC_PLLCFGR_PLLP_SHIFT 16
36#define RCC_PLLCFGR_PLLQ_SHIFT 24
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090037
Michael Kurzc204fb72017-01-22 16:04:24 +010038#define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4)
39#define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10)
40#define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13)
41#define RCC_CFGR_SW0 BIT(0)
42#define RCC_CFGR_SW1 BIT(1)
43#define RCC_CFGR_SW_MASK GENMASK(1, 0)
44#define RCC_CFGR_SW_HSI 0
45#define RCC_CFGR_SW_HSE RCC_CFGR_SW0
46#define RCC_CFGR_SW_PLL RCC_CFGR_SW1
47#define RCC_CFGR_SWS0 BIT(2)
48#define RCC_CFGR_SWS1 BIT(3)
49#define RCC_CFGR_SWS_MASK GENMASK(3, 2)
50#define RCC_CFGR_SWS_HSI 0
51#define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0
52#define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1
53#define RCC_CFGR_HPRE_SHIFT 4
54#define RCC_CFGR_PPRE1_SHIFT 10
55#define RCC_CFGR_PPRE2_SHIFT 13
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +090056
Patrice Chotard9490aca2018-02-08 17:20:46 +010057#define RCC_PLLSAICFGR_PLLSAIN_MASK GENMASK(14, 6)
58#define RCC_PLLSAICFGR_PLLSAIP_MASK GENMASK(17, 16)
Patrice Chotard8aca2d12018-02-08 17:20:48 +010059#define RCC_PLLSAICFGR_PLLSAIQ_MASK GENMASK(27, 24)
60#define RCC_PLLSAICFGR_PLLSAIR_MASK GENMASK(30, 28)
Patrice Chotard369d4832017-11-15 13:14:52 +010061#define RCC_PLLSAICFGR_PLLSAIN_SHIFT 6
62#define RCC_PLLSAICFGR_PLLSAIP_SHIFT 16
Patrice Chotard8aca2d12018-02-08 17:20:48 +010063#define RCC_PLLSAICFGR_PLLSAIQ_SHIFT 24
64#define RCC_PLLSAICFGR_PLLSAIR_SHIFT 28
Patrice Chotardd5d36552018-01-19 18:02:40 +010065#define RCC_PLLSAICFGR_PLLSAIP_4 BIT(16)
Patrice Chotard369d4832017-11-15 13:14:52 +010066#define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26)
Patrice Chotardff7b11e2018-02-08 17:20:49 +010067#define RCC_PLLSAICFGR_PLLSAIR_3 BIT(29) | BIT(28)
Patrice Chotard369d4832017-11-15 13:14:52 +010068
Patrice Chotardef772872018-02-07 10:44:46 +010069#define RCC_DCKCFGRX_TIMPRE BIT(24)
Patrice Chotard369d4832017-11-15 13:14:52 +010070#define RCC_DCKCFGRX_CK48MSEL BIT(27)
71#define RCC_DCKCFGRX_SDMMC1SEL BIT(28)
72#define RCC_DCKCFGR2_SDMMC2SEL BIT(29)
73
Patrice Chotardff7b11e2018-02-08 17:20:49 +010074#define RCC_DCKCFGR_PLLSAIDIVR_SHIFT 16
75#define RCC_DCKCFGR_PLLSAIDIVR_MASK GENMASK(17, 16)
76#define RCC_DCKCFGR_PLLSAIDIVR_2 0
77
Patrice Chotard06fc6482017-11-15 13:14:49 +010078/*
79 * RCC AHB1ENR specific definitions
80 */
81#define RCC_AHB1ENR_ETHMAC_EN BIT(25)
82#define RCC_AHB1ENR_ETHMAC_TX_EN BIT(26)
83#define RCC_AHB1ENR_ETHMAC_RX_EN BIT(27)
84
85/*
86 * RCC APB1ENR specific definitions
87 */
88#define RCC_APB1ENR_TIM2EN BIT(0)
89#define RCC_APB1ENR_PWREN BIT(28)
90
91/*
92 * RCC APB2ENR specific definitions
93 */
94#define RCC_APB2ENR_SYSCFGEN BIT(14)
Patrice Chotarde2d564e2018-01-18 14:10:05 +010095#define RCC_APB2ENR_SAI1EN BIT(22)
Patrice Chotard06fc6482017-11-15 13:14:49 +010096
Patrice Chotard8aca2d12018-02-08 17:20:48 +010097enum pllsai_div {
98 PLLSAIP,
99 PLLSAIQ,
100 PLLSAIR,
101};
102
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100103static const struct stm32_clk_info stm32f4_clk_info = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100104 /* 180 MHz */
105 .sys_pll_psc = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100106 .pll_n = 360,
107 .pll_p = 2,
108 .pll_q = 8,
109 .ahb_psc = AHB_PSC_1,
110 .apb1_psc = APB_PSC_4,
111 .apb2_psc = APB_PSC_2,
112 },
113 .has_overdrive = false,
Patrice Chotard369d4832017-11-15 13:14:52 +0100114 .v2 = false,
Patrice Chotard1509d662017-11-15 13:14:47 +0100115};
116
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100117static const struct stm32_clk_info stm32f7_clk_info = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100118 /* 200 MHz */
119 .sys_pll_psc = {
Patrice Chotard1509d662017-11-15 13:14:47 +0100120 .pll_n = 400,
121 .pll_p = 2,
122 .pll_q = 8,
123 .ahb_psc = AHB_PSC_1,
124 .apb1_psc = APB_PSC_4,
125 .apb2_psc = APB_PSC_2,
126 },
127 .has_overdrive = true,
Patrice Chotard369d4832017-11-15 13:14:52 +0100128 .v2 = true,
Patrice Chotard1509d662017-11-15 13:14:47 +0100129};
130
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200131struct stm32_clk {
132 struct stm32_rcc_regs *base;
Patrice Chotard22768d52017-11-15 13:14:44 +0100133 struct stm32_pwr_regs *pwr_regs;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100134 struct stm32_clk_info info;
135 unsigned long hse_rate;
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900136};
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900137
Patrice Chotard2cd1ed12018-02-08 17:20:50 +0100138#ifdef CONFIG_VIDEO_STM32
139static const u8 plldivr_table[] = { 0, 0, 2, 3, 4, 5, 6, 7 };
140#endif
Patrice Chotardff7b11e2018-02-08 17:20:49 +0100141static const u8 pllsaidivr_table[] = { 2, 4, 8, 16 };
142
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200143static int configure_clocks(struct udevice *dev)
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900144{
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200145 struct stm32_clk *priv = dev_get_priv(dev);
146 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotard22768d52017-11-15 13:14:44 +0100147 struct stm32_pwr_regs *pwr = priv->pwr_regs;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100148 struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc;
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200149
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900150 /* Reset RCC configuration */
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200151 setbits_le32(&regs->cr, RCC_CR_HSION);
152 writel(0, &regs->cfgr); /* Reset CFGR */
153 clrbits_le32(&regs->cr, (RCC_CR_HSEON | RCC_CR_CSSON
Patrice Chotard369d4832017-11-15 13:14:52 +0100154 | RCC_CR_PLLON | RCC_CR_PLLSAION));
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200155 writel(0x24003010, &regs->pllcfgr); /* Reset value from RM */
156 clrbits_le32(&regs->cr, RCC_CR_HSEBYP);
157 writel(0, &regs->cir); /* Disable all interrupts */
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900158
159 /* Configure for HSE+PLL operation */
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200160 setbits_le32(&regs->cr, RCC_CR_HSEON);
161 while (!(readl(&regs->cr) & RCC_CR_HSERDY))
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900162 ;
163
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200164 setbits_le32(&regs->cfgr, ((
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100165 sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT)
166 | (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT)
167 | (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900168
169 /* Configure the main PLL */
Patrice Chotardb6653f62017-10-26 13:23:19 +0200170 setbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */
171 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLM_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100172 sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200173 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLN_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100174 sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200175 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLP_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100176 ((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT);
Patrice Chotardb6653f62017-10-26 13:23:19 +0200177 clrsetbits_le32(&regs->pllcfgr, RCC_PLLCFGR_PLLQ_MASK,
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100178 sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT);
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900179
Patrice Chotardcb15d282018-02-08 17:20:47 +0100180 /* configure SDMMC clock */
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100181 if (priv->info.v2) { /*stm32f7 case */
Patrice Chotardcb15d282018-02-08 17:20:47 +0100182 /* select PLLQ as 48MHz clock source */
183 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_CK48MSEL);
Patrice Chotard369d4832017-11-15 13:14:52 +0100184
185 /* select 48MHz as SDMMC1 clock source */
186 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGRX_SDMMC1SEL);
187
188 /* select 48MHz as SDMMC2 clock source */
189 clrbits_le32(&regs->dckcfgr2, RCC_DCKCFGR2_SDMMC2SEL);
190 } else { /* stm32f4 case */
Patrice Chotardcb15d282018-02-08 17:20:47 +0100191 /* select PLLQ as 48MHz clock source */
192 clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_CK48MSEL);
Patrice Chotard369d4832017-11-15 13:14:52 +0100193
194 /* select 48MHz as SDMMC1 clock source */
195 clrbits_le32(&regs->dckcfgr, RCC_DCKCFGRX_SDMMC1SEL);
196 }
197
Patrice Chotardff7b11e2018-02-08 17:20:49 +0100198#ifdef CONFIG_VIDEO_STM32
199 /*
200 * Configure the SAI PLL to generate LTDC pixel clock
201 */
202 clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
203 RCC_PLLSAICFGR_PLLSAIR_3);
204 clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIN_MASK,
205 195 << RCC_PLLSAICFGR_PLLSAIN_SHIFT);
206
207 clrsetbits_le32(&regs->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
208 RCC_DCKCFGR_PLLSAIDIVR_2 << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
209#endif
Patrice Chotardcb15d282018-02-08 17:20:47 +0100210 /* Enable the main PLL */
211 setbits_le32(&regs->cr, RCC_CR_PLLON);
212 while (!(readl(&regs->cr) & RCC_CR_PLLRDY))
Patrice Chotard369d4832017-11-15 13:14:52 +0100213 ;
214
Patrice Chotardff7b11e2018-02-08 17:20:49 +0100215#ifdef CONFIG_VIDEO_STM32
216/* Enable the SAI PLL */
217 setbits_le32(&regs->cr, RCC_CR_PLLSAION);
218 while (!(readl(&regs->cr) & RCC_CR_PLLSAIRDY))
219 ;
220#endif
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200221 setbits_le32(&regs->apb1enr, RCC_APB1ENR_PWREN);
Patrice Chotard1509d662017-11-15 13:14:47 +0100222
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100223 if (priv->info.has_overdrive) {
Patrice Chotard1509d662017-11-15 13:14:47 +0100224 /*
225 * Enable high performance mode
226 * System frequency up to 200 MHz
227 */
228 setbits_le32(&pwr->cr1, PWR_CR1_ODEN);
229 /* Infinite wait! */
230 while (!(readl(&pwr->csr1) & PWR_CSR1_ODRDY))
231 ;
232 /* Enable the Over-drive switch */
233 setbits_le32(&pwr->cr1, PWR_CR1_ODSWEN);
234 /* Infinite wait! */
235 while (!(readl(&pwr->csr1) & PWR_CSR1_ODSWRDY))
236 ;
237 }
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900238
239 stm32_flash_latency_cfg(5);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200240 clrbits_le32(&regs->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
241 setbits_le32(&regs->cfgr, RCC_CFGR_SW_PLL);
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900242
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200243 while ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) !=
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900244 RCC_CFGR_SWS_PLL)
245 ;
246
Patrice Chotarde2d564e2018-01-18 14:10:05 +0100247#ifdef CONFIG_ETH_DESIGNWARE
248 /* gate the SYSCFG clock, needed to set RMII ethernet interface */
249 setbits_le32(&regs->apb2enr, RCC_APB2ENR_SYSCFGEN);
250#endif
251
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900252 return 0;
253}
254
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100255static bool stm32_clk_get_ck48msel(struct stm32_clk *priv)
Patrice Chotard369d4832017-11-15 13:14:52 +0100256{
257 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotard369d4832017-11-15 13:14:52 +0100258
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100259 if (priv->info.v2) /*stm32f7 case */
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100260 return readl(&regs->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL;
Patrice Chotard369d4832017-11-15 13:14:52 +0100261 else
Patrice Chotard369d4832017-11-15 13:14:52 +0100262
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100263 return readl(&regs->dckcfgr) & RCC_DCKCFGRX_CK48MSEL;
264}
265
266static unsigned long stm32_clk_get_pllsai_vco_rate(struct stm32_clk *priv)
267{
268 struct stm32_rcc_regs *regs = priv->base;
269 u16 pllm, pllsain;
270
271 pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
272 pllsain = ((readl(&regs->pllsaicfgr) & RCC_PLLSAICFGR_PLLSAIN_MASK)
273 >> RCC_PLLSAICFGR_PLLSAIN_SHIFT);
274
275 return ((priv->hse_rate / pllm) * pllsain);
276}
277
278static unsigned long stm32_clk_get_pllsai_rate(struct stm32_clk *priv,
279 enum pllsai_div output)
280{
281 struct stm32_rcc_regs *regs = priv->base;
282 u16 pll_div_output;
283
284 switch (output) {
285 case PLLSAIP:
286 pll_div_output = ((((readl(&regs->pllsaicfgr)
287 & RCC_PLLSAICFGR_PLLSAIP_MASK)
288 >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1);
289 break;
290 case PLLSAIQ:
291 pll_div_output = (readl(&regs->pllsaicfgr)
292 & RCC_PLLSAICFGR_PLLSAIQ_MASK)
293 >> RCC_PLLSAICFGR_PLLSAIQ_SHIFT;
294 break;
295 case PLLSAIR:
296 pll_div_output = (readl(&regs->pllsaicfgr)
297 & RCC_PLLSAICFGR_PLLSAIR_MASK)
298 >> RCC_PLLSAICFGR_PLLSAIR_SHIFT;
299 break;
300 default:
301 pr_err("incorrect PLLSAI output %d\n", output);
302 return -EINVAL;
Patrice Chotard369d4832017-11-15 13:14:52 +0100303 }
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100304
305 return (stm32_clk_get_pllsai_vco_rate(priv) / pll_div_output);
Patrice Chotard369d4832017-11-15 13:14:52 +0100306}
307
Patrice Chotardef772872018-02-07 10:44:46 +0100308static bool stm32_get_timpre(struct stm32_clk *priv)
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200309{
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200310 struct stm32_rcc_regs *regs = priv->base;
Patrice Chotardef772872018-02-07 10:44:46 +0100311 u32 val;
312
313 if (priv->info.v2) /*stm32f7 case */
314 val = readl(&regs->dckcfgr2);
315 else
316 val = readl(&regs->dckcfgr);
317 /* get timer prescaler */
318 return !!(val & RCC_DCKCFGRX_TIMPRE);
319}
320
321static u32 stm32_get_hclk_rate(struct stm32_rcc_regs *regs, u32 sysclk)
322{
323 u8 shift;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200324 /* Prescaler table lookups for clock computation */
325 u8 ahb_psc_table[16] = {
326 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
327 };
Patrice Chotardef772872018-02-07 10:44:46 +0100328
329 shift = ahb_psc_table[(
330 (readl(&regs->cfgr) & RCC_CFGR_AHB_PSC_MASK)
331 >> RCC_CFGR_HPRE_SHIFT)];
332
333 return sysclk >> shift;
334};
335
336static u8 stm32_get_apb_shift(struct stm32_rcc_regs *regs, enum apb apb)
337{
338 /* Prescaler table lookups for clock computation */
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200339 u8 apb_psc_table[8] = {
340 0, 0, 0, 0, 1, 2, 3, 4
341 };
342
Patrice Chotardef772872018-02-07 10:44:46 +0100343 if (apb == APB1)
344 return apb_psc_table[(
345 (readl(&regs->cfgr) & RCC_CFGR_APB1_PSC_MASK)
346 >> RCC_CFGR_PPRE1_SHIFT)];
347 else /* APB2 */
348 return apb_psc_table[(
349 (readl(&regs->cfgr) & RCC_CFGR_APB2_PSC_MASK)
350 >> RCC_CFGR_PPRE2_SHIFT)];
351};
352
353static u32 stm32_get_timer_rate(struct stm32_clk *priv, u32 sysclk,
354 enum apb apb)
355{
356 struct stm32_rcc_regs *regs = priv->base;
357 u8 shift = stm32_get_apb_shift(regs, apb);
358
359 if (stm32_get_timpre(priv))
360 /*
361 * if APB prescaler is configured to a
362 * division factor of 1, 2 or 4
363 */
364 switch (shift) {
365 case 0:
366 case 1:
367 case 2:
368 return stm32_get_hclk_rate(regs, sysclk);
369 default:
370 return (sysclk >> shift) * 4;
371 }
372 else
373 /*
374 * if APB prescaler is configured to a
375 * division factor of 1
376 */
377 if (shift == 0)
378 return sysclk;
379 else
380 return (sysclk >> shift) * 2;
381};
382
383static ulong stm32_clk_get_rate(struct clk *clk)
384{
385 struct stm32_clk *priv = dev_get_priv(clk->dev);
386 struct stm32_rcc_regs *regs = priv->base;
387 u32 sysclk = 0;
Patrice Chotard81d77652018-02-08 17:20:45 +0100388 u32 vco;
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100389 u32 sdmmcxsel_bit;
Patrice Chotardff7b11e2018-02-08 17:20:49 +0100390 u32 saidivr;
391 u32 pllsai_rate;
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100392 u16 pllm, plln, pllp, pllq;
Patrice Chotardef772872018-02-07 10:44:46 +0100393
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200394 if ((readl(&regs->cfgr) & RCC_CFGR_SWS_MASK) ==
395 RCC_CFGR_SWS_PLL) {
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200396 pllm = (readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
397 plln = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
398 >> RCC_PLLCFGR_PLLN_SHIFT);
399 pllp = ((((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
400 >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100401 pllq = ((readl(&regs->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK)
402 >> RCC_PLLCFGR_PLLQ_SHIFT);
Patrice Chotard81d77652018-02-08 17:20:45 +0100403 vco = (priv->hse_rate / pllm) * plln;
404 sysclk = vco / pllp;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200405 } else {
406 return -EINVAL;
407 }
408
409 switch (clk->id) {
410 /*
411 * AHB CLOCK: 3 x 32 bits consecutive registers are used :
412 * AHB1, AHB2 and AHB3
413 */
414 case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
Patrice Chotardef772872018-02-07 10:44:46 +0100415 return stm32_get_hclk_rate(regs, sysclk);
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200416 /* APB1 CLOCK */
417 case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
Patrice Chotardef772872018-02-07 10:44:46 +0100418 /* For timer clock, an additionnal prescaler is used*/
419 switch (clk->id) {
420 case STM32F7_APB1_CLOCK(TIM2):
421 case STM32F7_APB1_CLOCK(TIM3):
422 case STM32F7_APB1_CLOCK(TIM4):
423 case STM32F7_APB1_CLOCK(TIM5):
424 case STM32F7_APB1_CLOCK(TIM6):
425 case STM32F7_APB1_CLOCK(TIM7):
426 case STM32F7_APB1_CLOCK(TIM12):
427 case STM32F7_APB1_CLOCK(TIM13):
428 case STM32F7_APB1_CLOCK(TIM14):
429 return stm32_get_timer_rate(priv, sysclk, APB1);
430 }
431 return (sysclk >> stm32_get_apb_shift(regs, APB1));
432
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200433 /* APB2 CLOCK */
Patrice Chotarde199c3a2018-02-08 17:20:51 +0100434 case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(DSI):
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100435 switch (clk->id) {
Patrice Chotard369d4832017-11-15 13:14:52 +0100436 /*
437 * particular case for SDMMC1 and SDMMC2 :
438 * 48Mhz source clock can be from main PLL or from
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100439 * PLLSAIP
Patrice Chotard369d4832017-11-15 13:14:52 +0100440 */
Patrice Chotard369d4832017-11-15 13:14:52 +0100441 case STM32F7_APB2_CLOCK(SDMMC1):
Patrice Chotard369d4832017-11-15 13:14:52 +0100442 case STM32F7_APB2_CLOCK(SDMMC2):
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100443 if (clk->id == STM32F7_APB2_CLOCK(SDMMC1))
444 sdmmcxsel_bit = RCC_DCKCFGRX_SDMMC1SEL;
445 else
446 sdmmcxsel_bit = RCC_DCKCFGR2_SDMMC2SEL;
447
448 if (readl(&regs->dckcfgr2) & sdmmcxsel_bit)
449 /* System clock is selected as SDMMC1 clock */
Patrice Chotard369d4832017-11-15 13:14:52 +0100450 return sysclk;
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100451 /*
452 * 48 MHz can be generated by either PLLSAIP
453 * or by PLLQ depending of CK48MSEL bit of RCC_DCKCFGR
454 */
455 if (stm32_clk_get_ck48msel(priv))
456 return stm32_clk_get_pllsai_rate(priv, PLLSAIP);
Patrice Chotard369d4832017-11-15 13:14:52 +0100457 else
Patrice Chotard8aca2d12018-02-08 17:20:48 +0100458 return (vco / pllq);
Patrice Chotard369d4832017-11-15 13:14:52 +0100459 break;
Patrice Chotardef772872018-02-07 10:44:46 +0100460
461 /* For timer clock, an additionnal prescaler is used*/
462 case STM32F7_APB2_CLOCK(TIM1):
463 case STM32F7_APB2_CLOCK(TIM8):
464 case STM32F7_APB2_CLOCK(TIM9):
465 case STM32F7_APB2_CLOCK(TIM10):
466 case STM32F7_APB2_CLOCK(TIM11):
467 return stm32_get_timer_rate(priv, sysclk, APB2);
468 break;
Patrice Chotardff7b11e2018-02-08 17:20:49 +0100469
470 /* particular case for LTDC clock */
471 case STM32F7_APB2_CLOCK(LTDC):
472 saidivr = readl(&regs->dckcfgr);
473 saidivr = (saidivr & RCC_DCKCFGR_PLLSAIDIVR_MASK)
474 >> RCC_DCKCFGR_PLLSAIDIVR_SHIFT;
475 pllsai_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR);
476
477 return pllsai_rate / pllsaidivr_table[saidivr];
Patrice Chotard369d4832017-11-15 13:14:52 +0100478 }
Patrice Chotardef772872018-02-07 10:44:46 +0100479 return (sysclk >> stm32_get_apb_shift(regs, APB2));
Patrice Chotard369d4832017-11-15 13:14:52 +0100480
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200481 default:
Masahiro Yamada81e10422017-09-16 14:10:41 +0900482 pr_err("clock index %ld out of range\n", clk->id);
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200483 return -EINVAL;
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200484 }
485}
486
Patrice Chotard24e85782018-01-29 18:14:14 +0100487static ulong stm32_set_rate(struct clk *clk, ulong rate)
488{
Patrice Chotard2cd1ed12018-02-08 17:20:50 +0100489#ifdef CONFIG_VIDEO_STM32
490 struct stm32_clk *priv = dev_get_priv(clk->dev);
491 struct stm32_rcc_regs *regs = priv->base;
492 u32 pllsair_rate, pllsai_vco_rate, current_rate;
493 u32 best_div, best_diff, diff;
494 u16 div;
495 u8 best_plldivr, best_pllsaidivr;
496 u8 i, j;
497 bool found = false;
498
499 /* Only set_rate for LTDC clock is implemented */
500 if (clk->id != STM32F7_APB2_CLOCK(LTDC)) {
501 pr_err("set_rate not implemented for clock index %ld\n",
502 clk->id);
503 return 0;
504 }
505
506 if (rate == stm32_clk_get_rate(clk))
507 /* already set to requested rate */
508 return rate;
509
510 /* get the current PLLSAIR output freq */
511 pllsair_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR);
512 best_div = pllsair_rate / rate;
513
514 /* look into pllsaidivr_table if this divider is available*/
515 for (i = 0 ; i < sizeof(pllsaidivr_table); i++)
516 if (best_div == pllsaidivr_table[i]) {
517 /* set pll_saidivr with found value */
518 clrsetbits_le32(&regs->dckcfgr,
519 RCC_DCKCFGR_PLLSAIDIVR_MASK,
520 pllsaidivr_table[i]);
521 return rate;
522 }
523
524 /*
525 * As no pllsaidivr value is suitable to obtain requested freq,
526 * test all combination of pllsaidivr * pllsair and find the one
527 * which give freq closest to requested rate.
528 */
529
530 pllsai_vco_rate = stm32_clk_get_pllsai_vco_rate(priv);
531 best_diff = ULONG_MAX;
532 best_pllsaidivr = 0;
533 best_plldivr = 0;
534 /*
535 * start at index 2 of plldivr_table as divider value at index 0
536 * and 1 are 0)
537 */
538 for (i = 2; i < sizeof(plldivr_table); i++) {
539 for (j = 0; j < sizeof(pllsaidivr_table); j++) {
540 div = plldivr_table[i] * pllsaidivr_table[j];
541 current_rate = pllsai_vco_rate / div;
542 /* perfect combination is found ? */
543 if (current_rate == rate) {
544 best_pllsaidivr = j;
545 best_plldivr = i;
546 found = true;
547 break;
548 }
549
550 diff = (current_rate > rate) ?
551 current_rate - rate : rate - current_rate;
552
553 /* found a better combination ? */
554 if (diff < best_diff) {
555 best_diff = diff;
556 best_pllsaidivr = j;
557 best_plldivr = i;
558 }
559 }
560
561 if (found)
562 break;
563 }
564
565 /* Disable the SAI PLL */
566 clrbits_le32(&regs->cr, RCC_CR_PLLSAION);
567
568 /* set pll_saidivr with found value */
569 clrsetbits_le32(&regs->dckcfgr, RCC_DCKCFGR_PLLSAIDIVR_MASK,
570 best_pllsaidivr << RCC_DCKCFGR_PLLSAIDIVR_SHIFT);
571
572 /* set pllsair with found value */
573 clrsetbits_le32(&regs->pllsaicfgr, RCC_PLLSAICFGR_PLLSAIR_MASK,
574 plldivr_table[best_plldivr]
575 << RCC_PLLSAICFGR_PLLSAIR_SHIFT);
576
577 /* Enable the SAI PLL */
578 setbits_le32(&regs->cr, RCC_CR_PLLSAION);
579 while (!(readl(&regs->cr) & RCC_CR_PLLSAIRDY))
580 ;
581
582 div = plldivr_table[best_plldivr] * pllsaidivr_table[best_pllsaidivr];
583 return pllsai_vco_rate / div;
584#else
Patrice Chotard24e85782018-01-29 18:14:14 +0100585 return 0;
Patrice Chotard2cd1ed12018-02-08 17:20:50 +0100586#endif
Patrice Chotard24e85782018-01-29 18:14:14 +0100587}
588
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800589static int stm32_clk_enable(struct clk *clk)
590{
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200591 struct stm32_clk *priv = dev_get_priv(clk->dev);
592 struct stm32_rcc_regs *regs = priv->base;
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800593 u32 offset = clk->id / 32;
594 u32 bit_index = clk->id % 32;
595
596 debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
597 __func__, clk->id, offset, bit_index);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200598 setbits_le32(&regs->ahb1enr + offset, BIT(bit_index));
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800599
600 return 0;
601}
Toshifumi NISHINAGA65bfb9c2016-07-08 01:02:24 +0900602
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800603static int stm32_clk_probe(struct udevice *dev)
604{
Patrice Chotard22768d52017-11-15 13:14:44 +0100605 struct ofnode_phandle_args args;
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100606 struct udevice *fixed_clock_dev = NULL;
607 struct clk clk;
Patrice Chotard22768d52017-11-15 13:14:44 +0100608 int err;
609
Patrice Chotardd4f2d202017-11-15 13:14:48 +0100610 debug("%s\n", __func__);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200611
612 struct stm32_clk *priv = dev_get_priv(dev);
613 fdt_addr_t addr;
614
Patrice Chotard1509d662017-11-15 13:14:47 +0100615 addr = dev_read_addr(dev);
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200616 if (addr == FDT_ADDR_T_NONE)
617 return -EINVAL;
618
619 priv->base = (struct stm32_rcc_regs *)addr;
Patrice Chotard03f10a12017-11-15 13:14:51 +0100620
621 switch (dev_get_driver_data(dev)) {
622 case STM32F4:
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100623 memcpy(&priv->info, &stm32f4_clk_info,
624 sizeof(struct stm32_clk_info));
Patrice Chotard03f10a12017-11-15 13:14:51 +0100625 break;
626 case STM32F7:
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100627 memcpy(&priv->info, &stm32f7_clk_info,
628 sizeof(struct stm32_clk_info));
Patrice Chotard03f10a12017-11-15 13:14:51 +0100629 break;
630 default:
631 return -EINVAL;
632 }
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200633
Patrice Chotardacd97ca2018-01-18 13:39:30 +0100634 /* retrieve HSE frequency (external oscillator) */
635 err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse",
636 &fixed_clock_dev);
637
638 if (err) {
639 pr_err("Can't find fixed clock (%d)", err);
640 return err;
641 }
642
643 err = clk_request(fixed_clock_dev, &clk);
644 if (err) {
645 pr_err("Can't request %s clk (%d)", fixed_clock_dev->name,
646 err);
647 return err;
648 }
649
650 /*
651 * set pllm factor accordingly to the external oscillator
652 * frequency (HSE). For STM32F4 and STM32F7, we want VCO
653 * freq at 1MHz
654 * if input PLL frequency is 25Mhz, divide it by 25
655 */
656 clk.id = 0;
657 priv->hse_rate = clk_get_rate(&clk);
658
659 if (priv->hse_rate < 1000000) {
660 pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__,
661 priv->hse_rate);
662 return -EINVAL;
663 }
664
665 priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000;
666
667 if (priv->info.has_overdrive) {
Patrice Chotard1509d662017-11-15 13:14:47 +0100668 err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0,
669 &args);
670 if (err) {
671 debug("%s: can't find syscon device (%d)\n", __func__,
672 err);
673 return err;
674 }
Patrice Chotard22768d52017-11-15 13:14:44 +0100675
Patrice Chotard1509d662017-11-15 13:14:47 +0100676 priv->pwr_regs = (struct stm32_pwr_regs *)ofnode_get_addr(args.node);
677 }
Patrice Chotard22768d52017-11-15 13:14:44 +0100678
Patrice Chotardd93fc2c2017-07-18 09:29:04 +0200679 configure_clocks(dev);
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800680
681 return 0;
682}
683
Simon Glassb7ae2772017-05-18 20:09:40 -0600684static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800685{
686 debug("%s(clk=%p)\n", __func__, clk);
687
688 if (args->args_count != 2) {
689 debug("Invaild args_count: %d\n", args->args_count);
690 return -EINVAL;
691 }
692
693 if (args->args_count)
694 clk->id = args->args[1];
695 else
696 clk->id = 0;
697
698 return 0;
699}
700
701static struct clk_ops stm32_clk_ops = {
702 .of_xlate = stm32_clk_of_xlate,
703 .enable = stm32_clk_enable,
Patrice Chotard7bdf9712017-07-18 09:29:05 +0200704 .get_rate = stm32_clk_get_rate,
Patrice Chotard24e85782018-01-29 18:14:14 +0100705 .set_rate = stm32_set_rate,
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800706};
707
Patrice Chotardd4f2d202017-11-15 13:14:48 +0100708U_BOOT_DRIVER(stm32fx_clk) = {
Patrice Chotard03f10a12017-11-15 13:14:51 +0100709 .name = "stm32fx_rcc_clock",
Patrice Chotardb323de52017-09-21 10:08:09 +0200710 .id = UCLASS_CLK,
Patrice Chotardb323de52017-09-21 10:08:09 +0200711 .ops = &stm32_clk_ops,
712 .probe = stm32_clk_probe,
713 .priv_auto_alloc_size = sizeof(struct stm32_clk),
714 .flags = DM_FLAG_PRE_RELOC,
Vikas Manochadaaeaab2017-02-12 10:25:45 -0800715};