1712f99a5SVikas Manocha /*
2712f99a5SVikas Manocha * (C) Copyright 2017
3712f99a5SVikas Manocha * Vikas Manocha, <vikas.manocha@st.com>
4712f99a5SVikas Manocha *
5712f99a5SVikas Manocha * SPDX-License-Identifier: GPL-2.0+
6712f99a5SVikas Manocha */
7712f99a5SVikas Manocha #include <common.h>
8712f99a5SVikas Manocha #include <clk-uclass.h>
9712f99a5SVikas Manocha #include <dm.h>
10712f99a5SVikas Manocha #include <asm/io.h>
11712f99a5SVikas Manocha #include <asm/arch/rcc.h>
12712f99a5SVikas Manocha #include <asm/arch/stm32.h>
13712f99a5SVikas Manocha #include <asm/arch/stm32_periph.h>
14712f99a5SVikas Manocha
15288f17e6SPatrice Chotard #include <dt-bindings/mfd/stm32f7-rcc.h>
16288f17e6SPatrice Chotard
17712f99a5SVikas Manocha #define RCC_CR_HSION BIT(0)
18712f99a5SVikas Manocha #define RCC_CR_HSEON BIT(16)
19712f99a5SVikas Manocha #define RCC_CR_HSERDY BIT(17)
20712f99a5SVikas Manocha #define RCC_CR_HSEBYP BIT(18)
21712f99a5SVikas Manocha #define RCC_CR_CSSON BIT(19)
22712f99a5SVikas Manocha #define RCC_CR_PLLON BIT(24)
23712f99a5SVikas Manocha #define RCC_CR_PLLRDY BIT(25)
24712f99a5SVikas Manocha
25712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLM_MASK GENMASK(5, 0)
26712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLN_MASK GENMASK(14, 6)
27712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLP_MASK GENMASK(17, 16)
28712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLQ_MASK GENMASK(27, 24)
29712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLSRC BIT(22)
30712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLM_SHIFT 0
31712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLN_SHIFT 6
32712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLP_SHIFT 16
33712f99a5SVikas Manocha #define RCC_PLLCFGR_PLLQ_SHIFT 24
34712f99a5SVikas Manocha
35712f99a5SVikas Manocha #define RCC_CFGR_AHB_PSC_MASK GENMASK(7, 4)
36712f99a5SVikas Manocha #define RCC_CFGR_APB1_PSC_MASK GENMASK(12, 10)
37712f99a5SVikas Manocha #define RCC_CFGR_APB2_PSC_MASK GENMASK(15, 13)
38712f99a5SVikas Manocha #define RCC_CFGR_SW0 BIT(0)
39712f99a5SVikas Manocha #define RCC_CFGR_SW1 BIT(1)
40712f99a5SVikas Manocha #define RCC_CFGR_SW_MASK GENMASK(1, 0)
41712f99a5SVikas Manocha #define RCC_CFGR_SW_HSI 0
42712f99a5SVikas Manocha #define RCC_CFGR_SW_HSE RCC_CFGR_SW0
43712f99a5SVikas Manocha #define RCC_CFGR_SW_PLL RCC_CFGR_SW1
44712f99a5SVikas Manocha #define RCC_CFGR_SWS0 BIT(2)
45712f99a5SVikas Manocha #define RCC_CFGR_SWS1 BIT(3)
46712f99a5SVikas Manocha #define RCC_CFGR_SWS_MASK GENMASK(3, 2)
47712f99a5SVikas Manocha #define RCC_CFGR_SWS_HSI 0
48712f99a5SVikas Manocha #define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0
49712f99a5SVikas Manocha #define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1
50712f99a5SVikas Manocha #define RCC_CFGR_HPRE_SHIFT 4
51712f99a5SVikas Manocha #define RCC_CFGR_PPRE1_SHIFT 10
52712f99a5SVikas Manocha #define RCC_CFGR_PPRE2_SHIFT 13
53712f99a5SVikas Manocha
54712f99a5SVikas Manocha /*
55712f99a5SVikas Manocha * Offsets of some PWR registers
56712f99a5SVikas Manocha */
57712f99a5SVikas Manocha #define PWR_CR1_ODEN BIT(16)
58712f99a5SVikas Manocha #define PWR_CR1_ODSWEN BIT(17)
59712f99a5SVikas Manocha #define PWR_CSR1_ODRDY BIT(16)
60712f99a5SVikas Manocha #define PWR_CSR1_ODSWRDY BIT(17)
61712f99a5SVikas Manocha
62712f99a5SVikas Manocha struct pll_psc {
63712f99a5SVikas Manocha u8 pll_m;
64712f99a5SVikas Manocha u16 pll_n;
65712f99a5SVikas Manocha u8 pll_p;
66712f99a5SVikas Manocha u8 pll_q;
67712f99a5SVikas Manocha u8 ahb_psc;
68712f99a5SVikas Manocha u8 apb1_psc;
69712f99a5SVikas Manocha u8 apb2_psc;
70712f99a5SVikas Manocha };
71712f99a5SVikas Manocha
72712f99a5SVikas Manocha #define AHB_PSC_1 0
73712f99a5SVikas Manocha #define AHB_PSC_2 0x8
74712f99a5SVikas Manocha #define AHB_PSC_4 0x9
75712f99a5SVikas Manocha #define AHB_PSC_8 0xA
76712f99a5SVikas Manocha #define AHB_PSC_16 0xB
77712f99a5SVikas Manocha #define AHB_PSC_64 0xC
78712f99a5SVikas Manocha #define AHB_PSC_128 0xD
79712f99a5SVikas Manocha #define AHB_PSC_256 0xE
80712f99a5SVikas Manocha #define AHB_PSC_512 0xF
81712f99a5SVikas Manocha
82712f99a5SVikas Manocha #define APB_PSC_1 0
83712f99a5SVikas Manocha #define APB_PSC_2 0x4
84712f99a5SVikas Manocha #define APB_PSC_4 0x5
85712f99a5SVikas Manocha #define APB_PSC_8 0x6
86712f99a5SVikas Manocha #define APB_PSC_16 0x7
87712f99a5SVikas Manocha
88199a2178SPatrice Chotard struct stm32_clk {
89199a2178SPatrice Chotard struct stm32_rcc_regs *base;
90199a2178SPatrice Chotard };
91199a2178SPatrice Chotard
92712f99a5SVikas Manocha #if !defined(CONFIG_STM32_HSE_HZ)
93712f99a5SVikas Manocha #error "CONFIG_STM32_HSE_HZ not defined!"
94712f99a5SVikas Manocha #else
95712f99a5SVikas Manocha #if (CONFIG_STM32_HSE_HZ == 25000000)
96712f99a5SVikas Manocha #if (CONFIG_SYS_CLK_FREQ == 200000000)
97712f99a5SVikas Manocha /* 200 MHz */
98712f99a5SVikas Manocha struct pll_psc sys_pll_psc = {
99712f99a5SVikas Manocha .pll_m = 25,
100712f99a5SVikas Manocha .pll_n = 400,
101712f99a5SVikas Manocha .pll_p = 2,
102712f99a5SVikas Manocha .pll_q = 8,
103712f99a5SVikas Manocha .ahb_psc = AHB_PSC_1,
104712f99a5SVikas Manocha .apb1_psc = APB_PSC_4,
105712f99a5SVikas Manocha .apb2_psc = APB_PSC_2
106712f99a5SVikas Manocha };
107712f99a5SVikas Manocha #endif
108712f99a5SVikas Manocha #else
109712f99a5SVikas Manocha #error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists"
110712f99a5SVikas Manocha #endif
111712f99a5SVikas Manocha #endif
112712f99a5SVikas Manocha
configure_clocks(struct udevice * dev)113199a2178SPatrice Chotard static int configure_clocks(struct udevice *dev)
114712f99a5SVikas Manocha {
115199a2178SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev);
116199a2178SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
117199a2178SPatrice Chotard
118712f99a5SVikas Manocha /* Reset RCC configuration */
119199a2178SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSION);
120199a2178SPatrice Chotard writel(0, ®s->cfgr); /* Reset CFGR */
121199a2178SPatrice Chotard clrbits_le32(®s->cr, (RCC_CR_HSEON | RCC_CR_CSSON
122712f99a5SVikas Manocha | RCC_CR_PLLON));
123199a2178SPatrice Chotard writel(0x24003010, ®s->pllcfgr); /* Reset value from RM */
124199a2178SPatrice Chotard clrbits_le32(®s->cr, RCC_CR_HSEBYP);
125199a2178SPatrice Chotard writel(0, ®s->cir); /* Disable all interrupts */
126712f99a5SVikas Manocha
127712f99a5SVikas Manocha /* Configure for HSE+PLL operation */
128199a2178SPatrice Chotard setbits_le32(®s->cr, RCC_CR_HSEON);
129199a2178SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_HSERDY))
130712f99a5SVikas Manocha ;
131712f99a5SVikas Manocha
132199a2178SPatrice Chotard setbits_le32(®s->cfgr, ((
133712f99a5SVikas Manocha sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT)
134712f99a5SVikas Manocha | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT)
135712f99a5SVikas Manocha | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT)));
136712f99a5SVikas Manocha
137712f99a5SVikas Manocha /* Configure the main PLL */
138712f99a5SVikas Manocha uint32_t pllcfgr = 0;
139712f99a5SVikas Manocha pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */
140712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT;
141712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT;
142712f99a5SVikas Manocha pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT;
143712f99a5SVikas Manocha pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT;
144199a2178SPatrice Chotard writel(pllcfgr, ®s->pllcfgr);
145712f99a5SVikas Manocha
146712f99a5SVikas Manocha /* Enable the main PLL */
147199a2178SPatrice Chotard setbits_le32(®s->cr, RCC_CR_PLLON);
148199a2178SPatrice Chotard while (!(readl(®s->cr) & RCC_CR_PLLRDY))
149712f99a5SVikas Manocha ;
150712f99a5SVikas Manocha
151712f99a5SVikas Manocha /* Enable high performance mode, System frequency up to 200 MHz */
152199a2178SPatrice Chotard setbits_le32(®s->apb1enr, RCC_APB1ENR_PWREN);
153712f99a5SVikas Manocha setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN);
154712f99a5SVikas Manocha /* Infinite wait! */
155712f99a5SVikas Manocha while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY))
156712f99a5SVikas Manocha ;
157712f99a5SVikas Manocha /* Enable the Over-drive switch */
158712f99a5SVikas Manocha setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN);
159712f99a5SVikas Manocha /* Infinite wait! */
160712f99a5SVikas Manocha while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY))
161712f99a5SVikas Manocha ;
162712f99a5SVikas Manocha
163712f99a5SVikas Manocha stm32_flash_latency_cfg(5);
164199a2178SPatrice Chotard clrbits_le32(®s->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1));
165199a2178SPatrice Chotard setbits_le32(®s->cfgr, RCC_CFGR_SW_PLL);
166712f99a5SVikas Manocha
167199a2178SPatrice Chotard while ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) !=
168712f99a5SVikas Manocha RCC_CFGR_SWS_PLL)
169712f99a5SVikas Manocha ;
170712f99a5SVikas Manocha
171712f99a5SVikas Manocha return 0;
172712f99a5SVikas Manocha }
173712f99a5SVikas Manocha
stm32_clk_get_rate(struct clk * clk)174288f17e6SPatrice Chotard static unsigned long stm32_clk_get_rate(struct clk *clk)
175288f17e6SPatrice Chotard {
176288f17e6SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev);
177288f17e6SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
178288f17e6SPatrice Chotard u32 sysclk = 0;
179288f17e6SPatrice Chotard u32 shift = 0;
180288f17e6SPatrice Chotard /* Prescaler table lookups for clock computation */
181288f17e6SPatrice Chotard u8 ahb_psc_table[16] = {
182288f17e6SPatrice Chotard 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
183288f17e6SPatrice Chotard };
184288f17e6SPatrice Chotard u8 apb_psc_table[8] = {
185288f17e6SPatrice Chotard 0, 0, 0, 0, 1, 2, 3, 4
186288f17e6SPatrice Chotard };
187288f17e6SPatrice Chotard
188288f17e6SPatrice Chotard if ((readl(®s->cfgr) & RCC_CFGR_SWS_MASK) ==
189288f17e6SPatrice Chotard RCC_CFGR_SWS_PLL) {
190288f17e6SPatrice Chotard u16 pllm, plln, pllp;
191288f17e6SPatrice Chotard pllm = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLM_MASK);
192288f17e6SPatrice Chotard plln = ((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLN_MASK)
193288f17e6SPatrice Chotard >> RCC_PLLCFGR_PLLN_SHIFT);
194288f17e6SPatrice Chotard pllp = ((((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLP_MASK)
195288f17e6SPatrice Chotard >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1);
196288f17e6SPatrice Chotard sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp;
197288f17e6SPatrice Chotard } else {
198288f17e6SPatrice Chotard return -EINVAL;
199288f17e6SPatrice Chotard }
200288f17e6SPatrice Chotard
201288f17e6SPatrice Chotard switch (clk->id) {
202288f17e6SPatrice Chotard /*
203288f17e6SPatrice Chotard * AHB CLOCK: 3 x 32 bits consecutive registers are used :
204288f17e6SPatrice Chotard * AHB1, AHB2 and AHB3
205288f17e6SPatrice Chotard */
206288f17e6SPatrice Chotard case STM32F7_AHB1_CLOCK(GPIOA) ... STM32F7_AHB3_CLOCK(QSPI):
207288f17e6SPatrice Chotard shift = ahb_psc_table[(
208288f17e6SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_AHB_PSC_MASK)
209288f17e6SPatrice Chotard >> RCC_CFGR_HPRE_SHIFT)];
210288f17e6SPatrice Chotard return sysclk >>= shift;
211288f17e6SPatrice Chotard break;
212288f17e6SPatrice Chotard /* APB1 CLOCK */
213288f17e6SPatrice Chotard case STM32F7_APB1_CLOCK(TIM2) ... STM32F7_APB1_CLOCK(UART8):
214288f17e6SPatrice Chotard shift = apb_psc_table[(
215288f17e6SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB1_PSC_MASK)
216288f17e6SPatrice Chotard >> RCC_CFGR_PPRE1_SHIFT)];
217288f17e6SPatrice Chotard return sysclk >>= shift;
218288f17e6SPatrice Chotard break;
219288f17e6SPatrice Chotard /* APB2 CLOCK */
220288f17e6SPatrice Chotard case STM32F7_APB2_CLOCK(TIM1) ... STM32F7_APB2_CLOCK(LTDC):
221288f17e6SPatrice Chotard shift = apb_psc_table[(
222288f17e6SPatrice Chotard (readl(®s->cfgr) & RCC_CFGR_APB2_PSC_MASK)
223288f17e6SPatrice Chotard >> RCC_CFGR_PPRE2_SHIFT)];
224288f17e6SPatrice Chotard return sysclk >>= shift;
225288f17e6SPatrice Chotard break;
226288f17e6SPatrice Chotard default:
227*90aa625cSMasahiro Yamada pr_err("clock index %ld out of range\n", clk->id);
228288f17e6SPatrice Chotard return -EINVAL;
229288f17e6SPatrice Chotard break;
230288f17e6SPatrice Chotard }
231288f17e6SPatrice Chotard }
232288f17e6SPatrice Chotard
stm32_clk_enable(struct clk * clk)233712f99a5SVikas Manocha static int stm32_clk_enable(struct clk *clk)
234712f99a5SVikas Manocha {
235199a2178SPatrice Chotard struct stm32_clk *priv = dev_get_priv(clk->dev);
236199a2178SPatrice Chotard struct stm32_rcc_regs *regs = priv->base;
237712f99a5SVikas Manocha u32 offset = clk->id / 32;
238712f99a5SVikas Manocha u32 bit_index = clk->id % 32;
239712f99a5SVikas Manocha
240712f99a5SVikas Manocha debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
241712f99a5SVikas Manocha __func__, clk->id, offset, bit_index);
242199a2178SPatrice Chotard setbits_le32(®s->ahb1enr + offset, BIT(bit_index));
243712f99a5SVikas Manocha
244712f99a5SVikas Manocha return 0;
245712f99a5SVikas Manocha }
246712f99a5SVikas Manocha
clock_setup(int peripheral)247712f99a5SVikas Manocha void clock_setup(int peripheral)
248712f99a5SVikas Manocha {
249712f99a5SVikas Manocha switch (peripheral) {
250712f99a5SVikas Manocha case SYSCFG_CLOCK_CFG:
251712f99a5SVikas Manocha setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN);
252712f99a5SVikas Manocha break;
253712f99a5SVikas Manocha case TIMER2_CLOCK_CFG:
254712f99a5SVikas Manocha setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN);
255712f99a5SVikas Manocha break;
256712f99a5SVikas Manocha case STMMAC_CLOCK_CFG:
257712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN);
258712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN);
259712f99a5SVikas Manocha setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN);
260712f99a5SVikas Manocha break;
261712f99a5SVikas Manocha default:
262712f99a5SVikas Manocha break;
263712f99a5SVikas Manocha }
264712f99a5SVikas Manocha }
265712f99a5SVikas Manocha
stm32_clk_probe(struct udevice * dev)266712f99a5SVikas Manocha static int stm32_clk_probe(struct udevice *dev)
267712f99a5SVikas Manocha {
268712f99a5SVikas Manocha debug("%s: stm32_clk_probe\n", __func__);
269199a2178SPatrice Chotard
270199a2178SPatrice Chotard struct stm32_clk *priv = dev_get_priv(dev);
271199a2178SPatrice Chotard fdt_addr_t addr;
272199a2178SPatrice Chotard
273199a2178SPatrice Chotard addr = devfdt_get_addr(dev);
274199a2178SPatrice Chotard if (addr == FDT_ADDR_T_NONE)
275199a2178SPatrice Chotard return -EINVAL;
276199a2178SPatrice Chotard
277199a2178SPatrice Chotard priv->base = (struct stm32_rcc_regs *)addr;
278199a2178SPatrice Chotard
279199a2178SPatrice Chotard configure_clocks(dev);
280712f99a5SVikas Manocha
281712f99a5SVikas Manocha return 0;
282712f99a5SVikas Manocha }
283712f99a5SVikas Manocha
stm32_clk_of_xlate(struct clk * clk,struct ofnode_phandle_args * args)284a4e0ef50SSimon Glass static int stm32_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
285712f99a5SVikas Manocha {
286712f99a5SVikas Manocha debug("%s(clk=%p)\n", __func__, clk);
287712f99a5SVikas Manocha
288712f99a5SVikas Manocha if (args->args_count != 2) {
289712f99a5SVikas Manocha debug("Invaild args_count: %d\n", args->args_count);
290712f99a5SVikas Manocha return -EINVAL;
291712f99a5SVikas Manocha }
292712f99a5SVikas Manocha
293712f99a5SVikas Manocha if (args->args_count)
294712f99a5SVikas Manocha clk->id = args->args[1];
295712f99a5SVikas Manocha else
296712f99a5SVikas Manocha clk->id = 0;
297712f99a5SVikas Manocha
298712f99a5SVikas Manocha return 0;
299712f99a5SVikas Manocha }
300712f99a5SVikas Manocha
301712f99a5SVikas Manocha static struct clk_ops stm32_clk_ops = {
302712f99a5SVikas Manocha .of_xlate = stm32_clk_of_xlate,
303712f99a5SVikas Manocha .enable = stm32_clk_enable,
304288f17e6SPatrice Chotard .get_rate = stm32_clk_get_rate,
305712f99a5SVikas Manocha };
306712f99a5SVikas Manocha
307712f99a5SVikas Manocha static const struct udevice_id stm32_clk_ids[] = {
308712f99a5SVikas Manocha { .compatible = "st,stm32f42xx-rcc"},
309712f99a5SVikas Manocha {}
310712f99a5SVikas Manocha };
311712f99a5SVikas Manocha
312712f99a5SVikas Manocha U_BOOT_DRIVER(stm32f7_clk) = {
313712f99a5SVikas Manocha .name = "stm32f7_clk",
314712f99a5SVikas Manocha .id = UCLASS_CLK,
315712f99a5SVikas Manocha .of_match = stm32_clk_ids,
316712f99a5SVikas Manocha .ops = &stm32_clk_ops,
317712f99a5SVikas Manocha .probe = stm32_clk_probe,
318712f99a5SVikas Manocha .flags = DM_FLAG_PRE_RELOC,
319712f99a5SVikas Manocha };
320