diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/ppc4xx/4xx_enet.c | 72 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu_init.c | 102 | ||||
-rw-r--r-- | cpu/ppc4xx/denali_spd_ddr2.c | 27 | ||||
-rw-r--r-- | cpu/ppc4xx/interrupts.c | 7 |
4 files changed, 181 insertions, 27 deletions
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index d990250..007cb4f 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -274,7 +274,7 @@ static void emac_loopback_disable(EMAC_4XX_HW_PST hw_p) static void ppc_4xx_eth_halt (struct eth_device *dev) { EMAC_4XX_HW_PST hw_p = dev->priv; - uint32_t failsafe = 10000; + u32 val = 10000; out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */ @@ -290,8 +290,8 @@ static void ppc_4xx_eth_halt (struct eth_device *dev) /* wait for reset */ while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) { udelay (1000); /* Delay 1 MS so as not to hammer the register */ - failsafe--; - if (failsafe == 0) + val--; + if (val == 0) break; } @@ -308,6 +308,13 @@ static void ppc_4xx_eth_halt (struct eth_device *dev) hw_p->print_speed = 1; /* print speed message again next time */ #endif +#if defined(CONFIG_460EX) || defined(CONFIG_460GT) + /* don't bypass the TAHOE0/TAHOE1 cores for Linux */ + mfsdr(SDR0_ETH_CFG, val); + val &= ~(SDR0_ETH_CFG_TAHOE0_BYPASS | SDR0_ETH_CFG_TAHOE1_BYPASS); + mtsdr(SDR0_ETH_CFG, val); +#endif + return; } @@ -494,11 +501,18 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) u32 zmiifer; /* ZMII0_FER reg. */ u32 rmiifer; /* RGMII0_FER reg. Bridge 0 */ u32 rmiifer1; /* RGMII0_FER reg. Bridge 1 */ + int mode; zmiifer = 0; rmiifer = 0; rmiifer1 = 0; +#if defined(CONFIG_460EX) + mode = 9; +#else + mode = 10; +#endif + /* TODO: * NOTE: 460GT has 2 RGMII bridge cores: * emac0 ------ RGMII0_BASE @@ -520,7 +534,7 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) * Right now only 2*RGMII is supported. Please extend when needed. * sr - 2008-02-19 */ - switch (9) { + switch (mode) { case 1: /* 1 MII - 460EX */ /* GMC0 EMAC4_0, ZMII Bridge */ @@ -703,6 +717,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #ifdef CONFIG_4xx_DCACHE static u32 last_used_ea = 0; #endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ + defined(CONFIG_405EX) + int rgmii_channel; +#endif EMAC_4XX_HW_PST hw_p = dev->priv; @@ -836,10 +855,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) reg = CONFIG_PHY1_ADDR; break; #endif -#if defined (CONFIG_440GX) +#if defined (CONFIG_PHY2_ADDR) case 2: reg = CONFIG_PHY2_ADDR; break; +#endif +#if defined (CONFIG_PHY3_ADDR) case 3: reg = CONFIG_PHY3_ADDR; break; @@ -1006,12 +1027,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ defined(CONFIG_405EX) + if (devnum >= 2) + rgmii_channel = devnum - 2; + else + rgmii_channel = devnum; + if (speed == 1000) - reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); + reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V(rgmii_channel)); else if (speed == 100) - reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum)); + reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V(rgmii_channel)); else if (speed == 10) - reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum)); + reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V(rgmii_channel)); else { printf("Error in RGMII Speed\n"); return -1; @@ -1131,7 +1157,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #endif #if defined(CONFIG_460EX) || defined(CONFIG_460GT) - mtdcr (malrxctp8r, hw_p->rx); + mtdcr (malrxctp8r, hw_p->rx_phys); /* set RX buffer size */ mtdcr (malrcbs8, ENET_MAX_MTU_ALIGNED / 16); #else @@ -1160,6 +1186,26 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16); break; #endif /* CONFIG_440GX */ +#if defined (CONFIG_460GT) + case 2: + /* setup MAL tx & rx channel pointers */ + mtdcr (maltxbattr, 0x0); + mtdcr (malrxbattr, 0x0); + mtdcr (maltxctp2r, hw_p->tx_phys); + mtdcr (malrxctp16r, hw_p->rx_phys); + /* set RX buffer size */ + mtdcr (malrcbs16, ENET_MAX_MTU_ALIGNED / 16); + break; + case 3: + /* setup MAL tx & rx channel pointers */ + mtdcr (maltxbattr, 0x0); + mtdcr (malrxbattr, 0x0); + mtdcr (maltxctp3r, hw_p->tx_phys); + mtdcr (malrxctp24r, hw_p->rx_phys); + /* set RX buffer size */ + mtdcr (malrcbs24, ENET_MAX_MTU_ALIGNED / 16); + break; +#endif /* CONFIG_460GT */ case 0: default: /* setup MAL tx & rx channel pointers */ @@ -1866,14 +1912,22 @@ int ppc_4xx_eth_initialize (bd_t * bis) case 2: memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START], bis->bi_enet2addr, 6); +#if defined(CONFIG_460GT) + hw_addr[eth_num] = 0x300; +#else hw_addr[eth_num] = 0x400; +#endif break; #endif #ifdef CONFIG_HAS_ETH3 case 3: memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START], bis->bi_enet3addr, 6); +#if defined(CONFIG_460GT) + hw_addr[eth_num] = 0x400; +#else hw_addr[eth_num] = 0x600; +#endif break; #endif } diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index 5d15e2f..42eabfe 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -99,10 +99,107 @@ DECLARE_GLOBAL_DATA_PTR; # endif #endif /* CFG_INIT_DCACHE_CS */ +#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... * - * Set up the memory map, + * Reconfigure PLL if necessary, + * set up the memory map, * initialize a bunch of registers */ void @@ -111,6 +208,7 @@ 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) /* @@ -135,6 +233,7 @@ cpu_init_f (void) #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) /* @@ -147,7 +246,6 @@ cpu_init_f (void) */ mtdcr(cpc0_pci, mfdcr(cpc0_pci) | CPC0_PCI_HOST_CFG_EN | CPC0_PCI_ARBIT_EN); #endif /* CONFIG_405EP */ -#endif /* CONFIG_405EP */ #if defined(CFG_4xx_GPIO_TABLE) gpio_set_chip_configuration(); diff --git a/cpu/ppc4xx/denali_spd_ddr2.c b/cpu/ppc4xx/denali_spd_ddr2.c index 60f89c9..e20c9eb 100644 --- a/cpu/ppc4xx/denali_spd_ddr2.c +++ b/cpu/ppc4xx/denali_spd_ddr2.c @@ -1093,10 +1093,10 @@ long int initdram(int board_type) program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); - /*------------------------------------------------------------------ + /* * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia - * board SDRAM, but may be overly concervate. - *-----------------------------------------------------------------*/ + * board SDRAM, but may be overly conservative. + */ mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | DDR0_07_TFAW_ENCODE(13) | DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | @@ -1181,26 +1181,29 @@ long int initdram(int board_type) denali_wait_for_dlllock(); #if defined(CONFIG_DDR_DATA_EYE) - /* -----------------------------------------------------------+ - * Perform data eye search if requested. - * ----------------------------------------------------------*/ - program_tlb(0, CFG_SDRAM_BASE, dram_size, TLB_WORD2_I_ENABLE); + /* + * Map the first 1 MiB of memory in the TLB, and perform the data eye + * search. + */ + program_tlb(0, CFG_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE); denali_core_search_data_eye(); denali_sdram_register_dump(); - remove_tlb(CFG_SDRAM_BASE, dram_size); + remove_tlb(CFG_SDRAM_BASE, TLB_1MB_SIZE); #endif #if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) program_tlb(0, CFG_SDRAM_BASE, dram_size, 0); sync(); - eieio(); /* Zero the memory */ debug("Zeroing SDRAM..."); - dcbz_area(CFG_SDRAM_BASE, dram_size); +#if defined(CFG_MEM_TOP_HIDE) + dcbz_area(CFG_SDRAM_BASE, dram_size - CFG_MEM_TOP_HIDE); +#else +#error Please define CFG_MEM_TOP_HIDE (see README) in your board config file +#endif dflush(); debug("Completed\n"); sync(); - eieio(); remove_tlb(CFG_SDRAM_BASE, dram_size); #if defined(CONFIG_DDR_ECC) @@ -1211,7 +1214,6 @@ long int initdram(int board_type) u32 val; sync(); - eieio(); /* Clear error status */ mfsdram(DDR0_00, val); mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); @@ -1229,7 +1231,6 @@ long int initdram(int board_type) print_mcsr(); #endif sync(); - eieio(); } #endif /* defined(CONFIG_DDR_ECC) */ #endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 698bcb5..8620e2b 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -218,15 +218,16 @@ static void uic_interrupt(u32 uic_base, int vec_base) } else { set_dcr(uic_base + UIC_ER, get_dcr(uic_base + UIC_ER) & - ~(0x80000000 >> vec)); + ~(0x80000000 >> (vec & 0x1f))); printf("Masking bogus interrupt vector %d" " (UIC_BASE=0x%x)\n", vec, uic_base); } /* - * After servicing the interrupt, we have to remove the status indicator. + * After servicing the interrupt, we have to remove the + * status indicator */ - set_dcr(uic_base + UIC_SR, (0x80000000 >> vec)); + set_dcr(uic_base + UIC_SR, (0x80000000 >> (vec & 0x1f))); } /* |