blob: 642d8780bb317243fb74285298342306f97dd877 [file] [log] [blame]
David Gibsonf6dfc802007-05-08 14:10:01 +10001/*
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
Josh Boyere90f3b72007-08-20 07:28:30 -050024/* Read the 4xx SDRAM controller to get size of system memory. */
25void ibm4xx_fixup_memsize(void)
David Gibsonf6dfc802007-05-08 14:10:01 +100026{
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}
David Gibson11123342007-06-13 14:52:58 +100041
Josh Boyere90f3b72007-08-20 07:28:30 -050042#define SPRN_DBCR0_40X 0x3F2
43#define SPRN_DBCR0_44X 0x134
44#define DBCR0_RST_SYSTEM 0x30000000
David Gibson11123342007-06-13 14:52:58 +100045
46void 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"
Josh Boyere90f3b72007-08-20 07:28:30 -050054 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
David Gibson11123342007-06-13 14:52:58 +100055 );
56
57}
David Gibsonb2ba34f2007-06-13 14:52:59 +100058
Josh Boyere90f3b72007-08-20 07:28:30 -050059void 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
72void 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
David Gibsonb2ba34f2007-06-13 14:52:59 +100083/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
84 * banks into the OPB address space */
85void 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}
Josh Boyer2ba45732007-08-20 07:30:32 -0500111
112#define SPRN_CCR1 0x378
113void 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}