2 * Copyright 2007 David Gibson, IBM Corporation.
4 * Based on earlier code:
5 * Matt Porter <mporter@kernel.crashing.org>
6 * Copyright 2002-2005 MontaVista Software Inc.
8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9 * Copyright (c) 2003, 2004 Zultys Technologies
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.
24 /* Read the 4xx SDRAM controller to get size of system memory. */
25 void ibm4xx_fixup_memsize(void)
28 unsigned long memsize
, bank_config
;
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
);
35 if (bank_config
& SDRAM_CONFIG_BANK_ENABLE
)
36 memsize
+= SDRAM_CONFIG_BANK_SIZE(bank_config
);
39 dt_fixup_memory(0, memsize
);
42 /* 4xx DDR1/2 Denali memory controller support */
53 #define DDR_START_SHIFT 0
54 #define DDR_MAX_CS_REG 0x3
55 #define DDR_MAX_CS_REG_SHIFT 24
56 #define DDR_MAX_COL_REG 0xf
57 #define DDR_MAX_COL_REG_SHIFT 16
58 #define DDR_MAX_ROW_REG 0xf
59 #define DDR_MAX_ROW_REG_SHIFT 8
61 #define DDR_DDR2_MODE 0x1
62 #define DDR_DDR2_MODE_SHIFT 0
64 #define DDR_CS_MAP 0x3
65 #define DDR_CS_MAP_SHIFT 8
68 #define DDR_REDUC_SHIFT 16
71 #define DDR_APIN_SHIFT 24
73 #define DDR_COL_SZ 0x7
74 #define DDR_COL_SZ_SHIFT 8
76 #define DDR_BANK8_SHIFT 0
78 #define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
80 static inline u32
mfdcr_sdram0(u32 reg
)
82 mtdcr(DCRN_SDRAM0_CFGADDR
, reg
);
83 return mfdcr(DCRN_SDRAM0_CFGDATA
);
86 void ibm4xx_denali_fixup_memsize(void)
88 u32 val
, max_cs
, max_col
, max_row
;
89 u32 cs
, col
, row
, bank
, dpath
;
90 unsigned long memsize
;
92 val
= mfdcr_sdram0(DDR0_02
);
93 if (!DDR_GET_VAL(val
, DDR_START
, DDR_START_SHIFT
))
94 fatal("DDR controller is not initialized\n");
96 /* get maximum cs col and row values */
97 max_cs
= DDR_GET_VAL(val
, DDR_MAX_CS_REG
, DDR_MAX_CS_REG_SHIFT
);
98 max_col
= DDR_GET_VAL(val
, DDR_MAX_COL_REG
, DDR_MAX_COL_REG_SHIFT
);
99 max_row
= DDR_GET_VAL(val
, DDR_MAX_ROW_REG
, DDR_MAX_ROW_REG_SHIFT
);
102 val
= mfdcr_sdram0(DDR0_10
);
104 val
= DDR_GET_VAL(val
, DDR_CS_MAP
, DDR_CS_MAP_SHIFT
);
113 fatal("No memory installed\n");
115 fatal("DDR wrong CS configuration\n");
117 /* get data path bytes */
118 val
= mfdcr_sdram0(DDR0_14
);
120 if (DDR_GET_VAL(val
, DDR_REDUC
, DDR_REDUC_SHIFT
))
121 dpath
= 8; /* 64 bits */
123 dpath
= 4; /* 32 bits */
125 /* get adress pins (rows) */
126 val
= mfdcr_sdram0(DDR0_42
);
128 row
= DDR_GET_VAL(val
, DDR_APIN
, DDR_APIN_SHIFT
);
130 fatal("DDR wrong APIN configuration\n");
133 /* get collomn size and banks */
134 val
= mfdcr_sdram0(DDR0_43
);
136 col
= DDR_GET_VAL(val
, DDR_COL_SZ
, DDR_COL_SZ_SHIFT
);
138 fatal("DDR wrong COL configuration\n");
141 if (DDR_GET_VAL(val
, DDR_BANK8
, DDR_BANK8_SHIFT
))
142 bank
= 8; /* 8 banks */
144 bank
= 4; /* 4 banks */
146 memsize
= cs
* (1 << (col
+row
)) * bank
* dpath
;
147 dt_fixup_memory(0, memsize
);
150 #define SPRN_DBCR0_40X 0x3F2
151 #define SPRN_DBCR0_44X 0x134
152 #define DBCR0_RST_SYSTEM 0x30000000
154 void ibm44x_dbcr_reset(void)
162 : "=&r"(tmp
) : "i"(SPRN_DBCR0_44X
), "i"(DBCR0_RST_SYSTEM
)
167 void ibm40x_dbcr_reset(void)
175 : "=&r"(tmp
) : "i"(SPRN_DBCR0_40X
), "i"(DBCR0_RST_SYSTEM
)
179 #define EMAC_RESET 0x20000000
180 void ibm4xx_quiesce_eth(u32
*emac0
, u32
*emac1
)
182 /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't do this for us */
188 mtdcr(DCRN_MAL0_CFG
, MAL_RESET
);
191 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
192 * banks into the OPB address space */
193 void ibm4xx_fixup_ebc_ranges(const char *ebc
)
197 u32 ranges
[EBC_NUM_BANKS
*4];
201 for (i
= 0; i
< EBC_NUM_BANKS
; i
++) {
202 mtdcr(DCRN_EBC0_CFGADDR
, EBC_BXCR(i
));
203 bxcr
= mfdcr(DCRN_EBC0_CFGDATA
);
205 if ((bxcr
& EBC_BXCR_BU
) != EBC_BXCR_BU_OFF
) {
208 *p
++ = bxcr
& EBC_BXCR_BAS
;
209 *p
++ = EBC_BXCR_BANK_SIZE(bxcr
);
213 devp
= finddevice(ebc
);
215 fatal("Couldn't locate EBC node %s\n\r", ebc
);
217 setprop(devp
, "ranges", ranges
, (p
- ranges
) * sizeof(u32
));
220 #define SPRN_CCR1 0x378
221 void ibm440ep_fixup_clocks(unsigned int sysclk
, unsigned int ser_clk
)
223 u32 cpu
, plb
, opb
, ebc
, tb
, uart0
, m
, vco
;
225 u32 fwdva
, fwdvb
, fbdv
, lfbdv
, opbdv0
, perdv0
, spcid0
, prbdv0
, tmp
;
227 mtdcr(DCRN_CPR0_ADDR
, CPR0_PLLD0
);
228 reg
= mfdcr(DCRN_CPR0_DATA
);
229 tmp
= (reg
& 0x000F0000) >> 16;
230 fwdva
= tmp
? tmp
: 16;
231 tmp
= (reg
& 0x00000700) >> 8;
232 fwdvb
= tmp
? tmp
: 8;
233 tmp
= (reg
& 0x1F000000) >> 24;
234 fbdv
= tmp
? tmp
: 32;
235 lfbdv
= (reg
& 0x0000007F);
237 mtdcr(DCRN_CPR0_ADDR
, CPR0_OPBD0
);
238 reg
= mfdcr(DCRN_CPR0_DATA
);
239 tmp
= (reg
& 0x03000000) >> 24;
240 opbdv0
= tmp
? tmp
: 4;
242 mtdcr(DCRN_CPR0_ADDR
, CPR0_PERD0
);
243 reg
= mfdcr(DCRN_CPR0_DATA
);
244 tmp
= (reg
& 0x07000000) >> 24;
245 perdv0
= tmp
? tmp
: 8;
247 mtdcr(DCRN_CPR0_ADDR
, CPR0_PRIMBD0
);
248 reg
= mfdcr(DCRN_CPR0_DATA
);
249 tmp
= (reg
& 0x07000000) >> 24;
250 prbdv0
= tmp
? tmp
: 8;
252 mtdcr(DCRN_CPR0_ADDR
, CPR0_SCPID
);
253 reg
= mfdcr(DCRN_CPR0_DATA
);
254 tmp
= (reg
& 0x03000000) >> 24;
255 spcid0
= tmp
? tmp
: 4;
258 mtdcr(DCRN_CPR0_ADDR
, CPR0_PLLC0
);
259 reg
= mfdcr(DCRN_CPR0_DATA
);
260 tmp
= (reg
& 0x03000000) >> 24;
261 if (tmp
== 0) { /* PLL output */
262 tmp
= (reg
& 0x20000000) >> 29;
263 if (!tmp
) /* PLLOUTA */
264 m
= fbdv
* lfbdv
* fwdva
;
266 m
= fbdv
* lfbdv
* fwdvb
;
268 else if (tmp
== 1) /* CPU output */
271 m
= perdv0
* opbdv0
* fwdvb
;
273 vco
= (m
* sysclk
) + (m
>> 1);
275 plb
= vco
/ fwdvb
/ prbdv0
;
282 /* Figure out timebase. Either CPU or default TmrClk */
286 "=&r"(reg
) : "i"(SPRN_CCR1
));
288 tb
= 25000000; /* TmrClk is 25MHz */
292 dt_fixup_cpu_clocks(cpu
, tb
, 0);
293 dt_fixup_clock("/plb", plb
);
294 dt_fixup_clock("/plb/opb", opb
);
295 dt_fixup_clock("/plb/opb/ebc", ebc
);
296 dt_fixup_clock("/plb/opb/serial@ef600300", uart0
);
297 dt_fixup_clock("/plb/opb/serial@ef600400", uart0
);
298 dt_fixup_clock("/plb/opb/serial@ef600500", uart0
);
299 dt_fixup_clock("/plb/opb/serial@ef600600", uart0
);