1 // SPDX-License-Identifier: GPL-2.0+
4 * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc.
5 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
9 #include <asm/processor.h>
11 #include <asm/immap.h>
14 DECLARE_GLOBAL_DATA_PTR
;
17 * Low Power Divider specifications
19 #define CLOCK_LPD_MIN (1 << 0) /* Divider (decoded) */
20 #define CLOCK_LPD_MAX (1 << 15) /* Divider (decoded) */
22 #define CLOCK_PLL_FVCO_MAX 540000000
23 #define CLOCK_PLL_FVCO_MIN 300000000
25 #define CLOCK_PLL_FSYS_MAX 266666666
26 #define CLOCK_PLL_FSYS_MIN 100000000
29 void clock_enter_limp(int lpdiv
)
31 ccm_t
*ccm
= (ccm_t
*)MMAP_CCM
;
34 /* Check bounds of divider */
35 if (lpdiv
< CLOCK_LPD_MIN
)
36 lpdiv
= CLOCK_LPD_MIN
;
37 if (lpdiv
> CLOCK_LPD_MAX
)
38 lpdiv
= CLOCK_LPD_MAX
;
40 /* Round divider down to nearest power of two */
41 for (i
= 0, j
= lpdiv
; j
!= 1; j
>>= 1, i
++) ;
43 #ifdef CONFIG_MCF5445x
44 /* Apply the divider to the system clock */
45 clrsetbits_be16(&ccm
->cdr
, 0x0f00, CCM_CDR_LPDIV(i
));
48 /* Enable Limp Mode */
49 setbits_be16(&ccm
->misccr
, CCM_MISCCR_LIMP
);
53 * brief Exit Limp mode
54 * warning The PLL should be set and locked prior to exiting Limp mode
56 void clock_exit_limp(void)
58 ccm_t
*ccm
= (ccm_t
*)MMAP_CCM
;
59 pll_t
*pll
= (pll_t
*)MMAP_PLL
;
62 clrbits_be16(&ccm
->misccr
, CCM_MISCCR_LIMP
);
64 /* Wait for the PLL to lock */
65 while (!(in_be32(&pll
->psr
) & PLL_PSR_LOCK
))
69 #ifdef CONFIG_MCF5441x
70 void setup_5441x_clocks(void)
72 ccm_t
*ccm
= (ccm_t
*)MMAP_CCM
;
73 pll_t
*pll
= (pll_t
*)MMAP_PLL
;
74 int temp
, vco
= 0, bootmod_ccr
, pdr
;
76 bootmod_ccr
= (in_be16(&ccm
->ccr
) & CCM_CCR_BOOTMOD
) >> 14;
78 switch (bootmod_ccr
) {
80 out_be32(&pll
->pcr
, 0x00000013);
81 out_be32(&pll
->pdr
, 0x00e70c61);
90 /*Change frequency for Modelo SER1 USB host*/
91 #ifdef CONFIG_LOW_MCFCLK
92 temp
= in_be32(&pll
->pcr
);
95 out_be32(&pll
->pcr
, temp
);
97 temp
= in_be32(&pll
->pdr
);
100 out_be32(&pll
->pdr
, temp
);
104 setbits_be16(&ccm
->misccr2
, 0x02);
106 vco
= ((in_be32(&pll
->pcr
) & PLL_CR_FBKDIV_BITS
) + 1) *
107 CONFIG_SYS_INPUT_CLKSRC
;
108 gd
->arch
.vco_clk
= vco
;
110 gd
->arch
.inp_clk
= CONFIG_SYS_INPUT_CLKSRC
; /* Input clock */
112 pdr
= in_be32(&pll
->pdr
);
113 temp
= (pdr
& PLL_DR_OUTDIV1_BITS
) + 1;
114 gd
->cpu_clk
= vco
/ temp
; /* cpu clock */
115 gd
->arch
.flb_clk
= vco
/ temp
; /* FlexBus clock */
116 gd
->arch
.flb_clk
>>= 1;
117 if (in_be16(&ccm
->misccr2
) & 2) /* fsys/4 */
118 gd
->arch
.flb_clk
>>= 1;
120 temp
= ((pdr
& PLL_DR_OUTDIV2_BITS
) >> 5) + 1;
121 gd
->bus_clk
= vco
/ temp
; /* bus clock */
126 #ifdef CONFIG_MCF5445x
127 void setup_5445x_clocks(void)
129 ccm_t
*ccm
= (ccm_t
*)MMAP_CCM
;
130 pll_t
*pll
= (pll_t
*)MMAP_PLL
;
131 int pllmult_nopci
[] = { 20, 10, 24, 18, 12, 6, 16, 8 };
132 int pllmult_pci
[] = { 12, 6, 16, 8 };
133 int vco
= 0, temp
, fbtemp
, pcrvalue
;
134 int *pPllmult
= NULL
;
140 #ifdef CONFIG_M54455EVB
141 u8
*cpld
= (u8
*)(CONFIG_SYS_CS2_BASE
+ 3);
145 /* To determine PCI is present or not */
146 if (((in_be16(&ccm
->ccr
) & CCM_CCR_360_FBCONFIG_MASK
) == 0x00e0) ||
147 ((in_be16(&ccm
->ccr
) & CCM_CCR_360_FBCONFIG_MASK
) == 0x0060)) {
148 pPllmult
= &pllmult_pci
[0];
149 fbpll_mask
= 3; /* 11b */
154 pPllmult
= &pllmult_nopci
[0];
155 fbpll_mask
= 7; /* 111b */
162 #ifdef CONFIG_M54455EVB
163 bootmode
= (in_8(cpld
) & 0x03);
166 /* Temporary read from CCR- fixed fb issue, must be the same clock
167 as pci or input clock, causing cpld/fpga read inconsistancy */
168 fbtemp
= pPllmult
[ccm
->ccr
& fbpll_mask
];
170 /* Break down into small pieces, code still in flex bus */
171 pcrvalue
= in_be32(&pll
->pcr
) & 0xFFFFF0FF;
173 pcrvalue
|= PLL_PCR_OUTDIV3(temp
);
175 out_be32(&pll
->pcr
, pcrvalue
);
178 #ifdef CONFIG_M54451EVB
179 /* No external logic to read the bootmode, hard coded from built */
185 /* default value is 16 mul, set to 20 mul */
186 pcrvalue
= (in_be32(&pll
->pcr
) & 0x00FFFFFF) | 0x14000000;
187 out_be32(&pll
->pcr
, pcrvalue
);
188 while ((in_be32(&pll
->psr
) & PLL_PSR_LOCK
) != PLL_PSR_LOCK
)
195 vco
= pPllmult
[ccm
->rcon
& fbpll_mask
] * CONFIG_SYS_INPUT_CLKSRC
;
197 if ((vco
< CLOCK_PLL_FVCO_MIN
) || (vco
> CLOCK_PLL_FVCO_MAX
)) {
198 /* invaild range, re-set in PCR */
199 int temp
= ((in_be32(&pll
->pcr
) & PLL_PCR_OUTDIV2_MASK
) >> 4) + 1;
202 j
= (in_be32(&pll
->pcr
) & 0xFF000000) >> 24;
203 for (i
= j
; i
< 0xFF; i
++) {
204 vco
= i
* CONFIG_SYS_INPUT_CLKSRC
;
205 if (vco
>= CLOCK_PLL_FVCO_MIN
) {
207 if (bus
<= CLOCK_PLL_FSYS_MIN
- MHZ
)
213 pcrvalue
= in_be32(&pll
->pcr
) & 0x00FF00FF;
214 fbtemp
= ((i
- 1) << 8) | ((i
- 1) << 12);
215 pcrvalue
|= ((i
<< 24) | fbtemp
);
217 out_be32(&pll
->pcr
, pcrvalue
);
219 gd
->arch
.vco_clk
= vco
; /* Vco clock */
220 } else if (bootmode
== 2) {
222 vco
= ((in_be32(&pll
->pcr
) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC
;
223 if ((vco
< CLOCK_PLL_FVCO_MIN
) || (vco
> CLOCK_PLL_FVCO_MAX
)) {
225 pcrvalue
= (in_be32(&pll
->pcr
) & 0x00FFFFFF);
226 pcrvalue
|= pPllmult
[in_be16(&ccm
->ccr
) & fbpll_mask
] << 24;
227 out_be32(&pll
->pcr
, pcrvalue
);
228 vco
= ((in_be32(&pll
->pcr
) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC
;
230 gd
->arch
.vco_clk
= vco
; /* Vco clock */
231 } else if (bootmode
== 3) {
233 vco
= ((in_be32(&pll
->pcr
) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC
;
234 gd
->arch
.vco_clk
= vco
; /* Vco clock */
237 if ((in_be16(&ccm
->ccr
) & CCM_MISCCR_LIMP
) == CCM_MISCCR_LIMP
) {
240 gd
->arch
.inp_clk
= CONFIG_SYS_INPUT_CLKSRC
; /* Input clock */
242 temp
= (in_be32(&pll
->pcr
) & PLL_PCR_OUTDIV1_MASK
) + 1;
243 gd
->cpu_clk
= vco
/ temp
; /* cpu clock */
245 temp
= ((in_be32(&pll
->pcr
) & PLL_PCR_OUTDIV2_MASK
) >> 4) + 1;
246 gd
->bus_clk
= vco
/ temp
; /* bus clock */
248 temp
= ((in_be32(&pll
->pcr
) & PLL_PCR_OUTDIV3_MASK
) >> 8) + 1;
249 gd
->arch
.flb_clk
= vco
/ temp
; /* FlexBus clock */
253 temp
= ((in_be32(&pll
->pcr
) & PLL_PCR_OUTDIV4_MASK
) >> 12) + 1;
254 gd
->pci_clk
= vco
/ temp
; /* PCI clock */
259 #ifdef CONFIG_SYS_I2C_FSL
260 gd
->arch
.i2c1_clk
= gd
->bus_clk
;
265 /* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
268 #ifdef CONFIG_MCF5441x
269 setup_5441x_clocks();
271 #ifdef CONFIG_MCF5445x
272 setup_5445x_clocks();
275 #ifdef CONFIG_SYS_FSL_I2C
276 gd
->arch
.i2c1_clk
= gd
->bus_clk
;