]>
Commit | Line | Data |
---|---|---|
c8758102 TL |
1 | /* |
2 | * | |
849fc424 | 3 | * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc. |
c8758102 TL |
4 | * TsiChung Liew (Tsi-Chung.Liew@freescale.com) |
5 | * | |
1a459660 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
c8758102 TL |
7 | */ |
8 | ||
9 | #include <common.h> | |
10 | #include <asm/processor.h> | |
11 | ||
12 | #include <asm/immap.h> | |
849fc424 | 13 | #include <asm/io.h> |
c8758102 TL |
14 | |
15 | DECLARE_GLOBAL_DATA_PTR; | |
16 | ||
17 | /* | |
18 | * Low Power Divider specifications | |
19 | */ | |
20 | #define CLOCK_LPD_MIN (1 << 0) /* Divider (decoded) */ | |
21 | #define CLOCK_LPD_MAX (1 << 15) /* Divider (decoded) */ | |
22 | ||
23 | #define CLOCK_PLL_FVCO_MAX 540000000 | |
24 | #define CLOCK_PLL_FVCO_MIN 300000000 | |
25 | ||
26 | #define CLOCK_PLL_FSYS_MAX 266666666 | |
27 | #define CLOCK_PLL_FSYS_MIN 100000000 | |
28 | #define MHZ 1000000 | |
29 | ||
30 | void clock_enter_limp(int lpdiv) | |
31 | { | |
849fc424 | 32 | ccm_t *ccm = (ccm_t *)MMAP_CCM; |
c8758102 TL |
33 | int i, j; |
34 | ||
35 | /* Check bounds of divider */ | |
36 | if (lpdiv < CLOCK_LPD_MIN) | |
37 | lpdiv = CLOCK_LPD_MIN; | |
38 | if (lpdiv > CLOCK_LPD_MAX) | |
39 | lpdiv = CLOCK_LPD_MAX; | |
40 | ||
41 | /* Round divider down to nearest power of two */ | |
42 | for (i = 0, j = lpdiv; j != 1; j >>= 1, i++) ; | |
43 | ||
44 | /* Apply the divider to the system clock */ | |
849fc424 | 45 | clrsetbits_be16(&ccm->cdr, 0x0f00, CCM_CDR_LPDIV(i)); |
c8758102 TL |
46 | |
47 | /* Enable Limp Mode */ | |
849fc424 | 48 | setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP); |
c8758102 TL |
49 | } |
50 | ||
51 | /* | |
52 | * brief Exit Limp mode | |
53 | * warning The PLL should be set and locked prior to exiting Limp mode | |
54 | */ | |
55 | void clock_exit_limp(void) | |
56 | { | |
849fc424 AW |
57 | ccm_t *ccm = (ccm_t *)MMAP_CCM; |
58 | pll_t *pll = (pll_t *)MMAP_PLL; | |
c8758102 TL |
59 | |
60 | /* Exit Limp mode */ | |
849fc424 | 61 | clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP); |
c8758102 TL |
62 | |
63 | /* Wait for the PLL to lock */ | |
849fc424 AW |
64 | while (!(in_be32(&pll->psr) & PLL_PSR_LOCK)) |
65 | ; | |
c8758102 TL |
66 | } |
67 | ||
68 | /* | |
69 | * get_clocks() fills in gd->cpu_clock and gd->bus_clk | |
70 | */ | |
71 | int get_clocks(void) | |
72 | { | |
73 | ||
849fc424 AW |
74 | ccm_t *ccm = (ccm_t *)MMAP_CCM; |
75 | pll_t *pll = (pll_t *)MMAP_PLL; | |
c8758102 TL |
76 | int vco, temp, pcrvalue, pfdr; |
77 | u8 bootmode; | |
78 | ||
849fc424 | 79 | pcrvalue = in_be32(&pll->pcr) & 0xFF0F0FFF; |
c8758102 TL |
80 | pfdr = pcrvalue >> 24; |
81 | ||
a21d0c2c TL |
82 | if (pfdr == 0x1E) |
83 | bootmode = 0; /* Normal Mode */ | |
84 | ||
85 | #ifdef CONFIG_CF_SBF | |
86 | bootmode = 3; /* Serial Mode */ | |
87 | #endif | |
88 | ||
89 | if (bootmode == 0) { | |
90 | /* Normal mode */ | |
849fc424 | 91 | vco = ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC; |
a21d0c2c TL |
92 | if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) { |
93 | /* Default value */ | |
849fc424 | 94 | pcrvalue = (in_be32(&pll->pcr) & 0x00FFFFFF); |
a21d0c2c | 95 | pcrvalue |= 0x1E << 24; |
849fc424 | 96 | out_be32(&pll->pcr, pcrvalue); |
a21d0c2c | 97 | vco = |
849fc424 | 98 | ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * |
a21d0c2c TL |
99 | CONFIG_SYS_INPUT_CLKSRC; |
100 | } | |
7e2592fd | 101 | gd->arch.vco_clk = vco; /* Vco clock */ |
a21d0c2c | 102 | } else if (bootmode == 3) { |
c8758102 | 103 | /* serial mode */ |
849fc424 | 104 | vco = ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC; |
7e2592fd | 105 | gd->arch.vco_clk = vco; /* Vco clock */ |
c8758102 TL |
106 | } |
107 | ||
849fc424 | 108 | if ((in_be16(&ccm->ccr) & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) { |
c8758102 TL |
109 | /* Limp mode */ |
110 | } else { | |
7e2592fd | 111 | gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC; /* Input clock */ |
c8758102 | 112 | |
849fc424 | 113 | temp = (in_be32(&pll->pcr) & PLL_PCR_OUTDIV1_MASK) + 1; |
c8758102 TL |
114 | gd->cpu_clk = vco / temp; /* cpu clock */ |
115 | ||
849fc424 | 116 | temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV2_MASK) >> 4) + 1; |
7e2592fd SG |
117 | gd->arch.flb_clk = vco / temp; /* flexbus clock */ |
118 | gd->bus_clk = gd->arch.flb_clk; | |
c8758102 TL |
119 | } |
120 | ||
eec567a6 | 121 | #ifdef CONFIG_FSL_I2C |
609e6ec3 | 122 | gd->arch.i2c1_clk = gd->bus_clk; |
eec567a6 TL |
123 | #endif |
124 | ||
c8758102 TL |
125 | return (0); |
126 | } |