~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to cpu/ppc4xx/cpu_init.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2000-2007
 
3
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
4
 *
 
5
 * See file CREDITS for list of people who contributed to this
 
6
 * project.
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License as
 
10
 * published by the Free Software Foundation; either version 2 of
 
11
 * the License, or (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
21
 * MA 02111-1307 USA
 
22
 */
 
23
 
 
24
#include <common.h>
 
25
#include <watchdog.h>
 
26
#include <ppc4xx_enet.h>
 
27
#include <asm/processor.h>
 
28
#include <asm/gpio.h>
 
29
#include <ppc4xx.h>
 
30
 
 
31
#if defined(CONFIG_405GP)  || defined(CONFIG_405EP)
 
32
DECLARE_GLOBAL_DATA_PTR;
 
33
#endif
 
34
 
 
35
#ifndef CONFIG_SYS_PLL_RECONFIG
 
36
#define CONFIG_SYS_PLL_RECONFIG 0
 
37
#endif
 
38
 
 
39
void reconfigure_pll(u32 new_cpu_freq)
 
40
{
 
41
#if defined(CONFIG_440EPX)
 
42
        int     reset_needed = 0;
 
43
        u32     reg, temp;
 
44
        u32     prbdv0, target_prbdv0,                          /* CLK_PRIMBD */
 
45
                fwdva, target_fwdva, fwdvb, target_fwdvb,       /* CLK_PLLD */
 
46
                fbdv, target_fbdv, lfbdv, target_lfbdv,
 
47
                perdv0, target_perdv0,                          /* CLK_PERD */
 
48
                spcid0, target_spcid0;                          /* CLK_SPCID */
 
49
 
 
50
        /* Reconfigure clocks if necessary.
 
51
         * See PPC440EPx User's Manual, sections 8.2 and 14 */
 
52
        if (new_cpu_freq == 667) {
 
53
                target_prbdv0 = 2;
 
54
                target_fwdva = 2;
 
55
                target_fwdvb = 4;
 
56
                target_fbdv = 20;
 
57
                target_lfbdv = 1;
 
58
                target_perdv0 = 4;
 
59
                target_spcid0 = 4;
 
60
 
 
61
                mfcpr(CPR0_PRIMBD0, reg);
 
62
                temp = (reg & PRBDV_MASK) >> 24;
 
63
                prbdv0 = temp ? temp : 8;
 
64
                if (prbdv0 != target_prbdv0) {
 
65
                        reg &= ~PRBDV_MASK;
 
66
                        reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
 
67
                        mtcpr(CPR0_PRIMBD0, reg);
 
68
                        reset_needed = 1;
 
69
                }
 
70
 
 
71
                mfcpr(CPR0_PLLD, reg);
 
72
 
 
73
                temp = (reg & PLLD_FWDVA_MASK) >> 16;
 
74
                fwdva = temp ? temp : 16;
 
75
 
 
76
                temp = (reg & PLLD_FWDVB_MASK) >> 8;
 
77
                fwdvb = temp ? temp : 8;
 
78
 
 
79
                temp = (reg & PLLD_FBDV_MASK) >> 24;
 
80
                fbdv = temp ? temp : 32;
 
81
 
 
82
                temp = (reg & PLLD_LFBDV_MASK);
 
83
                lfbdv = temp ? temp : 64;
 
84
 
 
85
                if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
 
86
                        reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
 
87
                                 PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
 
88
                        reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
 
89
                                ((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
 
90
                                ((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
 
91
                                (target_lfbdv == 64 ? 0 : target_lfbdv);
 
92
                        mtcpr(CPR0_PLLD, reg);
 
93
                        reset_needed = 1;
 
94
                }
 
95
 
 
96
                mfcpr(CPR0_PERD, reg);
 
97
                perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
 
98
                if (perdv0 != target_perdv0) {
 
99
                        reg &= ~CPR0_PERD_PERDV0_MASK;
 
100
                        reg |= (target_perdv0 << 24);
 
101
                        mtcpr(CPR0_PERD, reg);
 
102
                        reset_needed = 1;
 
103
                }
 
104
 
 
105
                mfcpr(CPR0_SPCID, reg);
 
106
                temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
 
107
                spcid0 = temp ? temp : 4;
 
108
                if (spcid0 != target_spcid0) {
 
109
                        reg &= ~CPR0_SPCID_SPCIDV0_MASK;
 
110
                        reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
 
111
                        mtcpr(CPR0_SPCID, reg);
 
112
                        reset_needed = 1;
 
113
                }
 
114
 
 
115
                /* Set reload inhibit so configuration will persist across
 
116
                 * processor resets */
 
117
                mfcpr(CPR0_ICFG, reg);
 
118
                reg &= ~CPR0_ICFG_RLI_MASK;
 
119
                reg |= 1 << 31;
 
120
                mtcpr(CPR0_ICFG, reg);
 
121
        }
 
122
 
 
123
        /* Reset processor if configuration changed */
 
124
        if (reset_needed) {
 
125
                __asm__ __volatile__ ("sync; isync");
 
126
                mtspr(SPRN_DBCR0, 0x20000000);
 
127
        }
 
128
#endif
 
129
}
 
130
 
 
131
/*
 
132
 * Breath some life into the CPU...
 
133
 *
 
134
 * Reconfigure PLL if necessary,
 
135
 * set up the memory map,
 
136
 * initialize a bunch of registers
 
137
 */
 
138
void
 
139
cpu_init_f (void)
 
140
{
 
141
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
 
142
        u32 val;
 
143
#endif
 
144
 
 
145
        reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
 
146
 
 
147
#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CONFIG_SYS_4xx_GPIO_TABLE)
 
148
        /*
 
149
         * GPIO0 setup (select GPIO or alternate function)
 
150
         */
 
151
#if defined(CONFIG_SYS_GPIO0_OR)
 
152
        out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR);           /* set initial state of output pins     */
 
153
#endif
 
154
#if defined(CONFIG_SYS_GPIO0_ODR)
 
155
        out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR); /* open-drain select                    */
 
156
#endif
 
157
        out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH);       /* output select                        */
 
158
        out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL);
 
159
        out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H);     /* input select                         */
 
160
        out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L);
 
161
        out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH);       /* three-state select                   */
 
162
        out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL);
 
163
#if defined(CONFIG_SYS_GPIO0_ISR2H)
 
164
        out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H);
 
165
        out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L);
 
166
#endif
 
167
#if defined (CONFIG_SYS_GPIO0_TCR)
 
168
        out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR); /* enable output driver for outputs     */
 
169
#endif
 
170
#endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */
 
171
 
 
172
#if defined (CONFIG_405EP)
 
173
        /*
 
174
         * Set EMAC noise filter bits
 
175
         */
 
176
        mtdcr(CPC0_EPCTL, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
 
177
#endif /* CONFIG_405EP */
 
178
 
 
179
#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
 
180
        gpio_set_chip_configuration();
 
181
#endif /* CONFIG_SYS_4xx_GPIO_TABLE */
 
182
 
 
183
        /*
 
184
         * External Bus Controller (EBC) Setup
 
185
         */
 
186
#if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
 
187
#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
 
188
     defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
 
189
     defined(CONFIG_405EX) || defined(CONFIG_405))
 
190
        /*
 
191
         * Move the next instructions into icache, since these modify the flash
 
192
         * we are running from!
 
193
         */
 
194
        asm volatile("  bl      0f"             ::: "lr");
 
195
        asm volatile("0:        mflr    3"              ::: "r3");
 
196
        asm volatile("  addi    4, 0, 14"       ::: "r4");
 
197
        asm volatile("  mtctr   4"              ::: "ctr");
 
198
        asm volatile("1:        icbt    0, 3");
 
199
        asm volatile("  addi    3, 3, 32"       ::: "r3");
 
200
        asm volatile("  bdnz    1b"             ::: "ctr", "cr0");
 
201
        asm volatile("  addis   3, 0, 0x0"      ::: "r3");
 
202
        asm volatile("  ori     3, 3, 0xA000"   ::: "r3");
 
203
        asm volatile("  mtctr   3"              ::: "ctr");
 
204
        asm volatile("2:        bdnz    2b"             ::: "ctr", "cr0");
 
205
#endif
 
206
 
 
207
        mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP);
 
208
        mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR);
 
209
#endif
 
210
 
 
211
#if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1))
 
212
        mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP);
 
213
        mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR);
 
214
#endif
 
215
 
 
216
#if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2))
 
217
        mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP);
 
218
        mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR);
 
219
#endif
 
220
 
 
221
#if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3))
 
222
        mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);
 
223
        mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
 
224
#endif
 
225
 
 
226
#if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4))
 
227
        mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP);
 
228
        mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR);
 
229
#endif
 
230
 
 
231
#if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5))
 
232
        mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP);
 
233
        mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR);
 
234
#endif
 
235
 
 
236
#if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6))
 
237
        mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP);
 
238
        mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR);
 
239
#endif
 
240
 
 
241
#if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7))
 
242
        mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP);
 
243
        mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR);
 
244
#endif
 
245
 
 
246
#if defined (CONFIG_SYS_EBC_CFG)
 
247
        mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG);
 
248
#endif
 
249
 
 
250
#if defined(CONFIG_WATCHDOG)
 
251
        val = mfspr(tcr);
 
252
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
 
253
        val |= 0xb8000000;      /* generate system reset after 1.34 seconds */
 
254
#elif defined(CONFIG_440EPX)
 
255
        val |= 0xb0000000;      /* generate system reset after 1.34 seconds */
 
256
#else
 
257
        val |= 0xf0000000;      /* generate system reset after 2.684 seconds */
 
258
#endif
 
259
#if defined(CONFIG_SYS_4xx_RESET_TYPE)
 
260
        val &= ~0x30000000;                     /* clear WRC bits */
 
261
        val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */
 
262
#endif
 
263
        mtspr(tcr, val);
 
264
 
 
265
        val = mfspr(tsr);
 
266
        val |= 0x80000000;      /* enable watchdog timer */
 
267
        mtspr(tsr, val);
 
268
 
 
269
        reset_4xx_watchdog();
 
270
#endif /* CONFIG_WATCHDOG */
 
271
 
 
272
#if defined(CONFIG_440GX)
 
273
        /* Take the GX out of compatibility mode
 
274
         * Travis Sawyer, 9 Mar 2004
 
275
         * NOTE: 440gx user manual inconsistency here
 
276
         *       Compatibility mode and Ethernet Clock select are not
 
277
         *       correct in the manual
 
278
         */
 
279
        mfsdr(SDR0_MFR, val);
 
280
        val &= ~0x10000000;
 
281
        mtsdr(SDR0_MFR,val);
 
282
#endif /* CONFIG_440GX */
 
283
 
 
284
#if defined(CONFIG_460EX)
 
285
        /*
 
286
         * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
 
287
         * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata
 
288
         * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA
 
289
         */
 
290
        mfsdr(SDR0_AHB_CFG, val);
 
291
        val |= 0x80;
 
292
        val &= ~0x40;
 
293
        mtsdr(SDR0_AHB_CFG, val);
 
294
        mfsdr(SDR0_USB2HOST_CFG, val);
 
295
        val &= ~0xf00;
 
296
        val |= 0x400;
 
297
        mtsdr(SDR0_USB2HOST_CFG, val);
 
298
#endif /* CONFIG_460EX */
 
299
 
 
300
#if defined(CONFIG_405EX) || \
 
301
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
 
302
    defined(CONFIG_460EX) || defined(CONFIG_460GT)  || \
 
303
    defined(CONFIG_460SX)
 
304
        /*
 
305
         * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
 
306
         */
 
307
        mtdcr(PLB0_ACR, (mfdcr(PLB0_ACR) & ~PLB0_ACR_RDP_MASK) |
 
308
              PLB0_ACR_RDP_4DEEP);
 
309
        mtdcr(PLB1_ACR, (mfdcr(PLB1_ACR) & ~PLB1_ACR_RDP_MASK) |
 
310
              PLB1_ACR_RDP_4DEEP);
 
311
#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
 
312
}
 
313
 
 
314
/*
 
315
 * initialize higher level parts of CPU like time base and timers
 
316
 */
 
317
int cpu_init_r (void)
 
318
{
 
319
#if defined(CONFIG_405GP)
 
320
        uint pvr = get_pvr();
 
321
 
 
322
        /*
 
323
         * Set edge conditioning circuitry on PPC405GPr
 
324
         * for compatibility to existing PPC405GP designs.
 
325
         */
 
326
        if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
 
327
                mtdcr(CPC0_ECR, 0x60606000);
 
328
        }
 
329
#endif  /* defined(CONFIG_405GP) */
 
330
 
 
331
        return 0;
 
332
}
 
333
 
 
334
#if defined(CONFIG_PCI) && \
 
335
        (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
 
336
         defined(CONFIG_440GR) || defined(CONFIG_440GRX))
 
337
/*
 
338
 * 440EP(x)/GR(x) PCI async/sync clocking restriction:
 
339
 *
 
340
 * In asynchronous PCI mode, the synchronous PCI clock must meet
 
341
 * certain requirements. The following equation describes the
 
342
 * relationship that must be maintained between the asynchronous PCI
 
343
 * clock and synchronous PCI clock. Select an appropriate PCI:PLB
 
344
 * ratio to maintain the relationship:
 
345
 *
 
346
 * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz
 
347
 */
 
348
static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async)
 
349
{
 
350
        if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000)))
 
351
                return 0;
 
352
        else
 
353
                return 1;
 
354
}
 
355
 
 
356
int ppc4xx_pci_sync_clock_config(u32 async)
 
357
{
 
358
        sys_info_t sys_info;
 
359
        u32 sync;
 
360
        int div;
 
361
        u32 reg;
 
362
        u32 spcid_val[] = {
 
363
                CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2,
 
364
                CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 };
 
365
 
 
366
        get_sys_info(&sys_info);
 
367
        sync = sys_info.freqPCI;
 
368
 
 
369
        /*
 
370
         * First check if the equation above is met
 
371
         */
 
372
        if (!ppc4xx_pci_sync_clock_ok(sync, async)) {
 
373
                /*
 
374
                 * Reconfigure PCI sync clock to meet the equation.
 
375
                 * Start with highest possible PCI sync frequency
 
376
                 * (divider 1).
 
377
                 */
 
378
                for (div = 1; div <= 4; div++) {
 
379
                        sync = sys_info.freqPLB / div;
 
380
                        if (ppc4xx_pci_sync_clock_ok(sync, async))
 
381
                            break;
 
382
                }
 
383
 
 
384
                if (div <= 4) {
 
385
                        mtcpr(CPR0_SPCID, spcid_val[div]);
 
386
 
 
387
                        mfcpr(CPR0_ICFG, reg);
 
388
                        reg |= CPR0_ICFG_RLI_MASK;
 
389
                        mtcpr(CPR0_ICFG, reg);
 
390
 
 
391
                        /* do chip reset */
 
392
                        mtspr(SPRN_DBCR0, 0x20000000);
 
393
                } else {
 
394
                        /* Impossible to configure the PCI sync clock */
 
395
                        return -1;
 
396
                }
 
397
        }
 
398
 
 
399
        return 0;
 
400
}
 
401
#endif