1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2013-2014 Freescale Semiconductor, Inc. |
4 | */ |
5 | |
6 | #include <linux/bits.h> |
7 | #include <linux/clk.h> |
8 | #include <linux/clkdev.h> |
9 | #include <linux/clk/imx.h> |
10 | #include <linux/err.h> |
11 | #include <linux/of.h> |
12 | #include <linux/of_address.h> |
13 | #include <linux/of_irq.h> |
14 | #include <dt-bindings/clock/imx6sl-clock.h> |
15 | |
16 | #include "clk.h" |
17 | |
18 | #define CCSR 0xc |
19 | #define BM_CCSR_PLL1_SW_CLK_SEL BIT(2) |
20 | #define CACRR 0x10 |
21 | #define CDHIPR 0x48 |
22 | #define BM_CDHIPR_ARM_PODF_BUSY BIT(16) |
23 | #define ARM_WAIT_DIV_396M 2 |
24 | #define ARM_WAIT_DIV_792M 4 |
25 | #define ARM_WAIT_DIV_996M 6 |
26 | |
27 | #define PLL_ARM 0x0 |
28 | #define BM_PLL_ARM_DIV_SELECT 0x7f |
29 | #define BM_PLL_ARM_POWERDOWN BIT(12) |
30 | #define BM_PLL_ARM_ENABLE BIT(13) |
31 | #define BM_PLL_ARM_LOCK BIT(31) |
32 | #define PLL_ARM_DIV_792M 66 |
33 | |
34 | static const char *step_sels[] = { "osc" , "pll2_pfd2" , }; |
35 | static const char *pll1_sw_sels[] = { "pll1_sys" , "step" , }; |
36 | static const char *ocram_alt_sels[] = { "pll2_pfd2" , "pll3_pfd1" , }; |
37 | static const char *ocram_sels[] = { "periph" , "ocram_alt_sels" , }; |
38 | static const char *pre_periph_sels[] = { "pll2_bus" , "pll2_pfd2" , "pll2_pfd0" , "pll2_198m" , }; |
39 | static const char *periph_clk2_sels[] = { "pll3_usb_otg" , "osc" , "osc" , "dummy" , }; |
40 | static const char *periph2_clk2_sels[] = { "pll3_usb_otg" , "pll2_bus" , }; |
41 | static const char *periph_sels[] = { "pre_periph_sel" , "periph_clk2_podf" , }; |
42 | static const char *periph2_sels[] = { "pre_periph2_sel" , "periph2_clk2_podf" , }; |
43 | static const char *csi_sels[] = { "osc" , "pll2_pfd2" , "pll3_120m" , "pll3_pfd1" , }; |
44 | static const char *lcdif_axi_sels[] = { "pll2_bus" , "pll2_pfd2" , "pll3_usb_otg" , "pll3_pfd1" , }; |
45 | static const char *usdhc_sels[] = { "pll2_pfd2" , "pll2_pfd0" , }; |
46 | static const char *ssi_sels[] = { "pll3_pfd2" , "pll3_pfd3" , "pll4_audio_div" , "dummy" , }; |
47 | static const char *perclk_sels[] = { "ipg" , "osc" , }; |
48 | static const char *pxp_axi_sels[] = { "pll2_bus" , "pll3_usb_otg" , "pll5_video_div" , "pll2_pfd0" , "pll2_pfd2" , "pll3_pfd3" , }; |
49 | static const char *epdc_axi_sels[] = { "pll2_bus" , "pll3_usb_otg" , "pll5_video_div" , "pll2_pfd0" , "pll2_pfd2" , "pll3_pfd2" , }; |
50 | static const char *gpu2d_ovg_sels[] = { "pll3_pfd1" , "pll3_usb_otg" , "pll2_bus" , "pll2_pfd2" , }; |
51 | static const char *gpu2d_sels[] = { "pll2_pfd2" , "pll3_usb_otg" , "pll3_pfd1" , "pll2_bus" , }; |
52 | static const char *lcdif_pix_sels[] = { "pll2_bus" , "pll3_usb_otg" , "pll5_video_div" , "pll2_pfd0" , "pll3_pfd0" , "pll3_pfd1" , }; |
53 | static const char *epdc_pix_sels[] = { "pll2_bus" , "pll3_usb_otg" , "pll5_video_div" , "pll2_pfd0" , "pll2_pfd1" , "pll3_pfd1" , }; |
54 | static const char *audio_sels[] = { "pll4_audio_div" , "pll3_pfd2" , "pll3_pfd3" , "pll3_usb_otg" , }; |
55 | static const char *ecspi_sels[] = { "pll3_60m" , "osc" , }; |
56 | static const char *uart_sels[] = { "pll3_80m" , "osc" , }; |
57 | static const char *lvds_sels[] = { |
58 | "pll1_sys" , "pll2_bus" , "pll2_pfd0" , "pll2_pfd1" , "pll2_pfd2" , "dummy" , "pll4_audio" , "pll5_video" , |
59 | "dummy" , "enet_ref" , "dummy" , "dummy" , "pll3_usb_otg" , "pll7_usb_host" , "pll3_pfd0" , "pll3_pfd1" , |
60 | "pll3_pfd2" , "pll3_pfd3" , "osc" , "dummy" , "dummy" , "dummy" , "dummy" , "dummy" , |
61 | "dummy" , "dummy" , "dummy" , "dummy" , "dummy" , "dummy" , "dummy" , "dummy" , |
62 | }; |
63 | static const char *pll_bypass_src_sels[] = { "osc" , "lvds1_in" , }; |
64 | static const char *pll1_bypass_sels[] = { "pll1" , "pll1_bypass_src" , }; |
65 | static const char *pll2_bypass_sels[] = { "pll2" , "pll2_bypass_src" , }; |
66 | static const char *pll3_bypass_sels[] = { "pll3" , "pll3_bypass_src" , }; |
67 | static const char *pll4_bypass_sels[] = { "pll4" , "pll4_bypass_src" , }; |
68 | static const char *pll5_bypass_sels[] = { "pll5" , "pll5_bypass_src" , }; |
69 | static const char *pll6_bypass_sels[] = { "pll6" , "pll6_bypass_src" , }; |
70 | static const char *pll7_bypass_sels[] = { "pll7" , "pll7_bypass_src" , }; |
71 | |
72 | static const struct clk_div_table clk_enet_ref_table[] = { |
73 | { .val = 0, .div = 20, }, |
74 | { .val = 1, .div = 10, }, |
75 | { .val = 2, .div = 5, }, |
76 | { .val = 3, .div = 4, }, |
77 | { } |
78 | }; |
79 | |
80 | static const struct clk_div_table post_div_table[] = { |
81 | { .val = 2, .div = 1, }, |
82 | { .val = 1, .div = 2, }, |
83 | { .val = 0, .div = 4, }, |
84 | { } |
85 | }; |
86 | |
87 | static const struct clk_div_table video_div_table[] = { |
88 | { .val = 0, .div = 1, }, |
89 | { .val = 1, .div = 2, }, |
90 | { .val = 2, .div = 1, }, |
91 | { .val = 3, .div = 4, }, |
92 | { } |
93 | }; |
94 | |
95 | static unsigned int share_count_ssi1; |
96 | static unsigned int share_count_ssi2; |
97 | static unsigned int share_count_ssi3; |
98 | static unsigned int share_count_spdif; |
99 | |
100 | static struct clk_hw **hws; |
101 | static struct clk_hw_onecell_data *clk_hw_data; |
102 | static void __iomem *ccm_base; |
103 | static void __iomem *anatop_base; |
104 | |
105 | /* |
106 | * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken |
107 | * during WAIT mode entry process could cause cache memory |
108 | * corruption. |
109 | * |
110 | * Software workaround: |
111 | * To prevent this issue from occurring, software should ensure that the |
112 | * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before |
113 | * entering WAIT mode. |
114 | * |
115 | * This function will set the ARM clk to max value within the 12:5 limit. |
116 | * As IPG clock is fixed at 66MHz(so ARM freq must not exceed 158.4MHz), |
117 | * ARM freq are one of below setpoints: 396MHz, 792MHz and 996MHz, since |
118 | * the clk APIs can NOT be called in idle thread(may cause kernel schedule |
119 | * as there is sleep function in PLL wait function), so here we just slow |
120 | * down ARM to below freq according to previous freq: |
121 | * |
122 | * run mode wait mode |
123 | * 396MHz -> 132MHz; |
124 | * 792MHz -> 158.4MHz; |
125 | * 996MHz -> 142.3MHz; |
126 | */ |
127 | static int imx6sl_get_arm_divider_for_wait(void) |
128 | { |
129 | if (readl_relaxed(ccm_base + CCSR) & BM_CCSR_PLL1_SW_CLK_SEL) { |
130 | return ARM_WAIT_DIV_396M; |
131 | } else { |
132 | if ((readl_relaxed(anatop_base + PLL_ARM) & |
133 | BM_PLL_ARM_DIV_SELECT) == PLL_ARM_DIV_792M) |
134 | return ARM_WAIT_DIV_792M; |
135 | else |
136 | return ARM_WAIT_DIV_996M; |
137 | } |
138 | } |
139 | |
140 | static void imx6sl_enable_pll_arm(bool enable) |
141 | { |
142 | static u32 saved_pll_arm; |
143 | u32 val; |
144 | |
145 | if (enable) { |
146 | saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM); |
147 | val |= BM_PLL_ARM_ENABLE; |
148 | val &= ~BM_PLL_ARM_POWERDOWN; |
149 | writel_relaxed(val, anatop_base + PLL_ARM); |
150 | while (!(readl_relaxed(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK)) |
151 | ; |
152 | } else { |
153 | writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM); |
154 | } |
155 | } |
156 | |
157 | void imx6sl_set_wait_clk(bool enter) |
158 | { |
159 | static unsigned long saved_arm_div; |
160 | int arm_div_for_wait = imx6sl_get_arm_divider_for_wait(); |
161 | |
162 | /* |
163 | * According to hardware design, arm podf change need |
164 | * PLL1 clock enabled. |
165 | */ |
166 | if (arm_div_for_wait == ARM_WAIT_DIV_396M) |
167 | imx6sl_enable_pll_arm(enable: true); |
168 | |
169 | if (enter) { |
170 | saved_arm_div = readl_relaxed(ccm_base + CACRR); |
171 | writel_relaxed(arm_div_for_wait, ccm_base + CACRR); |
172 | } else { |
173 | writel_relaxed(saved_arm_div, ccm_base + CACRR); |
174 | } |
175 | while (__raw_readl(addr: ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY) |
176 | ; |
177 | |
178 | if (arm_div_for_wait == ARM_WAIT_DIV_396M) |
179 | imx6sl_enable_pll_arm(enable: false); |
180 | } |
181 | |
182 | static void __init imx6sl_clocks_init(struct device_node *ccm_node) |
183 | { |
184 | struct device_node *np; |
185 | void __iomem *base; |
186 | int ret; |
187 | |
188 | clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, |
189 | IMX6SL_CLK_END), GFP_KERNEL); |
190 | if (WARN_ON(!clk_hw_data)) |
191 | return; |
192 | |
193 | clk_hw_data->num = IMX6SL_CLK_END; |
194 | hws = clk_hw_data->hws; |
195 | |
196 | hws[IMX6SL_CLK_DUMMY] = imx_clk_hw_fixed(name: "dummy" , rate: 0); |
197 | hws[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock_hw(name: "ckil" , rate: 0); |
198 | hws[IMX6SL_CLK_OSC] = imx_obtain_fixed_clock_hw(name: "osc" , rate: 0); |
199 | /* Clock source from external clock via CLK1 PAD */ |
200 | hws[IMX6SL_CLK_ANACLK1] = imx_obtain_fixed_clock_hw(name: "anaclk1" , rate: 0); |
201 | |
202 | np = of_find_compatible_node(NULL, NULL, compat: "fsl,imx6sl-anatop" ); |
203 | base = of_iomap(node: np, index: 0); |
204 | WARN_ON(!base); |
205 | of_node_put(node: np); |
206 | anatop_base = base; |
207 | |
208 | hws[IMX6SL_PLL1_BYPASS_SRC] = imx_clk_hw_mux("pll1_bypass_src" , base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
209 | hws[IMX6SL_PLL2_BYPASS_SRC] = imx_clk_hw_mux("pll2_bypass_src" , base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
210 | hws[IMX6SL_PLL3_BYPASS_SRC] = imx_clk_hw_mux("pll3_bypass_src" , base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
211 | hws[IMX6SL_PLL4_BYPASS_SRC] = imx_clk_hw_mux("pll4_bypass_src" , base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
212 | hws[IMX6SL_PLL5_BYPASS_SRC] = imx_clk_hw_mux("pll5_bypass_src" , base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
213 | hws[IMX6SL_PLL6_BYPASS_SRC] = imx_clk_hw_mux("pll6_bypass_src" , base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
214 | hws[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_hw_mux("pll7_bypass_src" , base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); |
215 | |
216 | /* type name parent_name base div_mask */ |
217 | hws[IMX6SL_CLK_PLL1] = imx_clk_hw_pllv3(type: IMX_PLLV3_SYS, name: "pll1" , parent_name: "osc" , base: base + 0x00, div_mask: 0x7f); |
218 | hws[IMX6SL_CLK_PLL2] = imx_clk_hw_pllv3(type: IMX_PLLV3_GENERIC, name: "pll2" , parent_name: "osc" , base: base + 0x30, div_mask: 0x1); |
219 | hws[IMX6SL_CLK_PLL3] = imx_clk_hw_pllv3(type: IMX_PLLV3_USB, name: "pll3" , parent_name: "osc" , base: base + 0x10, div_mask: 0x3); |
220 | hws[IMX6SL_CLK_PLL4] = imx_clk_hw_pllv3(type: IMX_PLLV3_AV, name: "pll4" , parent_name: "osc" , base: base + 0x70, div_mask: 0x7f); |
221 | hws[IMX6SL_CLK_PLL5] = imx_clk_hw_pllv3(type: IMX_PLLV3_AV, name: "pll5" , parent_name: "osc" , base: base + 0xa0, div_mask: 0x7f); |
222 | hws[IMX6SL_CLK_PLL6] = imx_clk_hw_pllv3(type: IMX_PLLV3_ENET, name: "pll6" , parent_name: "osc" , base: base + 0xe0, div_mask: 0x3); |
223 | hws[IMX6SL_CLK_PLL7] = imx_clk_hw_pllv3(type: IMX_PLLV3_USB, name: "pll7" , parent_name: "osc" , base: base + 0x20, div_mask: 0x3); |
224 | |
225 | hws[IMX6SL_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass" , base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); |
226 | hws[IMX6SL_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass" , base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); |
227 | hws[IMX6SL_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass" , base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); |
228 | hws[IMX6SL_PLL4_BYPASS] = imx_clk_hw_mux_flags("pll4_bypass" , base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT); |
229 | hws[IMX6SL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass" , base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); |
230 | hws[IMX6SL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass" , base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); |
231 | hws[IMX6SL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass" , base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); |
232 | |
233 | /* Do not bypass PLLs initially */ |
234 | clk_set_parent(clk: hws[IMX6SL_PLL1_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL1]->clk); |
235 | clk_set_parent(clk: hws[IMX6SL_PLL2_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL2]->clk); |
236 | clk_set_parent(clk: hws[IMX6SL_PLL3_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL3]->clk); |
237 | clk_set_parent(clk: hws[IMX6SL_PLL4_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL4]->clk); |
238 | clk_set_parent(clk: hws[IMX6SL_PLL5_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL5]->clk); |
239 | clk_set_parent(clk: hws[IMX6SL_PLL6_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL6]->clk); |
240 | clk_set_parent(clk: hws[IMX6SL_PLL7_BYPASS]->clk, parent: hws[IMX6SL_CLK_PLL7]->clk); |
241 | |
242 | hws[IMX6SL_CLK_PLL1_SYS] = imx_clk_hw_gate("pll1_sys" , "pll1_bypass" , base + 0x00, 13); |
243 | hws[IMX6SL_CLK_PLL2_BUS] = imx_clk_hw_gate("pll2_bus" , "pll2_bypass" , base + 0x30, 13); |
244 | hws[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_hw_gate("pll3_usb_otg" , "pll3_bypass" , base + 0x10, 13); |
245 | hws[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_hw_gate("pll4_audio" , "pll4_bypass" , base + 0x70, 13); |
246 | hws[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_hw_gate("pll5_video" , "pll5_bypass" , base + 0xa0, 13); |
247 | hws[IMX6SL_CLK_PLL6_ENET] = imx_clk_hw_gate("pll6_enet" , "pll6_bypass" , base + 0xe0, 13); |
248 | hws[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_hw_gate("pll7_usb_host" , "pll7_bypass" , base + 0x20, 13); |
249 | |
250 | hws[IMX6SL_CLK_LVDS1_SEL] = imx_clk_hw_mux("lvds1_sel" , base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); |
251 | hws[IMX6SL_CLK_LVDS1_OUT] = imx_clk_hw_gate_exclusive(name: "lvds1_out" , parent: "lvds1_sel" , reg: base + 0x160, shift: 10, BIT(12)); |
252 | hws[IMX6SL_CLK_LVDS1_IN] = imx_clk_hw_gate_exclusive(name: "lvds1_in" , parent: "anaclk1" , reg: base + 0x160, shift: 12, BIT(10)); |
253 | |
254 | /* |
255 | * usbphy1 and usbphy2 are implemented as dummy gates using reserve |
256 | * bit 20. They are used by phy driver to keep the refcount of |
257 | * parent PLL correct. usbphy1_gate and usbphy2_gate only needs to be |
258 | * turned on during boot, and software will not need to control it |
259 | * anymore after that. |
260 | */ |
261 | hws[IMX6SL_CLK_USBPHY1] = imx_clk_hw_gate("usbphy1" , "pll3_usb_otg" , base + 0x10, 20); |
262 | hws[IMX6SL_CLK_USBPHY2] = imx_clk_hw_gate("usbphy2" , "pll7_usb_host" , base + 0x20, 20); |
263 | hws[IMX6SL_CLK_USBPHY1_GATE] = imx_clk_hw_gate("usbphy1_gate" , "dummy" , base + 0x10, 6); |
264 | hws[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_hw_gate("usbphy2_gate" , "dummy" , base + 0x20, 6); |
265 | |
266 | /* dev name parent_name flags reg shift width div: flags, div_table lock */ |
267 | hws[IMX6SL_CLK_PLL4_POST_DIV] = clk_hw_register_divider_table(NULL, "pll4_post_div" , "pll4_audio" , CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); |
268 | hws[IMX6SL_CLK_PLL4_AUDIO_DIV] = clk_hw_register_divider(NULL, "pll4_audio_div" , "pll4_post_div" , CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); |
269 | hws[IMX6SL_CLK_PLL5_POST_DIV] = clk_hw_register_divider_table(NULL, "pll5_post_div" , "pll5_video" , CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); |
270 | hws[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_hw_register_divider_table(NULL, "pll5_video_div" , "pll5_post_div" , CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); |
271 | hws[IMX6SL_CLK_ENET_REF] = clk_hw_register_divider_table(NULL, "enet_ref" , "pll6_enet" , 0, base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock); |
272 | |
273 | /* name parent_name reg idx */ |
274 | hws[IMX6SL_CLK_PLL2_PFD0] = imx_clk_hw_pfd(name: "pll2_pfd0" , parent_name: "pll2_bus" , reg: base + 0x100, idx: 0); |
275 | hws[IMX6SL_CLK_PLL2_PFD1] = imx_clk_hw_pfd(name: "pll2_pfd1" , parent_name: "pll2_bus" , reg: base + 0x100, idx: 1); |
276 | hws[IMX6SL_CLK_PLL2_PFD2] = imx_clk_hw_pfd(name: "pll2_pfd2" , parent_name: "pll2_bus" , reg: base + 0x100, idx: 2); |
277 | hws[IMX6SL_CLK_PLL3_PFD0] = imx_clk_hw_pfd(name: "pll3_pfd0" , parent_name: "pll3_usb_otg" , reg: base + 0xf0, idx: 0); |
278 | hws[IMX6SL_CLK_PLL3_PFD1] = imx_clk_hw_pfd(name: "pll3_pfd1" , parent_name: "pll3_usb_otg" , reg: base + 0xf0, idx: 1); |
279 | hws[IMX6SL_CLK_PLL3_PFD2] = imx_clk_hw_pfd(name: "pll3_pfd2" , parent_name: "pll3_usb_otg" , reg: base + 0xf0, idx: 2); |
280 | hws[IMX6SL_CLK_PLL3_PFD3] = imx_clk_hw_pfd(name: "pll3_pfd3" , parent_name: "pll3_usb_otg" , reg: base + 0xf0, idx: 3); |
281 | |
282 | /* name parent_name mult div */ |
283 | hws[IMX6SL_CLK_PLL2_198M] = imx_clk_hw_fixed_factor(name: "pll2_198m" , parent: "pll2_pfd2" , mult: 1, div: 2); |
284 | hws[IMX6SL_CLK_PLL3_120M] = imx_clk_hw_fixed_factor(name: "pll3_120m" , parent: "pll3_usb_otg" , mult: 1, div: 4); |
285 | hws[IMX6SL_CLK_PLL3_80M] = imx_clk_hw_fixed_factor(name: "pll3_80m" , parent: "pll3_usb_otg" , mult: 1, div: 6); |
286 | hws[IMX6SL_CLK_PLL3_60M] = imx_clk_hw_fixed_factor(name: "pll3_60m" , parent: "pll3_usb_otg" , mult: 1, div: 8); |
287 | |
288 | np = ccm_node; |
289 | base = of_iomap(node: np, index: 0); |
290 | WARN_ON(!base); |
291 | ccm_base = base; |
292 | |
293 | /* name reg shift width parent_names num_parents */ |
294 | hws[IMX6SL_CLK_STEP] = imx_clk_hw_mux("step" , base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); |
295 | hws[IMX6SL_CLK_PLL1_SW] = imx_clk_hw_mux("pll1_sw" , base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); |
296 | hws[IMX6SL_CLK_OCRAM_ALT_SEL] = imx_clk_hw_mux("ocram_alt_sel" , base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels)); |
297 | hws[IMX6SL_CLK_OCRAM_SEL] = imx_clk_hw_mux("ocram_sel" , base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels)); |
298 | hws[IMX6SL_CLK_PRE_PERIPH2_SEL] = imx_clk_hw_mux("pre_periph2_sel" , base + 0x18, 21, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); |
299 | hws[IMX6SL_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel" , base + 0x18, 18, 2, pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); |
300 | hws[IMX6SL_CLK_PERIPH2_CLK2_SEL] = imx_clk_hw_mux("periph2_clk2_sel" , base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); |
301 | hws[IMX6SL_CLK_PERIPH_CLK2_SEL] = imx_clk_hw_mux("periph_clk2_sel" , base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); |
302 | hws[IMX6SL_CLK_CSI_SEL] = imx_clk_hw_mux("csi_sel" , base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); |
303 | hws[IMX6SL_CLK_LCDIF_AXI_SEL] = imx_clk_hw_mux("lcdif_axi_sel" , base + 0x3c, 14, 2, lcdif_axi_sels, ARRAY_SIZE(lcdif_axi_sels)); |
304 | hws[IMX6SL_CLK_USDHC1_SEL] = imx_clk_hw_fixup_mux(name: "usdhc1_sel" , reg: base + 0x1c, shift: 16, width: 1, parents: usdhc_sels, ARRAY_SIZE(usdhc_sels), fixup: imx_cscmr1_fixup); |
305 | hws[IMX6SL_CLK_USDHC2_SEL] = imx_clk_hw_fixup_mux(name: "usdhc2_sel" , reg: base + 0x1c, shift: 17, width: 1, parents: usdhc_sels, ARRAY_SIZE(usdhc_sels), fixup: imx_cscmr1_fixup); |
306 | hws[IMX6SL_CLK_USDHC3_SEL] = imx_clk_hw_fixup_mux(name: "usdhc3_sel" , reg: base + 0x1c, shift: 18, width: 1, parents: usdhc_sels, ARRAY_SIZE(usdhc_sels), fixup: imx_cscmr1_fixup); |
307 | hws[IMX6SL_CLK_USDHC4_SEL] = imx_clk_hw_fixup_mux(name: "usdhc4_sel" , reg: base + 0x1c, shift: 19, width: 1, parents: usdhc_sels, ARRAY_SIZE(usdhc_sels), fixup: imx_cscmr1_fixup); |
308 | hws[IMX6SL_CLK_SSI1_SEL] = imx_clk_hw_fixup_mux(name: "ssi1_sel" , reg: base + 0x1c, shift: 10, width: 2, parents: ssi_sels, ARRAY_SIZE(ssi_sels), fixup: imx_cscmr1_fixup); |
309 | hws[IMX6SL_CLK_SSI2_SEL] = imx_clk_hw_fixup_mux(name: "ssi2_sel" , reg: base + 0x1c, shift: 12, width: 2, parents: ssi_sels, ARRAY_SIZE(ssi_sels), fixup: imx_cscmr1_fixup); |
310 | hws[IMX6SL_CLK_SSI3_SEL] = imx_clk_hw_fixup_mux(name: "ssi3_sel" , reg: base + 0x1c, shift: 14, width: 2, parents: ssi_sels, ARRAY_SIZE(ssi_sels), fixup: imx_cscmr1_fixup); |
311 | hws[IMX6SL_CLK_PERCLK_SEL] = imx_clk_hw_fixup_mux(name: "perclk_sel" , reg: base + 0x1c, shift: 6, width: 1, parents: perclk_sels, ARRAY_SIZE(perclk_sels), fixup: imx_cscmr1_fixup); |
312 | hws[IMX6SL_CLK_PXP_AXI_SEL] = imx_clk_hw_mux("pxp_axi_sel" , base + 0x34, 6, 3, pxp_axi_sels, ARRAY_SIZE(pxp_axi_sels)); |
313 | hws[IMX6SL_CLK_EPDC_AXI_SEL] = imx_clk_hw_mux("epdc_axi_sel" , base + 0x34, 15, 3, epdc_axi_sels, ARRAY_SIZE(epdc_axi_sels)); |
314 | hws[IMX6SL_CLK_GPU2D_OVG_SEL] = imx_clk_hw_mux("gpu2d_ovg_sel" , base + 0x18, 4, 2, gpu2d_ovg_sels, ARRAY_SIZE(gpu2d_ovg_sels)); |
315 | hws[IMX6SL_CLK_GPU2D_SEL] = imx_clk_hw_mux("gpu2d_sel" , base + 0x18, 8, 2, gpu2d_sels, ARRAY_SIZE(gpu2d_sels)); |
316 | hws[IMX6SL_CLK_LCDIF_PIX_SEL] = imx_clk_hw_mux("lcdif_pix_sel" , base + 0x38, 6, 3, lcdif_pix_sels, ARRAY_SIZE(lcdif_pix_sels)); |
317 | hws[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_hw_mux("epdc_pix_sel" , base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels)); |
318 | hws[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_hw_mux("spdif0_sel" , base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); |
319 | hws[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_hw_mux("spdif1_sel" , base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); |
320 | hws[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_hw_mux("extern_audio_sel" , base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); |
321 | hws[IMX6SL_CLK_ECSPI_SEL] = imx_clk_hw_mux("ecspi_sel" , base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); |
322 | hws[IMX6SL_CLK_UART_SEL] = imx_clk_hw_mux("uart_sel" , base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); |
323 | |
324 | /* name reg shift width busy: reg, shift parent_names num_parents */ |
325 | hws[IMX6SL_CLK_PERIPH] = imx_clk_hw_busy_mux(name: "periph" , reg: base + 0x14, shift: 25, width: 1, busy_reg: base + 0x48, busy_shift: 5, parent_names: periph_sels, ARRAY_SIZE(periph_sels)); |
326 | hws[IMX6SL_CLK_PERIPH2] = imx_clk_hw_busy_mux(name: "periph2" , reg: base + 0x14, shift: 26, width: 1, busy_reg: base + 0x48, busy_shift: 3, parent_names: periph2_sels, ARRAY_SIZE(periph2_sels)); |
327 | |
328 | /* name parent_name reg shift width */ |
329 | hws[IMX6SL_CLK_OCRAM_PODF] = imx_clk_hw_busy_divider(name: "ocram_podf" , parent_name: "ocram_sel" , reg: base + 0x14, shift: 16, width: 3, busy_reg: base + 0x48, busy_shift: 0); |
330 | hws[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_hw_divider("periph_clk2_podf" , "periph_clk2_sel" , base + 0x14, 27, 3); |
331 | hws[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_hw_divider("periph2_clk2_podf" , "periph2_clk2_sel" , base + 0x14, 0, 3); |
332 | hws[IMX6SL_CLK_IPG] = imx_clk_hw_divider("ipg" , "ahb" , base + 0x14, 8, 2); |
333 | hws[IMX6SL_CLK_CSI_PODF] = imx_clk_hw_divider("csi_podf" , "csi_sel" , base + 0x3c, 11, 3); |
334 | hws[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_hw_divider("lcdif_axi_podf" , "lcdif_axi_sel" , base + 0x3c, 16, 3); |
335 | hws[IMX6SL_CLK_USDHC1_PODF] = imx_clk_hw_divider("usdhc1_podf" , "usdhc1_sel" , base + 0x24, 11, 3); |
336 | hws[IMX6SL_CLK_USDHC2_PODF] = imx_clk_hw_divider("usdhc2_podf" , "usdhc2_sel" , base + 0x24, 16, 3); |
337 | hws[IMX6SL_CLK_USDHC3_PODF] = imx_clk_hw_divider("usdhc3_podf" , "usdhc3_sel" , base + 0x24, 19, 3); |
338 | hws[IMX6SL_CLK_USDHC4_PODF] = imx_clk_hw_divider("usdhc4_podf" , "usdhc4_sel" , base + 0x24, 22, 3); |
339 | hws[IMX6SL_CLK_SSI1_PRED] = imx_clk_hw_divider("ssi1_pred" , "ssi1_sel" , base + 0x28, 6, 3); |
340 | hws[IMX6SL_CLK_SSI1_PODF] = imx_clk_hw_divider("ssi1_podf" , "ssi1_pred" , base + 0x28, 0, 6); |
341 | hws[IMX6SL_CLK_SSI2_PRED] = imx_clk_hw_divider("ssi2_pred" , "ssi2_sel" , base + 0x2c, 6, 3); |
342 | hws[IMX6SL_CLK_SSI2_PODF] = imx_clk_hw_divider("ssi2_podf" , "ssi2_pred" , base + 0x2c, 0, 6); |
343 | hws[IMX6SL_CLK_SSI3_PRED] = imx_clk_hw_divider("ssi3_pred" , "ssi3_sel" , base + 0x28, 22, 3); |
344 | hws[IMX6SL_CLK_SSI3_PODF] = imx_clk_hw_divider("ssi3_podf" , "ssi3_pred" , base + 0x28, 16, 6); |
345 | hws[IMX6SL_CLK_PERCLK] = imx_clk_hw_fixup_divider(name: "perclk" , parent: "perclk_sel" , reg: base + 0x1c, shift: 0, width: 6, fixup: imx_cscmr1_fixup); |
346 | hws[IMX6SL_CLK_PXP_AXI_PODF] = imx_clk_hw_divider("pxp_axi_podf" , "pxp_axi_sel" , base + 0x34, 3, 3); |
347 | hws[IMX6SL_CLK_EPDC_AXI_PODF] = imx_clk_hw_divider("epdc_axi_podf" , "epdc_axi_sel" , base + 0x34, 12, 3); |
348 | hws[IMX6SL_CLK_GPU2D_OVG_PODF] = imx_clk_hw_divider("gpu2d_ovg_podf" , "gpu2d_ovg_sel" , base + 0x18, 26, 3); |
349 | hws[IMX6SL_CLK_GPU2D_PODF] = imx_clk_hw_divider("gpu2d_podf" , "gpu2d_sel" , base + 0x18, 29, 3); |
350 | hws[IMX6SL_CLK_LCDIF_PIX_PRED] = imx_clk_hw_divider("lcdif_pix_pred" , "lcdif_pix_sel" , base + 0x38, 3, 3); |
351 | hws[IMX6SL_CLK_EPDC_PIX_PRED] = imx_clk_hw_divider("epdc_pix_pred" , "epdc_pix_sel" , base + 0x38, 12, 3); |
352 | hws[IMX6SL_CLK_LCDIF_PIX_PODF] = imx_clk_hw_fixup_divider(name: "lcdif_pix_podf" , parent: "lcdif_pix_pred" , reg: base + 0x1c, shift: 20, width: 3, fixup: imx_cscmr1_fixup); |
353 | hws[IMX6SL_CLK_EPDC_PIX_PODF] = imx_clk_hw_divider("epdc_pix_podf" , "epdc_pix_pred" , base + 0x18, 23, 3); |
354 | hws[IMX6SL_CLK_SPDIF0_PRED] = imx_clk_hw_divider("spdif0_pred" , "spdif0_sel" , base + 0x30, 25, 3); |
355 | hws[IMX6SL_CLK_SPDIF0_PODF] = imx_clk_hw_divider("spdif0_podf" , "spdif0_pred" , base + 0x30, 22, 3); |
356 | hws[IMX6SL_CLK_SPDIF1_PRED] = imx_clk_hw_divider("spdif1_pred" , "spdif1_sel" , base + 0x30, 12, 3); |
357 | hws[IMX6SL_CLK_SPDIF1_PODF] = imx_clk_hw_divider("spdif1_podf" , "spdif1_pred" , base + 0x30, 9, 3); |
358 | hws[IMX6SL_CLK_EXTERN_AUDIO_PRED] = imx_clk_hw_divider("extern_audio_pred" , "extern_audio_sel" , base + 0x28, 9, 3); |
359 | hws[IMX6SL_CLK_EXTERN_AUDIO_PODF] = imx_clk_hw_divider("extern_audio_podf" , "extern_audio_pred" , base + 0x28, 25, 3); |
360 | hws[IMX6SL_CLK_ECSPI_ROOT] = imx_clk_hw_divider("ecspi_root" , "ecspi_sel" , base + 0x38, 19, 6); |
361 | hws[IMX6SL_CLK_UART_ROOT] = imx_clk_hw_divider("uart_root" , "uart_sel" , base + 0x24, 0, 6); |
362 | |
363 | /* name parent_name reg shift width busy: reg, shift */ |
364 | hws[IMX6SL_CLK_AHB] = imx_clk_hw_busy_divider(name: "ahb" , parent_name: "periph" , reg: base + 0x14, shift: 10, width: 3, busy_reg: base + 0x48, busy_shift: 1); |
365 | hws[IMX6SL_CLK_MMDC_ROOT] = imx_clk_hw_busy_divider(name: "mmdc" , parent_name: "periph2" , reg: base + 0x14, shift: 3, width: 3, busy_reg: base + 0x48, busy_shift: 2); |
366 | hws[IMX6SL_CLK_ARM] = imx_clk_hw_busy_divider(name: "arm" , parent_name: "pll1_sw" , reg: base + 0x10, shift: 0, width: 3, busy_reg: base + 0x48, busy_shift: 16); |
367 | |
368 | /* name parent_name reg shift */ |
369 | hws[IMX6SL_CLK_ECSPI1] = imx_clk_hw_gate2("ecspi1" , "ecspi_root" , base + 0x6c, 0); |
370 | hws[IMX6SL_CLK_ECSPI2] = imx_clk_hw_gate2("ecspi2" , "ecspi_root" , base + 0x6c, 2); |
371 | hws[IMX6SL_CLK_ECSPI3] = imx_clk_hw_gate2("ecspi3" , "ecspi_root" , base + 0x6c, 4); |
372 | hws[IMX6SL_CLK_ECSPI4] = imx_clk_hw_gate2("ecspi4" , "ecspi_root" , base + 0x6c, 6); |
373 | hws[IMX6SL_CLK_ENET] = imx_clk_hw_gate2("enet" , "ipg" , base + 0x6c, 10); |
374 | hws[IMX6SL_CLK_EPIT1] = imx_clk_hw_gate2("epit1" , "perclk" , base + 0x6c, 12); |
375 | hws[IMX6SL_CLK_EPIT2] = imx_clk_hw_gate2("epit2" , "perclk" , base + 0x6c, 14); |
376 | hws[IMX6SL_CLK_EXTERN_AUDIO] = imx_clk_hw_gate2("extern_audio" , "extern_audio_podf" , base + 0x6c, 16); |
377 | hws[IMX6SL_CLK_GPT] = imx_clk_hw_gate2("gpt" , "perclk" , base + 0x6c, 20); |
378 | hws[IMX6SL_CLK_GPT_SERIAL] = imx_clk_hw_gate2("gpt_serial" , "perclk" , base + 0x6c, 22); |
379 | hws[IMX6SL_CLK_GPU2D_OVG] = imx_clk_hw_gate2("gpu2d_ovg" , "gpu2d_ovg_podf" , base + 0x6c, 26); |
380 | hws[IMX6SL_CLK_I2C1] = imx_clk_hw_gate2("i2c1" , "perclk" , base + 0x70, 6); |
381 | hws[IMX6SL_CLK_I2C2] = imx_clk_hw_gate2("i2c2" , "perclk" , base + 0x70, 8); |
382 | hws[IMX6SL_CLK_I2C3] = imx_clk_hw_gate2("i2c3" , "perclk" , base + 0x70, 10); |
383 | hws[IMX6SL_CLK_OCOTP] = imx_clk_hw_gate2("ocotp" , "ipg" , base + 0x70, 12); |
384 | hws[IMX6SL_CLK_CSI] = imx_clk_hw_gate2("csi" , "csi_podf" , base + 0x74, 0); |
385 | hws[IMX6SL_CLK_PXP_AXI] = imx_clk_hw_gate2("pxp_axi" , "pxp_axi_podf" , base + 0x74, 2); |
386 | hws[IMX6SL_CLK_EPDC_AXI] = imx_clk_hw_gate2("epdc_axi" , "epdc_axi_podf" , base + 0x74, 4); |
387 | hws[IMX6SL_CLK_LCDIF_AXI] = imx_clk_hw_gate2("lcdif_axi" , "lcdif_axi_podf" , base + 0x74, 6); |
388 | hws[IMX6SL_CLK_LCDIF_PIX] = imx_clk_hw_gate2("lcdif_pix" , "lcdif_pix_podf" , base + 0x74, 8); |
389 | hws[IMX6SL_CLK_EPDC_PIX] = imx_clk_hw_gate2("epdc_pix" , "epdc_pix_podf" , base + 0x74, 10); |
390 | hws[IMX6SL_CLK_MMDC_P0_IPG] = imx_clk_hw_gate2_flags("mmdc_p0_ipg" , "ipg" , base + 0x74, 24, CLK_IS_CRITICAL); |
391 | hws[IMX6SL_CLK_MMDC_P1_IPG] = imx_clk_hw_gate2("mmdc_p1_ipg" , "ipg" , base + 0x74, 26); |
392 | hws[IMX6SL_CLK_OCRAM] = imx_clk_hw_gate2("ocram" , "ocram_podf" , base + 0x74, 28); |
393 | hws[IMX6SL_CLK_PWM1] = imx_clk_hw_gate2("pwm1" , "perclk" , base + 0x78, 16); |
394 | hws[IMX6SL_CLK_PWM2] = imx_clk_hw_gate2("pwm2" , "perclk" , base + 0x78, 18); |
395 | hws[IMX6SL_CLK_PWM3] = imx_clk_hw_gate2("pwm3" , "perclk" , base + 0x78, 20); |
396 | hws[IMX6SL_CLK_PWM4] = imx_clk_hw_gate2("pwm4" , "perclk" , base + 0x78, 22); |
397 | hws[IMX6SL_CLK_SDMA] = imx_clk_hw_gate2("sdma" , "ipg" , base + 0x7c, 6); |
398 | hws[IMX6SL_CLK_SPBA] = imx_clk_hw_gate2("spba" , "ipg" , base + 0x7c, 12); |
399 | hws[IMX6SL_CLK_SPDIF] = imx_clk_hw_gate2_shared("spdif" , "spdif0_podf" , base + 0x7c, 14, &share_count_spdif); |
400 | hws[IMX6SL_CLK_SPDIF_GCLK] = imx_clk_hw_gate2_shared("spdif_gclk" , "ipg" , base + 0x7c, 14, &share_count_spdif); |
401 | hws[IMX6SL_CLK_SSI1_IPG] = imx_clk_hw_gate2_shared("ssi1_ipg" , "ipg" , base + 0x7c, 18, &share_count_ssi1); |
402 | hws[IMX6SL_CLK_SSI2_IPG] = imx_clk_hw_gate2_shared("ssi2_ipg" , "ipg" , base + 0x7c, 20, &share_count_ssi2); |
403 | hws[IMX6SL_CLK_SSI3_IPG] = imx_clk_hw_gate2_shared("ssi3_ipg" , "ipg" , base + 0x7c, 22, &share_count_ssi3); |
404 | hws[IMX6SL_CLK_SSI1] = imx_clk_hw_gate2_shared("ssi1" , "ssi1_podf" , base + 0x7c, 18, &share_count_ssi1); |
405 | hws[IMX6SL_CLK_SSI2] = imx_clk_hw_gate2_shared("ssi2" , "ssi2_podf" , base + 0x7c, 20, &share_count_ssi2); |
406 | hws[IMX6SL_CLK_SSI3] = imx_clk_hw_gate2_shared("ssi3" , "ssi3_podf" , base + 0x7c, 22, &share_count_ssi3); |
407 | hws[IMX6SL_CLK_UART] = imx_clk_hw_gate2("uart" , "ipg" , base + 0x7c, 24); |
408 | hws[IMX6SL_CLK_UART_SERIAL] = imx_clk_hw_gate2("uart_serial" , "uart_root" , base + 0x7c, 26); |
409 | hws[IMX6SL_CLK_USBOH3] = imx_clk_hw_gate2("usboh3" , "ipg" , base + 0x80, 0); |
410 | hws[IMX6SL_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1" , "usdhc1_podf" , base + 0x80, 2); |
411 | hws[IMX6SL_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2" , "usdhc2_podf" , base + 0x80, 4); |
412 | hws[IMX6SL_CLK_USDHC3] = imx_clk_hw_gate2("usdhc3" , "usdhc3_podf" , base + 0x80, 6); |
413 | hws[IMX6SL_CLK_USDHC4] = imx_clk_hw_gate2("usdhc4" , "usdhc4_podf" , base + 0x80, 8); |
414 | |
415 | /* Ensure the MMDC CH0 handshake is bypassed */ |
416 | imx_mmdc_mask_handshake(ccm_base: base, chn: 0); |
417 | |
418 | imx_check_clk_hws(clks: hws, IMX6SL_CLK_END); |
419 | |
420 | of_clk_add_hw_provider(np, get: of_clk_hw_onecell_get, data: clk_hw_data); |
421 | |
422 | /* Ensure the AHB clk is at 132MHz. */ |
423 | ret = clk_set_rate(clk: hws[IMX6SL_CLK_AHB]->clk, rate: 132000000); |
424 | if (ret) |
425 | pr_warn("%s: failed to set AHB clock rate %d!\n" , |
426 | __func__, ret); |
427 | |
428 | if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { |
429 | clk_prepare_enable(clk: hws[IMX6SL_CLK_USBPHY1_GATE]->clk); |
430 | clk_prepare_enable(clk: hws[IMX6SL_CLK_USBPHY2_GATE]->clk); |
431 | } |
432 | |
433 | /* Audio-related clocks configuration */ |
434 | clk_set_parent(clk: hws[IMX6SL_CLK_SPDIF0_SEL]->clk, parent: hws[IMX6SL_CLK_PLL3_PFD3]->clk); |
435 | |
436 | /* set PLL5 video as lcdif pix parent clock */ |
437 | clk_set_parent(clk: hws[IMX6SL_CLK_LCDIF_PIX_SEL]->clk, |
438 | parent: hws[IMX6SL_CLK_PLL5_VIDEO_DIV]->clk); |
439 | |
440 | clk_set_parent(clk: hws[IMX6SL_CLK_LCDIF_AXI_SEL]->clk, |
441 | parent: hws[IMX6SL_CLK_PLL2_PFD2]->clk); |
442 | |
443 | imx_register_uart_clocks(); |
444 | } |
445 | CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm" , imx6sl_clocks_init); |
446 | |