clk: imx: clk-imxrt1050: setup PLL5 for video in non-SPL
[oweals/u-boot.git] / drivers / clk / imx / clk-imxrt1050.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright(C) 2019
4  * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com>
5  */
6
7 #include <common.h>
8 #include <clk.h>
9 #include <clk-uclass.h>
10 #include <dm.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/imx-regs.h>
13 #include <dt-bindings/clock/imxrt1050-clock.h>
14
15 #include "clk.h"
16
17 static ulong imxrt1050_clk_get_rate(struct clk *clk)
18 {
19         struct clk *c;
20         int ret;
21
22         debug("%s(#%lu)\n", __func__, clk->id);
23
24         ret = clk_get_by_id(clk->id, &c);
25         if (ret)
26                 return ret;
27
28         return clk_get_rate(c);
29 }
30
31 static ulong imxrt1050_clk_set_rate(struct clk *clk, ulong rate)
32 {
33         struct clk *c;
34         int ret;
35
36         debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
37
38         ret = clk_get_by_id(clk->id, &c);
39         if (ret)
40                 return ret;
41
42         return clk_set_rate(c, rate);
43 }
44
45 static int __imxrt1050_clk_enable(struct clk *clk, bool enable)
46 {
47         struct clk *c;
48         int ret;
49
50         debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
51
52         ret = clk_get_by_id(clk->id, &c);
53         if (ret)
54                 return ret;
55
56         if (enable)
57                 ret = clk_enable(c);
58         else
59                 ret = clk_disable(c);
60
61         return ret;
62 }
63
64 static int imxrt1050_clk_disable(struct clk *clk)
65 {
66         return __imxrt1050_clk_enable(clk, 0);
67 }
68
69 static int imxrt1050_clk_enable(struct clk *clk)
70 {
71         return __imxrt1050_clk_enable(clk, 1);
72 }
73
74 static struct clk_ops imxrt1050_clk_ops = {
75         .set_rate = imxrt1050_clk_set_rate,
76         .get_rate = imxrt1050_clk_get_rate,
77         .enable = imxrt1050_clk_enable,
78         .disable = imxrt1050_clk_disable,
79 };
80
81 static const char * const pll_ref_sels[] = {"osc", "dummy", };
82 static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
83 static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
84 static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", };
85 static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", };
86
87 static const char *const pre_periph_sels[] = { "pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", };
88 static const char *const periph_sels[] = { "pre_periph_sel", "todo", };
89 static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
90 static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
91 static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
92 static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
93 static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"};
94
95 static int imxrt1050_clk_probe(struct udevice *dev)
96 {
97         void *base;
98
99         /* Anatop clocks */
100         base = (void *)ANATOP_BASE_ADDR;
101
102         clk_dm(IMXRT1050_CLK_PLL1_REF_SEL,
103                imx_clk_mux("pll1_arm_ref_sel", base + 0x0, 14, 2,
104                            pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
105         clk_dm(IMXRT1050_CLK_PLL2_REF_SEL,
106                imx_clk_mux("pll2_sys_ref_sel", base + 0x30, 14, 2,
107                            pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
108         clk_dm(IMXRT1050_CLK_PLL3_REF_SEL,
109                imx_clk_mux("pll3_usb_otg_ref_sel", base + 0x10, 14, 2,
110                            pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
111         clk_dm(IMXRT1050_CLK_PLL5_REF_SEL,
112                imx_clk_mux("pll5_video_ref_sel", base + 0xa0, 14, 2,
113                            pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
114
115         clk_dm(IMXRT1050_CLK_PLL1_ARM,
116                imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_arm", "pll1_arm_ref_sel",
117                              base + 0x0, 0x7f));
118         clk_dm(IMXRT1050_CLK_PLL2_SYS,
119                imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_sys", "pll2_sys_ref_sel",
120                              base + 0x30, 0x1));
121         clk_dm(IMXRT1050_CLK_PLL3_USB_OTG,
122                imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg",
123                              "pll3_usb_otg_ref_sel",
124                              base + 0x10, 0x1));
125         clk_dm(IMXRT1050_CLK_PLL5_VIDEO,
126                imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "pll5_video_ref_sel",
127                              base + 0xa0, 0x7f));
128
129         /* PLL bypass out */
130         clk_dm(IMXRT1050_CLK_PLL1_BYPASS,
131                imx_clk_mux_flags("pll1_bypass", base + 0x0, 16, 1,
132                                  pll1_bypass_sels,
133                                  ARRAY_SIZE(pll1_bypass_sels),
134                                  CLK_SET_RATE_PARENT));
135         clk_dm(IMXRT1050_CLK_PLL2_BYPASS,
136                imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1,
137                                  pll2_bypass_sels,
138                                  ARRAY_SIZE(pll2_bypass_sels),
139                                  CLK_SET_RATE_PARENT));
140         clk_dm(IMXRT1050_CLK_PLL3_BYPASS,
141                imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1,
142                                  pll3_bypass_sels,
143                                  ARRAY_SIZE(pll3_bypass_sels),
144                                  CLK_SET_RATE_PARENT));
145         clk_dm(IMXRT1050_CLK_PLL5_BYPASS,
146                imx_clk_mux_flags("pll5_bypass", base + 0xa0, 16, 1,
147                                  pll5_bypass_sels,
148                                  ARRAY_SIZE(pll5_bypass_sels),
149                                  CLK_SET_RATE_PARENT));
150
151         clk_dm(IMXRT1050_CLK_VIDEO_POST_DIV_SEL,
152                imx_clk_divider("video_post_div_sel", "pll5_video",
153                                base + 0xa0, 19, 2));
154         clk_dm(IMXRT1050_CLK_VIDEO_DIV,
155                imx_clk_divider("video_div", "video_post_div_sel",
156                                base + 0x170, 30, 2));
157
158         clk_dm(IMXRT1050_CLK_PLL3_80M,
159                imx_clk_fixed_factor("pll3_80m",  "pll3_usb_otg",   1, 6));
160
161         clk_dm(IMXRT1050_CLK_PLL2_PFD0_352M,
162                imx_clk_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0));
163         clk_dm(IMXRT1050_CLK_PLL2_PFD1_594M,
164                imx_clk_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1));
165         clk_dm(IMXRT1050_CLK_PLL2_PFD2_396M,
166                imx_clk_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2));
167         clk_dm(IMXRT1050_CLK_PLL3_PFD1_664_62M,
168                imx_clk_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0,
169                            1));
170         clk_dm(IMXRT1050_CLK_PLL3_PFD3_454_74M,
171                imx_clk_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0,
172                            3));
173
174         /* CCM clocks */
175         base = dev_read_addr_ptr(dev);
176         if (base == (void *)FDT_ADDR_T_NONE)
177                 return -EINVAL;
178
179         clk_dm(IMXRT1050_CLK_ARM_PODF,
180                imx_clk_divider("arm_podf", "pll1_arm",
181                                base + 0x10, 0, 3));
182
183         clk_dm(IMXRT1050_CLK_PRE_PERIPH_SEL,
184                imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2,
185                            pre_periph_sels, ARRAY_SIZE(pre_periph_sels)));
186         clk_dm(IMXRT1050_CLK_PERIPH_SEL,
187                imx_clk_mux("periph_sel", base + 0x14, 25, 1,
188                            periph_sels, ARRAY_SIZE(periph_sels)));
189         clk_dm(IMXRT1050_CLK_USDHC1_SEL,
190                imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1,
191                            usdhc_sels, ARRAY_SIZE(usdhc_sels)));
192         clk_dm(IMXRT1050_CLK_USDHC2_SEL,
193                imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1,
194                            usdhc_sels, ARRAY_SIZE(usdhc_sels)));
195         clk_dm(IMXRT1050_CLK_LPUART_SEL,
196                imx_clk_mux("lpuart_sel", base + 0x24, 6, 1,
197                            lpuart_sels, ARRAY_SIZE(lpuart_sels)));
198         clk_dm(IMXRT1050_CLK_SEMC_ALT_SEL,
199                imx_clk_mux("semc_alt_sel", base + 0x14, 7, 1,
200                            semc_alt_sels, ARRAY_SIZE(semc_alt_sels)));
201         clk_dm(IMXRT1050_CLK_SEMC_SEL,
202                imx_clk_mux("semc_sel", base + 0x14, 6, 1,
203                            semc_sels, ARRAY_SIZE(semc_sels)));
204         clk_dm(IMXRT1050_CLK_LCDIF_SEL,
205                imx_clk_mux("lcdif_sel", base + 0x38, 15, 3,
206                            lcdif_sels, ARRAY_SIZE(lcdif_sels)));
207
208         clk_dm(IMXRT1050_CLK_AHB_PODF,
209                imx_clk_divider("ahb_podf", "periph_sel",
210                                base + 0x14, 10, 3));
211         clk_dm(IMXRT1050_CLK_USDHC1_PODF,
212                imx_clk_divider("usdhc1_podf", "usdhc1_sel",
213                                base + 0x24, 11, 3));
214         clk_dm(IMXRT1050_CLK_USDHC2_PODF,
215                imx_clk_divider("usdhc2_podf", "usdhc2_sel",
216                                base + 0x24, 16, 3));
217         clk_dm(IMXRT1050_CLK_LPUART_PODF,
218                imx_clk_divider("lpuart_podf", "lpuart_sel",
219                                base + 0x24, 0, 6));
220         clk_dm(IMXRT1050_CLK_SEMC_PODF,
221                imx_clk_divider("semc_podf", "semc_sel",
222                                base + 0x14, 16, 3));
223         clk_dm(IMXRT1050_CLK_LCDIF_PRED,
224                imx_clk_divider("lcdif_pred", "lcdif_sel",
225                                base + 0x38, 12, 3));
226         clk_dm(IMXRT1050_CLK_LCDIF_PODF,
227                imx_clk_divider("lcdif_podf", "lcdif_pred",
228                                base + 0x18, 23, 3));
229
230         clk_dm(IMXRT1050_CLK_USDHC1,
231                imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2));
232         clk_dm(IMXRT1050_CLK_USDHC2,
233                imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4));
234         clk_dm(IMXRT1050_CLK_LPUART1,
235                imx_clk_gate2("lpuart1", "lpuart_podf", base + 0x7c, 24));
236         clk_dm(IMXRT1050_CLK_SEMC,
237                imx_clk_gate2("semc", "semc_podf", base + 0x74, 4));
238         clk_dm(IMXRT1050_CLK_LCDIF,
239                imx_clk_gate2("lcdif", "lcdif_podf", base + 0x70, 28));
240
241         struct clk *clk, *clk1;
242
243 #ifdef CONFIG_SPL_BUILD
244         /* bypass pll1 before setting its rate */
245         clk_get_by_id(IMXRT1050_CLK_PLL1_REF_SEL, &clk);
246         clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1);
247         clk_set_parent(clk1, clk);
248
249         clk_get_by_id(IMXRT1050_CLK_PLL1_ARM, &clk);
250         clk_enable(clk);
251         clk_set_rate(clk, 1056000000UL);
252
253         clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1);
254         clk_set_parent(clk1, clk);
255
256         clk_get_by_id(IMXRT1050_CLK_SEMC_SEL, &clk1);
257         clk_get_by_id(IMXRT1050_CLK_SEMC_ALT_SEL, &clk);
258         clk_set_parent(clk1, clk);
259
260         clk_get_by_id(IMXRT1050_CLK_PLL2_SYS, &clk);
261         clk_enable(clk);
262         clk_set_rate(clk, 528000000UL);
263
264         clk_get_by_id(IMXRT1050_CLK_PLL2_BYPASS, &clk1);
265         clk_set_parent(clk1, clk);
266
267         /* Configure PLL3_USB_OTG to 480MHz */
268         clk_get_by_id(IMXRT1050_CLK_PLL3_USB_OTG, &clk);
269         clk_enable(clk);
270         clk_set_rate(clk, 480000000UL);
271
272         clk_get_by_id(IMXRT1050_CLK_PLL3_BYPASS, &clk1);
273         clk_set_parent(clk1, clk);
274 #else
275         /* Set PLL5 for LCDIF to its default 650Mhz */
276         clk_get_by_id(IMXRT1050_CLK_PLL5_VIDEO, &clk);
277         clk_enable(clk);
278         clk_set_rate(clk, 650000000UL);
279
280         clk_get_by_id(IMXRT1050_CLK_PLL5_BYPASS, &clk1);
281         clk_set_parent(clk1, clk);
282 #endif
283
284         return 0;
285 }
286
287 static const struct udevice_id imxrt1050_clk_ids[] = {
288         { .compatible = "fsl,imxrt1050-ccm" },
289         { },
290 };
291
292 U_BOOT_DRIVER(imxrt1050_clk) = {
293         .name = "clk_imxrt1050",
294         .id = UCLASS_CLK,
295         .of_match = imxrt1050_clk_ids,
296         .ops = &imxrt1050_clk_ops,
297         .probe = imxrt1050_clk_probe,
298         .flags = DM_FLAG_PRE_RELOC,
299 };