]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/powerpc/boot/4xx.c
[POWERPC] Bamboo zImage wrapper
[linux-2.6-omap-h63xx.git] / arch / powerpc / boot / 4xx.c
1 /*
2  * Copyright 2007 David Gibson, IBM Corporation.
3  *
4  * Based on earlier code:
5  *   Matt Porter <mporter@kernel.crashing.org>
6  *   Copyright 2002-2005 MontaVista Software Inc.
7  *
8  *   Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9  *   Copyright (c) 2003, 2004 Zultys Technologies
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version
14  * 2 of the License, or (at your option) any later version.
15  */
16 #include <stddef.h>
17 #include "types.h"
18 #include "string.h"
19 #include "stdio.h"
20 #include "ops.h"
21 #include "reg.h"
22 #include "dcr.h"
23
24 /* Read the 4xx SDRAM controller to get size of system memory. */
25 void ibm4xx_fixup_memsize(void)
26 {
27         int i;
28         unsigned long memsize, bank_config;
29
30         memsize = 0;
31         for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
32                 mtdcr(DCRN_SDRAM0_CFGADDR, sdram_bxcr[i]);
33                 bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
34
35                 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
36                         memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
37         }
38
39         dt_fixup_memory(0, memsize);
40 }
41
42 #define SPRN_DBCR0_40X 0x3F2
43 #define SPRN_DBCR0_44X 0x134
44 #define DBCR0_RST_SYSTEM 0x30000000
45
46 void ibm44x_dbcr_reset(void)
47 {
48         unsigned long tmp;
49
50         asm volatile (
51                 "mfspr  %0,%1\n"
52                 "oris   %0,%0,%2@h\n"
53                 "mtspr  %1,%0"
54                 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
55                 );
56
57 }
58
59 void ibm40x_dbcr_reset(void)
60 {
61         unsigned long tmp;
62
63         asm volatile (
64                 "mfspr  %0,%1\n"
65                 "oris   %0,%0,%2@h\n"
66                 "mtspr  %1,%0"
67                 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
68                 );
69 }
70
71 #define EMAC_RESET 0x20000000
72 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
73 {
74         /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't do this for us */
75         if (emac0)
76                 *emac0 = EMAC_RESET;
77         if (emac1)
78                 *emac1 = EMAC_RESET;
79
80         mtdcr(DCRN_MAL0_CFG, MAL_RESET);
81 }
82
83 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
84  * banks into the OPB address space */
85 void ibm4xx_fixup_ebc_ranges(const char *ebc)
86 {
87         void *devp;
88         u32 bxcr;
89         u32 ranges[EBC_NUM_BANKS*4];
90         u32 *p = ranges;
91         int i;
92
93         for (i = 0; i < EBC_NUM_BANKS; i++) {
94                 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
95                 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
96
97                 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
98                         *p++ = i;
99                         *p++ = 0;
100                         *p++ = bxcr & EBC_BXCR_BAS;
101                         *p++ = EBC_BXCR_BANK_SIZE(bxcr);
102                 }
103         }
104
105         devp = finddevice(ebc);
106         if (! devp)
107                 fatal("Couldn't locate EBC node %s\n\r", ebc);
108
109         setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
110 }
111
112 #define SPRN_CCR1 0x378
113 void ibm440ep_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
114 {
115         u32 cpu, plb, opb, ebc, tb, uart0, m, vco;
116         u32 reg;
117         u32 fwdva, fwdvb, fbdv, lfbdv, opbdv0, perdv0, spcid0, prbdv0, tmp;
118
119         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLD0);
120         reg = mfdcr(DCRN_CPR0_DATA);
121         tmp = (reg & 0x000F0000) >> 16;
122         fwdva = tmp ? tmp : 16;
123         tmp = (reg & 0x00000700) >> 8;
124         fwdvb = tmp ? tmp : 8;
125         tmp = (reg & 0x1F000000) >> 24;
126         fbdv = tmp ? tmp : 32;
127         lfbdv = (reg & 0x0000007F);
128
129         mtdcr(DCRN_CPR0_ADDR, CPR0_OPBD0);
130         reg = mfdcr(DCRN_CPR0_DATA);
131         tmp = (reg & 0x03000000) >> 24;
132         opbdv0 = tmp ? tmp : 4;
133
134         mtdcr(DCRN_CPR0_ADDR, CPR0_PERD0);
135         reg = mfdcr(DCRN_CPR0_DATA);
136         tmp = (reg & 0x07000000) >> 24;
137         perdv0 = tmp ? tmp : 8;
138
139         mtdcr(DCRN_CPR0_ADDR, CPR0_PRIMBD0);
140         reg = mfdcr(DCRN_CPR0_DATA);
141         tmp = (reg & 0x07000000) >> 24;
142         prbdv0 = tmp ? tmp : 8;
143
144         mtdcr(DCRN_CPR0_ADDR, CPR0_SCPID);
145         reg = mfdcr(DCRN_CPR0_DATA);
146         tmp = (reg & 0x03000000) >> 24;
147         spcid0 = tmp ? tmp : 4;
148
149         /* Calculate M */
150         mtdcr(DCRN_CPR0_ADDR, CPR0_PLLC0);
151         reg = mfdcr(DCRN_CPR0_DATA);
152         tmp = (reg & 0x03000000) >> 24;
153         if (tmp == 0) { /* PLL output */
154                 tmp = (reg & 0x20000000) >> 29;
155                 if (!tmp) /* PLLOUTA */
156                         m = fbdv * lfbdv * fwdva;
157                 else
158                         m = fbdv * lfbdv * fwdvb;
159         }
160         else if (tmp == 1) /* CPU output */
161                 m = fbdv * fwdva;
162         else
163                 m = perdv0 * opbdv0 * fwdvb;
164
165         vco = (m * sysclk) + (m >> 1);
166         cpu = vco / fwdva;
167         plb = vco / fwdvb / prbdv0;
168         opb = plb / opbdv0;
169         ebc = plb / perdv0;
170
171         /* FIXME */
172         uart0 = ser_clk;
173
174         /* Figure out timebase.  Either CPU or default TmrClk */
175         asm volatile (
176                         "mfspr  %0,%1\n"
177                         :
178                         "=&r"(reg) : "i"(SPRN_CCR1));
179         if (reg & 0x0080)
180                 tb = 25000000; /* TmrClk is 25MHz */
181         else
182                 tb = cpu;
183
184         dt_fixup_cpu_clocks(cpu, tb, 0);
185         dt_fixup_clock("/plb", plb);
186         dt_fixup_clock("/plb/opb", opb);
187         dt_fixup_clock("/plb/opb/ebc", ebc);
188         dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
189         dt_fixup_clock("/plb/opb/serial@ef600400", uart0);
190         dt_fixup_clock("/plb/opb/serial@ef600500", uart0);
191         dt_fixup_clock("/plb/opb/serial@ef600600", uart0);
192 }