1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com> |
4 | * |
5 | * Common Clock Framework support for all S3C64xx SoCs. |
6 | */ |
7 | |
8 | #include <linux/slab.h> |
9 | #include <linux/clk-provider.h> |
10 | #include <linux/clk/samsung.h> |
11 | #include <linux/of.h> |
12 | #include <linux/of_address.h> |
13 | |
14 | #include <dt-bindings/clock/samsung,s3c64xx-clock.h> |
15 | |
16 | #include "clk.h" |
17 | #include "clk-pll.h" |
18 | |
19 | /* S3C64xx clock controller register offsets. */ |
20 | #define APLL_LOCK 0x000 |
21 | #define MPLL_LOCK 0x004 |
22 | #define EPLL_LOCK 0x008 |
23 | #define APLL_CON 0x00c |
24 | #define MPLL_CON 0x010 |
25 | #define EPLL_CON0 0x014 |
26 | #define EPLL_CON1 0x018 |
27 | #define CLK_SRC 0x01c |
28 | #define CLK_DIV0 0x020 |
29 | #define CLK_DIV1 0x024 |
30 | #define CLK_DIV2 0x028 |
31 | #define HCLK_GATE 0x030 |
32 | #define PCLK_GATE 0x034 |
33 | #define SCLK_GATE 0x038 |
34 | #define MEM0_GATE 0x03c |
35 | #define CLK_SRC2 0x10c |
36 | #define OTHERS 0x900 |
37 | |
38 | /* Helper macros to define clock arrays. */ |
39 | #define FIXED_RATE_CLOCKS(name) \ |
40 | static struct samsung_fixed_rate_clock name[] |
41 | #define MUX_CLOCKS(name) \ |
42 | static struct samsung_mux_clock name[] |
43 | #define DIV_CLOCKS(name) \ |
44 | static struct samsung_div_clock name[] |
45 | #define GATE_CLOCKS(name) \ |
46 | static struct samsung_gate_clock name[] |
47 | |
48 | /* Helper macros for gate types present on S3C64xx. */ |
49 | #define GATE_BUS(_id, cname, pname, o, b) \ |
50 | GATE(_id, cname, pname, o, b, 0, 0) |
51 | #define GATE_SCLK(_id, cname, pname, o, b) \ |
52 | GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0) |
53 | #define GATE_ON(_id, cname, pname, o, b) \ |
54 | GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0) |
55 | |
56 | static void __iomem *reg_base; |
57 | static bool is_s3c6400; |
58 | |
59 | /* |
60 | * List of controller registers to be saved and restored during |
61 | * a suspend/resume cycle. |
62 | */ |
63 | static unsigned long s3c64xx_clk_regs[] __initdata = { |
64 | APLL_LOCK, |
65 | MPLL_LOCK, |
66 | EPLL_LOCK, |
67 | APLL_CON, |
68 | MPLL_CON, |
69 | EPLL_CON0, |
70 | EPLL_CON1, |
71 | CLK_SRC, |
72 | CLK_DIV0, |
73 | CLK_DIV1, |
74 | CLK_DIV2, |
75 | HCLK_GATE, |
76 | PCLK_GATE, |
77 | SCLK_GATE, |
78 | }; |
79 | |
80 | static unsigned long s3c6410_clk_regs[] __initdata = { |
81 | CLK_SRC2, |
82 | MEM0_GATE, |
83 | }; |
84 | |
85 | /* List of parent clocks common for all S3C64xx SoCs. */ |
86 | PNAME(spi_mmc_p) = { "mout_epll" , "dout_mpll" , "fin_pll" , "clk27m" }; |
87 | PNAME(uart_p) = { "mout_epll" , "dout_mpll" }; |
88 | PNAME(audio0_p) = { "mout_epll" , "dout_mpll" , "fin_pll" , "iiscdclk0" , |
89 | "pcmcdclk0" , "none" , "none" , "none" }; |
90 | PNAME(audio1_p) = { "mout_epll" , "dout_mpll" , "fin_pll" , "iiscdclk1" , |
91 | "pcmcdclk0" , "none" , "none" , "none" }; |
92 | PNAME(mfc_p) = { "hclkx2" , "mout_epll" }; |
93 | PNAME(apll_p) = { "fin_pll" , "fout_apll" }; |
94 | PNAME(mpll_p) = { "fin_pll" , "fout_mpll" }; |
95 | PNAME(epll_p) = { "fin_pll" , "fout_epll" }; |
96 | PNAME(hclkx2_p) = { "mout_mpll" , "mout_apll" }; |
97 | |
98 | /* S3C6400-specific parent clocks. */ |
99 | PNAME(scaler_lcd_p6400) = { "mout_epll" , "dout_mpll" , "none" , "none" }; |
100 | PNAME(irda_p6400) = { "mout_epll" , "dout_mpll" , "none" , "clk48m" }; |
101 | PNAME(uhost_p6400) = { "clk48m" , "mout_epll" , "dout_mpll" , "none" }; |
102 | |
103 | /* S3C6410-specific parent clocks. */ |
104 | PNAME(clk27_p6410) = { "clk27m" , "fin_pll" }; |
105 | PNAME(scaler_lcd_p6410) = { "mout_epll" , "dout_mpll" , "fin_pll" , "none" }; |
106 | PNAME(irda_p6410) = { "mout_epll" , "dout_mpll" , "fin_pll" , "clk48m" }; |
107 | PNAME(uhost_p6410) = { "clk48m" , "mout_epll" , "dout_mpll" , "fin_pll" }; |
108 | PNAME(audio2_p6410) = { "mout_epll" , "dout_mpll" , "fin_pll" , "iiscdclk2" , |
109 | "pcmcdclk1" , "none" , "none" , "none" }; |
110 | |
111 | /* Fixed rate clocks generated outside the SoC. */ |
112 | FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = { |
113 | FRATE(0, "fin_pll" , NULL, 0, 0), |
114 | FRATE(0, "xusbxti" , NULL, 0, 0), |
115 | }; |
116 | |
117 | /* Fixed rate clocks generated inside the SoC. */ |
118 | FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = { |
119 | FRATE(CLK27M, "clk27m" , NULL, 0, 27000000), |
120 | FRATE(CLK48M, "clk48m" , NULL, 0, 48000000), |
121 | }; |
122 | |
123 | /* List of clock muxes present on all S3C64xx SoCs. */ |
124 | MUX_CLOCKS(s3c64xx_mux_clks) __initdata = { |
125 | MUX_F(0, "mout_syncmux" , hclkx2_p, OTHERS, 6, 1, 0, CLK_MUX_READ_ONLY), |
126 | MUX(MOUT_APLL, "mout_apll" , apll_p, CLK_SRC, 0, 1), |
127 | MUX(MOUT_MPLL, "mout_mpll" , mpll_p, CLK_SRC, 1, 1), |
128 | MUX(MOUT_EPLL, "mout_epll" , epll_p, CLK_SRC, 2, 1), |
129 | MUX(MOUT_MFC, "mout_mfc" , mfc_p, CLK_SRC, 4, 1), |
130 | MUX(MOUT_AUDIO0, "mout_audio0" , audio0_p, CLK_SRC, 7, 3), |
131 | MUX(MOUT_AUDIO1, "mout_audio1" , audio1_p, CLK_SRC, 10, 3), |
132 | MUX(MOUT_UART, "mout_uart" , uart_p, CLK_SRC, 13, 1), |
133 | MUX(MOUT_SPI0, "mout_spi0" , spi_mmc_p, CLK_SRC, 14, 2), |
134 | MUX(MOUT_SPI1, "mout_spi1" , spi_mmc_p, CLK_SRC, 16, 2), |
135 | MUX(MOUT_MMC0, "mout_mmc0" , spi_mmc_p, CLK_SRC, 18, 2), |
136 | MUX(MOUT_MMC1, "mout_mmc1" , spi_mmc_p, CLK_SRC, 20, 2), |
137 | MUX(MOUT_MMC2, "mout_mmc2" , spi_mmc_p, CLK_SRC, 22, 2), |
138 | }; |
139 | |
140 | /* List of clock muxes present on S3C6400. */ |
141 | MUX_CLOCKS(s3c6400_mux_clks) __initdata = { |
142 | MUX(MOUT_UHOST, "mout_uhost" , uhost_p6400, CLK_SRC, 5, 2), |
143 | MUX(MOUT_IRDA, "mout_irda" , irda_p6400, CLK_SRC, 24, 2), |
144 | MUX(MOUT_LCD, "mout_lcd" , scaler_lcd_p6400, CLK_SRC, 26, 2), |
145 | MUX(MOUT_SCALER, "mout_scaler" , scaler_lcd_p6400, CLK_SRC, 28, 2), |
146 | }; |
147 | |
148 | /* List of clock muxes present on S3C6410. */ |
149 | MUX_CLOCKS(s3c6410_mux_clks) __initdata = { |
150 | MUX(MOUT_UHOST, "mout_uhost" , uhost_p6410, CLK_SRC, 5, 2), |
151 | MUX(MOUT_IRDA, "mout_irda" , irda_p6410, CLK_SRC, 24, 2), |
152 | MUX(MOUT_LCD, "mout_lcd" , scaler_lcd_p6410, CLK_SRC, 26, 2), |
153 | MUX(MOUT_SCALER, "mout_scaler" , scaler_lcd_p6410, CLK_SRC, 28, 2), |
154 | MUX(MOUT_DAC27, "mout_dac27" , clk27_p6410, CLK_SRC, 30, 1), |
155 | MUX(MOUT_TV27, "mout_tv27" , clk27_p6410, CLK_SRC, 31, 1), |
156 | MUX(MOUT_AUDIO2, "mout_audio2" , audio2_p6410, CLK_SRC2, 0, 3), |
157 | }; |
158 | |
159 | /* List of clock dividers present on all S3C64xx SoCs. */ |
160 | DIV_CLOCKS(s3c64xx_div_clks) __initdata = { |
161 | DIV(DOUT_MPLL, "dout_mpll" , "mout_mpll" , CLK_DIV0, 4, 1), |
162 | DIV(HCLKX2, "hclkx2" , "mout_syncmux" , CLK_DIV0, 9, 3), |
163 | DIV(HCLK, "hclk" , "hclkx2" , CLK_DIV0, 8, 1), |
164 | DIV(PCLK, "pclk" , "hclkx2" , CLK_DIV0, 12, 4), |
165 | DIV(DOUT_SECUR, "dout_secur" , "hclkx2" , CLK_DIV0, 18, 2), |
166 | DIV(DOUT_CAM, "dout_cam" , "hclkx2" , CLK_DIV0, 20, 4), |
167 | DIV(DOUT_JPEG, "dout_jpeg" , "hclkx2" , CLK_DIV0, 24, 4), |
168 | DIV(DOUT_MFC, "dout_mfc" , "mout_mfc" , CLK_DIV0, 28, 4), |
169 | DIV(DOUT_MMC0, "dout_mmc0" , "mout_mmc0" , CLK_DIV1, 0, 4), |
170 | DIV(DOUT_MMC1, "dout_mmc1" , "mout_mmc1" , CLK_DIV1, 4, 4), |
171 | DIV(DOUT_MMC2, "dout_mmc2" , "mout_mmc2" , CLK_DIV1, 8, 4), |
172 | DIV(DOUT_LCD, "dout_lcd" , "mout_lcd" , CLK_DIV1, 12, 4), |
173 | DIV(DOUT_SCALER, "dout_scaler" , "mout_scaler" , CLK_DIV1, 16, 4), |
174 | DIV(DOUT_UHOST, "dout_uhost" , "mout_uhost" , CLK_DIV1, 20, 4), |
175 | DIV(DOUT_SPI0, "dout_spi0" , "mout_spi0" , CLK_DIV2, 0, 4), |
176 | DIV(DOUT_SPI1, "dout_spi1" , "mout_spi1" , CLK_DIV2, 4, 4), |
177 | DIV(DOUT_AUDIO0, "dout_audio0" , "mout_audio0" , CLK_DIV2, 8, 4), |
178 | DIV(DOUT_AUDIO1, "dout_audio1" , "mout_audio1" , CLK_DIV2, 12, 4), |
179 | DIV(DOUT_UART, "dout_uart" , "mout_uart" , CLK_DIV2, 16, 4), |
180 | DIV(DOUT_IRDA, "dout_irda" , "mout_irda" , CLK_DIV2, 20, 4), |
181 | }; |
182 | |
183 | /* List of clock dividers present on S3C6400. */ |
184 | DIV_CLOCKS(s3c6400_div_clks) __initdata = { |
185 | DIV(ARMCLK, "armclk" , "mout_apll" , CLK_DIV0, 0, 3), |
186 | }; |
187 | |
188 | /* List of clock dividers present on S3C6410. */ |
189 | DIV_CLOCKS(s3c6410_div_clks) __initdata = { |
190 | DIV(ARMCLK, "armclk" , "mout_apll" , CLK_DIV0, 0, 4), |
191 | DIV(DOUT_FIMC, "dout_fimc" , "hclk" , CLK_DIV1, 24, 4), |
192 | DIV(DOUT_AUDIO2, "dout_audio2" , "mout_audio2" , CLK_DIV2, 24, 4), |
193 | }; |
194 | |
195 | /* List of clock gates present on all S3C64xx SoCs. */ |
196 | GATE_CLOCKS(s3c64xx_gate_clks) __initdata = { |
197 | GATE_BUS(HCLK_UHOST, "hclk_uhost" , "hclk" , HCLK_GATE, 29), |
198 | GATE_BUS(HCLK_SECUR, "hclk_secur" , "hclk" , HCLK_GATE, 28), |
199 | GATE_BUS(HCLK_SDMA1, "hclk_sdma1" , "hclk" , HCLK_GATE, 27), |
200 | GATE_BUS(HCLK_SDMA0, "hclk_sdma0" , "hclk" , HCLK_GATE, 26), |
201 | GATE_ON(HCLK_DDR1, "hclk_ddr1" , "hclk" , HCLK_GATE, 24), |
202 | GATE_BUS(HCLK_USB, "hclk_usb" , "hclk" , HCLK_GATE, 20), |
203 | GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2" , "hclk" , HCLK_GATE, 19), |
204 | GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1" , "hclk" , HCLK_GATE, 18), |
205 | GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0" , "hclk" , HCLK_GATE, 17), |
206 | GATE_BUS(HCLK_MDP, "hclk_mdp" , "hclk" , HCLK_GATE, 16), |
207 | GATE_BUS(HCLK_DHOST, "hclk_dhost" , "hclk" , HCLK_GATE, 15), |
208 | GATE_BUS(HCLK_IHOST, "hclk_ihost" , "hclk" , HCLK_GATE, 14), |
209 | GATE_BUS(HCLK_DMA1, "hclk_dma1" , "hclk" , HCLK_GATE, 13), |
210 | GATE_BUS(HCLK_DMA0, "hclk_dma0" , "hclk" , HCLK_GATE, 12), |
211 | GATE_BUS(HCLK_JPEG, "hclk_jpeg" , "hclk" , HCLK_GATE, 11), |
212 | GATE_BUS(HCLK_CAMIF, "hclk_camif" , "hclk" , HCLK_GATE, 10), |
213 | GATE_BUS(HCLK_SCALER, "hclk_scaler" , "hclk" , HCLK_GATE, 9), |
214 | GATE_BUS(HCLK_2D, "hclk_2d" , "hclk" , HCLK_GATE, 8), |
215 | GATE_BUS(HCLK_TV, "hclk_tv" , "hclk" , HCLK_GATE, 7), |
216 | GATE_BUS(HCLK_POST0, "hclk_post0" , "hclk" , HCLK_GATE, 5), |
217 | GATE_BUS(HCLK_ROT, "hclk_rot" , "hclk" , HCLK_GATE, 4), |
218 | GATE_BUS(HCLK_LCD, "hclk_lcd" , "hclk" , HCLK_GATE, 3), |
219 | GATE_BUS(HCLK_TZIC, "hclk_tzic" , "hclk" , HCLK_GATE, 2), |
220 | GATE_ON(HCLK_INTC, "hclk_intc" , "hclk" , HCLK_GATE, 1), |
221 | GATE_ON(PCLK_SKEY, "pclk_skey" , "pclk" , PCLK_GATE, 24), |
222 | GATE_ON(PCLK_CHIPID, "pclk_chipid" , "pclk" , PCLK_GATE, 23), |
223 | GATE_BUS(PCLK_SPI1, "pclk_spi1" , "pclk" , PCLK_GATE, 22), |
224 | GATE_BUS(PCLK_SPI0, "pclk_spi0" , "pclk" , PCLK_GATE, 21), |
225 | GATE_BUS(PCLK_HSIRX, "pclk_hsirx" , "pclk" , PCLK_GATE, 20), |
226 | GATE_BUS(PCLK_HSITX, "pclk_hsitx" , "pclk" , PCLK_GATE, 19), |
227 | GATE_ON(PCLK_GPIO, "pclk_gpio" , "pclk" , PCLK_GATE, 18), |
228 | GATE_BUS(PCLK_IIC0, "pclk_iic0" , "pclk" , PCLK_GATE, 17), |
229 | GATE_BUS(PCLK_IIS1, "pclk_iis1" , "pclk" , PCLK_GATE, 16), |
230 | GATE_BUS(PCLK_IIS0, "pclk_iis0" , "pclk" , PCLK_GATE, 15), |
231 | GATE_BUS(PCLK_AC97, "pclk_ac97" , "pclk" , PCLK_GATE, 14), |
232 | GATE_BUS(PCLK_TZPC, "pclk_tzpc" , "pclk" , PCLK_GATE, 13), |
233 | GATE_BUS(PCLK_TSADC, "pclk_tsadc" , "pclk" , PCLK_GATE, 12), |
234 | GATE_BUS(PCLK_KEYPAD, "pclk_keypad" , "pclk" , PCLK_GATE, 11), |
235 | GATE_BUS(PCLK_IRDA, "pclk_irda" , "pclk" , PCLK_GATE, 10), |
236 | GATE_BUS(PCLK_PCM1, "pclk_pcm1" , "pclk" , PCLK_GATE, 9), |
237 | GATE_BUS(PCLK_PCM0, "pclk_pcm0" , "pclk" , PCLK_GATE, 8), |
238 | GATE_BUS(PCLK_PWM, "pclk_pwm" , "pclk" , PCLK_GATE, 7), |
239 | GATE_BUS(PCLK_RTC, "pclk_rtc" , "pclk" , PCLK_GATE, 6), |
240 | GATE_BUS(PCLK_WDT, "pclk_wdt" , "pclk" , PCLK_GATE, 5), |
241 | GATE_BUS(PCLK_UART3, "pclk_uart3" , "pclk" , PCLK_GATE, 4), |
242 | GATE_BUS(PCLK_UART2, "pclk_uart2" , "pclk" , PCLK_GATE, 3), |
243 | GATE_BUS(PCLK_UART1, "pclk_uart1" , "pclk" , PCLK_GATE, 2), |
244 | GATE_BUS(PCLK_UART0, "pclk_uart0" , "pclk" , PCLK_GATE, 1), |
245 | GATE_BUS(PCLK_MFC, "pclk_mfc" , "pclk" , PCLK_GATE, 0), |
246 | GATE_SCLK(SCLK_UHOST, "sclk_uhost" , "dout_uhost" , SCLK_GATE, 30), |
247 | GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48" , "clk48m" , SCLK_GATE, 29), |
248 | GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48" , "clk48m" , SCLK_GATE, 28), |
249 | GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48" , "clk48m" , SCLK_GATE, 27), |
250 | GATE_SCLK(SCLK_MMC2, "sclk_mmc2" , "dout_mmc2" , SCLK_GATE, 26), |
251 | GATE_SCLK(SCLK_MMC1, "sclk_mmc1" , "dout_mmc1" , SCLK_GATE, 25), |
252 | GATE_SCLK(SCLK_MMC0, "sclk_mmc0" , "dout_mmc0" , SCLK_GATE, 24), |
253 | GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48" , "clk48m" , SCLK_GATE, 23), |
254 | GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48" , "clk48m" , SCLK_GATE, 22), |
255 | GATE_SCLK(SCLK_SPI1, "sclk_spi1" , "dout_spi1" , SCLK_GATE, 21), |
256 | GATE_SCLK(SCLK_SPI0, "sclk_spi0" , "dout_spi0" , SCLK_GATE, 20), |
257 | GATE_SCLK(SCLK_DAC27, "sclk_dac27" , "mout_dac27" , SCLK_GATE, 19), |
258 | GATE_SCLK(SCLK_TV27, "sclk_tv27" , "mout_tv27" , SCLK_GATE, 18), |
259 | GATE_SCLK(SCLK_SCALER27, "sclk_scaler27" , "clk27m" , SCLK_GATE, 17), |
260 | GATE_SCLK(SCLK_SCALER, "sclk_scaler" , "dout_scaler" , SCLK_GATE, 16), |
261 | GATE_SCLK(SCLK_LCD27, "sclk_lcd27" , "clk27m" , SCLK_GATE, 15), |
262 | GATE_SCLK(SCLK_LCD, "sclk_lcd" , "dout_lcd" , SCLK_GATE, 14), |
263 | GATE_SCLK(SCLK_POST0_27, "sclk_post0_27" , "clk27m" , SCLK_GATE, 12), |
264 | GATE_SCLK(SCLK_POST0, "sclk_post0" , "dout_lcd" , SCLK_GATE, 10), |
265 | GATE_SCLK(SCLK_AUDIO1, "sclk_audio1" , "dout_audio1" , SCLK_GATE, 9), |
266 | GATE_SCLK(SCLK_AUDIO0, "sclk_audio0" , "dout_audio0" , SCLK_GATE, 8), |
267 | GATE_SCLK(SCLK_SECUR, "sclk_secur" , "dout_secur" , SCLK_GATE, 7), |
268 | GATE_SCLK(SCLK_IRDA, "sclk_irda" , "dout_irda" , SCLK_GATE, 6), |
269 | GATE_SCLK(SCLK_UART, "sclk_uart" , "dout_uart" , SCLK_GATE, 5), |
270 | GATE_SCLK(SCLK_MFC, "sclk_mfc" , "dout_mfc" , SCLK_GATE, 3), |
271 | GATE_SCLK(SCLK_CAM, "sclk_cam" , "dout_cam" , SCLK_GATE, 2), |
272 | GATE_SCLK(SCLK_JPEG, "sclk_jpeg" , "dout_jpeg" , SCLK_GATE, 1), |
273 | }; |
274 | |
275 | /* List of clock gates present on S3C6400. */ |
276 | GATE_CLOCKS(s3c6400_gate_clks) __initdata = { |
277 | GATE_ON(HCLK_DDR0, "hclk_ddr0" , "hclk" , HCLK_GATE, 23), |
278 | GATE_SCLK(SCLK_ONENAND, "sclk_onenand" , "parent" , SCLK_GATE, 4), |
279 | }; |
280 | |
281 | /* List of clock gates present on S3C6410. */ |
282 | GATE_CLOCKS(s3c6410_gate_clks) __initdata = { |
283 | GATE_BUS(HCLK_3DSE, "hclk_3dse" , "hclk" , HCLK_GATE, 31), |
284 | GATE_ON(HCLK_IROM, "hclk_irom" , "hclk" , HCLK_GATE, 25), |
285 | GATE_ON(HCLK_MEM1, "hclk_mem1" , "hclk" , HCLK_GATE, 22), |
286 | GATE_ON(HCLK_MEM0, "hclk_mem0" , "hclk" , HCLK_GATE, 21), |
287 | GATE_BUS(HCLK_MFC, "hclk_mfc" , "hclk" , HCLK_GATE, 0), |
288 | GATE_BUS(PCLK_IIC1, "pclk_iic1" , "pclk" , PCLK_GATE, 27), |
289 | GATE_BUS(PCLK_IIS2, "pclk_iis2" , "pclk" , PCLK_GATE, 26), |
290 | GATE_SCLK(SCLK_FIMC, "sclk_fimc" , "dout_fimc" , SCLK_GATE, 13), |
291 | GATE_SCLK(SCLK_AUDIO2, "sclk_audio2" , "dout_audio2" , SCLK_GATE, 11), |
292 | GATE_BUS(MEM0_CFCON, "mem0_cfcon" , "hclk_mem0" , MEM0_GATE, 5), |
293 | GATE_BUS(MEM0_ONENAND1, "mem0_onenand1" , "hclk_mem0" , MEM0_GATE, 4), |
294 | GATE_BUS(MEM0_ONENAND0, "mem0_onenand0" , "hclk_mem0" , MEM0_GATE, 3), |
295 | GATE_BUS(MEM0_NFCON, "mem0_nfcon" , "hclk_mem0" , MEM0_GATE, 2), |
296 | GATE_ON(MEM0_SROM, "mem0_srom" , "hclk_mem0" , MEM0_GATE, 1), |
297 | }; |
298 | |
299 | /* List of PLL clocks. */ |
300 | static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = { |
301 | PLL(pll_6552, FOUT_APLL, "fout_apll" , "fin_pll" , |
302 | APLL_LOCK, APLL_CON, NULL), |
303 | PLL(pll_6552, FOUT_MPLL, "fout_mpll" , "fin_pll" , |
304 | MPLL_LOCK, MPLL_CON, NULL), |
305 | PLL(pll_6553, FOUT_EPLL, "fout_epll" , "fin_pll" , |
306 | EPLL_LOCK, EPLL_CON0, NULL), |
307 | }; |
308 | |
309 | /* Aliases for common s3c64xx clocks. */ |
310 | static struct samsung_clock_alias s3c64xx_clock_aliases[] = { |
311 | ALIAS(FOUT_APLL, NULL, "fout_apll" ), |
312 | ALIAS(FOUT_MPLL, NULL, "fout_mpll" ), |
313 | ALIAS(FOUT_EPLL, NULL, "fout_epll" ), |
314 | ALIAS(MOUT_EPLL, NULL, "mout_epll" ), |
315 | ALIAS(DOUT_MPLL, NULL, "dout_mpll" ), |
316 | ALIAS(HCLKX2, NULL, "hclk2" ), |
317 | ALIAS(HCLK, NULL, "hclk" ), |
318 | ALIAS(PCLK, NULL, "pclk" ), |
319 | ALIAS(PCLK, NULL, "clk_uart_baud2" ), |
320 | ALIAS(ARMCLK, NULL, "armclk" ), |
321 | ALIAS(HCLK_UHOST, "s3c2410-ohci" , "usb-host" ), |
322 | ALIAS(HCLK_USB, "s3c-hsotg" , "otg" ), |
323 | ALIAS(HCLK_HSMMC2, "s3c-sdhci.2" , "hsmmc" ), |
324 | ALIAS(HCLK_HSMMC2, "s3c-sdhci.2" , "mmc_busclk.0" ), |
325 | ALIAS(HCLK_HSMMC1, "s3c-sdhci.1" , "hsmmc" ), |
326 | ALIAS(HCLK_HSMMC1, "s3c-sdhci.1" , "mmc_busclk.0" ), |
327 | ALIAS(HCLK_HSMMC0, "s3c-sdhci.0" , "hsmmc" ), |
328 | ALIAS(HCLK_HSMMC0, "s3c-sdhci.0" , "mmc_busclk.0" ), |
329 | ALIAS(HCLK_DMA1, "dma-pl080s.1" , "apb_pclk" ), |
330 | ALIAS(HCLK_DMA0, "dma-pl080s.0" , "apb_pclk" ), |
331 | ALIAS(HCLK_CAMIF, "s3c-camif" , "camif" ), |
332 | ALIAS(HCLK_LCD, "s3c-fb" , "lcd" ), |
333 | ALIAS(PCLK_SPI1, "s3c6410-spi.1" , "spi" ), |
334 | ALIAS(PCLK_SPI0, "s3c6410-spi.0" , "spi" ), |
335 | ALIAS(PCLK_IIC0, "s3c2440-i2c.0" , "i2c" ), |
336 | ALIAS(PCLK_IIS1, "samsung-i2s.1" , "iis" ), |
337 | ALIAS(PCLK_IIS0, "samsung-i2s.0" , "iis" ), |
338 | ALIAS(PCLK_AC97, "samsung-ac97" , "ac97" ), |
339 | ALIAS(PCLK_TSADC, "s3c64xx-adc" , "adc" ), |
340 | ALIAS(PCLK_KEYPAD, "samsung-keypad" , "keypad" ), |
341 | ALIAS(PCLK_PCM1, "samsung-pcm.1" , "pcm" ), |
342 | ALIAS(PCLK_PCM0, "samsung-pcm.0" , "pcm" ), |
343 | ALIAS(PCLK_PWM, NULL, "timers" ), |
344 | ALIAS(PCLK_RTC, "s3c64xx-rtc" , "rtc" ), |
345 | ALIAS(PCLK_WDT, NULL, "watchdog" ), |
346 | ALIAS(PCLK_UART3, "s3c6400-uart.3" , "uart" ), |
347 | ALIAS(PCLK_UART2, "s3c6400-uart.2" , "uart" ), |
348 | ALIAS(PCLK_UART1, "s3c6400-uart.1" , "uart" ), |
349 | ALIAS(PCLK_UART0, "s3c6400-uart.0" , "uart" ), |
350 | ALIAS(SCLK_UHOST, "s3c2410-ohci" , "usb-bus-host" ), |
351 | ALIAS(SCLK_MMC2, "s3c-sdhci.2" , "mmc_busclk.2" ), |
352 | ALIAS(SCLK_MMC1, "s3c-sdhci.1" , "mmc_busclk.2" ), |
353 | ALIAS(SCLK_MMC0, "s3c-sdhci.0" , "mmc_busclk.2" ), |
354 | ALIAS(PCLK_SPI1, "s3c6410-spi.1" , "spi_busclk0" ), |
355 | ALIAS(SCLK_SPI1, "s3c6410-spi.1" , "spi_busclk2" ), |
356 | ALIAS(PCLK_SPI0, "s3c6410-spi.0" , "spi_busclk0" ), |
357 | ALIAS(SCLK_SPI0, "s3c6410-spi.0" , "spi_busclk2" ), |
358 | ALIAS(SCLK_AUDIO1, "samsung-pcm.1" , "audio-bus" ), |
359 | ALIAS(SCLK_AUDIO1, "samsung-i2s.1" , "audio-bus" ), |
360 | ALIAS(SCLK_AUDIO0, "samsung-pcm.0" , "audio-bus" ), |
361 | ALIAS(SCLK_AUDIO0, "samsung-i2s.0" , "audio-bus" ), |
362 | ALIAS(SCLK_UART, NULL, "clk_uart_baud3" ), |
363 | ALIAS(SCLK_CAM, "s3c-camif" , "camera" ), |
364 | }; |
365 | |
366 | /* Aliases for s3c6400-specific clocks. */ |
367 | static struct samsung_clock_alias s3c6400_clock_aliases[] = { |
368 | /* Nothing to place here yet. */ |
369 | }; |
370 | |
371 | /* Aliases for s3c6410-specific clocks. */ |
372 | static struct samsung_clock_alias s3c6410_clock_aliases[] = { |
373 | ALIAS(PCLK_IIC1, "s3c2440-i2c.1" , "i2c" ), |
374 | ALIAS(PCLK_IIS2, "samsung-i2s.2" , "iis" ), |
375 | ALIAS(SCLK_FIMC, "s3c-camif" , "fimc" ), |
376 | ALIAS(SCLK_AUDIO2, "samsung-i2s.2" , "audio-bus" ), |
377 | ALIAS(MEM0_SROM, NULL, "srom" ), |
378 | }; |
379 | |
380 | static void __init s3c64xx_clk_register_fixed_ext( |
381 | struct samsung_clk_provider *ctx, |
382 | unsigned long fin_pll_f, |
383 | unsigned long xusbxti_f) |
384 | { |
385 | s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; |
386 | s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; |
387 | samsung_clk_register_fixed_rate(ctx, clk_list: s3c64xx_fixed_rate_ext_clks, |
388 | ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); |
389 | } |
390 | |
391 | /* Register s3c64xx clocks. */ |
392 | void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, |
393 | unsigned long xusbxti_f, bool s3c6400, |
394 | void __iomem *base) |
395 | { |
396 | struct samsung_clk_provider *ctx; |
397 | struct clk_hw **hws; |
398 | |
399 | reg_base = base; |
400 | is_s3c6400 = s3c6400; |
401 | |
402 | if (np) { |
403 | reg_base = of_iomap(node: np, index: 0); |
404 | if (!reg_base) |
405 | panic(fmt: "%s: failed to map registers\n" , __func__); |
406 | } |
407 | |
408 | ctx = samsung_clk_init(NULL, base: reg_base, NR_CLKS); |
409 | hws = ctx->clk_data.hws; |
410 | |
411 | /* Register external clocks. */ |
412 | if (!np) |
413 | s3c64xx_clk_register_fixed_ext(ctx, fin_pll_f: xtal_f, xusbxti_f); |
414 | |
415 | /* Register PLLs. */ |
416 | samsung_clk_register_pll(ctx, pll_list: s3c64xx_pll_clks, |
417 | ARRAY_SIZE(s3c64xx_pll_clks)); |
418 | |
419 | /* Register common internal clocks. */ |
420 | samsung_clk_register_fixed_rate(ctx, clk_list: s3c64xx_fixed_rate_clks, |
421 | ARRAY_SIZE(s3c64xx_fixed_rate_clks)); |
422 | samsung_clk_register_mux(ctx, clk_list: s3c64xx_mux_clks, |
423 | ARRAY_SIZE(s3c64xx_mux_clks)); |
424 | samsung_clk_register_div(ctx, clk_list: s3c64xx_div_clks, |
425 | ARRAY_SIZE(s3c64xx_div_clks)); |
426 | samsung_clk_register_gate(ctx, clk_list: s3c64xx_gate_clks, |
427 | ARRAY_SIZE(s3c64xx_gate_clks)); |
428 | |
429 | /* Register SoC-specific clocks. */ |
430 | if (is_s3c6400) { |
431 | samsung_clk_register_mux(ctx, clk_list: s3c6400_mux_clks, |
432 | ARRAY_SIZE(s3c6400_mux_clks)); |
433 | samsung_clk_register_div(ctx, clk_list: s3c6400_div_clks, |
434 | ARRAY_SIZE(s3c6400_div_clks)); |
435 | samsung_clk_register_gate(ctx, clk_list: s3c6400_gate_clks, |
436 | ARRAY_SIZE(s3c6400_gate_clks)); |
437 | samsung_clk_register_alias(ctx, list: s3c6400_clock_aliases, |
438 | ARRAY_SIZE(s3c6400_clock_aliases)); |
439 | } else { |
440 | samsung_clk_register_mux(ctx, clk_list: s3c6410_mux_clks, |
441 | ARRAY_SIZE(s3c6410_mux_clks)); |
442 | samsung_clk_register_div(ctx, clk_list: s3c6410_div_clks, |
443 | ARRAY_SIZE(s3c6410_div_clks)); |
444 | samsung_clk_register_gate(ctx, clk_list: s3c6410_gate_clks, |
445 | ARRAY_SIZE(s3c6410_gate_clks)); |
446 | samsung_clk_register_alias(ctx, list: s3c6410_clock_aliases, |
447 | ARRAY_SIZE(s3c6410_clock_aliases)); |
448 | } |
449 | |
450 | samsung_clk_register_alias(ctx, list: s3c64xx_clock_aliases, |
451 | ARRAY_SIZE(s3c64xx_clock_aliases)); |
452 | |
453 | samsung_clk_sleep_init(reg_base, s3c64xx_clk_regs, |
454 | ARRAY_SIZE(s3c64xx_clk_regs)); |
455 | if (!is_s3c6400) |
456 | samsung_clk_sleep_init(reg_base, s3c6410_clk_regs, |
457 | ARRAY_SIZE(s3c6410_clk_regs)); |
458 | |
459 | samsung_clk_of_add_provider(np, ctx); |
460 | |
461 | pr_info("%s clocks: apll = %lu, mpll = %lu\n" |
462 | "\tepll = %lu, arm_clk = %lu\n" , |
463 | is_s3c6400 ? "S3C6400" : "S3C6410" , |
464 | clk_hw_get_rate(hws[MOUT_APLL]), |
465 | clk_hw_get_rate(hws[MOUT_MPLL]), |
466 | clk_hw_get_rate(hws[MOUT_EPLL]), |
467 | clk_hw_get_rate(hws[ARMCLK])); |
468 | } |
469 | |
470 | static void __init s3c6400_clk_init(struct device_node *np) |
471 | { |
472 | s3c64xx_clk_init(np, xtal_f: 0, xusbxti_f: 0, s3c6400: true, NULL); |
473 | } |
474 | CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock" , s3c6400_clk_init); |
475 | |
476 | static void __init s3c6410_clk_init(struct device_node *np) |
477 | { |
478 | s3c64xx_clk_init(np, xtal_f: 0, xusbxti_f: 0, s3c6400: false, NULL); |
479 | } |
480 | CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock" , s3c6410_clk_init); |
481 | |