]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
b43c17cb MP |
2 | /* |
3 | * clock_ti814x.c | |
4 | * | |
5 | * Clocks for TI814X based boards | |
6 | * | |
7 | * Copyright (C) 2013, Texas Instruments, Incorporated | |
b43c17cb MP |
8 | */ |
9 | ||
10 | #include <common.h> | |
11 | #include <asm/arch/cpu.h> | |
12 | #include <asm/arch/clock.h> | |
13 | #include <asm/arch/hardware.h> | |
14 | #include <asm/io.h> | |
c05ed00a | 15 | #include <linux/delay.h> |
b43c17cb MP |
16 | |
17 | /* PRCM */ | |
18 | #define PRCM_MOD_EN 0x2 | |
19 | ||
20 | /* CLK_SRC */ | |
21 | #define OSC_SRC0 0 | |
22 | #define OSC_SRC1 1 | |
23 | ||
24 | #define L3_OSC_SRC OSC_SRC0 | |
25 | ||
26 | #define OSC_0_FREQ 20 | |
27 | ||
28 | #define DCO_HS2_MIN 500 | |
29 | #define DCO_HS2_MAX 1000 | |
30 | #define DCO_HS1_MIN 1000 | |
31 | #define DCO_HS1_MAX 2000 | |
32 | ||
33 | #define SELFREQDCO_HS2 0x00000801 | |
34 | #define SELFREQDCO_HS1 0x00001001 | |
35 | ||
36 | #define MPU_N 0x1 | |
37 | #define MPU_M 0x3C | |
38 | #define MPU_M2 1 | |
39 | #define MPU_CLKCTRL 0x1 | |
40 | ||
41 | #define L3_N 19 | |
42 | #define L3_M 880 | |
43 | #define L3_M2 4 | |
44 | #define L3_CLKCTRL 0x801 | |
45 | ||
46 | #define DDR_N 19 | |
47 | #define DDR_M 666 | |
48 | #define DDR_M2 2 | |
49 | #define DDR_CLKCTRL 0x801 | |
50 | ||
51 | /* ADPLLJ register values */ | |
52 | #define ADPLLJ_CLKCTRL_HS2 0x00000801 /* HS2 mode, TINT2 = 1 */ | |
53 | #define ADPLLJ_CLKCTRL_HS1 0x00001001 /* HS1 mode, TINT2 = 1 */ | |
54 | #define ADPLLJ_CLKCTRL_CLKDCOLDOEN (1 << 29) | |
55 | #define ADPLLJ_CLKCTRL_IDLE (1 << 23) | |
56 | #define ADPLLJ_CLKCTRL_CLKOUTEN (1 << 20) | |
57 | #define ADPLLJ_CLKCTRL_CLKOUTLDOEN (1 << 19) | |
58 | #define ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ (1 << 17) | |
59 | #define ADPLLJ_CLKCTRL_LPMODE (1 << 12) | |
60 | #define ADPLLJ_CLKCTRL_DRIFTGUARDIAN (1 << 11) | |
61 | #define ADPLLJ_CLKCTRL_REGM4XEN (1 << 10) | |
62 | #define ADPLLJ_CLKCTRL_TINITZ (1 << 0) | |
63 | #define ADPLLJ_CLKCTRL_CLKDCO (ADPLLJ_CLKCTRL_CLKDCOLDOEN | \ | |
64 | ADPLLJ_CLKCTRL_CLKOUTEN | \ | |
65 | ADPLLJ_CLKCTRL_CLKOUTLDOEN | \ | |
66 | ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ) | |
67 | ||
68 | #define ADPLLJ_STATUS_PHASELOCK (1 << 10) | |
69 | #define ADPLLJ_STATUS_FREQLOCK (1 << 9) | |
70 | #define ADPLLJ_STATUS_PHSFRQLOCK (ADPLLJ_STATUS_PHASELOCK | \ | |
71 | ADPLLJ_STATUS_FREQLOCK) | |
72 | #define ADPLLJ_STATUS_BYPASSACK (1 << 8) | |
73 | #define ADPLLJ_STATUS_BYPASS (1 << 0) | |
74 | #define ADPLLJ_STATUS_BYPASSANDACK (ADPLLJ_STATUS_BYPASSACK | \ | |
75 | ADPLLJ_STATUS_BYPASS) | |
76 | ||
77 | #define ADPLLJ_TENABLE_ENB (1 << 0) | |
78 | #define ADPLLJ_TENABLEDIV_ENB (1 << 0) | |
79 | ||
80 | #define ADPLLJ_M2NDIV_M2SHIFT 16 | |
81 | ||
82 | #define MPU_PLL_BASE (PLL_SUBSYS_BASE + 0x048) | |
83 | #define L3_PLL_BASE (PLL_SUBSYS_BASE + 0x110) | |
84 | #define DDR_PLL_BASE (PLL_SUBSYS_BASE + 0x290) | |
85 | ||
86 | struct ad_pll { | |
87 | unsigned int pwrctrl; | |
88 | unsigned int clkctrl; | |
89 | unsigned int tenable; | |
90 | unsigned int tenablediv; | |
91 | unsigned int m2ndiv; | |
92 | unsigned int mn2div; | |
93 | unsigned int fracdiv; | |
94 | unsigned int bwctrl; | |
95 | unsigned int fracctrl; | |
96 | unsigned int status; | |
97 | unsigned int m3div; | |
98 | unsigned int rampctrl; | |
99 | }; | |
100 | ||
101 | #define OSC_SRC_CTRL (PLL_SUBSYS_BASE + 0x2C0) | |
102 | ||
035d5639 MP |
103 | #define ENET_CLKCTRL_CMPL 0x30000 |
104 | ||
035d5639 MP |
105 | #define SATA_PLL_BASE (CTRL_BASE + 0x0720) |
106 | ||
107 | struct sata_pll { | |
108 | unsigned int pllcfg0; | |
109 | unsigned int pllcfg1; | |
110 | unsigned int pllcfg2; | |
111 | unsigned int pllcfg3; | |
112 | unsigned int pllcfg4; | |
113 | unsigned int pllstatus; | |
114 | unsigned int rxstatus; | |
115 | unsigned int txstatus; | |
116 | unsigned int testcfg; | |
117 | }; | |
118 | ||
119 | #define SEL_IN_FREQ (0x1 << 31) | |
120 | #define DIGCLRZ (0x1 << 30) | |
121 | #define ENDIGLDO (0x1 << 4) | |
122 | #define APLL_CP_CURR (0x1 << 3) | |
123 | #define ENBGSC_REF (0x1 << 2) | |
124 | #define ENPLLLDO (0x1 << 1) | |
125 | #define ENPLL (0x1 << 0) | |
126 | ||
127 | #define SATA_PLLCFG0_1 (SEL_IN_FREQ | ENBGSC_REF) | |
128 | #define SATA_PLLCFG0_2 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF) | |
129 | #define SATA_PLLCFG0_3 (SEL_IN_FREQ | ENDIGLDO | ENBGSC_REF | ENPLLLDO) | |
130 | #define SATA_PLLCFG0_4 (SEL_IN_FREQ | DIGCLRZ | ENDIGLDO | ENBGSC_REF | \ | |
131 | ENPLLLDO | ENPLL) | |
132 | ||
133 | #define PLL_LOCK (0x1 << 0) | |
134 | ||
135 | #define ENSATAMODE (0x1 << 31) | |
136 | #define PLLREFSEL (0x1 << 30) | |
137 | #define MDIVINT (0x4b << 18) | |
138 | #define EN_CLKAUX (0x1 << 5) | |
139 | #define EN_CLK125M (0x1 << 4) | |
140 | #define EN_CLK100M (0x1 << 3) | |
141 | #define EN_CLK50M (0x1 << 2) | |
142 | ||
143 | #define SATA_PLLCFG1 (ENSATAMODE | \ | |
144 | PLLREFSEL | \ | |
145 | MDIVINT | \ | |
146 | EN_CLKAUX | \ | |
147 | EN_CLK125M | \ | |
148 | EN_CLK100M | \ | |
149 | EN_CLK50M) | |
150 | ||
151 | #define DIGLDO_EN_CAPLESSMODE (0x1 << 22) | |
152 | #define PLLDO_EN_LDO_STABLE (0x1 << 11) | |
153 | #define PLLDO_EN_BUF_CUR (0x1 << 7) | |
154 | #define PLLDO_EN_LP (0x1 << 6) | |
155 | #define PLLDO_CTRL_TRIM_1_4V (0x10 << 1) | |
156 | ||
157 | #define SATA_PLLCFG3 (DIGLDO_EN_CAPLESSMODE | \ | |
158 | PLLDO_EN_LDO_STABLE | \ | |
159 | PLLDO_EN_BUF_CUR | \ | |
160 | PLLDO_EN_LP | \ | |
161 | PLLDO_CTRL_TRIM_1_4V) | |
b43c17cb MP |
162 | |
163 | const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE; | |
164 | const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE; | |
035d5639 | 165 | const struct sata_pll *spll = (struct sata_pll *)SATA_PLL_BASE; |
b43c17cb MP |
166 | |
167 | /* | |
168 | * Enable the peripheral clock for required peripherals | |
169 | */ | |
170 | static void enable_per_clocks(void) | |
171 | { | |
b43c17cb MP |
172 | /* HSMMC1 */ |
173 | writel(PRCM_MOD_EN, &cmalwon->mmchs1clkctrl); | |
174 | while (readl(&cmalwon->mmchs1clkctrl) != PRCM_MOD_EN) | |
175 | ; | |
035d5639 MP |
176 | |
177 | /* Ethernet */ | |
178 | writel(PRCM_MOD_EN, &cmalwon->ethclkstctrl); | |
179 | writel(PRCM_MOD_EN, &cmalwon->ethernet0clkctrl); | |
180 | while ((readl(&cmalwon->ethernet0clkctrl) & ENET_CLKCTRL_CMPL) != 0) | |
181 | ; | |
182 | writel(PRCM_MOD_EN, &cmalwon->ethernet1clkctrl); | |
183 | while ((readl(&cmalwon->ethernet1clkctrl) & ENET_CLKCTRL_CMPL) != 0) | |
184 | ; | |
0660481a HS |
185 | |
186 | /* RTC clocks */ | |
187 | writel(PRCM_MOD_EN, &cmalwon->rtcclkstctrl); | |
188 | writel(PRCM_MOD_EN, &cmalwon->rtcclkctrl); | |
189 | while (readl(&cmalwon->rtcclkctrl) != PRCM_MOD_EN) | |
190 | ; | |
b43c17cb MP |
191 | } |
192 | ||
193 | /* | |
194 | * select the HS1 or HS2 for DCO Freq | |
195 | * return : CLKCTRL | |
196 | */ | |
197 | static u32 pll_dco_freq_sel(u32 clkout_dco) | |
198 | { | |
199 | if (clkout_dco >= DCO_HS2_MIN && clkout_dco < DCO_HS2_MAX) | |
200 | return SELFREQDCO_HS2; | |
201 | else if (clkout_dco >= DCO_HS1_MIN && clkout_dco < DCO_HS1_MAX) | |
202 | return SELFREQDCO_HS1; | |
203 | else | |
204 | return -1; | |
205 | } | |
206 | ||
207 | /* | |
208 | * select the sigma delta config | |
209 | * return: sigma delta val | |
210 | */ | |
211 | static u32 pll_sigma_delta_val(u32 clkout_dco) | |
212 | { | |
213 | u32 sig_val = 0; | |
b43c17cb | 214 | |
11f29687 | 215 | sig_val = (clkout_dco + 225) / 250; |
b43c17cb MP |
216 | sig_val = sig_val << 24; |
217 | ||
218 | return sig_val; | |
219 | } | |
220 | ||
221 | /* | |
222 | * configure individual ADPLLJ | |
223 | */ | |
224 | static void pll_config(u32 base, u32 n, u32 m, u32 m2, | |
225 | u32 clkctrl_val, int adpllj) | |
226 | { | |
227 | const struct ad_pll *adpll = (struct ad_pll *)base; | |
228 | u32 m2nval, mn2val, read_clkctrl = 0, clkout_dco = 0; | |
229 | u32 sig_val = 0, hs_mod = 0; | |
230 | ||
231 | m2nval = (m2 << ADPLLJ_M2NDIV_M2SHIFT) | n; | |
232 | mn2val = m; | |
233 | ||
234 | /* calculate clkout_dco */ | |
235 | clkout_dco = ((OSC_0_FREQ / (n+1)) * m); | |
236 | ||
237 | /* sigma delta & Hs mode selection skip for ADPLLS*/ | |
238 | if (adpllj) { | |
239 | sig_val = pll_sigma_delta_val(clkout_dco); | |
240 | hs_mod = pll_dco_freq_sel(clkout_dco); | |
241 | } | |
242 | ||
243 | /* by-pass pll */ | |
244 | read_clkctrl = readl(&adpll->clkctrl); | |
245 | writel((read_clkctrl | ADPLLJ_CLKCTRL_IDLE), &adpll->clkctrl); | |
246 | while ((readl(&adpll->status) & ADPLLJ_STATUS_BYPASSANDACK) | |
247 | != ADPLLJ_STATUS_BYPASSANDACK) | |
248 | ; | |
249 | ||
250 | /* clear TINITZ */ | |
251 | read_clkctrl = readl(&adpll->clkctrl); | |
252 | writel((read_clkctrl & ~ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); | |
253 | ||
254 | /* | |
255 | * ref_clk = 20/(n + 1); | |
256 | * clkout_dco = ref_clk * m; | |
257 | * clk_out = clkout_dco/m2; | |
258 | */ | |
259 | read_clkctrl = readl(&adpll->clkctrl) & | |
260 | ~(ADPLLJ_CLKCTRL_LPMODE | | |
261 | ADPLLJ_CLKCTRL_DRIFTGUARDIAN | | |
262 | ADPLLJ_CLKCTRL_REGM4XEN); | |
263 | writel(m2nval, &adpll->m2ndiv); | |
264 | writel(mn2val, &adpll->mn2div); | |
265 | ||
266 | /* Skip for modena(ADPLLS) */ | |
267 | if (adpllj) { | |
268 | writel(sig_val, &adpll->fracdiv); | |
269 | writel((read_clkctrl | hs_mod), &adpll->clkctrl); | |
270 | } | |
271 | ||
272 | /* Load M2, N2 dividers of ADPLL */ | |
273 | writel(ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); | |
274 | writel(~ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); | |
275 | ||
276 | /* Load M, N dividers of ADPLL */ | |
277 | writel(ADPLLJ_TENABLE_ENB, &adpll->tenable); | |
278 | writel(~ADPLLJ_TENABLE_ENB, &adpll->tenable); | |
279 | ||
280 | /* Configure CLKDCOLDOEN,CLKOUTLDOEN,CLKOUT Enable BITS */ | |
281 | read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_CLKDCO; | |
282 | if (adpllj) | |
283 | writel((read_clkctrl | ADPLLJ_CLKCTRL_CLKDCO), | |
284 | &adpll->clkctrl); | |
285 | ||
286 | /* Enable TINTZ and disable IDLE(PLL in Active & Locked Mode */ | |
287 | read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_IDLE; | |
288 | writel((read_clkctrl | ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); | |
289 | ||
290 | /* Wait for phase and freq lock */ | |
291 | while ((readl(&adpll->status) & ADPLLJ_STATUS_PHSFRQLOCK) != | |
292 | ADPLLJ_STATUS_PHSFRQLOCK) | |
293 | ; | |
294 | } | |
295 | ||
296 | static void unlock_pll_control_mmr(void) | |
297 | { | |
298 | /* TRM 2.10.1.4 and 3.2.7-3.2.11 */ | |
299 | writel(0x1EDA4C3D, 0x481C5040); | |
300 | writel(0x2FF1AC2B, 0x48140060); | |
301 | writel(0xF757FDC0, 0x48140064); | |
302 | writel(0xE2BC3A6D, 0x48140068); | |
303 | writel(0x1EBF131D, 0x4814006c); | |
304 | writel(0x6F361E05, 0x48140070); | |
305 | } | |
306 | ||
307 | static void mpu_pll_config(void) | |
308 | { | |
309 | pll_config(MPU_PLL_BASE, MPU_N, MPU_M, MPU_M2, MPU_CLKCTRL, 0); | |
310 | } | |
311 | ||
312 | static void l3_pll_config(void) | |
313 | { | |
314 | u32 l3_osc_src, rd_osc_src = 0; | |
315 | ||
316 | l3_osc_src = L3_OSC_SRC; | |
317 | rd_osc_src = readl(OSC_SRC_CTRL); | |
318 | ||
319 | if (OSC_SRC0 == l3_osc_src) | |
320 | writel((rd_osc_src & 0xfffffffe)|0x0, OSC_SRC_CTRL); | |
321 | else | |
322 | writel((rd_osc_src & 0xfffffffe)|0x1, OSC_SRC_CTRL); | |
323 | ||
324 | pll_config(L3_PLL_BASE, L3_N, L3_M, L3_M2, L3_CLKCTRL, 1); | |
325 | } | |
326 | ||
327 | void ddr_pll_config(unsigned int ddrpll_m) | |
328 | { | |
329 | pll_config(DDR_PLL_BASE, DDR_N, DDR_M, DDR_M2, DDR_CLKCTRL, 1); | |
330 | } | |
331 | ||
035d5639 MP |
332 | void sata_pll_config(void) |
333 | { | |
334 | /* | |
335 | * This sequence for configuring the SATA PLL | |
336 | * resident in the control module is documented | |
337 | * in TI8148 TRM section 21.3.1 | |
338 | */ | |
339 | writel(SATA_PLLCFG1, &spll->pllcfg1); | |
340 | udelay(50); | |
341 | ||
342 | writel(SATA_PLLCFG3, &spll->pllcfg3); | |
343 | udelay(50); | |
344 | ||
345 | writel(SATA_PLLCFG0_1, &spll->pllcfg0); | |
346 | udelay(50); | |
347 | ||
348 | writel(SATA_PLLCFG0_2, &spll->pllcfg0); | |
349 | udelay(50); | |
350 | ||
351 | writel(SATA_PLLCFG0_3, &spll->pllcfg0); | |
352 | udelay(50); | |
353 | ||
354 | writel(SATA_PLLCFG0_4, &spll->pllcfg0); | |
355 | udelay(50); | |
356 | ||
357 | while (((readl(&spll->pllstatus) & PLL_LOCK) == 0)) | |
358 | ; | |
359 | } | |
360 | ||
b43c17cb MP |
361 | void enable_dmm_clocks(void) |
362 | { | |
363 | writel(PRCM_MOD_EN, &cmdef->fwclkctrl); | |
364 | writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl); | |
365 | writel(PRCM_MOD_EN, &cmdef->emif0clkctrl); | |
366 | while ((readl(&cmdef->emif0clkctrl)) != PRCM_MOD_EN) | |
367 | ; | |
368 | writel(PRCM_MOD_EN, &cmdef->emif1clkctrl); | |
369 | while ((readl(&cmdef->emif1clkctrl)) != PRCM_MOD_EN) | |
370 | ; | |
371 | while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300) | |
372 | ; | |
373 | writel(PRCM_MOD_EN, &cmdef->dmmclkctrl); | |
374 | while ((readl(&cmdef->dmmclkctrl)) != PRCM_MOD_EN) | |
375 | ; | |
376 | writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl); | |
377 | while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100) | |
378 | ; | |
379 | } | |
380 | ||
95cb69fa LV |
381 | void setup_clocks_for_console(void) |
382 | { | |
383 | unlock_pll_control_mmr(); | |
384 | /* UART0 */ | |
385 | writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl); | |
386 | while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN) | |
387 | ; | |
388 | } | |
b64a7cb9 LV |
389 | |
390 | void setup_early_clocks(void) | |
391 | { | |
392 | setup_clocks_for_console(); | |
393 | } | |
394 | ||
b43c17cb MP |
395 | /* |
396 | * Configure the PLL/PRCM for necessary peripherals | |
397 | */ | |
95cb69fa | 398 | void prcm_init(void) |
b43c17cb | 399 | { |
b43c17cb MP |
400 | /* Enable the control module */ |
401 | writel(PRCM_MOD_EN, &cmalwon->controlclkctrl); | |
402 | ||
035d5639 | 403 | /* Configure PLLs */ |
b43c17cb | 404 | mpu_pll_config(); |
b43c17cb | 405 | l3_pll_config(); |
035d5639 | 406 | sata_pll_config(); |
b43c17cb MP |
407 | |
408 | /* Enable the required peripherals */ | |
409 | enable_per_clocks(); | |
410 | } |