Commit 0c515e4972c7367d6cb1b75c305117cfc2310f1d
1 parent
4a75c31bbf
Exists in
smarc-imx_v2018.03_4.14.78_1.0.0_ga
MLK-20602 imx8mq: Change clock source of GIC
Change the the GIC clock source to sys_pll2_200m. Improve the IRQ response latency. Signed-off-by: Bai Ping <ping.bai@nxp.com> (cherry picked from commit f4c76d52da9c272b275adf26145d033099cd1974)
Showing 1 changed file with 5 additions and 0 deletions Inline Diff
arch/arm/mach-imx/imx8m/clock_imx8mq.c
1 | /* | 1 | /* |
2 | * Copyright 2017 NXP | 2 | * Copyright 2017 NXP |
3 | * | 3 | * |
4 | * Peng Fan <peng.fan@nxp.com> | 4 | * Peng Fan <peng.fan@nxp.com> |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <common.h> | 9 | #include <common.h> |
10 | #include <asm/arch/clock.h> | 10 | #include <asm/arch/clock.h> |
11 | #include <asm/arch/imx-regs.h> | 11 | #include <asm/arch/imx-regs.h> |
12 | #include <asm/io.h> | 12 | #include <asm/io.h> |
13 | #include <asm/arch/sys_proto.h> | 13 | #include <asm/arch/sys_proto.h> |
14 | #include <errno.h> | 14 | #include <errno.h> |
15 | #include <linux/iopoll.h> | 15 | #include <linux/iopoll.h> |
16 | 16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | 17 | DECLARE_GLOBAL_DATA_PTR; |
18 | 18 | ||
19 | static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; | 19 | static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR; |
20 | 20 | ||
21 | static u32 decode_frac_pll(enum clk_root_src frac_pll) | 21 | static u32 decode_frac_pll(enum clk_root_src frac_pll) |
22 | { | 22 | { |
23 | u32 pll_cfg0, pll_cfg1, pllout; | 23 | u32 pll_cfg0, pll_cfg1, pllout; |
24 | u32 pll_refclk_sel, pll_refclk; | 24 | u32 pll_refclk_sel, pll_refclk; |
25 | u32 divr_val, divq_val, divf_val, divff, divfi; | 25 | u32 divr_val, divq_val, divf_val, divff, divfi; |
26 | u32 pllout_div_shift, pllout_div_mask, pllout_div; | 26 | u32 pllout_div_shift, pllout_div_mask, pllout_div; |
27 | 27 | ||
28 | switch (frac_pll) { | 28 | switch (frac_pll) { |
29 | case ARM_PLL_CLK: | 29 | case ARM_PLL_CLK: |
30 | pll_cfg0 = readl(&ana_pll->arm_pll_cfg0); | 30 | pll_cfg0 = readl(&ana_pll->arm_pll_cfg0); |
31 | pll_cfg1 = readl(&ana_pll->arm_pll_cfg1); | 31 | pll_cfg1 = readl(&ana_pll->arm_pll_cfg1); |
32 | pllout_div_shift = HW_FRAC_ARM_PLL_DIV_SHIFT; | 32 | pllout_div_shift = HW_FRAC_ARM_PLL_DIV_SHIFT; |
33 | pllout_div_mask = HW_FRAC_ARM_PLL_DIV_MASK; | 33 | pllout_div_mask = HW_FRAC_ARM_PLL_DIV_MASK; |
34 | break; | 34 | break; |
35 | default: | 35 | default: |
36 | printf("Frac PLL %d not supporte\n", frac_pll); | 36 | printf("Frac PLL %d not supporte\n", frac_pll); |
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | pllout_div = readl(&ana_pll->frac_pllout_div_cfg); | 40 | pllout_div = readl(&ana_pll->frac_pllout_div_cfg); |
41 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; | 41 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; |
42 | 42 | ||
43 | /* Power down */ | 43 | /* Power down */ |
44 | if (pll_cfg0 & FRAC_PLL_PD_MASK) | 44 | if (pll_cfg0 & FRAC_PLL_PD_MASK) |
45 | return 0; | 45 | return 0; |
46 | 46 | ||
47 | /* output not enabled */ | 47 | /* output not enabled */ |
48 | if ((pll_cfg0 & FRAC_PLL_CLKE_MASK) == 0) | 48 | if ((pll_cfg0 & FRAC_PLL_CLKE_MASK) == 0) |
49 | return 0; | 49 | return 0; |
50 | 50 | ||
51 | pll_refclk_sel = pll_cfg0 & FRAC_PLL_REFCLK_SEL_MASK; | 51 | pll_refclk_sel = pll_cfg0 & FRAC_PLL_REFCLK_SEL_MASK; |
52 | 52 | ||
53 | if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_25M) | 53 | if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_25M) |
54 | pll_refclk = 25000000u; | 54 | pll_refclk = 25000000u; |
55 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_27M) | 55 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_27M) |
56 | pll_refclk = 27000000u; | 56 | pll_refclk = 27000000u; |
57 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_HDMI_PHY_27M) | 57 | else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_HDMI_PHY_27M) |
58 | pll_refclk = 27000000u; | 58 | pll_refclk = 27000000u; |
59 | else | 59 | else |
60 | pll_refclk = 0; | 60 | pll_refclk = 0; |
61 | 61 | ||
62 | if (pll_cfg0 & FRAC_PLL_BYPASS_MASK) | 62 | if (pll_cfg0 & FRAC_PLL_BYPASS_MASK) |
63 | return pll_refclk; | 63 | return pll_refclk; |
64 | 64 | ||
65 | divr_val = (pll_cfg0 & FRAC_PLL_REFCLK_DIV_VAL_MASK) >> | 65 | divr_val = (pll_cfg0 & FRAC_PLL_REFCLK_DIV_VAL_MASK) >> |
66 | FRAC_PLL_REFCLK_DIV_VAL_SHIFT; | 66 | FRAC_PLL_REFCLK_DIV_VAL_SHIFT; |
67 | divq_val = pll_cfg0 & FRAC_PLL_OUTPUT_DIV_VAL_MASK; | 67 | divq_val = pll_cfg0 & FRAC_PLL_OUTPUT_DIV_VAL_MASK; |
68 | 68 | ||
69 | divff = (pll_cfg1 & FRAC_PLL_FRAC_DIV_CTL_MASK) >> | 69 | divff = (pll_cfg1 & FRAC_PLL_FRAC_DIV_CTL_MASK) >> |
70 | FRAC_PLL_FRAC_DIV_CTL_SHIFT; | 70 | FRAC_PLL_FRAC_DIV_CTL_SHIFT; |
71 | divfi = pll_cfg1 & FRAC_PLL_INT_DIV_CTL_MASK; | 71 | divfi = pll_cfg1 & FRAC_PLL_INT_DIV_CTL_MASK; |
72 | 72 | ||
73 | divf_val = 1 + divfi + divff / (1 << 24); | 73 | divf_val = 1 + divfi + divff / (1 << 24); |
74 | 74 | ||
75 | pllout = pll_refclk / (divr_val + 1) * 8 * divf_val / | 75 | pllout = pll_refclk / (divr_val + 1) * 8 * divf_val / |
76 | ((divq_val + 1) * 2); | 76 | ((divq_val + 1) * 2); |
77 | 77 | ||
78 | return pllout / (pllout_div + 1); | 78 | return pllout / (pllout_div + 1); |
79 | } | 79 | } |
80 | 80 | ||
81 | static u32 decode_sscg_pll(enum clk_root_src sscg_pll) | 81 | static u32 decode_sscg_pll(enum clk_root_src sscg_pll) |
82 | { | 82 | { |
83 | u32 pll_cfg0, pll_cfg1, pll_cfg2; | 83 | u32 pll_cfg0, pll_cfg1, pll_cfg2; |
84 | u32 pll_refclk_sel, pll_refclk; | 84 | u32 pll_refclk_sel, pll_refclk; |
85 | u32 divr1, divr2, divf1, divf2, divq, div; | 85 | u32 divr1, divr2, divf1, divf2, divq, div; |
86 | u32 sse; | 86 | u32 sse; |
87 | u32 pll_clke; | 87 | u32 pll_clke; |
88 | u32 pllout_div_shift, pllout_div_mask, pllout_div; | 88 | u32 pllout_div_shift, pllout_div_mask, pllout_div; |
89 | u32 pllout; | 89 | u32 pllout; |
90 | 90 | ||
91 | switch (sscg_pll) { | 91 | switch (sscg_pll) { |
92 | case SYSTEM_PLL1_800M_CLK: | 92 | case SYSTEM_PLL1_800M_CLK: |
93 | case SYSTEM_PLL1_400M_CLK: | 93 | case SYSTEM_PLL1_400M_CLK: |
94 | case SYSTEM_PLL1_266M_CLK: | 94 | case SYSTEM_PLL1_266M_CLK: |
95 | case SYSTEM_PLL1_200M_CLK: | 95 | case SYSTEM_PLL1_200M_CLK: |
96 | case SYSTEM_PLL1_160M_CLK: | 96 | case SYSTEM_PLL1_160M_CLK: |
97 | case SYSTEM_PLL1_133M_CLK: | 97 | case SYSTEM_PLL1_133M_CLK: |
98 | case SYSTEM_PLL1_100M_CLK: | 98 | case SYSTEM_PLL1_100M_CLK: |
99 | case SYSTEM_PLL1_80M_CLK: | 99 | case SYSTEM_PLL1_80M_CLK: |
100 | case SYSTEM_PLL1_40M_CLK: | 100 | case SYSTEM_PLL1_40M_CLK: |
101 | pll_cfg0 = readl(&ana_pll->sys_pll1_cfg0); | 101 | pll_cfg0 = readl(&ana_pll->sys_pll1_cfg0); |
102 | pll_cfg1 = readl(&ana_pll->sys_pll1_cfg1); | 102 | pll_cfg1 = readl(&ana_pll->sys_pll1_cfg1); |
103 | pll_cfg2 = readl(&ana_pll->sys_pll1_cfg2); | 103 | pll_cfg2 = readl(&ana_pll->sys_pll1_cfg2); |
104 | pllout_div_shift = HW_SSCG_SYSTEM_PLL1_DIV_SHIFT; | 104 | pllout_div_shift = HW_SSCG_SYSTEM_PLL1_DIV_SHIFT; |
105 | pllout_div_mask = HW_SSCG_SYSTEM_PLL1_DIV_MASK; | 105 | pllout_div_mask = HW_SSCG_SYSTEM_PLL1_DIV_MASK; |
106 | break; | 106 | break; |
107 | case SYSTEM_PLL2_1000M_CLK: | 107 | case SYSTEM_PLL2_1000M_CLK: |
108 | case SYSTEM_PLL2_500M_CLK: | 108 | case SYSTEM_PLL2_500M_CLK: |
109 | case SYSTEM_PLL2_333M_CLK: | 109 | case SYSTEM_PLL2_333M_CLK: |
110 | case SYSTEM_PLL2_250M_CLK: | 110 | case SYSTEM_PLL2_250M_CLK: |
111 | case SYSTEM_PLL2_200M_CLK: | 111 | case SYSTEM_PLL2_200M_CLK: |
112 | case SYSTEM_PLL2_166M_CLK: | 112 | case SYSTEM_PLL2_166M_CLK: |
113 | case SYSTEM_PLL2_125M_CLK: | 113 | case SYSTEM_PLL2_125M_CLK: |
114 | case SYSTEM_PLL2_100M_CLK: | 114 | case SYSTEM_PLL2_100M_CLK: |
115 | case SYSTEM_PLL2_50M_CLK: | 115 | case SYSTEM_PLL2_50M_CLK: |
116 | pll_cfg0 = readl(&ana_pll->sys_pll2_cfg0); | 116 | pll_cfg0 = readl(&ana_pll->sys_pll2_cfg0); |
117 | pll_cfg1 = readl(&ana_pll->sys_pll2_cfg1); | 117 | pll_cfg1 = readl(&ana_pll->sys_pll2_cfg1); |
118 | pll_cfg2 = readl(&ana_pll->sys_pll2_cfg2); | 118 | pll_cfg2 = readl(&ana_pll->sys_pll2_cfg2); |
119 | pllout_div_shift = HW_SSCG_SYSTEM_PLL2_DIV_SHIFT; | 119 | pllout_div_shift = HW_SSCG_SYSTEM_PLL2_DIV_SHIFT; |
120 | pllout_div_mask = HW_SSCG_SYSTEM_PLL2_DIV_MASK; | 120 | pllout_div_mask = HW_SSCG_SYSTEM_PLL2_DIV_MASK; |
121 | break; | 121 | break; |
122 | case SYSTEM_PLL3_CLK: | 122 | case SYSTEM_PLL3_CLK: |
123 | pll_cfg0 = readl(&ana_pll->sys_pll3_cfg0); | 123 | pll_cfg0 = readl(&ana_pll->sys_pll3_cfg0); |
124 | pll_cfg1 = readl(&ana_pll->sys_pll3_cfg1); | 124 | pll_cfg1 = readl(&ana_pll->sys_pll3_cfg1); |
125 | pll_cfg2 = readl(&ana_pll->sys_pll3_cfg2); | 125 | pll_cfg2 = readl(&ana_pll->sys_pll3_cfg2); |
126 | pllout_div_shift = HW_SSCG_SYSTEM_PLL3_DIV_SHIFT; | 126 | pllout_div_shift = HW_SSCG_SYSTEM_PLL3_DIV_SHIFT; |
127 | pllout_div_mask = HW_SSCG_SYSTEM_PLL3_DIV_MASK; | 127 | pllout_div_mask = HW_SSCG_SYSTEM_PLL3_DIV_MASK; |
128 | break; | 128 | break; |
129 | case DRAM_PLL1_CLK: | 129 | case DRAM_PLL1_CLK: |
130 | pll_cfg0 = readl(&ana_pll->dram_pll_cfg0); | 130 | pll_cfg0 = readl(&ana_pll->dram_pll_cfg0); |
131 | pll_cfg1 = readl(&ana_pll->dram_pll_cfg1); | 131 | pll_cfg1 = readl(&ana_pll->dram_pll_cfg1); |
132 | pll_cfg2 = readl(&ana_pll->dram_pll_cfg2); | 132 | pll_cfg2 = readl(&ana_pll->dram_pll_cfg2); |
133 | pllout_div_shift = HW_SSCG_DRAM_PLL_DIV_SHIFT; | 133 | pllout_div_shift = HW_SSCG_DRAM_PLL_DIV_SHIFT; |
134 | pllout_div_mask = HW_SSCG_DRAM_PLL_DIV_MASK; | 134 | pllout_div_mask = HW_SSCG_DRAM_PLL_DIV_MASK; |
135 | break; | 135 | break; |
136 | default: | 136 | default: |
137 | printf("sscg pll %d not supporte\n", sscg_pll); | 137 | printf("sscg pll %d not supporte\n", sscg_pll); |
138 | return 0; | 138 | return 0; |
139 | } | 139 | } |
140 | 140 | ||
141 | switch (sscg_pll) { | 141 | switch (sscg_pll) { |
142 | case DRAM_PLL1_CLK: | 142 | case DRAM_PLL1_CLK: |
143 | pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK; | 143 | pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK; |
144 | div = 1; | 144 | div = 1; |
145 | break; | 145 | break; |
146 | case SYSTEM_PLL3_CLK: | 146 | case SYSTEM_PLL3_CLK: |
147 | pll_clke = SSCG_PLL_PLL3_CLKE_MASK; | 147 | pll_clke = SSCG_PLL_PLL3_CLKE_MASK; |
148 | div = 1; | 148 | div = 1; |
149 | break; | 149 | break; |
150 | case SYSTEM_PLL2_1000M_CLK: | 150 | case SYSTEM_PLL2_1000M_CLK: |
151 | case SYSTEM_PLL1_800M_CLK: | 151 | case SYSTEM_PLL1_800M_CLK: |
152 | pll_clke = SSCG_PLL_CLKE_MASK; | 152 | pll_clke = SSCG_PLL_CLKE_MASK; |
153 | div = 1; | 153 | div = 1; |
154 | break; | 154 | break; |
155 | case SYSTEM_PLL2_500M_CLK: | 155 | case SYSTEM_PLL2_500M_CLK: |
156 | case SYSTEM_PLL1_400M_CLK: | 156 | case SYSTEM_PLL1_400M_CLK: |
157 | pll_clke = SSCG_PLL_DIV2_CLKE_MASK; | 157 | pll_clke = SSCG_PLL_DIV2_CLKE_MASK; |
158 | div = 2; | 158 | div = 2; |
159 | break; | 159 | break; |
160 | case SYSTEM_PLL2_333M_CLK: | 160 | case SYSTEM_PLL2_333M_CLK: |
161 | case SYSTEM_PLL1_266M_CLK: | 161 | case SYSTEM_PLL1_266M_CLK: |
162 | pll_clke = SSCG_PLL_DIV3_CLKE_MASK; | 162 | pll_clke = SSCG_PLL_DIV3_CLKE_MASK; |
163 | div = 3; | 163 | div = 3; |
164 | break; | 164 | break; |
165 | case SYSTEM_PLL2_250M_CLK: | 165 | case SYSTEM_PLL2_250M_CLK: |
166 | case SYSTEM_PLL1_200M_CLK: | 166 | case SYSTEM_PLL1_200M_CLK: |
167 | pll_clke = SSCG_PLL_DIV4_CLKE_MASK; | 167 | pll_clke = SSCG_PLL_DIV4_CLKE_MASK; |
168 | div = 4; | 168 | div = 4; |
169 | break; | 169 | break; |
170 | case SYSTEM_PLL2_200M_CLK: | 170 | case SYSTEM_PLL2_200M_CLK: |
171 | case SYSTEM_PLL1_160M_CLK: | 171 | case SYSTEM_PLL1_160M_CLK: |
172 | pll_clke = SSCG_PLL_DIV5_CLKE_MASK; | 172 | pll_clke = SSCG_PLL_DIV5_CLKE_MASK; |
173 | div = 5; | 173 | div = 5; |
174 | break; | 174 | break; |
175 | case SYSTEM_PLL2_166M_CLK: | 175 | case SYSTEM_PLL2_166M_CLK: |
176 | case SYSTEM_PLL1_133M_CLK: | 176 | case SYSTEM_PLL1_133M_CLK: |
177 | pll_clke = SSCG_PLL_DIV6_CLKE_MASK; | 177 | pll_clke = SSCG_PLL_DIV6_CLKE_MASK; |
178 | div = 6; | 178 | div = 6; |
179 | break; | 179 | break; |
180 | case SYSTEM_PLL2_125M_CLK: | 180 | case SYSTEM_PLL2_125M_CLK: |
181 | case SYSTEM_PLL1_100M_CLK: | 181 | case SYSTEM_PLL1_100M_CLK: |
182 | pll_clke = SSCG_PLL_DIV8_CLKE_MASK; | 182 | pll_clke = SSCG_PLL_DIV8_CLKE_MASK; |
183 | div = 8; | 183 | div = 8; |
184 | break; | 184 | break; |
185 | case SYSTEM_PLL2_100M_CLK: | 185 | case SYSTEM_PLL2_100M_CLK: |
186 | case SYSTEM_PLL1_80M_CLK: | 186 | case SYSTEM_PLL1_80M_CLK: |
187 | pll_clke = SSCG_PLL_DIV10_CLKE_MASK; | 187 | pll_clke = SSCG_PLL_DIV10_CLKE_MASK; |
188 | div = 10; | 188 | div = 10; |
189 | break; | 189 | break; |
190 | case SYSTEM_PLL2_50M_CLK: | 190 | case SYSTEM_PLL2_50M_CLK: |
191 | case SYSTEM_PLL1_40M_CLK: | 191 | case SYSTEM_PLL1_40M_CLK: |
192 | pll_clke = SSCG_PLL_DIV20_CLKE_MASK; | 192 | pll_clke = SSCG_PLL_DIV20_CLKE_MASK; |
193 | div = 20; | 193 | div = 20; |
194 | break; | 194 | break; |
195 | default: | 195 | default: |
196 | printf("sscg pll %d not supporte\n", sscg_pll); | 196 | printf("sscg pll %d not supporte\n", sscg_pll); |
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | /* Power down */ | 200 | /* Power down */ |
201 | if (pll_cfg0 & SSCG_PLL_PD_MASK) | 201 | if (pll_cfg0 & SSCG_PLL_PD_MASK) |
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | /* output not enabled */ | 204 | /* output not enabled */ |
205 | if ((pll_cfg0 & pll_clke) == 0) | 205 | if ((pll_cfg0 & pll_clke) == 0) |
206 | return 0; | 206 | return 0; |
207 | 207 | ||
208 | pllout_div = readl(&ana_pll->sscg_pllout_div_cfg); | 208 | pllout_div = readl(&ana_pll->sscg_pllout_div_cfg); |
209 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; | 209 | pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift; |
210 | 210 | ||
211 | pll_refclk_sel = pll_cfg0 & SSCG_PLL_REFCLK_SEL_MASK; | 211 | pll_refclk_sel = pll_cfg0 & SSCG_PLL_REFCLK_SEL_MASK; |
212 | 212 | ||
213 | if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_25M) | 213 | if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_25M) |
214 | pll_refclk = 25000000u; | 214 | pll_refclk = 25000000u; |
215 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_27M) | 215 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_27M) |
216 | pll_refclk = 27000000u; | 216 | pll_refclk = 27000000u; |
217 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_HDMI_PHY_27M) | 217 | else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_HDMI_PHY_27M) |
218 | pll_refclk = 27000000u; | 218 | pll_refclk = 27000000u; |
219 | else | 219 | else |
220 | pll_refclk = 0; | 220 | pll_refclk = 0; |
221 | 221 | ||
222 | /* We assume bypass1/2 are the same value */ | 222 | /* We assume bypass1/2 are the same value */ |
223 | if ((pll_cfg0 & SSCG_PLL_BYPASS1_MASK) || | 223 | if ((pll_cfg0 & SSCG_PLL_BYPASS1_MASK) || |
224 | (pll_cfg0 & SSCG_PLL_BYPASS2_MASK)) | 224 | (pll_cfg0 & SSCG_PLL_BYPASS2_MASK)) |
225 | return pll_refclk; | 225 | return pll_refclk; |
226 | 226 | ||
227 | divr1 = (pll_cfg2 & SSCG_PLL_REF_DIVR1_MASK) >> | 227 | divr1 = (pll_cfg2 & SSCG_PLL_REF_DIVR1_MASK) >> |
228 | SSCG_PLL_REF_DIVR1_SHIFT; | 228 | SSCG_PLL_REF_DIVR1_SHIFT; |
229 | divr2 = (pll_cfg2 & SSCG_PLL_REF_DIVR2_MASK) >> | 229 | divr2 = (pll_cfg2 & SSCG_PLL_REF_DIVR2_MASK) >> |
230 | SSCG_PLL_REF_DIVR2_SHIFT; | 230 | SSCG_PLL_REF_DIVR2_SHIFT; |
231 | divf1 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F1_MASK) >> | 231 | divf1 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F1_MASK) >> |
232 | SSCG_PLL_FEEDBACK_DIV_F1_SHIFT; | 232 | SSCG_PLL_FEEDBACK_DIV_F1_SHIFT; |
233 | divf2 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F2_MASK) >> | 233 | divf2 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F2_MASK) >> |
234 | SSCG_PLL_FEEDBACK_DIV_F2_SHIFT; | 234 | SSCG_PLL_FEEDBACK_DIV_F2_SHIFT; |
235 | divq = (pll_cfg2 & SSCG_PLL_OUTPUT_DIV_VAL_MASK) >> | 235 | divq = (pll_cfg2 & SSCG_PLL_OUTPUT_DIV_VAL_MASK) >> |
236 | SSCG_PLL_OUTPUT_DIV_VAL_SHIFT; | 236 | SSCG_PLL_OUTPUT_DIV_VAL_SHIFT; |
237 | sse = pll_cfg1 & SSCG_PLL_SSE_MASK; | 237 | sse = pll_cfg1 & SSCG_PLL_SSE_MASK; |
238 | 238 | ||
239 | if (sse) | 239 | if (sse) |
240 | sse = 8; | 240 | sse = 8; |
241 | else | 241 | else |
242 | sse = 2; | 242 | sse = 2; |
243 | 243 | ||
244 | pllout = pll_refclk / (divr1 + 1) * sse * (divf1 + 1) / | 244 | pllout = pll_refclk / (divr1 + 1) * sse * (divf1 + 1) / |
245 | (divr2 + 1) * (divf2 + 1) / (divq + 1); | 245 | (divr2 + 1) * (divf2 + 1) / (divq + 1); |
246 | 246 | ||
247 | return pllout / (pllout_div + 1) / div; | 247 | return pllout / (pllout_div + 1) / div; |
248 | } | 248 | } |
249 | 249 | ||
250 | static u32 get_root_src_clk(enum clk_root_src root_src) | 250 | static u32 get_root_src_clk(enum clk_root_src root_src) |
251 | { | 251 | { |
252 | switch (root_src) { | 252 | switch (root_src) { |
253 | case OSC_25M_CLK: | 253 | case OSC_25M_CLK: |
254 | return 25000000; | 254 | return 25000000; |
255 | case OSC_27M_CLK: | 255 | case OSC_27M_CLK: |
256 | return 25000000; | 256 | return 25000000; |
257 | case OSC_32K_CLK: | 257 | case OSC_32K_CLK: |
258 | return 32000; | 258 | return 32000; |
259 | case ARM_PLL_CLK: | 259 | case ARM_PLL_CLK: |
260 | return decode_frac_pll(root_src); | 260 | return decode_frac_pll(root_src); |
261 | case SYSTEM_PLL1_800M_CLK: | 261 | case SYSTEM_PLL1_800M_CLK: |
262 | case SYSTEM_PLL1_400M_CLK: | 262 | case SYSTEM_PLL1_400M_CLK: |
263 | case SYSTEM_PLL1_266M_CLK: | 263 | case SYSTEM_PLL1_266M_CLK: |
264 | case SYSTEM_PLL1_200M_CLK: | 264 | case SYSTEM_PLL1_200M_CLK: |
265 | case SYSTEM_PLL1_160M_CLK: | 265 | case SYSTEM_PLL1_160M_CLK: |
266 | case SYSTEM_PLL1_133M_CLK: | 266 | case SYSTEM_PLL1_133M_CLK: |
267 | case SYSTEM_PLL1_100M_CLK: | 267 | case SYSTEM_PLL1_100M_CLK: |
268 | case SYSTEM_PLL1_80M_CLK: | 268 | case SYSTEM_PLL1_80M_CLK: |
269 | case SYSTEM_PLL1_40M_CLK: | 269 | case SYSTEM_PLL1_40M_CLK: |
270 | case SYSTEM_PLL2_1000M_CLK: | 270 | case SYSTEM_PLL2_1000M_CLK: |
271 | case SYSTEM_PLL2_500M_CLK: | 271 | case SYSTEM_PLL2_500M_CLK: |
272 | case SYSTEM_PLL2_333M_CLK: | 272 | case SYSTEM_PLL2_333M_CLK: |
273 | case SYSTEM_PLL2_250M_CLK: | 273 | case SYSTEM_PLL2_250M_CLK: |
274 | case SYSTEM_PLL2_200M_CLK: | 274 | case SYSTEM_PLL2_200M_CLK: |
275 | case SYSTEM_PLL2_166M_CLK: | 275 | case SYSTEM_PLL2_166M_CLK: |
276 | case SYSTEM_PLL2_125M_CLK: | 276 | case SYSTEM_PLL2_125M_CLK: |
277 | case SYSTEM_PLL2_100M_CLK: | 277 | case SYSTEM_PLL2_100M_CLK: |
278 | case SYSTEM_PLL2_50M_CLK: | 278 | case SYSTEM_PLL2_50M_CLK: |
279 | case SYSTEM_PLL3_CLK: | 279 | case SYSTEM_PLL3_CLK: |
280 | return decode_sscg_pll(root_src); | 280 | return decode_sscg_pll(root_src); |
281 | default: | 281 | default: |
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | return 0; | 285 | return 0; |
286 | } | 286 | } |
287 | 287 | ||
288 | static u32 get_root_clk(enum clk_root_index clock_id) | 288 | static u32 get_root_clk(enum clk_root_index clock_id) |
289 | { | 289 | { |
290 | enum clk_root_src root_src; | 290 | enum clk_root_src root_src; |
291 | u32 post_podf, pre_podf, root_src_clk; | 291 | u32 post_podf, pre_podf, root_src_clk; |
292 | 292 | ||
293 | if (clock_root_enabled(clock_id) <= 0) | 293 | if (clock_root_enabled(clock_id) <= 0) |
294 | return 0; | 294 | return 0; |
295 | 295 | ||
296 | if (clock_get_prediv(clock_id, &pre_podf) < 0) | 296 | if (clock_get_prediv(clock_id, &pre_podf) < 0) |
297 | return 0; | 297 | return 0; |
298 | 298 | ||
299 | if (clock_get_postdiv(clock_id, &post_podf) < 0) | 299 | if (clock_get_postdiv(clock_id, &post_podf) < 0) |
300 | return 0; | 300 | return 0; |
301 | 301 | ||
302 | if (clock_get_src(clock_id, &root_src) < 0) | 302 | if (clock_get_src(clock_id, &root_src) < 0) |
303 | return 0; | 303 | return 0; |
304 | 304 | ||
305 | root_src_clk = get_root_src_clk(root_src); | 305 | root_src_clk = get_root_src_clk(root_src); |
306 | 306 | ||
307 | return root_src_clk / (post_podf + 1) / (pre_podf + 1); | 307 | return root_src_clk / (post_podf + 1) / (pre_podf + 1); |
308 | } | 308 | } |
309 | 309 | ||
310 | #ifdef CONFIG_SECURE_BOOT | 310 | #ifdef CONFIG_SECURE_BOOT |
311 | void hab_caam_clock_enable(unsigned char enable) | 311 | void hab_caam_clock_enable(unsigned char enable) |
312 | { | 312 | { |
313 | /* The CAAM clock is always on for iMX8M */ | 313 | /* The CAAM clock is always on for iMX8M */ |
314 | } | 314 | } |
315 | #endif | 315 | #endif |
316 | 316 | ||
317 | #ifdef CONFIG_MXC_OCOTP | 317 | #ifdef CONFIG_MXC_OCOTP |
318 | void enable_ocotp_clk(unsigned char enable) | 318 | void enable_ocotp_clk(unsigned char enable) |
319 | { | 319 | { |
320 | clock_enable(CCGR_OCOTP, !!enable); | 320 | clock_enable(CCGR_OCOTP, !!enable); |
321 | } | 321 | } |
322 | #endif | 322 | #endif |
323 | 323 | ||
324 | int enable_i2c_clk(unsigned char enable, unsigned int i2c_num) | 324 | int enable_i2c_clk(unsigned char enable, unsigned int i2c_num) |
325 | { | 325 | { |
326 | /* 0 - 3 is valid i2c num */ | 326 | /* 0 - 3 is valid i2c num */ |
327 | if (i2c_num > 3) | 327 | if (i2c_num > 3) |
328 | return -EINVAL; | 328 | return -EINVAL; |
329 | 329 | ||
330 | clock_enable(CCGR_I2C1 + i2c_num, !!enable); | 330 | clock_enable(CCGR_I2C1 + i2c_num, !!enable); |
331 | 331 | ||
332 | return 0; | 332 | return 0; |
333 | } | 333 | } |
334 | 334 | ||
335 | unsigned int mxc_get_clock(enum clk_root_index clk) | 335 | unsigned int mxc_get_clock(enum clk_root_index clk) |
336 | { | 336 | { |
337 | u32 val; | 337 | u32 val; |
338 | 338 | ||
339 | if (clk >= CLK_ROOT_MAX) | 339 | if (clk >= CLK_ROOT_MAX) |
340 | return 0; | 340 | return 0; |
341 | 341 | ||
342 | if (clk == MXC_ARM_CLK) | 342 | if (clk == MXC_ARM_CLK) |
343 | return get_root_clk(ARM_A53_CLK_ROOT); | 343 | return get_root_clk(ARM_A53_CLK_ROOT); |
344 | 344 | ||
345 | if (clk == MXC_IPG_CLK) { | 345 | if (clk == MXC_IPG_CLK) { |
346 | clock_get_target_val(IPG_CLK_ROOT, &val); | 346 | clock_get_target_val(IPG_CLK_ROOT, &val); |
347 | val = val & 0x3; | 347 | val = val & 0x3; |
348 | return get_root_clk(AHB_CLK_ROOT) / (val + 1); | 348 | return get_root_clk(AHB_CLK_ROOT) / (val + 1); |
349 | } | 349 | } |
350 | 350 | ||
351 | return get_root_clk(clk); | 351 | return get_root_clk(clk); |
352 | } | 352 | } |
353 | 353 | ||
354 | u32 imx_get_uartclk(void) | 354 | u32 imx_get_uartclk(void) |
355 | { | 355 | { |
356 | return mxc_get_clock(UART1_CLK_ROOT); | 356 | return mxc_get_clock(UART1_CLK_ROOT); |
357 | } | 357 | } |
358 | 358 | ||
359 | void mxs_set_lcdclk(u32 base_addr, u32 freq) | 359 | void mxs_set_lcdclk(u32 base_addr, u32 freq) |
360 | { | 360 | { |
361 | /* | 361 | /* |
362 | * LCDIF_PIXEL_CLK: select 800MHz root clock, | 362 | * LCDIF_PIXEL_CLK: select 800MHz root clock, |
363 | * select pre divider 8, output is 100 MHz | 363 | * select pre divider 8, output is 100 MHz |
364 | */ | 364 | */ |
365 | clock_set_target_val(LCDIF_PIXEL_CLK_ROOT, CLK_ROOT_ON | | 365 | clock_set_target_val(LCDIF_PIXEL_CLK_ROOT, CLK_ROOT_ON | |
366 | CLK_ROOT_SOURCE_SEL(4) | | 366 | CLK_ROOT_SOURCE_SEL(4) | |
367 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV8)); | 367 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV8)); |
368 | } | 368 | } |
369 | 369 | ||
370 | void init_wdog_clk(void) | 370 | void init_wdog_clk(void) |
371 | { | 371 | { |
372 | clock_enable(CCGR_WDOG1, 0); | 372 | clock_enable(CCGR_WDOG1, 0); |
373 | clock_enable(CCGR_WDOG2, 0); | 373 | clock_enable(CCGR_WDOG2, 0); |
374 | clock_enable(CCGR_WDOG3, 0); | 374 | clock_enable(CCGR_WDOG3, 0); |
375 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | 375 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | |
376 | CLK_ROOT_SOURCE_SEL(0)); | 376 | CLK_ROOT_SOURCE_SEL(0)); |
377 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | 377 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | |
378 | CLK_ROOT_SOURCE_SEL(0)); | 378 | CLK_ROOT_SOURCE_SEL(0)); |
379 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | | 379 | clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON | |
380 | CLK_ROOT_SOURCE_SEL(0)); | 380 | CLK_ROOT_SOURCE_SEL(0)); |
381 | clock_enable(CCGR_WDOG1, 1); | 381 | clock_enable(CCGR_WDOG1, 1); |
382 | clock_enable(CCGR_WDOG2, 1); | 382 | clock_enable(CCGR_WDOG2, 1); |
383 | clock_enable(CCGR_WDOG3, 1); | 383 | clock_enable(CCGR_WDOG3, 1); |
384 | } | 384 | } |
385 | 385 | ||
386 | void init_usb_clk(void) | 386 | void init_usb_clk(void) |
387 | { | 387 | { |
388 | if (!is_usb_boot()) { | 388 | if (!is_usb_boot()) { |
389 | clock_enable(CCGR_USB_CTRL1, 0); | 389 | clock_enable(CCGR_USB_CTRL1, 0); |
390 | clock_enable(CCGR_USB_CTRL2, 0); | 390 | clock_enable(CCGR_USB_CTRL2, 0); |
391 | clock_enable(CCGR_USB_PHY1, 0); | 391 | clock_enable(CCGR_USB_PHY1, 0); |
392 | clock_enable(CCGR_USB_PHY2, 0); | 392 | clock_enable(CCGR_USB_PHY2, 0); |
393 | /* 500MHz */ | 393 | /* 500MHz */ |
394 | clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON | | 394 | clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON | |
395 | CLK_ROOT_SOURCE_SEL(1)); | 395 | CLK_ROOT_SOURCE_SEL(1)); |
396 | /* 100MHz */ | 396 | /* 100MHz */ |
397 | clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON | | 397 | clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON | |
398 | CLK_ROOT_SOURCE_SEL(1)); | 398 | CLK_ROOT_SOURCE_SEL(1)); |
399 | /* 100MHz */ | 399 | /* 100MHz */ |
400 | clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON | | 400 | clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON | |
401 | CLK_ROOT_SOURCE_SEL(1)); | 401 | CLK_ROOT_SOURCE_SEL(1)); |
402 | clock_enable(CCGR_USB_CTRL1, 1); | 402 | clock_enable(CCGR_USB_CTRL1, 1); |
403 | clock_enable(CCGR_USB_CTRL2, 1); | 403 | clock_enable(CCGR_USB_CTRL2, 1); |
404 | clock_enable(CCGR_USB_PHY1, 1); | 404 | clock_enable(CCGR_USB_PHY1, 1); |
405 | clock_enable(CCGR_USB_PHY2, 1); | 405 | clock_enable(CCGR_USB_PHY2, 1); |
406 | } | 406 | } |
407 | } | 407 | } |
408 | 408 | ||
409 | void init_nand_clk(void) | 409 | void init_nand_clk(void) |
410 | { | 410 | { |
411 | /* | 411 | /* |
412 | * set rawnand root | 412 | * set rawnand root |
413 | * sys pll1 400M | 413 | * sys pll1 400M |
414 | */ | 414 | */ |
415 | clock_enable(CCGR_RAWNAND, 0); | 415 | clock_enable(CCGR_RAWNAND, 0); |
416 | clock_set_target_val(NAND_CLK_ROOT, CLK_ROOT_ON | | 416 | clock_set_target_val(NAND_CLK_ROOT, CLK_ROOT_ON | |
417 | CLK_ROOT_SOURCE_SEL(3) | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4)); /* 100M */ | 417 | CLK_ROOT_SOURCE_SEL(3) | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4)); /* 100M */ |
418 | clock_enable(CCGR_RAWNAND, 1); | 418 | clock_enable(CCGR_RAWNAND, 1); |
419 | } | 419 | } |
420 | 420 | ||
421 | void init_uart_clk(u32 index) | 421 | void init_uart_clk(u32 index) |
422 | { | 422 | { |
423 | /* Set uart clock root 25M OSC */ | 423 | /* Set uart clock root 25M OSC */ |
424 | switch (index) { | 424 | switch (index) { |
425 | case 0: | 425 | case 0: |
426 | clock_enable(CCGR_UART1, 0); | 426 | clock_enable(CCGR_UART1, 0); |
427 | clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON | | 427 | clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON | |
428 | CLK_ROOT_SOURCE_SEL(0)); | 428 | CLK_ROOT_SOURCE_SEL(0)); |
429 | clock_enable(CCGR_UART1, 1); | 429 | clock_enable(CCGR_UART1, 1); |
430 | return; | 430 | return; |
431 | case 1: | 431 | case 1: |
432 | clock_enable(CCGR_UART2, 0); | 432 | clock_enable(CCGR_UART2, 0); |
433 | clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON | | 433 | clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON | |
434 | CLK_ROOT_SOURCE_SEL(0)); | 434 | CLK_ROOT_SOURCE_SEL(0)); |
435 | clock_enable(CCGR_UART2, 1); | 435 | clock_enable(CCGR_UART2, 1); |
436 | return; | 436 | return; |
437 | case 2: | 437 | case 2: |
438 | clock_enable(CCGR_UART3, 0); | 438 | clock_enable(CCGR_UART3, 0); |
439 | clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON | | 439 | clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON | |
440 | CLK_ROOT_SOURCE_SEL(0)); | 440 | CLK_ROOT_SOURCE_SEL(0)); |
441 | clock_enable(CCGR_UART3, 1); | 441 | clock_enable(CCGR_UART3, 1); |
442 | return; | 442 | return; |
443 | case 3: | 443 | case 3: |
444 | clock_enable(CCGR_UART4, 0); | 444 | clock_enable(CCGR_UART4, 0); |
445 | clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON | | 445 | clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON | |
446 | CLK_ROOT_SOURCE_SEL(0)); | 446 | CLK_ROOT_SOURCE_SEL(0)); |
447 | clock_enable(CCGR_UART4, 1); | 447 | clock_enable(CCGR_UART4, 1); |
448 | return; | 448 | return; |
449 | default: | 449 | default: |
450 | printf("Invalid uart index\n"); | 450 | printf("Invalid uart index\n"); |
451 | return; | 451 | return; |
452 | } | 452 | } |
453 | } | 453 | } |
454 | 454 | ||
455 | void init_clk_usdhc(u32 index) | 455 | void init_clk_usdhc(u32 index) |
456 | { | 456 | { |
457 | /* | 457 | /* |
458 | * set usdhc clock root | 458 | * set usdhc clock root |
459 | * sys pll1 400M | 459 | * sys pll1 400M |
460 | */ | 460 | */ |
461 | switch (index) { | 461 | switch (index) { |
462 | case 0: | 462 | case 0: |
463 | clock_enable(CCGR_USDHC1, 0); | 463 | clock_enable(CCGR_USDHC1, 0); |
464 | clock_set_target_val(USDHC1_CLK_ROOT, CLK_ROOT_ON | | 464 | clock_set_target_val(USDHC1_CLK_ROOT, CLK_ROOT_ON | |
465 | CLK_ROOT_SOURCE_SEL(1) | | 465 | CLK_ROOT_SOURCE_SEL(1) | |
466 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | 466 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); |
467 | clock_enable(CCGR_USDHC1, 1); | 467 | clock_enable(CCGR_USDHC1, 1); |
468 | return; | 468 | return; |
469 | case 1: | 469 | case 1: |
470 | clock_enable(CCGR_USDHC2, 0); | 470 | clock_enable(CCGR_USDHC2, 0); |
471 | clock_set_target_val(USDHC2_CLK_ROOT, CLK_ROOT_ON | | 471 | clock_set_target_val(USDHC2_CLK_ROOT, CLK_ROOT_ON | |
472 | CLK_ROOT_SOURCE_SEL(1) | | 472 | CLK_ROOT_SOURCE_SEL(1) | |
473 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | 473 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); |
474 | clock_enable(CCGR_USDHC2, 1); | 474 | clock_enable(CCGR_USDHC2, 1); |
475 | return; | 475 | return; |
476 | default: | 476 | default: |
477 | printf("Invalid usdhc index\n"); | 477 | printf("Invalid usdhc index\n"); |
478 | return; | 478 | return; |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
482 | int set_clk_qspi(void) | 482 | int set_clk_qspi(void) |
483 | { | 483 | { |
484 | /* | 484 | /* |
485 | * set qspi root | 485 | * set qspi root |
486 | * sys pll1 100M | 486 | * sys pll1 100M |
487 | */ | 487 | */ |
488 | clock_enable(CCGR_QSPI, 0); | 488 | clock_enable(CCGR_QSPI, 0); |
489 | clock_set_target_val(QSPI_CLK_ROOT, CLK_ROOT_ON | | 489 | clock_set_target_val(QSPI_CLK_ROOT, CLK_ROOT_ON | |
490 | CLK_ROOT_SOURCE_SEL(7)); | 490 | CLK_ROOT_SOURCE_SEL(7)); |
491 | clock_enable(CCGR_QSPI, 1); | 491 | clock_enable(CCGR_QSPI, 1); |
492 | 492 | ||
493 | return 0; | 493 | return 0; |
494 | } | 494 | } |
495 | 495 | ||
496 | #ifdef CONFIG_FEC_MXC | 496 | #ifdef CONFIG_FEC_MXC |
497 | int set_clk_enet(enum enet_freq type) | 497 | int set_clk_enet(enum enet_freq type) |
498 | { | 498 | { |
499 | u32 target; | 499 | u32 target; |
500 | u32 enet1_ref; | 500 | u32 enet1_ref; |
501 | 501 | ||
502 | switch (type) { | 502 | switch (type) { |
503 | case ENET_125MHZ: | 503 | case ENET_125MHZ: |
504 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; | 504 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK; |
505 | break; | 505 | break; |
506 | case ENET_50MHZ: | 506 | case ENET_50MHZ: |
507 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; | 507 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK; |
508 | break; | 508 | break; |
509 | case ENET_25MHZ: | 509 | case ENET_25MHZ: |
510 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; | 510 | enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK; |
511 | break; | 511 | break; |
512 | default: | 512 | default: |
513 | return -EINVAL; | 513 | return -EINVAL; |
514 | } | 514 | } |
515 | 515 | ||
516 | /* disable the clock first */ | 516 | /* disable the clock first */ |
517 | clock_enable(CCGR_ENET1, 0); | 517 | clock_enable(CCGR_ENET1, 0); |
518 | clock_enable(CCGR_SIM_ENET, 0); | 518 | clock_enable(CCGR_SIM_ENET, 0); |
519 | 519 | ||
520 | /* set enet axi clock 266Mhz */ | 520 | /* set enet axi clock 266Mhz */ |
521 | target = CLK_ROOT_ON | ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M | | 521 | target = CLK_ROOT_ON | ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M | |
522 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | 522 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | |
523 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); | 523 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); |
524 | clock_set_target_val(ENET_AXI_CLK_ROOT, target); | 524 | clock_set_target_val(ENET_AXI_CLK_ROOT, target); |
525 | 525 | ||
526 | target = CLK_ROOT_ON | enet1_ref | | 526 | target = CLK_ROOT_ON | enet1_ref | |
527 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | 527 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | |
528 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); | 528 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1); |
529 | clock_set_target_val(ENET_REF_CLK_ROOT, target); | 529 | clock_set_target_val(ENET_REF_CLK_ROOT, target); |
530 | 530 | ||
531 | target = CLK_ROOT_ON | | 531 | target = CLK_ROOT_ON | |
532 | ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK | | 532 | ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK | |
533 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | | 533 | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) | |
534 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4); | 534 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4); |
535 | clock_set_target_val(ENET_TIMER_CLK_ROOT, target); | 535 | clock_set_target_val(ENET_TIMER_CLK_ROOT, target); |
536 | 536 | ||
537 | /* enable clock */ | 537 | /* enable clock */ |
538 | clock_enable(CCGR_SIM_ENET, 1); | 538 | clock_enable(CCGR_SIM_ENET, 1); |
539 | clock_enable(CCGR_ENET1, 1); | 539 | clock_enable(CCGR_ENET1, 1); |
540 | 540 | ||
541 | return 0; | 541 | return 0; |
542 | } | 542 | } |
543 | #endif | 543 | #endif |
544 | 544 | ||
545 | u32 imx_get_fecclk(void) | 545 | u32 imx_get_fecclk(void) |
546 | { | 546 | { |
547 | return get_root_clk(ENET_AXI_CLK_ROOT); | 547 | return get_root_clk(ENET_AXI_CLK_ROOT); |
548 | } | 548 | } |
549 | 549 | ||
550 | #define DRAM_BYPASS_ROOT_CONFIG(_rate, _m, _p, _s, _k) \ | 550 | #define DRAM_BYPASS_ROOT_CONFIG(_rate, _m, _p, _s, _k) \ |
551 | { \ | 551 | { \ |
552 | .clk = (_rate), \ | 552 | .clk = (_rate), \ |
553 | .alt_root_sel = (_m), \ | 553 | .alt_root_sel = (_m), \ |
554 | .alt_pre_div = (_p), \ | 554 | .alt_pre_div = (_p), \ |
555 | .apb_root_sel = (_s), \ | 555 | .apb_root_sel = (_s), \ |
556 | .apb_pre_div = (_k), \ | 556 | .apb_pre_div = (_k), \ |
557 | } | 557 | } |
558 | 558 | ||
559 | struct dram_bypass_clk_setting { | 559 | struct dram_bypass_clk_setting { |
560 | enum dram_bypassclk_val clk; | 560 | enum dram_bypassclk_val clk; |
561 | int alt_root_sel; | 561 | int alt_root_sel; |
562 | enum root_pre_div alt_pre_div; | 562 | enum root_pre_div alt_pre_div; |
563 | int apb_root_sel; | 563 | int apb_root_sel; |
564 | enum root_pre_div apb_pre_div; | 564 | enum root_pre_div apb_pre_div; |
565 | }; | 565 | }; |
566 | 566 | ||
567 | static struct dram_bypass_clk_setting imx8mm_dram_bypass_tbl[] = { | 567 | static struct dram_bypass_clk_setting imx8mm_dram_bypass_tbl[] = { |
568 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_100M, 2, CLK_ROOT_PRE_DIV1, 2, CLK_ROOT_PRE_DIV2), | 568 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_100M, 2, CLK_ROOT_PRE_DIV1, 2, CLK_ROOT_PRE_DIV2), |
569 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_250M, 3, CLK_ROOT_PRE_DIV2, 2, CLK_ROOT_PRE_DIV2), | 569 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_250M, 3, CLK_ROOT_PRE_DIV2, 2, CLK_ROOT_PRE_DIV2), |
570 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_400M, 1, CLK_ROOT_PRE_DIV2, 3, CLK_ROOT_PRE_DIV2), | 570 | DRAM_BYPASS_ROOT_CONFIG(DRAM_BYPASSCLK_400M, 1, CLK_ROOT_PRE_DIV2, 3, CLK_ROOT_PRE_DIV2), |
571 | }; | 571 | }; |
572 | 572 | ||
573 | void dram_enable_bypass(enum dram_bypassclk_val clk_val) | 573 | void dram_enable_bypass(enum dram_bypassclk_val clk_val) |
574 | { | 574 | { |
575 | int i; | 575 | int i; |
576 | struct dram_bypass_clk_setting *config; | 576 | struct dram_bypass_clk_setting *config; |
577 | 577 | ||
578 | for (i = 0; i < ARRAY_SIZE(imx8mm_dram_bypass_tbl); i++) { | 578 | for (i = 0; i < ARRAY_SIZE(imx8mm_dram_bypass_tbl); i++) { |
579 | if (clk_val == imx8mm_dram_bypass_tbl[i].clk) | 579 | if (clk_val == imx8mm_dram_bypass_tbl[i].clk) |
580 | break; | 580 | break; |
581 | } | 581 | } |
582 | 582 | ||
583 | if (i == ARRAY_SIZE(imx8mm_dram_bypass_tbl)) { | 583 | if (i == ARRAY_SIZE(imx8mm_dram_bypass_tbl)) { |
584 | printf("No matched freq table %u\n", clk_val); | 584 | printf("No matched freq table %u\n", clk_val); |
585 | return; | 585 | return; |
586 | } | 586 | } |
587 | 587 | ||
588 | config = &imx8mm_dram_bypass_tbl[i]; | 588 | config = &imx8mm_dram_bypass_tbl[i]; |
589 | 589 | ||
590 | clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | CLK_ROOT_PRE_DIV(config->alt_pre_div)); | 590 | clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(config->alt_root_sel) | CLK_ROOT_PRE_DIV(config->alt_pre_div)); |
591 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | CLK_ROOT_PRE_DIV(config->apb_pre_div)); | 591 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(config->apb_root_sel) | CLK_ROOT_PRE_DIV(config->apb_pre_div)); |
592 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); | 592 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); |
593 | } | 593 | } |
594 | 594 | ||
595 | void dram_disable_bypass(void) | 595 | void dram_disable_bypass(void) |
596 | { | 596 | { |
597 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(0)); | 597 | clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(0)); |
598 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); | 598 | clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5)); |
599 | } | 599 | } |
600 | 600 | ||
601 | #ifdef CONFIG_SPL_BUILD | 601 | #ifdef CONFIG_SPL_BUILD |
602 | void dram_pll_init(enum dram_pll_out_val pll_val) | 602 | void dram_pll_init(enum dram_pll_out_val pll_val) |
603 | { | 603 | { |
604 | u32 val; | 604 | u32 val; |
605 | void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; | 605 | void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0; |
606 | void __iomem *pll_cfg_reg2 = &ana_pll->dram_pll_cfg2; | 606 | void __iomem *pll_cfg_reg2 = &ana_pll->dram_pll_cfg2; |
607 | 607 | ||
608 | /* Bypass */ | 608 | /* Bypass */ |
609 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); | 609 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); |
610 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); | 610 | setbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); |
611 | 611 | ||
612 | switch (pll_val) { | 612 | switch (pll_val) { |
613 | case DRAM_PLL_OUT_800M: | 613 | case DRAM_PLL_OUT_800M: |
614 | val = readl(pll_cfg_reg2); | 614 | val = readl(pll_cfg_reg2); |
615 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | 615 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | |
616 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); | 616 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); |
617 | val |= SSCG_PLL_OUTPUT_DIV_VAL(0); | 617 | val |= SSCG_PLL_OUTPUT_DIV_VAL(0); |
618 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); | 618 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); |
619 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | 619 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); |
620 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | 620 | val |= SSCG_PLL_REF_DIVR2_VAL(29); |
621 | writel(val, pll_cfg_reg2); | 621 | writel(val, pll_cfg_reg2); |
622 | break; | 622 | break; |
623 | case DRAM_PLL_OUT_600M: | 623 | case DRAM_PLL_OUT_600M: |
624 | val = readl(pll_cfg_reg2); | 624 | val = readl(pll_cfg_reg2); |
625 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | 625 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | |
626 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); | 626 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); |
627 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); | 627 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); |
628 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17); | 628 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17); |
629 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | 629 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); |
630 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | 630 | val |= SSCG_PLL_REF_DIVR2_VAL(29); |
631 | writel(val, pll_cfg_reg2); | 631 | writel(val, pll_cfg_reg2); |
632 | break; | 632 | break; |
633 | case DRAM_PLL_OUT_400M: | 633 | case DRAM_PLL_OUT_400M: |
634 | val = readl(pll_cfg_reg2); | 634 | val = readl(pll_cfg_reg2); |
635 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | 635 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | |
636 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); | 636 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); |
637 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); | 637 | val |= SSCG_PLL_OUTPUT_DIV_VAL(1); |
638 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); | 638 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11); |
639 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); | 639 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39); |
640 | val |= SSCG_PLL_REF_DIVR2_VAL(29); | 640 | val |= SSCG_PLL_REF_DIVR2_VAL(29); |
641 | writel(val, pll_cfg_reg2); | 641 | writel(val, pll_cfg_reg2); |
642 | break; | 642 | break; |
643 | case DRAM_PLL_OUT_167M: | 643 | case DRAM_PLL_OUT_167M: |
644 | val = readl(pll_cfg_reg2); | 644 | val = readl(pll_cfg_reg2); |
645 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | | 645 | val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK | SSCG_PLL_FEEDBACK_DIV_F2_MASK | |
646 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); | 646 | SSCG_PLL_FEEDBACK_DIV_F1_MASK | SSCG_PLL_REF_DIVR2_MASK); |
647 | val |= SSCG_PLL_OUTPUT_DIV_VAL(3); | 647 | val |= SSCG_PLL_OUTPUT_DIV_VAL(3); |
648 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8); | 648 | val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8); |
649 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45); | 649 | val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45); |
650 | val |= SSCG_PLL_REF_DIVR2_VAL(30); | 650 | val |= SSCG_PLL_REF_DIVR2_VAL(30); |
651 | writel(val, pll_cfg_reg2); | 651 | writel(val, pll_cfg_reg2); |
652 | break; | 652 | break; |
653 | default: | 653 | default: |
654 | break; | 654 | break; |
655 | } | 655 | } |
656 | 656 | ||
657 | /* Clear power down bit */ | 657 | /* Clear power down bit */ |
658 | clrbits_le32(pll_control_reg, SSCG_PLL_PD_MASK); | 658 | clrbits_le32(pll_control_reg, SSCG_PLL_PD_MASK); |
659 | /* Eanble ARM_PLL/SYS_PLL */ | 659 | /* Eanble ARM_PLL/SYS_PLL */ |
660 | setbits_le32(pll_control_reg, SSCG_PLL_DRAM_PLL_CLKE_MASK); | 660 | setbits_le32(pll_control_reg, SSCG_PLL_DRAM_PLL_CLKE_MASK); |
661 | 661 | ||
662 | /* Clear bypass */ | 662 | /* Clear bypass */ |
663 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); | 663 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS1_MASK); |
664 | __udelay(100); | 664 | __udelay(100); |
665 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); | 665 | clrbits_le32(pll_control_reg, SSCG_PLL_BYPASS2_MASK); |
666 | /* Wait lock */ | 666 | /* Wait lock */ |
667 | while (!(readl(pll_control_reg) & SSCG_PLL_LOCK_MASK)) | 667 | while (!(readl(pll_control_reg) & SSCG_PLL_LOCK_MASK)) |
668 | ; | 668 | ; |
669 | } | 669 | } |
670 | 670 | ||
671 | int frac_pll_init(u32 pll, enum frac_pll_out_val val) | 671 | int frac_pll_init(u32 pll, enum frac_pll_out_val val) |
672 | { | 672 | { |
673 | void __iomem *pll_cfg0, __iomem *pll_cfg1; | 673 | void __iomem *pll_cfg0, __iomem *pll_cfg1; |
674 | u32 val_cfg0, val_cfg1; | 674 | u32 val_cfg0, val_cfg1; |
675 | int ret; | 675 | int ret; |
676 | 676 | ||
677 | switch (pll) { | 677 | switch (pll) { |
678 | case ANATOP_ARM_PLL: | 678 | case ANATOP_ARM_PLL: |
679 | pll_cfg0 = &ana_pll->arm_pll_cfg0; | 679 | pll_cfg0 = &ana_pll->arm_pll_cfg0; |
680 | pll_cfg1 = &ana_pll->arm_pll_cfg1; | 680 | pll_cfg1 = &ana_pll->arm_pll_cfg1; |
681 | 681 | ||
682 | if (val == FRAC_PLL_OUT_1000M) | 682 | if (val == FRAC_PLL_OUT_1000M) |
683 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(49); | 683 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(49); |
684 | else | 684 | else |
685 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(79); | 685 | val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(79); |
686 | val_cfg0 = FRAC_PLL_CLKE_MASK | FRAC_PLL_REFCLK_SEL_OSC_25M | | 686 | val_cfg0 = FRAC_PLL_CLKE_MASK | FRAC_PLL_REFCLK_SEL_OSC_25M | |
687 | FRAC_PLL_LOCK_SEL_MASK | FRAC_PLL_NEWDIV_VAL_MASK | | 687 | FRAC_PLL_LOCK_SEL_MASK | FRAC_PLL_NEWDIV_VAL_MASK | |
688 | FRAC_PLL_REFCLK_DIV_VAL(4) | | 688 | FRAC_PLL_REFCLK_DIV_VAL(4) | |
689 | FRAC_PLL_OUTPUT_DIV_VAL(0); | 689 | FRAC_PLL_OUTPUT_DIV_VAL(0); |
690 | break; | 690 | break; |
691 | default: | 691 | default: |
692 | return -EINVAL; | 692 | return -EINVAL; |
693 | } | 693 | } |
694 | 694 | ||
695 | /* bypass the clock */ | 695 | /* bypass the clock */ |
696 | setbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); | 696 | setbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); |
697 | /* Set the value */ | 697 | /* Set the value */ |
698 | writel(val_cfg1, pll_cfg1); | 698 | writel(val_cfg1, pll_cfg1); |
699 | writel(val_cfg0 | FRAC_PLL_BYPASS_MASK, pll_cfg0); | 699 | writel(val_cfg0 | FRAC_PLL_BYPASS_MASK, pll_cfg0); |
700 | val_cfg0 = readl(pll_cfg0); | 700 | val_cfg0 = readl(pll_cfg0); |
701 | /* unbypass the clock */ | 701 | /* unbypass the clock */ |
702 | clrbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); | 702 | clrbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK); |
703 | ret = readl_poll_timeout(pll_cfg0, val_cfg0, | 703 | ret = readl_poll_timeout(pll_cfg0, val_cfg0, |
704 | val_cfg0 & FRAC_PLL_LOCK_MASK, 1); | 704 | val_cfg0 & FRAC_PLL_LOCK_MASK, 1); |
705 | if (ret) | 705 | if (ret) |
706 | printf("%s timeout\n", __func__); | 706 | printf("%s timeout\n", __func__); |
707 | clrbits_le32(pll_cfg0, FRAC_PLL_NEWDIV_VAL_MASK); | 707 | clrbits_le32(pll_cfg0, FRAC_PLL_NEWDIV_VAL_MASK); |
708 | 708 | ||
709 | return 0; | 709 | return 0; |
710 | } | 710 | } |
711 | 711 | ||
712 | int sscg_pll_init(u32 pll) | 712 | int sscg_pll_init(u32 pll) |
713 | { | 713 | { |
714 | void __iomem *pll_cfg0, __iomem *pll_cfg1, __iomem *pll_cfg2; | 714 | void __iomem *pll_cfg0, __iomem *pll_cfg1, __iomem *pll_cfg2; |
715 | u32 val_cfg0, val_cfg1, val_cfg2, val; | 715 | u32 val_cfg0, val_cfg1, val_cfg2, val; |
716 | u32 bypass1_mask = 0x20, bypass2_mask = 0x10; | 716 | u32 bypass1_mask = 0x20, bypass2_mask = 0x10; |
717 | int ret; | 717 | int ret; |
718 | 718 | ||
719 | switch (pll) { | 719 | switch (pll) { |
720 | case ANATOP_SYSTEM_PLL1: | 720 | case ANATOP_SYSTEM_PLL1: |
721 | pll_cfg0 = &ana_pll->sys_pll1_cfg0; | 721 | pll_cfg0 = &ana_pll->sys_pll1_cfg0; |
722 | pll_cfg1 = &ana_pll->sys_pll1_cfg1; | 722 | pll_cfg1 = &ana_pll->sys_pll1_cfg1; |
723 | pll_cfg2 = &ana_pll->sys_pll1_cfg2; | 723 | pll_cfg2 = &ana_pll->sys_pll1_cfg2; |
724 | /* 800MHz */ | 724 | /* 800MHz */ |
725 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | 725 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | |
726 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); | 726 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); |
727 | val_cfg1 = 0; | 727 | val_cfg1 = 0; |
728 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | | 728 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | |
729 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | | 729 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | |
730 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | | 730 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | |
731 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | | 731 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | |
732 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | 732 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | |
733 | SSCG_PLL_REFCLK_SEL_OSC_25M; | 733 | SSCG_PLL_REFCLK_SEL_OSC_25M; |
734 | break; | 734 | break; |
735 | case ANATOP_SYSTEM_PLL2: | 735 | case ANATOP_SYSTEM_PLL2: |
736 | pll_cfg0 = &ana_pll->sys_pll2_cfg0; | 736 | pll_cfg0 = &ana_pll->sys_pll2_cfg0; |
737 | pll_cfg1 = &ana_pll->sys_pll2_cfg1; | 737 | pll_cfg1 = &ana_pll->sys_pll2_cfg1; |
738 | pll_cfg2 = &ana_pll->sys_pll2_cfg2; | 738 | pll_cfg2 = &ana_pll->sys_pll2_cfg2; |
739 | /* 1000MHz */ | 739 | /* 1000MHz */ |
740 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | 740 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | |
741 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(4); | 741 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(4); |
742 | val_cfg1 = 0; | 742 | val_cfg1 = 0; |
743 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | | 743 | val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK | |
744 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | | 744 | SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK | |
745 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | | 745 | SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK | |
746 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | | 746 | SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK | |
747 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | 747 | SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | |
748 | SSCG_PLL_REFCLK_SEL_OSC_25M; | 748 | SSCG_PLL_REFCLK_SEL_OSC_25M; |
749 | break; | 749 | break; |
750 | case ANATOP_SYSTEM_PLL3: | 750 | case ANATOP_SYSTEM_PLL3: |
751 | pll_cfg0 = &ana_pll->sys_pll3_cfg0; | 751 | pll_cfg0 = &ana_pll->sys_pll3_cfg0; |
752 | pll_cfg1 = &ana_pll->sys_pll3_cfg1; | 752 | pll_cfg1 = &ana_pll->sys_pll3_cfg1; |
753 | pll_cfg2 = &ana_pll->sys_pll3_cfg2; | 753 | pll_cfg2 = &ana_pll->sys_pll3_cfg2; |
754 | /* 800MHz */ | 754 | /* 800MHz */ |
755 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | | 755 | val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) | |
756 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); | 756 | SSCG_PLL_FEEDBACK_DIV_F2_VAL(3); |
757 | val_cfg1 = 0; | 757 | val_cfg1 = 0; |
758 | val_cfg0 = SSCG_PLL_PLL3_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | | 758 | val_cfg0 = SSCG_PLL_PLL3_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK | |
759 | SSCG_PLL_REFCLK_SEL_OSC_25M; | 759 | SSCG_PLL_REFCLK_SEL_OSC_25M; |
760 | break; | 760 | break; |
761 | default: | 761 | default: |
762 | return -EINVAL; | 762 | return -EINVAL; |
763 | } | 763 | } |
764 | 764 | ||
765 | /*bypass*/ | 765 | /*bypass*/ |
766 | setbits_le32(pll_cfg0, bypass1_mask | bypass2_mask); | 766 | setbits_le32(pll_cfg0, bypass1_mask | bypass2_mask); |
767 | /* set value */ | 767 | /* set value */ |
768 | writel(val_cfg2, pll_cfg2); | 768 | writel(val_cfg2, pll_cfg2); |
769 | writel(val_cfg1, pll_cfg1); | 769 | writel(val_cfg1, pll_cfg1); |
770 | /*unbypass1 and wait 70us */ | 770 | /*unbypass1 and wait 70us */ |
771 | writel(val_cfg0 | bypass2_mask, pll_cfg1); | 771 | writel(val_cfg0 | bypass2_mask, pll_cfg1); |
772 | 772 | ||
773 | __udelay(70); | 773 | __udelay(70); |
774 | 774 | ||
775 | /* unbypass2 and wait lock */ | 775 | /* unbypass2 and wait lock */ |
776 | writel(val_cfg0, pll_cfg1); | 776 | writel(val_cfg0, pll_cfg1); |
777 | ret = readl_poll_timeout(pll_cfg0, val, val & SSCG_PLL_LOCK_MASK, 1); | 777 | ret = readl_poll_timeout(pll_cfg0, val, val & SSCG_PLL_LOCK_MASK, 1); |
778 | if (ret) | 778 | if (ret) |
779 | printf("%s timeout\n", __func__); | 779 | printf("%s timeout\n", __func__); |
780 | 780 | ||
781 | return ret; | 781 | return ret; |
782 | } | 782 | } |
783 | 783 | ||
784 | int clock_init(void) | 784 | int clock_init(void) |
785 | { | 785 | { |
786 | u32 grade; | 786 | u32 grade; |
787 | 787 | ||
788 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | 788 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | |
789 | CLK_ROOT_SOURCE_SEL(0)); | 789 | CLK_ROOT_SOURCE_SEL(0)); |
790 | 790 | ||
791 | /* | 791 | /* |
792 | * 8MQ only supports two grades: consumer and industrial. | 792 | * 8MQ only supports two grades: consumer and industrial. |
793 | * We set ARM clock to 1Ghz for consumer, 800Mhz for industrial | 793 | * We set ARM clock to 1Ghz for consumer, 800Mhz for industrial |
794 | */ | 794 | */ |
795 | grade = get_cpu_temp_grade(NULL, NULL); | 795 | grade = get_cpu_temp_grade(NULL, NULL); |
796 | if (!grade) { | 796 | if (!grade) { |
797 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1000M); | 797 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1000M); |
798 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | 798 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | |
799 | CLK_ROOT_SOURCE_SEL(1) | | 799 | CLK_ROOT_SOURCE_SEL(1) | |
800 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1)); | 800 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1)); |
801 | } else { | 801 | } else { |
802 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1600M); | 802 | frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1600M); |
803 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | | 803 | clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON | |
804 | CLK_ROOT_SOURCE_SEL(1) | | 804 | CLK_ROOT_SOURCE_SEL(1) | |
805 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); | 805 | CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2)); |
806 | } | 806 | } |
807 | /* | 807 | /* |
808 | * According to ANAMIX SPEC | 808 | * According to ANAMIX SPEC |
809 | * sys pll1 fixed at 800MHz | 809 | * sys pll1 fixed at 800MHz |
810 | * sys pll2 fixed at 1GHz | 810 | * sys pll2 fixed at 1GHz |
811 | * Here we only enable the outputs. | 811 | * Here we only enable the outputs. |
812 | */ | 812 | */ |
813 | setbits_le32(&ana_pll->sys_pll1_cfg0, SSCG_PLL_CLKE_MASK | | 813 | setbits_le32(&ana_pll->sys_pll1_cfg0, SSCG_PLL_CLKE_MASK | |
814 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | | 814 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | |
815 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | | 815 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | |
816 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | | 816 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | |
817 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); | 817 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); |
818 | 818 | ||
819 | setbits_le32(&ana_pll->sys_pll2_cfg0, SSCG_PLL_CLKE_MASK | | 819 | setbits_le32(&ana_pll->sys_pll2_cfg0, SSCG_PLL_CLKE_MASK | |
820 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | | 820 | SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK | |
821 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | | 821 | SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK | |
822 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | | 822 | SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK | |
823 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); | 823 | SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK); |
824 | 824 | ||
825 | clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON | | 825 | clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON | |
826 | CLK_ROOT_SOURCE_SEL(1)); | 826 | CLK_ROOT_SOURCE_SEL(1)); |
827 | 827 | ||
828 | init_wdog_clk(); | 828 | init_wdog_clk(); |
829 | clock_enable(CCGR_TSENSOR, 1); | 829 | clock_enable(CCGR_TSENSOR, 1); |
830 | clock_enable(CCGR_OCOTP, 1); | 830 | clock_enable(CCGR_OCOTP, 1); |
831 | 831 | ||
832 | /* config GIC to sys_pll2_200m */ | ||
833 | clock_enable(CCGR_GIC, 0); | ||
834 | clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); | ||
835 | clock_enable(CCGR_GIC, 1); | ||
836 | |||
832 | return 0; | 837 | return 0; |
833 | } | 838 | } |
834 | #endif | 839 | #endif |
835 | 840 | ||
836 | /* | 841 | /* |
837 | * Dump some clockes. | 842 | * Dump some clockes. |
838 | */ | 843 | */ |
839 | #ifndef CONFIG_SPL_BUILD | 844 | #ifndef CONFIG_SPL_BUILD |
840 | int do_mx8m_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, | 845 | int do_mx8m_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, |
841 | char * const argv[]) | 846 | char * const argv[]) |
842 | { | 847 | { |
843 | u32 freq; | 848 | u32 freq; |
844 | 849 | ||
845 | freq = decode_frac_pll(ARM_PLL_CLK); | 850 | freq = decode_frac_pll(ARM_PLL_CLK); |
846 | printf("ARM_PLL %8d MHz\n", freq / 1000000); | 851 | printf("ARM_PLL %8d MHz\n", freq / 1000000); |
847 | freq = decode_sscg_pll(SYSTEM_PLL1_800M_CLK); | 852 | freq = decode_sscg_pll(SYSTEM_PLL1_800M_CLK); |
848 | printf("SYS_PLL1_800 %8d MHz\n", freq / 1000000); | 853 | printf("SYS_PLL1_800 %8d MHz\n", freq / 1000000); |
849 | freq = decode_sscg_pll(SYSTEM_PLL1_400M_CLK); | 854 | freq = decode_sscg_pll(SYSTEM_PLL1_400M_CLK); |
850 | printf("SYS_PLL1_400 %8d MHz\n", freq / 1000000); | 855 | printf("SYS_PLL1_400 %8d MHz\n", freq / 1000000); |
851 | freq = decode_sscg_pll(SYSTEM_PLL1_266M_CLK); | 856 | freq = decode_sscg_pll(SYSTEM_PLL1_266M_CLK); |
852 | printf("SYS_PLL1_266 %8d MHz\n", freq / 1000000); | 857 | printf("SYS_PLL1_266 %8d MHz\n", freq / 1000000); |
853 | freq = decode_sscg_pll(SYSTEM_PLL1_200M_CLK); | 858 | freq = decode_sscg_pll(SYSTEM_PLL1_200M_CLK); |
854 | printf("SYS_PLL1_200 %8d MHz\n", freq / 1000000); | 859 | printf("SYS_PLL1_200 %8d MHz\n", freq / 1000000); |
855 | freq = decode_sscg_pll(SYSTEM_PLL1_160M_CLK); | 860 | freq = decode_sscg_pll(SYSTEM_PLL1_160M_CLK); |
856 | printf("SYS_PLL1_160 %8d MHz\n", freq / 1000000); | 861 | printf("SYS_PLL1_160 %8d MHz\n", freq / 1000000); |
857 | freq = decode_sscg_pll(SYSTEM_PLL1_133M_CLK); | 862 | freq = decode_sscg_pll(SYSTEM_PLL1_133M_CLK); |
858 | printf("SYS_PLL1_133 %8d MHz\n", freq / 1000000); | 863 | printf("SYS_PLL1_133 %8d MHz\n", freq / 1000000); |
859 | freq = decode_sscg_pll(SYSTEM_PLL1_100M_CLK); | 864 | freq = decode_sscg_pll(SYSTEM_PLL1_100M_CLK); |
860 | printf("SYS_PLL1_100 %8d MHz\n", freq / 1000000); | 865 | printf("SYS_PLL1_100 %8d MHz\n", freq / 1000000); |
861 | freq = decode_sscg_pll(SYSTEM_PLL1_80M_CLK); | 866 | freq = decode_sscg_pll(SYSTEM_PLL1_80M_CLK); |
862 | printf("SYS_PLL1_80 %8d MHz\n", freq / 1000000); | 867 | printf("SYS_PLL1_80 %8d MHz\n", freq / 1000000); |
863 | freq = decode_sscg_pll(SYSTEM_PLL1_40M_CLK); | 868 | freq = decode_sscg_pll(SYSTEM_PLL1_40M_CLK); |
864 | printf("SYS_PLL1_40 %8d MHz\n", freq / 1000000); | 869 | printf("SYS_PLL1_40 %8d MHz\n", freq / 1000000); |
865 | freq = decode_sscg_pll(SYSTEM_PLL2_1000M_CLK); | 870 | freq = decode_sscg_pll(SYSTEM_PLL2_1000M_CLK); |
866 | printf("SYS_PLL2_1000 %8d MHz\n", freq / 1000000); | 871 | printf("SYS_PLL2_1000 %8d MHz\n", freq / 1000000); |
867 | freq = decode_sscg_pll(SYSTEM_PLL2_500M_CLK); | 872 | freq = decode_sscg_pll(SYSTEM_PLL2_500M_CLK); |
868 | printf("SYS_PLL2_500 %8d MHz\n", freq / 1000000); | 873 | printf("SYS_PLL2_500 %8d MHz\n", freq / 1000000); |
869 | freq = decode_sscg_pll(SYSTEM_PLL2_333M_CLK); | 874 | freq = decode_sscg_pll(SYSTEM_PLL2_333M_CLK); |
870 | printf("SYS_PLL2_333 %8d MHz\n", freq / 1000000); | 875 | printf("SYS_PLL2_333 %8d MHz\n", freq / 1000000); |
871 | freq = decode_sscg_pll(SYSTEM_PLL2_250M_CLK); | 876 | freq = decode_sscg_pll(SYSTEM_PLL2_250M_CLK); |
872 | printf("SYS_PLL2_250 %8d MHz\n", freq / 1000000); | 877 | printf("SYS_PLL2_250 %8d MHz\n", freq / 1000000); |
873 | freq = decode_sscg_pll(SYSTEM_PLL2_200M_CLK); | 878 | freq = decode_sscg_pll(SYSTEM_PLL2_200M_CLK); |
874 | printf("SYS_PLL2_200 %8d MHz\n", freq / 1000000); | 879 | printf("SYS_PLL2_200 %8d MHz\n", freq / 1000000); |
875 | freq = decode_sscg_pll(SYSTEM_PLL2_166M_CLK); | 880 | freq = decode_sscg_pll(SYSTEM_PLL2_166M_CLK); |
876 | printf("SYS_PLL2_166 %8d MHz\n", freq / 1000000); | 881 | printf("SYS_PLL2_166 %8d MHz\n", freq / 1000000); |
877 | freq = decode_sscg_pll(SYSTEM_PLL2_125M_CLK); | 882 | freq = decode_sscg_pll(SYSTEM_PLL2_125M_CLK); |
878 | printf("SYS_PLL2_125 %8d MHz\n", freq / 1000000); | 883 | printf("SYS_PLL2_125 %8d MHz\n", freq / 1000000); |
879 | freq = decode_sscg_pll(SYSTEM_PLL2_100M_CLK); | 884 | freq = decode_sscg_pll(SYSTEM_PLL2_100M_CLK); |
880 | printf("SYS_PLL2_100 %8d MHz\n", freq / 1000000); | 885 | printf("SYS_PLL2_100 %8d MHz\n", freq / 1000000); |
881 | freq = decode_sscg_pll(SYSTEM_PLL2_50M_CLK); | 886 | freq = decode_sscg_pll(SYSTEM_PLL2_50M_CLK); |
882 | printf("SYS_PLL2_50 %8d MHz\n", freq / 1000000); | 887 | printf("SYS_PLL2_50 %8d MHz\n", freq / 1000000); |
883 | freq = decode_sscg_pll(SYSTEM_PLL3_CLK); | 888 | freq = decode_sscg_pll(SYSTEM_PLL3_CLK); |
884 | printf("SYS_PLL3 %8d MHz\n", freq / 1000000); | 889 | printf("SYS_PLL3 %8d MHz\n", freq / 1000000); |
885 | freq = mxc_get_clock(UART1_CLK_ROOT); | 890 | freq = mxc_get_clock(UART1_CLK_ROOT); |
886 | printf("UART1 %8d MHz\n", freq / 1000000); | 891 | printf("UART1 %8d MHz\n", freq / 1000000); |
887 | freq = mxc_get_clock(USDHC1_CLK_ROOT); | 892 | freq = mxc_get_clock(USDHC1_CLK_ROOT); |
888 | printf("USDHC1 %8d MHz\n", freq / 1000000); | 893 | printf("USDHC1 %8d MHz\n", freq / 1000000); |
889 | freq = mxc_get_clock(QSPI_CLK_ROOT); | 894 | freq = mxc_get_clock(QSPI_CLK_ROOT); |
890 | printf("QSPI %8d MHz\n", freq / 1000000); | 895 | printf("QSPI %8d MHz\n", freq / 1000000); |
891 | return 0; | 896 | return 0; |
892 | } | 897 | } |
893 | 898 | ||
894 | U_BOOT_CMD( | 899 | U_BOOT_CMD( |
895 | clocks, CONFIG_SYS_MAXARGS, 1, do_mx8m_showclocks, | 900 | clocks, CONFIG_SYS_MAXARGS, 1, do_mx8m_showclocks, |
896 | "display clocks", | 901 | "display clocks", |
897 | "" | 902 | "" |
898 | ); | 903 | ); |
899 | #endif | 904 | #endif |
900 | 905 |