]>
Commit | Line | Data |
---|---|---|
4ca28e98 GB |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright(C) 2019 | |
4 | * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com> | |
5 | */ | |
6 | ||
d678a59d | 7 | #include <common.h> |
4ca28e98 GB |
8 | #include <clk.h> |
9 | #include <clk-uclass.h> | |
10 | #include <dm.h> | |
f7ae49fc | 11 | #include <log.h> |
4ca28e98 GB |
12 | #include <asm/arch/clock.h> |
13 | #include <asm/arch/imx-regs.h> | |
14 | #include <dt-bindings/clock/imxrt1050-clock.h> | |
15 | ||
16 | #include "clk.h" | |
17 | ||
4ca28e98 GB |
18 | static const char * const pll_ref_sels[] = {"osc", "dummy", }; |
19 | static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", }; | |
20 | static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", }; | |
21 | static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", }; | |
22 | static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", }; | |
23 | ||
24 | static const char *const pre_periph_sels[] = { "pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", }; | |
25 | static const char *const periph_sels[] = { "pre_periph_sel", "todo", }; | |
26 | static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; | |
27 | static const char *const lpuart_sels[] = { "pll3_80m", "osc", }; | |
28 | static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", }; | |
29 | static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", }; | |
d303f9c3 | 30 | static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"}; |
4ca28e98 GB |
31 | |
32 | static int imxrt1050_clk_probe(struct udevice *dev) | |
33 | { | |
34 | void *base; | |
35 | ||
36 | /* Anatop clocks */ | |
a2d6fbf5 | 37 | base = (void *)ofnode_get_addr(ofnode_by_compatible(ofnode_null(), "fsl,imxrt-anatop")); |
4ca28e98 GB |
38 | |
39 | clk_dm(IMXRT1050_CLK_PLL1_REF_SEL, | |
40 | imx_clk_mux("pll1_arm_ref_sel", base + 0x0, 14, 2, | |
41 | pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); | |
42 | clk_dm(IMXRT1050_CLK_PLL2_REF_SEL, | |
43 | imx_clk_mux("pll2_sys_ref_sel", base + 0x30, 14, 2, | |
44 | pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); | |
45 | clk_dm(IMXRT1050_CLK_PLL3_REF_SEL, | |
46 | imx_clk_mux("pll3_usb_otg_ref_sel", base + 0x10, 14, 2, | |
47 | pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); | |
48 | clk_dm(IMXRT1050_CLK_PLL5_REF_SEL, | |
49 | imx_clk_mux("pll5_video_ref_sel", base + 0xa0, 14, 2, | |
50 | pll_ref_sels, ARRAY_SIZE(pll_ref_sels))); | |
51 | ||
52 | clk_dm(IMXRT1050_CLK_PLL1_ARM, | |
53 | imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_arm", "pll1_arm_ref_sel", | |
54 | base + 0x0, 0x7f)); | |
55 | clk_dm(IMXRT1050_CLK_PLL2_SYS, | |
56 | imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_sys", "pll2_sys_ref_sel", | |
57 | base + 0x30, 0x1)); | |
58 | clk_dm(IMXRT1050_CLK_PLL3_USB_OTG, | |
59 | imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", | |
60 | "pll3_usb_otg_ref_sel", | |
61 | base + 0x10, 0x1)); | |
62 | clk_dm(IMXRT1050_CLK_PLL5_VIDEO, | |
63 | imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "pll5_video_ref_sel", | |
64 | base + 0xa0, 0x7f)); | |
65 | ||
66 | /* PLL bypass out */ | |
67 | clk_dm(IMXRT1050_CLK_PLL1_BYPASS, | |
68 | imx_clk_mux_flags("pll1_bypass", base + 0x0, 16, 1, | |
69 | pll1_bypass_sels, | |
70 | ARRAY_SIZE(pll1_bypass_sels), | |
71 | CLK_SET_RATE_PARENT)); | |
72 | clk_dm(IMXRT1050_CLK_PLL2_BYPASS, | |
73 | imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, | |
74 | pll2_bypass_sels, | |
75 | ARRAY_SIZE(pll2_bypass_sels), | |
76 | CLK_SET_RATE_PARENT)); | |
77 | clk_dm(IMXRT1050_CLK_PLL3_BYPASS, | |
78 | imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, | |
79 | pll3_bypass_sels, | |
80 | ARRAY_SIZE(pll3_bypass_sels), | |
81 | CLK_SET_RATE_PARENT)); | |
82 | clk_dm(IMXRT1050_CLK_PLL5_BYPASS, | |
83 | imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1, | |
84 | pll5_bypass_sels, | |
85 | ARRAY_SIZE(pll5_bypass_sels), | |
86 | CLK_SET_RATE_PARENT)); | |
87 | ||
88 | clk_dm(IMXRT1050_CLK_VIDEO_POST_DIV_SEL, | |
89 | imx_clk_divider("video_post_div_sel", "pll5_video", | |
90 | base + 0xa0, 19, 2)); | |
91 | clk_dm(IMXRT1050_CLK_VIDEO_DIV, | |
92 | imx_clk_divider("video_div", "video_post_div_sel", | |
93 | base + 0x170, 30, 2)); | |
94 | ||
95 | clk_dm(IMXRT1050_CLK_PLL3_80M, | |
96 | imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6)); | |
97 | ||
98 | clk_dm(IMXRT1050_CLK_PLL2_PFD0_352M, | |
99 | imx_clk_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0)); | |
100 | clk_dm(IMXRT1050_CLK_PLL2_PFD1_594M, | |
101 | imx_clk_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1)); | |
102 | clk_dm(IMXRT1050_CLK_PLL2_PFD2_396M, | |
103 | imx_clk_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2)); | |
104 | clk_dm(IMXRT1050_CLK_PLL3_PFD1_664_62M, | |
105 | imx_clk_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, | |
106 | 1)); | |
107 | clk_dm(IMXRT1050_CLK_PLL3_PFD3_454_74M, | |
108 | imx_clk_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, | |
109 | 3)); | |
110 | ||
111 | /* CCM clocks */ | |
112 | base = dev_read_addr_ptr(dev); | |
113 | if (base == (void *)FDT_ADDR_T_NONE) | |
114 | return -EINVAL; | |
115 | ||
116 | clk_dm(IMXRT1050_CLK_ARM_PODF, | |
117 | imx_clk_divider("arm_podf", "pll1_arm", | |
118 | base + 0x10, 0, 3)); | |
119 | ||
120 | clk_dm(IMXRT1050_CLK_PRE_PERIPH_SEL, | |
121 | imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, | |
122 | pre_periph_sels, ARRAY_SIZE(pre_periph_sels))); | |
123 | clk_dm(IMXRT1050_CLK_PERIPH_SEL, | |
124 | imx_clk_mux("periph_sel", base + 0x14, 25, 1, | |
125 | periph_sels, ARRAY_SIZE(periph_sels))); | |
126 | clk_dm(IMXRT1050_CLK_USDHC1_SEL, | |
127 | imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, | |
128 | usdhc_sels, ARRAY_SIZE(usdhc_sels))); | |
129 | clk_dm(IMXRT1050_CLK_USDHC2_SEL, | |
130 | imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, | |
131 | usdhc_sels, ARRAY_SIZE(usdhc_sels))); | |
132 | clk_dm(IMXRT1050_CLK_LPUART_SEL, | |
133 | imx_clk_mux("lpuart_sel", base + 0x24, 6, 1, | |
134 | lpuart_sels, ARRAY_SIZE(lpuart_sels))); | |
135 | clk_dm(IMXRT1050_CLK_SEMC_ALT_SEL, | |
136 | imx_clk_mux("semc_alt_sel", base + 0x14, 7, 1, | |
137 | semc_alt_sels, ARRAY_SIZE(semc_alt_sels))); | |
138 | clk_dm(IMXRT1050_CLK_SEMC_SEL, | |
139 | imx_clk_mux("semc_sel", base + 0x14, 6, 1, | |
140 | semc_sels, ARRAY_SIZE(semc_sels))); | |
141 | clk_dm(IMXRT1050_CLK_LCDIF_SEL, | |
142 | imx_clk_mux("lcdif_sel", base + 0x38, 15, 3, | |
143 | lcdif_sels, ARRAY_SIZE(lcdif_sels))); | |
144 | ||
145 | clk_dm(IMXRT1050_CLK_AHB_PODF, | |
146 | imx_clk_divider("ahb_podf", "periph_sel", | |
147 | base + 0x14, 10, 3)); | |
148 | clk_dm(IMXRT1050_CLK_USDHC1_PODF, | |
149 | imx_clk_divider("usdhc1_podf", "usdhc1_sel", | |
150 | base + 0x24, 11, 3)); | |
151 | clk_dm(IMXRT1050_CLK_USDHC2_PODF, | |
152 | imx_clk_divider("usdhc2_podf", "usdhc2_sel", | |
153 | base + 0x24, 16, 3)); | |
154 | clk_dm(IMXRT1050_CLK_LPUART_PODF, | |
155 | imx_clk_divider("lpuart_podf", "lpuart_sel", | |
156 | base + 0x24, 0, 6)); | |
157 | clk_dm(IMXRT1050_CLK_SEMC_PODF, | |
158 | imx_clk_divider("semc_podf", "semc_sel", | |
159 | base + 0x14, 16, 3)); | |
160 | clk_dm(IMXRT1050_CLK_LCDIF_PRED, | |
161 | imx_clk_divider("lcdif_pred", "lcdif_sel", | |
162 | base + 0x38, 12, 3)); | |
163 | clk_dm(IMXRT1050_CLK_LCDIF_PODF, | |
164 | imx_clk_divider("lcdif_podf", "lcdif_pred", | |
165 | base + 0x18, 23, 3)); | |
166 | ||
167 | clk_dm(IMXRT1050_CLK_USDHC1, | |
168 | imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2)); | |
169 | clk_dm(IMXRT1050_CLK_USDHC2, | |
170 | imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4)); | |
171 | clk_dm(IMXRT1050_CLK_LPUART1, | |
172 | imx_clk_gate2("lpuart1", "lpuart_podf", base + 0x7c, 24)); | |
173 | clk_dm(IMXRT1050_CLK_SEMC, | |
174 | imx_clk_gate2("semc", "semc_podf", base + 0x74, 4)); | |
f544dfec GB |
175 | clk_dm(IMXRT1050_CLK_LCDIF_APB, |
176 | imx_clk_gate2("lcdif", "lcdif_podf", base + 0x70, 28)); | |
177 | clk_dm(IMXRT1050_CLK_LCDIF_PIX, | |
178 | imx_clk_gate2("lcdif_pix", "lcdif", base + 0x74, 10)); | |
45a5f76c GB |
179 | clk_dm(IMXRT1050_CLK_USBOH3, |
180 | imx_clk_gate2("usboh3", "pll3_usb_otg", base + 0x80, 0)); | |
4ca28e98 | 181 | |
4ca28e98 GB |
182 | struct clk *clk, *clk1; |
183 | ||
caac71b7 | 184 | #ifdef CONFIG_SPL_BUILD |
4ca28e98 GB |
185 | /* bypass pll1 before setting its rate */ |
186 | clk_get_by_id(IMXRT1050_CLK_PLL1_REF_SEL, &clk); | |
187 | clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1); | |
188 | clk_set_parent(clk1, clk); | |
189 | ||
190 | clk_get_by_id(IMXRT1050_CLK_PLL1_ARM, &clk); | |
191 | clk_enable(clk); | |
192 | clk_set_rate(clk, 1056000000UL); | |
193 | ||
194 | clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1); | |
195 | clk_set_parent(clk1, clk); | |
196 | ||
197 | clk_get_by_id(IMXRT1050_CLK_SEMC_SEL, &clk1); | |
198 | clk_get_by_id(IMXRT1050_CLK_SEMC_ALT_SEL, &clk); | |
199 | clk_set_parent(clk1, clk); | |
200 | ||
201 | clk_get_by_id(IMXRT1050_CLK_PLL2_SYS, &clk); | |
202 | clk_enable(clk); | |
203 | clk_set_rate(clk, 528000000UL); | |
204 | ||
205 | clk_get_by_id(IMXRT1050_CLK_PLL2_BYPASS, &clk1); | |
206 | clk_set_parent(clk1, clk); | |
207 | ||
208 | /* Configure PLL3_USB_OTG to 480MHz */ | |
209 | clk_get_by_id(IMXRT1050_CLK_PLL3_USB_OTG, &clk); | |
210 | clk_enable(clk); | |
211 | clk_set_rate(clk, 480000000UL); | |
212 | ||
213 | clk_get_by_id(IMXRT1050_CLK_PLL3_BYPASS, &clk1); | |
214 | clk_set_parent(clk1, clk); | |
caac71b7 GB |
215 | #else |
216 | /* Set PLL5 for LCDIF to its default 650Mhz */ | |
217 | clk_get_by_id(IMXRT1050_CLK_PLL5_VIDEO, &clk); | |
218 | clk_enable(clk); | |
219 | clk_set_rate(clk, 650000000UL); | |
4ca28e98 | 220 | |
caac71b7 GB |
221 | clk_get_by_id(IMXRT1050_CLK_PLL5_BYPASS, &clk1); |
222 | clk_set_parent(clk1, clk); | |
4ca28e98 GB |
223 | #endif |
224 | ||
225 | return 0; | |
226 | } | |
227 | ||
228 | static const struct udevice_id imxrt1050_clk_ids[] = { | |
229 | { .compatible = "fsl,imxrt1050-ccm" }, | |
230 | { }, | |
231 | }; | |
232 | ||
233 | U_BOOT_DRIVER(imxrt1050_clk) = { | |
234 | .name = "clk_imxrt1050", | |
235 | .id = UCLASS_CLK, | |
236 | .of_match = imxrt1050_clk_ids, | |
682e73d2 | 237 | .ops = &ccf_clk_ops, |
4ca28e98 GB |
238 | .probe = imxrt1050_clk_probe, |
239 | .flags = DM_FLAG_PRE_RELOC, | |
240 | }; |