19952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2358bdf89SDaniel Thompson /*
3358bdf89SDaniel Thompson * Author: Daniel Thompson <daniel.thompson@linaro.org>
4358bdf89SDaniel Thompson *
5358bdf89SDaniel Thompson * Inspired by clk-asm9260.c .
6358bdf89SDaniel Thompson */
7358bdf89SDaniel Thompson
8358bdf89SDaniel Thompson #include <linux/clk-provider.h>
9358bdf89SDaniel Thompson #include <linux/err.h>
10358bdf89SDaniel Thompson #include <linux/io.h>
11861adc44SGabriel Fernandez #include <linux/iopoll.h>
12861adc44SGabriel Fernandez #include <linux/ioport.h>
13358bdf89SDaniel Thompson #include <linux/slab.h>
14358bdf89SDaniel Thompson #include <linux/spinlock.h>
15358bdf89SDaniel Thompson #include <linux/of.h>
16358bdf89SDaniel Thompson #include <linux/of_address.h>
17861adc44SGabriel Fernandez #include <linux/regmap.h>
18861adc44SGabriel Fernandez #include <linux/mfd/syscon.h>
19358bdf89SDaniel Thompson
2083135ad3SGabriel Fernandez /*
2183135ad3SGabriel Fernandez * Include list of clocks wich are not derived from system clock (SYSCLOCK)
2283135ad3SGabriel Fernandez * The index of these clocks is the secondary index of DT bindings
2383135ad3SGabriel Fernandez *
2483135ad3SGabriel Fernandez */
2583135ad3SGabriel Fernandez #include <dt-bindings/clock/stm32fx-clock.h>
2683135ad3SGabriel Fernandez
2783135ad3SGabriel Fernandez #define STM32F4_RCC_CR 0x00
28358bdf89SDaniel Thompson #define STM32F4_RCC_PLLCFGR 0x04
29358bdf89SDaniel Thompson #define STM32F4_RCC_CFGR 0x08
30358bdf89SDaniel Thompson #define STM32F4_RCC_AHB1ENR 0x30
31358bdf89SDaniel Thompson #define STM32F4_RCC_AHB2ENR 0x34
32358bdf89SDaniel Thompson #define STM32F4_RCC_AHB3ENR 0x38
33358bdf89SDaniel Thompson #define STM32F4_RCC_APB1ENR 0x40
34358bdf89SDaniel Thompson #define STM32F4_RCC_APB2ENR 0x44
35861adc44SGabriel Fernandez #define STM32F4_RCC_BDCR 0x70
36861adc44SGabriel Fernandez #define STM32F4_RCC_CSR 0x74
3783135ad3SGabriel Fernandez #define STM32F4_RCC_PLLI2SCFGR 0x84
3883135ad3SGabriel Fernandez #define STM32F4_RCC_PLLSAICFGR 0x88
39517633efSGabriel Fernandez #define STM32F4_RCC_DCKCFGR 0x8c
4088c9b70bSGabriel Fernandez #define STM32F7_RCC_DCKCFGR2 0x90
41517633efSGabriel Fernandez
42517633efSGabriel Fernandez #define NONE -1
43517633efSGabriel Fernandez #define NO_IDX NONE
44daf2d117SGabriel Fernandez #define NO_MUX NONE
45daf2d117SGabriel Fernandez #define NO_GATE NONE
46358bdf89SDaniel Thompson
47358bdf89SDaniel Thompson struct stm32f4_gate_data {
48358bdf89SDaniel Thompson u8 offset;
49358bdf89SDaniel Thompson u8 bit_idx;
50358bdf89SDaniel Thompson const char *name;
51358bdf89SDaniel Thompson const char *parent_name;
52358bdf89SDaniel Thompson unsigned long flags;
53358bdf89SDaniel Thompson };
54358bdf89SDaniel Thompson
55a064a07fSGabriel Fernandez static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
56358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
57358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
58358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
59358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
60358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
61358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
62358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
63358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
64358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
65358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
66358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
67358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
68358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
69358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
70358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
71358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
72358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
73358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
74358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
75358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
76358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
77358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
78358bdf89SDaniel Thompson { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
79358bdf89SDaniel Thompson
80358bdf89SDaniel Thompson { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
81358bdf89SDaniel Thompson { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
82358bdf89SDaniel Thompson { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
83358bdf89SDaniel Thompson { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
84358bdf89SDaniel Thompson { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
85358bdf89SDaniel Thompson
86358bdf89SDaniel Thompson { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
87358bdf89SDaniel Thompson CLK_IGNORE_UNUSED },
88358bdf89SDaniel Thompson
89358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
90358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
91358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
92358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
93358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
94358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
95358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
96358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
97358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
98358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
99358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
100358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
101358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
102358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
103358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
104358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
105358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
106358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
107358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
108358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
109358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
110358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
111358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
112358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
113358bdf89SDaniel Thompson { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
114358bdf89SDaniel Thompson
115358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
116358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
117358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
118358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
119358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
120358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
121358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
122358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" },
123358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
124358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
125358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
126358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
127358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
128358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
129358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
130358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
131358bdf89SDaniel Thompson { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
132358bdf89SDaniel Thompson };
133358bdf89SDaniel Thompson
134a064a07fSGabriel Fernandez static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
135a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
136a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
137a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
138a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
139a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
140a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
141a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
142a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
143a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
144a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
145a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
146a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
147a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
148a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
149a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
150a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
151a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
152a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
153a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
154a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
155a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
156a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
157a064a07fSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
158a064a07fSGabriel Fernandez
159a064a07fSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
160a064a07fSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
161a064a07fSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
162a064a07fSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
163a064a07fSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
164a064a07fSGabriel Fernandez
165a064a07fSGabriel Fernandez { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
166a064a07fSGabriel Fernandez CLK_IGNORE_UNUSED },
167a064a07fSGabriel Fernandez { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
168a064a07fSGabriel Fernandez CLK_IGNORE_UNUSED },
169a064a07fSGabriel Fernandez
170a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
171a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
172a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
173a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
174a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
175a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
176a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
177a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
178a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
179a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
180a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
181a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
182a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
183a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
184a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
185a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
186a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
187a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
188a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
189a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
190a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
191a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
192a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
193a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
194a064a07fSGabriel Fernandez { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
195a064a07fSGabriel Fernandez
196a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
197a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
198a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
199a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
200a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
201a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
202a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
203844ca23fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 11, "sdio", "sdmux" },
204a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
205a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
206a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
207a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
208a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
209a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
210a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
211a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
212a064a07fSGabriel Fernandez { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
213a064a07fSGabriel Fernandez };
214a064a07fSGabriel Fernandez
21588c9b70bSGabriel Fernandez static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
21688c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
21788c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
21888c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
21988c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
22088c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
22188c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
22288c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
22388c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
22488c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
22588c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
22688c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
22788c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
22888c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
22988c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 20, "dtcmram", "ahb_div" },
23088c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
23188c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
23288c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
23388c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
23488c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
23588c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
23688c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
23788c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
23888c9b70bSGabriel Fernandez { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
23988c9b70bSGabriel Fernandez
24088c9b70bSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
24188c9b70bSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
24288c9b70bSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
24388c9b70bSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
24488c9b70bSGabriel Fernandez { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
24588c9b70bSGabriel Fernandez
24688c9b70bSGabriel Fernandez { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
24788c9b70bSGabriel Fernandez CLK_IGNORE_UNUSED },
24888c9b70bSGabriel Fernandez { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
24988c9b70bSGabriel Fernandez CLK_IGNORE_UNUSED },
25088c9b70bSGabriel Fernandez
25188c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
25288c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
25388c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
25488c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
25588c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
25688c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
25788c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
25888c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
25988c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
26088c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
26188c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
26288c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
26388c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 16, "spdifrx", "apb1_div" },
26488c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
26588c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
26688c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 27, "cec", "apb1_div" },
26788c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
26888c9b70bSGabriel Fernandez { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
26988c9b70bSGabriel Fernandez
27088c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
27188c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
272f9acf105SPatrice Chotard { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux" },
27388c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
27488c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
27588c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
27688c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 11, "sdmmc", "sdmux" },
27788c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
27888c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
27988c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
28088c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
28188c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
28288c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
28388c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
28488c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
28588c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
28688c9b70bSGabriel Fernandez { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
28788c9b70bSGabriel Fernandez };
28888c9b70bSGabriel Fernandez
289936289f0SGabriel Fernandez static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
290936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
291936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
292936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
293936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
294936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
295936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
296936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
297936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
298936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
299936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
300936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
301936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
302936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
303936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 20, "dtcmram", "ahb_div" },
304936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
305936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
306936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
307936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
308936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
309936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
310936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
311936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
312936289f0SGabriel Fernandez { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
313936289f0SGabriel Fernandez
314936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
315936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 1, "jpeg", "ahb_div" },
316936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
317936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
318936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
319936289f0SGabriel Fernandez { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
320936289f0SGabriel Fernandez
321936289f0SGabriel Fernandez { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
322936289f0SGabriel Fernandez CLK_IGNORE_UNUSED },
323936289f0SGabriel Fernandez { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
324936289f0SGabriel Fernandez CLK_IGNORE_UNUSED },
325936289f0SGabriel Fernandez
326936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
327936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
328936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
329936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
330936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
331936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
332936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
333936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
334936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
335936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 10, "rtcapb", "apb1_mul" },
336936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
337936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 13, "can3", "apb1_div" },
338936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
339936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
340936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 16, "spdifrx", "apb1_div" },
341936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
342936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
343936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 27, "cec", "apb1_div" },
344936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
345936289f0SGabriel Fernandez { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
346936289f0SGabriel Fernandez
347936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
348936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
349936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux2" },
350936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
351936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
352936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
353936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 11, "sdmmc1", "sdmux1" },
354936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
355936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
356936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
357936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
358936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
359936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
360936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
361936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
362936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
363936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
364936289f0SGabriel Fernandez { STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
365936289f0SGabriel Fernandez };
366936289f0SGabriel Fernandez
367358bdf89SDaniel Thompson /*
368358bdf89SDaniel Thompson * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
369358bdf89SDaniel Thompson * have gate bits associated with them. Its combined hweight is 71.
370358bdf89SDaniel Thompson */
371a064a07fSGabriel Fernandez #define MAX_GATE_MAP 3
372a064a07fSGabriel Fernandez
373a064a07fSGabriel Fernandez static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
374358bdf89SDaniel Thompson 0x0000000000000001ull,
375358bdf89SDaniel Thompson 0x04777f33f6fec9ffull };
376358bdf89SDaniel Thompson
377a064a07fSGabriel Fernandez static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
378a064a07fSGabriel Fernandez 0x0000000000000003ull,
379a064a07fSGabriel Fernandez 0x0c777f33f6fec9ffull };
380a064a07fSGabriel Fernandez
38188c9b70bSGabriel Fernandez static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
38288c9b70bSGabriel Fernandez 0x0000000000000003ull,
383f9acf105SPatrice Chotard 0x04f77f833e01c9ffull };
38488c9b70bSGabriel Fernandez
385936289f0SGabriel Fernandez static const u64 stm32f769_gate_map[MAX_GATE_MAP] = { 0x000000f37ef417ffull,
386936289f0SGabriel Fernandez 0x0000000000000003ull,
387936289f0SGabriel Fernandez 0x44F77F833E01EDFFull };
388936289f0SGabriel Fernandez
389a064a07fSGabriel Fernandez static const u64 *stm32f4_gate_map;
390a064a07fSGabriel Fernandez
391a064a07fSGabriel Fernandez static struct clk_hw **clks;
392a064a07fSGabriel Fernandez
393358bdf89SDaniel Thompson static DEFINE_SPINLOCK(stm32f4_clk_lock);
394358bdf89SDaniel Thompson static void __iomem *base;
395358bdf89SDaniel Thompson
396861adc44SGabriel Fernandez static struct regmap *pdrm;
397861adc44SGabriel Fernandez
39888c9b70bSGabriel Fernandez static int stm32fx_end_primary_clk;
39988c9b70bSGabriel Fernandez
400358bdf89SDaniel Thompson /*
401358bdf89SDaniel Thompson * "Multiplier" device for APBx clocks.
402358bdf89SDaniel Thompson *
403358bdf89SDaniel Thompson * The APBx dividers are power-of-two dividers and, if *not* running in 1:1
404358bdf89SDaniel Thompson * mode, they also tap out the one of the low order state bits to run the
405358bdf89SDaniel Thompson * timers. ST datasheets represent this feature as a (conditional) clock
406358bdf89SDaniel Thompson * multiplier.
407358bdf89SDaniel Thompson */
408358bdf89SDaniel Thompson struct clk_apb_mul {
409358bdf89SDaniel Thompson struct clk_hw hw;
410358bdf89SDaniel Thompson u8 bit_idx;
411358bdf89SDaniel Thompson };
412358bdf89SDaniel Thompson
413358bdf89SDaniel Thompson #define to_clk_apb_mul(_hw) container_of(_hw, struct clk_apb_mul, hw)
414358bdf89SDaniel Thompson
clk_apb_mul_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)415358bdf89SDaniel Thompson static unsigned long clk_apb_mul_recalc_rate(struct clk_hw *hw,
416358bdf89SDaniel Thompson unsigned long parent_rate)
417358bdf89SDaniel Thompson {
418358bdf89SDaniel Thompson struct clk_apb_mul *am = to_clk_apb_mul(hw);
419358bdf89SDaniel Thompson
420358bdf89SDaniel Thompson if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
421358bdf89SDaniel Thompson return parent_rate * 2;
422358bdf89SDaniel Thompson
423358bdf89SDaniel Thompson return parent_rate;
424358bdf89SDaniel Thompson }
425358bdf89SDaniel Thompson
clk_apb_mul_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)426358bdf89SDaniel Thompson static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
427358bdf89SDaniel Thompson unsigned long *prate)
428358bdf89SDaniel Thompson {
429358bdf89SDaniel Thompson struct clk_apb_mul *am = to_clk_apb_mul(hw);
430358bdf89SDaniel Thompson unsigned long mult = 1;
431358bdf89SDaniel Thompson
432358bdf89SDaniel Thompson if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
433358bdf89SDaniel Thompson mult = 2;
434358bdf89SDaniel Thompson
43598d8a60eSStephen Boyd if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
436358bdf89SDaniel Thompson unsigned long best_parent = rate / mult;
437358bdf89SDaniel Thompson
43817ae4b40SStephen Boyd *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
439358bdf89SDaniel Thompson }
440358bdf89SDaniel Thompson
441358bdf89SDaniel Thompson return *prate * mult;
442358bdf89SDaniel Thompson }
443358bdf89SDaniel Thompson
clk_apb_mul_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)444358bdf89SDaniel Thompson static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
445358bdf89SDaniel Thompson unsigned long parent_rate)
446358bdf89SDaniel Thompson {
447358bdf89SDaniel Thompson /*
448358bdf89SDaniel Thompson * We must report success but we can do so unconditionally because
449358bdf89SDaniel Thompson * clk_apb_mul_round_rate returns values that ensure this call is a
450358bdf89SDaniel Thompson * nop.
451358bdf89SDaniel Thompson */
452358bdf89SDaniel Thompson
453358bdf89SDaniel Thompson return 0;
454358bdf89SDaniel Thompson }
455358bdf89SDaniel Thompson
456358bdf89SDaniel Thompson static const struct clk_ops clk_apb_mul_factor_ops = {
457358bdf89SDaniel Thompson .round_rate = clk_apb_mul_round_rate,
458358bdf89SDaniel Thompson .set_rate = clk_apb_mul_set_rate,
459358bdf89SDaniel Thompson .recalc_rate = clk_apb_mul_recalc_rate,
460358bdf89SDaniel Thompson };
461358bdf89SDaniel Thompson
clk_register_apb_mul(struct device * dev,const char * name,const char * parent_name,unsigned long flags,u8 bit_idx)462358bdf89SDaniel Thompson static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
463358bdf89SDaniel Thompson const char *parent_name,
464358bdf89SDaniel Thompson unsigned long flags, u8 bit_idx)
465358bdf89SDaniel Thompson {
466358bdf89SDaniel Thompson struct clk_apb_mul *am;
467358bdf89SDaniel Thompson struct clk_init_data init;
468358bdf89SDaniel Thompson struct clk *clk;
469358bdf89SDaniel Thompson
470358bdf89SDaniel Thompson am = kzalloc(sizeof(*am), GFP_KERNEL);
471358bdf89SDaniel Thompson if (!am)
472358bdf89SDaniel Thompson return ERR_PTR(-ENOMEM);
473358bdf89SDaniel Thompson
474358bdf89SDaniel Thompson am->bit_idx = bit_idx;
475358bdf89SDaniel Thompson am->hw.init = &init;
476358bdf89SDaniel Thompson
477358bdf89SDaniel Thompson init.name = name;
478358bdf89SDaniel Thompson init.ops = &clk_apb_mul_factor_ops;
479358bdf89SDaniel Thompson init.flags = flags;
480358bdf89SDaniel Thompson init.parent_names = &parent_name;
481358bdf89SDaniel Thompson init.num_parents = 1;
482358bdf89SDaniel Thompson
483358bdf89SDaniel Thompson clk = clk_register(dev, &am->hw);
484358bdf89SDaniel Thompson
485358bdf89SDaniel Thompson if (IS_ERR(clk))
486358bdf89SDaniel Thompson kfree(am);
487358bdf89SDaniel Thompson
488358bdf89SDaniel Thompson return clk;
489358bdf89SDaniel Thompson }
490358bdf89SDaniel Thompson
49183135ad3SGabriel Fernandez enum {
49283135ad3SGabriel Fernandez PLL,
49383135ad3SGabriel Fernandez PLL_I2S,
49483135ad3SGabriel Fernandez PLL_SAI,
49583135ad3SGabriel Fernandez };
49683135ad3SGabriel Fernandez
49783135ad3SGabriel Fernandez static const struct clk_div_table pll_divp_table[] = {
49883135ad3SGabriel Fernandez { 0, 2 }, { 1, 4 }, { 2, 6 }, { 3, 8 }, { 0 }
49983135ad3SGabriel Fernandez };
50083135ad3SGabriel Fernandez
501ef189104SGabriel Fernandez static const struct clk_div_table pll_divq_table[] = {
502ef189104SGabriel Fernandez { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 },
503ef189104SGabriel Fernandez { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, { 12, 12 }, { 13, 13 },
504ef189104SGabriel Fernandez { 14, 14 }, { 15, 15 },
505ef189104SGabriel Fernandez { 0 }
506ef189104SGabriel Fernandez };
507ef189104SGabriel Fernandez
50883135ad3SGabriel Fernandez static const struct clk_div_table pll_divr_table[] = {
50983135ad3SGabriel Fernandez { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 0 }
51083135ad3SGabriel Fernandez };
51183135ad3SGabriel Fernandez
51283135ad3SGabriel Fernandez struct stm32f4_pll {
51383135ad3SGabriel Fernandez spinlock_t *lock;
51483135ad3SGabriel Fernandez struct clk_gate gate;
51583135ad3SGabriel Fernandez u8 offset;
51683135ad3SGabriel Fernandez u8 bit_rdy_idx;
51783135ad3SGabriel Fernandez u8 status;
51883135ad3SGabriel Fernandez u8 n_start;
51983135ad3SGabriel Fernandez };
52083135ad3SGabriel Fernandez
52183135ad3SGabriel Fernandez #define to_stm32f4_pll(_gate) container_of(_gate, struct stm32f4_pll, gate)
52283135ad3SGabriel Fernandez
523517633efSGabriel Fernandez struct stm32f4_pll_post_div_data {
524517633efSGabriel Fernandez int idx;
52524b5b197SDario Binacchi int pll_idx;
526517633efSGabriel Fernandez const char *name;
527517633efSGabriel Fernandez const char *parent;
528517633efSGabriel Fernandez u8 flag;
529517633efSGabriel Fernandez u8 offset;
530517633efSGabriel Fernandez u8 shift;
531517633efSGabriel Fernandez u8 width;
532517633efSGabriel Fernandez u8 flag_div;
533517633efSGabriel Fernandez const struct clk_div_table *div_table;
534517633efSGabriel Fernandez };
535517633efSGabriel Fernandez
53683135ad3SGabriel Fernandez struct stm32f4_vco_data {
53783135ad3SGabriel Fernandez const char *vco_name;
53883135ad3SGabriel Fernandez u8 offset;
53983135ad3SGabriel Fernandez u8 bit_idx;
54083135ad3SGabriel Fernandez u8 bit_rdy_idx;
54183135ad3SGabriel Fernandez };
54283135ad3SGabriel Fernandez
54383135ad3SGabriel Fernandez static const struct stm32f4_vco_data vco_data[] = {
54483135ad3SGabriel Fernandez { "vco", STM32F4_RCC_PLLCFGR, 24, 25 },
54583135ad3SGabriel Fernandez { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
54683135ad3SGabriel Fernandez { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
54783135ad3SGabriel Fernandez };
54883135ad3SGabriel Fernandez
549517633efSGabriel Fernandez
550517633efSGabriel Fernandez static const struct clk_div_table post_divr_table[] = {
551517633efSGabriel Fernandez { 0, 2 }, { 1, 4 }, { 2, 8 }, { 3, 16 }, { 0 }
552517633efSGabriel Fernandez };
553517633efSGabriel Fernandez
554517633efSGabriel Fernandez #define MAX_POST_DIV 3
555517633efSGabriel Fernandez static const struct stm32f4_pll_post_div_data post_div_data[MAX_POST_DIV] = {
55624b5b197SDario Binacchi { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
557517633efSGabriel Fernandez CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
558517633efSGabriel Fernandez
55924b5b197SDario Binacchi { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
560517633efSGabriel Fernandez CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
561517633efSGabriel Fernandez
56224b5b197SDario Binacchi { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
563517633efSGabriel Fernandez STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
564517633efSGabriel Fernandez };
565517633efSGabriel Fernandez
56683135ad3SGabriel Fernandez struct stm32f4_div_data {
56783135ad3SGabriel Fernandez u8 shift;
56883135ad3SGabriel Fernandez u8 width;
56983135ad3SGabriel Fernandez u8 flag_div;
57083135ad3SGabriel Fernandez const struct clk_div_table *div_table;
57183135ad3SGabriel Fernandez };
57283135ad3SGabriel Fernandez
57383135ad3SGabriel Fernandez #define MAX_PLL_DIV 3
57483135ad3SGabriel Fernandez static const struct stm32f4_div_data div_data[MAX_PLL_DIV] = {
57583135ad3SGabriel Fernandez { 16, 2, 0, pll_divp_table },
576ef189104SGabriel Fernandez { 24, 4, 0, pll_divq_table },
57783135ad3SGabriel Fernandez { 28, 3, 0, pll_divr_table },
57883135ad3SGabriel Fernandez };
57983135ad3SGabriel Fernandez
58083135ad3SGabriel Fernandez struct stm32f4_pll_data {
58183135ad3SGabriel Fernandez u8 pll_num;
58283135ad3SGabriel Fernandez u8 n_start;
58383135ad3SGabriel Fernandez const char *div_name[MAX_PLL_DIV];
58483135ad3SGabriel Fernandez };
58583135ad3SGabriel Fernandez
58683135ad3SGabriel Fernandez static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
58783135ad3SGabriel Fernandez { PLL, 192, { "pll", "pll48", NULL } },
58883135ad3SGabriel Fernandez { PLL_I2S, 192, { NULL, "plli2s-q", "plli2s-r" } },
58983135ad3SGabriel Fernandez { PLL_SAI, 49, { NULL, "pllsai-q", "pllsai-r" } },
59083135ad3SGabriel Fernandez };
59183135ad3SGabriel Fernandez
59283135ad3SGabriel Fernandez static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
5932f05b6b9SGabriel Fernandez { PLL, 50, { "pll", "pll-q", "pll-r" } },
59483135ad3SGabriel Fernandez { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
59583135ad3SGabriel Fernandez { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
59683135ad3SGabriel Fernandez };
59783135ad3SGabriel Fernandez
stm32f4_pll_is_enabled(struct clk_hw * hw)59883135ad3SGabriel Fernandez static int stm32f4_pll_is_enabled(struct clk_hw *hw)
599358bdf89SDaniel Thompson {
60083135ad3SGabriel Fernandez return clk_gate_ops.is_enabled(hw);
60183135ad3SGabriel Fernandez }
602358bdf89SDaniel Thompson
603ac03d8b3SGabriel Fernandez #define PLL_TIMEOUT 10000
604ac03d8b3SGabriel Fernandez
stm32f4_pll_enable(struct clk_hw * hw)60583135ad3SGabriel Fernandez static int stm32f4_pll_enable(struct clk_hw *hw)
60683135ad3SGabriel Fernandez {
60783135ad3SGabriel Fernandez struct clk_gate *gate = to_clk_gate(hw);
60883135ad3SGabriel Fernandez struct stm32f4_pll *pll = to_stm32f4_pll(gate);
609ac03d8b3SGabriel Fernandez int bit_status;
610ac03d8b3SGabriel Fernandez unsigned int timeout = PLL_TIMEOUT;
611358bdf89SDaniel Thompson
612ac03d8b3SGabriel Fernandez if (clk_gate_ops.is_enabled(hw))
613ac03d8b3SGabriel Fernandez return 0;
61483135ad3SGabriel Fernandez
615ac03d8b3SGabriel Fernandez clk_gate_ops.enable(hw);
61683135ad3SGabriel Fernandez
617ac03d8b3SGabriel Fernandez do {
618ac03d8b3SGabriel Fernandez bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx));
619ac03d8b3SGabriel Fernandez
620ac03d8b3SGabriel Fernandez } while (bit_status && --timeout);
621ac03d8b3SGabriel Fernandez
622ac03d8b3SGabriel Fernandez return bit_status;
62383135ad3SGabriel Fernandez }
62483135ad3SGabriel Fernandez
stm32f4_pll_disable(struct clk_hw * hw)62583135ad3SGabriel Fernandez static void stm32f4_pll_disable(struct clk_hw *hw)
62683135ad3SGabriel Fernandez {
62783135ad3SGabriel Fernandez clk_gate_ops.disable(hw);
62883135ad3SGabriel Fernandez }
62983135ad3SGabriel Fernandez
stm32f4_pll_recalc(struct clk_hw * hw,unsigned long parent_rate)63083135ad3SGabriel Fernandez static unsigned long stm32f4_pll_recalc(struct clk_hw *hw,
63183135ad3SGabriel Fernandez unsigned long parent_rate)
63283135ad3SGabriel Fernandez {
63383135ad3SGabriel Fernandez struct clk_gate *gate = to_clk_gate(hw);
63483135ad3SGabriel Fernandez struct stm32f4_pll *pll = to_stm32f4_pll(gate);
63583135ad3SGabriel Fernandez unsigned long n;
63683135ad3SGabriel Fernandez
63783135ad3SGabriel Fernandez n = (readl(base + pll->offset) >> 6) & 0x1ff;
63883135ad3SGabriel Fernandez
63983135ad3SGabriel Fernandez return parent_rate * n;
64083135ad3SGabriel Fernandez }
64183135ad3SGabriel Fernandez
stm32f4_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)64283135ad3SGabriel Fernandez static long stm32f4_pll_round_rate(struct clk_hw *hw, unsigned long rate,
64383135ad3SGabriel Fernandez unsigned long *prate)
64483135ad3SGabriel Fernandez {
64583135ad3SGabriel Fernandez struct clk_gate *gate = to_clk_gate(hw);
64683135ad3SGabriel Fernandez struct stm32f4_pll *pll = to_stm32f4_pll(gate);
64783135ad3SGabriel Fernandez unsigned long n;
64883135ad3SGabriel Fernandez
64983135ad3SGabriel Fernandez n = rate / *prate;
65083135ad3SGabriel Fernandez
65183135ad3SGabriel Fernandez if (n < pll->n_start)
65283135ad3SGabriel Fernandez n = pll->n_start;
65383135ad3SGabriel Fernandez else if (n > 432)
65483135ad3SGabriel Fernandez n = 432;
65583135ad3SGabriel Fernandez
65683135ad3SGabriel Fernandez return *prate * n;
65783135ad3SGabriel Fernandez }
65883135ad3SGabriel Fernandez
stm32f4_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)65983135ad3SGabriel Fernandez static int stm32f4_pll_set_rate(struct clk_hw *hw, unsigned long rate,
66083135ad3SGabriel Fernandez unsigned long parent_rate)
66183135ad3SGabriel Fernandez {
66283135ad3SGabriel Fernandez struct clk_gate *gate = to_clk_gate(hw);
66383135ad3SGabriel Fernandez struct stm32f4_pll *pll = to_stm32f4_pll(gate);
66483135ad3SGabriel Fernandez
66583135ad3SGabriel Fernandez unsigned long n;
66683135ad3SGabriel Fernandez unsigned long val;
66783135ad3SGabriel Fernandez int pll_state;
66883135ad3SGabriel Fernandez
66983135ad3SGabriel Fernandez pll_state = stm32f4_pll_is_enabled(hw);
67083135ad3SGabriel Fernandez
67183135ad3SGabriel Fernandez if (pll_state)
67283135ad3SGabriel Fernandez stm32f4_pll_disable(hw);
67383135ad3SGabriel Fernandez
67483135ad3SGabriel Fernandez n = rate / parent_rate;
67583135ad3SGabriel Fernandez
67683135ad3SGabriel Fernandez val = readl(base + pll->offset) & ~(0x1ff << 6);
67783135ad3SGabriel Fernandez
67883135ad3SGabriel Fernandez writel(val | ((n & 0x1ff) << 6), base + pll->offset);
67983135ad3SGabriel Fernandez
68083135ad3SGabriel Fernandez if (pll_state)
68183135ad3SGabriel Fernandez stm32f4_pll_enable(hw);
68283135ad3SGabriel Fernandez
68383135ad3SGabriel Fernandez return 0;
68483135ad3SGabriel Fernandez }
68583135ad3SGabriel Fernandez
68683135ad3SGabriel Fernandez static const struct clk_ops stm32f4_pll_gate_ops = {
68783135ad3SGabriel Fernandez .enable = stm32f4_pll_enable,
68883135ad3SGabriel Fernandez .disable = stm32f4_pll_disable,
68983135ad3SGabriel Fernandez .is_enabled = stm32f4_pll_is_enabled,
69083135ad3SGabriel Fernandez .recalc_rate = stm32f4_pll_recalc,
69183135ad3SGabriel Fernandez .round_rate = stm32f4_pll_round_rate,
69283135ad3SGabriel Fernandez .set_rate = stm32f4_pll_set_rate,
69383135ad3SGabriel Fernandez };
69483135ad3SGabriel Fernandez
69583135ad3SGabriel Fernandez struct stm32f4_pll_div {
69683135ad3SGabriel Fernandez struct clk_divider div;
69783135ad3SGabriel Fernandez struct clk_hw *hw_pll;
69883135ad3SGabriel Fernandez };
69983135ad3SGabriel Fernandez
70083135ad3SGabriel Fernandez #define to_pll_div_clk(_div) container_of(_div, struct stm32f4_pll_div, div)
70183135ad3SGabriel Fernandez
stm32f4_pll_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)70283135ad3SGabriel Fernandez static unsigned long stm32f4_pll_div_recalc_rate(struct clk_hw *hw,
70383135ad3SGabriel Fernandez unsigned long parent_rate)
70483135ad3SGabriel Fernandez {
70583135ad3SGabriel Fernandez return clk_divider_ops.recalc_rate(hw, parent_rate);
70683135ad3SGabriel Fernandez }
70783135ad3SGabriel Fernandez
stm32f4_pll_div_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)708*d1e40bc9SMartin Blumenstingl static int stm32f4_pll_div_determine_rate(struct clk_hw *hw,
709*d1e40bc9SMartin Blumenstingl struct clk_rate_request *req)
71083135ad3SGabriel Fernandez {
711*d1e40bc9SMartin Blumenstingl return clk_divider_ops.determine_rate(hw, req);
71283135ad3SGabriel Fernandez }
71383135ad3SGabriel Fernandez
stm32f4_pll_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)71483135ad3SGabriel Fernandez static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
71583135ad3SGabriel Fernandez unsigned long parent_rate)
71683135ad3SGabriel Fernandez {
71783135ad3SGabriel Fernandez int pll_state, ret;
71883135ad3SGabriel Fernandez
71983135ad3SGabriel Fernandez struct clk_divider *div = to_clk_divider(hw);
72083135ad3SGabriel Fernandez struct stm32f4_pll_div *pll_div = to_pll_div_clk(div);
72183135ad3SGabriel Fernandez
72283135ad3SGabriel Fernandez pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll);
72383135ad3SGabriel Fernandez
72483135ad3SGabriel Fernandez if (pll_state)
72583135ad3SGabriel Fernandez stm32f4_pll_disable(pll_div->hw_pll);
72683135ad3SGabriel Fernandez
72783135ad3SGabriel Fernandez ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
72883135ad3SGabriel Fernandez
72983135ad3SGabriel Fernandez if (pll_state)
73083135ad3SGabriel Fernandez stm32f4_pll_enable(pll_div->hw_pll);
73183135ad3SGabriel Fernandez
73283135ad3SGabriel Fernandez return ret;
73383135ad3SGabriel Fernandez }
73483135ad3SGabriel Fernandez
73583135ad3SGabriel Fernandez static const struct clk_ops stm32f4_pll_div_ops = {
73683135ad3SGabriel Fernandez .recalc_rate = stm32f4_pll_div_recalc_rate,
737*d1e40bc9SMartin Blumenstingl .determine_rate = stm32f4_pll_div_determine_rate,
73883135ad3SGabriel Fernandez .set_rate = stm32f4_pll_div_set_rate,
73983135ad3SGabriel Fernandez };
74083135ad3SGabriel Fernandez
clk_register_pll_div(const char * name,const char * parent_name,unsigned long flags,void __iomem * reg,u8 shift,u8 width,u8 clk_divider_flags,const struct clk_div_table * table,struct clk_hw * pll_hw,spinlock_t * lock)74183135ad3SGabriel Fernandez static struct clk_hw *clk_register_pll_div(const char *name,
74283135ad3SGabriel Fernandez const char *parent_name, unsigned long flags,
74383135ad3SGabriel Fernandez void __iomem *reg, u8 shift, u8 width,
74483135ad3SGabriel Fernandez u8 clk_divider_flags, const struct clk_div_table *table,
74583135ad3SGabriel Fernandez struct clk_hw *pll_hw, spinlock_t *lock)
74683135ad3SGabriel Fernandez {
74783135ad3SGabriel Fernandez struct stm32f4_pll_div *pll_div;
74883135ad3SGabriel Fernandez struct clk_hw *hw;
74983135ad3SGabriel Fernandez struct clk_init_data init;
75083135ad3SGabriel Fernandez int ret;
75183135ad3SGabriel Fernandez
75283135ad3SGabriel Fernandez /* allocate the divider */
75383135ad3SGabriel Fernandez pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
75483135ad3SGabriel Fernandez if (!pll_div)
75583135ad3SGabriel Fernandez return ERR_PTR(-ENOMEM);
75683135ad3SGabriel Fernandez
75783135ad3SGabriel Fernandez init.name = name;
75883135ad3SGabriel Fernandez init.ops = &stm32f4_pll_div_ops;
75983135ad3SGabriel Fernandez init.flags = flags;
76083135ad3SGabriel Fernandez init.parent_names = (parent_name ? &parent_name : NULL);
76183135ad3SGabriel Fernandez init.num_parents = (parent_name ? 1 : 0);
76283135ad3SGabriel Fernandez
76383135ad3SGabriel Fernandez /* struct clk_divider assignments */
76483135ad3SGabriel Fernandez pll_div->div.reg = reg;
76583135ad3SGabriel Fernandez pll_div->div.shift = shift;
76683135ad3SGabriel Fernandez pll_div->div.width = width;
76783135ad3SGabriel Fernandez pll_div->div.flags = clk_divider_flags;
76883135ad3SGabriel Fernandez pll_div->div.lock = lock;
76983135ad3SGabriel Fernandez pll_div->div.table = table;
77083135ad3SGabriel Fernandez pll_div->div.hw.init = &init;
77183135ad3SGabriel Fernandez
77283135ad3SGabriel Fernandez pll_div->hw_pll = pll_hw;
77383135ad3SGabriel Fernandez
77483135ad3SGabriel Fernandez /* register the clock */
77583135ad3SGabriel Fernandez hw = &pll_div->div.hw;
77683135ad3SGabriel Fernandez ret = clk_hw_register(NULL, hw);
77783135ad3SGabriel Fernandez if (ret) {
77883135ad3SGabriel Fernandez kfree(pll_div);
77983135ad3SGabriel Fernandez hw = ERR_PTR(ret);
78083135ad3SGabriel Fernandez }
78183135ad3SGabriel Fernandez
78283135ad3SGabriel Fernandez return hw;
78383135ad3SGabriel Fernandez }
78483135ad3SGabriel Fernandez
stm32f4_rcc_register_pll(const char * pllsrc,const struct stm32f4_pll_data * data,spinlock_t * lock)78583135ad3SGabriel Fernandez static struct clk_hw *stm32f4_rcc_register_pll(const char *pllsrc,
78683135ad3SGabriel Fernandez const struct stm32f4_pll_data *data, spinlock_t *lock)
78783135ad3SGabriel Fernandez {
78883135ad3SGabriel Fernandez struct stm32f4_pll *pll;
78983135ad3SGabriel Fernandez struct clk_init_data init = { NULL };
79083135ad3SGabriel Fernandez void __iomem *reg;
79183135ad3SGabriel Fernandez struct clk_hw *pll_hw;
79283135ad3SGabriel Fernandez int ret;
79383135ad3SGabriel Fernandez int i;
79483135ad3SGabriel Fernandez const struct stm32f4_vco_data *vco;
79583135ad3SGabriel Fernandez
79683135ad3SGabriel Fernandez
79783135ad3SGabriel Fernandez pll = kzalloc(sizeof(*pll), GFP_KERNEL);
79883135ad3SGabriel Fernandez if (!pll)
79983135ad3SGabriel Fernandez return ERR_PTR(-ENOMEM);
80083135ad3SGabriel Fernandez
80183135ad3SGabriel Fernandez vco = &vco_data[data->pll_num];
80283135ad3SGabriel Fernandez
80383135ad3SGabriel Fernandez init.name = vco->vco_name;
80483135ad3SGabriel Fernandez init.ops = &stm32f4_pll_gate_ops;
80583135ad3SGabriel Fernandez init.flags = CLK_SET_RATE_GATE;
80683135ad3SGabriel Fernandez init.parent_names = &pllsrc;
80783135ad3SGabriel Fernandez init.num_parents = 1;
80883135ad3SGabriel Fernandez
80983135ad3SGabriel Fernandez pll->gate.lock = lock;
81083135ad3SGabriel Fernandez pll->gate.reg = base + STM32F4_RCC_CR;
81183135ad3SGabriel Fernandez pll->gate.bit_idx = vco->bit_idx;
81283135ad3SGabriel Fernandez pll->gate.hw.init = &init;
81383135ad3SGabriel Fernandez
81483135ad3SGabriel Fernandez pll->offset = vco->offset;
81583135ad3SGabriel Fernandez pll->n_start = data->n_start;
81683135ad3SGabriel Fernandez pll->bit_rdy_idx = vco->bit_rdy_idx;
81783135ad3SGabriel Fernandez pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1;
81883135ad3SGabriel Fernandez
81983135ad3SGabriel Fernandez reg = base + pll->offset;
82083135ad3SGabriel Fernandez
82183135ad3SGabriel Fernandez pll_hw = &pll->gate.hw;
82283135ad3SGabriel Fernandez ret = clk_hw_register(NULL, pll_hw);
82383135ad3SGabriel Fernandez if (ret) {
82483135ad3SGabriel Fernandez kfree(pll);
82583135ad3SGabriel Fernandez return ERR_PTR(ret);
82683135ad3SGabriel Fernandez }
82783135ad3SGabriel Fernandez
82883135ad3SGabriel Fernandez for (i = 0; i < MAX_PLL_DIV; i++)
82983135ad3SGabriel Fernandez if (data->div_name[i])
83083135ad3SGabriel Fernandez clk_register_pll_div(data->div_name[i],
83183135ad3SGabriel Fernandez vco->vco_name,
83283135ad3SGabriel Fernandez 0,
83383135ad3SGabriel Fernandez reg,
83483135ad3SGabriel Fernandez div_data[i].shift,
83583135ad3SGabriel Fernandez div_data[i].width,
83683135ad3SGabriel Fernandez div_data[i].flag_div,
83783135ad3SGabriel Fernandez div_data[i].div_table,
83883135ad3SGabriel Fernandez pll_hw,
83983135ad3SGabriel Fernandez lock);
84083135ad3SGabriel Fernandez return pll_hw;
841358bdf89SDaniel Thompson }
842358bdf89SDaniel Thompson
843358bdf89SDaniel Thompson /*
844358bdf89SDaniel Thompson * Converts the primary and secondary indices (as they appear in DT) to an
845358bdf89SDaniel Thompson * offset into our struct clock array.
846358bdf89SDaniel Thompson */
stm32f4_rcc_lookup_clk_idx(u8 primary,u8 secondary)847358bdf89SDaniel Thompson static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
848358bdf89SDaniel Thompson {
849a064a07fSGabriel Fernandez u64 table[MAX_GATE_MAP];
850358bdf89SDaniel Thompson
851358bdf89SDaniel Thompson if (primary == 1) {
85288c9b70bSGabriel Fernandez if (WARN_ON(secondary >= stm32fx_end_primary_clk))
853358bdf89SDaniel Thompson return -EINVAL;
854358bdf89SDaniel Thompson return secondary;
855358bdf89SDaniel Thompson }
856358bdf89SDaniel Thompson
857a064a07fSGabriel Fernandez memcpy(table, stm32f4_gate_map, sizeof(table));
858358bdf89SDaniel Thompson
859358bdf89SDaniel Thompson /* only bits set in table can be used as indices */
86015ab3827SDaniel Thompson if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
861358bdf89SDaniel Thompson 0 == (table[BIT_ULL_WORD(secondary)] &
862358bdf89SDaniel Thompson BIT_ULL_MASK(secondary))))
863358bdf89SDaniel Thompson return -EINVAL;
864358bdf89SDaniel Thompson
865358bdf89SDaniel Thompson /* mask out bits above our current index */
866358bdf89SDaniel Thompson table[BIT_ULL_WORD(secondary)] &=
867358bdf89SDaniel Thompson GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
868358bdf89SDaniel Thompson
86988c9b70bSGabriel Fernandez return stm32fx_end_primary_clk - 1 + hweight64(table[0]) +
870358bdf89SDaniel Thompson (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
871358bdf89SDaniel Thompson (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
872358bdf89SDaniel Thompson }
873358bdf89SDaniel Thompson
8744e950d1eSStephen Boyd static struct clk_hw *
stm32f4_rcc_lookup_clk(struct of_phandle_args * clkspec,void * data)875358bdf89SDaniel Thompson stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
876358bdf89SDaniel Thompson {
877358bdf89SDaniel Thompson int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
878358bdf89SDaniel Thompson
879358bdf89SDaniel Thompson if (i < 0)
880358bdf89SDaniel Thompson return ERR_PTR(-EINVAL);
881358bdf89SDaniel Thompson
882358bdf89SDaniel Thompson return clks[i];
883358bdf89SDaniel Thompson }
884358bdf89SDaniel Thompson
885861adc44SGabriel Fernandez #define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate)
886861adc44SGabriel Fernandez
disable_power_domain_write_protection(void)887861adc44SGabriel Fernandez static inline void disable_power_domain_write_protection(void)
888861adc44SGabriel Fernandez {
889861adc44SGabriel Fernandez if (pdrm)
890861adc44SGabriel Fernandez regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
891861adc44SGabriel Fernandez }
892861adc44SGabriel Fernandez
enable_power_domain_write_protection(void)893861adc44SGabriel Fernandez static inline void enable_power_domain_write_protection(void)
894861adc44SGabriel Fernandez {
895861adc44SGabriel Fernandez if (pdrm)
896861adc44SGabriel Fernandez regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
897861adc44SGabriel Fernandez }
898861adc44SGabriel Fernandez
sofware_reset_backup_domain(void)8994261a881SGabriel Fernandez static inline void sofware_reset_backup_domain(void)
9004261a881SGabriel Fernandez {
9014261a881SGabriel Fernandez unsigned long val;
9024261a881SGabriel Fernandez
9034261a881SGabriel Fernandez val = readl(base + STM32F4_RCC_BDCR);
9044261a881SGabriel Fernandez writel(val | BIT(16), base + STM32F4_RCC_BDCR);
9054261a881SGabriel Fernandez writel(val & ~BIT(16), base + STM32F4_RCC_BDCR);
9064261a881SGabriel Fernandez }
9074261a881SGabriel Fernandez
908861adc44SGabriel Fernandez struct stm32_rgate {
909861adc44SGabriel Fernandez struct clk_gate gate;
910861adc44SGabriel Fernandez u8 bit_rdy_idx;
911861adc44SGabriel Fernandez };
912861adc44SGabriel Fernandez
913ac03d8b3SGabriel Fernandez #define RGATE_TIMEOUT 50000
914861adc44SGabriel Fernandez
rgclk_enable(struct clk_hw * hw)915861adc44SGabriel Fernandez static int rgclk_enable(struct clk_hw *hw)
916861adc44SGabriel Fernandez {
917861adc44SGabriel Fernandez struct clk_gate *gate = to_clk_gate(hw);
918861adc44SGabriel Fernandez struct stm32_rgate *rgate = to_rgclk(gate);
919ac03d8b3SGabriel Fernandez int bit_status;
920ac03d8b3SGabriel Fernandez unsigned int timeout = RGATE_TIMEOUT;
921ac03d8b3SGabriel Fernandez
922ac03d8b3SGabriel Fernandez if (clk_gate_ops.is_enabled(hw))
923ac03d8b3SGabriel Fernandez return 0;
924861adc44SGabriel Fernandez
925861adc44SGabriel Fernandez disable_power_domain_write_protection();
926861adc44SGabriel Fernandez
927861adc44SGabriel Fernandez clk_gate_ops.enable(hw);
928861adc44SGabriel Fernandez
929ac03d8b3SGabriel Fernandez do {
930ac03d8b3SGabriel Fernandez bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx));
931ac03d8b3SGabriel Fernandez if (bit_status)
932ac03d8b3SGabriel Fernandez udelay(100);
933ac03d8b3SGabriel Fernandez
934ac03d8b3SGabriel Fernandez } while (bit_status && --timeout);
935861adc44SGabriel Fernandez
936861adc44SGabriel Fernandez enable_power_domain_write_protection();
937ac03d8b3SGabriel Fernandez
938ac03d8b3SGabriel Fernandez return bit_status;
939861adc44SGabriel Fernandez }
940861adc44SGabriel Fernandez
rgclk_disable(struct clk_hw * hw)941861adc44SGabriel Fernandez static void rgclk_disable(struct clk_hw *hw)
942861adc44SGabriel Fernandez {
943861adc44SGabriel Fernandez clk_gate_ops.disable(hw);
944861adc44SGabriel Fernandez }
945861adc44SGabriel Fernandez
rgclk_is_enabled(struct clk_hw * hw)946861adc44SGabriel Fernandez static int rgclk_is_enabled(struct clk_hw *hw)
947861adc44SGabriel Fernandez {
948861adc44SGabriel Fernandez return clk_gate_ops.is_enabled(hw);
949861adc44SGabriel Fernandez }
950861adc44SGabriel Fernandez
951861adc44SGabriel Fernandez static const struct clk_ops rgclk_ops = {
952861adc44SGabriel Fernandez .enable = rgclk_enable,
953861adc44SGabriel Fernandez .disable = rgclk_disable,
954861adc44SGabriel Fernandez .is_enabled = rgclk_is_enabled,
955861adc44SGabriel Fernandez };
956861adc44SGabriel Fernandez
clk_register_rgate(struct device * dev,const char * name,const char * parent_name,unsigned long flags,void __iomem * reg,u8 bit_idx,u8 bit_rdy_idx,u8 clk_gate_flags,spinlock_t * lock)957861adc44SGabriel Fernandez static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
958861adc44SGabriel Fernandez const char *parent_name, unsigned long flags,
959861adc44SGabriel Fernandez void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx,
960861adc44SGabriel Fernandez u8 clk_gate_flags, spinlock_t *lock)
961861adc44SGabriel Fernandez {
962861adc44SGabriel Fernandez struct stm32_rgate *rgate;
963861adc44SGabriel Fernandez struct clk_init_data init = { NULL };
964861adc44SGabriel Fernandez struct clk_hw *hw;
965861adc44SGabriel Fernandez int ret;
966861adc44SGabriel Fernandez
967861adc44SGabriel Fernandez rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
968861adc44SGabriel Fernandez if (!rgate)
969861adc44SGabriel Fernandez return ERR_PTR(-ENOMEM);
970861adc44SGabriel Fernandez
971861adc44SGabriel Fernandez init.name = name;
972861adc44SGabriel Fernandez init.ops = &rgclk_ops;
973861adc44SGabriel Fernandez init.flags = flags;
974861adc44SGabriel Fernandez init.parent_names = &parent_name;
975861adc44SGabriel Fernandez init.num_parents = 1;
976861adc44SGabriel Fernandez
977861adc44SGabriel Fernandez rgate->bit_rdy_idx = bit_rdy_idx;
978861adc44SGabriel Fernandez
979861adc44SGabriel Fernandez rgate->gate.lock = lock;
980861adc44SGabriel Fernandez rgate->gate.reg = reg;
981861adc44SGabriel Fernandez rgate->gate.bit_idx = bit_idx;
982861adc44SGabriel Fernandez rgate->gate.hw.init = &init;
983861adc44SGabriel Fernandez
984861adc44SGabriel Fernandez hw = &rgate->gate.hw;
985861adc44SGabriel Fernandez ret = clk_hw_register(dev, hw);
986861adc44SGabriel Fernandez if (ret) {
987861adc44SGabriel Fernandez kfree(rgate);
988861adc44SGabriel Fernandez hw = ERR_PTR(ret);
989861adc44SGabriel Fernandez }
990861adc44SGabriel Fernandez
991861adc44SGabriel Fernandez return hw;
992861adc44SGabriel Fernandez }
993861adc44SGabriel Fernandez
cclk_gate_enable(struct clk_hw * hw)9944261a881SGabriel Fernandez static int cclk_gate_enable(struct clk_hw *hw)
9954261a881SGabriel Fernandez {
9964261a881SGabriel Fernandez int ret;
9974261a881SGabriel Fernandez
9984261a881SGabriel Fernandez disable_power_domain_write_protection();
9994261a881SGabriel Fernandez
10004261a881SGabriel Fernandez ret = clk_gate_ops.enable(hw);
10014261a881SGabriel Fernandez
10024261a881SGabriel Fernandez enable_power_domain_write_protection();
10034261a881SGabriel Fernandez
10044261a881SGabriel Fernandez return ret;
10054261a881SGabriel Fernandez }
10064261a881SGabriel Fernandez
cclk_gate_disable(struct clk_hw * hw)10074261a881SGabriel Fernandez static void cclk_gate_disable(struct clk_hw *hw)
10084261a881SGabriel Fernandez {
10094261a881SGabriel Fernandez disable_power_domain_write_protection();
10104261a881SGabriel Fernandez
10114261a881SGabriel Fernandez clk_gate_ops.disable(hw);
10124261a881SGabriel Fernandez
10134261a881SGabriel Fernandez enable_power_domain_write_protection();
10144261a881SGabriel Fernandez }
10154261a881SGabriel Fernandez
cclk_gate_is_enabled(struct clk_hw * hw)10164261a881SGabriel Fernandez static int cclk_gate_is_enabled(struct clk_hw *hw)
10174261a881SGabriel Fernandez {
10184261a881SGabriel Fernandez return clk_gate_ops.is_enabled(hw);
10194261a881SGabriel Fernandez }
10204261a881SGabriel Fernandez
10214261a881SGabriel Fernandez static const struct clk_ops cclk_gate_ops = {
10224261a881SGabriel Fernandez .enable = cclk_gate_enable,
10234261a881SGabriel Fernandez .disable = cclk_gate_disable,
10244261a881SGabriel Fernandez .is_enabled = cclk_gate_is_enabled,
10254261a881SGabriel Fernandez };
10264261a881SGabriel Fernandez
cclk_mux_get_parent(struct clk_hw * hw)10274261a881SGabriel Fernandez static u8 cclk_mux_get_parent(struct clk_hw *hw)
10284261a881SGabriel Fernandez {
10294261a881SGabriel Fernandez return clk_mux_ops.get_parent(hw);
10304261a881SGabriel Fernandez }
10314261a881SGabriel Fernandez
cclk_mux_set_parent(struct clk_hw * hw,u8 index)10324261a881SGabriel Fernandez static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
10334261a881SGabriel Fernandez {
10344261a881SGabriel Fernandez int ret;
10354261a881SGabriel Fernandez
10364261a881SGabriel Fernandez disable_power_domain_write_protection();
10374261a881SGabriel Fernandez
10384261a881SGabriel Fernandez sofware_reset_backup_domain();
10394261a881SGabriel Fernandez
10404261a881SGabriel Fernandez ret = clk_mux_ops.set_parent(hw, index);
10414261a881SGabriel Fernandez
10424261a881SGabriel Fernandez enable_power_domain_write_protection();
10434261a881SGabriel Fernandez
10444261a881SGabriel Fernandez return ret;
10454261a881SGabriel Fernandez }
10464261a881SGabriel Fernandez
10474261a881SGabriel Fernandez static const struct clk_ops cclk_mux_ops = {
10484261a881SGabriel Fernandez .determine_rate = clk_hw_determine_rate_no_reparent,
10494261a881SGabriel Fernandez .get_parent = cclk_mux_get_parent,
10504261a881SGabriel Fernandez .set_parent = cclk_mux_set_parent,
10514261a881SGabriel Fernandez };
10524261a881SGabriel Fernandez
stm32_register_cclk(struct device * dev,const char * name,const char * const * parent_names,int num_parents,void __iomem * reg,u8 bit_idx,u8 shift,unsigned long flags,spinlock_t * lock)10534261a881SGabriel Fernandez static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
10544261a881SGabriel Fernandez const char * const *parent_names, int num_parents,
10554261a881SGabriel Fernandez void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
10564261a881SGabriel Fernandez spinlock_t *lock)
10574261a881SGabriel Fernandez {
10584261a881SGabriel Fernandez struct clk_hw *hw;
10594261a881SGabriel Fernandez struct clk_gate *gate;
10604261a881SGabriel Fernandez struct clk_mux *mux;
10614261a881SGabriel Fernandez
10624261a881SGabriel Fernandez gate = kzalloc(sizeof(*gate), GFP_KERNEL);
10634261a881SGabriel Fernandez if (!gate) {
10644261a881SGabriel Fernandez hw = ERR_PTR(-EINVAL);
10654261a881SGabriel Fernandez goto fail;
10664261a881SGabriel Fernandez }
10674261a881SGabriel Fernandez
10684261a881SGabriel Fernandez mux = kzalloc(sizeof(*mux), GFP_KERNEL);
10694261a881SGabriel Fernandez if (!mux) {
10704261a881SGabriel Fernandez kfree(gate);
10714261a881SGabriel Fernandez hw = ERR_PTR(-EINVAL);
10724261a881SGabriel Fernandez goto fail;
10734261a881SGabriel Fernandez }
10744261a881SGabriel Fernandez
10754261a881SGabriel Fernandez gate->reg = reg;
10764261a881SGabriel Fernandez gate->bit_idx = bit_idx;
10774261a881SGabriel Fernandez gate->flags = 0;
10784261a881SGabriel Fernandez gate->lock = lock;
10794261a881SGabriel Fernandez
10804261a881SGabriel Fernandez mux->reg = reg;
10814261a881SGabriel Fernandez mux->shift = shift;
10824261a881SGabriel Fernandez mux->mask = 3;
10834261a881SGabriel Fernandez mux->flags = 0;
10844261a881SGabriel Fernandez
10854261a881SGabriel Fernandez hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
10864261a881SGabriel Fernandez &mux->hw, &cclk_mux_ops,
10874261a881SGabriel Fernandez NULL, NULL,
10884261a881SGabriel Fernandez &gate->hw, &cclk_gate_ops,
10894261a881SGabriel Fernandez flags);
10904261a881SGabriel Fernandez
10914261a881SGabriel Fernandez if (IS_ERR(hw)) {
10924261a881SGabriel Fernandez kfree(gate);
10934261a881SGabriel Fernandez kfree(mux);
10944261a881SGabriel Fernandez }
10954261a881SGabriel Fernandez
10964261a881SGabriel Fernandez fail:
10974261a881SGabriel Fernandez return hw;
10984261a881SGabriel Fernandez }
1099358bdf89SDaniel Thompson
1100358bdf89SDaniel Thompson static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" };
1101358bdf89SDaniel Thompson
1102358bdf89SDaniel Thompson static const struct clk_div_table ahb_div_table[] = {
1103358bdf89SDaniel Thompson { 0x0, 1 }, { 0x1, 1 }, { 0x2, 1 }, { 0x3, 1 },
1104358bdf89SDaniel Thompson { 0x4, 1 }, { 0x5, 1 }, { 0x6, 1 }, { 0x7, 1 },
1105358bdf89SDaniel Thompson { 0x8, 2 }, { 0x9, 4 }, { 0xa, 8 }, { 0xb, 16 },
1106358bdf89SDaniel Thompson { 0xc, 64 }, { 0xd, 128 }, { 0xe, 256 }, { 0xf, 512 },
1107358bdf89SDaniel Thompson { 0 },
1108358bdf89SDaniel Thompson };
1109358bdf89SDaniel Thompson
1110358bdf89SDaniel Thompson static const struct clk_div_table apb_div_table[] = {
1111358bdf89SDaniel Thompson { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
1112358bdf89SDaniel Thompson { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 },
1113358bdf89SDaniel Thompson { 0 },
1114358bdf89SDaniel Thompson };
11154261a881SGabriel Fernandez
11164261a881SGabriel Fernandez static const char *rtc_parents[4] = {
11174261a881SGabriel Fernandez "no-clock", "lse", "lsi", "hse-rtc"
11184261a881SGabriel Fernandez };
1119936289f0SGabriel Fernandez
1120936289f0SGabriel Fernandez static const char *pll_src = "pll-src";
1121936289f0SGabriel Fernandez
1122936289f0SGabriel Fernandez static const char *pllsrc_parent[2] = { "hsi", NULL };
11232f05b6b9SGabriel Fernandez
11242f05b6b9SGabriel Fernandez static const char *dsi_parent[2] = { NULL, "pll-r" };
1125daf2d117SGabriel Fernandez
1126daf2d117SGabriel Fernandez static const char *lcd_parent[1] = { "pllsai-r-div" };
112712696bacSGabriel Fernandez
112812696bacSGabriel Fernandez static const char *i2s_parents[2] = { "plli2s-r", NULL };
112962710c12SGabriel Fernandez
113062710c12SGabriel Fernandez static const char *sai_parents[4] = { "pllsai-q-div", "plli2s-q-div", NULL,
113162710c12SGabriel Fernandez "no-clock" };
1132844ca23fSGabriel Fernandez
1133844ca23fSGabriel Fernandez static const char *pll48_parents[2] = { "pll-q", "pllsai-p" };
1134844ca23fSGabriel Fernandez
1135844ca23fSGabriel Fernandez static const char *sdmux_parents[2] = { "pll48", "sys" };
113688c9b70bSGabriel Fernandez
113788c9b70bSGabriel Fernandez static const char *hdmi_parents[2] = { "lse", "hsi_div488" };
113888c9b70bSGabriel Fernandez
113988c9b70bSGabriel Fernandez static const char *spdif_parent[1] = { "plli2s-p" };
114088c9b70bSGabriel Fernandez
114188c9b70bSGabriel Fernandez static const char *lptim_parent[4] = { "apb1_mul", "lsi", "hsi", "lse" };
114288c9b70bSGabriel Fernandez
114388c9b70bSGabriel Fernandez static const char *uart_parents1[4] = { "apb2_div", "sys", "hsi", "lse" };
114488c9b70bSGabriel Fernandez static const char *uart_parents2[4] = { "apb1_div", "sys", "hsi", "lse" };
114588c9b70bSGabriel Fernandez
114688c9b70bSGabriel Fernandez static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
1147936289f0SGabriel Fernandez
1148936289f0SGabriel Fernandez static const char * const dfsdm1_src[] = { "apb2_div", "sys" };
1149936289f0SGabriel Fernandez static const char * const adsfdm1_parent[] = { "sai1_clk", "sai2_clk" };
1150daf2d117SGabriel Fernandez
1151daf2d117SGabriel Fernandez struct stm32_aux_clk {
1152daf2d117SGabriel Fernandez int idx;
1153daf2d117SGabriel Fernandez const char *name;
1154daf2d117SGabriel Fernandez const char * const *parent_names;
1155daf2d117SGabriel Fernandez int num_parents;
1156daf2d117SGabriel Fernandez int offset_mux;
1157daf2d117SGabriel Fernandez u8 shift;
1158daf2d117SGabriel Fernandez u8 mask;
1159daf2d117SGabriel Fernandez int offset_gate;
1160daf2d117SGabriel Fernandez u8 bit_idx;
1161daf2d117SGabriel Fernandez unsigned long flags;
1162daf2d117SGabriel Fernandez };
1163a064a07fSGabriel Fernandez
1164a064a07fSGabriel Fernandez struct stm32f4_clk_data {
1165a064a07fSGabriel Fernandez const struct stm32f4_gate_data *gates_data;
1166a064a07fSGabriel Fernandez const u64 *gates_map;
116783135ad3SGabriel Fernandez int gates_num;
1168daf2d117SGabriel Fernandez const struct stm32f4_pll_data *pll_data;
1169daf2d117SGabriel Fernandez const struct stm32_aux_clk *aux_clk;
117088c9b70bSGabriel Fernandez int aux_clk_num;
1171daf2d117SGabriel Fernandez int end_primary;
1172daf2d117SGabriel Fernandez };
1173daf2d117SGabriel Fernandez
1174daf2d117SGabriel Fernandez static const struct stm32_aux_clk stm32f429_aux_clk[] = {
1175daf2d117SGabriel Fernandez {
1176daf2d117SGabriel Fernandez CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1177daf2d117SGabriel Fernandez NO_MUX, 0, 0,
1178daf2d117SGabriel Fernandez STM32F4_RCC_APB2ENR, 26,
1179daf2d117SGabriel Fernandez CLK_SET_RATE_PARENT
118012696bacSGabriel Fernandez },
118112696bacSGabriel Fernandez {
118212696bacSGabriel Fernandez CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
118312696bacSGabriel Fernandez STM32F4_RCC_CFGR, 23, 1,
118412696bacSGabriel Fernandez NO_GATE, 0,
118512696bacSGabriel Fernandez CLK_SET_RATE_PARENT
118662710c12SGabriel Fernandez },
118762710c12SGabriel Fernandez {
118862710c12SGabriel Fernandez CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
118962710c12SGabriel Fernandez STM32F4_RCC_DCKCFGR, 20, 3,
119062710c12SGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
119162710c12SGabriel Fernandez CLK_SET_RATE_PARENT
119262710c12SGabriel Fernandez },
119362710c12SGabriel Fernandez {
119462710c12SGabriel Fernandez CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
119562710c12SGabriel Fernandez STM32F4_RCC_DCKCFGR, 22, 3,
119662710c12SGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
119762710c12SGabriel Fernandez CLK_SET_RATE_PARENT
1198a064a07fSGabriel Fernandez },
1199a064a07fSGabriel Fernandez };
1200844ca23fSGabriel Fernandez
1201844ca23fSGabriel Fernandez static const struct stm32_aux_clk stm32f469_aux_clk[] = {
1202844ca23fSGabriel Fernandez {
1203844ca23fSGabriel Fernandez CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1204844ca23fSGabriel Fernandez NO_MUX, 0, 0,
1205844ca23fSGabriel Fernandez STM32F4_RCC_APB2ENR, 26,
1206844ca23fSGabriel Fernandez CLK_SET_RATE_PARENT
1207844ca23fSGabriel Fernandez },
1208844ca23fSGabriel Fernandez {
1209844ca23fSGabriel Fernandez CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
1210844ca23fSGabriel Fernandez STM32F4_RCC_CFGR, 23, 1,
1211844ca23fSGabriel Fernandez NO_GATE, 0,
1212844ca23fSGabriel Fernandez CLK_SET_RATE_PARENT
1213844ca23fSGabriel Fernandez },
1214844ca23fSGabriel Fernandez {
1215844ca23fSGabriel Fernandez CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
1216844ca23fSGabriel Fernandez STM32F4_RCC_DCKCFGR, 20, 3,
1217844ca23fSGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
1218844ca23fSGabriel Fernandez CLK_SET_RATE_PARENT
1219844ca23fSGabriel Fernandez },
1220844ca23fSGabriel Fernandez {
1221844ca23fSGabriel Fernandez CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
1222844ca23fSGabriel Fernandez STM32F4_RCC_DCKCFGR, 22, 3,
1223844ca23fSGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
1224844ca23fSGabriel Fernandez CLK_SET_RATE_PARENT
1225844ca23fSGabriel Fernandez },
1226844ca23fSGabriel Fernandez {
1227844ca23fSGabriel Fernandez NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
1228844ca23fSGabriel Fernandez STM32F4_RCC_DCKCFGR, 27, 1,
1229844ca23fSGabriel Fernandez NO_GATE, 0,
1230844ca23fSGabriel Fernandez 0
1231844ca23fSGabriel Fernandez },
1232844ca23fSGabriel Fernandez {
1233844ca23fSGabriel Fernandez NO_IDX, "sdmux", sdmux_parents, ARRAY_SIZE(sdmux_parents),
1234844ca23fSGabriel Fernandez STM32F4_RCC_DCKCFGR, 28, 1,
1235844ca23fSGabriel Fernandez NO_GATE, 0,
1236844ca23fSGabriel Fernandez 0
12372f05b6b9SGabriel Fernandez },
12382f05b6b9SGabriel Fernandez {
12392f05b6b9SGabriel Fernandez CLK_F469_DSI, "dsi", dsi_parent, ARRAY_SIZE(dsi_parent),
12402f05b6b9SGabriel Fernandez STM32F4_RCC_DCKCFGR, 29, 1,
12412f05b6b9SGabriel Fernandez STM32F4_RCC_APB2ENR, 27,
12422f05b6b9SGabriel Fernandez CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
1243a064a07fSGabriel Fernandez },
1244a064a07fSGabriel Fernandez };
124588c9b70bSGabriel Fernandez
124688c9b70bSGabriel Fernandez static const struct stm32_aux_clk stm32f746_aux_clk[] = {
124788c9b70bSGabriel Fernandez {
124888c9b70bSGabriel Fernandez CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
124988c9b70bSGabriel Fernandez NO_MUX, 0, 0,
125088c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 26,
125188c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
125288c9b70bSGabriel Fernandez },
125388c9b70bSGabriel Fernandez {
125488c9b70bSGabriel Fernandez CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
125588c9b70bSGabriel Fernandez STM32F4_RCC_CFGR, 23, 1,
125688c9b70bSGabriel Fernandez NO_GATE, 0,
125788c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
125888c9b70bSGabriel Fernandez },
125988c9b70bSGabriel Fernandez {
126088c9b70bSGabriel Fernandez CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
126188c9b70bSGabriel Fernandez STM32F4_RCC_DCKCFGR, 20, 3,
126288c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
126388c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
126488c9b70bSGabriel Fernandez },
126588c9b70bSGabriel Fernandez {
126688c9b70bSGabriel Fernandez CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
126788c9b70bSGabriel Fernandez STM32F4_RCC_DCKCFGR, 22, 3,
126888c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 23,
126988c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
127088c9b70bSGabriel Fernandez },
127188c9b70bSGabriel Fernandez {
127288c9b70bSGabriel Fernandez NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
127388c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 27, 1,
127488c9b70bSGabriel Fernandez NO_GATE, 0,
127588c9b70bSGabriel Fernandez 0
127688c9b70bSGabriel Fernandez },
127788c9b70bSGabriel Fernandez {
127888c9b70bSGabriel Fernandez NO_IDX, "sdmux", sdmux_parents, ARRAY_SIZE(sdmux_parents),
127988c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 28, 1,
128088c9b70bSGabriel Fernandez NO_GATE, 0,
128188c9b70bSGabriel Fernandez 0
128288c9b70bSGabriel Fernandez },
128388c9b70bSGabriel Fernandez {
128488c9b70bSGabriel Fernandez CLK_HDMI_CEC, "hdmi-cec",
128588c9b70bSGabriel Fernandez hdmi_parents, ARRAY_SIZE(hdmi_parents),
128688c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 26, 1,
128788c9b70bSGabriel Fernandez NO_GATE, 0,
128888c9b70bSGabriel Fernandez 0
128988c9b70bSGabriel Fernandez },
129088c9b70bSGabriel Fernandez {
129188c9b70bSGabriel Fernandez CLK_SPDIF, "spdif-rx",
129288c9b70bSGabriel Fernandez spdif_parent, ARRAY_SIZE(spdif_parent),
129388c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 22, 3,
129488c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 23,
129588c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
129688c9b70bSGabriel Fernandez },
129788c9b70bSGabriel Fernandez {
129888c9b70bSGabriel Fernandez CLK_USART1, "usart1",
129988c9b70bSGabriel Fernandez uart_parents1, ARRAY_SIZE(uart_parents1),
130088c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 0, 3,
130188c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 4,
130288c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
130388c9b70bSGabriel Fernandez },
130488c9b70bSGabriel Fernandez {
130588c9b70bSGabriel Fernandez CLK_USART2, "usart2",
130688c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
130788c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 2, 3,
130888c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 17,
130988c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
131088c9b70bSGabriel Fernandez },
131188c9b70bSGabriel Fernandez {
131288c9b70bSGabriel Fernandez CLK_USART3, "usart3",
131388c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
131488c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 4, 3,
131588c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 18,
131688c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
131788c9b70bSGabriel Fernandez },
131888c9b70bSGabriel Fernandez {
131988c9b70bSGabriel Fernandez CLK_UART4, "uart4",
132088c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
132188c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 6, 3,
132288c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 19,
132388c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
132488c9b70bSGabriel Fernandez },
132588c9b70bSGabriel Fernandez {
132688c9b70bSGabriel Fernandez CLK_UART5, "uart5",
132788c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
132888c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 8, 3,
132988c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 20,
133088c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
133188c9b70bSGabriel Fernandez },
133288c9b70bSGabriel Fernandez {
133388c9b70bSGabriel Fernandez CLK_USART6, "usart6",
133488c9b70bSGabriel Fernandez uart_parents1, ARRAY_SIZE(uart_parents1),
133588c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 10, 3,
133688c9b70bSGabriel Fernandez STM32F4_RCC_APB2ENR, 5,
133788c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
133888c9b70bSGabriel Fernandez },
133988c9b70bSGabriel Fernandez
134088c9b70bSGabriel Fernandez {
134188c9b70bSGabriel Fernandez CLK_UART7, "uart7",
134288c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
134388c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 12, 3,
134488c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 30,
134588c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
134688c9b70bSGabriel Fernandez },
134788c9b70bSGabriel Fernandez {
134888c9b70bSGabriel Fernandez CLK_UART8, "uart8",
134988c9b70bSGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
135088c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 14, 3,
135188c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 31,
135288c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
135388c9b70bSGabriel Fernandez },
135488c9b70bSGabriel Fernandez {
135588c9b70bSGabriel Fernandez CLK_I2C1, "i2c1",
135688c9b70bSGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
135788c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 16, 3,
135888c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 21,
135988c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
136088c9b70bSGabriel Fernandez },
136188c9b70bSGabriel Fernandez {
136288c9b70bSGabriel Fernandez CLK_I2C2, "i2c2",
136388c9b70bSGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
136488c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 18, 3,
136588c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 22,
136688c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
136788c9b70bSGabriel Fernandez },
136888c9b70bSGabriel Fernandez {
136988c9b70bSGabriel Fernandez CLK_I2C3, "i2c3",
137088c9b70bSGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
137188c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 20, 3,
137288c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 23,
137388c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
137488c9b70bSGabriel Fernandez },
137588c9b70bSGabriel Fernandez {
137688c9b70bSGabriel Fernandez CLK_I2C4, "i2c4",
137788c9b70bSGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
137888c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 22, 3,
137988c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 24,
138088c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT,
138188c9b70bSGabriel Fernandez },
138288c9b70bSGabriel Fernandez
138388c9b70bSGabriel Fernandez {
138488c9b70bSGabriel Fernandez CLK_LPTIMER, "lptim1",
138588c9b70bSGabriel Fernandez lptim_parent, ARRAY_SIZE(lptim_parent),
138688c9b70bSGabriel Fernandez STM32F7_RCC_DCKCFGR2, 24, 3,
138788c9b70bSGabriel Fernandez STM32F4_RCC_APB1ENR, 9,
138888c9b70bSGabriel Fernandez CLK_SET_RATE_PARENT
138988c9b70bSGabriel Fernandez },
139088c9b70bSGabriel Fernandez };
1391936289f0SGabriel Fernandez
1392936289f0SGabriel Fernandez static const struct stm32_aux_clk stm32f769_aux_clk[] = {
1393936289f0SGabriel Fernandez {
1394936289f0SGabriel Fernandez CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1395936289f0SGabriel Fernandez NO_MUX, 0, 0,
1396936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 26,
1397936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1398936289f0SGabriel Fernandez },
1399936289f0SGabriel Fernandez {
1400936289f0SGabriel Fernandez CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
1401936289f0SGabriel Fernandez STM32F4_RCC_CFGR, 23, 1,
1402936289f0SGabriel Fernandez NO_GATE, 0,
1403936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1404936289f0SGabriel Fernandez },
1405936289f0SGabriel Fernandez {
1406936289f0SGabriel Fernandez CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
1407936289f0SGabriel Fernandez STM32F4_RCC_DCKCFGR, 20, 3,
1408936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 22,
1409936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1410936289f0SGabriel Fernandez },
1411936289f0SGabriel Fernandez {
1412936289f0SGabriel Fernandez CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
1413936289f0SGabriel Fernandez STM32F4_RCC_DCKCFGR, 22, 3,
1414936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 23,
1415936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1416936289f0SGabriel Fernandez },
1417936289f0SGabriel Fernandez {
1418936289f0SGabriel Fernandez NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
1419936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 27, 1,
1420936289f0SGabriel Fernandez NO_GATE, 0,
1421936289f0SGabriel Fernandez 0
1422936289f0SGabriel Fernandez },
1423936289f0SGabriel Fernandez {
1424936289f0SGabriel Fernandez NO_IDX, "sdmux1", sdmux_parents, ARRAY_SIZE(sdmux_parents),
1425936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 28, 1,
1426936289f0SGabriel Fernandez NO_GATE, 0,
1427936289f0SGabriel Fernandez 0
1428936289f0SGabriel Fernandez },
1429936289f0SGabriel Fernandez {
1430936289f0SGabriel Fernandez NO_IDX, "sdmux2", sdmux_parents, ARRAY_SIZE(sdmux_parents),
1431936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 29, 1,
1432936289f0SGabriel Fernandez NO_GATE, 0,
1433936289f0SGabriel Fernandez 0
1434936289f0SGabriel Fernandez },
1435936289f0SGabriel Fernandez {
1436936289f0SGabriel Fernandez CLK_HDMI_CEC, "hdmi-cec",
1437936289f0SGabriel Fernandez hdmi_parents, ARRAY_SIZE(hdmi_parents),
1438936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 26, 1,
1439936289f0SGabriel Fernandez NO_GATE, 0,
1440936289f0SGabriel Fernandez 0
1441936289f0SGabriel Fernandez },
1442936289f0SGabriel Fernandez {
1443936289f0SGabriel Fernandez CLK_SPDIF, "spdif-rx",
1444936289f0SGabriel Fernandez spdif_parent, ARRAY_SIZE(spdif_parent),
1445936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 22, 3,
1446936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 23,
1447936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1448936289f0SGabriel Fernandez },
1449936289f0SGabriel Fernandez {
1450936289f0SGabriel Fernandez CLK_USART1, "usart1",
1451936289f0SGabriel Fernandez uart_parents1, ARRAY_SIZE(uart_parents1),
1452936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 0, 3,
1453936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 4,
1454936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1455936289f0SGabriel Fernandez },
1456936289f0SGabriel Fernandez {
1457936289f0SGabriel Fernandez CLK_USART2, "usart2",
1458936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1459936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 2, 3,
1460936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 17,
1461936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1462936289f0SGabriel Fernandez },
1463936289f0SGabriel Fernandez {
1464936289f0SGabriel Fernandez CLK_USART3, "usart3",
1465936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1466936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 4, 3,
1467936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 18,
1468936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1469936289f0SGabriel Fernandez },
1470936289f0SGabriel Fernandez {
1471936289f0SGabriel Fernandez CLK_UART4, "uart4",
1472936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1473936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 6, 3,
1474936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 19,
1475936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1476936289f0SGabriel Fernandez },
1477936289f0SGabriel Fernandez {
1478936289f0SGabriel Fernandez CLK_UART5, "uart5",
1479936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1480936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 8, 3,
1481936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 20,
1482936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1483936289f0SGabriel Fernandez },
1484936289f0SGabriel Fernandez {
1485936289f0SGabriel Fernandez CLK_USART6, "usart6",
1486936289f0SGabriel Fernandez uart_parents1, ARRAY_SIZE(uart_parents1),
1487936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 10, 3,
1488936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 5,
1489936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1490936289f0SGabriel Fernandez },
1491936289f0SGabriel Fernandez {
1492936289f0SGabriel Fernandez CLK_UART7, "uart7",
1493936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1494936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 12, 3,
1495936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 30,
1496936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1497936289f0SGabriel Fernandez },
1498936289f0SGabriel Fernandez {
1499936289f0SGabriel Fernandez CLK_UART8, "uart8",
1500936289f0SGabriel Fernandez uart_parents2, ARRAY_SIZE(uart_parents1),
1501936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 14, 3,
1502936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 31,
1503936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1504936289f0SGabriel Fernandez },
1505936289f0SGabriel Fernandez {
1506936289f0SGabriel Fernandez CLK_I2C1, "i2c1",
1507936289f0SGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
1508936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 16, 3,
1509936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 21,
1510936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1511936289f0SGabriel Fernandez },
1512936289f0SGabriel Fernandez {
1513936289f0SGabriel Fernandez CLK_I2C2, "i2c2",
1514936289f0SGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
1515936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 18, 3,
1516936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 22,
1517936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1518936289f0SGabriel Fernandez },
1519936289f0SGabriel Fernandez {
1520936289f0SGabriel Fernandez CLK_I2C3, "i2c3",
1521936289f0SGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
1522936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 20, 3,
1523936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 23,
1524936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1525936289f0SGabriel Fernandez },
1526936289f0SGabriel Fernandez {
1527936289f0SGabriel Fernandez CLK_I2C4, "i2c4",
1528936289f0SGabriel Fernandez i2c_parents, ARRAY_SIZE(i2c_parents),
1529936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 22, 3,
1530936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 24,
1531936289f0SGabriel Fernandez CLK_SET_RATE_PARENT,
1532936289f0SGabriel Fernandez },
1533936289f0SGabriel Fernandez {
1534936289f0SGabriel Fernandez CLK_LPTIMER, "lptim1",
1535936289f0SGabriel Fernandez lptim_parent, ARRAY_SIZE(lptim_parent),
1536936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 24, 3,
1537936289f0SGabriel Fernandez STM32F4_RCC_APB1ENR, 9,
1538936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1539936289f0SGabriel Fernandez },
1540936289f0SGabriel Fernandez {
1541936289f0SGabriel Fernandez CLK_F769_DSI, "dsi",
1542936289f0SGabriel Fernandez dsi_parent, ARRAY_SIZE(dsi_parent),
1543936289f0SGabriel Fernandez STM32F7_RCC_DCKCFGR2, 0, 1,
1544936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 27,
1545936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1546936289f0SGabriel Fernandez },
1547936289f0SGabriel Fernandez {
1548936289f0SGabriel Fernandez CLK_DFSDM1, "dfsdm1",
1549936289f0SGabriel Fernandez dfsdm1_src, ARRAY_SIZE(dfsdm1_src),
1550936289f0SGabriel Fernandez STM32F4_RCC_DCKCFGR, 25, 1,
1551936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 29,
1552936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1553936289f0SGabriel Fernandez },
1554936289f0SGabriel Fernandez {
1555936289f0SGabriel Fernandez CLK_ADFSDM1, "adfsdm1",
1556936289f0SGabriel Fernandez adsfdm1_parent, ARRAY_SIZE(adsfdm1_parent),
1557936289f0SGabriel Fernandez STM32F4_RCC_DCKCFGR, 26, 1,
1558936289f0SGabriel Fernandez STM32F4_RCC_APB2ENR, 29,
1559936289f0SGabriel Fernandez CLK_SET_RATE_PARENT
1560936289f0SGabriel Fernandez },
1561936289f0SGabriel Fernandez };
1562a064a07fSGabriel Fernandez
156388c9b70bSGabriel Fernandez static const struct stm32f4_clk_data stm32f429_clk_data = {
1564a064a07fSGabriel Fernandez .end_primary = END_PRIMARY_CLK,
1565a064a07fSGabriel Fernandez .gates_data = stm32f429_gates,
1566a064a07fSGabriel Fernandez .gates_map = stm32f42xx_gate_map,
156783135ad3SGabriel Fernandez .gates_num = ARRAY_SIZE(stm32f429_gates),
1568daf2d117SGabriel Fernandez .pll_data = stm32f429_pll,
1569daf2d117SGabriel Fernandez .aux_clk = stm32f429_aux_clk,
1570a064a07fSGabriel Fernandez .aux_clk_num = ARRAY_SIZE(stm32f429_aux_clk),
1571a064a07fSGabriel Fernandez };
1572a064a07fSGabriel Fernandez
157388c9b70bSGabriel Fernandez static const struct stm32f4_clk_data stm32f469_clk_data = {
1574a064a07fSGabriel Fernandez .end_primary = END_PRIMARY_CLK,
1575a064a07fSGabriel Fernandez .gates_data = stm32f469_gates,
1576a064a07fSGabriel Fernandez .gates_map = stm32f46xx_gate_map,
157783135ad3SGabriel Fernandez .gates_num = ARRAY_SIZE(stm32f469_gates),
1578844ca23fSGabriel Fernandez .pll_data = stm32f469_pll,
1579844ca23fSGabriel Fernandez .aux_clk = stm32f469_aux_clk,
1580a064a07fSGabriel Fernandez .aux_clk_num = ARRAY_SIZE(stm32f469_aux_clk),
1581a064a07fSGabriel Fernandez };
158288c9b70bSGabriel Fernandez
158388c9b70bSGabriel Fernandez static const struct stm32f4_clk_data stm32f746_clk_data = {
158488c9b70bSGabriel Fernandez .end_primary = END_PRIMARY_CLK_F7,
158588c9b70bSGabriel Fernandez .gates_data = stm32f746_gates,
158688c9b70bSGabriel Fernandez .gates_map = stm32f746_gate_map,
158788c9b70bSGabriel Fernandez .gates_num = ARRAY_SIZE(stm32f746_gates),
158888c9b70bSGabriel Fernandez .pll_data = stm32f469_pll,
158988c9b70bSGabriel Fernandez .aux_clk = stm32f746_aux_clk,
159088c9b70bSGabriel Fernandez .aux_clk_num = ARRAY_SIZE(stm32f746_aux_clk),
159188c9b70bSGabriel Fernandez };
1592936289f0SGabriel Fernandez
1593936289f0SGabriel Fernandez static const struct stm32f4_clk_data stm32f769_clk_data = {
1594936289f0SGabriel Fernandez .end_primary = END_PRIMARY_CLK_F7,
1595936289f0SGabriel Fernandez .gates_data = stm32f769_gates,
1596936289f0SGabriel Fernandez .gates_map = stm32f769_gate_map,
1597936289f0SGabriel Fernandez .gates_num = ARRAY_SIZE(stm32f769_gates),
1598936289f0SGabriel Fernandez .pll_data = stm32f469_pll,
1599936289f0SGabriel Fernandez .aux_clk = stm32f769_aux_clk,
1600936289f0SGabriel Fernandez .aux_clk_num = ARRAY_SIZE(stm32f769_aux_clk),
1601936289f0SGabriel Fernandez };
1602a064a07fSGabriel Fernandez
1603a064a07fSGabriel Fernandez static const struct of_device_id stm32f4_of_match[] = {
1604a064a07fSGabriel Fernandez {
1605a064a07fSGabriel Fernandez .compatible = "st,stm32f42xx-rcc",
1606a064a07fSGabriel Fernandez .data = &stm32f429_clk_data
1607a064a07fSGabriel Fernandez },
1608a064a07fSGabriel Fernandez {
1609a064a07fSGabriel Fernandez .compatible = "st,stm32f469-rcc",
1610a064a07fSGabriel Fernandez .data = &stm32f469_clk_data
161188c9b70bSGabriel Fernandez },
161288c9b70bSGabriel Fernandez {
161388c9b70bSGabriel Fernandez .compatible = "st,stm32f746-rcc",
161488c9b70bSGabriel Fernandez .data = &stm32f746_clk_data
1615936289f0SGabriel Fernandez },
1616936289f0SGabriel Fernandez {
1617936289f0SGabriel Fernandez .compatible = "st,stm32f769-rcc",
1618936289f0SGabriel Fernandez .data = &stm32f769_clk_data
1619a064a07fSGabriel Fernandez },
1620a064a07fSGabriel Fernandez {}
1621a064a07fSGabriel Fernandez };
1622daf2d117SGabriel Fernandez
stm32_register_aux_clk(const char * name,const char * const * parent_names,int num_parents,int offset_mux,u8 shift,u8 mask,int offset_gate,u8 bit_idx,unsigned long flags,spinlock_t * lock)1623daf2d117SGabriel Fernandez static struct clk_hw *stm32_register_aux_clk(const char *name,
1624daf2d117SGabriel Fernandez const char * const *parent_names, int num_parents,
1625daf2d117SGabriel Fernandez int offset_mux, u8 shift, u8 mask,
1626daf2d117SGabriel Fernandez int offset_gate, u8 bit_idx,
1627daf2d117SGabriel Fernandez unsigned long flags, spinlock_t *lock)
1628daf2d117SGabriel Fernandez {
162989d5dcc4SArnd Bergmann struct clk_hw *hw;
1630daf2d117SGabriel Fernandez struct clk_gate *gate = NULL;
1631daf2d117SGabriel Fernandez struct clk_mux *mux = NULL;
1632daf2d117SGabriel Fernandez struct clk_hw *mux_hw = NULL, *gate_hw = NULL;
1633daf2d117SGabriel Fernandez const struct clk_ops *mux_ops = NULL, *gate_ops = NULL;
1634daf2d117SGabriel Fernandez
1635daf2d117SGabriel Fernandez if (offset_gate != NO_GATE) {
1636daf2d117SGabriel Fernandez gate = kzalloc(sizeof(*gate), GFP_KERNEL);
1637daf2d117SGabriel Fernandez if (!gate) {
1638daf2d117SGabriel Fernandez hw = ERR_PTR(-EINVAL);
1639daf2d117SGabriel Fernandez goto fail;
1640daf2d117SGabriel Fernandez }
1641daf2d117SGabriel Fernandez
1642daf2d117SGabriel Fernandez gate->reg = base + offset_gate;
1643daf2d117SGabriel Fernandez gate->bit_idx = bit_idx;
1644daf2d117SGabriel Fernandez gate->flags = 0;
1645daf2d117SGabriel Fernandez gate->lock = lock;
1646daf2d117SGabriel Fernandez gate_hw = &gate->hw;
1647daf2d117SGabriel Fernandez gate_ops = &clk_gate_ops;
1648daf2d117SGabriel Fernandez }
1649daf2d117SGabriel Fernandez
1650daf2d117SGabriel Fernandez if (offset_mux != NO_MUX) {
1651daf2d117SGabriel Fernandez mux = kzalloc(sizeof(*mux), GFP_KERNEL);
1652daf2d117SGabriel Fernandez if (!mux) {
1653daf2d117SGabriel Fernandez hw = ERR_PTR(-EINVAL);
1654daf2d117SGabriel Fernandez goto fail;
1655daf2d117SGabriel Fernandez }
1656daf2d117SGabriel Fernandez
1657daf2d117SGabriel Fernandez mux->reg = base + offset_mux;
1658daf2d117SGabriel Fernandez mux->shift = shift;
1659daf2d117SGabriel Fernandez mux->mask = mask;
1660daf2d117SGabriel Fernandez mux->flags = 0;
1661daf2d117SGabriel Fernandez mux_hw = &mux->hw;
1662daf2d117SGabriel Fernandez mux_ops = &clk_mux_ops;
1663daf2d117SGabriel Fernandez }
166489d5dcc4SArnd Bergmann
166589d5dcc4SArnd Bergmann if (mux_hw == NULL && gate_hw == NULL) {
166689d5dcc4SArnd Bergmann hw = ERR_PTR(-EINVAL);
166789d5dcc4SArnd Bergmann goto fail;
1668daf2d117SGabriel Fernandez }
1669daf2d117SGabriel Fernandez
1670daf2d117SGabriel Fernandez hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
1671daf2d117SGabriel Fernandez mux_hw, mux_ops,
1672daf2d117SGabriel Fernandez NULL, NULL,
1673daf2d117SGabriel Fernandez gate_hw, gate_ops,
1674daf2d117SGabriel Fernandez flags);
167589d5dcc4SArnd Bergmann
1676daf2d117SGabriel Fernandez fail:
1677daf2d117SGabriel Fernandez if (IS_ERR(hw)) {
1678daf2d117SGabriel Fernandez kfree(gate);
1679daf2d117SGabriel Fernandez kfree(mux);
168089d5dcc4SArnd Bergmann }
1681daf2d117SGabriel Fernandez
1682daf2d117SGabriel Fernandez return hw;
1683daf2d117SGabriel Fernandez }
1684358bdf89SDaniel Thompson
stm32f4_rcc_init(struct device_node * np)1685358bdf89SDaniel Thompson static void __init stm32f4_rcc_init(struct device_node *np)
168612696bacSGabriel Fernandez {
1687358bdf89SDaniel Thompson const char *hse_clk, *i2s_in_clk;
1688a064a07fSGabriel Fernandez int n;
1689a064a07fSGabriel Fernandez const struct of_device_id *match;
169083135ad3SGabriel Fernandez const struct stm32f4_clk_data *data;
1691936289f0SGabriel Fernandez unsigned long pllm;
1692358bdf89SDaniel Thompson struct clk_hw *pll_src_hw;
1693358bdf89SDaniel Thompson
1694358bdf89SDaniel Thompson base = of_iomap(np, 0);
1695e665f029SRob Herring if (!base) {
1696358bdf89SDaniel Thompson pr_err("%pOFn: unable to map resource\n", np);
1697358bdf89SDaniel Thompson return;
1698358bdf89SDaniel Thompson }
1699861adc44SGabriel Fernandez
1700861adc44SGabriel Fernandez pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
1701861adc44SGabriel Fernandez if (IS_ERR(pdrm)) {
1702861adc44SGabriel Fernandez pdrm = NULL;
1703861adc44SGabriel Fernandez pr_warn("%s: Unable to get syscfg\n", __func__);
1704861adc44SGabriel Fernandez }
1705a064a07fSGabriel Fernandez
1706a064a07fSGabriel Fernandez match = of_match_node(stm32f4_of_match, np);
1707a064a07fSGabriel Fernandez if (WARN_ON(!match))
1708a064a07fSGabriel Fernandez return;
1709a064a07fSGabriel Fernandez
1710a064a07fSGabriel Fernandez data = match->data;
171188c9b70bSGabriel Fernandez
171288c9b70bSGabriel Fernandez stm32fx_end_primary_clk = data->end_primary;
171388c9b70bSGabriel Fernandez
1714a064a07fSGabriel Fernandez clks = kmalloc_array(data->gates_num + stm32fx_end_primary_clk,
1715a064a07fSGabriel Fernandez sizeof(*clks), GFP_KERNEL);
1716a064a07fSGabriel Fernandez if (!clks)
1717a064a07fSGabriel Fernandez goto fail;
1718a064a07fSGabriel Fernandez
1719a064a07fSGabriel Fernandez stm32f4_gate_map = data->gates_map;
1720358bdf89SDaniel Thompson
17212f05b6b9SGabriel Fernandez hse_clk = of_clk_get_parent_name(np, 0);
1722936289f0SGabriel Fernandez dsi_parent[0] = hse_clk;
1723358bdf89SDaniel Thompson pllsrc_parent[1] = hse_clk;
172412696bacSGabriel Fernandez
172512696bacSGabriel Fernandez i2s_in_clk = of_clk_get_parent_name(np, 1);
172612696bacSGabriel Fernandez
172762710c12SGabriel Fernandez i2s_parents[1] = i2s_in_clk;
172812696bacSGabriel Fernandez sai_parents[2] = i2s_in_clk;
1729936289f0SGabriel Fernandez
1730936289f0SGabriel Fernandez if (of_device_is_compatible(np, "st,stm32f769-rcc")) {
1731936289f0SGabriel Fernandez clk_hw_register_gate(NULL, "dfsdm1_apb", "apb2_div", 0,
1732936289f0SGabriel Fernandez base + STM32F4_RCC_APB2ENR, 29,
1733936289f0SGabriel Fernandez CLK_IGNORE_UNUSED, &stm32f4_clk_lock);
1734936289f0SGabriel Fernandez dsi_parent[0] = pll_src;
1735936289f0SGabriel Fernandez sai_parents[3] = pll_src;
1736936289f0SGabriel Fernandez }
173788c9b70bSGabriel Fernandez
173888c9b70bSGabriel Fernandez clks[CLK_HSI] = clk_hw_register_fixed_rate_with_accuracy(NULL, "hsi",
173988c9b70bSGabriel Fernandez NULL, 0, 16000000, 160000);
1740936289f0SGabriel Fernandez
1741936289f0SGabriel Fernandez pll_src_hw = clk_hw_register_mux(NULL, pll_src, pllsrc_parent,
1742936289f0SGabriel Fernandez ARRAY_SIZE(pllsrc_parent), 0,
1743936289f0SGabriel Fernandez base + STM32F4_RCC_PLLCFGR, 22, 1, 0,
174483135ad3SGabriel Fernandez &stm32f4_clk_lock);
1745936289f0SGabriel Fernandez
1746936289f0SGabriel Fernandez pllm = readl(base + STM32F4_RCC_PLLCFGR) & 0x3f;
1747936289f0SGabriel Fernandez
174883135ad3SGabriel Fernandez clk_hw_register_fixed_factor(NULL, "vco_in", pll_src,
174983135ad3SGabriel Fernandez 0, 1, pllm);
175083135ad3SGabriel Fernandez
175183135ad3SGabriel Fernandez stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
175283135ad3SGabriel Fernandez &stm32f4_clk_lock);
175383135ad3SGabriel Fernandez
175483135ad3SGabriel Fernandez clks[PLL_VCO_I2S] = stm32f4_rcc_register_pll("vco_in",
175583135ad3SGabriel Fernandez &data->pll_data[1], &stm32f4_clk_lock);
175683135ad3SGabriel Fernandez
175783135ad3SGabriel Fernandez clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll("vco_in",
1758358bdf89SDaniel Thompson &data->pll_data[2], &stm32f4_clk_lock);
1759517633efSGabriel Fernandez
1760517633efSGabriel Fernandez for (n = 0; n < MAX_POST_DIV; n++) {
1761517633efSGabriel Fernandez const struct stm32f4_pll_post_div_data *post_div;
1762517633efSGabriel Fernandez struct clk_hw *hw;
1763517633efSGabriel Fernandez
1764517633efSGabriel Fernandez post_div = &post_div_data[n];
1765517633efSGabriel Fernandez
1766517633efSGabriel Fernandez hw = clk_register_pll_div(post_div->name,
1767517633efSGabriel Fernandez post_div->parent,
1768517633efSGabriel Fernandez post_div->flag,
1769517633efSGabriel Fernandez base + post_div->offset,
1770517633efSGabriel Fernandez post_div->shift,
1771517633efSGabriel Fernandez post_div->width,
1772517633efSGabriel Fernandez post_div->flag_div,
177324b5b197SDario Binacchi post_div->div_table,
1774517633efSGabriel Fernandez clks[post_div->pll_idx],
1775517633efSGabriel Fernandez &stm32f4_clk_lock);
1776517633efSGabriel Fernandez
1777517633efSGabriel Fernandez if (post_div->idx != NO_IDX)
1778517633efSGabriel Fernandez clks[post_div->idx] = hw;
1779358bdf89SDaniel Thompson }
1780358bdf89SDaniel Thompson
178188c9b70bSGabriel Fernandez sys_parents[1] = hse_clk;
178288c9b70bSGabriel Fernandez
1783358bdf89SDaniel Thompson clks[CLK_SYSCLK] = clk_hw_register_mux_table(
1784358bdf89SDaniel Thompson NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
1785358bdf89SDaniel Thompson base + STM32F4_RCC_CFGR, 0, 3, 0, NULL, &stm32f4_clk_lock);
1786358bdf89SDaniel Thompson
1787358bdf89SDaniel Thompson clk_register_divider_table(NULL, "ahb_div", "sys",
1788358bdf89SDaniel Thompson CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
1789358bdf89SDaniel Thompson 4, 4, 0, ahb_div_table, &stm32f4_clk_lock);
1790358bdf89SDaniel Thompson
1791358bdf89SDaniel Thompson clk_register_divider_table(NULL, "apb1_div", "ahb_div",
1792358bdf89SDaniel Thompson CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
1793358bdf89SDaniel Thompson 10, 3, 0, apb_div_table, &stm32f4_clk_lock);
1794358bdf89SDaniel Thompson clk_register_apb_mul(NULL, "apb1_mul", "apb1_div",
1795358bdf89SDaniel Thompson CLK_SET_RATE_PARENT, 12);
1796358bdf89SDaniel Thompson
1797358bdf89SDaniel Thompson clk_register_divider_table(NULL, "apb2_div", "ahb_div",
1798358bdf89SDaniel Thompson CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
1799358bdf89SDaniel Thompson 13, 3, 0, apb_div_table, &stm32f4_clk_lock);
1800358bdf89SDaniel Thompson clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
1801358bdf89SDaniel Thompson CLK_SET_RATE_PARENT, 15);
18024e950d1eSStephen Boyd
1803358bdf89SDaniel Thompson clks[SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", "ahb_div",
18044e950d1eSStephen Boyd 0, 1, 8);
1805358bdf89SDaniel Thompson clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
1806358bdf89SDaniel Thompson 0, 1, 1);
1807a064a07fSGabriel Fernandez
1808a064a07fSGabriel Fernandez for (n = 0; n < data->gates_num; n++) {
1809a064a07fSGabriel Fernandez const struct stm32f4_gate_data *gd;
1810a064a07fSGabriel Fernandez unsigned int secondary;
1811a064a07fSGabriel Fernandez int idx;
1812a064a07fSGabriel Fernandez
1813a064a07fSGabriel Fernandez gd = &data->gates_data[n];
1814a064a07fSGabriel Fernandez secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
1815a064a07fSGabriel Fernandez gd->bit_idx;
1816358bdf89SDaniel Thompson idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
1817358bdf89SDaniel Thompson
1818358bdf89SDaniel Thompson if (idx < 0)
1819358bdf89SDaniel Thompson goto fail;
18204e950d1eSStephen Boyd
1821358bdf89SDaniel Thompson clks[idx] = clk_hw_register_gate(
1822358bdf89SDaniel Thompson NULL, gd->name, gd->parent_name, gd->flags,
1823358bdf89SDaniel Thompson base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
1824334e125bSChristophe JAILLET
182516673931SRob Herring if (IS_ERR(clks[idx])) {
182616673931SRob Herring pr_err("%pOF: Unable to register leaf clock %s\n",
1827358bdf89SDaniel Thompson np, gd->name);
1828358bdf89SDaniel Thompson goto fail;
1829358bdf89SDaniel Thompson }
1830358bdf89SDaniel Thompson }
1831861adc44SGabriel Fernandez
1832ac03d8b3SGabriel Fernandez clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
1833861adc44SGabriel Fernandez base + STM32F4_RCC_CSR, 0, 1, 0, &stm32f4_clk_lock);
1834861adc44SGabriel Fernandez
1835861adc44SGabriel Fernandez if (IS_ERR(clks[CLK_LSI])) {
1836861adc44SGabriel Fernandez pr_err("Unable to register lsi clock\n");
1837861adc44SGabriel Fernandez goto fail;
1838861adc44SGabriel Fernandez }
1839861adc44SGabriel Fernandez
1840ac03d8b3SGabriel Fernandez clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
1841861adc44SGabriel Fernandez base + STM32F4_RCC_BDCR, 0, 1, 0, &stm32f4_clk_lock);
1842861adc44SGabriel Fernandez
1843861adc44SGabriel Fernandez if (IS_ERR(clks[CLK_LSE])) {
1844861adc44SGabriel Fernandez pr_err("Unable to register lse clock\n");
1845861adc44SGabriel Fernandez goto fail;
1846861adc44SGabriel Fernandez }
18474261a881SGabriel Fernandez
18484261a881SGabriel Fernandez clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
18494261a881SGabriel Fernandez 0, base + STM32F4_RCC_CFGR, 16, 5, 0,
18504261a881SGabriel Fernandez &stm32f4_clk_lock);
18514261a881SGabriel Fernandez
18524261a881SGabriel Fernandez if (IS_ERR(clks[CLK_HSE_RTC])) {
18534261a881SGabriel Fernandez pr_err("Unable to register hse-rtc clock\n");
18544261a881SGabriel Fernandez goto fail;
18554261a881SGabriel Fernandez }
18564261a881SGabriel Fernandez
18574261a881SGabriel Fernandez clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
18584261a881SGabriel Fernandez base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
18594261a881SGabriel Fernandez
18604261a881SGabriel Fernandez if (IS_ERR(clks[CLK_RTC])) {
18614261a881SGabriel Fernandez pr_err("Unable to register rtc clock\n");
18624261a881SGabriel Fernandez goto fail;
18634261a881SGabriel Fernandez }
1864daf2d117SGabriel Fernandez
1865daf2d117SGabriel Fernandez for (n = 0; n < data->aux_clk_num; n++) {
1866daf2d117SGabriel Fernandez const struct stm32_aux_clk *aux_clk;
1867daf2d117SGabriel Fernandez struct clk_hw *hw;
1868daf2d117SGabriel Fernandez
1869daf2d117SGabriel Fernandez aux_clk = &data->aux_clk[n];
1870daf2d117SGabriel Fernandez
1871daf2d117SGabriel Fernandez hw = stm32_register_aux_clk(aux_clk->name,
1872daf2d117SGabriel Fernandez aux_clk->parent_names, aux_clk->num_parents,
1873daf2d117SGabriel Fernandez aux_clk->offset_mux, aux_clk->shift,
1874daf2d117SGabriel Fernandez aux_clk->mask, aux_clk->offset_gate,
1875daf2d117SGabriel Fernandez aux_clk->bit_idx, aux_clk->flags,
1876daf2d117SGabriel Fernandez &stm32f4_clk_lock);
1877daf2d117SGabriel Fernandez
1878daf2d117SGabriel Fernandez if (IS_ERR(hw)) {
1879daf2d117SGabriel Fernandez pr_warn("Unable to register %s clk\n", aux_clk->name);
1880daf2d117SGabriel Fernandez continue;
1881daf2d117SGabriel Fernandez }
1882daf2d117SGabriel Fernandez
1883daf2d117SGabriel Fernandez if (aux_clk->idx != NO_IDX)
1884daf2d117SGabriel Fernandez clks[aux_clk->idx] = hw;
1885daf2d117SGabriel Fernandez }
1886936289f0SGabriel Fernandez
188788c9b70bSGabriel Fernandez if (of_device_is_compatible(np, "st,stm32f746-rcc")) {
188888c9b70bSGabriel Fernandez
188988c9b70bSGabriel Fernandez clk_hw_register_fixed_factor(NULL, "hsi_div488", "hsi", 0,
189088c9b70bSGabriel Fernandez 1, 488);
1891936289f0SGabriel Fernandez
1892936289f0SGabriel Fernandez clks[CLK_PLL_SRC] = pll_src_hw;
1893936289f0SGabriel Fernandez }
18944e950d1eSStephen Boyd
1895936289f0SGabriel Fernandez of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
1896358bdf89SDaniel Thompson
1897358bdf89SDaniel Thompson return;
1898a064a07fSGabriel Fernandez fail:
1899358bdf89SDaniel Thompson kfree(clks);
1900358bdf89SDaniel Thompson iounmap(base);
19013868f132SGabriel Fernandez }
19023868f132SGabriel Fernandez CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
190388c9b70bSGabriel Fernandez CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
1904936289f0SGabriel Fernandez CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
1905 CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);
1906