~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/m68k/cpu/mcf5445x/speed.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (C) 2004-2007, 2012 Freescale Semiconductor, Inc.
 
4
 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
 
5
 *
 
6
 * SPDX-License-Identifier:     GPL-2.0+
 
7
 */
 
8
 
 
9
#include <common.h>
 
10
#include <asm/processor.h>
 
11
 
 
12
#include <asm/immap.h>
 
13
#include <asm/io.h>
 
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
{
 
32
        ccm_t *ccm = (ccm_t *)MMAP_CCM;
 
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
#ifdef CONFIG_MCF5445x
 
45
        /* Apply the divider to the system clock */
 
46
        clrsetbits_be16(&ccm->cdr, 0x0f00, CCM_CDR_LPDIV(i));
 
47
#endif
 
48
 
 
49
        /* Enable Limp Mode */
 
50
        setbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
 
51
}
 
52
 
 
53
/*
 
54
 * brief   Exit Limp mode
 
55
 * warning The PLL should be set and locked prior to exiting Limp mode
 
56
 */
 
57
void clock_exit_limp(void)
 
58
{
 
59
        ccm_t *ccm = (ccm_t *)MMAP_CCM;
 
60
        pll_t *pll = (pll_t *)MMAP_PLL;
 
61
 
 
62
        /* Exit Limp mode */
 
63
        clrbits_be16(&ccm->misccr, CCM_MISCCR_LIMP);
 
64
 
 
65
        /* Wait for the PLL to lock */
 
66
        while (!(in_be32(&pll->psr) & PLL_PSR_LOCK))
 
67
                ;
 
68
}
 
69
 
 
70
#ifdef CONFIG_MCF5441x
 
71
void setup_5441x_clocks(void)
 
72
{
 
73
        ccm_t *ccm = (ccm_t *)MMAP_CCM;
 
74
        pll_t *pll = (pll_t *)MMAP_PLL;
 
75
        int temp, vco = 0, bootmod_ccr, pdr;
 
76
 
 
77
        bootmod_ccr = (in_be16(&ccm->ccr) & CCM_CCR_BOOTMOD) >> 14;
 
78
 
 
79
        switch (bootmod_ccr) {
 
80
        case 0:
 
81
                out_be32(&pll->pcr, 0x00000013);
 
82
                out_be32(&pll->pdr, 0x00e70c61);
 
83
                clock_exit_limp();
 
84
                break;
 
85
        case 2:
 
86
                break;
 
87
        case 3:
 
88
                break;
 
89
        }
 
90
 
 
91
        /*Change frequency for Modelo SER1 USB host*/
 
92
#ifdef CONFIG_LOW_MCFCLK
 
93
        temp = in_be32(&pll->pcr);
 
94
        temp &= ~0x3f;
 
95
        temp |= 5;
 
96
        out_be32(&pll->pcr, temp);
 
97
 
 
98
        temp = in_be32(&pll->pdr);
 
99
        temp &= ~0x001f0000;
 
100
        temp |= 0x00040000;
 
101
        out_be32(&pll->pdr, temp);
 
102
        __asm__("tpf");
 
103
#endif
 
104
 
 
105
        setbits_be16(&ccm->misccr2, 0x02);
 
106
 
 
107
        vco =  ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
 
108
                CONFIG_SYS_INPUT_CLKSRC;
 
109
        gd->arch.vco_clk = vco;
 
110
 
 
111
        gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC;     /* Input clock */
 
112
 
 
113
        pdr = in_be32(&pll->pdr);
 
114
        temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
 
115
        gd->cpu_clk = vco / temp;       /* cpu clock */
 
116
        gd->arch.flb_clk = vco / temp;  /* FlexBus clock */
 
117
        gd->arch.flb_clk >>= 1;
 
118
        if (in_be16(ccm->misccr2) & 2)          /* fsys/4 */
 
119
                gd->arch.flb_clk >>= 1;
 
120
 
 
121
        temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
 
122
        gd->bus_clk = vco / temp;       /* bus clock */
 
123
 
 
124
}
 
125
#endif
 
126
 
 
127
#ifdef CONFIG_MCF5445x
 
128
void setup_5445x_clocks(void)
 
129
{
 
130
        ccm_t *ccm = (ccm_t *)MMAP_CCM;
 
131
        pll_t *pll = (pll_t *)MMAP_PLL;
 
132
        int pllmult_nopci[] = { 20, 10, 24, 18, 12, 6, 16, 8 };
 
133
        int pllmult_pci[] = { 12, 6, 16, 8 };
 
134
        int vco = 0, temp, fbtemp, pcrvalue;
 
135
        int *pPllmult = NULL;
 
136
        u16 fbpll_mask;
 
137
#ifdef CONFIG_PCI
 
138
        int bPci;
 
139
#endif
 
140
 
 
141
#ifdef CONFIG_M54455EVB
 
142
        u8 *cpld = (u8 *)(CONFIG_SYS_CS2_BASE + 3);
 
143
#endif
 
144
        u8 bootmode;
 
145
 
 
146
        /* To determine PCI is present or not */
 
147
        if (((in_be16(&ccm->ccr) & CCM_CCR_360_FBCONFIG_MASK) == 0x00e0) ||
 
148
            ((in_be16(&ccm->ccr) & CCM_CCR_360_FBCONFIG_MASK) == 0x0060)) {
 
149
                pPllmult = &pllmult_pci[0];
 
150
                fbpll_mask = 3;         /* 11b */
 
151
#ifdef CONFIG_PCI
 
152
                bPci = 1;
 
153
#endif
 
154
        } else {
 
155
                pPllmult = &pllmult_nopci[0];
 
156
                fbpll_mask = 7;         /* 111b */
 
157
#ifdef CONFIG_PCI
 
158
                gd->pci_clk = 0;
 
159
                bPci = 0;
 
160
#endif
 
161
        }
 
162
 
 
163
#ifdef CONFIG_M54455EVB
 
164
        bootmode = (in_8(cpld) & 0x03);
 
165
 
 
166
        if (bootmode != 3) {
 
167
                /* Temporary read from CCR- fixed fb issue, must be the same clock
 
168
                   as pci or input clock, causing cpld/fpga read inconsistancy */
 
169
                fbtemp = pPllmult[ccm->ccr & fbpll_mask];
 
170
 
 
171
                /* Break down into small pieces, code still in flex bus */
 
172
                pcrvalue = in_be32(&pll->pcr) & 0xFFFFF0FF;
 
173
                temp = fbtemp - 1;
 
174
                pcrvalue |= PLL_PCR_OUTDIV3(temp);
 
175
 
 
176
                out_be32(&pll->pcr, pcrvalue);
 
177
        }
 
178
#endif
 
179
#ifdef CONFIG_M54451EVB
 
180
        /* No external logic to read the bootmode, hard coded from built */
 
181
#ifdef CONFIG_CF_SBF
 
182
        bootmode = 3;
 
183
#else
 
184
        bootmode = 2;
 
185
 
 
186
        /* default value is 16 mul, set to 20 mul */
 
187
        pcrvalue = (in_be32(&pll->pcr) & 0x00FFFFFF) | 0x14000000;
 
188
        out_be32(&pll->pcr, pcrvalue);
 
189
        while ((in_be32(&pll->psr) & PLL_PSR_LOCK) != PLL_PSR_LOCK)
 
190
                ;
 
191
#endif
 
192
#endif
 
193
 
 
194
        if (bootmode == 0) {
 
195
                /* RCON mode */
 
196
                vco = pPllmult[ccm->rcon & fbpll_mask] * CONFIG_SYS_INPUT_CLKSRC;
 
197
 
 
198
                if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
 
199
                        /* invaild range, re-set in PCR */
 
200
                        int temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
 
201
                        int i, j, bus;
 
202
 
 
203
                        j = (in_be32(&pll->pcr) & 0xFF000000) >> 24;
 
204
                        for (i = j; i < 0xFF; i++) {
 
205
                                vco = i * CONFIG_SYS_INPUT_CLKSRC;
 
206
                                if (vco >= CLOCK_PLL_FVCO_MIN) {
 
207
                                        bus = vco / temp;
 
208
                                        if (bus <= CLOCK_PLL_FSYS_MIN - MHZ)
 
209
                                                continue;
 
210
                                        else
 
211
                                                break;
 
212
                                }
 
213
                        }
 
214
                        pcrvalue = in_be32(&pll->pcr) & 0x00FF00FF;
 
215
                        fbtemp = ((i - 1) << 8) | ((i - 1) << 12);
 
216
                        pcrvalue |= ((i << 24) | fbtemp);
 
217
 
 
218
                        out_be32(&pll->pcr, pcrvalue);
 
219
                }
 
220
                gd->arch.vco_clk = vco; /* Vco clock */
 
221
        } else if (bootmode == 2) {
 
222
                /* Normal mode */
 
223
                vco =  ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
 
224
                if ((vco < CLOCK_PLL_FVCO_MIN) || (vco > CLOCK_PLL_FVCO_MAX)) {
 
225
                        /* Default value */
 
226
                        pcrvalue = (in_be32(&pll->pcr) & 0x00FFFFFF);
 
227
                        pcrvalue |= pPllmult[in_be16(&ccm->ccr) & fbpll_mask] << 24;
 
228
                        out_be32(&pll->pcr, pcrvalue);
 
229
                        vco = ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
 
230
                }
 
231
                gd->arch.vco_clk = vco; /* Vco clock */
 
232
        } else if (bootmode == 3) {
 
233
                /* serial mode */
 
234
                vco =  ((in_be32(&pll->pcr) & 0xFF000000) >> 24) * CONFIG_SYS_INPUT_CLKSRC;
 
235
                gd->arch.vco_clk = vco; /* Vco clock */
 
236
        }
 
237
 
 
238
        if ((in_be16(&ccm->ccr) & CCM_MISCCR_LIMP) == CCM_MISCCR_LIMP) {
 
239
                /* Limp mode */
 
240
        } else {
 
241
                gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC; /* Input clock */
 
242
 
 
243
                temp = (in_be32(&pll->pcr) & PLL_PCR_OUTDIV1_MASK) + 1;
 
244
                gd->cpu_clk = vco / temp;       /* cpu clock */
 
245
 
 
246
                temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV2_MASK) >> 4) + 1;
 
247
                gd->bus_clk = vco / temp;       /* bus clock */
 
248
 
 
249
                temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV3_MASK) >> 8) + 1;
 
250
                gd->arch.flb_clk = vco / temp;  /* FlexBus clock */
 
251
 
 
252
#ifdef CONFIG_PCI
 
253
                if (bPci) {
 
254
                        temp = ((in_be32(&pll->pcr) & PLL_PCR_OUTDIV4_MASK) >> 12) + 1;
 
255
                        gd->pci_clk = vco / temp;       /* PCI clock */
 
256
                }
 
257
#endif
 
258
        }
 
259
 
 
260
#ifdef CONFIG_SYS_I2C_FSL
 
261
        gd->arch.i2c1_clk = gd->bus_clk;
 
262
#endif
 
263
}
 
264
#endif
 
265
 
 
266
/* get_clocks() fills in gd->cpu_clock and gd->bus_clk */
 
267
int get_clocks(void)
 
268
{
 
269
#ifdef CONFIG_MCF5441x
 
270
        setup_5441x_clocks();
 
271
#endif
 
272
#ifdef CONFIG_MCF5445x
 
273
        setup_5445x_clocks();
 
274
#endif
 
275
 
 
276
#ifdef CONFIG_SYS_FSL_I2C
 
277
        gd->arch.i2c1_clk = gd->bus_clk;
 
278
#endif
 
279
 
 
280
        return (0);
 
281
}