mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-04 02:20:25 +00:00
c821b5f120
This patch (Part 1 of 2): * Rolls up a suite of changes to enable correct primordial stack and global data handling when the data cache is used for such a purpose for PPC40x-variants (i.e. CFG_INIT_DCACHE_CS). * Related to the first, unifies DDR2 SDRAM and ECC initialization by eliminating redundant ECC initialization implementations and moving redundant SDRAM initialization out of board code into shared 4xx code. * Enables MCSR visibility on the 405EX(r). * Enables the use of the data cache for initial RAM on both AMCC's Kilauea and Makalu and removes a redundant CFG_POST_MEMORY flag from each board's CONFIG_POST value. - Removed, per Stefan Roese's request, defunct memory.c file for Makalu and rolled sdram_init from it into makalu.c. With respect to the 4xx DDR initialization and ECC unification, there is certainly more work that can and should be done (file renaming, etc.). However, that can be handled at a later date on a second or third pass. As it stands, this patch moves things forward in an incremental yet positive way for those platforms that utilize this code and the features associated with it. Signed-off-by: Grant Erickson <gerickson@nuovations.com> Signed-off-by: Stefan Roese <sr@denx.de>
320 lines
8.7 KiB
C
320 lines
8.7 KiB
C
/*
|
|
* (C) Copyright 2000-2007
|
|
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
|
*
|
|
* See file CREDITS for list of people who contributed to this
|
|
* project.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <watchdog.h>
|
|
#include <ppc4xx_enet.h>
|
|
#include <asm/processor.h>
|
|
#include <asm/gpio.h>
|
|
#include <ppc4xx.h>
|
|
|
|
#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
#endif
|
|
|
|
#ifndef CFG_PLL_RECONFIG
|
|
#define CFG_PLL_RECONFIG 0
|
|
#endif
|
|
|
|
void reconfigure_pll(u32 new_cpu_freq)
|
|
{
|
|
#if defined(CONFIG_440EPX)
|
|
int reset_needed = 0;
|
|
u32 reg, temp;
|
|
u32 prbdv0, target_prbdv0, /* CLK_PRIMBD */
|
|
fwdva, target_fwdva, fwdvb, target_fwdvb, /* CLK_PLLD */
|
|
fbdv, target_fbdv, lfbdv, target_lfbdv,
|
|
perdv0, target_perdv0, /* CLK_PERD */
|
|
spcid0, target_spcid0; /* CLK_SPCID */
|
|
|
|
/* Reconfigure clocks if necessary.
|
|
* See PPC440EPx User's Manual, sections 8.2 and 14 */
|
|
if (new_cpu_freq == 667) {
|
|
target_prbdv0 = 2;
|
|
target_fwdva = 2;
|
|
target_fwdvb = 4;
|
|
target_fbdv = 20;
|
|
target_lfbdv = 1;
|
|
target_perdv0 = 4;
|
|
target_spcid0 = 4;
|
|
|
|
mfcpr(clk_primbd, reg);
|
|
temp = (reg & PRBDV_MASK) >> 24;
|
|
prbdv0 = temp ? temp : 8;
|
|
if (prbdv0 != target_prbdv0) {
|
|
reg &= ~PRBDV_MASK;
|
|
reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
|
|
mtcpr(clk_primbd, reg);
|
|
reset_needed = 1;
|
|
}
|
|
|
|
mfcpr(clk_plld, reg);
|
|
|
|
temp = (reg & PLLD_FWDVA_MASK) >> 16;
|
|
fwdva = temp ? temp : 16;
|
|
|
|
temp = (reg & PLLD_FWDVB_MASK) >> 8;
|
|
fwdvb = temp ? temp : 8;
|
|
|
|
temp = (reg & PLLD_FBDV_MASK) >> 24;
|
|
fbdv = temp ? temp : 32;
|
|
|
|
temp = (reg & PLLD_LFBDV_MASK);
|
|
lfbdv = temp ? temp : 64;
|
|
|
|
if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
|
|
reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
|
|
PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
|
|
reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
|
|
((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
|
|
((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
|
|
(target_lfbdv == 64 ? 0 : target_lfbdv);
|
|
mtcpr(clk_plld, reg);
|
|
reset_needed = 1;
|
|
}
|
|
|
|
mfcpr(clk_perd, reg);
|
|
perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
|
|
if (perdv0 != target_perdv0) {
|
|
reg &= ~CPR0_PERD_PERDV0_MASK;
|
|
reg |= (target_perdv0 << 24);
|
|
mtcpr(clk_perd, reg);
|
|
reset_needed = 1;
|
|
}
|
|
|
|
mfcpr(clk_spcid, reg);
|
|
temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
|
|
spcid0 = temp ? temp : 4;
|
|
if (spcid0 != target_spcid0) {
|
|
reg &= ~CPR0_SPCID_SPCIDV0_MASK;
|
|
reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
|
|
mtcpr(clk_spcid, reg);
|
|
reset_needed = 1;
|
|
}
|
|
|
|
/* Set reload inhibit so configuration will persist across
|
|
* processor resets */
|
|
mfcpr(clk_icfg, reg);
|
|
reg &= ~CPR0_ICFG_RLI_MASK;
|
|
reg |= 1 << 31;
|
|
mtcpr(clk_icfg, reg);
|
|
}
|
|
|
|
/* Reset processor if configuration changed */
|
|
if (reset_needed) {
|
|
__asm__ __volatile__ ("sync; isync");
|
|
mtspr(dbcr0, 0x20000000);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Breath some life into the CPU...
|
|
*
|
|
* Reconfigure PLL if necessary,
|
|
* set up the memory map,
|
|
* initialize a bunch of registers
|
|
*/
|
|
void
|
|
cpu_init_f (void)
|
|
{
|
|
#if defined(CONFIG_WATCHDOG)
|
|
unsigned long val;
|
|
#endif
|
|
reconfigure_pll(CFG_PLL_RECONFIG);
|
|
|
|
#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE)
|
|
/*
|
|
* GPIO0 setup (select GPIO or alternate function)
|
|
*/
|
|
#if defined(CFG_GPIO0_OR)
|
|
out32(GPIO0_OR, CFG_GPIO0_OR); /* set initial state of output pins */
|
|
#endif
|
|
#if defined(CFG_GPIO0_ODR)
|
|
out32(GPIO0_ODR, CFG_GPIO0_ODR); /* open-drain select */
|
|
#endif
|
|
out32(GPIO0_OSRH, CFG_GPIO0_OSRH); /* output select */
|
|
out32(GPIO0_OSRL, CFG_GPIO0_OSRL);
|
|
out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H); /* input select */
|
|
out32(GPIO0_ISR1L, CFG_GPIO0_ISR1L);
|
|
out32(GPIO0_TSRH, CFG_GPIO0_TSRH); /* three-state select */
|
|
out32(GPIO0_TSRL, CFG_GPIO0_TSRL);
|
|
#if defined(CFG_GPIO0_ISR2H)
|
|
out32(GPIO0_ISR2H, CFG_GPIO0_ISR2H);
|
|
out32(GPIO0_ISR2L, CFG_GPIO0_ISR2L);
|
|
#endif
|
|
#if defined (CFG_GPIO0_TCR)
|
|
out32(GPIO0_TCR, CFG_GPIO0_TCR); /* enable output driver for outputs */
|
|
#endif
|
|
#endif /* CONFIG_405EP ... && !CFG_4xx_GPIO_TABLE */
|
|
|
|
#if defined (CONFIG_405EP)
|
|
/*
|
|
* Set EMAC noise filter bits
|
|
*/
|
|
mtdcr(cpc0_epctl, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
|
|
|
|
/*
|
|
* Enable the internal PCI arbiter
|
|
*/
|
|
mtdcr(cpc0_pci, mfdcr(cpc0_pci) | CPC0_PCI_HOST_CFG_EN | CPC0_PCI_ARBIT_EN);
|
|
#endif /* CONFIG_405EP */
|
|
|
|
#if defined(CFG_4xx_GPIO_TABLE)
|
|
gpio_set_chip_configuration();
|
|
#endif /* CFG_4xx_GPIO_TABLE */
|
|
|
|
/*
|
|
* External Bus Controller (EBC) Setup
|
|
*/
|
|
#if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
|
|
#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
|
|
defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
|
|
defined(CONFIG_405EX) || defined(CONFIG_405))
|
|
/*
|
|
* Move the next instructions into icache, since these modify the flash
|
|
* we are running from!
|
|
*/
|
|
asm volatile(" bl 0f" ::: "lr");
|
|
asm volatile("0: mflr 3" ::: "r3");
|
|
asm volatile(" addi 4, 0, 14" ::: "r4");
|
|
asm volatile(" mtctr 4" ::: "ctr");
|
|
asm volatile("1: icbt 0, 3");
|
|
asm volatile(" addi 3, 3, 32" ::: "r3");
|
|
asm volatile(" bdnz 1b" ::: "ctr", "cr0");
|
|
asm volatile(" addis 3, 0, 0x0" ::: "r3");
|
|
asm volatile(" ori 3, 3, 0xA000" ::: "r3");
|
|
asm volatile(" mtctr 3" ::: "ctr");
|
|
asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
|
|
#endif
|
|
|
|
mtebc(pb0ap, CFG_EBC_PB0AP);
|
|
mtebc(pb0cr, CFG_EBC_PB0CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR) && !(CFG_INIT_DCACHE_CS == 1))
|
|
mtebc(pb1ap, CFG_EBC_PB1AP);
|
|
mtebc(pb1cr, CFG_EBC_PB1CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR) && !(CFG_INIT_DCACHE_CS == 2))
|
|
mtebc(pb2ap, CFG_EBC_PB2AP);
|
|
mtebc(pb2cr, CFG_EBC_PB2CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR) && !(CFG_INIT_DCACHE_CS == 3))
|
|
mtebc(pb3ap, CFG_EBC_PB3AP);
|
|
mtebc(pb3cr, CFG_EBC_PB3CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR) && !(CFG_INIT_DCACHE_CS == 4))
|
|
mtebc(pb4ap, CFG_EBC_PB4AP);
|
|
mtebc(pb4cr, CFG_EBC_PB4CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR) && !(CFG_INIT_DCACHE_CS == 5))
|
|
mtebc(pb5ap, CFG_EBC_PB5AP);
|
|
mtebc(pb5cr, CFG_EBC_PB5CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR) && !(CFG_INIT_DCACHE_CS == 6))
|
|
mtebc(pb6ap, CFG_EBC_PB6AP);
|
|
mtebc(pb6cr, CFG_EBC_PB6CR);
|
|
#endif
|
|
|
|
#if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR) && !(CFG_INIT_DCACHE_CS == 7))
|
|
mtebc(pb7ap, CFG_EBC_PB7AP);
|
|
mtebc(pb7cr, CFG_EBC_PB7CR);
|
|
#endif
|
|
|
|
#if defined (CFG_EBC_CFG)
|
|
mtebc(EBC0_CFG, CFG_EBC_CFG);
|
|
#endif
|
|
|
|
#if defined(CONFIG_WATCHDOG)
|
|
val = mfspr(tcr);
|
|
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
|
|
val |= 0xb8000000; /* generate system reset after 1.34 seconds */
|
|
#elif defined(CONFIG_440EPX)
|
|
val |= 0xb0000000; /* generate system reset after 1.34 seconds */
|
|
#else
|
|
val |= 0xf0000000; /* generate system reset after 2.684 seconds */
|
|
#endif
|
|
#if defined(CFG_4xx_RESET_TYPE)
|
|
val &= ~0x30000000; /* clear WRC bits */
|
|
val |= CFG_4xx_RESET_TYPE << 28; /* set board specific WRC type */
|
|
#endif
|
|
mtspr(tcr, val);
|
|
|
|
val = mfspr(tsr);
|
|
val |= 0x80000000; /* enable watchdog timer */
|
|
mtspr(tsr, val);
|
|
|
|
reset_4xx_watchdog();
|
|
#endif /* CONFIG_WATCHDOG */
|
|
}
|
|
|
|
/*
|
|
* initialize higher level parts of CPU like time base and timers
|
|
*/
|
|
int cpu_init_r (void)
|
|
{
|
|
#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
|
|
bd_t *bd = gd->bd;
|
|
unsigned long reg;
|
|
#if defined(CONFIG_405GP)
|
|
uint pvr = get_pvr();
|
|
#endif
|
|
|
|
/*
|
|
* Write Ethernetaddress into on-chip register
|
|
*/
|
|
reg = 0x00000000;
|
|
reg |= bd->bi_enetaddr[0]; /* set high address */
|
|
reg = reg << 8;
|
|
reg |= bd->bi_enetaddr[1];
|
|
out32 (EMAC_IAH, reg);
|
|
|
|
reg = 0x00000000;
|
|
reg |= bd->bi_enetaddr[2]; /* set low address */
|
|
reg = reg << 8;
|
|
reg |= bd->bi_enetaddr[3];
|
|
reg = reg << 8;
|
|
reg |= bd->bi_enetaddr[4];
|
|
reg = reg << 8;
|
|
reg |= bd->bi_enetaddr[5];
|
|
out32 (EMAC_IAL, reg);
|
|
|
|
#if defined(CONFIG_405GP)
|
|
/*
|
|
* Set edge conditioning circuitry on PPC405GPr
|
|
* for compatibility to existing PPC405GP designs.
|
|
*/
|
|
if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
|
|
mtdcr(ecr, 0x60606000);
|
|
}
|
|
#endif /* defined(CONFIG_405GP) */
|
|
#endif /* defined(CONFIG_405GP) || defined(CONFIG_405EP) */
|
|
|
|
return (0);
|
|
}
|