diff options
Diffstat (limited to 'cpu')
65 files changed, 4513 insertions, 2507 deletions
diff --git a/cpu/ixp/npe/npe.c b/cpu/ixp/npe/npe.c index 7e4af44..a33b956 100644 --- a/cpu/ixp/npe/npe.c +++ b/cpu/ixp/npe/npe.c @@ -408,25 +408,25 @@ static int npe_init(struct eth_device *dev, bd_t * bis) if (ixEthAccPortRxCallbackRegister(p_npe->eth_id, npe_rx_callback, (u32)p_npe) != IX_ETH_ACC_SUCCESS) { printf("can't register RX callback!\n"); - return 0; + return -1; } if (ixEthAccPortTxDoneCallbackRegister(p_npe->eth_id, npe_tx_callback, (u32)p_npe) != IX_ETH_ACC_SUCCESS) { printf("can't register TX callback!\n"); - return 0; + return -1; } npe_set_mac_address(dev); if (ixEthAccPortEnable(p_npe->eth_id) != IX_ETH_ACC_SUCCESS) { printf("can't enable port!\n"); - return 0; + return -1; } p_npe->active = 1; - return 1; + return 0; } #if 0 /* test-only: probably have to deal with it when booting linux (for a clean state) */ diff --git a/cpu/ixp/serial.c b/cpu/ixp/serial.c index 2015958..cf520b6 100644 --- a/cpu/ixp/serial.c +++ b/cpu/ixp/serial.c @@ -31,6 +31,13 @@ #include <common.h> #include <asm/arch/ixp425.h> +/* + * 14.7456 MHz + * Baud Rate = -------------- + * 16 x Divisor + */ +#define SERIAL_CLOCK 921600 + DECLARE_GLOBAL_DATA_PTR; void serial_setbrg (void) @@ -38,18 +45,8 @@ void serial_setbrg (void) unsigned int quot = 0; int uart = CFG_IXP425_CONSOLE; - if (gd->baudrate == 1200) - quot = 192; - else if (gd->baudrate == 9600) - quot = 96; - else if (gd->baudrate == 19200) - quot = 48; - else if (gd->baudrate == 38400) - quot = 24; - else if (gd->baudrate == 57600) - quot = 16; - else if (gd->baudrate == 115200) - quot = 8; + if ((gd->baudrate <= SERIAL_CLOCK) && (SERIAL_CLOCK % gd->baudrate == 0)) + quot = SERIAL_CLOCK / gd->baudrate; else hang (); @@ -65,7 +62,6 @@ void serial_setbrg (void) IER(uart) = IER_UUE; } - /* * Initialise the serial port with the given baudrate. The settings * are always 8 data bits, no parity, 1 stop bit, no start bits. diff --git a/cpu/mpc512x/cpu.c b/cpu/mpc512x/cpu.c index accae6e..6421a51 100644 --- a/cpu/mpc512x/cpu.c +++ b/cpu/mpc512x/cpu.c @@ -32,6 +32,10 @@ #include <mpc512x.h> #include <asm/processor.h> +#if defined(CONFIG_OF_LIBFDT) +#include <fdt_support.h> +#endif + DECLARE_GLOBAL_DATA_PTR; int checkcpu (void) @@ -125,3 +129,20 @@ void watchdog_reset (void) enable_interrupts (); } #endif + +#ifdef CONFIG_OF_LIBFDT +void ft_cpu_setup(void *blob, bd_t *bd) +{ + char * cpu_path = "/cpus/" OF_CPU; + char * eth_path = "/" OF_SOC "/ethernet@2800"; + + do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1); + do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1); + do_fixup_by_path_u32(blob, cpu_path, "ref-frequency", CFG_MPC512X_CLKIN, 1); + do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1); + do_fixup_by_path_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipsfreq, 1); + do_fixup_by_path_u32(blob, "/" OF_SOC, "ref-frequency", CFG_MPC512X_CLKIN, 1); + do_fixup_by_path(blob, eth_path, "address", bd->bi_enetaddr, 6, 0); + do_fixup_by_path(blob, eth_path, "local-mac-address", bd->bi_enetaddr, 6, 0); +} +#endif diff --git a/cpu/mpc512x/fec.c b/cpu/mpc512x/fec.c index 675b7a2..c226a8a 100644 --- a/cpu/mpc512x/fec.c +++ b/cpu/mpc512x/fec.c @@ -299,7 +299,7 @@ int mpc512x_fec_init_phy (struct eth_device *dev, bd_t * bis) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */ - fec->eth->mii_speed = (((gd->ipb_clk / 1000000) / 5) + 1) << 1; + fec->eth->mii_speed = (((gd->ips_clk / 1000000) / 5) + 1) << 1; /* * Reset PHY, then delay 300ns diff --git a/cpu/mpc512x/i2c.c b/cpu/mpc512x/i2c.c index 00e28d6..56ba443 100644 --- a/cpu/mpc512x/i2c.c +++ b/cpu/mpc512x/i2c.c @@ -236,7 +236,7 @@ static int mpc_get_fdr (int speed) if (fdr == -1) { ulong best_speed = 0; ulong divider; - ulong ipb, scl; + ulong ips, scl; ulong bestmatch = 0xffffffffUL; int best_i = 0, best_j = 0, i, j; int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8}; @@ -251,18 +251,18 @@ static int mpc_get_fdr (int speed) {126, 128} }; - ipb = gd->ipb_clk; + ips = gd->ips_clk; for (i = 7; i >= 0; i--) { for (j = 7; j >= 0; j--) { scl = 2 * (scltap[j].scl2tap + (SCL_Tap[i] - 1) * scltap[j].tap2tap + 2); - if (ipb <= speed*scl) { - if ((speed*scl - ipb) < bestmatch) { - bestmatch = speed*scl - ipb; + if (ips <= speed*scl) { + if ((speed*scl - ips) < bestmatch) { + bestmatch = speed*scl - ips; best_i = i; best_j = j; - best_speed = ipb/scl; + best_speed = ips/scl; } } } diff --git a/cpu/mpc512x/serial.c b/cpu/mpc512x/serial.c index 200ff2c..8a21404 100644 --- a/cpu/mpc512x/serial.c +++ b/cpu/mpc512x/serial.c @@ -86,7 +86,7 @@ int serial_init(void) psc->mode = PSC_MODE_1_STOPBIT; /* calculate dividor for setting PSC CTUR and CTLR registers */ - baseclk = (gd->ipb_clk + 8) / 16; + baseclk = (gd->ips_clk + 8) / 16; div = (baseclk + (gd->baudrate / 2)) / gd->baudrate; psc->ctur = (div >> 8) & 0xff; diff --git a/cpu/mpc512x/speed.c b/cpu/mpc512x/speed.c index a609827..99e3495 100644 --- a/cpu/mpc512x/speed.c +++ b/cpu/mpc512x/speed.c @@ -96,7 +96,7 @@ int get_clocks (void) ips_clk = 0; } - gd->ipb_clk = ips_clk; + gd->ips_clk = ips_clk; gd->csb_clk = csb_clk; gd->cpu_clk = core_clk; gd->bus_clk = csb_clk; @@ -118,7 +118,7 @@ int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) printf ("Clock configuration:\n"); printf (" CPU: %4d MHz\n", gd->cpu_clk / 1000000); printf (" Coherent System Bus: %4d MHz\n", gd->csb_clk / 1000000); - printf (" IPS Bus: %4d MHz\n", gd->ipb_clk / 1000000); + printf (" IPS Bus: %4d MHz\n", gd->ips_clk / 1000000); printf (" DDR: %4d MHz\n", 2 * gd->csb_clk / 1000000); return 0; } diff --git a/cpu/mpc5xx/u-boot.lds b/cpu/mpc5xx/u-boot.lds index 5b03fef..ca1de95 100644 --- a/cpu/mpc5xx/u-boot.lds +++ b/cpu/mpc5xx/u-boot.lds @@ -121,7 +121,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c index 1d3da77..2aded1a 100644 --- a/cpu/mpc5xxx/fec.c +++ b/cpu/mpc5xxx/fec.c @@ -288,13 +288,13 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */ - fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); /* No MII for 7-wire mode */ + fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); /* No MII for 7-wire mode */ } /* * Set Opcode/Pause Duration Register */ - fec->eth->op_pause = 0x00010020; /*FIXME0xffff0020; */ + fec->eth->op_pause = 0x00010020; /*FIXME 0xffff0020; */ /* * Set Rx FIFO alarm and granularity value @@ -902,7 +902,8 @@ int mpc5xxx_fec_initialize(bd_t * bis) defined(CONFIG_TOP5200) || \ defined(CONFIG_TQM5200) || \ defined(CONFIG_UC101) || \ - defined(CONFIG_V38B) + defined(CONFIG_V38B) || \ + defined(CONFIG_MUNICES) # ifndef CONFIG_FEC_10MBIT fec->xcv_type = MII100; # else diff --git a/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S b/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S index 1d83fe2..a07c776 100644 --- a/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S +++ b/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S @@ -23,7 +23,7 @@ scEthernetRecv_Entry: /* Task 0 */ .long 0x00000000 .long 0x00000000 .long scEthernetRecv_CSave - taskTable /* Task 0 context save space */ -.long 0xf0000000 +.long CFG_MBAR .globl scEthernetXmit_Entry scEthernetXmit_Entry: /* Task 1 */ .long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */ @@ -33,7 +33,7 @@ scEthernetXmit_Entry: /* Task 1 */ .long 0x00000000 .long 0x00000000 .long scEthernetXmit_CSave - taskTable /* Task 1 context save space */ -.long 0xf0000000 +.long CFG_MBAR .globl scEthernetRecv_TDT @@ -151,7 +151,7 @@ scEthernetRecv_VarTab: /* Task 0 Variable Table */ .long 0x00000000 /* var[6] */ .long 0x00000000 /* var[7] */ .long 0x00000000 /* var[8] */ -.long 0xf0008800 /* var[9] */ +.long (CFG_MBAR + 0x8800) /* var[9] */ .long 0x00000008 /* var[10] */ .long 0x0000000c /* var[11] */ .long 0x80000000 /* var[12] */ @@ -190,7 +190,7 @@ scEthernetXmit_VarTab: /* Task 1 Variable Table */ .long 0x00000000 /* var[8] */ .long 0x00000000 /* var[9] */ .long 0x00000000 /* var[10] */ -.long 0xf0008800 /* var[11] */ +.long (CFG_MBAR + 0x8800) /* var[11] */ .long 0x00000000 /* var[12] */ .long 0x80000000 /* var[13] */ .long 0x10000000 /* var[14] */ diff --git a/cpu/mpc5xxx/u-boot-customlayout.lds b/cpu/mpc5xxx/u-boot-customlayout.lds index 123a14c..4e10ddb 100644 --- a/cpu/mpc5xxx/u-boot-customlayout.lds +++ b/cpu/mpc5xxx/u-boot-customlayout.lds @@ -124,7 +124,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc5xxx/u-boot.lds b/cpu/mpc5xxx/u-boot.lds index 78818a4..bb2747b 100644 --- a/cpu/mpc5xxx/u-boot.lds +++ b/cpu/mpc5xxx/u-boot.lds @@ -113,7 +113,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc8220/u-boot.lds b/cpu/mpc8220/u-boot.lds index 889bc77..98b0a79 100644 --- a/cpu/mpc8220/u-boot.lds +++ b/cpu/mpc8220/u-boot.lds @@ -113,7 +113,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc824x/u-boot.lds b/cpu/mpc824x/u-boot.lds index c90d1e9..036e61b 100644 --- a/cpu/mpc824x/u-boot.lds +++ b/cpu/mpc824x/u-boot.lds @@ -113,7 +113,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc8260/ether_scc.c b/cpu/mpc8260/ether_scc.c index e56839d..633d053 100644 --- a/cpu/mpc8260/ether_scc.c +++ b/cpu/mpc8260/ether_scc.c @@ -77,7 +77,9 @@ #define TX_BUF_CNT 2 -#define TOUT_LOOP 1000000 +#if !defined(CFG_SCC_TOUT_LOOP) + #define CFG_SCC_TOUT_LOOP 1000000 +#endif static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ]; @@ -109,7 +111,7 @@ int eth_send(volatile void *packet, int length) } for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { + if (i >= CFG_SCC_TOUT_LOOP) { puts ("scc: tx buffer not ready\n"); goto out; } @@ -121,7 +123,7 @@ int eth_send(volatile void *packet, int length) BD_ENET_TX_WRAP); for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) { - if (i >= TOUT_LOOP) { + if (i >= CFG_SCC_TOUT_LOOP) { puts ("scc: tx error\n"); goto out; } @@ -262,7 +264,6 @@ int eth_init(bd_t *bis) pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */ pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */ - /* 24.21 - (19): Initialize RxBD */ for (i = 0; i < PKTBUFSRX; i++) { diff --git a/cpu/mpc8260/u-boot.lds b/cpu/mpc8260/u-boot.lds index 3e84f23..8384549 100644 --- a/cpu/mpc8260/u-boot.lds +++ b/cpu/mpc8260/u-boot.lds @@ -113,7 +113,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile index 2329970..94a3cb8 100644 --- a/cpu/mpc83xx/Makefile +++ b/cpu/mpc83xx/Makefile @@ -29,7 +29,7 @@ LIB = $(obj)lib$(CPU).a START = start.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \ - spd_sdram.o ecc.o qe_io.o pci.o + spd_sdram.o ecc.o qe_io.o pci.o fdt.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index f1ea17d..bff3cef 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -31,12 +31,7 @@ #include <command.h> #include <mpc83xx.h> #include <asm/processor.h> -#if defined(CONFIG_OF_FLAT_TREE) -#include <ft_build.h> -#elif defined(CONFIG_OF_LIBFDT) #include <libfdt.h> -#include <fdt_support.h> -#endif DECLARE_GLOBAL_DATA_PTR; @@ -65,6 +60,10 @@ int checkcpu(void) printf("e300c3, "); break; + case PVR_E300C4: + printf("e300c4, "); + break; + default: printf("Unknown core, "); } @@ -149,6 +148,36 @@ int checkcpu(void) case SPR_8313E_REV10: puts("MPC8313E, "); break; + case SPR_8315E_REV10: + puts("MPC8315E, "); + break; + case SPR_8315_REV10: + puts("MPC8315, "); + break; + case SPR_8314E_REV10: + puts("MPC8314E, "); + break; + case SPR_8314_REV10: + puts("MPC8314, "); + break; + case SPR_8379E_REV10: + puts("MPC8379E, "); + break; + case SPR_8379_REV10: + puts("MPC8379, "); + break; + case SPR_8378E_REV10: + puts("MPC8378E, "); + break; + case SPR_8378_REV10: + puts("MPC8378, "); + break; + case SPR_8377E_REV10: + puts("MPC8377E, "); + break; + case SPR_8377_REV10: + puts("MPC8377, "); + break; default: printf("Rev: Unknown revision number:%08x\n" "Warning: Unsupported cpu revision!\n",spridr); @@ -325,313 +354,6 @@ void watchdog_reset (void) } #endif -#if defined(CONFIG_OF_LIBFDT) - -/* - * "Setter" functions used to add/modify FDT entries. - */ -static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - /* Fix it up if it exists, don't create it if it doesn't exist */ - if (fdt_get_property(blob, nodeoffset, name, 0)) { - return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6); - } - return 0; -} -#ifdef CONFIG_HAS_ETH1 -/* second onboard ethernet port */ -static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - /* Fix it up if it exists, don't create it if it doesn't exist */ - if (fdt_get_property(blob, nodeoffset, name, 0)) { - return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6); - } - return 0; -} -#endif -#ifdef CONFIG_HAS_ETH2 -/* third onboard ethernet port */ -static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - /* Fix it up if it exists, don't create it if it doesn't exist */ - if (fdt_get_property(blob, nodeoffset, name, 0)) { - return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6); - } - return 0; -} -#endif -#ifdef CONFIG_HAS_ETH3 -/* fourth onboard ethernet port */ -static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - /* Fix it up if it exists, don't create it if it doesn't exist */ - if (fdt_get_property(blob, nodeoffset, name, 0)) { - return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6); - } - return 0; -} -#endif - -static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - u32 tmp; - /* Create or update the property */ - tmp = cpu_to_be32(bd->bi_busfreq); - return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); -} - -static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - u32 tmp; - /* Create or update the property */ - tmp = cpu_to_be32(OF_TBCLK); - return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); -} - - -static int fdt_set_clockfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - u32 tmp; - /* Create or update the property */ - tmp = cpu_to_be32(gd->core_clk); - return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); -} - -#ifdef CONFIG_QE -static int fdt_set_qe_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - u32 tmp; - /* Create or update the property */ - tmp = cpu_to_be32(gd->qe_clk); - return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); -} - -static int fdt_set_qe_brgfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) -{ - u32 tmp; - /* Create or update the property */ - tmp = cpu_to_be32(gd->brg_clk); - return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); -} -#endif - -/* - * Fixups to the fdt. - */ -static const struct { - char *node; - char *prop; - int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd); -} fixup_props[] = { - { "/cpus/" OF_CPU, - "timebase-frequency", - fdt_set_tbfreq - }, - { "/cpus/" OF_CPU, - "bus-frequency", - fdt_set_busfreq - }, - { "/cpus/" OF_CPU, - "clock-frequency", - fdt_set_clockfreq - }, - { "/" OF_SOC, - "bus-frequency", - fdt_set_busfreq - }, - { "/" OF_SOC "/serial@4500", - "clock-frequency", - fdt_set_busfreq - }, - { "/" OF_SOC "/serial@4600", - "clock-frequency", - fdt_set_busfreq - }, -#ifdef CONFIG_TSEC1 - { "/" OF_SOC "/ethernet@24000", - "mac-address", - fdt_set_eth0 - }, - { "/" OF_SOC "/ethernet@24000", - "local-mac-address", - fdt_set_eth0 - }, -#endif -#ifdef CONFIG_TSEC2 - { "/" OF_SOC "/ethernet@25000", - "mac-address", - fdt_set_eth1 - }, - { "/" OF_SOC "/ethernet@25000", - "local-mac-address", - fdt_set_eth1 - }, -#endif -#ifdef CONFIG_QE - { "/" OF_QE, - "brg-frequency", - fdt_set_qe_brgfreq - }, - { "/" OF_QE, - "bus-frequency", - fdt_set_qe_busfreq - }, -#ifdef CONFIG_UEC_ETH1 -#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ - { "/" OF_QE "/ucc@2000", - "mac-address", - fdt_set_eth0 - }, - { "/" OF_QE "/ucc@2000", - "local-mac-address", - fdt_set_eth0 - }, -#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ - { "/" OF_QE "/ucc@2200", - "mac-address", - fdt_set_eth0 - }, - { "/" OF_QE "/ucc@2200", - "local-mac-address", - fdt_set_eth0 - }, -#endif -#endif /* CONFIG_UEC_ETH1 */ -#ifdef CONFIG_UEC_ETH2 -#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ - { "/" OF_QE "/ucc@3000", - "mac-address", - fdt_set_eth1 - }, - { "/" OF_QE "/ucc@3000", - "local-mac-address", - fdt_set_eth1 - }, -#elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */ - { "/" OF_QE "/ucc@3200", - "mac-address", - fdt_set_eth1 - }, - { "/" OF_QE "/ucc@3200", - "local-mac-address", - fdt_set_eth1 - }, -#endif -#endif /* CONFIG_UEC_ETH2 */ -#endif /* CONFIG_QE */ -}; - -void -ft_cpu_setup(void *blob, bd_t *bd) -{ - int nodeoffset; - int err; - int j; - - for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { - nodeoffset = fdt_path_offset(blob, fixup_props[j].node); - if (nodeoffset >= 0) { - err = fixup_props[j].set_fn(blob, nodeoffset, - fixup_props[j].prop, bd); - if (err < 0) - debug("Problem setting %s = %s: %s\n", - fixup_props[j].node, fixup_props[j].prop, - fdt_strerror(err)); - } else { - debug("Couldn't find %s: %s\n", - fixup_props[j].node, fdt_strerror(nodeoffset)); - } - } - - fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); -} -#elif defined(CONFIG_OF_FLAT_TREE) -void -ft_cpu_setup(void *blob, bd_t *bd) -{ - u32 *p; - int len; - ulong clock; - - clock = bd->bi_busfreq; - p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); - - p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); - - p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); - - p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); - -#ifdef CONFIG_TSEC1 - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); - - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); -#endif - -#ifdef CONFIG_TSEC2 - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); - - p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); -#endif - -#ifdef CONFIG_UEC_ETH1 -#if CFG_UEC1_UCC_NUM == 0 /* UCC1 */ - p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); - - p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); -#elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */ - p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); - - p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enetaddr, 6); -#endif -#endif - -#ifdef CONFIG_UEC_ETH2 -#if CFG_UEC2_UCC_NUM == 1 /* UCC2 */ - p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); - - p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); -#elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */ - p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); - - p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len); - if (p != NULL) - memcpy(p, bd->bi_enet1addr, 6); -#endif -#endif -} -#endif - #if defined(CONFIG_DDR_ECC) void dma_init(void) { diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 7224979..2b92be0 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -155,6 +155,10 @@ void cpu_init_f (volatile immap_t * im) #ifdef CFG_DDRCDR im->sysconf.ddrcdr = CFG_DDRCDR; #endif + /* Output buffer impedance register */ +#ifdef CFG_OBIR + im->sysconf.obir = CFG_OBIR; +#endif #ifdef CONFIG_QE /* Config QE ioports */ diff --git a/cpu/mpc83xx/fdt.c b/cpu/mpc83xx/fdt.c new file mode 100644 index 0000000..909171f --- /dev/null +++ b/cpu/mpc83xx/fdt.c @@ -0,0 +1,78 @@ +/* + * Copyright 2007 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * 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> + +#if defined(CONFIG_OF_LIBFDT) + +#include <libfdt.h> +#include <fdt_support.h> + +DECLARE_GLOBAL_DATA_PTR; + +void ft_cpu_setup(void *blob, bd_t *bd) +{ +#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\ + defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) + fdt_fixup_ethernet(blob, bd); +#endif + + do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, + "timebase-frequency", (bd->bi_busfreq / 4), 1); + do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, + "bus-frequency", bd->bi_busfreq, 1); + do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, + "clock-frequency", gd->core_clk, 1); + do_fixup_by_prop_u32(blob, "device_type", "soc", 4, + "bus-frequency", bd->bi_busfreq, 1); +#ifdef CONFIG_QE + do_fixup_by_prop_u32(blob, "device_type", "qe", 4, + "bus-frequency", gd->qe_clk, 1); + do_fixup_by_prop_u32(blob, "device_type", "qe", 4, + "brg-frequency", gd->brg_clk, 1); + do_fixup_by_compat_u32(blob, "fsl,qe", + "clock-frequency", gd->qe_clk, 1); + do_fixup_by_compat_u32(blob, "fsl,qe", + "bus-frequency", gd->qe_clk, 1); + do_fixup_by_compat_u32(blob, "fsl,qe", + "brg-frequency", gd->brg_clk, 1); +#endif + +#ifdef CFG_NS16550 + do_fixup_by_compat_u32(blob, "ns16550", + "clock-frequency", bd->bi_busfreq, 1); +#endif + +#ifdef CONFIG_CPM2 + do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart", + "current-speed", bd->bi_baudrate, 1); + + do_fixup_by_compat_u32(blob, "fsl,cpm2-brg", + "clock-frequency", bd->bi_brgfreq, 1); +#endif + + fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); +} +#endif /* CONFIG_OF_LIBFDT */ diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index 0defb0e..18558db 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -28,8 +28,7 @@ #if defined(CONFIG_OF_LIBFDT) #include <libfdt.h> -#elif defined(CONFIG_OF_FLAT_TREE) -#include <ft_build.h> +#include <fdt_support.h> #endif #include <asm/mpc8349_pci.h> @@ -173,63 +172,41 @@ void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot) void ft_pci_setup(void *blob, bd_t *bd) { int nodeoffset; - int err; int tmp[2]; + const char *path; if (pci_num_buses < 1) return; - nodeoffset = fdt_path_offset(blob, "/" OF_SOC "/pci@8500"); + nodeoffset = fdt_path_offset(blob, "/aliases"); if (nodeoffset >= 0) { - tmp[0] = cpu_to_be32(pci_hose[0].first_busno); - tmp[1] = cpu_to_be32(pci_hose[0].last_busno); - err = fdt_setprop(blob, nodeoffset, "bus-range", - tmp, sizeof(tmp)); - - tmp[0] = cpu_to_be32(gd->pci_clk); - err = fdt_setprop(blob, nodeoffset, "clock-frequency", - tmp, sizeof(tmp[0])); - } - - if (pci_num_buses < 2) - return; - - nodeoffset = fdt_path_offset(blob, "/" OF_SOC "/pci@8600"); - if (nodeoffset >= 0) { - tmp[0] = cpu_to_be32(pci_hose[0].first_busno); - tmp[1] = cpu_to_be32(pci_hose[0].last_busno); - err = fdt_setprop(blob, nodeoffset, "bus-range", - tmp, sizeof(tmp)); - - tmp[0] = cpu_to_be32(gd->pci_clk); - err = fdt_setprop(blob, nodeoffset, "clock-frequency", - tmp, sizeof(tmp[0])); - } -} -#elif CONFIG_OF_FLAT_TREE -void ft_pci_setup(void *blob, bd_t *bd) -{ - u32 *p; - int len; - - if (pci_num_buses < 1) - return; - - p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); - if (p) { - p[0] = pci_hose[0].first_busno; - p[1] = pci_hose[0].last_busno; - } - - if (pci_num_buses < 2) - return; - - p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8600/bus-range", &len); - if (p) { - p[0] = pci_hose[1].first_busno; - p[1] = pci_hose[1].last_busno; + path = fdt_getprop(blob, nodeoffset, "pci0", NULL); + if (path) { + tmp[0] = cpu_to_be32(pci_hose[0].first_busno); + tmp[1] = cpu_to_be32(pci_hose[0].last_busno); + do_fixup_by_path(blob, path, "bus-range", + &tmp, sizeof(tmp), 1); + + tmp[0] = cpu_to_be32(gd->pci_clk); + do_fixup_by_path(blob, path, "clock-frequency", + &tmp, sizeof(tmp[0]), 1); + } + + if (pci_num_buses < 2) + return; + + path = fdt_getprop(blob, nodeoffset, "pci1", NULL); + if (path) { + tmp[0] = cpu_to_be32(pci_hose[0].first_busno); + tmp[1] = cpu_to_be32(pci_hose[0].last_busno); + do_fixup_by_path(blob, path, "bus-range", + &tmp, sizeof(tmp), 1); + + tmp[0] = cpu_to_be32(gd->pci_clk); + do_fixup_by_path(blob, path, "clock-frequency", + &tmp, sizeof(tmp[0]), 1); + } } } -#endif /* CONFIG_OF_FLAT_TREE */ - +#endif /* CONFIG_OF_LIBFDT */ #endif /* CONFIG_83XX_GENERIC_PCI */ diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index ee2d038..0acca47 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2006 Freescale Semiconductor, Inc. + * (C) Copyright 2006-2007 Freescale Semiconductor, Inc. * * (C) Copyright 2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -198,6 +198,7 @@ long int spd_sdram() if(spd.mem_type == SPD_MEMTYPE_DDR2) { immap->sysconf.ddrcdr = CFG_DDRCDR_VALUE; } + udelay(50000); #endif /* @@ -573,10 +574,10 @@ long int spd_sdram() */ cpo = 0; if (spd.mem_type == SPD_MEMTYPE_DDR2) { - if (effective_data_rate == 266 || effective_data_rate == 333) { + if (effective_data_rate == 266) { + cpo = 0x4; /* READ_LAT + 1/2 */ + } else if (effective_data_rate == 333 || effective_data_rate == 400) { cpo = 0x7; /* READ_LAT + 5/4 */ - } else if (effective_data_rate == 400) { - cpo = 0x9; /* READ_LAT + 7/4 */ } else { /* Automatic calibration */ cpo = 0x1f; @@ -705,9 +706,11 @@ long int spd_sdram() * SDRAM Cfg 2 */ odt_cfg = 0; +#ifndef CONFIG_NEVER_ASSERT_ODT_TO_CPU if (odt_rd_cfg | odt_wr_cfg) { odt_cfg = 0x2; /* ODT to IOs during reads */ } +#endif if (spd.mem_type == SPD_MEMTYPE_DDR2) { ddr->sdram_cfg2 = (0 | (0 << 26) /* True DQS */ diff --git a/cpu/mpc83xx/speed.c b/cpu/mpc83xx/speed.c index cba57fa..4f5a866 100644 --- a/cpu/mpc83xx/speed.c +++ b/cpu/mpc83xx/speed.c @@ -2,7 +2,7 @@ * (C) Copyright 2000-2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * Copyright (C) 2004-2006 Freescale Semiconductor, Inc. + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -100,7 +100,7 @@ int get_clocks(void) u32 lcrr; u32 csb_clk; -#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) +#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) || defined(CONFIG_MPC837X) u32 tsec1_clk; u32 tsec2_clk; u32 usbdr_clk; @@ -113,6 +113,12 @@ int get_clocks(void) #if !defined(CONFIG_MPC832X) u32 i2c2_clk; #endif +#if defined(CONFIG_MPC8315) + u32 tdm_clk; +#endif +#if defined(CONFIG_MPC837X) + u32 sdhc_clk; +#endif u32 enc_clk; u32 lbiu_clk; u32 lclk_clk; @@ -126,6 +132,13 @@ int get_clocks(void) u32 qe_clk; u32 brg_clk; #endif +#if defined(CONFIG_MPC837X) + u32 pciexp1_clk; + u32 pciexp2_clk; +#endif +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) + u32 sata_clk; +#endif if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) return -1; @@ -151,7 +164,7 @@ int get_clocks(void) sccr = im->clk.sccr; -#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) +#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) || defined(CONFIG_MPC837X) switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) { case 0: tsec1_clk = 0; @@ -167,7 +180,7 @@ int get_clocks(void) break; default: /* unkown SCCR_TSEC1CM value */ - return -4; + return -2; } switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) { @@ -185,11 +198,11 @@ int get_clocks(void) break; default: /* unkown SCCR_USBDRCM value */ - return -8; + return -3; } #endif -#if defined(CONFIG_MPC834X) +#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) { case 0: tsec2_clk = 0; @@ -205,11 +218,18 @@ int get_clocks(void) break; default: /* unkown SCCR_TSEC2CM value */ - return -5; + return -4; } +#elif defined(CONFIG_MPC8313) + tsec2_clk = tsec1_clk; - i2c1_clk = tsec2_clk; + if (!(sccr & SCCR_TSEC1ON)) + tsec1_clk = 0; + if (!(sccr & SCCR_TSEC2ON)) + tsec2_clk = 0; +#endif +#if defined(CONFIG_MPC834X) switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) { case 0: usbmph_clk = 0; @@ -225,7 +245,7 @@ int get_clocks(void) break; default: /* unkown SCCR_USBMPHCM value */ - return -7; + return -5; } if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) { @@ -233,41 +253,138 @@ int get_clocks(void) * USB DR clock is not disabled then * USB MPH & USB DR must have the same rate */ - return -9; + return -6; + } +#endif + switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) { + case 0: + enc_clk = 0; + break; + case 1: + enc_clk = csb_clk; + break; + case 2: + enc_clk = csb_clk / 2; + break; + case 3: + enc_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_ENCCM value */ + return -7; } -#elif defined(CONFIG_MPC831X) - tsec2_clk = tsec1_clk; - if (!(sccr & SCCR_TSEC1ON)) - tsec1_clk = 0; - if (!(sccr & SCCR_TSEC2ON)) - tsec2_clk = 0; +#if defined(CONFIG_MPC837X) + switch ((sccr & SCCR_SDHCCM) >> SCCR_SDHCCM_SHIFT) { + case 0: + sdhc_clk = 0; + break; + case 1: + sdhc_clk = csb_clk; + break; + case 2: + sdhc_clk = csb_clk / 2; + break; + case 3: + sdhc_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_SDHCCM value */ + return -8; + } +#endif +#if defined(CONFIG_MPC8315) + switch ((sccr & SCCR_TDMCM) >> SCCR_TDMCM_SHIFT) { + case 0: + tdm_clk = 0; + break; + case 1: + tdm_clk = csb_clk; + break; + case 2: + tdm_clk = csb_clk / 2; + break; + case 3: + tdm_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_TDMCM value */ + return -8; + } #endif -#if !defined(CONFIG_MPC834X) +#if defined(CONFIG_MPC834X) + i2c1_clk = tsec2_clk; +#elif defined(CONFIG_MPC8360) i2c1_clk = csb_clk; +#elif defined(CONFIG_MPC832X) + i2c1_clk = enc_clk; +#elif defined(CONFIG_MPC831X) + i2c1_clk = enc_clk; +#elif defined(CONFIG_MPC837X) + i2c1_clk = sdhc_clk; #endif #if !defined(CONFIG_MPC832X) - i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */ + i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */ #endif - switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) { +#if defined(CONFIG_MPC837X) + switch ((sccr & SCCR_PCIEXP1CM) >> SCCR_PCIEXP1CM_SHIFT) { case 0: - enc_clk = 0; + pciexp1_clk = 0; break; case 1: - enc_clk = csb_clk; + pciexp1_clk = csb_clk; break; case 2: - enc_clk = csb_clk / 2; + pciexp1_clk = csb_clk / 2; break; case 3: - enc_clk = csb_clk / 3; + pciexp1_clk = csb_clk / 3; break; default: - /* unkown SCCR_ENCCM value */ - return -6; + /* unkown SCCR_PCIEXP1CM value */ + return -9; + } + + switch ((sccr & SCCR_PCIEXP2CM) >> SCCR_PCIEXP2CM_SHIFT) { + case 0: + pciexp2_clk = 0; + break; + case 1: + pciexp2_clk = csb_clk; + break; + case 2: + pciexp2_clk = csb_clk / 2; + break; + case 3: + pciexp2_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_PCIEXP2CM value */ + return -10; } +#endif + +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) + switch ((sccr & SCCR_SATA1CM) >> SCCR_SATA1CM_SHIFT) { + case 0: + sata_clk = 0; + break; + case 1: + sata_clk = csb_clk; + break; + case 2: + sata_clk = csb_clk / 2; + break; + case 3: + sata_clk = csb_clk / 3; + break; + default: + /* unkown SCCR_SATA1CM value */ + return -11; + } +#endif lbiu_clk = csb_clk * (1 + ((im->reset.rcwl & HRCWL_LBIUCM) >> HRCWL_LBIUCM_SHIFT)); @@ -280,7 +397,7 @@ int get_clocks(void) break; default: /* unknown lcrr */ - return -10; + return -12; } ddr_clk = csb_clk * @@ -316,7 +433,7 @@ int get_clocks(void) break; default: /* unkown core to csb ratio */ - return -12; + return -13; } #if defined(CONFIG_MPC8360) || defined(CONFIG_MPC832X) @@ -327,7 +444,7 @@ int get_clocks(void) #endif gd->csb_clk = csb_clk; -#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) +#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) || defined(CONFIG_MPC837X) gd->tsec1_clk = tsec1_clk; gd->tsec2_clk = tsec2_clk; gd->usbdr_clk = usbdr_clk; @@ -335,6 +452,12 @@ int get_clocks(void) #if defined(CONFIG_MPC834X) gd->usbmph_clk = usbmph_clk; #endif +#if defined(CONFIG_MPC8315) + gd->tdm_clk = tdm_clk; +#endif +#if defined(CONFIG_MPC837X) + gd->sdhc_clk = sdhc_clk; +#endif gd->core_clk = core_clk; gd->i2c1_clk = i2c1_clk; #if !defined(CONFIG_MPC832X) @@ -351,6 +474,13 @@ int get_clocks(void) gd->qe_clk = qe_clk; gd->brg_clk = brg_clk; #endif +#if defined(CONFIG_MPC837X) + gd->pciexp1_clk = pciexp1_clk; + gd->pciexp2_clk = pciexp2_clk; +#endif +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) + gd->sata_clk = sata_clk; +#endif gd->pci_clk = pci_sync_in; gd->cpu_clk = gd->core_clk; gd->bus_clk = gd->csb_clk; @@ -387,7 +517,13 @@ int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) #if !defined(CONFIG_MPC832X) printf(" I2C2: %4d MHz\n", gd->i2c2_clk / 1000000); #endif -#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) +#if defined(CONFIG_MPC8315) + printf(" TDM: %4d MHz\n", gd->tdm_clk / 1000000); +#endif +#if defined(CONFIG_MPC837X) + printf(" SDHC: %4d MHz\n", gd->sdhc_clk / 1000000); +#endif +#if defined(CONFIG_MPC834X) || defined(CONFIG_MPC831X) || defined(CONFIG_MPC837X) printf(" TSEC1: %4d MHz\n", gd->tsec1_clk / 1000000); printf(" TSEC2: %4d MHz\n", gd->tsec2_clk / 1000000); printf(" USB DR: %4d MHz\n", gd->usbdr_clk / 1000000); @@ -395,6 +531,13 @@ int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_MPC834X) printf(" USB MPH: %4d MHz\n", gd->usbmph_clk / 1000000); #endif +#if defined(CONFIG_MPC837X) + printf(" PCIEXP1: %4d MHz\n", gd->pciexp1_clk / 1000000); + printf(" PCIEXP2: %4d MHz\n", gd->pciexp2_clk / 1000000); +#endif +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC8315) + printf(" SATA: %4d MHz\n", gd->sata_clk / 1000000); +#endif return 0; } diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 496c8a5..1dfbf62 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -462,7 +462,7 @@ init_e300_core: /* time t 10 */ li r4, 0x556C sth r4, SWSRR@l(r3) - li r4, 0xAA39 + li r4, -0x55C7 sth r4, SWSRR@l(r3) #else /* Disable Wathcdog */ diff --git a/cpu/mpc83xx/u-boot.lds b/cpu/mpc83xx/u-boot.lds index 937c87a..8da6f14 100644 --- a/cpu/mpc83xx/u-boot.lds +++ b/cpu/mpc83xx/u-boot.lds @@ -110,7 +110,7 @@ SECTIONS __init_end = .; __bss_start = .; - .bss : + .bss (NOLOAD) : { *(.sbss) *(.scommon) *(.dynbss) diff --git a/cpu/mpc85xx/fdt.c b/cpu/mpc85xx/fdt.c index 737a6c4..0ce17e7 100644 --- a/cpu/mpc85xx/fdt.c +++ b/cpu/mpc85xx/fdt.c @@ -43,8 +43,11 @@ void ft_cpu_setup(void *blob, bd_t *bd) do_fixup_by_prop_u32(blob, "device_type", "soc", 4, "bus-frequency", bd->bi_busfreq, 1); #ifdef CONFIG_QE - do_fixup_by_prop_u32(blob, "device_type", "soc", 4, + do_fixup_by_prop_u32(blob, "device_type", "qe", 4, "bus-frequency", bd->bi_busfreq, 1); + do_fixup_by_prop_u32(blob, "device_type", "qe", 4, + "brg-frequency", bd->bi_busfreq / 2, 1); + fdt_fixup_qe_firmware(blob); #endif #ifdef CFG_NS16550 diff --git a/cpu/mpc85xx/spd_sdram.c b/cpu/mpc85xx/spd_sdram.c index 553f736..adc9c4d 100644 --- a/cpu/mpc85xx/spd_sdram.c +++ b/cpu/mpc85xx/spd_sdram.c @@ -1071,22 +1071,19 @@ setup_laws_and_tlbs(unsigned int memsize) ram_tlb_address = (unsigned int)CFG_DDR_SDRAM_BASE; while (ram_tlb_address < (memsize * 1024 * 1024) && ram_tlb_index < 16) { - mtspr(MAS0, TLB1_MAS0(1, ram_tlb_index, 0)); - mtspr(MAS1, TLB1_MAS1(1, 1, 0, 0, tlb_size)); - mtspr(MAS2, TLB1_MAS2(E500_TLB_EPN(ram_tlb_address), - 0, 0, 0, 0, 0, 0, 0, 0)); - mtspr(MAS3, TLB1_MAS3(E500_TLB_RPN(ram_tlb_address), - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1)); + mtspr(MAS0, FSL_BOOKE_MAS0(1, ram_tlb_index, 0)); + mtspr(MAS1, FSL_BOOKE_MAS1(1, 1, 0, 0, tlb_size)); + mtspr(MAS2, FSL_BOOKE_MAS2(ram_tlb_address, 0)); + mtspr(MAS3, FSL_BOOKE_MAS3(ram_tlb_address, 0, + (MAS3_SX|MAS3_SW|MAS3_SR))); asm volatile("isync;msync;tlbwe;isync"); - debug("DDR: MAS0=0x%08x\n", TLB1_MAS0(1, ram_tlb_index, 0)); - debug("DDR: MAS1=0x%08x\n", TLB1_MAS1(1, 1, 0, 0, tlb_size)); - debug("DDR: MAS2=0x%08x\n", - TLB1_MAS2(E500_TLB_EPN(ram_tlb_address), - 0, 0, 0, 0, 0, 0, 0, 0)); + debug("DDR: MAS0=0x%08x\n", FSL_BOOKE_MAS0(1, ram_tlb_index, 0)); + debug("DDR: MAS1=0x%08x\n", FSL_BOOKE_MAS1(1, 1, 0, 0, tlb_size)); + debug("DDR: MAS2=0x%08x\n", FSL_BOOKE_MAS2(ram_tlb_address, 0)); debug("DDR: MAS3=0x%08x\n", - TLB1_MAS3(E500_TLB_RPN(ram_tlb_address), - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1)); + FSL_BOOKE_MAS3(ram_tlb_address, 0, + (MAS3_SX|MAS3_SW|MAS3_SR))); ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2)); ram_tlb_index++; diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S index b769ef8..b489d2f 100644 --- a/cpu/mpc85xx/start.S +++ b/cpu/mpc85xx/start.S @@ -268,7 +268,10 @@ _start_e500: */ lis r3,CFG_INIT_RAM_ADDR@h ori r3,r3,CFG_INIT_RAM_ADDR@l - li r2,(CFG_DCACHE_SIZE / (2 * CFG_CACHELINE_SIZE)) + mfspr r2, L1CFG0 + andi. r2, r2, 0x1ff + /* cache size * 1024 / (2 * L1 line size) */ + slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT) mtctr r2 li r0,0 1: @@ -1061,7 +1064,9 @@ unlock_ram_in_cache: /* invalidate the INIT_RAM section */ lis r3,(CFG_INIT_RAM_ADDR & ~31)@h ori r3,r3,(CFG_INIT_RAM_ADDR & ~31)@l - li r4,(CFG_DCACHE_SIZE / (2 * CFG_CACHELINE_SIZE)) + mfspr r4,L1CFG0 + andi. r4,r4,0x1ff + slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT) mtctr r4 1: icbi r0,r3 dcbi r0,r3 diff --git a/cpu/mpc86xx/cpu.c b/cpu/mpc86xx/cpu.c index d83bedd..11354d3 100644 --- a/cpu/mpc86xx/cpu.c +++ b/cpu/mpc86xx/cpu.c @@ -41,6 +41,8 @@ checkcpu(void) uint major, minor; uint lcrr; /* local bus clock ratio register */ uint clkdiv; /* clock divider portion of lcrr */ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile ccsr_gur_t *gur = &immap->im_gur; puts("Freescale PowerPC\n"); @@ -54,8 +56,14 @@ checkcpu(void) switch (ver) { case PVR_VER(PVR_86xx): - puts("E600"); - break; + { + uint msscr0 = mfspr(MSSCR0); + printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 ); + if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE) + puts("\n Core1Translation Enabled"); + debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr); + } + break; default: puts("Unknown"); break; @@ -76,6 +84,9 @@ checkcpu(void) puts("8641"); } break; + case SVR_8610: + puts("8610"); + break; default: puts("Unknown"); break; diff --git a/cpu/mpc86xx/spd_sdram.c b/cpu/mpc86xx/spd_sdram.c index 265e033..54e40f1 100644 --- a/cpu/mpc86xx/spd_sdram.c +++ b/cpu/mpc86xx/spd_sdram.c @@ -196,7 +196,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, spd_eeprom_t spd; unsigned int n_ranks; unsigned int rank_density; - unsigned int odt_rd_cfg, odt_wr_cfg; + unsigned int odt_rd_cfg, odt_wr_cfg, ba_bits; unsigned int odt_cfg, mode_odt_enable; unsigned int refresh_clk; #ifdef MPC86xx_DDR_SDRAM_CLK_CNTL @@ -321,6 +321,10 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, odt_wr_cfg = 1; /* Assert ODT on writes to CS0 */ } + ba_bits = 0; + if (spd.nbanks == 0x8) + ba_bits = 1; + #ifdef CONFIG_DDR_INTERLEAVE if (dimm_num != 1) { @@ -357,6 +361,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, #endif | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) + | (ba_bits << 14) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); @@ -386,6 +391,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, ddr->cs0_config = ( 1 << 31 | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) + | (ba_bits << 14) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); @@ -403,6 +409,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, ddr->cs1_config = ( 1<<31 | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) + | (ba_bits << 14) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); debug("DDR: cs1_bnds = 0x%08x\n", ddr->cs1_bnds); @@ -422,6 +429,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, ddr->cs2_config = ( 1 << 31 | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) + | (ba_bits << 14) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); @@ -439,6 +447,7 @@ spd_init(unsigned char i2c_address, unsigned int ddr_num, ddr->cs3_config = ( 1<<31 | (odt_rd_cfg << 20) | (odt_wr_cfg << 16) + | (ba_bits << 14) | (spd.nrow_addr - 12) << 8 | (spd.ncol_addr - 8) ); debug("DDR: cs3_bnds = 0x%08x\n", ddr->cs3_bnds); diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c index 97112f0..c878352 100644 --- a/cpu/mpc8xx/cpu.c +++ b/cpu/mpc8xx/cpu.c @@ -39,6 +39,12 @@ #include <mpc8xx.h> #include <asm/cache.h> +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#include <fdt_support.h> +#endif + DECLARE_GLOBAL_DATA_PTR; static char *cpu_warning = "\n " \ @@ -632,3 +638,13 @@ void reset_8xx_watchdog (volatile immap_t * immr) #endif /* CONFIG_WATCHDOG */ /* ------------------------------------------------------------------------- */ +#if defined(CONFIG_OF_LIBFDT) +void ft_cpu_setup (void *blob, bd_t *bd) +{ + char * cpu_path = "/cpus/" OF_CPU; + + do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1); + do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1); + do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1); +} +#endif /* CONFIG_OF_LIBFDT */ diff --git a/cpu/mpc8xx/cpu_init.c b/cpu/mpc8xx/cpu_init.c index c79e578..fb3414a 100644 --- a/cpu/mpc8xx/cpu_init.c +++ b/cpu/mpc8xx/cpu_init.c @@ -31,7 +31,8 @@ DECLARE_GLOBAL_DATA_PTR; #endif -#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) || \ + defined(CFG_SMC_UCODE_PATCH) void cpm_load_patch (volatile immap_t * immr); #endif @@ -253,7 +254,8 @@ void cpu_init_f (volatile immap_t * immr) immr->im_cpm.cp_rccr = CFG_RCCR; #endif -#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) || \ + defined(CFG_SMC_UCODE_PATCH) cpm_load_patch (immr); /* load mpc8xx microcode patch */ #endif } diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index 08a3715..37eb481 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -143,6 +143,9 @@ static int fec_send(struct eth_device* dev, volatile void *packet, int length); static int fec_recv(struct eth_device* dev); static int fec_init(struct eth_device* dev, bd_t * bd); static void fec_halt(struct eth_device* dev); +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +static void __mii_init(void); +#endif int fec_initialize(bd_t *bis) { @@ -539,6 +542,30 @@ static void fec_pin_init(int fecidx) } } +static int fec_reset(volatile fec_t *fecp) +{ + int i; + + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) + return -1; + + return 0; +} + static int fec_init (struct eth_device *dev, bd_t * bd) { struct ether_fcc_info_s *efis = dev->priv; @@ -573,23 +600,17 @@ static int fec_init (struct eth_device *dev, bd_t * bd) #endif /* CONFIG_FADS */ } - /* Whack a reset. - * A delay is required between a reset of the FEC block and - * initialization of other FEC registers because the reset takes - * some time to complete. If you don't delay, subsequent writes - * to FEC registers might get killed by the reset routine which is - * still in progress. +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + /* the MII interface is connected to FEC1 + * so for the miiphy_xxx function to work we must + * call mii_init since fec_halt messes the thing up */ - fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; - for (i = 0; - (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); - ++i) { - udelay (1); - } - if (i == FEC_RESET_DELAY) { + if (efis->ether_index != 0) + __mii_init(); +#endif + + if (fec_reset(fecp) < 0) printf ("FEC_RESET_DELAY timeout\n"); - return 0; - } /* We use strictly polling mode only */ @@ -603,7 +624,7 @@ static int fec_init (struct eth_device *dev, bd_t * bd) /* Set station address */ -#define ea eth_get_dev()->enetaddr +#define ea dev->enetaddr fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); fecp->fec_addr_high = (ea[4] << 8) | (ea[5]); #undef ea @@ -708,7 +729,7 @@ static int fec_init (struct eth_device *dev, bd_t * bd) if (efis->actual_phy_addr == -1) { printf ("Unable to discover phy!\n"); - return 0; + return -1; } #else efis->actual_phy_addr = -1; @@ -716,15 +737,8 @@ static int fec_init (struct eth_device *dev, bd_t * bd) } else { efis->actual_phy_addr = efis->phy_addr; } -#if defined(CONFIG_MII) && defined(CONFIG_RMII) - - /* the MII interface is connected to FEC1 - * so for the miiphy_xxx function to work we must - * call mii_init since fec_halt messes the thing up - */ - if (efis->ether_index != 0) - mii_init(); +#if defined(CONFIG_MII) && defined(CONFIG_RMII) /* * adapt the RMII speed to the speed of the phy */ @@ -751,7 +765,7 @@ static int fec_init (struct eth_device *dev, bd_t * bd) efis->initialized = 1; - return 1; + return 0; } @@ -874,15 +888,14 @@ static int mii_discover_phy(struct eth_device *dev) udelay(10000); /* wait 10ms */ } for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) { - phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1)); + phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR2)); #ifdef ET_DEBUG printf("PHY type 0x%x pass %d type ", phytype, pass); #endif if (phytype != 0xffff) { phyaddr = phyno; - phytype <<= 16; phytype |= mii_send(mk_mii_read(phyno, - PHY_PHYIDR2)); + PHY_PHYIDR1)) << 16; #ifdef ET_DEBUG printf("PHY @ 0x%x pass %d type ",phyno,pass); @@ -929,36 +942,17 @@ static int mii_discover_phy(struct eth_device *dev) #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII) /**************************************************************************** - * mii_init -- Initialize the MII for MII command without ethernet + * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet * This function is a subset of eth_init **************************************************************************** */ -void mii_init (void) +static void __mii_init(void) { volatile immap_t *immr = (immap_t *) CFG_IMMR; volatile fec_t *fecp = &(immr->im_cpm.cp_fec); - int i, j; - for (j = 0; j < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); j++) { - - /* Whack a reset. - * A delay is required between a reset of the FEC block and - * initialization of other FEC registers because the reset takes - * some time to complete. If you don't delay, subsequent writes - * to FEC registers might get killed by the reset routine which is - * still in progress. - */ - - fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; - for (i = 0; - (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); - ++i) { - udelay (1); - } - if (i == FEC_RESET_DELAY) { + if (fec_reset(fecp) < 0) printf ("FEC_RESET_DELAY timeout\n"); - return; - } /* We use strictly polling mode only */ @@ -968,14 +962,21 @@ void mii_init (void) */ fecp->fec_ievent = 0xffc0; - /* Setup the pin configuration of the FEC(s) - */ - fec_pin_init(ether_fcc_info[i].ether_index); - /* Now enable the transmit and receive processing */ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; - } +} + +void mii_init (void) +{ + int i; + + __mii_init(); + + /* Setup the pin configuration of the FEC(s) + */ + for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) + fec_pin_init(ether_fcc_info[i].ether_index); } /***************************************************************************** diff --git a/cpu/mpc8xx/serial.c b/cpu/mpc8xx/serial.c index 68804cc..ad02299 100644 --- a/cpu/mpc8xx/serial.c +++ b/cpu/mpc8xx/serial.c @@ -124,6 +124,12 @@ static int smc_init (void) sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]); up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC]; +#ifdef CFG_SMC_UCODE_PATCH + up = (smc_uart_t *) &cp->cp_dpmem[up->smc_rpbase]; +#else + /* Disable relocation */ + up->smc_rpbase = 0; +#endif /* Disable transmitter/receiver. */ @@ -212,6 +218,12 @@ static int smc_init (void) up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = SMC_EB; up->smc_tfcr = SMC_EB; +#if defined (CFG_SMC_UCODE_PATCH) + up->smc_rbptr = up->smc_rbase; + up->smc_tbptr = up->smc_tbase; + up->smc_rstate = 0; + up->smc_tstate = 0; +#endif #if defined(CONFIG_MBX) board_serial_init(); @@ -288,6 +300,9 @@ smc_putc(const char c) smc_putc ('\r'); up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; +#ifdef CFG_SMC_UCODE_PATCH + up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; +#endif tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; @@ -326,6 +341,9 @@ smc_getc(void) unsigned char c; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; +#ifdef CFG_SMC_UCODE_PATCH + up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; +#endif rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; @@ -351,6 +369,9 @@ smc_tstc(void) volatile cpm8xx_t *cpmp = &(im->im_cpm); up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; +#ifdef CFG_SMC_UCODE_PATCH + up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; +#endif rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; diff --git a/cpu/mpc8xx/upatch.c b/cpu/mpc8xx/upatch.c index eccff64..4d6c522 100644 --- a/cpu/mpc8xx/upatch.c +++ b/cpu/mpc8xx/upatch.c @@ -1,7 +1,8 @@ #include <common.h> #include <commproc.h> -#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH) || \ + defined(CFG_SMC_UCODE_PATCH) static void UcodeCopy (volatile cpm8xx_t *cpm); @@ -32,13 +33,29 @@ void cpm_load_patch (volatile immap_t *immr) } #endif +#ifdef CFG_SMC_UCODE_PATCH + { + volatile smc_uart_t *up = (smc_uart_t *) & immr->im_cpm.cp_dparam[PROFF_SMC1]; + /* Activate the microcode per the instructions in the microcode manual */ + /* NOTE: We're only relocating the SMC parameters. */ + immr->im_cpm.cp_cpmcr1 = 0x8080; /* Write Trap register 1 value */ + immr->im_cpm.cp_cpmcr2 = 0x8088; /* Write Trap register 2 value */ + up->smc_rpbase = CFG_SMC_DPMEM_OFFSET; /* Where to relocte SMC params */ + } +#endif + /* * Enable DPRAM microcode to execute from the first 512 bytes * and a 256 byte extension of DPRAM. */ +#ifdef CFG_SMC_UCODE_PATCH + immr->im_cpm.cp_rccr |= 0x0002; +#else immr->im_cpm.cp_rccr |= 0x0001; +#endif } +#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCh) static ulong patch_2000[] = { 0x7FFFEFD9, 0x3FFD0000, 0x7FFB49F7, 0x7FF90000, 0x5FEFADF7, 0x5F88ADF7, 0x5FEFAFF7, 0x5F88AFF7, @@ -82,6 +99,81 @@ static ulong patch_2F00[] = { 0x35931497, 0x35376956, 0xBD697B9D, 0x96931313, 0x19797937, 0x69350000, }; +#else + +static ulong patch_2000[] = { + 0x3fff0000, 0x3ffd0000, 0x3ffb0000, 0x3ff90000, + 0x5fefeff8, 0x5f91eff8, 0x3ff30000, 0x3ff10000, + 0x3a11e710, 0xedf0ccb9, 0xf318ed66, 0x7f0e5fe2, + 0x7fedbb38, 0x3afe7468, 0x7fedf4d8, 0x8ffbb92d, + 0xb83b77fd, 0xb0bb5eb9, 0xdfda7fed, 0x90bde74d, + 0x6f0dcbd3, 0xe7decfed, 0xcb50cfed, 0xcfeddf6d, + 0x914d4f74, 0x5eaedfcb, 0x9ee0e7df, 0xefbb6ffb, + 0xe7ef7f0e, 0x9ee57fed, 0xebb7effa, 0xeb30affb, + 0x7fea90b3, 0x7e0cf09f, 0xbffff318, 0x5fffdfff, + 0xac35efea, 0x7fce1fc1, 0xe2ff5fbd, 0xaffbe2ff, + 0x5fbfaffb, 0xf9a87d0f, 0xaef8770f, 0x7d0fb0a2, + 0xeffbbfff, 0xcfef5fba, 0x7d0fbfff, 0x5fba4cf8, + 0x7fddd09b, 0x49f847fd, 0x7efdf097, 0x7fedfffd, + 0x7dfdf093, 0xef7e7e1e, 0x5fba7f0e, 0x3a11e710, + 0xedf0cc87, 0xfb18ad0a, 0x1f85bbb8, 0x74283b7e, + 0x7375e4bb, 0x2ab64fb8, 0x5c7de4bb, 0x32fdffbf, + 0x5f0843f8, 0x7ce3e1bb, 0xe74f7ded, 0x6f0f4fe8, + 0xc7ba32be, 0x73f2efeb, 0x600b4f78, 0xe5bb760b, + 0x5388aef8, 0x4ef80b6a, 0xcfef9ee5, 0xabf8751f, + 0xefef5b88, 0x741f4fe8, 0x751e760d, 0x7fdb70dd, + 0x741cafce, 0xefcc7fce, 0x751e7088, 0x741ce7bb, + 0x334ecfed, 0xafdbefeb, 0xe5bb760b, 0x53ceaef8, + 0xafe8e7eb, 0x4bf8771e, 0x7e007fed, 0x4fcbe2cc, + 0x7fbc3085, 0x7b0f7a0f, 0x34b177fd, 0xb0e75e93, + 0xdf313e3b, 0xaf78741f, 0x741f30cc, 0xcfef5f08, + 0x741f3e88, 0xafb8771e, 0x5f437fed, 0x0bafe2cc, + 0x741ccfec, 0xe5ca53a9, 0x6fcb4f74, 0x5e89df27, + 0x2a923d14, 0x4b8fdf0c, 0x751f741c, 0x6c1eeffa, + 0xefea7fce, 0x6ffc309a, 0xefec3fca, 0x308fdf0a, + 0xadf85e7a, 0xaf7daefd, 0x5e7adf0a, 0x5e7aafdd, + 0x761f1088, 0x1e7c7efd, 0x3089fffe, 0x4908fb18, + 0x5fffdfff, 0xafbbf0f7, 0x4ef85f43, 0xadf81489, + 0x7a0f7089, 0xcfef5089, 0x7a0fdf0c, 0x5e7cafed, + 0xbc6e780f, 0xefef780f, 0xefef790f, 0xa7f85eeb, + 0xffef790f, 0xefef790f, 0x1489df0a, 0x5e7aadfd, + 0x5f09fffb, 0xe79aded9, 0xeff96079, 0x607ae79a, + 0xded8eff9, 0x60795edb, 0x607acfef, 0xefefefdf, + 0xefbfef7f, 0xeeffedff, 0xebffe7ff, 0xafefafdf, + 0xafbfaf7f, 0xaeffadff, 0xabffa7ff, 0x6fef6fdf, + 0x6fbf6f7f, 0x6eff6dff, 0x6bff67ff, 0x2fef2fdf, + 0x2fbf2f7f, 0x2eff2dff, 0x2bff27ff, 0x4e08fd1f, + 0xe5ff6e0f, 0xaff87eef, 0x7e0ffdef, 0xf11f6079, + 0xabf8f51e, 0x7e0af11c, 0x37cfae16, 0x7fec909a, + 0xadf8efdc, 0xcfeae52f, 0x7d0fe12b, 0xf11c6079, + 0x7e0a4df8, 0xcfea5ea0, 0x7d0befec, 0xcfea5ea2, + 0xe522efdc, 0x5ea2cfda, 0x4e08fd1f, 0x6e0faff8, + 0x7c1f761f, 0xfdeff91f, 0x6079abf8, 0x761cee00, + 0xf91f2bfb, 0xefefcfec, 0xf91f6079, 0x761c27fb, + 0xefdf5e83, 0xcfdc7fdd, 0x50f84bf8, 0x47fd7c1f, + 0x761ccfcf, 0x7eef7fed, 0x7dfd70ef, 0xef7e7f1e, + 0x771efb18, 0x6079e722, 0xe6bbe5bb, 0x2e66e5bb, + 0x600b2ee1, 0xe2bbe2bb, 0xe2bbe2bb, 0x2f5ee2bb, + 0xe2bb2ff9, 0x6079e2bb, +}; + +static ulong patch_2F00[] = { + 0x30303030, 0x3e3e3030, 0xaf79b9b3, 0xbaa3b979, + 0x9693369f, 0x79f79777, 0x97333fff, 0xfb3b9e9f, + 0x79b91d11, 0x9e13f3ff, 0x3f9b6bd9, 0xe173d136, + 0x695669d1, 0x697b3daf, 0x79b93a3a, 0x3f979f91, + 0x379ff976, 0xf99777fd, 0x9779737d, 0xe9d6bbf9, + 0xbfffd9df, 0x97f7fd97, 0x6f7b9bff, 0xf9bd9683, + 0x397db973, 0xd97b3b9f, 0xd7f9f733, 0x9993bb9e, + 0xe1f9ef93, 0x73773337, 0xb936917d, 0x11f87379, + 0xb979d336, 0x8b7ded73, 0x1b7d9337, 0x31f3f22f, + 0x3f2327ee, 0xeeeeeeee, 0xeeeeeeee, 0xeeeeeeee, + 0xeeeeee4b, 0xf4fbdbd2, 0x58bb1878, 0x577fdfd2, + 0xd573b773, 0xf7374b4f, 0xbdbd25b8, 0xb177d2d1, + 0x7376856b, 0xbfdd687b, 0xdd2fff8f, 0x78ffff8f, + 0xf22f0000, +}; +#endif static void UcodeCopy (volatile cpm8xx_t *cpm) { diff --git a/cpu/ppc4xx/40x_spd_sdram.c b/cpu/ppc4xx/40x_spd_sdram.c index 19c4f76..42fd7fb 100644 --- a/cpu/ppc4xx/40x_spd_sdram.c +++ b/cpu/ppc4xx/40x_spd_sdram.c @@ -148,7 +148,7 @@ long int spd_sdram(int(read_spd)(uint addr)) int t_rc; int min_cas; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; unsigned long bus_period_x_10; /* diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h deleted file mode 100644 index 38745eb..0000000 --- a/cpu/ppc4xx/440spe_pcie.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Roland Dreier <rolandd@cisco.com> - * - * 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. - */ - -#include <ppc4xx.h> -#ifndef __440SPE_PCIE_H -#define __440SPE_PCIE_H - -#define mdelay(n) ({unsigned long __ms=(n); while (__ms--) udelay(1000);}) - -#define DCRN_SDR0_CFGADDR 0x00e -#define DCRN_SDR0_CFGDATA 0x00f - -#define DCRN_PCIE0_BASE 0x100 -#define DCRN_PCIE1_BASE 0x120 -#define DCRN_PCIE2_BASE 0x140 -#define PCIE0 DCRN_PCIE0_BASE -#define PCIE1 DCRN_PCIE1_BASE -#define PCIE2 DCRN_PCIE2_BASE - -#define DCRN_PEGPL_CFGBAH(base) (base + 0x00) -#define DCRN_PEGPL_CFGBAL(base) (base + 0x01) -#define DCRN_PEGPL_CFGMSK(base) (base + 0x02) -#define DCRN_PEGPL_MSGBAH(base) (base + 0x03) -#define DCRN_PEGPL_MSGBAL(base) (base + 0x04) -#define DCRN_PEGPL_MSGMSK(base) (base + 0x05) -#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06) -#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07) -#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08) -#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09) -#define DCRN_PEGPL_REGBAH(base) (base + 0x12) -#define DCRN_PEGPL_REGBAL(base) (base + 0x13) -#define DCRN_PEGPL_REGMSK(base) (base + 0x14) -#define DCRN_PEGPL_SPECIAL(base) (base + 0x15) -#define DCRN_PEGPL_CFG(base) (base + 0x16) - -/* - * System DCRs (SDRs) - */ -#define PESDR0_PLLLCT1 0x03a0 -#define PESDR0_PLLLCT2 0x03a1 -#define PESDR0_PLLLCT3 0x03a2 - -#define PESDR0_UTLSET1 0x0300 -#define PESDR0_UTLSET2 0x0301 -#define PESDR0_DLPSET 0x0302 -#define PESDR0_LOOP 0x0303 -#define PESDR0_RCSSET 0x0304 -#define PESDR0_RCSSTS 0x0305 -#define PESDR0_HSSL0SET1 0x0306 -#define PESDR0_HSSL0SET2 0x0307 -#define PESDR0_HSSL0STS 0x0308 -#define PESDR0_HSSL1SET1 0x0309 -#define PESDR0_HSSL1SET2 0x030a -#define PESDR0_HSSL1STS 0x030b -#define PESDR0_HSSL2SET1 0x030c -#define PESDR0_HSSL2SET2 0x030d -#define PESDR0_HSSL2STS 0x030e -#define PESDR0_HSSL3SET1 0x030f -#define PESDR0_HSSL3SET2 0x0310 -#define PESDR0_HSSL3STS 0x0311 -#define PESDR0_HSSL4SET1 0x0312 -#define PESDR0_HSSL4SET2 0x0313 -#define PESDR0_HSSL4STS 0x0314 -#define PESDR0_HSSL5SET1 0x0315 -#define PESDR0_HSSL5SET2 0x0316 -#define PESDR0_HSSL5STS 0x0317 -#define PESDR0_HSSL6SET1 0x0318 -#define PESDR0_HSSL6SET2 0x0319 -#define PESDR0_HSSL6STS 0x031a -#define PESDR0_HSSL7SET1 0x031b -#define PESDR0_HSSL7SET2 0x031c -#define PESDR0_HSSL7STS 0x031d -#define PESDR0_HSSCTLSET 0x031e -#define PESDR0_LANE_ABCD 0x031f -#define PESDR0_LANE_EFGH 0x0320 - -#define PESDR1_UTLSET1 0x0340 -#define PESDR1_UTLSET2 0x0341 -#define PESDR1_DLPSET 0x0342 -#define PESDR1_LOOP 0x0343 -#define PESDR1_RCSSET 0x0344 -#define PESDR1_RCSSTS 0x0345 -#define PESDR1_HSSL0SET1 0x0346 -#define PESDR1_HSSL0SET2 0x0347 -#define PESDR1_HSSL0STS 0x0348 -#define PESDR1_HSSL1SET1 0x0349 -#define PESDR1_HSSL1SET2 0x034a -#define PESDR1_HSSL1STS 0x034b -#define PESDR1_HSSL2SET1 0x034c -#define PESDR1_HSSL2SET2 0x034d -#define PESDR1_HSSL2STS 0x034e -#define PESDR1_HSSL3SET1 0x034f -#define PESDR1_HSSL3SET2 0x0350 -#define PESDR1_HSSL3STS 0x0351 -#define PESDR1_HSSCTLSET 0x0352 -#define PESDR1_LANE_ABCD 0x0353 - -#define PESDR2_UTLSET1 0x0370 -#define PESDR2_UTLSET2 0x0371 -#define PESDR2_DLPSET 0x0372 -#define PESDR2_LOOP 0x0373 -#define PESDR2_RCSSET 0x0374 -#define PESDR2_RCSSTS 0x0375 -#define PESDR2_HSSL0SET1 0x0376 -#define PESDR2_HSSL0SET2 0x0377 -#define PESDR2_HSSL0STS 0x0378 -#define PESDR2_HSSL1SET1 0x0379 -#define PESDR2_HSSL1SET2 0x037a -#define PESDR2_HSSL1STS 0x037b -#define PESDR2_HSSL2SET1 0x037c -#define PESDR2_HSSL2SET2 0x037d -#define PESDR2_HSSL2STS 0x037e -#define PESDR2_HSSL3SET1 0x037f -#define PESDR2_HSSL3SET2 0x0380 -#define PESDR2_HSSL3STS 0x0381 -#define PESDR2_HSSCTLSET 0x0382 -#define PESDR2_LANE_ABCD 0x0383 - -/* - * UTL register offsets - */ -#define PEUTL_PBBSZ 0x20 -#define PEUTL_OPDBSZ 0x68 -#define PEUTL_IPHBSZ 0x70 -#define PEUTL_IPDBSZ 0x78 -#define PEUTL_OUTTR 0x90 -#define PEUTL_INTR 0x98 -#define PEUTL_PCTL 0xa0 -#define PEUTL_RCIRQEN 0xb8 - -/* - * Config space register offsets - */ -#define PECFG_BAR0LMPA 0x210 -#define PECFG_BAR0HMPA 0x214 -#define PECFG_BAR1MPA 0x218 -#define PECFG_BAR2MPA 0x220 - -#define PECFG_PIMEN 0x33c -#define PECFG_PIM0LAL 0x340 -#define PECFG_PIM0LAH 0x344 -#define PECFG_PIM1LAL 0x348 -#define PECFG_PIM1LAH 0x34c -#define PECFG_PIM01SAL 0x350 -#define PECFG_PIM01SAH 0x354 - -#define PECFG_POM0LAL 0x380 -#define PECFG_POM0LAH 0x384 - -#define SDR_READ(offset) ({\ - mtdcr(DCRN_SDR0_CFGADDR, offset); \ - mfdcr(DCRN_SDR0_CFGDATA);}) - -#define SDR_WRITE(offset, data) ({\ - mtdcr(DCRN_SDR0_CFGADDR, offset); \ - mtdcr(DCRN_SDR0_CFGDATA,data);}) - -#define GPL_DMER_MASK_DISA 0x02000000 - -int ppc440spe_init_pcie(void); -int ppc440spe_init_pcie_rootport(int port); -void yucca_setup_pcie_fpga_rootpoint(int port); -void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port); -int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port); -int yucca_pcie_card_present(int port); -int pcie_hose_scan(struct pci_controller *hose, int bus); -#endif /* __440SPE_PCIE_H */ diff --git a/cpu/ppc4xx/44x_spd_ddr.c b/cpu/ppc4xx/44x_spd_ddr.c index 4a4c6f2..b9cf5cb 100644 --- a/cpu/ppc4xx/44x_spd_ddr.c +++ b/cpu/ppc4xx/44x_spd_ddr.c @@ -251,10 +251,10 @@ void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")) * memory. * * If at some time this restriction doesn't apply anymore, just define - * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup + * CONFIG_4xx_DCACHE in the board config file and this code should setup * everything correctly. */ -#ifdef CFG_ENABLE_SDRAM_CACHE +#ifdef CONFIG_4xx_DCACHE #define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ #else #define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ @@ -345,7 +345,7 @@ long int spd_sdram(void) { */ check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP) +#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) /* * Soft-reset SDRAM controller. */ @@ -645,7 +645,7 @@ static void program_rtr(unsigned long *dimm_populated, unsigned char refresh_rate_type; unsigned long refresh_interval; unsigned long sdram_rtr; - PPC440_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; /* * get the board info @@ -721,7 +721,7 @@ static void program_tr0(unsigned long *dimm_populated, unsigned long tcyc_2_0_ns_x_10; unsigned long tcyc_reg; unsigned long bus_period_x_10; - PPC440_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; unsigned long residue; /* @@ -1065,7 +1065,7 @@ static void program_tr1(void) unsigned char window_found; unsigned char fail_found; unsigned char pass_found; - PPC440_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; /* * get the board info @@ -1197,9 +1197,6 @@ static void program_tr1(void) } rdclt_average = ((max_start + max_end) >> 1); - if (rdclt_average >= 0x60) - while (1) - ; if (rdclt_average < 0) { rdclt_average = 0; diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 67ba5bd..3ac2cdc 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -3,7 +3,7 @@ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a * DDR2 controller (non Denali Core). Those are 440SP/SPe. * - * (C) Copyright 2007 + * (C) Copyright 2007-2008 * Stefan Roese, DENX Software Engineering, sr@denx.de. * * COPYRIGHT AMCC CORPORATION 2004 @@ -111,8 +111,6 @@ #define NUMMEMWORDS 8 #define NUMLOOPS 64 /* memory test loops */ -#undef CONFIG_ECC_ERROR_RESET /* test-only: see description below, at check_ecc() */ - /* * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory * region. Right now the cache should still be disabled in U-Boot because of the @@ -120,10 +118,10 @@ * memory. * * If at some time this restriction doesn't apply anymore, just define - * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup + * CONFIG_4xx_DCACHE in the board config file and this code should setup * everything correctly. */ -#ifdef CFG_ENABLE_SDRAM_CACHE +#ifdef CONFIG_4xx_DCACHE #define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ #else #define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ @@ -623,7 +621,7 @@ static void get_spd_info(unsigned long *dimm_populated, void board_add_ram_info(int use_default) { - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; u32 val; if (is_ecc_enabled()) @@ -741,7 +739,7 @@ static void check_frequency(unsigned long *dimm_populated, unsigned long calc_cycle_time; unsigned long sdram_freq; unsigned long sdr_ddrpll; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; /*------------------------------------------------------------------ * Get the board configuration info. @@ -1353,7 +1351,7 @@ static void program_mode(unsigned long *dimm_populated, unsigned long max_4_0_tcyc_ns_x_100; unsigned long max_5_0_tcyc_ns_x_100; unsigned long cycle_time_ns_x_100[3]; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; unsigned char cas_2_0_available; unsigned char cas_2_5_available; unsigned char cas_3_0_available; @@ -1640,7 +1638,7 @@ static void program_rtr(unsigned long *dimm_populated, unsigned char *iic0_dimm_addr, unsigned long num_dimm_banks) { - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; unsigned long max_refresh_rate; unsigned long dimm_num; unsigned long refresh_rate_type; @@ -1737,7 +1735,7 @@ static void program_tr(unsigned long *dimm_populated, unsigned long sdram_freq; unsigned long sdr_ddrpll; - PPC440_SYS_INFO board_cfg; + PPC4xx_SYS_INFO board_cfg; /*------------------------------------------------------------------ * Get the board configuration info. @@ -2048,14 +2046,10 @@ static void program_bxcf(unsigned long *dimm_populated, /*------------------------------------------------------------------ * Set the BxCF regs. First, wipe out the bank config registers. *-----------------------------------------------------------------*/ - mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB1CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB2CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); - mtdcr(SDRAMC_CFGADDR, SDRAM_MB3CF); - mtdcr(SDRAMC_CFGDATA, 0x00000000); + mtsdram(SDRAM_MB0CF, 0x00000000); + mtsdram(SDRAM_MB1CF, 0x00000000); + mtsdram(SDRAM_MB2CF, 0x00000000); + mtsdram(SDRAM_MB3CF, 0x00000000); mode = SDRAM_BXCF_M_BE_ENABLE; @@ -2107,8 +2101,9 @@ static void program_bxcf(unsigned long *dimm_populated, bank_0_populated = 1; for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) { - mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF + ((dimm_num + bank_0_populated + ind_rank) << 2)); - mtdcr(SDRAMC_CFGDATA, mode); + mtsdram(SDRAM_MB0CF + + ((dimm_num + bank_0_populated + ind_rank) << 2), + mode); } } } @@ -2271,39 +2266,6 @@ static void program_ecc(unsigned long *dimm_populated, return; } -#ifdef CONFIG_ECC_ERROR_RESET -/* - * Check for ECC errors and reset board upon any error here - * - * On the Katmai 440SPe eval board, from time to time, the first - * lword write access after DDR2 initializazion with ECC checking - * enabled, leads to an ECC error. I couldn't find a configuration - * without this happening. On my board with the current setup it - * happens about 1 from 10 times. - * - * The ECC modules used for testing are: - * - Kingston ValueRAM KVR667D2E5/512 (tested with 1 and 2 DIMM's) - * - * This has to get fixed for the Katmai and tested for the other - * board (440SP/440SPe) that will eventually use this code in the - * future. - * - * 2007-03-01, sr - */ -static void check_ecc(void) -{ - u32 val; - - mfsdram(SDRAM_ECCCR, val); - if (val != 0) { - printf("\nECC error: MCIF0_ECCES=%08lx MQ0_ESL=%08lx address=%08lx\n", - val, mfdcr(0x4c), mfdcr(0x4e)); - printf("ECC error occured, resetting board...\n"); - do_reset(NULL, 0, 0, NULL); - } -} -#endif - static void wait_ddr_idle(void) { u32 val; @@ -2378,15 +2340,6 @@ static void program_ecc_addr(unsigned long start_address, sync(); eieio(); wait_ddr_idle(); - -#ifdef CONFIG_ECC_ERROR_RESET - /* - * One write to 0 is enough to trigger this ECC error - * (see description above) - */ - out_be32(0, 0x12345678); - check_ecc(); -#endif } } #endif @@ -2412,17 +2365,10 @@ static void program_DQS_calibration(unsigned long *dimm_populated, * Read sample cycle auto-update enable *-----------------------------------------------------------------*/ - /* - * Modified for the Katmai platform: with some DIMMs, the DDR2 - * controller automatically selects the T2 read cycle, but this - * proves unreliable. Go ahead and force the DDR2 controller - * to use the T4 sample and disable the automatic update of the - * RDSS field. - */ mfsdram(SDRAM_RDCC, val); mtsdram(SDRAM_RDCC, (val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK)) - | (SDRAM_RDCC_RDSS_T4 | SDRAM_RDCC_RSAE_DISABLE)); + | SDRAM_RDCC_RSAE_ENABLE); /*------------------------------------------------------------------ * Program RQDC register @@ -2515,10 +2461,7 @@ static void DQS_calibration_process(void) { unsigned long rfdc_reg; unsigned long rffd; - unsigned long rqdc_reg; - unsigned long rqfd; unsigned long val; - long rqfd_average; long rffd_average; long max_start; long min_end; @@ -2536,10 +2479,14 @@ static void DQS_calibration_process(void) long max_end; unsigned char fail_found; unsigned char pass_found; +#if !defined(CONFIG_DDR_RQDC_FIXED) + u32 rqdc_reg; + u32 rqfd; u32 rqfd_start; + u32 rqfd_average; + int loopi = 0; char str[] = "Auto calibration -"; char slash[] = "\\|/-\\|/-"; - int loopi = 0; /*------------------------------------------------------------------ * Test to determine the best read clock delay tuning bits. @@ -2574,6 +2521,16 @@ calibration_loop: mfsdram(SDRAM_RQDC, rqdc_reg); mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_start)); +#else /* CONFIG_DDR_RQDC_FIXED */ + /* + * On Katmai the complete auto-calibration somehow doesn't seem to + * produce the best results, meaning optimal values for RQFD/RFFD. + * This was discovered by GDA using a high bandwidth scope, + * analyzing the DDR2 signals. GDA provided a fixed value for RQFD, + * so now on Katmai "only" RFFD is auto-calibrated. + */ + mtsdram(SDRAM_RQDC, CONFIG_DDR_RQDC_FIXED); +#endif /* CONFIG_DDR_RQDC_FIXED */ max_start = 0; min_end = 0; @@ -2658,6 +2615,7 @@ calibration_loop: /* now fix RFDC[RFFD] found and find RQDC[RQFD] */ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); +#if !defined(CONFIG_DDR_RQDC_FIXED) max_pass_length = 0; max_start = 0; max_end = 0; @@ -2730,8 +2688,6 @@ calibration_loop: spd_ddr_init_hang (); } - blank_string(strlen(str)); - if (rqfd_average < 0) rqfd_average = 0; @@ -2742,12 +2698,31 @@ calibration_loop: (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); + blank_string(strlen(str)); +#endif /* CONFIG_DDR_RQDC_FIXED */ + + /* + * Now complete RDSS configuration as mentioned on page 7 of the AMCC + * PowerPC440SP/SPe DDR2 application note: + * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning" + */ + mfsdram(SDRAM_RTSR, val); + if ((val & SDRAM_RTSR_TRK1SM_MASK) == SDRAM_RTSR_TRK1SM_ATPLS1) { + mfsdram(SDRAM_RDCC, val); + if ((val & SDRAM_RDCC_RDSS_MASK) != SDRAM_RDCC_RDSS_T4) { + val += 0x40000000; + mtsdram(SDRAM_RDCC, val); + } + } + mfsdram(SDRAM_DLCR, val); debug("%s[%d] DLCR: 0x%08X\n", __FUNCTION__, __LINE__, val); mfsdram(SDRAM_RQDC, val); debug("%s[%d] RQDC: 0x%08X\n", __FUNCTION__, __LINE__, val); mfsdram(SDRAM_RFDC, val); debug("%s[%d] RFDC: 0x%08X\n", __FUNCTION__, __LINE__, val); + mfsdram(SDRAM_RDCC, val); + debug("%s[%d] RDCC: 0x%08X\n", __FUNCTION__, __LINE__, val); } #else /* calibration test with hardvalues */ /*-----------------------------------------------------------------------------+ diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index 71a9e37..44659ff 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -81,13 +81,16 @@ #include <common.h> #include <net.h> #include <asm/processor.h> +#include <asm/io.h> +#include <asm/cache.h> +#include <asm/mmu.h> #include <commproc.h> #include <ppc4xx.h> #include <ppc4xx_enet.h> #include <405_mal.h> #include <miiphy.h> #include <malloc.h> -#include "vecnum.h" +#include <asm/ppc4xx-intvec.h> /* * Only compile for platform with AMCC EMAC ethernet controller and @@ -105,7 +108,7 @@ #endif #define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */ -#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */ +#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* 5000 ms autonegotiate timeout */ /* Ethernet Transmit and Receive Buffers */ /* AS.HARNOIS @@ -133,13 +136,15 @@ #define BI_PHYMODE_GMII 3 #define BI_PHYMODE_RTBI 4 #define BI_PHYMODE_TBI 5 -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) #define BI_PHYMODE_SMII 6 #define BI_PHYMODE_MII 7 #endif -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GRX) || defined(CONFIG_440SP) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) #define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) #endif @@ -156,7 +161,14 @@ struct eth_device *emac0_dev = NULL; /* * Get count of EMAC devices (doesn't have to be the max. possible number * supported by the cpu) + * + * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the + * EMAC count is possible. As it is needed for the Kilauea/Haleakala + * 405EX/405EXr eval board, using the same binary. */ +#if defined(CONFIG_BOARD_EMAC_COUNT) +#define LAST_EMAC_NUM board_emac_count() +#else /* CONFIG_BOARD_EMAC_COUNT */ #if defined(CONFIG_HAS_ETH3) #define LAST_EMAC_NUM 4 #elif defined(CONFIG_HAS_ETH2) @@ -166,12 +178,23 @@ struct eth_device *emac0_dev = NULL; #else #define LAST_EMAC_NUM 1 #endif +#endif /* CONFIG_BOARD_EMAC_COUNT */ /* normal boards start with EMAC0 */ #if !defined(CONFIG_EMAC_NR_START) #define CONFIG_EMAC_NR_START 0 #endif +#if defined(CONFIG_405EX) || defined(CONFIG_440EPX) +#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev))) +#else +#define ETH_IRQ_NUM(dev) (VECNUM_ETH0 + ((dev) * 2)) +#endif + +#define MAL_RX_DESC_SIZE 2048 +#define MAL_TX_DESC_SIZE 2048 +#define MAL_ALLOC_SIZE (MAL_TX_DESC_SIZE + MAL_RX_DESC_SIZE) + /*-----------------------------------------------------------------------------+ * Prototypes and externals. *-----------------------------------------------------------------------------*/ @@ -189,6 +212,8 @@ extern int emac4xx_miiphy_read (char *devname, unsigned char addr, extern int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg, unsigned short value); +int board_emac_count(void); + /*-----------------------------------------------------------------------------+ | ppc_4xx_eth_halt | Disable MAL channel, and EMACn @@ -197,11 +222,13 @@ static void ppc_4xx_eth_halt (struct eth_device *dev) { EMAC_4XX_HW_PST hw_p = dev->priv; uint32_t failsafe = 10000; -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) unsigned long mfr; #endif - out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */ + out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */ /* 1st reset MAL channel */ /* Note: writing a 0 to a channel has no effect */ @@ -221,16 +248,20 @@ static void ppc_4xx_eth_halt (struct eth_device *dev) } /* EMAC RESET */ -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) /* provide clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum); mtsdr(sdr_mfr, mfr); #endif - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); + out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) /* remove clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum); @@ -329,8 +360,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) /* Ensure we setup mdio for this devnum and ONLY this devnum */ zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); - out32 (ZMII_FER, zmiifer); - out32 (RGMII_FER, rmiifer); + out_be32((void *)ZMII_FER, zmiifer); + out_be32((void *)RGMII_FER, rmiifer); return ((int)pfc1); } @@ -348,31 +379,31 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) switch (pfc1) { case SDR0_PFC1_SELECT_CONFIG_2: /* 1 x GMII port */ - out32 (ZMII_FER, 0x00); - out32 (RGMII_FER, 0x00000037); + out_be32((void *)ZMII_FER, 0x00); + out_be32((void *)RGMII_FER, 0x00000037); bis->bi_phymode[0] = BI_PHYMODE_GMII; bis->bi_phymode[1] = BI_PHYMODE_NONE; break; case SDR0_PFC1_SELECT_CONFIG_4: /* 2 x RGMII ports */ - out32 (ZMII_FER, 0x00); - out32 (RGMII_FER, 0x00000055); + out_be32((void *)ZMII_FER, 0x00); + out_be32((void *)RGMII_FER, 0x00000055); bis->bi_phymode[0] = BI_PHYMODE_RGMII; bis->bi_phymode[1] = BI_PHYMODE_RGMII; break; case SDR0_PFC1_SELECT_CONFIG_6: /* 2 x SMII ports */ - out32 (ZMII_FER, - ((ZMII_FER_SMII) << ZMII_FER_V(0)) | - ((ZMII_FER_SMII) << ZMII_FER_V(1))); - out32 (RGMII_FER, 0x00000000); + out_be32((void *)ZMII_FER, + ((ZMII_FER_SMII) << ZMII_FER_V(0)) | + ((ZMII_FER_SMII) << ZMII_FER_V(1))); + out_be32((void *)RGMII_FER, 0x00000000); bis->bi_phymode[0] = BI_PHYMODE_SMII; bis->bi_phymode[1] = BI_PHYMODE_SMII; break; case SDR0_PFC1_SELECT_CONFIG_1_2: /* only 1 x MII supported */ - out32 (ZMII_FER, (ZMII_FER_MII) << ZMII_FER_V(0)); - out32 (RGMII_FER, 0x00000000); + out_be32((void *)ZMII_FER, (ZMII_FER_MII) << ZMII_FER_V(0)); + out_be32((void *)RGMII_FER, 0x00000000); bis->bi_phymode[0] = BI_PHYMODE_MII; bis->bi_phymode[1] = BI_PHYMODE_NONE; break; @@ -381,17 +412,55 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) } /* Ensure we setup mdio for this devnum and ONLY this devnum */ - zmiifer = in32 (ZMII_FER); + zmiifer = in_be32((void *)ZMII_FER); zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); - out32 (ZMII_FER, zmiifer); + out_be32((void *)ZMII_FER, zmiifer); return ((int)0x0); } #endif /* CONFIG_440EPX */ +#if defined(CONFIG_405EX) +int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) +{ + u32 gmiifer = 0; + + /* + * Right now only 2*RGMII is supported. Please extend when needed. + * sr - 2007-09-19 + */ + switch (1) { + case 1: + /* 2 x RGMII ports */ + out_be32((void *)RGMII_FER, 0x00000055); + bis->bi_phymode[0] = BI_PHYMODE_RGMII; + bis->bi_phymode[1] = BI_PHYMODE_RGMII; + break; + case 2: + /* 2 x SMII ports */ + break; + default: + break; + } + + /* Ensure we setup mdio for this devnum and ONLY this devnum */ + gmiifer = in_be32((void *)RGMII_FER); + gmiifer |= (1 << (19-devnum)); + out_be32((void *)RGMII_FER, gmiifer); + + return ((int)0x0); +} +#endif /* CONFIG_405EX */ + +static inline void *malloc_aligned(u32 size, u32 align) +{ + return (void *)(((u32)malloc(size + align) + align - 1) & + ~(align - 1)); +} + static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) { - int i, j; + int i; unsigned long reg = 0; unsigned long msr; unsigned long speed; @@ -402,18 +471,22 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) unsigned short reg_short; #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) sys_info_t sysinfo; #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) int ethgroup = -1; #endif #endif #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) unsigned long mfr; #endif - + u32 bd_cached; + u32 bd_uncached = 0; EMAC_4XX_HW_PST hw_p = dev->priv; @@ -426,7 +499,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) /* Need to get the OPB frequency so we can access the PHY */ get_sys_info (&sysinfo); #endif @@ -476,53 +550,57 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) /* NOTE: Therefore, disable all other EMACS, since we handle */ /* NOTE: only one emac at a time */ reg = 0; - out32 (ZMII_FER, 0); + out_be32((void *)ZMII_FER, 0); udelay (100); #if defined(CONFIG_440EP) || defined(CONFIG_440GR) - out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); + out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); #elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis); #elif defined(CONFIG_440GP) /* set RMII mode */ - out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0); + out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0); #else if ((devnum == 0) || (devnum == 1)) { - out32 (ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); + out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); } else { /* ((devnum == 2) || (devnum == 3)) */ - out32 (ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum)); - out32 (RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) | - (RGMII_FER_RGMII << RGMII_FER_V (3)))); + out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum)); + out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) | + (RGMII_FER_RGMII << RGMII_FER_V (3)))); } #endif - out32 (ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum)); + out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum)); #endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */ +#if defined(CONFIG_405EX) + ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis); +#endif __asm__ volatile ("eieio"); /* reset emac so we have access to the phy */ -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) /* provide clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); mtsdr(sdr_mfr, mfr); #endif - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); - __asm__ volatile ("eieio"); + out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); failsafe = 1000; - while ((in32 (EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) { + while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) { udelay (1000); failsafe--; } if (failsafe <= 0) printf("\nProblem resetting EMAC!\n"); -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) /* remove clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); @@ -531,7 +609,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) /* Whack the M1 register */ mode_reg = 0x0; mode_reg &= ~0x00000038; @@ -545,7 +624,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) else mode_reg |= EMAC_M1_OBCI_GT100; - out32 (EMAC_M1 + hw_p->hw_addr, mode_reg); + out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg); #endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ /* wait for PHY to complete auto negotiation */ @@ -591,7 +670,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) #if defined(CONFIG_CIS8201_PHY) /* @@ -702,11 +782,11 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #endif /* Set ZMII/RGMII speed according to the phy link speed */ - reg = in32 (ZMII_SSR); + reg = in_be32((void *)ZMII_SSR); if ( (speed == 100) || (speed == 1000) ) - out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum))); + out_be32((void *)ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum))); else - out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum)))); + out_be32((void *)ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum)))); if ((devnum == 2) || (devnum == 3)) { if (speed == 1000) @@ -719,11 +799,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) printf("Error in RGMII Speed\n"); return -1; } - out32 (RGMII_SSR, reg); + out_be32((void *)RGMII_SSR, reg); } #endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */ -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) if (speed == 1000) reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); else if (speed == 100) @@ -734,13 +815,14 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) printf("Error in RGMII Speed\n"); return -1; } - out32 (RGMII_SSR, reg); + out_be32((void *)RGMII_SSR, reg); #endif /* set the Mal configuration reg */ #if defined(CONFIG_440GX) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_405EX) mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000); #else @@ -751,91 +833,58 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) } #endif - /* Free "old" buffers */ - if (hw_p->alloc_tx_buf) - free (hw_p->alloc_tx_buf); - if (hw_p->alloc_rx_buf) - free (hw_p->alloc_rx_buf); - /* * Malloc MAL buffer desciptors, make sure they are * aligned on cache line boundary size * (401/403/IOP480 = 16, 405 = 32) * and doesn't cross cache block boundaries. */ - hw_p->alloc_tx_buf = - (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) + - ((2 * CFG_CACHELINE_SIZE) - 2)); - if (NULL == hw_p->alloc_tx_buf) - return -1; - if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) { - hw_p->tx = - (mal_desc_t *) ((int) hw_p->alloc_tx_buf + - CFG_CACHELINE_SIZE - - ((int) hw_p-> - alloc_tx_buf & CACHELINE_MASK)); - } else { - hw_p->tx = hw_p->alloc_tx_buf; - } + if (hw_p->first_init == 0) { + debug("*** Allocating descriptor memory ***\n"); - hw_p->alloc_rx_buf = - (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) + - ((2 * CFG_CACHELINE_SIZE) - 2)); - if (NULL == hw_p->alloc_rx_buf) { - free(hw_p->alloc_tx_buf); - hw_p->alloc_tx_buf = NULL; - return -1; - } + bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096); + if (!bd_cached) { + printf("%s: Error allocating MAL descriptor buffers!\n"); + return -1; + } - if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) { - hw_p->rx = - (mal_desc_t *) ((int) hw_p->alloc_rx_buf + - CFG_CACHELINE_SIZE - - ((int) hw_p-> - alloc_rx_buf & CACHELINE_MASK)); - } else { - hw_p->rx = hw_p->alloc_rx_buf; +#ifdef CONFIG_4xx_DCACHE + flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE); + bd_uncached = bis->bi_memsize; + program_tlb(bd_cached, bd_uncached, MAL_ALLOC_SIZE, + TLB_WORD2_I_ENABLE); +#else + bd_uncached = bd_cached; +#endif + hw_p->tx_phys = bd_cached; + hw_p->rx_phys = bd_cached + MAL_TX_DESC_SIZE; + hw_p->tx = (mal_desc_t *)(bd_uncached); + hw_p->rx = (mal_desc_t *)(bd_uncached + MAL_TX_DESC_SIZE); + debug("hw_p->tx=%08x, hw_p->rx=%08x\n", hw_p->tx, hw_p->rx); } for (i = 0; i < NUM_TX_BUFF; i++) { hw_p->tx[i].ctrl = 0; hw_p->tx[i].data_len = 0; - if (hw_p->first_init == 0) { - hw_p->txbuf_ptr = - (char *) malloc (ENET_MAX_MTU_ALIGNED); - if (NULL == hw_p->txbuf_ptr) { - free(hw_p->alloc_rx_buf); - free(hw_p->alloc_tx_buf); - hw_p->alloc_rx_buf = NULL; - hw_p->alloc_tx_buf = NULL; - for(j = 0; j < i; j++) { - free(hw_p->tx[i].data_ptr); - hw_p->tx[i].data_ptr = NULL; - } - } - } + if (hw_p->first_init == 0) + hw_p->txbuf_ptr = malloc_aligned(MAL_ALLOC_SIZE, + L1_CACHE_BYTES); hw_p->tx[i].data_ptr = hw_p->txbuf_ptr; if ((NUM_TX_BUFF - 1) == i) hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP; hw_p->tx_run[i] = -1; -#if 0 - printf ("TX_BUFF %d @ 0x%08lx\n", i, - (ulong) hw_p->tx[i].data_ptr); -#endif + debug("TX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->tx[i].data_ptr); } for (i = 0; i < NUM_RX_BUFF; i++) { hw_p->rx[i].ctrl = 0; hw_p->rx[i].data_len = 0; - /* rx[i].data_ptr = (char *) &rx_buff[i]; */ - hw_p->rx[i].data_ptr = (char *) NetRxPackets[i]; + hw_p->rx[i].data_ptr = (char *)NetRxPackets[i]; if ((NUM_RX_BUFF - 1) == i) hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP; hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR; hw_p->rx_ready[i] = -1; -#if 0 - printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) hw_p->rx[i].data_ptr); -#endif + debug("RX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->rx[i].data_ptr); } reg = 0x00000000; @@ -844,7 +893,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) reg = reg << 8; reg |= dev->enetaddr[1]; - out32 (EMAC_IAH + hw_p->hw_addr, reg); + out_be32((void *)EMAC_IAH + hw_p->hw_addr, reg); reg = 0x00000000; reg |= dev->enetaddr[2]; /* set low address */ @@ -855,21 +904,21 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) reg = reg << 8; reg |= dev->enetaddr[5]; - out32 (EMAC_IAL + hw_p->hw_addr, reg); + out_be32((void *)EMAC_IAL + hw_p->hw_addr, reg); switch (devnum) { case 1: /* setup MAL tx & rx channel pointers */ #if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) - mtdcr (maltxctp2r, hw_p->tx); + mtdcr (maltxctp2r, hw_p->tx_phys); #else - mtdcr (maltxctp1r, hw_p->tx); + mtdcr (maltxctp1r, hw_p->tx_phys); #endif #if defined(CONFIG_440) mtdcr (maltxbattr, 0x0); mtdcr (malrxbattr, 0x0); #endif - mtdcr (malrxctp1r, hw_p->rx); + mtdcr (malrxctp1r, hw_p->rx_phys); /* set RX buffer size */ mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16); break; @@ -878,17 +927,17 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) /* setup MAL tx & rx channel pointers */ mtdcr (maltxbattr, 0x0); mtdcr (malrxbattr, 0x0); - mtdcr (maltxctp2r, hw_p->tx); - mtdcr (malrxctp2r, hw_p->rx); + mtdcr (maltxctp2r, hw_p->tx_phys); + mtdcr (malrxctp2r, hw_p->rx_phys); /* set RX buffer size */ mtdcr (malrcbs2, ENET_MAX_MTU_ALIGNED / 16); break; case 3: /* setup MAL tx & rx channel pointers */ mtdcr (maltxbattr, 0x0); - mtdcr (maltxctp3r, hw_p->tx); + mtdcr (maltxctp3r, hw_p->tx_phys); mtdcr (malrxbattr, 0x0); - mtdcr (malrxctp3r, hw_p->rx); + mtdcr (malrxctp3r, hw_p->rx_phys); /* set RX buffer size */ mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16); break; @@ -900,8 +949,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) mtdcr (maltxbattr, 0x0); mtdcr (malrxbattr, 0x0); #endif - mtdcr (maltxctp0r, hw_p->tx); - mtdcr (malrxctp0r, hw_p->rx); + mtdcr (maltxctp0r, hw_p->tx_phys); + mtdcr (malrxctp0r, hw_p->rx_phys); /* set RX buffer size */ mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16); break; @@ -916,10 +965,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum)); /* set transmit enable & receive enable */ - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE); + out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE); /* set receive fifo to 4k and tx fifo to 2k */ - mode_reg = in32 (EMAC_M1 + hw_p->hw_addr); + mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr); mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K; /* set speed */ @@ -940,46 +989,46 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) if (duplex == FULL) mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST; - out32 (EMAC_M1 + hw_p->hw_addr, mode_reg); + out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg); /* Enable broadcast and indvidual address */ /* TBS: enabling runts as some misbehaved nics will send runts */ - out32 (EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE); + out_be32((void *)EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE); /* we probably need to set the tx mode1 reg? maybe at tx time */ /* set transmit request threshold register */ - out32 (EMAC_TRTR + hw_p->hw_addr, 0x18000000); /* 256 byte threshold */ + out_be32((void *)EMAC_TRTR + hw_p->hw_addr, 0x18000000); /* 256 byte threshold */ /* set receive low/high water mark register */ #if defined(CONFIG_440) /* 440s has a 64 byte burst length */ - out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000); + out_be32((void *)EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000); #else /* 405s have a 16 byte burst length */ - out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000); + out_be32((void *)EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000); #endif /* defined(CONFIG_440) */ - out32 (EMAC_TXM1 + hw_p->hw_addr, 0xf8640000); + out_be32((void *)EMAC_TXM1 + hw_p->hw_addr, 0xf8640000); /* Set fifo limit entry in tx mode 0 */ - out32 (EMAC_TXM0 + hw_p->hw_addr, 0x00000003); + out_be32((void *)EMAC_TXM0 + hw_p->hw_addr, 0x00000003); /* Frame gap set */ - out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008); + out_be32((void *)EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008); /* Set EMAC IER */ hw_p->emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE; if (speed == _100BASET) hw_p->emac_ier = hw_p->emac_ier | EMAC_ISR_SYE; - out32 (EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */ - out32 (EMAC_IER + hw_p->hw_addr, hw_p->emac_ier); + out_be32((void *)EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */ + out_be32((void *)EMAC_IER + hw_p->hw_addr, hw_p->emac_ier); if (hw_p->first_init == 0) { /* * Connect interrupt service routines */ - irq_install_handler (VECNUM_ETH0 + (hw_p->devnum * 2), - (interrupt_handler_t *) enetInt, dev); + irq_install_handler(ETH_IRQ_NUM(hw_p->devnum), + (interrupt_handler_t *) enetInt, dev); } mtmsr (msr); /* enable interrupts again */ @@ -987,7 +1036,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) hw_p->bis = bis; hw_p->first_init = 1; - return (1); + return 0; } @@ -1015,6 +1064,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, /* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */ memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len); + flush_dcache_range((u32)hw_p->txbuf_ptr, (u32)hw_p->txbuf_ptr + len); /*-----------------------------------------------------------------------+ * set TX Buffer busy, and send it @@ -1030,8 +1080,8 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, __asm__ volatile ("eieio"); - out32 (EMAC_TXM0 + hw_p->hw_addr, - in32 (EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0); + out_be32((void *)EMAC_TXM0 + hw_p->hw_addr, + in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0); #ifdef INFO_4XX_ENET hw_p->stats.pkts_tx++; #endif @@ -1041,7 +1091,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, *-----------------------------------------------------------------------*/ time_start = get_timer (0); while (1) { - temp_txm0 = in32 (EMAC_TXM0 + hw_p->hw_addr); + temp_txm0 = in_be32((void *)EMAC_TXM0 + hw_p->hw_addr); /* loop until either TINT turns on or 3 seconds elapse */ if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) { /* transmit is done, so now check for errors @@ -1059,7 +1109,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, } -#if defined (CONFIG_440) +#if defined (CONFIG_440) || defined(CONFIG_405EX) #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) /* @@ -1073,7 +1123,8 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, #define UIC0SR uic0sr #endif -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) #define UICMSR_ETHX uic0msr #define UICSR_ETHX uic0sr #else @@ -1149,7 +1200,7 @@ int enetInt (struct eth_device *dev) /* port by port dispatch of emac interrupts */ if (hw_p->devnum == 0) { if (UIC_ETH0 & my_uicmsr_ethx) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); + emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; @@ -1168,7 +1219,7 @@ int enetInt (struct eth_device *dev) #if !defined(CONFIG_440SP) if (hw_p->devnum == 1) { if (UIC_ETH1 & my_uicmsr_ethx) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); + emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; @@ -1186,7 +1237,7 @@ int enetInt (struct eth_device *dev) #if defined (CONFIG_440GX) if (hw_p->devnum == 2) { if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); + emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; @@ -1204,7 +1255,7 @@ int enetInt (struct eth_device *dev) if (hw_p->devnum == 3) { if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); + emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; @@ -1316,7 +1367,7 @@ int enetInt (struct eth_device *dev) /* port by port dispatch of emac interrupts */ if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */ - emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); + emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; @@ -1390,7 +1441,7 @@ static void emac_err (struct eth_device *dev, unsigned long isr) EMAC_4XX_HW_PST hw_p = dev->priv; printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr); - out32 (EMAC_ISR + hw_p->hw_addr, isr); + out_be32((void *)EMAC_ISR + hw_p->hw_addr, isr); } /*-----------------------------------------------------------------------------+ @@ -1513,6 +1564,9 @@ static int ppc_4xx_eth_rx (struct eth_device *dev) /* Pass the packet up to the protocol layers. */ /* NetReceive(NetRxPackets[rxIdx], length - 4); */ /* NetReceive(NetRxPackets[i], length); */ + invalidate_dcache_range((u32)hw_p->rx[user_index].data_ptr, + (u32)hw_p->rx[user_index].data_ptr + + length - 4); NetReceive (NetRxPackets[user_index], length - 4); /* Free Recv Buffer */ hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY; @@ -1601,7 +1655,11 @@ int ppc_4xx_eth_initialize (bd_t * bis) bis->bi_phynum[3] = CONFIG_PHY3_ADDR; bis->bi_phymode[2] = 2; bis->bi_phymode[3] = 2; +#endif +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) ppc_4xx_eth_setup_bridge(0, bis); #endif @@ -1649,7 +1707,9 @@ int ppc_4xx_eth_initialize (bd_t * bis) if (0 == virgin) { /* set the MAL IER ??? names may change with new spec ??? */ -#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#if defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) mal_ier = MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE | MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ; @@ -1695,7 +1755,8 @@ int ppc_4xx_eth_initialize (bd_t * bis) #endif #endif } /* end for each supported device */ - return (1); + + return 0; } #if !defined(CONFIG_NET_MULTI) diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/4xx_pci.c index 282e7a1..a5b9690 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/4xx_pci.c @@ -72,7 +72,7 @@ #include <common.h> #include <command.h> #if !defined(CONFIG_440) -#include <405gp_pci.h> +#include <asm/4xx_pci.h> #endif #include <asm/processor.h> #include <pci.h> @@ -339,7 +339,7 @@ void pci_405gp_init(struct pci_controller *hose) } /* - * drivers/pci.c skips every host bridge but the 405GP since it could + * drivers/pci/pci.c skips every host bridge but the 405GP since it could * be set as an Adapter. * * I (Andrew May) don't know what we should do here, but I don't want @@ -592,4 +592,15 @@ void pci_init_board(void) } #endif /* CONFIG_440 */ + +#if defined(CONFIG_405EX) +void pci_init_board(void) +{ +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + pcie_setup_hoses(0); +} +#endif /* CONFIG_405EX */ + #endif /* CONFIG_PCI */ diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/4xx_pcie.c index 3eac0ae..3af9862 100644 --- a/cpu/ppc4xx/440spe_pcie.c +++ b/cpu/ppc4xx/4xx_pcie.c @@ -20,15 +20,21 @@ * */ +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + #include <asm/processor.h> #include <asm-ppc/io.h> #include <ppc4xx.h> #include <common.h> #include <pci.h> -#if defined(CONFIG_440SPE) && defined(CONFIG_PCI) +#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX)) && \ + defined(CONFIG_PCI) -#include "440spe_pcie.h" +#include <asm/4xx_pcie.h> enum { PTYPE_ENDPOINT = 0x0, @@ -40,6 +46,20 @@ enum { LNKW_X8 = 0x8 }; +static int validate_endpoint(struct pci_controller *hose) +{ + if (hose->cfg_data == (u8 *)CFG_PCIE0_CFGBASE) + return (is_end_point(0)); + else if (hose->cfg_data == (u8 *)CFG_PCIE1_CFGBASE) + return (is_end_point(1)); +#if CFG_PCIE_NR_PORTS > 2 + else if (hose->cfg_data == (u8 *)CFG_PCIE2_CFGBASE) + return (is_end_point(2)); +#endif + + return 0; +} + static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn) { u8 *base = (u8*)hose->cfg_data; @@ -50,8 +70,10 @@ static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn) base = (u8*)CFG_PCIE0_XCFGBASE; if (hose->cfg_data == (u8*)CFG_PCIE1_CFGBASE) base = (u8*)CFG_PCIE1_XCFGBASE; +#if CFG_PCIE_NR_PORTS > 2 if (hose->cfg_data == (u8*)CFG_PCIE2_CFGBASE) base = (u8*)CFG_PCIE2_XCFGBASE; +#endif } return base; @@ -63,8 +85,10 @@ static void pcie_dmer_disable(void) mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA); mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE), mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA); +#if CFG_PCIE_NR_PORTS > 2 mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE), mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA); +#endif } static void pcie_dmer_enable(void) @@ -73,8 +97,10 @@ static void pcie_dmer_enable(void) mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA); mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE), mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA); +#if CFG_PCIE_NR_PORTS > 2 mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE), mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA); +#endif } static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, @@ -83,6 +109,9 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, u8 *address; *val = 0; + if (validate_endpoint(hose)) + return 0; /* No upstream config access */ + /* * Bus numbers are relative to hose->first_busno */ @@ -115,6 +144,7 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, */ pcie_dmer_disable (); + debug("%s: cfg_data=%08x offset=%08x\n", __func__, hose->cfg_data, offset); switch (len) { case 1: *val = in_8(hose->cfg_data + offset); @@ -137,6 +167,9 @@ static int pcie_write_config(struct pci_controller *hose, unsigned int devfn, u8 *address; + if (validate_endpoint(hose)) + return 0; /* No upstream config access */ + /* * Bus numbers are relative to hose->first_busno */ @@ -222,7 +255,8 @@ int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val); } -static void ppc440spe_setup_utl(u32 port) { +#if defined(CONFIG_440SPE) +static void ppc4xx_setup_utl(u32 port) { volatile void *utl_base = NULL; @@ -333,7 +367,7 @@ static int check_error(void) /* * Initialize PCI Express core */ -int ppc440spe_init_pcie(void) +int ppc4xx_init_pcie(void) { int time_out = 20; @@ -366,13 +400,223 @@ int ppc440spe_init_pcie(void) } return 0; } +#else +static void ppc4xx_setup_utl(u32 port) +{ + u32 utl_base; + + /* + * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000); + mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CFG_PCIE0_UTLBASE); + mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */ + mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0); + break; + + case 1: + mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000); + mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CFG_PCIE1_UTLBASE); + mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */ + mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0); + + break; + } + utl_base = (port==0) ? CFG_PCIE0_UTLBASE : CFG_PCIE1_UTLBASE; + + /* + * Set buffer allocations and then assert VRB and TXE. + */ + out_be32((u32 *)(utl_base + PEUTL_OUTTR), 0x02000000); + out_be32((u32 *)(utl_base + PEUTL_INTR), 0x02000000); + out_be32((u32 *)(utl_base + PEUTL_OPDBSZ), 0x04000000); + out_be32((u32 *)(utl_base + PEUTL_PBBSZ), 0x21000000); + out_be32((u32 *)(utl_base + PEUTL_IPHBSZ), 0x02000000); + out_be32((u32 *)(utl_base + PEUTL_IPDBSZ), 0x04000000); + out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000); + out_be32((u32 *)(utl_base + PEUTL_PCTL), 0x80800066); + + out_be32((u32 *)(utl_base + PEUTL_PBCTL), 0x0800000c); + out_be32((u32 *)(utl_base + PEUTL_RCSTA), + in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000); +} + +int ppc4xx_init_pcie(void) +{ + /* + * Nothing to do on 405EX + */ + return 0; +} +#endif /* - * Yucca board as End point and root point setup + * Board-specific pcie initialization + * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed + */ + +/* + * Initialize various parts of the PCI Express core for our port: + * + * - Set as a root port and enable max width + * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). + * - Set up UTL configuration. + * - Increase SERDES drive strength to levels suggested by AMCC. + * - De-assert RSTPYN, RSTDL and RSTGU. + * + * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it + * with default setting 0x11310000. The register has new fields, + * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core + * hang. + */ +#if defined(CONFIG_440SPE) +int __ppc4xx_init_pcie_port_hw(int port, int rootport) +{ + u32 val = 1 << 24; + u32 utlset1; + + if (rootport) { + val = PTYPE_ROOT_PORT << 20; + utlset1 = 0x21222222; + } else { + val = PTYPE_LEGACY_ENDPOINT << 20; + utlset1 = 0x20222222; + } + + if (port == 0) + val |= LNKW_X8 << 12; + else + val |= LNKW_X4 << 12; + + SDR_WRITE(SDRN_PESDR_DLPSET(port), val); + SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1); + if (!ppc440spe_revB()) + SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000); + SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000); + SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000); + SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000); + SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000); + if (port == 0) { + SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); + SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); + } + SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) & + ~(1 << 24 | 1 << 16)) | 1 << 12); + + return 0; +} +#endif /* CONFIG_440SPE */ + +#if defined(CONFIG_405EX) +int __ppc4xx_init_pcie_port_hw(int port, int rootport) +{ + u32 val; + + if (rootport) + val = 0x00401000; + else + val = 0x00101000; + + SDR_WRITE(SDRN_PESDR_DLPSET(port), val); + SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000); + SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000); + SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000); + SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003); + + /* Assert the PE0_PHY reset */ + SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000); + udelay(1000); + + /* deassert the PE0_hotreset */ + if (is_end_point(port)) + SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000); + else + SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000); + + /* poll for phy !reset */ + while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000)) + ; + + /* deassert the PE0_gpl_utl_reset */ + SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000); + + if (port == 0) + mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000); /* guarded on */ + else + mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000); /* guarded on */ + + return 0; +} +#endif /* CONFIG_405EX */ + +int ppc4xx_init_pcie_port_hw(int port, int rootport) +__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw"))); + +/* + * We map PCI Express configuration access into the 512MB regions + * + * NOTICE: revB is very strict about PLB real addressess and ranges to + * be mapped for config space; it seems to only work with d_nnnn_nnnn + * range (hangs the core upon config transaction attempts when set + * otherwise) while revA uses c_nnnn_nnnn. + * + * For revA: + * PCIE0: 0xc_4000_0000 + * PCIE1: 0xc_8000_0000 + * PCIE2: 0xc_c000_0000 + * + * For revB: + * PCIE0: 0xd_0000_0000 + * PCIE1: 0xd_2000_0000 + * PCIE2: 0xd_4000_0000 + * + * For 405EX: + * PCIE0: 0xa000_0000 + * PCIE1: 0xc000_0000 + */ +static inline u64 ppc4xx_get_cfgaddr(int port) +{ +#if defined(CONFIG_405EX) + if (port == 0) + return (u64)CFG_PCIE0_CFGBASE; + else + return (u64)CFG_PCIE1_CFGBASE; +#endif +#if defined(CONFIG_440SPE) + if (ppc440spe_revB()) { + switch (port) { + default: /* to satisfy compiler */ + case 0: + return 0x0000000d00000000ULL; + case 1: + return 0x0000000d20000000ULL; + case 2: + return 0x0000000d40000000ULL; + } + } else { + switch (port) { + default: /* to satisfy compiler */ + case 0: + return 0x0000000c40000000ULL; + case 1: + return 0x0000000c80000000ULL; + case 2: + return 0x0000000cc0000000ULL; + } + } +#endif +} + +/* + * 4xx boards as end point and root point setup * and * testing inbound and out bound windows * - * YUCCA board can be plugged into another yucca board or you can get PCI-E + * 4xx boards can be plugged into another 4xx boards or you can get PCI-E * cable which can be used to setup loop back from one port to another port. * Please rememeber that unless there is a endpoint plugged in to root port it * will not initialize. It is the same in case of endpoint , unless there is @@ -386,110 +630,47 @@ int ppc440spe_init_pcie(void) * /proc/bus/pci/devices. Where you can see the configuration registers * of end point device attached to the port. * - * Enpoint cofiguration can be verified by connecting Yucca board to any - * host or another yucca board. Then try to scan the device. In case of + * Enpoint cofiguration can be verified by connecting 4xx board to any + * host or another 4xx board. Then try to scan the device. In case of * linux use "lspci" or appripriate os command. * - * How do I verify the inbound and out bound windows ?(yucca to yucca) + * How do I verify the inbound and out bound windows ? (4xx to 4xx) * in this configuration inbound and outbound windows are setup to access * sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address * is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000, * This is waere your POM(PLB out bound memory window) mapped. then - * read the data from other yucca board's u-boot prompt at address + * read the data from other 4xx board's u-boot prompt at address * 0x9000 0000(SRAM). Data should match. * In case of inbound , write data to u-boot command prompt at 0xb000 0000 * which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check * data at 0x9000 0000(SRAM).Data should match. */ -int ppc440spe_init_pcie_rootport(int port) +int ppc4xx_init_pcie_port(int port, int rootport) { static int core_init; volatile u32 val = 0; int attempts; + u64 addr; + u32 low, high; if (!core_init) { - ++core_init; - if (ppc440spe_init_pcie()) + if (ppc4xx_init_pcie()) return -1; + ++core_init; } /* - * Initialize various parts of the PCI Express core for our port: - * - * - Set as a root port and enable max width - * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). - * - Set up UTL configuration. - * - Increase SERDES drive strength to levels suggested by AMCC. - * - De-assert RSTPYN, RSTDL and RSTGU. - * - * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with - * default setting 0x11310000. The register has new fields, - * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core - * hang. + * Initialize various parts of the PCI Express core for our port */ - switch (port) { - case 0: - SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12); - - SDR_WRITE(PESDR0_UTLSET1, 0x21222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR0_UTLSET2, 0x11000000); - SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); - SDR_WRITE(PESDR0_RCSSET, - (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; + ppc4xx_init_pcie_port_hw(port, rootport); - case 1: - SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); - SDR_WRITE(PESDR1_UTLSET1, 0x21222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR1_UTLSET2, 0x11000000); - SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR1_RCSSET, - (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; - - case 2: - SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); - SDR_WRITE(PESDR2_UTLSET1, 0x21222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR2_UTLSET2, 0x11000000); - SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR2_RCSSET, - (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; - } /* * Notice: the following delay has critical impact on device * initialization - if too short (<50ms) the link doesn't get up. */ mdelay(100); - switch (port) { - case 0: - val = SDR_READ(PESDR0_RCSSTS); - break; - case 1: - val = SDR_READ(PESDR1_RCSSTS); - break; - case 2: - val = SDR_READ(PESDR2_RCSSTS); - break; - } - + val = SDR_READ(SDRN_PESDR_RCSSTS(port)); if (val & (1 << 20)) { printf("PCIE%d: PGRST failed %08x\n", port, val); return -1; @@ -498,18 +679,7 @@ int ppc440spe_init_pcie_rootport(int port) /* * Verify link is up */ - val = 0; - switch (port) { - case 0: - val = SDR_READ(PESDR0_LOOP); - break; - case 1: - val = SDR_READ(PESDR1_LOOP); - break; - case 2: - val = SDR_READ(PESDR2_LOOP); - break; - } + val = SDR_READ(SDRN_PESDR_LOOP(port)); if (!(val & 0x00001000)) { printf("PCIE%d: link is not up.\n", port); return -1; @@ -520,331 +690,75 @@ int ppc440spe_init_pcie_rootport(int port) * We use default settings for revB chip. */ if (!ppc440spe_revB()) - ppc440spe_setup_utl(port); + ppc4xx_setup_utl(port); /* * We map PCI Express configuration access into the 512MB regions - * - * NOTICE: revB is very strict about PLB real addressess and ranges to - * be mapped for config space; it seems to only work with d_nnnn_nnnn - * range (hangs the core upon config transaction attempts when set - * otherwise) while revA uses c_nnnn_nnnn. - * - * For revA: - * PCIE0: 0xc_4000_0000 - * PCIE1: 0xc_8000_0000 - * PCIE2: 0xc_c000_0000 - * - * For revB: - * PCIE0: 0xd_0000_0000 - * PCIE1: 0xd_2000_0000 - * PCIE2: 0xd_4000_0000 */ + addr = ppc4xx_get_cfgaddr(port); + low = U64_TO_U32_LOW(addr); + high = U64_TO_U32_HIGH(addr); switch (port) { case 0: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000); - } else { - /* revA */ - mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); - } + mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), high); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), low); mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ break; - case 1: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000); - } else { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); - } + mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), high); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), low); mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ break; - +#if CFG_PCIE_NR_PORTS > 2 case 2: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000); - } else { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); - } + mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), high); + mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), low); mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ break; +#endif } /* * Check for VC0 active and assert RDY. */ attempts = 10; - switch (port) { - case 0: - while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE0: VC0 not active\n"); - return -1; - } - mdelay(1000); - } - SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); - break; - case 1: - while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE1: VC0 not active\n"); - return -1; - } - mdelay(1000); - } - - SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); - break; - case 2: - while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE2: VC0 not active\n"); - return -1; - } - mdelay(1000); + while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 16))) { + if (!(attempts--)) { + printf("PCIE%d: VC0 not active\n", port); + return -1; } - - SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); - break; + mdelay(1000); } + SDR_WRITE(SDRN_PESDR_RCSSET(port), + SDR_READ(SDRN_PESDR_RCSSET(port)) | 1 << 20); mdelay(100); return 0; } -int ppc440spe_init_pcie_endport(int port) +int ppc4xx_init_pcie_rootport(int port) { - static int core_init; - volatile u32 val = 0; - int attempts; - - if (!core_init) { - ++core_init; - if (ppc440spe_init_pcie()) - return -1; - } - - /* - * Initialize various parts of the PCI Express core for our port: - * - * - Set as a end port and enable max width - * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). - * - Set up UTL configuration. - * - Increase SERDES drive strength to levels suggested by AMCC. - * - De-assert RSTPYN, RSTDL and RSTGU. - * - * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with - * default setting 0x11310000. The register has new fields, - * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core - * hang. - */ - switch (port) { - case 0: - SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X8 << 12); - - SDR_WRITE(PESDR0_UTLSET1, 0x20222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR0_UTLSET2, 0x11000000); - SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); - SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); - SDR_WRITE(PESDR0_RCSSET, - (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; - - case 1: - SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); - SDR_WRITE(PESDR1_UTLSET1, 0x20222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR1_UTLSET2, 0x11000000); - SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR1_RCSSET, - (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; - - case 2: - SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); - SDR_WRITE(PESDR2_UTLSET1, 0x20222222); - if (!ppc440spe_revB()) - SDR_WRITE(PESDR2_UTLSET2, 0x11000000); - SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); - SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); - SDR_WRITE(PESDR2_RCSSET, - (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); - break; - } - /* - * Notice: the following delay has critical impact on device - * initialization - if too short (<50ms) the link doesn't get up. - */ - mdelay(100); - - switch (port) { - case 0: val = SDR_READ(PESDR0_RCSSTS); break; - case 1: val = SDR_READ(PESDR1_RCSSTS); break; - case 2: val = SDR_READ(PESDR2_RCSSTS); break; - } - - if (val & (1 << 20)) { - printf("PCIE%d: PGRST failed %08x\n", port, val); - return -1; - } - - /* - * Verify link is up - */ - val = 0; - switch (port) - { - case 0: - val = SDR_READ(PESDR0_LOOP); - break; - case 1: - val = SDR_READ(PESDR1_LOOP); - break; - case 2: - val = SDR_READ(PESDR2_LOOP); - break; - } - if (!(val & 0x00001000)) { - printf("PCIE%d: link is not up.\n", port); - return -1; - } - - /* - * Setup UTL registers - but only on revA! - * We use default settings for revB chip. - */ - if (!ppc440spe_revB()) - ppc440spe_setup_utl(port); - - /* - * We map PCI Express configuration access into the 512MB regions - * - * NOTICE: revB is very strict about PLB real addressess and ranges to - * be mapped for config space; it seems to only work with d_nnnn_nnnn - * range (hangs the core upon config transaction attempts when set - * otherwise) while revA uses c_nnnn_nnnn. - * - * For revA: - * PCIE0: 0xc_4000_0000 - * PCIE1: 0xc_8000_0000 - * PCIE2: 0xc_c000_0000 - * - * For revB: - * PCIE0: 0xd_0000_0000 - * PCIE1: 0xd_2000_0000 - * PCIE2: 0xd_4000_0000 - */ - switch (port) { - case 0: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000); - } else { - /* revA */ - mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); - } - mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ - break; - - case 1: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000); - } else { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); - } - mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ - break; - - case 2: - if (ppc440spe_revB()) { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000); - } else { - mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); - mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); - } - mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ - break; - } - - /* - * Check for VC0 active and assert RDY. - */ - attempts = 10; - switch (port) { - case 0: - while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE0: VC0 not active\n"); - return -1; - } - mdelay(1000); - } - SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); - break; - case 1: - while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE1: VC0 not active\n"); - return -1; - } - mdelay(1000); - } - - SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); - break; - case 2: - while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) { - if (!(attempts--)) { - printf("PCIE2: VC0 not active\n"); - return -1; - } - mdelay(1000); - } - - SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); - break; - } - mdelay(100); + return ppc4xx_init_pcie_port(port, 1); +} - return 0; +int ppc4xx_init_pcie_endport(int port) +{ + return ppc4xx_init_pcie_port(port, 0); } -void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) +void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port) { volatile void *mbase = NULL; volatile void *rmbase = NULL; pci_set_ops(hose, - pcie_read_config_byte, - pcie_read_config_word, - pcie_read_config_dword, - pcie_write_config_byte, - pcie_write_config_word, - pcie_write_config_dword); + pcie_read_config_byte, + pcie_read_config_word, + pcie_read_config_dword, + pcie_write_config_byte, + pcie_write_config_word, + pcie_write_config_dword); switch (port) { case 0: @@ -857,11 +771,13 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) rmbase = (u32 *)CFG_PCIE1_CFGBASE; hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; break; +#if CFG_PCIE_NR_PORTS > 2 case 2: mbase = (u32 *)CFG_PCIE2_XCFGBASE; rmbase = (u32 *)CFG_PCIE2_CFGBASE; hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; break; +#endif } /* @@ -878,33 +794,53 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) * subregions and to enable the outbound translation. */ out_le32(mbase + PECFG_POM0LAH, 0x00000000); - out_le32(mbase + PECFG_POM0LAL, 0x00000000); + out_le32(mbase + PECFG_POM0LAL, CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); + debug("PECFG_POM0LA=%08x.%08x\n", in_le32(mbase + PECFG_POM0LAH), + in_le32(mbase + PECFG_POM0LAL)); switch (port) { case 0: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), - ~(CFG_PCIE_MEMSIZE - 1) | 3); + ~(CFG_PCIE_MEMSIZE - 1) | 3); + debug("0:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", + mfdcr(DCRN_PEGPL_OMR1BAH(PCIE0)), + mfdcr(DCRN_PEGPL_OMR1BAL(PCIE0)), + mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE0)), + mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE0))); break; case 1: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), (CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE)); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), - ~(CFG_PCIE_MEMSIZE - 1) | 3); - break; + ~(CFG_PCIE_MEMSIZE - 1) | 3); + debug("1:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", + mfdcr(DCRN_PEGPL_OMR1BAH(PCIE1)), + mfdcr(DCRN_PEGPL_OMR1BAL(PCIE1)), + mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE1)), + mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE1))); + break; +#if CFG_PCIE_NR_PORTS > 2 case 2: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), (CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE)); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), - ~(CFG_PCIE_MEMSIZE - 1) | 3); + ~(CFG_PCIE_MEMSIZE - 1) | 3); + debug("2:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n", + mfdcr(DCRN_PEGPL_OMR1BAH(PCIE2)), + mfdcr(DCRN_PEGPL_OMR1BAL(PCIE2)), + mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE2)), + mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE2))); break; +#endif } /* Set up 16GB inbound memory window at 0 */ @@ -917,41 +853,26 @@ void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) out_le32(mbase + PECFG_PIM01SAL, 0x00000000); out_le32(mbase + PECFG_PIM0LAL, 0); out_le32(mbase + PECFG_PIM0LAH, 0); - out_le32(mbase + PECFG_PIM1LAL, 0x00000000); - out_le32(mbase + PECFG_PIM1LAH, 0x00000004); + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); + out_le32(mbase + PECFG_PIM1LAH, 0x00000004); out_le32(mbase + PECFG_PIMEN, 0x1); /* Enable I/O, Mem, and Busmaster cycles */ out_le16((u16 *)(mbase + PCI_COMMAND), in_le16((u16 *)(mbase + PCI_COMMAND)) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - printf("PCIE:%d successfully set as rootpoint\n",port); /* Set Device and Vendor Id */ - switch (port) { - case 0: - out_le16(mbase + 0x200, 0xaaa0); - out_le16(mbase + 0x202, 0xbed0); - break; - case 1: - out_le16(mbase + 0x200, 0xaaa1); - out_le16(mbase + 0x202, 0xbed1); - break; - case 2: - out_le16(mbase + 0x200, 0xaaa2); - out_le16(mbase + 0x202, 0xbed2); - break; - default: - out_le16(mbase + 0x200, 0xaaa3); - out_le16(mbase + 0x202, 0xbed3); - } + out_le16(mbase + 0x200, 0xaaa0 + port); + out_le16(mbase + 0x202, 0xbed0 + port); /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ out_le32(mbase + 0x208, 0x06040001); + printf("PCIE%d: successfully set as root-complex\n", port); } -int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port) +int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port) { volatile void *mbase = NULL; int attempts = 0; @@ -973,10 +894,12 @@ int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port) mbase = (u32 *)CFG_PCIE1_XCFGBASE; hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; break; +#if defined(CFG_PCIE2_CFGBASE) case 2: mbase = (u32 *)CFG_PCIE2_XCFGBASE; hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; break; +#endif } /* @@ -990,77 +913,73 @@ int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port) switch (port) { case 0: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), - ~(CFG_PCIE_MEMSIZE - 1) | 3); + ~(CFG_PCIE_MEMSIZE - 1) | 3); break; case 1: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), (CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE)); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), - ~(CFG_PCIE_MEMSIZE - 1) | 3); + ~(CFG_PCIE_MEMSIZE - 1) | 3); break; +#if CFG_PCIE_NR_PORTS > 2 case 2: - mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); - mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), (CFG_PCIE_MEMBASE + - port * CFG_PCIE_MEMSIZE)); + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CFG_PCIE_ADDR_HIGH); + mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE); mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), - ~(CFG_PCIE_MEMSIZE - 1) | 3); + ~(CFG_PCIE_MEMSIZE - 1) | 3); break; +#endif } - /* Set up 16GB inbound memory window at 0 */ + /* Set up 64MB inbound memory window at 0 */ out_le32(mbase + PCI_BASE_ADDRESS_0, 0); out_le32(mbase + PCI_BASE_ADDRESS_1, 0); - out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); - out_le32(mbase + PECFG_BAR0LMPA, 0); - out_le32(mbase + PECFG_PIM0LAL, 0x00000000); - out_le32(mbase + PECFG_PIM0LAH, 0x00000004); /* pointing to SRAM */ + + out_le32(mbase + PECFG_PIM01SAH, 0xffffffff); + out_le32(mbase + PECFG_PIM01SAL, 0xfc000000); + + /* Setup BAR0 */ + out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffff); + out_le32(mbase + PECFG_BAR0LMPA, 0xfc000000 | PCI_BASE_ADDRESS_MEM_TYPE_64); + + /* Disable BAR1 & BAR2 */ + out_le32(mbase + PECFG_BAR1MPA, 0); + out_le32(mbase + PECFG_BAR2HMPA, 0); + out_le32(mbase + PECFG_BAR2LMPA, 0); + + out_le32(mbase + PECFG_PIM0LAL, U64_TO_U32_LOW(CFG_PCIE_INBOUND_BASE)); + out_le32(mbase + PECFG_PIM0LAH, U64_TO_U32_HIGH(CFG_PCIE_INBOUND_BASE)); out_le32(mbase + PECFG_PIMEN, 0x1); /* Enable I/O, Mem, and Busmaster cycles */ out_le16((u16 *)(mbase + PCI_COMMAND), - in_le16((u16 *)(mbase + PCI_COMMAND)) | - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - out_le16(mbase + 0x200,0xcaad); /* Setting vendor ID */ - out_le16(mbase + 0x202,0xfeed); /* Setting device ID */ + in_le16((u16 *)(mbase + PCI_COMMAND)) | + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + out_le16(mbase + 0x200, 0xcaad); /* Setting vendor ID */ + out_le16(mbase + 0x202, 0xfeed); /* Setting device ID */ + + /* Set Class Code to Processor/PPC */ + out_le32(mbase + 0x208, 0x0b200001); + attempts = 10; - switch (port) { - case 0: - while (!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) { - if (!(attempts--)) { - printf("PCIE0: BMEN is not active\n"); - return -1; - } - mdelay(1000); - } - break; - case 1: - while (!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) { - if (!(attempts--)) { - printf("PCIE1: BMEN is not active\n"); - return -1; - } - mdelay(1000); - } - break; - case 2: - while (!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) { - if (!(attempts--)) { - printf("PCIE2: BMEN is not active\n"); - return -1; - } - mdelay(1000); + while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 8))) { + if (!(attempts--)) { + printf("PCIE%d: BME not active\n", port); + return -1; } - break; + mdelay(1000); } - printf("PCIE:%d successfully set as endpoint\n",port); + + printf("PCIE%d: successfully set as endpoint\n", port); return 0; } diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/4xx_uart.c index 60712b1..3d1124e 100644 --- a/cpu/ppc4xx/serial.c +++ b/cpu/ppc4xx/4xx_uart.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ -/*------------------------------------------------------------------------------+ */ + /* * This source code has been made available to you by IBM on an AS-IS * basis. Anyone receiving this source is licensed under IBM @@ -40,16 +40,13 @@ * COPYRIGHT I B M CORPORATION 1995 * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M */ -/*------------------------------------------------------------------------------- */ -/* - * Travis Sawyer 15 September 2004 - * Added CONFIG_SERIAL_MULTI support - */ + #include <common.h> #include <commproc.h> #include <asm/processor.h> +#include <asm/io.h> #include <watchdog.h> -#include "vecnum.h" +#include <asm/ppc4xx-intvec.h> #ifdef CONFIG_SERIAL_MULTI #include <serial.h> @@ -61,212 +58,9 @@ DECLARE_GLOBAL_DATA_PTR; -/*****************************************************************************/ -#ifdef CONFIG_IOP480 - -#define SPU_BASE 0x40000000 - -#define spu_LineStat_rc 0x00 /* Line Status Register (Read/Clear) */ -#define spu_LineStat_w 0x04 /* Line Status Register (Set) */ -#define spu_Handshk_rc 0x08 /* Handshake Status Register (Read/Clear) */ -#define spu_Handshk_w 0x0c /* Handshake Status Register (Set) */ -#define spu_BRateDivh 0x10 /* Baud rate divisor high */ -#define spu_BRateDivl 0x14 /* Baud rate divisor low */ -#define spu_CtlReg 0x18 /* Control Register */ -#define spu_RxCmd 0x1c /* Rx Command Register */ -#define spu_TxCmd 0x20 /* Tx Command Register */ -#define spu_RxBuff 0x24 /* Rx data buffer */ -#define spu_TxBuff 0x24 /* Tx data buffer */ - -/*-----------------------------------------------------------------------------+ - | Line Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncLSRport1 0x40000000 -#define asyncLSRport1set 0x40000004 -#define asyncLSRDataReady 0x80 -#define asyncLSRFramingError 0x40 -#define asyncLSROverrunError 0x20 -#define asyncLSRParityError 0x10 -#define asyncLSRBreakInterrupt 0x08 -#define asyncLSRTxHoldEmpty 0x04 -#define asyncLSRTxShiftEmpty 0x02 - -/*-----------------------------------------------------------------------------+ - | Handshake Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncHSRport1 0x40000008 -#define asyncHSRport1set 0x4000000c -#define asyncHSRDsr 0x80 -#define asyncLSRCts 0x40 - -/*-----------------------------------------------------------------------------+ - | Control Register. - +-----------------------------------------------------------------------------*/ -#define asyncCRport1 0x40000018 -#define asyncCRNormal 0x00 -#define asyncCRLoopback 0x40 -#define asyncCRAutoEcho 0x80 -#define asyncCRDtr 0x20 -#define asyncCRRts 0x10 -#define asyncCRWordLength7 0x00 -#define asyncCRWordLength8 0x08 -#define asyncCRParityDisable 0x00 -#define asyncCRParityEnable 0x04 -#define asyncCREvenParity 0x00 -#define asyncCROddParity 0x02 -#define asyncCRStopBitsOne 0x00 -#define asyncCRStopBitsTwo 0x01 -#define asyncCRDisableDtrRts 0x00 - -/*-----------------------------------------------------------------------------+ - | Receiver Command Register. - +-----------------------------------------------------------------------------*/ -#define asyncRCRport1 0x4000001c -#define asyncRCRDisable 0x00 -#define asyncRCREnable 0x80 -#define asyncRCRIntDisable 0x00 -#define asyncRCRIntEnabled 0x20 -#define asyncRCRDMACh2 0x40 -#define asyncRCRDMACh3 0x60 -#define asyncRCRErrorInt 0x10 -#define asyncRCRPauseEnable 0x08 - -/*-----------------------------------------------------------------------------+ - | Transmitter Command Register. - +-----------------------------------------------------------------------------*/ -#define asyncTCRport1 0x40000020 -#define asyncTCRDisable 0x00 -#define asyncTCREnable 0x80 -#define asyncTCRIntDisable 0x00 -#define asyncTCRIntEnabled 0x20 -#define asyncTCRDMACh2 0x40 -#define asyncTCRDMACh3 0x60 -#define asyncTCRTxEmpty 0x10 -#define asyncTCRErrorInt 0x08 -#define asyncTCRStopPause 0x04 -#define asyncTCRBreakGen 0x02 - -/*-----------------------------------------------------------------------------+ - | Miscellanies defines. - +-----------------------------------------------------------------------------*/ -#define asyncTxBufferport1 0x40000024 -#define asyncRxBufferport1 0x40000024 -#define asyncDLABLsbport1 0x40000014 -#define asyncDLABMsbport1 0x40000010 -#define asyncXOFFchar 0x13 -#define asyncXONchar 0x11 - -/* - * Minimal serial functions needed to use one of the SMC ports - * as serial console interface. - */ - -int serial_init (void) -{ - volatile char val; - unsigned short br_reg; - - br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); - - /* - * Init onboard UART - */ - out8 (SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */ - out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ - out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */ - out8 (SPU_BASE + spu_CtlReg, 0x08); /* Set 8 bits, no parity and 1 stop bit */ - out8 (SPU_BASE + spu_RxCmd, 0xb0); /* Enable Rx */ - out8 (SPU_BASE + spu_TxCmd, 0x9c); /* Enable Tx */ - out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - val = in8 (SPU_BASE + spu_RxBuff); /* Dummy read, to clear receiver */ - - return (0); -} - -void serial_setbrg (void) -{ - unsigned short br_reg; - - br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); - - out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ - out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */ -} - -void serial_putc (const char c) -{ - if (c == '\n') - serial_putc ('\r'); - - /* load status from handshake register */ - if (in8 (SPU_BASE + spu_Handshk_rc) != 00) - out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - - out8 (SPU_BASE + spu_TxBuff, c); /* Put char */ - - while ((in8 (SPU_BASE + spu_LineStat_rc) & 04) != 04) { - if (in8 (SPU_BASE + spu_Handshk_rc) != 00) - out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ - } -} - -void serial_puts (const char *s) -{ - while (*s) { - serial_putc (*s++); - } -} - -int serial_getc () -{ - unsigned char status = 0; - - while (1) { - status = in8 (asyncLSRport1); - if ((status & asyncLSRDataReady) != 0x0) { - break; - } - if ((status & ( asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt )) != 0) { - (void) out8 (asyncLSRport1, - asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt ); - } - } - return (0x000000ff & (int) in8 (asyncRxBufferport1)); -} - -int serial_tstc () -{ - unsigned char status; - - status = in8 (asyncLSRport1); - if ((status & asyncLSRDataReady) != 0x0) { - return (1); - } - if ((status & ( asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt )) != 0) { - (void) out8 (asyncLSRport1, - asyncLSRFramingError | - asyncLSROverrunError | - asyncLSRParityError | - asyncLSRBreakInterrupt); - } - return 0; -} - -#endif /* CONFIG_IOP480 */ - -/*****************************************************************************/ #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440) + defined(CONFIG_405EX) || defined(CONFIG_440) #if defined(CONFIG_440) #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ @@ -318,6 +112,15 @@ int serial_tstc () #define UCR0_UDIV_POS 0 #define UCR1_UDIV_POS 8 #define UDIV_MAX 127 +#elif defined(CONFIG_405EX) +#define UART0_BASE 0xef600200 +#define UART1_BASE 0xef600300 +#define CR0_MASK 0x000000ff +#define CR0_EXTCLK_ENA 0x00800000 +#define CR0_UDIV_POS 0 +#define UDIV_SUBTRACT 0 +#define UART0_SDR sdr_uart0 +#define UART1_SDR sdr_uart1 #else /* CONFIG_405GP || CONFIG_405CR */ #define UART0_BASE 0xef600300 #define UART1_BASE 0xef600400 @@ -336,12 +139,6 @@ int serial_tstc () #define ACTING_UART1_BASE UART1_BASE #endif -#if defined(CONFIG_SERIAL_MULTI) -#define UART_BASE dev_base -#else -#define UART_BASE ACTING_UART0_BASE -#endif - #if defined(CONFIG_405EP) && defined(CFG_EXT_SERIAL_CLOCK) #error "External serial clock not supported on AMCC PPC405EP!" #endif @@ -362,7 +159,6 @@ int serial_tstc () /*-----------------------------------------------------------------------------+ | Line Status Register. +-----------------------------------------------------------------------------*/ -/*#define asyncLSRport1 ACTING_UART0_BASE+0x05 */ #define asyncLSRDataReady1 0x01 #define asyncLSROverrunError1 0x02 #define asyncLSRParityError1 0x04 @@ -372,12 +168,6 @@ int serial_tstc () #define asyncLSRTxShiftEmpty1 0x40 #define asyncLSRRxFifoError1 0x80 -/*-----------------------------------------------------------------------------+ - | Miscellanies defines. - +-----------------------------------------------------------------------------*/ -/*#define asyncTxBufferport1 ACTING_UART0_BASE+0x00 */ -/*#define asyncRxBufferport1 ACTING_UART0_BASE+0x00 */ - #ifdef CONFIG_SERIAL_SOFTWARE_FIFO /*-----------------------------------------------------------------------------+ | Fifo @@ -391,7 +181,36 @@ typedef struct { volatile static serial_buffer_t buf_info; #endif -#if defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLOCK) +static void serial_init_common(u32 base, u32 udiv, u16 bdiv) +{ + PPC4xx_SYS_INFO sys_info; + u8 val; + + get_sys_info(&sys_info); + + /* Correct UART frequency in bd-info struct now that + * the UART divisor is available + */ +#ifdef CFG_EXT_SERIAL_CLOCK + gd->uart_clk = CFG_EXT_SERIAL_CLOCK; +#else + gd->uart_clk = sys_info.freqUART / udiv; +#endif + + out_8((u8 *)base + UART_LCR, 0x80); /* set DLAB bit */ + out_8((u8 *)base + UART_DLL, bdiv); /* set baudrate divisor */ + out_8((u8 *)base + UART_DLM, bdiv >> 8); /* set baudrate divisor */ + out_8((u8 *)base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ + out_8((u8 *)base + UART_FCR, 0x00); /* disable FIFO */ + out_8((u8 *)base + UART_MCR, 0x00); /* no modem control DTR RTS */ + val = in_8((u8 *)base + UART_LSR); /* clear line status */ + val = in_8((u8 *)base + UART_RBR); /* read receive buffer */ + out_8((u8 *)base + UART_SCR, 0x00); /* set scratchpad */ + out_8((u8 *)base + UART_IER, 0x00); /* set interrupt enable reg */ +} + +#if (defined(CONFIG_440) || defined(CONFIG_405EX)) && \ + !defined(CFG_EXT_SERIAL_CLOCK) static void serial_divs (int baudrate, unsigned long *pudiv, unsigned short *pbdiv) { @@ -457,8 +276,8 @@ static void serial_divs (int baudrate, unsigned long *pudiv, get_sys_info(&sysinfo); plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ? - sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * sysinfo.pllFbkDiv) / - sysinfo.pllFwdDivB); + sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) * + sysinfo.pllFbkDiv) / sysinfo.pllFwdDivB); udiv = 256; /* Assume lowest possible serial clk */ div = plloutb / (16 * baudrate); /* total divisor */ umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */ @@ -496,16 +315,11 @@ static void serial_divs (int baudrate, unsigned long *pudiv, */ #if defined(CONFIG_440) -#if defined(CONFIG_SERIAL_MULTI) -int serial_init_dev (unsigned long dev_base) -#else -int serial_init(void) -#endif +int serial_init_dev(unsigned long base) { unsigned long reg; unsigned long udiv; unsigned short bdiv; - volatile char val; #ifdef CFG_EXT_SERIAL_CLOCK unsigned long tmp; #endif @@ -543,36 +357,46 @@ int serial_init(void) MTREG(UART3_SDR, reg); #endif - out8(UART_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8(UART_BASE + UART_DLL, bdiv); /* set baudrate divisor */ - out8(UART_BASE + UART_DLM, bdiv >> 8); /* set baudrate divisor */ - out8(UART_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8(UART_BASE + UART_FCR, 0x00); /* disable FIFO */ - out8(UART_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8(UART_BASE + UART_LSR); /* clear line status */ - val = in8(UART_BASE + UART_RBR); /* read receive buffer */ - out8(UART_BASE + UART_SCR, 0x00); /* set scratchpad */ - out8(UART_BASE + UART_IER, 0x00); /* set interrupt enable reg */ + serial_init_common(base, udiv, bdiv); return (0); } #else /* !defined(CONFIG_440) */ -#if defined(CONFIG_SERIAL_MULTI) -int serial_init_dev (unsigned long dev_base) -#else -int serial_init (void) -#endif +int serial_init_dev (unsigned long base) { unsigned long reg; unsigned long tmp; unsigned long clk; unsigned long udiv; unsigned short bdiv; - volatile char val; -#if defined(CONFIG_405EZ) +#ifdef CONFIG_405EX + clk = tmp = 0; + mfsdr(UART0_SDR, reg); + reg &= ~CR0_MASK; +#ifdef CFG_EXT_SERIAL_CLOCK + reg |= CR0_EXTCLK_ENA; + udiv = 1; + tmp = gd->baudrate * 16; + bdiv = (CFG_EXT_SERIAL_CLOCK + tmp / 2) / tmp; +#else + serial_divs(gd->baudrate, &udiv, &bdiv); +#endif + reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */ + + /* + * Configure input clock to baudrate generator for all + * available serial ports here + */ + mtsdr(UART0_SDR, reg); + +#if defined(UART1_SDR) + mtsdr(UART1_SDR, reg); +#endif + +#elif defined(CONFIG_405EZ) serial_divs(gd->baudrate, &udiv, &bdiv); clk = tmp = reg = 0; #else @@ -608,81 +432,44 @@ int serial_init (void) #endif /* CONFIG_405EP */ tmp = gd->baudrate * udiv * 16; bdiv = (clk + tmp / 2) / tmp; -#endif /* CONFIG_405EZ */ - - out8(UART_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8(UART_BASE + UART_DLL, bdiv); /* set baudrate divisor */ - out8(UART_BASE + UART_DLM, bdiv >> 8); /* set baudrate divisor */ - out8(UART_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8(UART_BASE + UART_FCR, 0x00); /* disable FIFO */ - out8(UART_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8(UART_BASE + UART_LSR); /* clear line status */ - val = in8(UART_BASE + UART_RBR); /* read receive buffer */ - out8(UART_BASE + UART_SCR, 0x00); /* set scratchpad */ - out8(UART_BASE + UART_IER, 0x00); /* set interrupt enable reg */ +#endif /* CONFIG_405EX */ + + serial_init_common(base, udiv, bdiv); return (0); } #endif /* if defined(CONFIG_440) */ -#if defined(CONFIG_SERIAL_MULTI) -void serial_setbrg_dev (unsigned long dev_base) -#else -void serial_setbrg (void) -#endif +void serial_setbrg_dev(unsigned long base) { -#if defined(CONFIG_SERIAL_MULTI) - serial_init_dev(dev_base); -#else - serial_init(); -#endif + serial_init_dev(base); } -#if defined(CONFIG_SERIAL_MULTI) -void serial_putc_dev (unsigned long dev_base, const char c) -#else -void serial_putc (const char c) -#endif +void serial_putc_dev(unsigned long base, const char c) { int i; if (c == '\n') -#if defined(CONFIG_SERIAL_MULTI) - serial_putc_dev (dev_base, '\r'); -#else - serial_putc ('\r'); -#endif + serial_putc_dev(base, '\r'); /* check THRE bit, wait for transmiter available */ for (i = 1; i < 3500; i++) { - if ((in8 (UART_BASE + UART_LSR) & 0x20) == 0x20) + if ((in_8((u8 *)base + UART_LSR) & 0x20) == 0x20) break; udelay (100); } - out8 (UART_BASE + UART_THR, c); /* put character out */ + + out_8((u8 *)base + UART_THR, c); /* put character out */ } -#if defined(CONFIG_SERIAL_MULTI) -void serial_puts_dev (unsigned long dev_base, const char *s) -#else -void serial_puts (const char *s) -#endif +void serial_puts_dev (unsigned long base, const char *s) { - while (*s) { -#if defined(CONFIG_SERIAL_MULTI) - serial_putc_dev (dev_base, *s++); -#else - serial_putc (*s++); -#endif - } + while (*s) + serial_putc_dev (base, *s++); } -#if defined(CONFIG_SERIAL_MULTI) -int serial_getc_dev (unsigned long dev_base) -#else -int serial_getc (void) -#endif +int serial_getc_dev (unsigned long base) { unsigned char status = 0; @@ -690,46 +477,45 @@ int serial_getc (void) #if defined(CONFIG_HW_WATCHDOG) WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ #endif /* CONFIG_HW_WATCHDOG */ - status = in8 (UART_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { + + status = in_8((u8 *)base + UART_LSR); + if ((status & asyncLSRDataReady1) != 0x0) break; - } + if ((status & ( asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1 )) != 0) { - out8 (UART_BASE + UART_LSR, + out_8((u8 *)base + UART_LSR, asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1); } } - return (0x000000ff & (int) in8 (UART_BASE)); + + return (0x000000ff & (int) in_8((u8 *)base)); } -#if defined(CONFIG_SERIAL_MULTI) -int serial_tstc_dev (unsigned long dev_base) -#else -int serial_tstc (void) -#endif +int serial_tstc_dev (unsigned long base) { unsigned char status; - status = in8 (UART_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { + status = in_8((u8 *)base + UART_LSR); + if ((status & asyncLSRDataReady1) != 0x0) return (1); - } + if ((status & ( asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1 )) != 0) { - out8 (UART_BASE + UART_LSR, + out_8((u8 *)base + UART_LSR, asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1); } + return 0; } @@ -742,11 +528,11 @@ void serial_isr (void *arg) const int rx_get = buf_info.rx_get; int rx_put = buf_info.rx_put; - if (rx_get <= rx_put) { + if (rx_get <= rx_put) space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get); - } else { + else space = rx_get - rx_put; - } + while (serial_tstc_dev (ACTING_UART0_BASE)) { c = serial_getc_dev (ACTING_UART0_BASE); if (space) { @@ -757,8 +543,9 @@ void serial_isr (void *arg) rx_put = 0; if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) { /* Stop flow by setting RTS inactive */ - out8 (ACTING_UART0_BASE + UART_MCR, - in8 (ACTING_UART0_BASE + UART_MCR) & (0xFF ^ 0x02)); + out_8((u8 *)ACTING_UART0_BASE + UART_MCR, + in_8((u8 *)ACTING_UART0_BASE + UART_MCR) & + (0xFF ^ 0x02)); } } buf_info.rx_put = rx_put; @@ -771,35 +558,35 @@ void serial_buffered_init (void) buf_info.rx_put = 0; buf_info.rx_get = 0; - if (in8 (ACTING_UART0_BASE + UART_MSR) & 0x10) { + if (in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10) serial_puts ("Check CTS signal present on serial port: OK.\n"); - } else { + else serial_puts ("WARNING: CTS signal not present on serial port.\n"); - } irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ , serial_isr /*interrupt_handler_t *handler */ , (void *) &buf_info /*void *arg */ ); /* Enable "RX Data Available" Interrupt on UART */ - /* out8(ACTING_UART0_BASE + UART_IER, in8(ACTING_UART0_BASE + UART_IER) |0x01); */ - out8 (ACTING_UART0_BASE + UART_IER, 0x01); + out_8(ACTING_UART0_BASE + UART_IER, 0x01); /* Set DTR active */ - out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x01); + out_8(ACTING_UART0_BASE + UART_MCR, + in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x01); /* Start flow by setting RTS active */ - out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02); + out_8(ACTING_UART0_BASE + UART_MCR, + in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x02); /* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */ - out8 (ACTING_UART0_BASE + UART_FCR, (1 << 6) | 1); + out_8(ACTING_UART0_BASE + UART_FCR, (1 << 6) | 1); } void serial_buffered_putc (const char c) { /* Wait for CTS */ #if defined(CONFIG_HW_WATCHDOG) - while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10)) + while (!(in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10)) WATCHDOG_RESET (); #else - while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10)); + while (!(in_8((u8 *)ACTING_UART0_BASE + UART_MSR) & 0x10)); #endif serial_putc (c); } @@ -828,14 +615,15 @@ int serial_buffered_getc (void) buf_info.rx_get = rx_get; rx_put = buf_info.rx_put; - if (rx_get <= rx_put) { + if (rx_get <= rx_put) space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get); - } else { + else space = rx_get - rx_put; - } + if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) { /* Start flow by setting RTS active */ - out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02); + out_8(ACTING_UART0_BASE + UART_MCR, + in_8((u8 *)ACTING_UART0_BASE + UART_MCR) | 0x02); } return c; @@ -860,8 +648,8 @@ int serial_buffered_tstc (void) #if (CONFIG_KGDB_SER_INDEX & 2) void kgdb_serial_init (void) { - volatile char val; - unsigned short br_reg; + u8 val; + u16 br_reg; get_clocks (); br_reg = (((((gd->cpu_clk / 16) / 18) * 10) / CONFIG_KGDB_BAUDRATE) + @@ -869,16 +657,16 @@ void kgdb_serial_init (void) /* * Init onboard 16550 UART */ - out8 (ACTING_UART1_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8 (ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */ - out8 (ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8)); /* set divisor for 9600 baud */ - out8 (ACTING_UART1_BASE + UART_LCR, 0x03); /* line control 8 bits no parity */ - out8 (ACTING_UART1_BASE + UART_FCR, 0x00); /* disable FIFO */ - out8 (ACTING_UART1_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8 (ACTING_UART1_BASE + UART_LSR); /* clear line status */ - val = in8 (ACTING_UART1_BASE + UART_RBR); /* read receive buffer */ - out8 (ACTING_UART1_BASE + UART_SCR, 0x00); /* set scratchpad */ - out8 (ACTING_UART1_BASE + UART_IER, 0x00); /* set interrupt enable reg */ + out_8((u8 *)ACTING_UART1_BASE + UART_LCR, 0x80); /* set DLAB bit */ + out_8((u8 *)ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */ + out_8((u8 *)ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8)); /* set divisor for 9600 baud */ + out_8((u8 *)ACTING_UART1_BASE + UART_LCR, 0x03); /* line control 8 bits no parity */ + out_8((u8 *)ACTING_UART1_BASE + UART_FCR, 0x00); /* disable FIFO */ + out_8((u8 *)ACTING_UART1_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ + val = in_8((u8 *)ACTING_UART1_BASE + UART_LSR); /* clear line status */ + val = in_8((u8 *)ACTING_UART1_BASE + UART_RBR); /* read receive buffer */ + out_8((u8 *)ACTING_UART1_BASE + UART_SCR, 0x00); /* set scratchpad */ + out_8((u8 *)ACTING_UART1_BASE + UART_IER, 0x00); /* set interrupt enable reg */ } void putDebugChar (const char c) @@ -886,17 +674,16 @@ void putDebugChar (const char c) if (c == '\n') serial_putc ('\r'); - out8 (ACTING_UART1_BASE + UART_THR, c); /* put character out */ + out_8((u8 *)ACTING_UART1_BASE + UART_THR, c); /* put character out */ /* check THRE bit, wait for transfer done */ - while ((in8 (ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20); + while ((in_8((u8 *)ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20); } void putDebugStr (const char *s) { - while (*s) { + while (*s) serial_putc (*s++); - } } int getDebugChar (void) @@ -904,22 +691,23 @@ int getDebugChar (void) unsigned char status = 0; while (1) { - status = in8 (ACTING_UART1_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { + status = in_8((u8 *)ACTING_UART1_BASE + UART_LSR); + if ((status & asyncLSRDataReady1) != 0x0) break; - } - if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - out8 (ACTING_UART1_BASE + UART_LSR, + + if ((status & (asyncLSRFramingError1 | + asyncLSROverrunError1 | + asyncLSRParityError1 | + asyncLSRBreakInterrupt1 )) != 0) { + out_8((u8 *)ACTING_UART1_BASE + UART_LSR, asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1); } } - return (0x000000ff & (int) in8 (ACTING_UART1_BASE)); + + return (0x000000ff & (int) in_8((u8 *)ACTING_UART1_BASE)); } void kgdb_interruptible (int yes) @@ -967,10 +755,12 @@ int serial1_init(void) { return (serial_init_dev(UART1_BASE)); } + void serial0_setbrg (void) { serial_setbrg_dev(UART0_BASE); } + void serial1_setbrg (void) { serial_setbrg_dev(UART1_BASE); @@ -985,6 +775,7 @@ void serial1_putc(const char c) { serial_putc_dev(UART1_BASE, c); } + void serial0_puts(const char *s) { serial_puts_dev(UART0_BASE, s); @@ -1004,6 +795,7 @@ int serial1_getc(void) { return(serial_getc_dev(UART1_BASE)); } + int serial0_tstc(void) { return (serial_tstc_dev(UART0_BASE)); @@ -1037,6 +829,39 @@ struct serial_device serial1_device = serial1_putc, serial1_puts, }; +#else +/* + * Wrapper functions + */ +int serial_init(void) +{ + return serial_init_dev(ACTING_UART0_BASE); +} + +void serial_setbrg(void) +{ + serial_setbrg_dev(ACTING_UART0_BASE); +} + +void serial_putc(const char c) +{ + serial_putc_dev(ACTING_UART0_BASE, c); +} + +void serial_puts(const char *s) +{ + serial_puts_dev(ACTING_UART0_BASE, s); +} + +int serial_getc(void) +{ + return serial_getc_dev(ACTING_UART0_BASE); +} + +int serial_tstc(void) +{ + return serial_tstc_dev(ACTING_UART0_BASE); +} #endif /* CONFIG_SERIAL_MULTI */ #endif /* CONFIG_405GP || CONFIG_405CR */ diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index af9da5b..178c5c6 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -25,15 +25,40 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a -START = start.o resetvec.o kgdb.o -SOBJS = dcr.o -COBJS = 405gp_pci.o 440spe_pcie.o 4xx_enet.o \ - bedbug_405.o commproc.o \ - cpu.o cpu_init.o gpio.o i2c.o interrupts.o \ - miiphy.o ndfc.o sdram.o serial.o \ - 40x_spd_sdram.o 44x_spd_ddr.o 44x_spd_ddr2.o speed.o \ - tlb.o traps.o usb_ohci.o usb.o usbdev.o \ - 440spe_pcie.o +START := resetvec.o +START += start.o + +SOBJS := cache.o +SOBJS += dcr.o +SOBJS += kgdb.o + +COBJS := 40x_spd_sdram.o +COBJS += 44x_spd_ddr.o +COBJS += 44x_spd_ddr2.o +COBJS += 4xx_enet.o +COBJS += 4xx_pci.o +COBJS += 4xx_pcie.o +COBJS += 4xx_uart.o +COBJS += bedbug_405.o +COBJS += commproc.o +COBJS += cpu.o +COBJS += cpu_init.o +COBJS += denali_data_eye.o +COBJS += denali_spd_ddr2.o +COBJS += fdt.o +COBJS += gpio.o +COBJS += i2c.o +COBJS += interrupts.o +COBJS += iop480_uart.o +COBJS += miiphy.o +COBJS += ndfc.o +COBJS += sdram.o +COBJS += speed.o +COBJS += tlb.o +COBJS += traps.o +COBJS += usb.o +COBJS += usb_ohci.o +COBJS += usbdev.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/ppc4xx/cache.S b/cpu/ppc4xx/cache.S new file mode 100644 index 0000000..5124dec --- /dev/null +++ b/cpu/ppc4xx/cache.S @@ -0,0 +1,233 @@ +/* + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras. + * + * 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. + * + */ + +#include <config.h> +#include <config.h> +#include <ppc4xx.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +/* + * Flush instruction cache. + */ +_GLOBAL(invalidate_icache) + iccci r0,r0 + isync + blr + +/* + * Write any modified data cache blocks out to memory + * and invalidate the corresponding instruction cache blocks. + * + * flush_icache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(flush_icache_range) + li r5,L1_CACHE_BYTES-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,L1_CACHE_SHIFT + beqlr + mtctr r4 + mr r6,r3 +1: dcbst 0,r3 + addi r3,r3,L1_CACHE_BYTES + bdnz 1b + sync /* wait for dcbst's to get to ram */ + mtctr r4 +2: icbi 0,r6 + addi r6,r6,L1_CACHE_BYTES + bdnz 2b + sync /* additional sync needed on g4 */ + isync + blr + +/* + * Write any modified data cache blocks out to memory. + * Does not invalidate the corresponding cache lines (especially for + * any corresponding instruction cache). + * + * clean_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(clean_dcache_range) + li r5,L1_CACHE_BYTES-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,L1_CACHE_SHIFT + beqlr + mtctr r4 + +1: dcbst 0,r3 + addi r3,r3,L1_CACHE_BYTES + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr + +/* + * Write any modified data cache blocks out to memory and invalidate them. + * Does not invalidate the corresponding instruction cache blocks. + * + * flush_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(flush_dcache_range) + li r5,L1_CACHE_BYTES-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,L1_CACHE_SHIFT + beqlr + mtctr r4 + +1: dcbf 0,r3 + addi r3,r3,L1_CACHE_BYTES + bdnz 1b + sync /* wait for dcbst's to get to ram */ + blr + +/* + * Like above, but invalidate the D-cache. This is used by the 8xx + * to invalidate the cache so the PPC core doesn't get stale data + * from the CPM (no cache snooping here :-). + * + * invalidate_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(invalidate_dcache_range) + li r5,L1_CACHE_BYTES-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,L1_CACHE_SHIFT + beqlr + mtctr r4 + +1: dcbi 0,r3 + addi r3,r3,L1_CACHE_BYTES + bdnz 1b + sync /* wait for dcbi's to get to ram */ + blr + +/* + * 40x cores have 8K or 16K dcache and 32 byte line size. + * 44x has a 32K dcache and 32 byte line size. + * 8xx has 1, 2, 4, 8K variants. + * For now, cover the worst case of the 44x. + * Must be called with external interrupts disabled. + */ +#define CACHE_NWAYS 64 +#define CACHE_NLINES 32 + +_GLOBAL(flush_dcache) + li r4,(2 * CACHE_NWAYS * CACHE_NLINES) + mtctr r4 + lis r5,0 +1: lwz r3,0(r5) /* Load one word from every line */ + addi r5,r5,L1_CACHE_BYTES + bdnz 1b + sync + blr + +_GLOBAL(invalidate_dcache) + addi r6,0,0x0000 /* clear GPR 6 */ + /* Do loop for # of dcache congruence classes. */ + lis r7,(CFG_DCACHE_SIZE / L1_CACHE_BYTES / 2)@ha /* TBS for large sized cache */ + ori r7,r7,(CFG_DCACHE_SIZE / L1_CACHE_BYTES / 2)@l + /* NOTE: dccci invalidates both */ + mtctr r7 /* ways in the D cache */ +..dcloop: + dccci 0,r6 /* invalidate line */ + addi r6,r6,L1_CACHE_BYTES /* bump to next line */ + bdnz ..dcloop + sync + blr + +/* + * Cache functions. + * + * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, + * although for some cache-ralated calls stubs have to be provided to satisfy + * symbols resolution. + * Icache-related functions are used in POST framework. + * + */ +#ifdef CONFIG_440 + + .globl dcache_disable + .globl icache_disable + .globl icache_enable +dcache_disable: +icache_disable: +icache_enable: + blr + + .globl dcache_status + .globl icache_status +dcache_status: +icache_status: + mr r3, 0 + blr + +#else /* CONFIG_440 */ + + .globl icache_enable +icache_enable: + mflr r8 + bl invalidate_icache + mtlr r8 + isync + addis r3,r0, 0xc000 /* set bit 0 */ + mticcr r3 + blr + + .globl icache_disable +icache_disable: + addis r3,r0, 0x0000 /* clear bit 0 */ + mticcr r3 + isync + blr + + .globl icache_status +icache_status: + mficcr r3 + srwi r3, r3, 31 /* >>31 => select bit 0 */ + blr + + .globl dcache_enable +dcache_enable: + mflr r8 + bl invalidate_dcache + mtlr r8 + isync + addis r3,r0, 0x8000 /* set bit 0 */ + mtdccr r3 + blr + + .globl dcache_disable +dcache_disable: + mflr r8 + bl flush_dcache + mtlr r8 + addis r3,r0, 0x0000 /* clear bit 0 */ + mtdccr r3 + blr + + .globl dcache_status +dcache_status: + mfdccr r3 + srwi r3, r3, 31 /* >>31 => select bit 0 */ + blr + +#endif /* CONFIG_440 */ diff --git a/cpu/ppc4xx/commproc.c b/cpu/ppc4xx/commproc.c index 68aab5b..22156dd 100644 --- a/cpu/ppc4xx/commproc.c +++ b/cpu/ppc4xx/commproc.c @@ -26,10 +26,21 @@ #include <common.h> #include <commproc.h> - +#include <asm/io.h> #if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) +#if defined(CFG_POST_ALT_WORD_ADDR) +void post_word_store (ulong a) +{ + out_be32((void *)CFG_POST_ALT_WORD_ADDR, a); +} + +ulong post_word_load (void) +{ + return in_be32((void *)CFG_POST_ALT_WORD_ADDR); +} +#else /* CFG_POST_ALT_WORD_ADDR */ void post_word_store (ulong a) { volatile void *save_addr = (volatile void *)(CFG_OCM_DATA_ADDR + CFG_POST_WORD_ADDR); @@ -41,6 +52,7 @@ ulong post_word_load (void) volatile void *save_addr = (volatile void *)(CFG_OCM_DATA_ADDR + CFG_POST_WORD_ADDR); return *(volatile ulong *) save_addr; } +#endif /* CFG_POST_ALT_WORD_ADDR */ #endif /* CONFIG_POST || CONFIG_LOGBUFFER*/ diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index c07bc0c..9e9c685 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2006 + * (C) Copyright 2000-2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -37,22 +37,9 @@ #include <asm/cache.h> #include <ppc4xx.h> -#if !defined(CONFIG_405) DECLARE_GLOBAL_DATA_PTR; -#endif -#if defined(CONFIG_BOARD_RESET) void board_reset(void); -#endif - -#if defined(CONFIG_440) -#define FREQ_EBC (sys_info.freqEPB) -#elif defined(CONFIG_405EZ) -#define FREQ_EBC ((CONFIG_SYS_CLK_FREQ * sys_info.pllFbkDiv) / \ - sys_info.pllExtBusDiv) -#else -#define FREQ_EBC (sys_info.freqPLB / sys_info.pllExtBusDiv) -#endif #if defined(CONFIG_405GP) || \ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ @@ -60,7 +47,7 @@ void board_reset(void); #define PCI_ASYNC -int pci_async_enabled(void) +static int pci_async_enabled(void) { #if defined(CONFIG_405GP) return (mfdcr(strap) & PSR_PCI_ASYNC_EN); @@ -76,8 +63,9 @@ int pci_async_enabled(void) } #endif -#if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && !defined(CONFIG_405) -int pci_arbiter_enabled(void) +#if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && \ + !defined(CONFIG_405) && !defined(CONFIG_405EX) +static int pci_arbiter_enabled(void) { #if defined(CONFIG_405GP) return (mfdcr(strap) & PSR_PCI_ARBIT_EN); @@ -107,14 +95,10 @@ int pci_arbiter_enabled(void) } #endif -#if defined(CONFIG_405EP) || defined(CONFIG_440GX) || \ - defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) - +#if defined(CONFIG_405EP) #define I2C_BOOTROM -int i2c_bootrom_enabled(void) +static int i2c_bootrom_enabled(void) { #if defined(CONFIG_405EP) return (mfdcr(cpc0_boot) & CPC0_BOOT_SEP); @@ -207,6 +191,21 @@ static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', \ 'I', 'x', 'K', 'L', 'M', 'N', 'O', 'P' }; #endif +#if defined(CONFIG_405EX) +#define SDR0_PINSTP_SHIFT 29 +static char *bootstrap_str[] = { + "EBC (8 bits)", + "EBC (16 bits)", + "EBC (16 bits)", + "NAND (8 bits)", + "NAND (8 bits)", + "I2C (Addr 0x54)", + "EBC (8 bits)", + "I2C (Addr 0x52)", +}; +static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' }; +#endif + #if defined(SDR0_PINSTP_SHIFT) static int bootstrap_option(void) { @@ -219,7 +218,19 @@ static int bootstrap_option(void) #if defined(CONFIG_440) -static int do_chip_reset(unsigned long sys0, unsigned long sys1); +static int do_chip_reset (unsigned long sys0, unsigned long sys1) +{ + /* Changes to cpc0_sys0 and cpc0_sys1 require chip + * reset. + */ + mtdcr (cntrl0, mfdcr (cntrl0) | 0x80000000); /* Set SWE */ + mtdcr (cpc0_sys0, sys0); + mtdcr (cpc0_sys1, sys1); + mtdcr (cntrl0, mfdcr (cntrl0) & ~0x80000000); /* Clr SWE */ + mtspr (dbcr0, 0x20000000); /* Reset the chip */ + + return 1; +} #endif @@ -241,7 +252,8 @@ int checkcpu (void) puts("AMCC PowerPC 4"); #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_405EZ) + defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ + defined(CONFIG_405EX) puts("05"); #endif #if defined(CONFIG_440) @@ -293,6 +305,26 @@ int checkcpu (void) puts("EZ Rev. A"); break; + case PVR_405EX1_RA: + puts("EX Rev. A"); + strcpy(addstr, "Security support"); + break; + + case PVR_405EX2_RA: + puts("EX Rev. A"); + strcpy(addstr, "No Security support"); + break; + + case PVR_405EXR1_RA: + puts("EXr Rev. A"); + strcpy(addstr, "Security support"); + break; + + case PVR_405EXR2_RA: + puts("EXr Rev. A"); + strcpy(addstr, "No Security support"); + break; + #if defined(CONFIG_440) case PVR_440GP_RB: puts("GP Rev. B"); @@ -424,7 +456,7 @@ int checkcpu (void) printf (" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock), sys_info.freqPLB / 1000000, get_OPB_freq() / 1000000, - FREQ_EBC / 1000000); + sys_info.freqEBC / 1000000); if (addstr[0] != 0) printf(" %s\n", addstr); @@ -437,7 +469,7 @@ int checkcpu (void) printf ("Boot ROM Location %s\n", bootstrap_str[bootstrap_option()]); #endif /* SDR0_PINSTP_SHIFT */ -#if defined(CONFIG_PCI) +#if defined(CONFIG_PCI) && !defined(CONFIG_405EX) printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis"); #endif @@ -450,11 +482,11 @@ int checkcpu (void) } #endif -#if defined(CONFIG_PCI) +#if defined(CONFIG_PCI) && !defined(CONFIG_405EX) putc('\n'); #endif -#if defined(CONFIG_405EP) || defined(CONFIG_405EZ) +#if defined(CONFIG_405EP) || defined(CONFIG_405EZ) || defined(CONFIG_405EX) printf (" 16 kB I-Cache 16 kB D-Cache"); #elif defined(CONFIG_440) printf (" 32 kB I-Cache 32 kB D-Cache"); @@ -478,7 +510,6 @@ int checkcpu (void) return 0; } -#if defined (CONFIG_440SPE) int ppc440spe_revB() { unsigned int pvr; @@ -488,7 +519,6 @@ int ppc440spe_revB() { else return 0; } -#endif /* ------------------------------------------------------------------------- */ @@ -510,22 +540,6 @@ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } -#if defined(CONFIG_440) -static int do_chip_reset (unsigned long sys0, unsigned long sys1) -{ - /* Changes to cpc0_sys0 and cpc0_sys1 require chip - * reset. - */ - mtdcr (cntrl0, mfdcr (cntrl0) | 0x80000000); /* Set SWE */ - mtdcr (cpc0_sys0, sys0); - mtdcr (cpc0_sys1, sys1); - mtdcr (cntrl0, mfdcr (cntrl0) & ~0x80000000); /* Clr SWE */ - mtspr (dbcr0, 0x20000000); /* Reset the chip */ - - return 1; -} -#endif - /* * Get timebase clock frequency @@ -545,16 +559,14 @@ unsigned long get_tbclk (void) #if defined(CONFIG_WATCHDOG) -void -watchdog_reset(void) +void watchdog_reset(void) { int re_enable = disable_interrupts(); reset_4xx_watchdog(); if (re_enable) enable_interrupts(); } -void -reset_4xx_watchdog(void) +void reset_4xx_watchdog(void) { /* * Clear TSR(WIS) bit diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index 351da36..2e0dd6f 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2006 + * (C) Copyright 2000-2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -112,7 +112,7 @@ cpu_init_f (void) unsigned long val; #endif -#if defined(CONFIG_405EP) +#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE) /* * GPIO0 setup (select GPIO or alternate function) */ @@ -128,17 +128,30 @@ cpu_init_f (void) 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 +#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 */ #endif /* CONFIG_405EP */ -#if defined(CFG_440_GPIO_TABLE) +#if defined(CFG_4xx_GPIO_TABLE) gpio_set_chip_configuration(); -#endif /* CFG_440_GPIO_TABLE */ +#endif /* CFG_4xx_GPIO_TABLE */ /* * External Bus Controller (EBC) Setup @@ -146,7 +159,7 @@ cpu_init_f (void) #if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR)) #if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405)) + defined(CONFIG_405EX) || defined(CONFIG_405)) /* * Move the next instructions into icache, since these modify the flash * we are running from! diff --git a/cpu/ppc4xx/denali_data_eye.c b/cpu/ppc4xx/denali_data_eye.c new file mode 100644 index 0000000..967e61b --- /dev/null +++ b/cpu/ppc4xx/denali_data_eye.c @@ -0,0 +1,389 @@ +/* + * cpu/ppc4xx/denali_data_eye.c + * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>. + * + * (C) Copyright 2006 + * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com + * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com + * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com + * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com + * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com + * + * (C) Copyright 2006-2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * 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 + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <ppc4xx.h> + +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +/*-----------------------------------------------------------------------------+ + * denali_wait_for_dlllock. + +----------------------------------------------------------------------------*/ +int denali_wait_for_dlllock(void) +{ + u32 val; + int wait; + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + for (wait = 0; wait != 0xffff; ++wait) { + mfsdram(DDR0_17, val); + if (DDR0_17_DLLLOCKREG_DECODE(val)) { + /* dlllockreg bit on */ + return 0; + } + } + debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val); + debug("Waiting for dlllockreg bit to raise\n"); + return -1; +} + +#if defined(CONFIG_DDR_DATA_EYE) +#define DDR_DCR_BASE 0x10 +#define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */ +#define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */ + +/*-----------------------------------------------------------------------------+ + * wait_for_dram_init_complete. + +----------------------------------------------------------------------------*/ +static int wait_for_dram_init_complete(void) +{ + unsigned long val; + int wait = 0; + + /* --------------------------------------------------------------+ + * Wait for 'DRAM initialization complete' bit in status register + * -------------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_00); + + while (wait != 0xffff) { + val = mfdcr(ddrcfgd); + if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6) + /* 'DRAM initialization complete' bit */ + return 0; + else + wait++; + } + debug("DRAM initialization complete bit in status register did not " + "rise\n"); + return -1; +} + +#define NUM_TRIES 64 +#define NUM_READS 10 + +/*-----------------------------------------------------------------------------+ + * denali_core_search_data_eye. + +----------------------------------------------------------------------------*/ +void denali_core_search_data_eye(void) +{ + int k, j; + u32 val; + u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X; + u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0; + u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0; + u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0; + volatile u32 *ram_pointer; + u32 test[NUM_TRIES] = { + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 + }; + + ram_pointer = (volatile u32 *)(CFG_SDRAM_BASE); + + for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) { + /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */ + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | + DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'wr_dqs_shift' + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_09); + val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) | + DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'dqs_out_shift' = wr_dqs_shift + 32 + * ----------------------------------------------------------*/ + dqs_out_shift = wr_dqs_shift + 32; + mtdcr(ddrcfga, DDR0_22); + val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) | + DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); + mtdcr(ddrcfgd, val); + + passing_cases = 0; + + for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64; + dll_dqs_delay_X++) { + /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128; + dll_dqs_delay_X++) { */ + /* -----------------------------------------------------------+ + * Set 'dll_dqs_delay_X'. + * ----------------------------------------------------------*/ + /* dll_dqs_delay_0 */ + mtdcr(ddrcfga, DDR0_17); + val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) + | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + /* dll_dqs_delay_1 to dll_dqs_delay_4 */ + mtdcr(ddrcfga, DDR0_18); + val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) + | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + /* dll_dqs_delay_5 to dll_dqs_delay_8 */ + mtdcr(ddrcfga, DDR0_19); + val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) + | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + /* clear any ECC errors */ + mtdcr(ddrcfga, DDR0_00); + mtdcr(ddrcfgd, + mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C)); + + sync(); + eieio(); + + /* -----------------------------------------------------------+ + * Assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | + DDR0_02_START_ON; + mtdcr(ddrcfgd, val); + + sync(); + eieio(); + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + if (denali_wait_for_dlllock() != 0) { + printf("dll lock did not occur !!!\n"); + printf("denali_core_search_data_eye!!!\n"); + printf("wr_dqs_shift = %d - dll_dqs_delay_X = " + "%d\n", wr_dqs_shift, dll_dqs_delay_X); + hang(); + } + sync(); + eieio(); + + if (wait_for_dram_init_complete() != 0) { + printf("dram init complete did not occur!!!\n"); + printf("denali_core_search_data_eye!!!\n"); + printf("wr_dqs_shift = %d - dll_dqs_delay_X = " + "%d\n", wr_dqs_shift, dll_dqs_delay_X); + hang(); + } + udelay(100); /* wait 100us to ensure init is really completed !!! */ + + /* write values */ + for (j = 0; j < NUM_TRIES; j++) { + ram_pointer[j] = test[j]; + + /* clear any cache at ram location */ + __asm__("dcbf 0,%0": :"r"(&ram_pointer[j])); + } + + /* read values back */ + for (j = 0; j < NUM_TRIES; j++) { + for (k = 0; k < NUM_READS; k++) { + /* clear any cache at ram location */ + __asm__("dcbf 0,%0": :"r"(&ram_pointer + [j])); + + if (ram_pointer[j] != test[j]) + break; + } + + /* read error */ + if (k != NUM_READS) + break; + } + + /* See if the dll_dqs_delay_X value passed. */ + mtdcr(ddrcfga, DDR0_00); + if (j < NUM_TRIES + || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) & + 0x3F)) { + /* Failed */ + passing_cases = 0; + /* break; */ + } else { + /* Passed */ + if (passing_cases == 0) + dll_dqs_delay_X_sw_val = + dll_dqs_delay_X; + passing_cases++; + if (passing_cases >= max_passing_cases) { + max_passing_cases = passing_cases; + wr_dqs_shift_with_max_passing_cases = + wr_dqs_shift; + dll_dqs_delay_X_start_window = + dll_dqs_delay_X_sw_val; + dll_dqs_delay_X_end_window = + dll_dqs_delay_X; + } + } + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | + DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */ + } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */ + + /* -----------------------------------------------------------+ + * Largest passing window is now detected. + * ----------------------------------------------------------*/ + + /* Compute dll_dqs_delay_X value */ + dll_dqs_delay_X = (dll_dqs_delay_X_end_window + + dll_dqs_delay_X_start_window) / 2; + wr_dqs_shift = wr_dqs_shift_with_max_passing_cases; + + debug("DQS calibration - Window detected:\n"); + debug("max_passing_cases = %d\n", max_passing_cases); + debug("wr_dqs_shift = %d\n", wr_dqs_shift); + debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X); + debug("dll_dqs_delay_X window = %d - %d\n", + dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window); + + /* -----------------------------------------------------------+ + * De-assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF; + mtdcr(ddrcfgd, val); + + /* -----------------------------------------------------------+ + * Set 'wr_dqs_shift' + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_09); + val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) + | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift); + mtdcr(ddrcfgd, val); + debug("DDR0_09=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Set 'dqs_out_shift' = wr_dqs_shift + 32 + * ----------------------------------------------------------*/ + dqs_out_shift = wr_dqs_shift + 32; + mtdcr(ddrcfga, DDR0_22); + val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) + | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift); + mtdcr(ddrcfgd, val); + debug("DDR0_22=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Set 'dll_dqs_delay_X'. + * ----------------------------------------------------------*/ + /* dll_dqs_delay_0 */ + mtdcr(ddrcfga, DDR0_17); + val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK) + | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_17=0x%08lx\n", val); + + /* dll_dqs_delay_1 to dll_dqs_delay_4 */ + mtdcr(ddrcfga, DDR0_18); + val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK) + | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X) + | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_18=0x%08lx\n", val); + + /* dll_dqs_delay_5 to dll_dqs_delay_8 */ + mtdcr(ddrcfga, DDR0_19); + val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK) + | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X) + | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X); + mtdcr(ddrcfgd, val); + debug("DDR0_19=0x%08lx\n", val); + + /* -----------------------------------------------------------+ + * Assert 'start' parameter. + * ----------------------------------------------------------*/ + mtdcr(ddrcfga, DDR0_02); + val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON; + mtdcr(ddrcfgd, val); + + sync(); + eieio(); + + /* -----------------------------------------------------------+ + * Wait for the DCC master delay line to finish calibration + * ----------------------------------------------------------*/ + if (denali_wait_for_dlllock() != 0) { + printf("dll lock did not occur !!!\n"); + hang(); + } + sync(); + eieio(); + + if (wait_for_dram_init_complete() != 0) { + printf("dram init complete did not occur !!!\n"); + hang(); + } + udelay(100); /* wait 100us to ensure init is really completed !!! */ +} +#endif /* defined(CONFIG_DDR_DATA_EYE) */ +#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */ diff --git a/cpu/ppc4xx/denali_spd_ddr2.c b/cpu/ppc4xx/denali_spd_ddr2.c new file mode 100644 index 0000000..825bc21 --- /dev/null +++ b/cpu/ppc4xx/denali_spd_ddr2.c @@ -0,0 +1,1254 @@ +/* + * cpu/ppc4xx/denali_spd_ddr2.c + * This SPD SDRAM detection code supports AMCC PPC44x CPUs with a Denali-core + * DDR2 controller, specifically the 440EPx/GRx. + * + * (C) Copyright 2007 + * Larry Johnson, lrj@acm.org. + * + * Based primarily on cpu/ppc4xx/4xx_spd_ddr2.c, which is... + * + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * COPYRIGHT AMCC CORPORATION 2004 + * + * 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 + * + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <command.h> +#include <ppc4xx.h> +#include <i2c.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/mmu.h> + +#if defined(CONFIG_SPD_EEPROM) && \ + (defined(CONFIG_440EPX) || defined(CONFIG_440GRX)) + +/*-----------------------------------------------------------------------------+ + * Defines + *-----------------------------------------------------------------------------*/ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAXDIMMS 2 +#define MAXRANKS 2 + +#define ONE_BILLION 1000000000 + +#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) + +#define DLL_DQS_DELAY 0x19 +#define DLL_DQS_BYPASS 0x0B +#define DQS_OUT_SHIFT 0x7F + +/* + * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory + * region. Right now the cache should still be disabled in U-Boot because of the + * EMAC driver, that need it's buffer descriptor to be located in non cached + * memory. + * + * If at some time this restriction doesn't apply anymore, just define + * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup + * everything correctly. + */ +#if defined(CFG_ENABLE_SDRAM_CACHE) +#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */ +#else +#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */ +#endif + +/*-----------------------------------------------------------------------------+ + * Prototypes + *-----------------------------------------------------------------------------*/ +extern int denali_wait_for_dlllock(void); +extern void denali_core_search_data_eye(void); +extern void dcbz_area(u32 start_address, u32 num_bytes); +extern void dflush(void); + +/* + * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed + */ +void __spd_ddr_init_hang(void) +{ + hang(); +} +void spd_ddr_init_hang(void) + __attribute__ ((weak, alias("__spd_ddr_init_hang"))); + +#if defined(DEBUG) +static void print_mcsr(void) +{ + printf("MCSR = 0x%08X\n", mfspr(SPRN_MCSR)); +} + +static void denali_sdram_register_dump(void) +{ + unsigned int sdram_data; + + printf("\n Register Dump:\n"); + mfsdram(DDR0_00, sdram_data); + printf(" DDR0_00 = 0x%08X", sdram_data); + mfsdram(DDR0_01, sdram_data); + printf(" DDR0_01 = 0x%08X\n", sdram_data); + mfsdram(DDR0_02, sdram_data); + printf(" DDR0_02 = 0x%08X", sdram_data); + mfsdram(DDR0_03, sdram_data); + printf(" DDR0_03 = 0x%08X\n", sdram_data); + mfsdram(DDR0_04, sdram_data); + printf(" DDR0_04 = 0x%08X", sdram_data); + mfsdram(DDR0_05, sdram_data); + printf(" DDR0_05 = 0x%08X\n", sdram_data); + mfsdram(DDR0_06, sdram_data); + printf(" DDR0_06 = 0x%08X", sdram_data); + mfsdram(DDR0_07, sdram_data); + printf(" DDR0_07 = 0x%08X\n", sdram_data); + mfsdram(DDR0_08, sdram_data); + printf(" DDR0_08 = 0x%08X", sdram_data); + mfsdram(DDR0_09, sdram_data); + printf(" DDR0_09 = 0x%08X\n", sdram_data); + mfsdram(DDR0_10, sdram_data); + printf(" DDR0_10 = 0x%08X", sdram_data); + mfsdram(DDR0_11, sdram_data); + printf(" DDR0_11 = 0x%08X\n", sdram_data); + mfsdram(DDR0_12, sdram_data); + printf(" DDR0_12 = 0x%08X", sdram_data); + mfsdram(DDR0_14, sdram_data); + printf(" DDR0_14 = 0x%08X\n", sdram_data); + mfsdram(DDR0_17, sdram_data); + printf(" DDR0_17 = 0x%08X", sdram_data); + mfsdram(DDR0_18, sdram_data); + printf(" DDR0_18 = 0x%08X\n", sdram_data); + mfsdram(DDR0_19, sdram_data); + printf(" DDR0_19 = 0x%08X", sdram_data); + mfsdram(DDR0_20, sdram_data); + printf(" DDR0_20 = 0x%08X\n", sdram_data); + mfsdram(DDR0_21, sdram_data); + printf(" DDR0_21 = 0x%08X", sdram_data); + mfsdram(DDR0_22, sdram_data); + printf(" DDR0_22 = 0x%08X\n", sdram_data); + mfsdram(DDR0_23, sdram_data); + printf(" DDR0_23 = 0x%08X", sdram_data); + mfsdram(DDR0_24, sdram_data); + printf(" DDR0_24 = 0x%08X\n", sdram_data); + mfsdram(DDR0_25, sdram_data); + printf(" DDR0_25 = 0x%08X", sdram_data); + mfsdram(DDR0_26, sdram_data); + printf(" DDR0_26 = 0x%08X\n", sdram_data); + mfsdram(DDR0_27, sdram_data); + printf(" DDR0_27 = 0x%08X", sdram_data); + mfsdram(DDR0_28, sdram_data); + printf(" DDR0_28 = 0x%08X\n", sdram_data); + mfsdram(DDR0_31, sdram_data); + printf(" DDR0_31 = 0x%08X", sdram_data); + mfsdram(DDR0_32, sdram_data); + printf(" DDR0_32 = 0x%08X\n", sdram_data); + mfsdram(DDR0_33, sdram_data); + printf(" DDR0_33 = 0x%08X", sdram_data); + mfsdram(DDR0_34, sdram_data); + printf(" DDR0_34 = 0x%08X\n", sdram_data); + mfsdram(DDR0_35, sdram_data); + printf(" DDR0_35 = 0x%08X", sdram_data); + mfsdram(DDR0_36, sdram_data); + printf(" DDR0_36 = 0x%08X\n", sdram_data); + mfsdram(DDR0_37, sdram_data); + printf(" DDR0_37 = 0x%08X", sdram_data); + mfsdram(DDR0_38, sdram_data); + printf(" DDR0_38 = 0x%08X\n", sdram_data); + mfsdram(DDR0_39, sdram_data); + printf(" DDR0_39 = 0x%08X", sdram_data); + mfsdram(DDR0_40, sdram_data); + printf(" DDR0_40 = 0x%08X\n", sdram_data); + mfsdram(DDR0_41, sdram_data); + printf(" DDR0_41 = 0x%08X", sdram_data); + mfsdram(DDR0_42, sdram_data); + printf(" DDR0_42 = 0x%08X\n", sdram_data); + mfsdram(DDR0_43, sdram_data); + printf(" DDR0_43 = 0x%08X", sdram_data); + mfsdram(DDR0_44, sdram_data); + printf(" DDR0_44 = 0x%08X\n", sdram_data); +} +#else +static inline void denali_sdram_register_dump(void) +{ +} + +inline static void print_mcsr(void) +{ +} +#endif /* defined(DEBUG) */ + +static int is_ecc_enabled(void) +{ + u32 val; + + mfsdram(DDR0_22, val); + return 0x3 == DDR0_22_CTRL_RAW_DECODE(val); +} + +static unsigned char spd_read(u8 chip, unsigned int addr) +{ + u8 data[2]; + + if (0 != i2c_probe(chip) || 0 != i2c_read(chip, addr, 1, data, 1)) { + debug("spd_read(0x%02X, 0x%02X) failed\n", chip, addr); + return 0; + } + debug("spd_read(0x%02X, 0x%02X) returned 0x%02X\n", + chip, addr, data[0]); + return data[0]; +} + +static unsigned long get_tcyc(unsigned char reg) +{ + /* + * Byte 9, et al: Cycle time for CAS Latency=X, is split into two + * nibbles: the higher order nibble (bits 4-7) designates the cycle time + * to a granularity of 1ns; the value presented by the lower order + * nibble (bits 0-3) has a granularity of .1ns and is added to the value + * designated by the higher nibble. In addition, four lines of the lower + * order nibble are assigned to support +.25, +.33, +.66, and +.75. + */ + + unsigned char subfield_b = reg & 0x0F; + + switch (subfield_b & 0x0F) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + return 1000 * (reg >> 4) + 100 * subfield_b; + case 0xA: + return 1000 * (reg >> 4) + 250; + case 0xB: + return 1000 * (reg >> 4) + 333; + case 0xC: + return 1000 * (reg >> 4) + 667; + case 0xD: + return 1000 * (reg >> 4) + 750; + } + return 0; +} + +/*------------------------------------------------------------------ + * Find the installed DIMMs, make sure that the are DDR2, and fill + * in the dimm_ranks array. Then dimm_ranks[dimm_num] > 0 iff the + * DIMM and dimm_num is present. + * Note: Because there are only two chip-select lines, it is assumed + * that a board with a single socket can support two ranks on that + * socket, while a board with two sockets can support only one rank + * on each socket. + *-----------------------------------------------------------------*/ +static void get_spd_info(unsigned long dimm_ranks[], + unsigned long *ranks, + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long dimm_found = FALSE; + unsigned long const max_ranks_per_dimm = (1 == num_dimm_banks) ? 2 : 1; + unsigned char num_of_bytes; + unsigned char total_size; + + *ranks = 0; + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + num_of_bytes = 0; + total_size = 0; + + num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); + total_size = spd_read(iic0_dimm_addr[dimm_num], 1); + if ((num_of_bytes != 0) && (total_size != 0)) { + unsigned char const dimm_type = + spd_read(iic0_dimm_addr[dimm_num], 2); + + unsigned long ranks_on_dimm = + (spd_read(iic0_dimm_addr[dimm_num], 5) & 0x07) + 1; + + if (8 != dimm_type) { + switch (dimm_type) { + case 1: + printf("ERROR: Standard Fast Page Mode " + "DRAM DIMM"); + break; + case 2: + printf("ERROR: EDO DIMM"); + break; + case 3: + printf("ERROR: Pipelined Nibble DIMM"); + break; + case 4: + printf("ERROR: SDRAM DIMM"); + break; + case 5: + printf("ERROR: Multiplexed ROM DIMM"); + break; + case 6: + printf("ERROR: SGRAM DIMM"); + break; + case 7: + printf("ERROR: DDR1 DIMM"); + break; + default: + printf("ERROR: Unknown DIMM (type %d)", + (unsigned int)dimm_type); + break; + } + printf(" detected in slot %lu.\n", dimm_num); + printf("Only DDR2 SDRAM DIMMs are supported." + "\n"); + printf("Replace the module with a DDR2 DIMM." + "\n\n"); + spd_ddr_init_hang(); + } + dimm_found = TRUE; + debug("DIMM slot %lu: populated with %lu-rank DDR2 DIMM" + "\n", dimm_num, ranks_on_dimm); + if (ranks_on_dimm > max_ranks_per_dimm) { + printf("WARNING: DRAM DIMM in slot %lu has %lu " + "ranks.\n"); + if (1 == max_ranks_per_dimm) { + printf("Only one rank will be used.\n"); + } else { + printf + ("Only two ranks will be used.\n"); + } + ranks_on_dimm = max_ranks_per_dimm; + } + dimm_ranks[dimm_num] = ranks_on_dimm; + *ranks += ranks_on_dimm; + } else { + dimm_ranks[dimm_num] = 0; + debug("DIMM slot %lu: Not populated\n", dimm_num); + } + } + if (dimm_found == FALSE) { + printf("ERROR: No memory installed.\n"); + printf("Install at least one DDR2 DIMM.\n\n"); + spd_ddr_init_hang(); + } + debug("Total number of ranks = %d\n", *ranks); +} + +/*------------------------------------------------------------------ + * For the memory DIMMs installed, this routine verifies that + * frequency previously calculated is supported. + *-----------------------------------------------------------------*/ +static void check_frequency(unsigned long *dimm_ranks, + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq) +{ + unsigned long dimm_num; + unsigned long cycle_time; + unsigned long calc_cycle_time; + + /* + * calc_cycle_time is calculated from DDR frequency set by board/chip + * and is expressed in picoseconds to match the way DIMM cycle time is + * calculated below. + */ + calc_cycle_time = MULDIV64(ONE_BILLION, 1000, sdram_freq); + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_ranks[dimm_num]) { + cycle_time = + get_tcyc(spd_read(iic0_dimm_addr[dimm_num], 9)); + debug("cycle_time=%d ps\n", cycle_time); + + if (cycle_time > (calc_cycle_time + 10)) { + /* + * the provided sdram cycle_time is too small + * for the available DIMM cycle_time. The + * additionnal 10ps is here to accept a small + * incertainty. + */ + printf + ("ERROR: DRAM DIMM detected with cycle_time %d ps in " + "slot %d \n while calculated cycle time is %d ps.\n", + (unsigned int)cycle_time, + (unsigned int)dimm_num, + (unsigned int)calc_cycle_time); + printf + ("Replace the DIMM, or change DDR frequency via " + "strapping bits.\n\n"); + spd_ddr_init_hang(); + } + } + } +} + +/*------------------------------------------------------------------ + * This routine gets size information for the installed memory + * DIMMs. + *-----------------------------------------------------------------*/ +static void get_dimm_size(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long *const rows, + unsigned long *const banks, + unsigned long *const cols, unsigned long *const width) +{ + unsigned long dimm_num; + + *rows = 0; + *banks = 0; + *cols = 0; + *width = 0; + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_ranks[dimm_num]) { + unsigned long t; + + /* Rows */ + t = spd_read(iic0_dimm_addr[dimm_num], 3); + if (0 == *rows) { + *rows = t; + } else if (t != *rows) { + printf("ERROR: DRAM DIMM modules do not all " + "have the same number of rows.\n\n"); + spd_ddr_init_hang(); + } + /* Banks */ + t = spd_read(iic0_dimm_addr[dimm_num], 17); + if (0 == *banks) { + *banks = t; + } else if (t != *banks) { + printf("ERROR: DRAM DIMM modules do not all " + "have the same number of banks.\n\n"); + spd_ddr_init_hang(); + } + /* Columns */ + t = spd_read(iic0_dimm_addr[dimm_num], 4); + if (0 == *cols) { + *cols = t; + } else if (t != *cols) { + printf("ERROR: DRAM DIMM modules do not all " + "have the same number of columns.\n\n"); + spd_ddr_init_hang(); + } + /* Data width */ + t = spd_read(iic0_dimm_addr[dimm_num], 6); + if (0 == *width) { + *width = t; + } else if (t != *width) { + printf("ERROR: DRAM DIMM modules do not all " + "have the same data width.\n\n"); + spd_ddr_init_hang(); + } + } + } + debug("Number of rows = %d\n", *rows); + debug("Number of columns = %d\n", *cols); + debug("Number of banks = %d\n", *banks); + debug("Data width = %d\n", *width); + if (*rows > 14) { + printf("ERROR: DRAM DIMM modules have %lu address rows.\n", + *rows); + printf("Only modules with 14 or fewer rows are supported.\n\n"); + spd_ddr_init_hang(); + } + if (4 != *banks && 8 != *banks) { + printf("ERROR: DRAM DIMM modules have %lu banks.\n", *banks); + printf("Only modules with 4 or 8 banks are supported.\n\n"); + spd_ddr_init_hang(); + } + if (*cols > 12) { + printf("ERROR: DRAM DIMM modules have %lu address columns.\n", + *cols); + printf("Only modules with 12 or fewer columns are " + "supported.\n\n"); + spd_ddr_init_hang(); + } + if (32 != *width && 40 != *width && 64 != *width && 72 != *width) { + printf("ERROR: DRAM DIMM modules have a width of %lu bit.\n", + *width); + printf("Only modules with widths of 32, 40, 64, and 72 bits " + "are supported.\n\n"); + spd_ddr_init_hang(); + } +} + +/*------------------------------------------------------------------ + * Only 1.8V modules are supported. This routine verifies this. + *-----------------------------------------------------------------*/ +static void check_voltage_type(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long voltage_type; + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_ranks[dimm_num]) { + voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); + if (0x05 != voltage_type) { /* 1.8V for DDR2 */ + printf("ERROR: Slot %lu provides 1.8V for DDR2 " + "DIMMs.\n", dimm_num); + switch (voltage_type) { + case 0x00: + printf("This DIMM is 5.0 Volt/TTL.\n"); + break; + case 0x01: + printf("This DIMM is LVTTL.\n"); + break; + case 0x02: + printf("This DIMM is 1.5 Volt.\n"); + break; + case 0x03: + printf("This DIMM is 3.3 Volt/TTL.\n"); + break; + case 0x04: + printf("This DIMM is 2.5 Volt.\n"); + break; + default: + printf("This DIMM is an unknown " + "voltage.\n"); + break; + } + printf("Replace it with a 1.8V DDR2 DIMM.\n\n"); + spd_ddr_init_hang(); + } + } + } +} + +static void program_ddr0_03(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq, + unsigned long rows, unsigned long *cas_latency) +{ + unsigned long dimm_num; + unsigned long cas_index; + unsigned long cycle_2_0_clk; + unsigned long cycle_3_0_clk; + unsigned long cycle_4_0_clk; + unsigned long cycle_5_0_clk; + unsigned long max_2_0_tcyc_ps = 100; + unsigned long max_3_0_tcyc_ps = 100; + unsigned long max_4_0_tcyc_ps = 100; + unsigned long max_5_0_tcyc_ps = 100; + unsigned char cas_available = 0x3C; /* value for DDR2 */ + u32 ddr0_03 = DDR0_03_BSTLEN_ENCODE(0x2) | DDR0_03_INITAREF_ENCODE(0x2); + unsigned int const tcyc_addr[3] = { 9, 23, 25 }; + + /*------------------------------------------------------------------ + * Get the board configuration info. + *-----------------------------------------------------------------*/ + debug("sdram_freq = %d\n", sdram_freq); + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned char const cas_bit = + spd_read(iic0_dimm_addr[dimm_num], 18); + unsigned char cas_mask; + + cas_available &= cas_bit; + for (cas_mask = 0x80; cas_mask; cas_mask >>= 1) { + if (cas_bit & cas_mask) + break; + } + debug("cas_bit (SPD byte 18) = %02X, cas_mask = %02X\n", + cas_bit, cas_mask); + + for (cas_index = 0; cas_index < 3; + cas_mask >>= 1, cas_index++) { + unsigned long cycle_time_ps; + + if (!(cas_available & cas_mask)) { + continue; + } + cycle_time_ps = + get_tcyc(spd_read(iic0_dimm_addr[dimm_num], + tcyc_addr[cas_index])); + + debug("cas_index = %d: cycle_time_ps = %d\n", + cas_index, cycle_time_ps); + /* + * DDR2 devices use the following bitmask for CAS latency: + * Bit 7 6 5 4 3 2 1 0 + * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD + */ + switch (cas_mask) { + case 0x20: + max_5_0_tcyc_ps = + max(max_5_0_tcyc_ps, cycle_time_ps); + break; + case 0x10: + max_4_0_tcyc_ps = + max(max_4_0_tcyc_ps, cycle_time_ps); + break; + case 0x08: + max_3_0_tcyc_ps = + max(max_3_0_tcyc_ps, cycle_time_ps); + break; + case 0x04: + max_2_0_tcyc_ps = + max(max_2_0_tcyc_ps, cycle_time_ps); + break; + } + } + } + } + debug("cas_available (bit map) = 0x%02X\n", cas_available); + + /*------------------------------------------------------------------ + * Set the SDRAM mode, SDRAM_MMODE + *-----------------------------------------------------------------*/ + + /* add 10 here because of rounding problems */ + cycle_2_0_clk = MULDIV64(ONE_BILLION, 1000, max_2_0_tcyc_ps) + 10; + cycle_3_0_clk = MULDIV64(ONE_BILLION, 1000, max_3_0_tcyc_ps) + 10; + cycle_4_0_clk = MULDIV64(ONE_BILLION, 1000, max_4_0_tcyc_ps) + 10; + cycle_5_0_clk = MULDIV64(ONE_BILLION, 1000, max_5_0_tcyc_ps) + 10; + debug("cycle_2_0_clk = %d\n", cycle_2_0_clk); + debug("cycle_3_0_clk = %d\n", cycle_3_0_clk); + debug("cycle_4_0_clk = %d\n", cycle_4_0_clk); + debug("cycle_5_0_clk = %d\n", cycle_5_0_clk); + + if ((cas_available & 0x04) && (sdram_freq <= cycle_2_0_clk)) { + *cas_latency = 2; + ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x2) | + DDR0_03_CASLAT_LIN_ENCODE(0x4); + } else if ((cas_available & 0x08) && (sdram_freq <= cycle_3_0_clk)) { + *cas_latency = 3; + ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x3) | + DDR0_03_CASLAT_LIN_ENCODE(0x6); + } else if ((cas_available & 0x10) && (sdram_freq <= cycle_4_0_clk)) { + *cas_latency = 4; + ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x4) | + DDR0_03_CASLAT_LIN_ENCODE(0x8); + } else if ((cas_available & 0x20) && (sdram_freq <= cycle_5_0_clk)) { + *cas_latency = 5; + ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x5) | + DDR0_03_CASLAT_LIN_ENCODE(0xA); + } else { + printf("ERROR: Cannot find a supported CAS latency with the " + "installed DIMMs.\n"); + printf("Only DDR2 DIMMs with CAS latencies of 2.0, 3.0, 4.0, " + "and 5.0 are supported.\n"); + printf("Make sure the PLB speed is within the supported range " + "of the DIMMs.\n"); + printf("sdram_freq=%d cycle2=%d cycle3=%d cycle4=%d " + "cycle5=%d\n\n", sdram_freq, cycle_2_0_clk, + cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk); + spd_ddr_init_hang(); + } + debug("CAS latency = %d\n", *cas_latency); + mtsdram(DDR0_03, ddr0_03); +} + +static void program_ddr0_04(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq) +{ + unsigned long dimm_num; + unsigned long t_rc_ps = 0; + unsigned long t_rrd_ps = 0; + unsigned long t_rtp_ps = 0; + unsigned long t_rc_clk; + unsigned long t_rrd_clk; + unsigned long t_rtp_clk; + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned long ps; + + /* tRC */ + ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 41); + switch (spd_read(iic0_dimm_addr[dimm_num], 40) >> 4) { + case 0x1: + ps += 250; + break; + case 0x2: + ps += 333; + break; + case 0x3: + ps += 500; + break; + case 0x4: + ps += 667; + break; + case 0x5: + ps += 750; + break; + } + t_rc_ps = max(t_rc_ps, ps); + /* tRRD */ + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 28); + t_rrd_ps = max(t_rrd_ps, ps); + /* tRTP */ + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 38); + t_rtp_ps = max(t_rtp_ps, ps); + } + } + debug("t_rc_ps = %d\n", t_rc_ps); + t_rc_clk = (MULDIV64(sdram_freq, t_rc_ps, ONE_BILLION) + 999) / 1000; + debug("t_rrd_ps = %d\n", t_rrd_ps); + t_rrd_clk = (MULDIV64(sdram_freq, t_rrd_ps, ONE_BILLION) + 999) / 1000; + debug("t_rtp_ps = %d\n", t_rtp_ps); + t_rtp_clk = (MULDIV64(sdram_freq, t_rtp_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_04, DDR0_04_TRC_ENCODE(t_rc_clk) | + DDR0_04_TRRD_ENCODE(t_rrd_clk) | + DDR0_04_TRTP_ENCODE(t_rtp_clk)); +} + +static void program_ddr0_05(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq) +{ + unsigned long dimm_num; + unsigned long t_rp_ps = 0; + unsigned long t_ras_ps = 0; + unsigned long t_rp_clk; + unsigned long t_ras_clk; + u32 ddr0_05 = DDR0_05_TMRD_ENCODE(0x2) | DDR0_05_TEMRS_ENCODE(0x2); + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned long ps; + + /* tRP */ + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 27); + t_rp_ps = max(t_rp_ps, ps); + /* tRAS */ + ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 30); + t_ras_ps = max(t_ras_ps, ps); + } + } + debug("t_rp_ps = %d\n", t_rp_ps); + t_rp_clk = (MULDIV64(sdram_freq, t_rp_ps, ONE_BILLION) + 999) / 1000; + debug("t_ras_ps = %d\n", t_ras_ps); + t_ras_clk = (MULDIV64(sdram_freq, t_ras_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_05, ddr0_05 | DDR0_05_TRP_ENCODE(t_rp_clk) | + DDR0_05_TRAS_MIN_ENCODE(t_ras_clk)); +} + +static void program_ddr0_06(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq) +{ + unsigned long dimm_num; + unsigned char spd_40; + unsigned long t_wtr_ps = 0; + unsigned long t_rfc_ps = 0; + unsigned long t_wtr_clk; + unsigned long t_rfc_clk; + u32 ddr0_06 = + DDR0_06_WRITEINTERP_ENCODE(0x1) | DDR0_06_TDLL_ENCODE(200); + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned long ps; + + /* tWTR */ + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 37); + t_wtr_ps = max(t_wtr_ps, ps); + /* tRFC */ + ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 42); + spd_40 = spd_read(iic0_dimm_addr[dimm_num], 40); + ps += 256000 * (spd_40 & 0x01); + switch ((spd_40 & 0x0E) >> 1) { + case 0x1: + ps += 250; + break; + case 0x2: + ps += 333; + break; + case 0x3: + ps += 500; + break; + case 0x4: + ps += 667; + break; + case 0x5: + ps += 750; + break; + } + t_rfc_ps = max(t_rfc_ps, ps); + } + } + debug("t_wtr_ps = %d\n", t_wtr_ps); + t_wtr_clk = (MULDIV64(sdram_freq, t_wtr_ps, ONE_BILLION) + 999) / 1000; + debug("t_rfc_ps = %d\n", t_rfc_ps); + t_rfc_clk = (MULDIV64(sdram_freq, t_rfc_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_06, ddr0_06 | DDR0_06_TWTR_ENCODE(t_wtr_clk) | + DDR0_06_TRFC_ENCODE(t_rfc_clk)); +} + +static void program_ddr0_10(unsigned long dimm_ranks[], unsigned long ranks) +{ + unsigned long csmap; + + if (2 == ranks) { + /* Both chip selects in use */ + csmap = 0x03; + } else { + /* One chip select in use */ + csmap = (1 == dimm_ranks[0]) ? 0x1 : 0x2; + } + mtsdram(DDR0_10, DDR0_10_WRITE_MODEREG_ENCODE(0x0) | + DDR0_10_CS_MAP_ENCODE(csmap) | + DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(0)); +} + +static void program_ddr0_11(unsigned long sdram_freq) +{ + unsigned long const t_xsnr_ps = 200000; /* 200 ns */ + unsigned long t_xsnr_clk; + + debug("t_xsnr_ps = %d\n", t_xsnr_ps); + t_xsnr_clk = + (MULDIV64(sdram_freq, t_xsnr_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_11, DDR0_11_SREFRESH_ENCODE(0) | + DDR0_11_TXSNR_ENCODE(t_xsnr_clk) | DDR0_11_TXSR_ENCODE(200)); +} + +static void program_ddr0_22(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, unsigned long width) +{ +#if defined(CONFIG_DDR_ECC) + unsigned long dimm_num; + unsigned long ecc_available = width >= 64; + u32 ddr0_22 = DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | + DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | + DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS); + + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + /* Check for ECC */ + if (0 == (spd_read(iic0_dimm_addr[dimm_num], 11) & + 0x02)) { + ecc_available = FALSE; + } + } + } + if (ecc_available) { + debug("ECC found on all DIMMs present\n"); + mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x3)); + } else { + debug("ECC not found on some or all DIMMs present\n"); + mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x0)); + } +#else + mtsdram(DDR0_22, DDR0_22_CTRL_RAW_ENCODE(0x0) | + DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) | + DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) | + DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS)); +#endif /* defined(CONFIG_DDR_ECC) */ +} + +static void program_ddr0_24(unsigned long ranks) +{ + u32 ddr0_24 = DDR0_24_RTT_PAD_TERMINATION_ENCODE(0x1) | /* 75 ohm */ + DDR0_24_ODT_RD_MAP_CS1_ENCODE(0x0); + + if (2 == ranks) { + /* Both chip selects in use */ + ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x1) | + DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x2); + } else { + /* One chip select in use */ + /* One of the two fields added to ddr0_24 is a "don't care" */ + ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x2) | + DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x1); + } + mtsdram(DDR0_24, ddr0_24); +} + +static void program_ddr0_26(unsigned long sdram_freq) +{ + unsigned long const t_ref_ps = 7800000; /* 7.8 us. refresh */ + /* TODO: check definition of tRAS_MAX */ + unsigned long const t_ras_max_ps = 9 * t_ref_ps; + unsigned long t_ras_max_clk; + unsigned long t_ref_clk; + + /* Round down t_ras_max_clk and t_ref_clk */ + debug("t_ras_max_ps = %d\n", t_ras_max_ps); + t_ras_max_clk = MULDIV64(sdram_freq, t_ras_max_ps, ONE_BILLION) / 1000; + debug("t_ref_ps = %d\n", t_ref_ps); + t_ref_clk = MULDIV64(sdram_freq, t_ref_ps, ONE_BILLION) / 1000; + mtsdram(DDR0_26, DDR0_26_TRAS_MAX_ENCODE(t_ras_max_clk) | + DDR0_26_TREF_ENCODE(t_ref_clk)); +} + +static void program_ddr0_27(unsigned long sdram_freq) +{ + unsigned long const t_init_ps = 200000000; /* 200 us. init */ + unsigned long t_init_clk; + + debug("t_init_ps = %d\n", t_init_ps); + t_init_clk = + (MULDIV64(sdram_freq, t_init_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_27, DDR0_27_EMRS_DATA_ENCODE(0x0000) | + DDR0_27_TINIT_ENCODE(t_init_clk)); +} + +static void program_ddr0_43(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq, + unsigned long cols, unsigned long banks) +{ + unsigned long dimm_num; + unsigned long t_wr_ps = 0; + unsigned long t_wr_clk; + u32 ddr0_43 = DDR0_43_APREBIT_ENCODE(10) | + DDR0_43_COLUMN_SIZE_ENCODE(12 - cols) | + DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0); + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned long ps; + + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 36); + t_wr_ps = max(t_wr_ps, ps); + } + } + debug("t_wr_ps = %d\n", t_wr_ps); + t_wr_clk = (MULDIV64(sdram_freq, t_wr_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_43, ddr0_43 | DDR0_43_TWR_ENCODE(t_wr_clk)); +} + +static void program_ddr0_44(unsigned long dimm_ranks[], + unsigned char const iic0_dimm_addr[], + unsigned long num_dimm_banks, + unsigned long sdram_freq) +{ + unsigned long dimm_num; + unsigned long t_rcd_ps = 0; + unsigned long t_rcd_clk; + + /*------------------------------------------------------------------ + * Handle the timing. We need to find the worst case timing of all + * the dimm modules installed. + *-----------------------------------------------------------------*/ + /* loop through all the DIMM slots on the board */ + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + /* If a dimm is installed in a particular slot ... */ + if (dimm_ranks[dimm_num]) { + unsigned long ps; + + ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 29); + t_rcd_ps = max(t_rcd_ps, ps); + } + } + debug("t_rcd_ps = %d\n", t_rcd_ps); + t_rcd_clk = (MULDIV64(sdram_freq, t_rcd_ps, ONE_BILLION) + 999) / 1000; + mtsdram(DDR0_44, DDR0_44_TRCD_ENCODE(t_rcd_clk)); +} + +/*-----------------------------------------------------------------------------+ + * initdram. Initializes the 440EPx/GPx DDR SDRAM controller. + * Note: This routine runs from flash with a stack set up in the chip's + * sram space. It is important that the routine does not require .sbss, .bss or + * .data sections. It also cannot call routines that require these sections. + *-----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------- + * Function: initdram + * Description: Configures SDRAM memory banks for DDR operation. + * Auto Memory Configuration option reads the DDR SDRAM EEPROMs + * via the IIC bus and then configures the DDR SDRAM memory + * banks appropriately. If Auto Memory Configuration is + * not used, it is assumed that no DIMM is plugged + *-----------------------------------------------------------------------------*/ +long int initdram(int board_type) +{ + unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; + unsigned long dimm_ranks[MAXDIMMS]; + unsigned long ranks; + unsigned long rows; + unsigned long banks; + unsigned long cols; + unsigned long width; + unsigned long const sdram_freq = get_bus_freq(0); + unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */ + unsigned long cas_latency = 0; /* to quiet initialization warning */ + unsigned long dram_size; + + debug("\nEntering initdram()\n"); + + /*------------------------------------------------------------------ + * Stop the DDR-SDRAM controller. + *-----------------------------------------------------------------*/ + mtsdram(DDR0_02, DDR0_02_START_ENCODE(0)); + + /* + * Make sure I2C controller is initialized + * before continuing. + */ + /* switch to correct I2C bus */ + I2C_SET_BUS(CFG_SPD_BUS_NUM); + i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + + /*------------------------------------------------------------------ + * Clear out the serial presence detect buffers. + * Perform IIC reads from the dimm. Fill in the spds. + * Check to see if the dimm slots are populated + *-----------------------------------------------------------------*/ + get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks); + + /*------------------------------------------------------------------ + * Check the frequency supported for the dimms plugged. + *-----------------------------------------------------------------*/ + check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); + + /*------------------------------------------------------------------ + * Check and get size information. + *-----------------------------------------------------------------*/ + get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks, + &cols, &width); + + /*------------------------------------------------------------------ + * Check the voltage type for the dimms plugged. + *-----------------------------------------------------------------*/ + check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks); + + /*------------------------------------------------------------------ + * Program registers for SDRAM controller. + *-----------------------------------------------------------------*/ + mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) | + DDR0_00_DLL_START_POINT_DECODE(0x0A)); + + mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) | + DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) | + DDR0_01_INT_MASK_ENCODE(0xFF)); + + program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, + rows, &cas_latency); + + program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); + + program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); + + 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. + *-----------------------------------------------------------------*/ + mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) | + DDR0_07_TFAW_ENCODE(13) | + DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) | + DDR0_07_AREFRESH_ENCODE(0)); + + mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) | + DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) | + DDR0_08_DDRII_ENCODE(1)); + + mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) | + DDR0_09_RTT_0_ENCODE(0x1) | + DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) | + DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20)); + + program_ddr0_10(dimm_ranks, ranks); + + program_ddr0_11(sdram_freq); + + mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3)); + + mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) | + DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) | + DDR0_14_REG_DIMM_ENABLE_ENCODE(0)); + + mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY)); + + mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) | + DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) | + DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) | + DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY)); + + mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) | + DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) | + DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) | + DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY)); + + mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) | + DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) | + DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) | + DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS)); + + mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) | + DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) | + DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) | + DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS)); + + program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width); + + mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) | + DDR0_23_FWC_ENCODE(0)); + + program_ddr0_24(ranks); + + program_ddr0_26(sdram_freq); + + program_ddr0_27(sdram_freq); + + mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) | + DDR0_28_EMRS2_DATA_ENCODE(0x0000)); + + mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000)); + + mtsdram(DDR0_42, DDR0_42_ADDR_PINS_DECODE(14 - rows) | + DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency)); + + program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq, + cols, banks); + + program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq); + + denali_sdram_register_dump(); + + dram_size = (width >= 64) ? 8 : 4; + dram_size *= 1 << cols; + dram_size *= banks; + dram_size *= 1 << rows; + dram_size *= ranks; + debug("dram_size = %lu\n", dram_size); + + /* Start the SDRAM controler */ + mtsdram(DDR0_02, DDR0_02_START_ENCODE(1)); + 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); + denali_core_search_data_eye(); + denali_sdram_register_dump(); + remove_tlb(CFG_SDRAM_BASE, dram_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); + dflush(); + debug("Completed\n"); + sync(); + eieio(); + remove_tlb(CFG_SDRAM_BASE, dram_size); + +#if defined(CONFIG_DDR_ECC) + /* + * If ECC is enabled, clear and enable interrupts + */ + if (is_ecc_enabled()) { + u32 val; + + sync(); + eieio(); + /* Clear error status */ + mfsdram(DDR0_00, val); + mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL); + /* Set 'int_mask' parameter to functionnal value */ + mfsdram(DDR0_01, val); + mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) | + DDR0_01_INT_MASK_ALL_OFF); +#if defined(CONFIG_DDR_DATA_EYE) + /* + * Running denali_core_search_data_eye() when ECC is enabled + * causes non-ECC machine checks. This clears them. + */ + print_mcsr(); + mtspr(SPRN_MCSR, mfspr(SPRN_MCSR)); + print_mcsr(); +#endif + sync(); + eieio(); + } +#endif /* defined(CONFIG_DDR_ECC) */ +#endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */ + + program_tlb(0, CFG_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE); + return dram_size; +} + +void board_add_ram_info(int use_default) +{ + u32 val; + + printf(" (ECC"); + if (!is_ecc_enabled()) { + printf(" not"); + } + printf(" enabled, %d MHz", (2 * get_bus_freq(0)) / 1000000); + + mfsdram(DDR0_03, val); + printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1); +} +#endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/ppc4xx/fdt.c b/cpu/ppc4xx/fdt.c new file mode 100644 index 0000000..afcb974 --- /dev/null +++ b/cpu/ppc4xx/fdt.c @@ -0,0 +1,64 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 <command.h> +#include <asm/cache.h> +#include <ppc4xx.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#include <fdt_support.h> + +DECLARE_GLOBAL_DATA_PTR; + +void ft_cpu_setup(void *blob, bd_t *bd) +{ + sys_info_t sys_info; + + get_sys_info(&sys_info); + + do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "timebase-frequency", + bd->bi_intfreq, 1); + do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "clock-frequency", + bd->bi_intfreq, 1); + do_fixup_by_path_u32(blob, "/plb", "clock-frequency", sys_info.freqPLB, 1); + do_fixup_by_path_u32(blob, "/plb/opb", "clock-frequency", sys_info.freqOPB, 1); + do_fixup_by_path_u32(blob, "/plb/opb/ebc", "clock-frequency", + sys_info.freqEBC, 1); + fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); + + /* + * Setup all baudrates for the UARTs + */ + do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1); + + /* + * Fixup all ethernet nodes + * Note: aliases in the dts are required for this + */ + fdt_fixup_ethernet(blob, bd); +} +#endif /* CONFIG_OF_LIBFDT */ diff --git a/cpu/ppc4xx/gpio.c b/cpu/ppc4xx/gpio.c index 50f2fdf..37d3fa8 100644 --- a/cpu/ppc4xx/gpio.c +++ b/cpu/ppc4xx/gpio.c @@ -26,8 +26,8 @@ #include <asm/io.h> #include <asm/gpio.h> -#if defined(CFG_440_GPIO_TABLE) -gpio_param_s gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_440_GPIO_TABLE; +#if defined(CFG_4xx_GPIO_TABLE) +gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CFG_4xx_GPIO_TABLE; #endif #if defined(GPIO0_OSRL) @@ -47,7 +47,7 @@ void gpio_config(int pin, int in_out, int gpio_alt, int out_val) } if (pin >= GPIO_MAX/2) { - offs2 = 0x100; + offs2 = 0x4; pin2 = (pin - GPIO_MAX/2) << 1; } @@ -55,10 +55,10 @@ void gpio_config(int pin, int in_out, int gpio_alt, int out_val) mask2 = 0xc0000000 >> (pin2 << 1); /* first set TCR to 0 */ - out32(GPIO0_TCR + offs, in32(GPIO0_TCR + offs) & ~mask); + out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask); if (in_out == GPIO_OUT) { - val = in32(GPIO0_OSRL + offs + offs2) & ~mask2; + val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2; switch (gpio_alt) { case GPIO_ALT1: val |= GPIO_ALT1_SEL >> pin2; @@ -70,20 +70,23 @@ void gpio_config(int pin, int in_out, int gpio_alt, int out_val) val |= GPIO_ALT3_SEL >> pin2; break; } - out32(GPIO0_OSRL + offs + offs2, val); + out_be32((void *)GPIO0_OSRL + offs + offs2, val); /* setup requested output value */ if (out_val == GPIO_OUT_0) - out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) & ~mask); + out_be32((void *)GPIO0_OR + offs, + in_be32((void *)GPIO0_OR + offs) & ~mask); else if (out_val == GPIO_OUT_1) - out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) | mask); + out_be32((void *)GPIO0_OR + offs, + in_be32((void *)GPIO0_OR + offs) | mask); /* now configure TCR to drive output if selected */ - out32(GPIO0_TCR + offs, in32(GPIO0_TCR + offs) | mask); + out_be32((void *)GPIO0_TCR + offs, + in_be32((void *)GPIO0_TCR + offs) | mask); } else { - val = in32(GPIO0_ISR1L + offs + offs2) & ~mask2; + val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2; val |= GPIO_IN_SEL >> pin2; - out32(GPIO0_ISR1L + offs + offs2, val); + out_be32((void *)GPIO0_ISR1L + offs + offs2, val); } } #endif /* GPIO_OSRL */ @@ -98,9 +101,11 @@ void gpio_write_bit(int pin, int val) } if (val) - out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) | GPIO_VAL(pin)); + out_be32((void *)GPIO0_OR + offs, + in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin)); else - out32(GPIO0_OR + offs, in32(GPIO0_OR + offs) & ~GPIO_VAL(pin)); + out_be32((void *)GPIO0_OR + offs, + in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin)); } int gpio_read_out_bit(int pin) @@ -112,10 +117,22 @@ int gpio_read_out_bit(int pin) pin -= GPIO_MAX; } - return (in32(GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0); + return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0); } -#if defined(CFG_440_GPIO_TABLE) +int gpio_read_in_bit(int pin) +{ + u32 offs = 0; + + if (pin >= GPIO_MAX) { + offs = 0x100; + pin -= GPIO_MAX; + } + + return (in_be32((void *)GPIO0_IR + offs) & GPIO_VAL(pin) ? 1 : 0); +} + +#if defined(CFG_4xx_GPIO_TABLE) void gpio_set_chip_configuration(void) { unsigned char i=0, j=0, offs=0, gpio_core; @@ -141,24 +158,24 @@ void gpio_set_chip_configuration(void) break; case GPIO_ALT1: - reg = in32(GPIO_IS1(core_add+offs)) + reg = in_be32((void *)GPIO_IS1(core_add+offs)) & ~(GPIO_MASK >> (j*2)); reg = reg | (GPIO_IN_SEL >> (j*2)); - out32(GPIO_IS1(core_add+offs), reg); + out_be32((void *)GPIO_IS1(core_add+offs), reg); break; case GPIO_ALT2: - reg = in32(GPIO_IS2(core_add+offs)) + reg = in_be32((void *)GPIO_IS2(core_add+offs)) & ~(GPIO_MASK >> (j*2)); reg = reg | (GPIO_IN_SEL >> (j*2)); - out32(GPIO_IS2(core_add+offs), reg); + out_be32((void *)GPIO_IS2(core_add+offs), reg); break; case GPIO_ALT3: - reg = in32(GPIO_IS3(core_add+offs)) + reg = in_be32((void *)GPIO_IS3(core_add+offs)) & ~(GPIO_MASK >> (j*2)); reg = reg | (GPIO_IN_SEL >> (j*2)); - out32(GPIO_IS3(core_add+offs), reg); + out_be32((void *)GPIO_IS3(core_add+offs), reg); break; } } @@ -166,89 +183,73 @@ void gpio_set_chip_configuration(void) if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) || (gpio_tab[gpio_core][i].in_out == GPIO_BI)) { + u32 gpio_alt_sel = 0; + switch (gpio_tab[gpio_core][i].alt_nb) { case GPIO_SEL: - if (gpio_core == GPIO0) { - /* - * Setup output value - * 1 -> high level - * 0 -> low level - * else -> don't touch - */ - reg = in32(GPIO0_OR); - if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) - reg |= (0x80000000 >> (i)); - else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) - reg &= ~(0x80000000 >> (i)); - out32(GPIO0_OR, reg); - - reg = in32(GPIO0_TCR) | (0x80000000 >> (i)); - out32(GPIO0_TCR, reg); - } - -#ifdef GPIO1 - if (gpio_core == GPIO1) { - /* - * Setup output value - * 1 -> high level - * 0 -> low level - * else -> don't touch - */ - reg = in32(GPIO1_OR); - if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) - reg |= (0x80000000 >> (i)); - else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) - reg &= ~(0x80000000 >> (i)); - out32(GPIO1_OR, reg); - - reg = in32(GPIO1_TCR) | (0x80000000 >> (i)); - out32(GPIO1_TCR, reg); - } -#endif /* GPIO1 */ - - reg = in32(GPIO_OS(core_add+offs)) + /* + * Setup output value + * 1 -> high level + * 0 -> low level + * else -> don't touch + */ + reg = in_be32((void *)GPIO_OR(core_add)); + if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) + reg |= (0x80000000 >> (i)); + else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0) + reg &= ~(0x80000000 >> (i)); + out_be32((void *)GPIO_OR(core_add), reg); + + reg = in_be32((void *)GPIO_TCR(core_add)) | + (0x80000000 >> (i)); + out_be32((void *)GPIO_TCR(core_add), reg); + + reg = in_be32((void *)GPIO_OS(core_add+offs)) & ~(GPIO_MASK >> (j*2)); - out32(GPIO_OS(core_add+offs), reg); - reg = in32(GPIO_TS(core_add+offs)) + out_be32((void *)GPIO_OS(core_add+offs), reg); + reg = in_be32((void *)GPIO_TS(core_add+offs)) & ~(GPIO_MASK >> (j*2)); - out32(GPIO_TS(core_add+offs), reg); + out_be32((void *)GPIO_TS(core_add+offs), reg); break; case GPIO_ALT1: - reg = in32(GPIO_OS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT1_SEL >> (j*2)); - out32(GPIO_OS(core_add+offs), reg); - reg = in32(GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT1_SEL >> (j*2)); - out32(GPIO_TS(core_add+offs), reg); + gpio_alt_sel = GPIO_ALT1_SEL; break; case GPIO_ALT2: - reg = in32(GPIO_OS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT2_SEL >> (j*2)); - out32(GPIO_OS(core_add+offs), reg); - reg = in32(GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT2_SEL >> (j*2)); - out32(GPIO_TS(core_add+offs), reg); + gpio_alt_sel = GPIO_ALT2_SEL; break; case GPIO_ALT3: - reg = in32(GPIO_OS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT3_SEL >> (j*2)); - out32(GPIO_OS(core_add+offs), reg); - reg = in32(GPIO_TS(core_add+offs)) - & ~(GPIO_MASK >> (j*2)); - reg = reg | (GPIO_ALT3_SEL >> (j*2)); - out32(GPIO_TS(core_add+offs), reg); + gpio_alt_sel = GPIO_ALT3_SEL; break; } + + if (0 != gpio_alt_sel) { + reg = in_be32((void *)GPIO_OS(core_add+offs)) + & ~(GPIO_MASK >> (j*2)); + reg = reg | (gpio_alt_sel >> (j*2)); + out_be32((void *)GPIO_OS(core_add+offs), reg); + + if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) { + reg = in_be32((void *)GPIO_TCR(core_add)) + | (0x80000000 >> (i)); + out_be32((void *)GPIO_TCR(core_add), reg); + reg = in_be32((void *)GPIO_TS(core_add+offs)) + & ~(GPIO_MASK >> (j*2)); + out_be32((void *)GPIO_TS(core_add+offs), reg); + } else { + reg = in_be32((void *)GPIO_TCR(core_add)) + & ~(0x80000000 >> (i)); + out_be32((void *)GPIO_TCR(core_add), reg); + reg = in_be32((void *)GPIO_TS(core_add+offs)) + & ~(GPIO_MASK >> (j*2)); + reg = reg | (gpio_alt_sel >> (j*2)); + out_be32((void *)GPIO_TS(core_add+offs), reg); + } + } } } } } -#endif /* CFG_440_GPIO_TABLE */ +#endif /* CFG_4xx_GPIO_TABLE */ diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index ca565cc..2f3dc32 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -34,7 +34,7 @@ #include <ppc4xx.h> #include <ppc_asm.tmpl> #include <commproc.h> -#include "vecnum.h" +#include <asm/ppc4xx-intvec.h> DECLARE_GLOBAL_DATA_PTR; @@ -52,7 +52,7 @@ struct irq_action { static struct irq_action irq_vecs[32]; void uic0_interrupt( void * parms); /* UIC0 handler */ -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) static struct irq_action irq_vecs1[32]; /* For UIC1 */ void uic1_interrupt( void * parms); /* UIC1 handler */ @@ -116,7 +116,7 @@ int interrupt_init_cpu (unsigned *decrementer_count) irq_vecs[vec].handler = NULL; irq_vecs[vec].arg = NULL; irq_vecs[vec].count = 0; -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) irq_vecs1[vec].handler = NULL; irq_vecs1[vec].arg = NULL; irq_vecs1[vec].count = 0; @@ -172,7 +172,7 @@ int interrupt_init_cpu (unsigned *decrementer_count) */ set_evpr(0x00000000); -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) #if !defined(CONFIG_440GX) /* Install the UIC1 handlers */ irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0); @@ -378,7 +378,7 @@ void uic0_interrupt( void * parms) #endif /* CONFIG_440GX */ -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) /* Handler for UIC1 interrupt */ void uic1_interrupt( void * parms) { @@ -525,7 +525,7 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) struct irq_action *irqa = irq_vecs; int i = vec; -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) { @@ -553,7 +553,7 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) irqa[i].handler = handler; irqa[i].arg = arg; -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) @@ -577,7 +577,7 @@ void irq_free_handler (int vec) struct irq_action *irqa = irq_vecs; int i = vec; -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) { @@ -599,7 +599,7 @@ void irq_free_handler (int vec) vec, irq_vecs[vec].handler); #endif -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) @@ -641,7 +641,7 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int vec; printf ("\nInterrupt-Information:\n"); -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) printf ("\nUIC 0\n"); #endif printf ("Nr Routine Arg Count\n"); @@ -656,7 +656,7 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } } -#if defined(CONFIG_440) +#if defined(CONFIG_440) || defined(CONFIG_405EX) printf ("\nUIC 1\n"); printf ("Nr Routine Arg Count\n"); diff --git a/cpu/ppc4xx/iop480_uart.c b/cpu/ppc4xx/iop480_uart.c new file mode 100644 index 0000000..3af0767 --- /dev/null +++ b/cpu/ppc4xx/iop480_uart.c @@ -0,0 +1,238 @@ +/* + * (C) Copyright 2000-2006 + * 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 <commproc.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <watchdog.h> +#include <asm/ppc4xx-intvec.h> + +#ifdef CONFIG_SERIAL_MULTI +#include <serial.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_IOP480 + +#define SPU_BASE 0x40000000 + +#define spu_LineStat_rc 0x00 /* Line Status Register (Read/Clear) */ +#define spu_LineStat_w 0x04 /* Line Status Register (Set) */ +#define spu_Handshk_rc 0x08 /* Handshake Status Register (Read/Clear) */ +#define spu_Handshk_w 0x0c /* Handshake Status Register (Set) */ +#define spu_BRateDivh 0x10 /* Baud rate divisor high */ +#define spu_BRateDivl 0x14 /* Baud rate divisor low */ +#define spu_CtlReg 0x18 /* Control Register */ +#define spu_RxCmd 0x1c /* Rx Command Register */ +#define spu_TxCmd 0x20 /* Tx Command Register */ +#define spu_RxBuff 0x24 /* Rx data buffer */ +#define spu_TxBuff 0x24 /* Tx data buffer */ + +/*-----------------------------------------------------------------------------+ + | Line Status Register. + +-----------------------------------------------------------------------------*/ +#define asyncLSRport1 0x40000000 +#define asyncLSRport1set 0x40000004 +#define asyncLSRDataReady 0x80 +#define asyncLSRFramingError 0x40 +#define asyncLSROverrunError 0x20 +#define asyncLSRParityError 0x10 +#define asyncLSRBreakInterrupt 0x08 +#define asyncLSRTxHoldEmpty 0x04 +#define asyncLSRTxShiftEmpty 0x02 + +/*-----------------------------------------------------------------------------+ + | Handshake Status Register. + +-----------------------------------------------------------------------------*/ +#define asyncHSRport1 0x40000008 +#define asyncHSRport1set 0x4000000c +#define asyncHSRDsr 0x80 +#define asyncLSRCts 0x40 + +/*-----------------------------------------------------------------------------+ + | Control Register. + +-----------------------------------------------------------------------------*/ +#define asyncCRport1 0x40000018 +#define asyncCRNormal 0x00 +#define asyncCRLoopback 0x40 +#define asyncCRAutoEcho 0x80 +#define asyncCRDtr 0x20 +#define asyncCRRts 0x10 +#define asyncCRWordLength7 0x00 +#define asyncCRWordLength8 0x08 +#define asyncCRParityDisable 0x00 +#define asyncCRParityEnable 0x04 +#define asyncCREvenParity 0x00 +#define asyncCROddParity 0x02 +#define asyncCRStopBitsOne 0x00 +#define asyncCRStopBitsTwo 0x01 +#define asyncCRDisableDtrRts 0x00 + +/*-----------------------------------------------------------------------------+ + | Receiver Command Register. + +-----------------------------------------------------------------------------*/ +#define asyncRCRport1 0x4000001c +#define asyncRCRDisable 0x00 +#define asyncRCREnable 0x80 +#define asyncRCRIntDisable 0x00 +#define asyncRCRIntEnabled 0x20 +#define asyncRCRDMACh2 0x40 +#define asyncRCRDMACh3 0x60 +#define asyncRCRErrorInt 0x10 +#define asyncRCRPauseEnable 0x08 + +/*-----------------------------------------------------------------------------+ + | Transmitter Command Register. + +-----------------------------------------------------------------------------*/ +#define asyncTCRport1 0x40000020 +#define asyncTCRDisable 0x00 +#define asyncTCREnable 0x80 +#define asyncTCRIntDisable 0x00 +#define asyncTCRIntEnabled 0x20 +#define asyncTCRDMACh2 0x40 +#define asyncTCRDMACh3 0x60 +#define asyncTCRTxEmpty 0x10 +#define asyncTCRErrorInt 0x08 +#define asyncTCRStopPause 0x04 +#define asyncTCRBreakGen 0x02 + +/*-----------------------------------------------------------------------------+ + | Miscellanies defines. + +-----------------------------------------------------------------------------*/ +#define asyncTxBufferport1 0x40000024 +#define asyncRxBufferport1 0x40000024 +#define asyncDLABLsbport1 0x40000014 +#define asyncDLABMsbport1 0x40000010 +#define asyncXOFFchar 0x13 +#define asyncXONchar 0x11 + +/* + * Minimal serial functions needed to use one of the SMC ports + * as serial console interface. + */ + +int serial_init (void) +{ + volatile char val; + unsigned short br_reg; + + br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); + + /* + * Init onboard UART + */ + out_8((u8 *)SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */ + out_8((u8 *)SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ + out_8((u8 *)SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */ + out_8((u8 *)SPU_BASE + spu_CtlReg, 0x08); /* Set 8 bits, no parity and 1 stop bit */ + out_8((u8 *)SPU_BASE + spu_RxCmd, 0xb0); /* Enable Rx */ + out_8((u8 *)SPU_BASE + spu_TxCmd, 0x9c); /* Enable Tx */ + out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ + val = in_8((u8 *)SPU_BASE + spu_RxBuff); /* Dummy read, to clear receiver */ + + return (0); +} + +void serial_setbrg (void) +{ + unsigned short br_reg; + + br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); + + out_8((u8 *)SPU_BASE + spu_BRateDivl, + (br_reg & 0x00ff)); /* Set baud rate divisor... */ + out_8((u8 *)SPU_BASE + spu_BRateDivh, + ((br_reg & 0xff00) >> 8)); /* ... */ +} + +void serial_putc (const char c) +{ + if (c == '\n') + serial_putc ('\r'); + + /* load status from handshake register */ + if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00) + out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ + + out_8((u8 *)SPU_BASE + spu_TxBuff, c); /* Put char */ + + while ((in_8((u8 *)SPU_BASE + spu_LineStat_rc) & 04) != 04) { + if (in_8((u8 *)SPU_BASE + spu_Handshk_rc) != 00) + out_8((u8 *)SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ + } +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc () +{ + unsigned char status = 0; + + while (1) { + status = in_8((u8 *)asyncLSRport1); + if ((status & asyncLSRDataReady) != 0x0) { + break; + } + if ((status & ( asyncLSRFramingError | + asyncLSROverrunError | + asyncLSRParityError | + asyncLSRBreakInterrupt )) != 0) { + (void) out_8((u8 *)asyncLSRport1, + asyncLSRFramingError | + asyncLSROverrunError | + asyncLSRParityError | + asyncLSRBreakInterrupt ); + } + } + return (0x000000ff & (int) in_8((u8 *)asyncRxBufferport1)); +} + +int serial_tstc () +{ + unsigned char status; + + status = in_8((u8 *)asyncLSRport1); + if ((status & asyncLSRDataReady) != 0x0) { + return (1); + } + if ((status & ( asyncLSRFramingError | + asyncLSROverrunError | + asyncLSRParityError | + asyncLSRBreakInterrupt )) != 0) { + (void) out_8((u8 *)asyncLSRport1, + asyncLSRFramingError | + asyncLSROverrunError | + asyncLSRParityError | + asyncLSRBreakInterrupt); + } + return 0; +} + +#endif /* CONFIG_IOP480 */ diff --git a/cpu/ppc4xx/kgdb.S b/cpu/ppc4xx/kgdb.S index 8c4bbf2..42b9546 100644 --- a/cpu/ppc4xx/kgdb.S +++ b/cpu/ppc4xx/kgdb.S @@ -56,21 +56,21 @@ kgdb_flush_cache_all: .globl kgdb_flush_cache_range kgdb_flush_cache_range: - li r5,CFG_CACHELINE_SIZE-1 + li r5,L1_CACHE_BYTES-1 andc r3,r3,r5 subf r4,r3,r4 add r4,r4,r5 - srwi. r4,r4,CFG_CACHELINE_SHIFT + srwi. r4,r4,L1_CACHE_SHIFT beqlr mtctr r4 mr r6,r3 1: dcbst 0,r3 - addi r3,r3,CFG_CACHELINE_SIZE + addi r3,r3,L1_CACHE_BYTES bdnz 1b sync /* wait for dcbst's to get to ram */ mtctr r4 2: icbi 0,r6 - addi r6,r6,CFG_CACHELINE_SIZE + addi r6,r6,L1_CACHE_BYTES bdnz 2b SYNC blr diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 6b98025..4216f0b 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -27,23 +27,11 @@ | | Author: Mark Wisner | - | Change Activity- - | - | Date Description of Change BY - | --------- --------------------- --- - | 05-May-99 Created MKW - | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to - | better match OPB speed. Also modified delay times. JWB - | 29-Jul-99 Added Full duplex support MKW - | 24-Aug-99 Removed printf from dp83843_duplex() JWB - | 19-Jul-00 Ported to esd cpci405 sr - | 23-Dec-03 Ported from miiphy.c to 440GX Travis Sawyer TBS - | <travis.sawyer@sandburst.com> - | +-----------------------------------------------------------------------------*/ #include <common.h> #include <asm/processor.h> +#include <asm/io.h> #include <ppc_asm.tmpl> #include <commproc.h> #include <ppc4xx_enet.h> @@ -60,7 +48,6 @@ void miiphy_dump (char *devname, unsigned char addr) unsigned long i; unsigned short data; - for (i = 0; i < 0x1A; i++) { if (miiphy_read (devname, addr, i, &data)) { printf ("read error for reg %lx\n", i); @@ -75,15 +62,86 @@ void miiphy_dump (char *devname, unsigned char addr) } /* end for loop */ } /* end dump */ - /***********************************************************/ /* (Re)start autonegotiation */ /***********************************************************/ int phy_setup_aneg (char *devname, unsigned char addr) { - unsigned short ctl, adv; + u16 bmcr; + +#if defined(CONFIG_PHY_DYNAMIC_ANEG) + /* + * Set up advertisement based on capablilities reported by the PHY. + * This should work for both copper and fiber. + */ + u16 bmsr; +#if defined(CONFIG_PHY_GIGE) + u16 exsr = 0x0000; +#endif + + miiphy_read (devname, addr, PHY_BMSR, &bmsr); + +#if defined(CONFIG_PHY_GIGE) + if (bmsr & PHY_BMSR_EXT_STAT) + miiphy_read (devname, addr, PHY_EXSR, &exsr); + + if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) { + /* 1000BASE-X */ + u16 anar = 0x0000; + + if (exsr & PHY_EXSR_1000XF) + anar |= PHY_X_ANLPAR_FD; + + if (exsr & PHY_EXSR_1000XH) + anar |= PHY_X_ANLPAR_HD; + + miiphy_write (devname, addr, PHY_ANAR, anar); + } else +#endif + { + u16 anar, btcr; + + miiphy_read (devname, addr, PHY_ANAR, &anar); + anar &= ~(0x5000 | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD | + PHY_ANLPAR_TX | PHY_ANLPAR_10FD | PHY_ANLPAR_10); + + miiphy_read (devname, addr, PHY_1000BTCR, &btcr); + btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD); + + if (bmsr & PHY_BMSR_100T4) + anar |= PHY_ANLPAR_T4; + + if (bmsr & PHY_BMSR_100TXF) + anar |= PHY_ANLPAR_TXFD; + + if (bmsr & PHY_BMSR_100TXH) + anar |= PHY_ANLPAR_TX; + + if (bmsr & PHY_BMSR_10TF) + anar |= PHY_ANLPAR_10FD; + + if (bmsr & PHY_BMSR_10TH) + anar |= PHY_ANLPAR_10; + + miiphy_write (devname, addr, PHY_ANAR, anar); + +#if defined(CONFIG_PHY_GIGE) + if (exsr & PHY_EXSR_1000TF) + btcr |= PHY_1000BTCR_1000FD; + + if (exsr & PHY_EXSR_1000TH) + btcr |= PHY_1000BTCR_1000HD; + + miiphy_write (devname, addr, PHY_1000BTCR, btcr); +#endif + } + +#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ + /* + * Set up standard advertisement + */ + u16 adv; - /* Setup standard advertise */ miiphy_read (devname, addr, PHY_ANAR, &adv); adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | @@ -94,15 +152,16 @@ int phy_setup_aneg (char *devname, unsigned char addr) adv |= (0x0300); miiphy_write (devname, addr, PHY_1000BTCR, adv); +#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ + /* Start/Restart aneg */ - miiphy_read (devname, addr, PHY_BMCR, &ctl); - ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); - miiphy_write (devname, addr, PHY_BMCR, ctl); + miiphy_read (devname, addr, PHY_BMCR, &bmcr); + bmcr |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); + miiphy_write (devname, addr, PHY_BMCR, bmcr); return 0; } - /***********************************************************/ /* read a phy reg and return the value with a rc */ /***********************************************************/ @@ -113,57 +172,70 @@ unsigned int miiphy_getemac_offset (void) unsigned long eoffset; /* Need to find out which mdi port we're using */ - zmii = in32 (ZMII_FER); + zmii = in_be32((void *)ZMII_FER); - if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0))) { + if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0))) /* using port 0 */ eoffset = 0; - } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1))) { + + else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1))) /* using port 1 */ eoffset = 0x100; - } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2))) { + + else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2))) /* using port 2 */ eoffset = 0x400; - } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3))) { + + else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3))) /* using port 3 */ eoffset = 0x600; - } else { + + else { /* None of the mdi ports are enabled! */ /* enable port 0 */ zmii |= ZMII_FER_MDI << ZMII_FER_V (0); - out32 (ZMII_FER, zmii); + out_be32((void *)ZMII_FER, zmii); eoffset = 0; /* need to soft reset port 0 */ - zmii = in32 (EMAC_M0); + zmii = in_be32((void *)EMAC_M0); zmii |= EMAC_M0_SRST; - out32 (EMAC_M0, zmii); + out_be32((void *)EMAC_M0, zmii); } return (eoffset); #else + +#if defined(CONFIG_NET_MULTI) && defined(CONFIG_405EX) + unsigned long rgmii; + int devnum = 1; + + rgmii = in_be32((void *)RGMII_FER); + if (rgmii & (1 << (19 - devnum))) + return 0x100; +#endif + return 0; #endif } - -int emac4xx_miiphy_read (char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) +int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg, + unsigned short *value) { unsigned long sta_reg; /* STA scratch area */ unsigned long i; unsigned long emac_reg; - emac_reg = miiphy_getemac_offset (); /* see if it is ready for 1000 nsec */ i = 0; /* see if it is ready for sec */ - while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { + while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == + EMAC_STACR_OC_MASK) { udelay (7); if (i > 5) { #ifdef ET_DEBUG - sta_reg = in32 (EMAC_STACR + emac_reg); + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); printf ("read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ printf ("read err 1\n"); #endif @@ -174,11 +246,12 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, sta_reg = reg; /* reg address */ /* set clock (50Mhz) and read flags */ #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ - sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ; + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) +#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ + sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ; #else - sta_reg |= EMAC_STACR_READ; + sta_reg |= EMAC_STACR_READ; #endif #else sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ; @@ -186,49 +259,47 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \ + !defined(CONFIG_405EX) sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; #endif sta_reg = sta_reg | (addr << 5); /* Phy address */ sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ - out32 (EMAC_STACR + emac_reg, sta_reg); + out_be32((void *)EMAC_STACR + emac_reg, sta_reg); #ifdef ET_DEBUG printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif - sta_reg = in32 (EMAC_STACR + emac_reg); + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG - printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ + printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif i = 0; while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { udelay (7); - if (i > 5) { + if (i > 5) return -1; - } + i++; - sta_reg = in32 (EMAC_STACR + emac_reg); + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG printf ("a22: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif } - if ((sta_reg & EMAC_STACR_PHYE) != 0) { + if ((sta_reg & EMAC_STACR_PHYE) != 0) return -1; - } - *value = *(short *) (&sta_reg); + *value = *(short *)(&sta_reg); return 0; - } /* phy_read */ - /***********************************************************/ /* write a phy reg and return the value with a rc */ /***********************************************************/ -int emac4xx_miiphy_write (char *devname, unsigned char addr, - unsigned char reg, unsigned short value) +int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg, + unsigned short value) { unsigned long sta_reg; /* STA scratch area */ unsigned long i; @@ -238,9 +309,11 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, /* see if it is ready for 1000 nsec */ i = 0; - while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { + while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == + EMAC_STACR_OC_MASK) { if (i > 5) return -1; + udelay (7); i++; } @@ -248,11 +321,12 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, sta_reg = reg; /* reg address */ /* set clock (50Mhz) and read flags */ #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ - defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ - sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE; + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_405EX) +#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ + sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE; #else - sta_reg |= EMAC_STACR_WRITE; + sta_reg |= EMAC_STACR_WRITE; #endif #else sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ; @@ -260,27 +334,29 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \ + !defined(CONFIG_405EX) sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */ #endif - sta_reg = sta_reg | ((unsigned long) addr << 5);/* Phy address */ - sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ + sta_reg = sta_reg | ((unsigned long)addr << 5); /* Phy address */ + sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ memcpy (&sta_reg, &value, 2); /* put in data */ - out32 (EMAC_STACR + emac_reg, sta_reg); + out_be32((void *)EMAC_STACR + emac_reg, sta_reg); /* wait for completion */ i = 0; - sta_reg = in32 (EMAC_STACR + emac_reg); + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG - printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ + printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { udelay (7); if (i > 5) return -1; + i++; - sta_reg = in32 (EMAC_STACR + emac_reg); + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG printf ("a32: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif @@ -288,6 +364,7 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, if ((sta_reg & EMAC_STACR_PHYE) != 0) return -1; + return 0; -} /* phy_write */ +} /* phy_write */ diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c index 3984577..ec1b38c 100644 --- a/cpu/ppc4xx/ndfc.c +++ b/cpu/ppc4xx/ndfc.c @@ -34,7 +34,7 @@ #if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \ (defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ - defined(CONFIG_405EZ)) + defined(CONFIG_405EZ) || defined(CONFIG_405EX)) #include <nand.h> #include <linux/mtd/ndfc.h> @@ -222,6 +222,7 @@ int board_nand_init(struct nand_chip *nand) */ board_nand_select_device(nand, cs); out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222); + return 0; } diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index da5330a..9006614 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000 + * (C) Copyright 2000-2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -37,7 +37,7 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_405GP) || defined(CONFIG_405CR) -void get_sys_info (PPC405_SYS_INFO * sysInfo) +void get_sys_info (PPC4xx_SYS_INFO * sysInfo) { unsigned long pllmr; unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); @@ -162,6 +162,8 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv; } } + + sysInfo->freqUART = sysInfo->freqProcessor; } @@ -173,7 +175,7 @@ ulong get_OPB_freq (void) { ulong val = 0; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; get_sys_info (&sys_info); val = sys_info.freqPLB / sys_info.pllOpbDiv; @@ -189,7 +191,7 @@ ulong get_OPB_freq (void) ulong get_PCI_freq (void) { ulong val; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; get_sys_info (&sys_info); val = sys_info.freqPLB / sys_info.pllPciDiv; @@ -216,7 +218,7 @@ void get_sys_info (sys_info_t *sysInfo) */ /* Decode CPR0_PLLD0 for divisors */ - mfclk(clk_plld, reg); + mfcpr(clk_plld, reg); temp = (reg & PLLD_FWDVA_MASK) >> 16; sysInfo->pllFwdDivA = temp ? temp : 16; temp = (reg & PLLD_FWDVB_MASK) >> 8; @@ -225,19 +227,19 @@ void get_sys_info (sys_info_t *sysInfo) sysInfo->pllFbkDiv = temp ? temp : 32; lfdiv = reg & PLLD_LFBDV_MASK; - mfclk(clk_opbd, reg); + mfcpr(clk_opbd, reg); temp = (reg & OPBDDV_MASK) >> 24; sysInfo->pllOpbDiv = temp ? temp : 4; - mfclk(clk_perd, reg); + mfcpr(clk_perd, reg); temp = (reg & PERDV_MASK) >> 24; sysInfo->pllExtBusDiv = temp ? temp : 8; - mfclk(clk_primbd, reg); + mfcpr(clk_primbd, reg); temp = (reg & PRBDV_MASK) >> 24; prbdv0 = temp ? temp : 8; - mfclk(clk_spcid, reg); + mfcpr(clk_spcid, reg); temp = (reg & SPCID_MASK) >> 24; sysInfo->pllPciDiv = temp ? temp : 4; @@ -246,7 +248,7 @@ void get_sys_info (sys_info_t *sysInfo) temp = (reg & PLLSYS0_SEL_MASK) >> 27; if (temp == 0) { /* PLL output */ /* Figure which pll to use */ - mfclk(clk_pllc, reg); + mfcpr(clk_pllc, reg); temp = (reg & PLLC_SRC_MASK) >> 29; if (!temp) /* PLLOUTA */ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA; @@ -263,8 +265,9 @@ void get_sys_info (sys_info_t *sysInfo) sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqPLB/sysInfo->pllExtBusDiv; + sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv; sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv; + sysInfo->freqUART = sysInfo->freqPLB; /* Figure which timer source to use */ if (mfspr(ccr1) & 0x0080) { /* External Clock, assume same as SYS_CLK */ @@ -277,6 +280,7 @@ void get_sys_info (sys_info_t *sysInfo) else /* Internal clock */ sysInfo->freqTmrClk = sysInfo->freqProcessor; } + /******************************************** * get_PCI_freq * return PCI bus freq in Hz @@ -317,8 +321,8 @@ void get_sys_info (sys_info_t * sysInfo) if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */ sysInfo->freqPLB >>= 1; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; - + sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; + sysInfo->freqUART = sysInfo->freqPLB; } #else void get_sys_info (sys_info_t * sysInfo) @@ -393,7 +397,7 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; + sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; #if defined(CONFIG_YUCCA) /* Determine PCI Clock Period */ @@ -403,7 +407,7 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); #endif - + sysInfo->freqUART = sysInfo->freqPLB; } #endif @@ -632,7 +636,8 @@ extern void get_sys_info (sys_info_t * sysInfo); extern ulong get_PCI_freq (void); #elif defined(CONFIG_AP1000) -void get_sys_info (sys_info_t * sysInfo) { +void get_sys_info (sys_info_t * sysInfo) +{ sysInfo->freqProcessor = 240 * 1000 * 1000; sysInfo->freqPLB = 80 * 1000 * 1000; sysInfo->freqPCI = 33 * 1000 * 1000; @@ -640,17 +645,16 @@ void get_sys_info (sys_info_t * sysInfo) { #elif defined(CONFIG_405) -void get_sys_info (sys_info_t * sysInfo) { - +void get_sys_info (sys_info_t * sysInfo) +{ sysInfo->freqVCOMhz=3125000; sysInfo->freqProcessor=12*1000*1000; sysInfo->freqPLB=50*1000*1000; sysInfo->freqPCI=66*1000*1000; - } #elif defined(CONFIG_405EP) -void get_sys_info (PPC405_SYS_INFO * sysInfo) +void get_sys_info (PPC4xx_SYS_INFO * sysInfo) { unsigned long pllmr0; unsigned long pllmr1; @@ -678,9 +682,8 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Determine FBK_DIV. */ sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20); - if (sysInfo->pllFbkDiv == 0) { + if (sysInfo->pllFbkDiv == 0) sysInfo->pllFbkDiv = 16; - } /* * Determine PLB_DIV. @@ -733,6 +736,10 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Determine PLB clock frequency */ sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv; + + sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv; + + sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv; } @@ -744,7 +751,7 @@ ulong get_OPB_freq (void) { ulong val = 0; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; get_sys_info (&sys_info); val = sys_info.freqPLB / sys_info.pllOpbDiv; @@ -760,7 +767,7 @@ ulong get_OPB_freq (void) ulong get_PCI_freq (void) { ulong val; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; get_sys_info (&sys_info); val = sys_info.freqPLB / sys_info.pllPciDiv; @@ -768,7 +775,7 @@ ulong get_PCI_freq (void) } #elif defined(CONFIG_405EZ) -void get_sys_info (PPC405_SYS_INFO * sysInfo) +void get_sys_info (PPC4xx_SYS_INFO * sysInfo) { unsigned long cpr_plld; unsigned long cpr_pllc; @@ -806,6 +813,7 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Read CPR_PRIMAD register */ mfcpr(cprprimad, cpr_primad); + /* * Determine PLB_DIV. */ @@ -856,6 +864,11 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) */ sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) / sysInfo->pllFwdDiv / sysInfo->pllPlbDiv; + + sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / + sysInfo->pllExtBusDiv; + + sysInfo->freqUART = sysInfo->freqVCOHz; } /******************************************** @@ -866,7 +879,7 @@ ulong get_OPB_freq (void) { ulong val = 0; - PPC405_SYS_INFO sys_info; + PPC4xx_SYS_INFO sys_info; get_sys_info (&sys_info); val = (CONFIG_SYS_CLK_FREQ * sys_info.pllFbkDiv) / sys_info.pllOpbDiv; @@ -874,13 +887,176 @@ ulong get_OPB_freq (void) return val; } +#elif defined(CONFIG_405EX) + +/* + * TODO: We need to get the CPR registers and calculate these values correctly!!!! + * We need the specs!!!! + */ +static unsigned char get_fbdv(unsigned char index) +{ + unsigned char ret = 0; + /* This is table should be 256 bytes. + * Only take first 52 values. + */ + unsigned char fbdv_tb[] = { + 0x00, 0xff, 0x7f, 0xfd, + 0x7a, 0xf5, 0x6a, 0xd5, + 0x2a, 0xd4, 0x29, 0xd3, + 0x26, 0xcc, 0x19, 0xb3, + 0x67, 0xce, 0x1d, 0xbb, + 0x77, 0xee, 0x5d, 0xba, + 0x74, 0xe9, 0x52, 0xa5, + 0x4b, 0x96, 0x2c, 0xd8, + 0x31, 0xe3, 0x46, 0x8d, + 0x1b, 0xb7, 0x6f, 0xde, + 0x3d, 0xfb, 0x76, 0xed, + 0x5a, 0xb5, 0x6b, 0xd6, + 0x2d, 0xdb, 0x36, 0xec, + + }; + + if ((index & 0x7f) == 0) + return 1; + while (ret < sizeof (fbdv_tb)) { + if (fbdv_tb[ret] == index) + break; + ret++; + } + ret++; + + return ret; +} + +#define PLL_FBK_PLL_LOCAL 0 +#define PLL_FBK_CPU 1 +#define PLL_FBK_PERCLK 5 + +void get_sys_info (sys_info_t * sysInfo) +{ + unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); + unsigned long m = 1; + unsigned int tmp; + unsigned char fwdva[16] = { + 1, 2, 14, 9, 4, 11, 16, 13, + 12, 5, 6, 15, 10, 7, 8, 3, + }; + unsigned char sel, cpudv0, plb2xDiv; + + mfcpr(cpr0_plld, tmp); + + /* + * Determine forward divider A + */ + sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */ + + /* + * Determine FBK_DIV. + */ + sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */ + + /* + * Determine PLBDV0 + */ + sysInfo->pllPlbDiv = 2; + + /* + * Determine PERDV0 + */ + mfcpr(cpr0_perd, tmp); + tmp = (tmp >> 24) & 0x03; + sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp; + + /* + * Determine OPBDV0 + */ + mfcpr(cpr0_opbd, tmp); + tmp = (tmp >> 24) & 0x03; + sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp; + + /* Determine PLB2XDV0 */ + mfcpr(cpr0_plbd, tmp); + tmp = (tmp >> 16) & 0x07; + plb2xDiv = (tmp == 0) ? 8 : tmp; + + /* Determine CPUDV0 */ + mfcpr(cpr0_cpud, tmp); + tmp = (tmp >> 24) & 0x07; + cpudv0 = (tmp == 0) ? 8 : tmp; + + /* Determine SEL(5:7) in CPR0_PLLC */ + mfcpr(cpr0_pllc, tmp); + sel = (tmp >> 24) & 0x07; + + /* + * Determine the M factor + * PLL local: M = FBDV + * CPU clock: M = FBDV * FWDVA * CPUDV0 + * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0 + * + */ + switch (sel) { + case PLL_FBK_CPU: + m = sysInfo->pllFwdDiv * cpudv0; + break; + case PLL_FBK_PERCLK: + m = sysInfo->pllFwdDiv * plb2xDiv * 2 + * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv; + break; + case PLL_FBK_PLL_LOCAL: + break; + default: + printf("%s unknown m\n", __FUNCTION__); + return; + + } + m *= sysInfo->pllFbkDiv; + + /* + * Determine VCO clock frequency + */ + sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / + (unsigned long long)sysClkPeriodPs; + + /* + * Determine CPU clock frequency + */ + sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0); + + /* + * Determine PLB clock frequency, ddr1x should be the same + */ + sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2); + sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; + sysInfo->freqDDR = sysInfo->freqPLB; + sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; + sysInfo->freqUART = sysInfo->freqPLB; +} + +/******************************************** + * get_OPB_freq + * return OPB bus freq in Hz + *********************************************/ +ulong get_OPB_freq (void) +{ + ulong val = 0; + + PPC4xx_SYS_INFO sys_info; + + get_sys_info (&sys_info); + val = sys_info.freqPLB / sys_info.pllOpbDiv; + + return val; +} + #endif int get_clocks (void) { #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440) || defined(CONFIG_405) + defined(CONFIG_405EX) || defined(CONFIG_405) || \ + defined(CONFIG_440) sys_info_t sys_info; get_sys_info (&sys_info); @@ -907,7 +1083,8 @@ ulong get_bus_freq (ulong dummy) #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440) || defined(CONFIG_405) + defined(CONFIG_405EX) || defined(CONFIG_405) || \ + defined(CONFIG_440) sys_info_t sys_info; get_sys_info (&sys_info); diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 9626b65..77c2aa4 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -636,6 +636,33 @@ _start: dcbz r0,r3 addi r3,r3,32 bdnz ..d_ag + + /* + * Lock the init-ram/stack in d-cache, so that other regions + * may use d-cache as well + * Note, that this current implementation locks exactly 4k + * of d-cache, so please make sure that you don't define a + * bigger init-ram area. Take a look at the lwmon5 440EPx + * implementation as a reference. + */ + msync + isync + /* 8. set TFLOOR/NFLOOR to 8 (-> 8*16*32 bytes locked -> 4k) */ + lis r1,0x0201 + ori r1,r1,0xf808 + mtspr dvlim,r1 + lis r1,0x0808 + ori r1,r1,0x0808 + mtspr dnv0,r1 + mtspr dnv1,r1 + mtspr dnv2,r1 + mtspr dnv3,r1 + mtspr dtv0,r1 + mtspr dtv1,r1 + mtspr dtv2,r1 + mtspr dtv3,r1 + msync + isync #endif /* CFG_INIT_RAM_DCACHE */ /* 440EP & 440GR are only 440er PPC's without internal SRAM */ @@ -800,7 +827,7 @@ _start: /*----------------------------------------------------------------------- */ /* Enable two 128MB cachable regions. */ /*----------------------------------------------------------------------- */ - addis r1,r0,0x8000 + addis r1,r0,0xc000 addi r1,r1,0x0001 mticcr r1 /* instruction cache */ @@ -823,12 +850,23 @@ _start: /*****************************************************************************/ #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_405) + defined(CONFIG_405EX) || defined(CONFIG_405) /*----------------------------------------------------------------------- */ /* Clear and set up some registers. */ /*----------------------------------------------------------------------- */ addi r4,r0,0x0000 +#if !defined(CONFIG_405EX) mtspr sgr,r4 +#else + /* + * On 405EX, completely clearing the SGR leads to PPC hangup + * upon PCIe configuration access. The PCIe memory regions + * need to be guarded! + */ + lis r3,0x0000 + ori r3,r3,0x7FFC + mtspr sgr,r3 +#endif mtspr dcwr,r4 mtesr r4 /* clear Exception Syndrome Reg */ mttcr r4 /* clear Timer Control Reg */ @@ -851,7 +889,7 @@ _start: /*----------------------------------------------------------------------- */ /* Enable two 128MB cachable regions. */ /*----------------------------------------------------------------------- */ - lis r4,0x8000 + lis r4,0xc000 ori r4,r4,0x0001 mticcr r4 /* instruction cache */ isync @@ -860,12 +898,34 @@ _start: ori r4,r4,0x0000 mtdccr r4 /* data cache */ -#if !(defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR)) +#if !(defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR)) || defined(CONFIG_405EX) /*----------------------------------------------------------------------- */ /* Tune the speed and size for flash CS0 */ /*----------------------------------------------------------------------- */ bl ext_bus_cntlr_init #endif +#if !(defined(CFG_INIT_DCACHE_CS) || defined(CFG_TEMP_STACK_OCM)) + /* + * Boards like the Kilauea (405EX) don't have OCM and can't use + * DCache for init-ram. So setup stack here directly after the + * SDRAM is initialized. + */ + lis r1, CFG_INIT_RAM_ADDR@h + ori r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */ + + li r0, 0 /* Make room for stack frame header and */ + stwu r0, -4(r1) /* clear final stack frame so that */ + stwu r0, -4(r1) /* stack backtraces terminate cleanly */ + /* + * Set up a dummy frame to store reset vector as return address. + * this causes stack underflow to reset board. + */ + stwu r1, -8(r1) /* Save back chain and move SP */ + lis r0, RESET_VECTOR@h /* Address of reset vector */ + ori r0, r0, RESET_VECTOR@l + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save return addr (underflow vect) */ +#endif /* !(CFG_INIT_DCACHE_CS || !CFG_TEM_STACK_OCM) */ #if defined(CONFIG_405EP) /*----------------------------------------------------------------------- */ @@ -983,7 +1043,7 @@ start_ram: ori r4,r4,0xa000 mtdcr ebccfgd,r4 - /* turn on data chache for this region */ + /* turn on data cache for this region */ lis r4,0x0080 mtdccr r4 @@ -1049,30 +1109,6 @@ start_ram: /*----------------------------------------------------------------------- */ bl sdram_init - /* - * Setup temporary stack pointer only for boards - * that do not use SDRAM SPD I2C stuff since it - * is already initialized to use DCACHE or OCM - * stacks. - */ -#if !(defined(CFG_INIT_DCACHE_CS) || defined(CFG_TEMP_STACK_OCM)) - lis r1, CFG_INIT_RAM_ADDR@h - ori r1,r1,CFG_INIT_SP_OFFSET /* set up the stack in SDRAM */ - - li r0, 0 /* Make room for stack frame header and */ - stwu r0, -4(r1) /* clear final stack frame so that */ - stwu r0, -4(r1) /* stack backtraces terminate cleanly */ - /* - * Set up a dummy frame to store reset vector as return address. - * this causes stack underflow to reset board. - */ - stwu r1, -8(r1) /* Save back chain and move SP */ - lis r0, RESET_VECTOR@h /* Address of reset vector */ - ori r0, r0, RESET_VECTOR@l - stwu r1, -8(r1) /* Save back chain and move SP */ - stw r0, +12(r1) /* Save return addr (underflow vect) */ -#endif /* !(CFG_INIT_DCACHE_CS || !CFG_TEM_STACK_OCM) */ - #ifdef CONFIG_NAND_SPL bl nand_boot /* will not return */ #else @@ -1211,111 +1247,6 @@ mck_return: #endif /* CONFIG_440 */ -/* - * Cache functions. - * - * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, - * although for some cache-ralated calls stubs have to be provided to satisfy - * symbols resolution. - * Icache-related functions are used in POST framework. - * - */ -#ifdef CONFIG_440 - .globl dcache_disable - .globl icache_disable - .globl icache_enable -dcache_disable: -icache_disable: -icache_enable: - blr - - .globl dcache_status - .globl icache_status -dcache_status: -icache_status: - mr r3, 0 - blr -#else -flush_dcache: - addis r9,r0,0x0002 /* set mask for EE and CE msr bits */ - ori r9,r9,0x8000 - mfmsr r12 /* save msr */ - andc r9,r12,r9 - mtmsr r9 /* disable EE and CE */ - addi r10,r0,0x0001 /* enable data cache for unused memory */ - mfdccr r9 /* region 0xF8000000-0xFFFFFFFF via */ - or r10,r10,r9 /* bit 31 in dccr */ - mtdccr r10 - - /* do loop for # of congruence classes. */ - lis r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS: for large cache sizes */ - ori r10,r10,(CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l - lis r11,(CFG_DCACHE_SIZE / 2)@ha /* D cache set size - 2 way sets */ - ori r11,r11,(CFG_DCACHE_SIZE / 2)@l /* D cache set size - 2 way sets */ - mtctr r10 - addi r10,r0,(0xE000-0x10000) /* start at 0xFFFFE000 */ - add r11,r10,r11 /* add to get to other side of cache line */ -..flush_dcache_loop: - lwz r3,0(r10) /* least recently used side */ - lwz r3,0(r11) /* the other side */ - dccci r0,r11 /* invalidate both sides */ - addi r10,r10,CFG_CACHELINE_SIZE /* bump to next line */ - addi r11,r11,CFG_CACHELINE_SIZE /* bump to next line */ - bdnz ..flush_dcache_loop - sync /* allow memory access to complete */ - mtdccr r9 /* restore dccr */ - mtmsr r12 /* restore msr */ - blr - - .globl icache_enable -icache_enable: - mflr r8 - bl invalidate_icache - mtlr r8 - isync - addis r3,r0, 0x8000 /* set bit 0 */ - mticcr r3 - blr - - .globl icache_disable -icache_disable: - addis r3,r0, 0x0000 /* clear bit 0 */ - mticcr r3 - isync - blr - - .globl icache_status -icache_status: - mficcr r3 - srwi r3, r3, 31 /* >>31 => select bit 0 */ - blr - - .globl dcache_enable -dcache_enable: - mflr r8 - bl invalidate_dcache - mtlr r8 - isync - addis r3,r0, 0x8000 /* set bit 0 */ - mtdccr r3 - blr - - .globl dcache_disable -dcache_disable: - mflr r8 - bl flush_dcache - mtlr r8 - addis r3,r0, 0x0000 /* clear bit 0 */ - mtdccr r3 - blr - - .globl dcache_status -dcache_status: - mfdccr r3 - srwi r3, r3, 31 /* >>31 => select bit 0 */ - blr -#endif - .globl get_pvr get_pvr: mfspr r3, PVR @@ -1421,6 +1352,51 @@ ppcSync: */ .globl relocate_code relocate_code: +#ifdef CONFIG_4xx_DCACHE + /* + * We need to flush the Init Data before the dcache will be + * invalidated + */ + + /* save regs */ + mr r9,r3 + mr r10,r4 + mr r11,r5 + + mr r3,r4 + addi r4,r4,0x200 /* should be enough for init data */ + bl flush_dcache_range + + /* restore regs */ + mr r3,r9 + mr r4,r10 + mr r5,r11 +#endif + +#ifdef CFG_INIT_RAM_DCACHE + /* + * Unlock the previously locked d-cache + */ + msync + isync + /* set TFLOOR/NFLOOR to 0 again */ + lis r6,0x0001 + ori r6,r6,0xf800 + mtspr dvlim,r6 + lis r6,0x0000 + ori r6,r6,0x0000 + mtspr dnv0,r6 + mtspr dnv1,r6 + mtspr dnv2,r6 + mtspr dnv3,r6 + mtspr dtv0,r6 + mtspr dtv1,r6 + mtspr dtv2,r6 + mtspr dtv3,r6 + msync + isync +#endif /* CFG_INIT_RAM_DCACHE */ + #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_440SP) || defined(CONFIG_440SPE) @@ -1432,7 +1408,11 @@ relocate_code: dccci 0,0 /* Invalidate data cache, now no longer our stack */ sync isync - addi r1,r0,0x0000 /* TLB entry #0 */ +#ifdef CFG_TLB_FOR_BOOT_FLASH + addi r1,r0,CFG_TLB_FOR_BOOT_FLASH /* Use defined TLB */ +#else + addi r1,r0,0x0000 /* Default TLB entry is #0 */ +#endif tlbre r0,r1,0x0002 /* Read contents */ ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */ tlbwe r0,r1,0x0002 /* Save it out */ @@ -1448,7 +1428,7 @@ relocate_code: ori r4, r4, CFG_MONITOR_BASE@l lwz r5, GOT(__init_end) sub r5, r5, r4 - li r6, CFG_CACHELINE_SIZE /* Cache Line Size */ + li r6, L1_CACHE_BYTES /* Cache Line Size */ /* * Fix GOT pointer: @@ -1566,16 +1546,25 @@ clear_bss: lwz r4,GOT(_end) cmplw 0, r3, r4 - beq 6f + beq 7f li r0, 0 -5: + + andi. r5, r4, 3 + beq 6f + sub r4, r4, r5 + mtctr r5 + mr r5, r4 +5: stb r0, 0(r5) + addi r5, r5, 1 + bdnz 5b +6: stw r0, 0(r3) addi r3, r3, 4 cmplw 0, r3, r4 - bne 5b -6: + bne 6b +7: mr r3, r9 /* Init Data pointer */ mr r4, r10 /* Destination Address */ bl board_init_r @@ -1711,6 +1700,7 @@ trap_reloc: rlwinm r8,r9,0,15,13 rlwinm r8,r8,0,17,15 mtmsr r8 + mfspr r8,dvlim addi r3,r0,0x0000 mtspr dvlim,r3 mfspr r3,ivpr @@ -1725,6 +1715,7 @@ trap_reloc: ..ag: dcbf r0,r3 addi r3,r3,-32 bdnz ..ag + mtspr dvlim,r8 sync mtmsr r9 blr @@ -1768,23 +1759,6 @@ in32: lwz 3,0x0000(3) blr -invalidate_icache: - iccci r0,r0 /* for 405, iccci invalidates the */ - blr /* entire I cache */ - -invalidate_dcache: - addi r6,0,0x0000 /* clear GPR 6 */ - /* Do loop for # of dcache congruence classes. */ - lis r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@ha /* TBS for large sized cache */ - ori r7, r7, (CFG_DCACHE_SIZE / CFG_CACHELINE_SIZE / 2)@l - /* NOTE: dccci invalidates both */ - mtctr r7 /* ways in the D cache */ -..dcloop: - dccci 0,r6 /* invalidate line */ - addi r6,r6, CFG_CACHELINE_SIZE /* bump to next line */ - bdnz ..dcloop - blr - /**************************************************************************/ /* PPC405EP specific stuff */ /**************************************************************************/ diff --git a/cpu/ppc4xx/tlb.c b/cpu/ppc4xx/tlb.c index 098694c..ed493f1 100644 --- a/cpu/ppc4xx/tlb.c +++ b/cpu/ppc4xx/tlb.c @@ -26,6 +26,7 @@ #if defined(CONFIG_440) #include <ppc440.h> +#include <asm/cache.h> #include <asm/io.h> #include <asm/mmu.h> @@ -42,7 +43,6 @@ void remove_tlb(u32 vaddr, u32 size) u32 tlb_vaddr; u32 tlb_size = 0; - /* First, find the index of a TLB entry not being used */ for (i=0; i<PPC4XX_TLB_SIZE; i++) { tlb_word0_value = mftlb1(i); tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value); @@ -96,6 +96,92 @@ void remove_tlb(u32 vaddr, u32 size) asm("isync"); } +/* + * Change the I attribute (cache inhibited) of a TLB or multiple TLB's. + * This function is used to either turn cache on or off in a specific + * memory area. + */ +void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value) +{ + int i; + u32 tlb_word0_value; + u32 tlb_word2_value; + u32 tlb_vaddr; + u32 tlb_size = 0; + + for (i=0; i<PPC4XX_TLB_SIZE; i++) { + tlb_word0_value = mftlb1(i); + tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value); + if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) && + (tlb_vaddr >= vaddr)) { + /* + * TLB is enabled and start address is lower or equal + * than the area we are looking for. Now we only have + * to check the size/end address for a match. + */ + switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) { + case TLB_WORD0_SIZE_1KB: + tlb_size = 1 << 10; + break; + case TLB_WORD0_SIZE_4KB: + tlb_size = 4 << 10; + break; + case TLB_WORD0_SIZE_16KB: + tlb_size = 16 << 10; + break; + case TLB_WORD0_SIZE_64KB: + tlb_size = 64 << 10; + break; + case TLB_WORD0_SIZE_256KB: + tlb_size = 256 << 10; + break; + case TLB_WORD0_SIZE_1MB: + tlb_size = 1 << 20; + break; + case TLB_WORD0_SIZE_16MB: + tlb_size = 16 << 20; + break; + case TLB_WORD0_SIZE_256MB: + tlb_size = 256 << 20; + break; + } + + /* + * Now check the end-address if it's in the range + */ + if ((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1)) { + /* + * Found a TLB in the range. + * Change cache attribute in tlb2 word. + */ + tlb_word2_value = + TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE | + TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE | + TLB_WORD2_W_DISABLE | tlb_word2_i_value | + TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE | + TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE | + TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE | + TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE | + TLB_WORD2_SR_ENABLE; + + /* + * Now either flush or invalidate the dcache + */ + if (tlb_word2_i_value) + flush_dcache(); + else + invalidate_dcache(); + + mttlb3(i, tlb_word2_value); + asm("iccci 0,0"); + } + } + } + + /* Execute an ISYNC instruction so that the new TLB entry takes effect */ + asm("isync"); +} + static int add_tlb_entry(unsigned long phys_addr, unsigned long virt_addr, unsigned long tlb_word0_size_value, diff --git a/cpu/ppc4xx/usb.c b/cpu/ppc4xx/usb.c index 272ed8c..cb8d5c7 100644 --- a/cpu/ppc4xx/usb.c +++ b/cpu/ppc4xx/usb.c @@ -25,25 +25,41 @@ #if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) +#ifdef CONFIG_4xx_DCACHE +#include <asm/mmu.h> +DECLARE_GLOBAL_DATA_PTR; +#endif + #include "usbdev.h" int usb_cpu_init(void) { +#ifdef CONFIG_4xx_DCACHE + /* disable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE); +#endif #if defined(CONFIG_440EP) || defined(CONFIG_440EPX) usb_dev_init(); #endif - return 0; } int usb_cpu_stop(void) { +#ifdef CONFIG_4xx_DCACHE + /* enable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif return 0; } int usb_cpu_init_fail(void) { +#ifdef CONFIG_4xx_DCACHE + /* enable cache */ + change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0); +#endif return 0; } diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c index 5924a6c..d71ba77 100644 --- a/cpu/ppc4xx/usbdev.c +++ b/cpu/ppc4xx/usbdev.c @@ -7,7 +7,7 @@ #include <usb.h> #include "usbdev.h" -#include "vecnum.h" +#include <asm/ppc4xx-intvec.h> #define USB_DT_DEVICE 0x01 #define USB_DT_CONFIG 0x02 diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h deleted file mode 100644 index bddf9e5..0000000 --- a/cpu/ppc4xx/vecnum.h +++ /dev/null @@ -1,299 +0,0 @@ -/* -* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com> -* -* 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 -*/ - -/* - * Interrupt vector number definitions to ease the - * 405 -- 440 porting pain ;-) - * - * NOTE: They're not all here yet ... update as needed. - * - */ - -#ifndef _VECNUMS_H_ -#define _VECNUMS_H_ - -#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) - -/* UIC 0 */ -#define VECNUM_U0 0 /* UART 0 */ -#define VECNUM_U1 1 /* UART 1 */ -#define VECNUM_IIC0 2 /* IIC */ -#define VECNUM_KRD 3 /* Kasumi Ready for data */ -#define VECNUM_KDA 4 /* Kasumi Data Available */ -#define VECNUM_PCRW 5 /* PCI command register write */ -#define VECNUM_PPM 6 /* PCI power management */ -#define VECNUM_IIC1 7 /* IIC */ -#define VECNUM_SPI 8 /* SPI */ -#define VECNUM_EPCISER 9 /* External PCI SERR */ -#define VECNUM_MTE 10 /* MAL TXEOB */ -#define VECNUM_MRE 11 /* MAL RXEOB */ -#define VECNUM_D0 12 /* DMA channel 0 */ -#define VECNUM_D1 13 /* DMA channel 1 */ -#define VECNUM_D2 14 /* DMA channel 2 */ -#define VECNUM_D3 15 /* DMA channel 3 */ -#define VECNUM_UD0 16 /* UDMA irq 0 */ -#define VECNUM_UD1 17 /* UDMA irq 1 */ -#define VECNUM_UD2 18 /* UDMA irq 2 */ -#define VECNUM_UD3 19 /* UDMA irq 3 */ -#define VECNUM_HSB2D 20 /* USB2.0 Device */ -#define VECNUM_USBDEV 20 /* USB 1.1/USB 2.0 Device */ -#define VECNUM_OHCI1 21 /* USB2.0 Host OHCI irq 1 */ -#define VECNUM_OHCI2 22 /* USB2.0 Host OHCI irq 2 */ -#define VECNUM_EIP94 23 /* Security EIP94 */ -#define VECNUM_ETH0 24 /* Emac 0 */ -#define VECNUM_ETH1 25 /* Emac 1 */ -#define VECNUM_EHCI 26 /* USB2.0 Host EHCI */ -#define VECNUM_EIR4 27 /* External interrupt 4 */ -#define VECNUM_UIC2NC 28 /* UIC2 non-critical interrupt */ -#define VECNUM_UIC2C 29 /* UIC2 critical interrupt */ -#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */ - -/* UIC 1 */ -#define VECNUM_MS (32 + 0) /* MAL SERR */ -#define VECNUM_MTDE (32 + 1) /* MAL TXDE */ -#define VECNUM_MRDE (32 + 2) /* MAL RXDE */ -#define VECNUM_U2 (32 + 3) /* UART 2 */ -#define VECNUM_U3 (32 + 4) /* UART 3 */ -#define VECNUM_EBCO (32 + 5) /* EBCO interrupt status */ -#define VECNUM_NDFC (32 + 6) /* NDFC */ -#define VECNUM_KSLE (32 + 7) /* KASUMI slave error */ -#define VECNUM_CT5 (32 + 8) /* GPT compare timer 5 */ -#define VECNUM_CT6 (32 + 9) /* GPT compare timer 6 */ -#define VECNUM_PLB34I0 (32 + 10) /* PLB3X4X MIRQ0 */ -#define VECNUM_PLB34I1 (32 + 11) /* PLB3X4X MIRQ1 */ -#define VECNUM_PLB34I2 (32 + 12) /* PLB3X4X MIRQ2 */ -#define VECNUM_PLB34I3 (32 + 13) /* PLB3X4X MIRQ3 */ -#define VECNUM_PLB34I4 (32 + 14) /* PLB3X4X MIRQ4 */ -#define VECNUM_PLB34I5 (32 + 15) /* PLB3X4X MIRQ5 */ -#define VECNUM_CT0 (32 + 16) /* GPT compare timer 0 */ -#define VECNUM_CT1 (32 + 17) /* GPT compare timer 1 */ -#define VECNUM_EIR7 (32 + 18) /* External interrupt 7 */ -#define VECNUM_EIR8 (32 + 19) /* External interrupt 8 */ -#define VECNUM_EIR9 (32 + 20) /* External interrupt 9 */ -#define VECNUM_CT2 (32 + 21) /* GPT compare timer 2 */ -#define VECNUM_CT3 (32 + 22) /* GPT compare timer 3 */ -#define VECNUM_CT4 (32 + 23) /* GPT compare timer 4 */ -#define VECNUM_SRE (32 + 24) /* Serial ROM error */ -#define VECNUM_GPTDC (32 + 25) /* GPT decrementer pulse */ -#define VECNUM_RSVD0 (32 + 26) /* Reserved */ -#define VECNUM_EPCIPER (32 + 27) /* External PCI PERR */ -#define VECNUM_EIR0 (32 + 28) /* External interrupt 0 */ -#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */ -#define VECNUM_EIR1 (32 + 30) /* External interrupt 1 */ -#define VECNUM_EWU1 (32 + 31) /* Ethernet 1 wakeup */ - -#define VECNUM_TXDE VECNUM_MTDE -#define VECNUM_RXDE VECNUM_MRDE - -/* UIC 2 */ -#define VECNUM_EIR5 (62 + 0) /* External interrupt 5 */ -#define VECNUM_EIR6 (62 + 1) /* External interrupt 6 */ -#define VECNUM_OPB (62 + 2) /* OPB to PLB bridge int stat */ -#define VECNUM_EIR2 (62 + 3) /* External interrupt 2 */ -#define VECNUM_EIR3 (62 + 4) /* External interrupt 3 */ -#define VECNUM_DDR2 (62 + 5) /* DDR2 sdram */ -#define VECNUM_MCTX0 (62 + 6) /* MAl intp coalescence TX0 */ -#define VECNUM_MCTX1 (62 + 7) /* MAl intp coalescence TX1 */ -#define VECNUM_MCTR0 (62 + 8) /* MAl intp coalescence TR0 */ -#define VECNUM_MCTR1 (62 + 9) /* MAl intp coalescence TR1 */ - -#elif defined(CONFIG_440SPE) - -/* UIC 0 */ -#define VECNUM_U0 0 /* UART0 */ -#define VECNUM_U1 1 /* UART1 */ -#define VECNUM_IIC0 2 /* IIC0 */ -#define VECNUM_IIC1 3 /* IIC1 */ -#define VECNUM_PIM 4 /* PCI inbound message */ -#define VECNUM_PCRW 5 /* PCI command reg write */ -#define VECNUM_PPM 6 /* PCI power management */ -#define VECNUM_MSI0 7 /* PCI MSI level 0 */ -#define VECNUM_MSI1 8 /* PCI MSI level 0 */ -#define VECNUM_MSI2 9 /* PCI MSI level 0 */ -#define VECNUM_D0 12 /* DMA channel 0 */ -#define VECNUM_D1 13 /* DMA channel 1 */ -#define VECNUM_D2 14 /* DMA channel 2 */ -#define VECNUM_D3 15 /* DMA channel 3 */ -#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */ - -/* UIC 1 */ -#define VECNUM_MS (32 + 1 ) /* MAL SERR */ -#define VECNUM_TXDE (32 + 2 ) /* MAL TXDE */ -#define VECNUM_RXDE (32 + 3 ) /* MAL RXDE */ -#define VECNUM_MTE (32 + 6 ) /* MAL Tx EOB */ -#define VECNUM_MRE (32 + 7 ) /* MAL Rx EOB */ -#define VECNUM_CT0 (32 + 12 ) /* GPT compare timer 0 */ -#define VECNUM_CT1 (32 + 13 ) /* GPT compare timer 1 */ -#define VECNUM_CT2 (32 + 14 ) /* GPT compare timer 2 */ -#define VECNUM_CT3 (32 + 15 ) /* GPT compare timer 3 */ -#define VECNUM_CT4 (32 + 16 ) /* GPT compare timer 4 */ -#define VECNUM_ETH0 (32 + 28) /* Ethernet interrupt status */ -#define VECNUM_EWU0 (32 + 29) /* Emac wakeup */ - -/* UIC 2 */ -#define VECNUM_EIR5 (62 + 24) /* External interrupt 5 */ -#define VECNUM_EIR4 (62 + 25) /* External interrupt 4 */ -#define VECNUM_EIR3 (62 + 26) /* External interrupt 3 */ -#define VECNUM_EIR2 (62 + 27) /* External interrupt 2 */ -#define VECNUM_EIR1 (62 + 28) /* External interrupt 1 */ -#define VECNUM_EIR0 (62 + 29) /* External interrupt 0 */ - -#elif defined(CONFIG_440SP) - -/* UIC 0 */ -#define VECNUM_U0 0 /* UART0 */ -#define VECNUM_U1 1 /* UART1 */ -#define VECNUM_IIC0 2 /* IIC0 */ -#define VECNUM_IIC1 3 /* IIC1 */ -#define VECNUM_PIM 4 /* PCI inbound message */ -#define VECNUM_PCRW 5 /* PCI command reg write */ -#define VECNUM_PPM 6 /* PCI power management */ -#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */ - -/* UIC 1 */ -#define VECNUM_EIR0 (32 + 0) /* External interrupt 0 */ -#define VECNUM_MS (32 + 1) /* MAL SERR */ -#define VECNUM_TXDE (32 + 2) /* MAL TXDE */ -#define VECNUM_RXDE (32 + 3) /* MAL RXDE */ -#define VECNUM_MTE (32 + 6) /* MAL Tx EOB */ -#define VECNUM_MRE (32 + 7) /* MAL Rx EOB */ -#define VECNUM_CT0 (32 + 12) /* GPT compare timer 0 */ -#define VECNUM_CT1 (32 + 13) /* GPT compare timer 1 */ -#define VECNUM_CT2 (32 + 14) /* GPT compare timer 2 */ -#define VECNUM_CT3 (32 + 15) /* GPT compare timer 3 */ -#define VECNUM_CT4 (32 + 16) /* GPT compare timer 4 */ -#define VECNUM_ETH0 (32 + 28) /* Ethernet interrupt status */ -#define VECNUM_EWU0 (32 + 29) /* Emac wakeup */ - -#elif defined(CONFIG_440) - -/* UIC 0 */ -#define VECNUM_U0 0 /* UART0 */ -#define VECNUM_U1 1 /* UART1 */ -#define VECNUM_IIC0 2 /* IIC0 */ -#define VECNUM_IIC1 3 /* IIC1 */ -#define VECNUM_PIM 4 /* PCI inbound message */ -#define VECNUM_PCRW 5 /* PCI command reg write */ -#define VECNUM_PPM 6 /* PCI power management */ -#define VECNUM_MSI0 7 /* PCI MSI level 0 */ -#define VECNUM_MSI1 8 /* PCI MSI level 0 */ -#define VECNUM_MSI2 9 /* PCI MSI level 0 */ -#define VECNUM_MTE 10 /* MAL TXEOB */ -#define VECNUM_MRE 11 /* MAL RXEOB */ -#define VECNUM_D0 12 /* DMA channel 0 */ -#define VECNUM_D1 13 /* DMA channel 1 */ -#define VECNUM_D2 14 /* DMA channel 2 */ -#define VECNUM_D3 15 /* DMA channel 3 */ -#define VECNUM_CT0 18 /* GPT compare timer 0 */ -#define VECNUM_CT1 19 /* GPT compare timer 1 */ -#define VECNUM_CT2 20 /* GPT compare timer 2 */ -#define VECNUM_CT3 21 /* GPT compare timer 3 */ -#define VECNUM_CT4 22 /* GPT compare timer 4 */ -#define VECNUM_EIR0 23 /* External interrupt 0 */ -#define VECNUM_EIR1 24 /* External interrupt 1 */ -#define VECNUM_EIR2 25 /* External interrupt 2 */ -#define VECNUM_EIR3 26 /* External interrupt 3 */ -#define VECNUM_EIR4 27 /* External interrupt 4 */ -#define VECNUM_EIR5 28 /* External interrupt 5 */ -#define VECNUM_EIR6 29 /* External interrupt 6 */ -#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */ - -/* UIC 1 */ -#define VECNUM_MS (32 + 0 ) /* MAL SERR */ -#define VECNUM_TXDE (32 + 1 ) /* MAL TXDE */ -#define VECNUM_RXDE (32 + 2 ) /* MAL RXDE */ -#define VECNUM_USBDEV (32 + 23) /* USB 1.1/USB 2.0 Device */ -#define VECNUM_ETH0 (32 + 28) /* Ethernet 0 interrupt status */ -#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */ - -#else /* !defined(CONFIG_440) */ - -#if defined(CONFIG_405EZ) -#define VECNUM_D0 0 /* DMA channel 0 */ -#define VECNUM_D1 1 /* DMA channel 1 */ -#define VECNUM_D2 2 /* DMA channel 2 */ -#define VECNUM_D3 3 /* DMA channel 3 */ -#define VECNUM_1588 4 /* IEEE 1588 network synchronization */ -#define VECNUM_U0 5 /* UART0 */ -#define VECNUM_U1 6 /* UART1 */ -#define VECNUM_CAN0 7 /* CAN 0 */ -#define VECNUM_CAN1 8 /* CAN 1 */ -#define VECNUM_SPI 9 /* SPI */ -#define VECNUM_IIC0 10 /* I2C */ -#define VECNUM_CHT0 11 /* Chameleon timer high pri interrupt */ -#define VECNUM_CHT1 12 /* Chameleon timer high pri interrupt */ -#define VECNUM_USBH1 13 /* USB Host 1 */ -#define VECNUM_USBH2 14 /* USB Host 2 */ -#define VECNUM_USBDEV 15 /* USB Device */ -#define VECNUM_ETH0 16 /* 10/100 Ethernet interrupt status */ -#define VECNUM_EWU0 17 /* Ethernet wakeup sequence detected */ - -#define VECNUM_MADMAL 18 /* Logical OR of following MadMAL int */ -#define VECNUM_MS 18 /* MAL_SERR_INT */ -#define VECNUM_TXDE 18 /* MAL_TXDE_INT */ -#define VECNUM_RXDE 18 /* MAL_RXDE_INT */ - -#define VECNUM_MTE 19 /* MAL TXEOB */ -#define VECNUM_MTE1 20 /* MAL TXEOB1 */ -#define VECNUM_MRE 21 /* MAL RXEOB */ -#define VECNUM_NAND 22 /* NAND Flash controller */ -#define VECNUM_ADC 23 /* ADC */ -#define VECNUM_DAC 24 /* DAC */ -#define VECNUM_OPB2PLB 25 /* OPB to PLB bridge interrupt */ -#define VECNUM_RESERVED0 26 /* Reserved */ -#define VECNUM_EIR0 27 /* External interrupt 0 */ -#define VECNUM_EIR1 28 /* External interrupt 1 */ -#define VECNUM_EIR2 29 /* External interrupt 2 */ -#define VECNUM_EIR3 30 /* External interrupt 3 */ -#define VECNUM_EIR4 31 /* External interrupt 4 */ - -#else /* !CONFIG_405EZ */ - -#define VECNUM_U0 0 /* UART0 */ -#define VECNUM_U1 1 /* UART1 */ -#define VECNUM_D0 5 /* DMA channel 0 */ -#define VECNUM_D1 6 /* DMA channel 1 */ -#define VECNUM_D2 7 /* DMA channel 2 */ -#define VECNUM_D3 8 /* DMA channel 3 */ -#define VECNUM_EWU0 9 /* Ethernet wakeup */ -#define VECNUM_MS 10 /* MAL SERR */ -#define VECNUM_MTE 11 /* MAL TXEOB */ -#define VECNUM_MRE 12 /* MAL RXEOB */ -#define VECNUM_TXDE 13 /* MAL TXDE */ -#define VECNUM_RXDE 14 /* MAL RXDE */ -#define VECNUM_ETH0 15 /* Ethernet interrupt status */ -#define VECNUM_EIR0 25 /* External interrupt 0 */ -#define VECNUM_EIR1 26 /* External interrupt 1 */ -#define VECNUM_EIR2 27 /* External interrupt 2 */ -#define VECNUM_EIR3 28 /* External interrupt 3 */ -#define VECNUM_EIR4 29 /* External interrupt 4 */ -#define VECNUM_EIR5 30 /* External interrupt 5 */ -#define VECNUM_EIR6 31 /* External interrupt 6 */ -#endif /* defined(CONFIG_405EZ) */ - -#endif /* defined(CONFIG_440) */ - -#endif /* _VECNUMS_H_ */ diff --git a/cpu/pxa/start.S b/cpu/pxa/start.S index b922485..31f408d 100644 --- a/cpu/pxa/start.S +++ b/cpu/pxa/start.S @@ -57,7 +57,7 @@ _fiq: .word fiq * Startup Code (reset vector) * * do important init only if we don't start from RAM! - * - relocate armboot to ram + * - relocate armboot to RAM * - setup stack * - jump to second stage */ @@ -90,7 +90,7 @@ IRQ_STACK_START: .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de -#endif +#endif /* CONFIG_USE_IRQ */ /****************************************************************************/ @@ -100,18 +100,18 @@ FIQ_STACK_START: /****************************************************************************/ reset: - mrs r0,cpsr /* set the cpu to SVC32 mode */ + mrs r0,cpsr /* set the CPU to SVC32 mode */ bic r0,r0,#0x1f /* (superviser mode, M=10011) */ orr r0,r0,#0x13 msr cpsr,r0 /* * we do sys-critical inits only at reboot, - * not when booting from ram! + * not when booting from RAM! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit /* we do sys-critical inits */ -#endif +#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ #ifndef CONFIG_SKIP_RELOCATE_UBOOT relocate: /* relocate U-Boot to RAM */ @@ -130,7 +130,7 @@ copy_loop: stmia r1!, {r3-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end addreee [r2] */ ble copy_loop -#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ +#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */ /* Set up the stack */ stack_setup: @@ -139,7 +139,7 @@ stack_setup: sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) -#endif +#endif /* CONFIG_USE_IRQ */ sub sp, r0, #12 /* leave 3 words for abort-stack */ clear_bss: @@ -172,11 +172,11 @@ _start_armboot: .word start_armboot #undef OSCR #undef OWER #undef OIER -#endif +#endif /* CONFIG_PXA250 || CONFIG_CPU_MONAHANS */ #ifdef CONFIG_PXA250 #undef RCSR #undef CCCR -#endif +#endif /* CONFIG_PXA250 */ /* Interrupt-Controller base address */ IC_BASE: .word 0x40d00000 @@ -197,18 +197,18 @@ OSTIMER_BASE: .word 0x40a00000 #ifdef CONFIG_CPU_MONAHANS # ifndef CFG_MONAHANS_RUN_MODE_OSC_RATIO # error "You have to define CFG_MONAHANS_RUN_MODE_OSC_RATIO!!" -# endif +# endif /* !CFG_MONAHANS_RUN_MODE_OSC_RATIO */ # ifndef CFG_MONAHANS_TURBO_RUN_MODE_RATIO # define CFG_MONAHANS_TURBO_RUN_MODE_RATIO 0x1 -# endif -#else /* ! CONFIG_CPU_MONAHANS */ +# endif /* !CFG_MONAHANS_TURBO_RUN_MODE_RATIO */ +#else /* !CONFIG_CPU_MONAHANS */ #ifdef CFG_CPUSPEED CC_BASE: .word 0x41300000 #define CCCR 0x00 cpuspeed: .word CFG_CPUSPEED -#else +#else /* !CFG_CPUSPEED */ #error "You have to define CFG_CPUSPEED!!" -#endif +#endif /* CFG_CPUSPEED */ #endif /* CONFIG_CPU_MONAHANS */ /* takes care the CP15 update has taken place */ @@ -225,7 +225,7 @@ cpu_init_crit: ldr r0, IC_BASE mov r1, #0x00 str r1, [r0, #ICMR] -#else +#else /* CONFIG_CPU_MONAHANS */ /* Step 1 - Enable CP6 permission */ mrc p15, 0, r1, c15, c1, 0 @ read CPAR orr r1, r1, #0x40 @@ -244,14 +244,14 @@ cpu_init_crit: ldr r1, =CKENB ldr r2, =(CKENB_6_IRQ) str r2, [r1] -#endif +#endif /* !CONFIG_CPU_MONAHANS */ /* set clock speed */ #ifdef CONFIG_CPU_MONAHANS ldr r0, =ACCR ldr r1, =(((CFG_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CFG_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK)) str r1, [r0] -#else /* ! CONFIG_CPU_MONAHANS */ +#else /* !CONFIG_CPU_MONAHANS */ #ifdef CFG_CPUSPEED ldr r0, CC_BASE ldr r1, cpuspeed @@ -451,7 +451,7 @@ fiq: bl do_fiq /* effiction fiq_save_user_regs */ irq_restore_user_regs -#else +#else /* !CONFIG_USE_IRQ */ .align 5 irq: @@ -465,7 +465,7 @@ fiq: bad_save_user_regs bl do_fiq -#endif +#endif /* CONFIG_USE_IRQ */ /****************************************************************************/ /* */ diff --git a/cpu/pxa/usb.c b/cpu/pxa/usb.c index 72b7dfa..aa6f4b7 100644 --- a/cpu/pxa/usb.c +++ b/cpu/pxa/usb.c @@ -89,6 +89,22 @@ int usb_cpu_stop(void) int usb_cpu_init_fail(void) { + UHCHR |= UHCHR_FHR; + udelay(11); + UHCHR &= ~UHCHR_FHR; + + UHCCOMS |= 1; + udelay(10); + +#if defined(CONFIG_CPU_MONAHANS) + UHCHR |= UHCHR_SSEP0; +#endif +#if defined(CONFIG_PXA27X) + UHCHR |= UHCHR_SSEP2; +#endif + UHCHR |= UHCHR_SSEP1; + UHCHR |= UHCHR_SSE; + return 0; } |