diff options
author | Wolfgang Denk <wd@pollux.denx.de> | 2006-11-27 16:13:00 +0100 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2006-11-27 16:13:00 +0100 |
commit | d3c5e8b2f5945d93de8f23b053e9dcd033983245 (patch) | |
tree | 72c292c41bc0dfadd6f634fe03e697d8a4473487 /cpu/ppc4xx | |
parent | 98280e3d431db77d92219438b8840853bd7cb412 (diff) | |
parent | a9398e018593782c5fa7d0741955fc1256b34c1e (diff) | |
download | u-boot-imx-d3c5e8b2f5945d93de8f23b053e9dcd033983245.zip u-boot-imx-d3c5e8b2f5945d93de8f23b053e9dcd033983245.tar.gz u-boot-imx-d3c5e8b2f5945d93de8f23b053e9dcd033983245.tar.bz2 |
Merge with /home/wd/git/u-boot/master
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/405gp_pci.c | 8 | ||||
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.c | 962 | ||||
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.h | 171 | ||||
-rw-r--r-- | cpu/ppc4xx/4xx_enet.c | 184 | ||||
-rw-r--r-- | cpu/ppc4xx/Makefile | 25 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu.c | 130 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu_init.c | 14 | ||||
-rw-r--r-- | cpu/ppc4xx/interrupts.c | 57 | ||||
-rw-r--r-- | cpu/ppc4xx/miiphy.c | 14 | ||||
-rw-r--r-- | cpu/ppc4xx/ndfc.c | 193 | ||||
-rw-r--r-- | cpu/ppc4xx/serial.c | 263 | ||||
-rw-r--r-- | cpu/ppc4xx/speed.c | 3 | ||||
-rw-r--r-- | cpu/ppc4xx/start.S | 173 | ||||
-rw-r--r-- | cpu/ppc4xx/usb_ohci.c | 8 | ||||
-rw-r--r-- | cpu/ppc4xx/usbdev.c | 20 | ||||
-rw-r--r-- | cpu/ppc4xx/vecnum.h | 89 |
16 files changed, 2019 insertions, 295 deletions
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index cf5eccb..03128d3 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/405gp_pci.c @@ -315,7 +315,6 @@ void pci_405gp_init(struct pci_controller *hose) #ifdef CONFIG_PCI_SCAN_SHOW printf("PCI: Bus Dev VenId DevId Class Int\n"); #endif - hose->last_busno = pci_hose_scan(hose); } #endif /* CONFIG_PCI_PNP */ @@ -556,17 +555,20 @@ void pci_440_init (struct pci_controller *hose) #ifdef CONFIG_PCI_SCAN_SHOW printf("PCI: Bus Dev VenId DevId Class Int\n"); #endif -#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) +#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) && \ + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) out16r( PCIX0_CMD, in16r( PCIX0_CMD ) | PCI_COMMAND_MASTER); #endif hose->last_busno = pci_hose_scan(hose); } } - void pci_init_board(void) { pci_440_init (&ppc440_hose); +#if defined(CONFIG_440SPE) + pcie_setup_hoses(); +#endif } #endif /* CONFIG_440 & CONFIG_PCI */ diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c new file mode 100644 index 0000000..6130cd2 --- /dev/null +++ b/cpu/ppc4xx/440spe_pcie.c @@ -0,0 +1,962 @@ +/* + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (c) 2005 Cisco Systems. All rights reserved. + * Roland Dreier <rolandd@cisco.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. + * + */ + +#include <asm/processor.h> +#include <asm-ppc/io.h> +#include <ppc4xx.h> +#include <common.h> +#include <pci.h> + +#include "440spe_pcie.h" + +#if defined(CONFIG_440SPE) +#if defined(CONFIG_PCI) + +enum { + PTYPE_ENDPOINT = 0x0, + PTYPE_LEGACY_ENDPOINT = 0x1, + PTYPE_ROOT_PORT = 0x4, + + LNKW_X1 = 0x1, + LNKW_X4 = 0x4, + LNKW_X8 = 0x8 +}; + +static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, + int offset, int len, u32 *val) { + + *val = 0; + /* + * 440SPE implements only one function per port + */ + if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1))) + return 0; + + devfn = PCI_BDF(0,0,0); + offset += devfn << 4; + + switch (len) { + case 1: + *val = in_8(hose->cfg_data + offset); + break; + case 2: + *val = in_le16((u16 *)(hose->cfg_data + offset)); + break; + default: + *val = in_le32((u32 *)(hose->cfg_data + offset)); + break; + } + return 0; +} + +static int pcie_write_config(struct pci_controller *hose, unsigned int devfn, + int offset, int len, u32 val) { + + /* + * 440SPE implements only one function per port + */ + if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1))) + return 0; + + devfn = PCI_BDF(0,0,0); + offset += devfn << 4; + + switch (len) { + case 1: + out_8(hose->cfg_data + offset, val); + break; + case 2: + out_le16((u16 *)(hose->cfg_data + offset), val); + break; + default: + out_le32((u32 *)(hose->cfg_data + offset), val); + break; + } + return 0; +} + +int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val) +{ + u32 v; + int rv; + + rv = pcie_read_config(hose, dev, offset, 1, &v); + *val = (u8)v; + return rv; +} + +int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val) +{ + u32 v; + int rv; + + rv = pcie_read_config(hose, dev, offset, 2, &v); + *val = (u16)v; + return rv; +} + +int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val) +{ + u32 v; + int rv; + + rv = pcie_read_config(hose, dev, offset, 3, &v); + *val = (u32)v; + return rv; +} + +int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val) +{ + return pcie_write_config(hose,(u32)dev,offset,1,val); +} + +int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val) +{ + return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val); +} + +int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val) +{ + return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val); +} + +static void ppc440spe_setup_utl(u32 port) { + + volatile void *utl_base = NULL; + + /* + * Map UTL registers + */ + switch (port) { + case 0: + mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x20000000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800); + break; + + case 1: + mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x20001000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800); + break; + + case 2: + mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c); + mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x20002000); + mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001); + mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800); + break; + } + utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port); + + /* + * Set buffer allocations and then assert VRB and TXE. + */ + out_be32(utl_base + PEUTL_OUTTR, 0x08000000); + out_be32(utl_base + PEUTL_INTR, 0x02000000); + out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); + out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); + out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); + out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); + out_be32(utl_base + PEUTL_PCTL, 0x80800066); +} + +static int check_error(void) +{ + u32 valPE0, valPE1, valPE2; + int err = 0; + + /* SDR0_PEGPLLLCT1 reset */ + if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) { + printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0); + } + + valPE0 = SDR_READ(PESDR0_RCSSET); + valPE1 = SDR_READ(PESDR1_RCSSET); + valPE2 = SDR_READ(PESDR2_RCSSET); + + /* SDR0_PExRCSSET rstgu */ + if (!(valPE0 & 0x01000000) || + !(valPE1 & 0x01000000) || + !(valPE2 & 0x01000000)) { + printf("PCIE: SDR0_PExRCSSET rstgu error\n"); + err = -1; + } + + /* SDR0_PExRCSSET rstdl */ + if (!(valPE0 & 0x00010000) || + !(valPE1 & 0x00010000) || + !(valPE2 & 0x00010000)) { + printf("PCIE: SDR0_PExRCSSET rstdl error\n"); + err = -1; + } + + /* SDR0_PExRCSSET rstpyn */ + if ((valPE0 & 0x00001000) || + (valPE1 & 0x00001000) || + (valPE2 & 0x00001000)) { + printf("PCIE: SDR0_PExRCSSET rstpyn error\n"); + err = -1; + } + + /* SDR0_PExRCSSET hldplb */ + if ((valPE0 & 0x10000000) || + (valPE1 & 0x10000000) || + (valPE2 & 0x10000000)) { + printf("PCIE: SDR0_PExRCSSET hldplb error\n"); + err = -1; + } + + /* SDR0_PExRCSSET rdy */ + if ((valPE0 & 0x00100000) || + (valPE1 & 0x00100000) || + (valPE2 & 0x00100000)) { + printf("PCIE: SDR0_PExRCSSET rdy error\n"); + err = -1; + } + + /* SDR0_PExRCSSET shutdown */ + if ((valPE0 & 0x00000100) || + (valPE1 & 0x00000100) || + (valPE2 & 0x00000100)) { + printf("PCIE: SDR0_PExRCSSET shutdown error\n"); + err = -1; + } + return err; +} + +/* + * Initialize PCI Express core + */ +int ppc440spe_init_pcie(void) +{ + int time_out = 20; + + /* Set PLL clock receiver to LVPECL */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28); + + if (check_error()) + return -1; + + if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) + { + printf("PCIE: PESDR_PLLCT2 resistance calibration failed (0x%08x)\n", + SDR_READ(PESDR0_PLLLCT2)); + return -1; + } + /* De-assert reset of PCIe PLL, wait for lock */ + SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24)); + udelay(3); + + while (time_out) { + if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) { + time_out--; + udelay(1); + } else + break; + } + if (!time_out) { + printf("PCIE: VCO output not locked\n"); + return -1; + } + return 0; +} + +/* + * Yucca board 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 + * 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 + * root port attached it will not initialize. + * + * In this release of software all the PCI-E ports are configured as either + * endpoint or rootpoint.In future we will have support for selective ports + * setup as endpoint and root point in single board. + * + * Once your board came up as root point , you can verify by reading + * /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 + * linux use "lspci" or appripriate os command. + * + * How do I verify the inbound and out bound windows ?(yucca to yucca) + * 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 + * 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) +{ + 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 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. + */ + 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; + + 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; + } + + 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 0; +} + +int ppc440spe_init_pcie_endport(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 0; +} + +void ppc440spe_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); + + switch (port) { + case 0: + mbase = (u32 *)CFG_PCIE0_XCFGBASE; + rmbase = (u32 *)CFG_PCIE0_CFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE; + break; + case 1: + mbase = (u32 *)CFG_PCIE1_XCFGBASE; + rmbase = (u32 *)CFG_PCIE1_CFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; + break; + case 2: + mbase = (u32 *)CFG_PCIE2_XCFGBASE; + rmbase = (u32 *)CFG_PCIE2_CFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; + break; + } + + /* + * Set bus numbers on our root port + */ + out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); + out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); + out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); + + /* + * Set up outbound translation to hose->mem_space from PLB + * addresses at an offset of 0xd_0000_0000. We set the low + * bits of the mask to 11 to turn off splitting into 8 + * subregions and to enable the outbound translation. + */ + out_le32(mbase + PECFG_POM0LAH, 0x00000000); + out_le32(mbase + PECFG_POM0LAL, 0x00000000); + + 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_OMR1MSKH(PCIE0), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), + ~(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_OMR1MSKH(PCIE1), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), + ~(CFG_PCIE_MEMSIZE - 1) | 3); + break; + case 2: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); + 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); + break; + } + + /* Set up 16GB 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_PIM01SAH, 0xffff0000); + 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_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); +} + +int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port) +{ + volatile void *mbase = NULL; + int attempts = 0; + + 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); + + switch (port) { + case 0: + mbase = (u32 *)CFG_PCIE0_XCFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE; + break; + case 1: + mbase = (u32 *)CFG_PCIE1_XCFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; + break; + case 2: + mbase = (u32 *)CFG_PCIE2_XCFGBASE; + hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; + break; + } + + /* + * Set up outbound translation to hose->mem_space from PLB + * addresses at an offset of 0xd_0000_0000. We set the low + * bits of the mask to 11 to turn off splitting into 8 + * subregions and to enable the outbound translation. + */ + out_le32(mbase + PECFG_POM0LAH, 0x00001ff8); + out_le32(mbase + PECFG_POM0LAL, 0x00001000); + + 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_OMR1MSKH(PCIE0), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), + ~(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_OMR1MSKH(PCIE1), 0x7fffffff); + mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), + ~(CFG_PCIE_MEMSIZE - 1) | 3); + break; + case 2: + mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); + 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); + break; + } + + /* Set up 16GB 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_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 */ + 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); + } + break; + } + printf("PCIE:%d successfully set as endpoint\n",port); + + return 0; +} +#endif /* CONFIG_PCI */ +#endif /* CONFIG_440SPE */ diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h new file mode 100644 index 0000000..2becc77 --- /dev/null +++ b/cpu/ppc4xx/440spe_pcie.h @@ -0,0 +1,171 @@ +/* + * 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) + +/* + * 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);}) + +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/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index fab65af..81d49ff 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -130,7 +130,17 @@ #define BI_PHYMODE_NONE 0 #define BI_PHYMODE_ZMII 1 #define BI_PHYMODE_RGMII 2 +#define BI_PHYMODE_GMII 3 +#define BI_PHYMODE_RTBI 4 +#define BI_PHYMODE_TBI 5 +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define BI_PHYMODE_SMII 6 +#define BI_PHYMODE_MII 7 +#endif +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1)) +#endif /*-----------------------------------------------------------------------------+ * Global variables. TX and RX descriptors and buffers. @@ -181,7 +191,7 @@ 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) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) unsigned long mfr; #endif @@ -205,19 +215,19 @@ static void ppc_4xx_eth_halt (struct eth_device *dev) } /* EMAC RESET */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* provide clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); - mfr |= 0x08000000; + 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); -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* remove clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); - mfr &= ~0x08000000; + mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum); mtsdr(sdr_mfr, mfr); #endif @@ -317,10 +327,50 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) out32 (RGMII_FER, rmiifer); return ((int)pfc1); - } #endif /* CONFIG_440_GX */ +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) +{ + unsigned long zmiifer=0x0; + + /* + * Right now only 2*RGMII is supported. Please extend when needed. + * sr - 2006-08-29 + */ + switch (1) { + case 0: + /* 1 x GMII port */ + out32 (ZMII_FER, 0x00); + out32 (RGMII_FER, 0x00000037); + bis->bi_phymode[0] = BI_PHYMODE_GMII; + bis->bi_phymode[1] = BI_PHYMODE_NONE; + break; + case 1: + /* 2 x RGMII ports */ + out32 (ZMII_FER, 0x00); + out32 (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 */ + zmiifer = in32 (ZMII_FER); + zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); + out32 (ZMII_FER, zmiifer); + + return ((int)0x0); +} +#endif /* CONFIG_440EPX */ + static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) { int i, j; @@ -332,13 +382,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) unsigned mode_reg; unsigned short devnum; unsigned short reg_short; -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) sys_info_t sysinfo; -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) int ethgroup = -1; #endif #endif -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) unsigned long mfr; #endif @@ -352,7 +405,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) return -1; } -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) /* Need to get the OPB frequency so we can access the PHY */ get_sys_info (&sysinfo); #endif @@ -407,7 +462,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) #if defined(CONFIG_440EP) || defined(CONFIG_440GR) out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); -#elif defined(CONFIG_440GX) +#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 */ @@ -429,10 +484,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) __asm__ volatile ("eieio"); /* reset emac so we have access to the phy */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* provide clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); - mfr |= 0x08000000; + mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); mtsdr(sdr_mfr, mfr); #endif @@ -444,15 +499,19 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) udelay (1000); failsafe--; } + if (failsafe <= 0) + printf("\nProblem resetting EMAC!\n"); -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* remove clocks for EMAC internal loopback */ mfsdr (sdr_mfr, mfr); - mfr &= ~0x08000000; + mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); mtsdr(sdr_mfr, mfr); #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) /* Whack the M1 register */ mode_reg = 0x0; mode_reg &= ~0x00000038; @@ -502,15 +561,39 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) * otherwise, just check the speeds & feeds */ if (hw_p->first_init == 0) { +#if defined(CONFIG_88E1111_CLK_DELAY) + /* + * On some boards (e.g. ALPR) the Marvell 88E1111 PHY needs + * the "RGMII transmit timing control" and "RGMII receive + * timing control" bits set, so that Gbit communication works + * without problems. + * Also set the "Transmitter disable" to 1 to enable the + * transmitter. + * After setting these bits a soft-reset must occur for this + * change to become active. + */ + miiphy_read (dev->name, reg, 0x14, ®_short); + reg_short |= (1 << 7) | (1 << 1) | (1 << 0); + miiphy_write (dev->name, reg, 0x14, reg_short); +#endif +#if defined(CONFIG_M88E1111_PHY) /* test-only: merge with CONFIG_88E1111_CLK_DELAY !!! */ + miiphy_write (dev->name, reg, 0x14, 0x0ce3); + miiphy_write (dev->name, reg, 0x18, 0x4101); + miiphy_write (dev->name, reg, 0x09, 0x0e00); + miiphy_write (dev->name, reg, 0x04, 0x01e1); +#endif miiphy_reset (dev->name, reg); -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) + #if defined(CONFIG_CIS8201_PHY) /* * Cicada 8201 PHY needs to have an extended register whacked * for RGMII mode. */ - if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) { + if (((devnum == 2) || (devnum == 3)) && (4 == ethgroup)) { #if defined(CONFIG_CIS8201_SHORT_ETCH) miiphy_write (dev->name, reg, 23, 0x1300); #else @@ -580,7 +663,8 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) (int) speed, (duplex == HALF) ? "HALF" : "FULL"); } -#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) +#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) #if defined(CONFIG_440EP) || defined(CONFIG_440GR) mfsdr(sdr_mfr, reg); if (speed == 100) { @@ -603,15 +687,34 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); else if (speed == 100) reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum)); - else + else if (speed == 10) reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum)); - + else { + printf("Error in RGMII Speed\n"); + return -1; + } out32 (RGMII_SSR, reg); } #endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */ +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + if (speed == 1000) + reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum)); + else if (speed == 100) + reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum)); + else if (speed == 10) + reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum)); + else { + printf("Error in RGMII Speed\n"); + return -1; + } + out32 (RGMII_SSR, reg); +#endif + /* set the Mal configuration reg */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000); #else @@ -795,8 +898,10 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) /* set speed */ if (speed == _1000BASET) { -#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) unsigned long pfc1; + mfsdr (sdr_pfc1, pfc1); pfc1 |= SDR0_PFC1_EM_1000; mtsdr (sdr_pfc1, pfc1); @@ -942,6 +1047,14 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr, #define UIC0SR uic0sr #endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define UICMSR_ETHX uic0msr +#define UICSR_ETHX uic0sr +#else +#define UICMSR_ETHX uic1msr +#define UICSR_ETHX uic1sr +#endif + int enetInt (struct eth_device *dev) { int serviced; @@ -950,6 +1063,7 @@ int enetInt (struct eth_device *dev) unsigned long emac_isr = 0; unsigned long mal_rx_eob; unsigned long my_uic0msr, my_uic1msr; + unsigned long my_uicmsr_ethx; #if defined(CONFIG_440GX) unsigned long my_uic2msr; @@ -977,8 +1091,11 @@ int enetInt (struct eth_device *dev) #if defined(CONFIG_440GX) my_uic2msr = mfdcr (uic2msr); #endif + my_uicmsr_ethx = mfdcr (UICMSR_ETHX); + if (!(my_uic0msr & (UIC_MRE | UIC_MTE)) - && !(my_uic1msr & (UIC_ETH0 | UIC_ETH1 | UIC_MS | UIC_MTDE | UIC_MRDE))) { + && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) + && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) { /* not for us */ return (rc); } @@ -997,8 +1114,7 @@ int enetInt (struct eth_device *dev) mal_isr = mfdcr (malesr); /* look for mal error */ if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) { - mal_err (dev, mal_isr, my_uic0msr, - MAL_UIC_DEF, MAL_UIC_ERR); + mal_err (dev, mal_isr, my_uic1msr, MAL_UIC_DEF, MAL_UIC_ERR); serviced = 1; rc = 0; } @@ -1006,7 +1122,7 @@ int enetInt (struct eth_device *dev) /* port by port dispatch of emac interrupts */ if (hw_p->devnum == 0) { - if (UIC_ETH0 & my_uic1msr) { /* look for EMAC errors */ + if (UIC_ETH0 & my_uicmsr_ethx) { /* look for EMAC errors */ emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); @@ -1017,14 +1133,15 @@ int enetInt (struct eth_device *dev) if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */ return (rc); /* we had errors so get out */ } } #if !defined(CONFIG_440SP) if (hw_p->devnum == 1) { - if (UIC_ETH1 & my_uic1msr) { /* look for EMAC errors */ + if (UIC_ETH1 & my_uicmsr_ethx) { /* look for EMAC errors */ emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); @@ -1035,7 +1152,8 @@ int enetInt (struct eth_device *dev) if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (UIC0SR, UIC_MRE | UIC_MTE); /* Clear */ - mtdcr (uic1sr, UIC_ETH1 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */ return (rc); /* we had errors so get out */ } } @@ -1102,10 +1220,10 @@ int enetInt (struct eth_device *dev) mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ switch (hw_p->devnum) { case 0: - mtdcr (uic1sr, UIC_ETH0); + mtdcr (UICSR_ETHX, UIC_ETH0); break; case 1: - mtdcr (uic1sr, UIC_ETH1); + mtdcr (UICSR_ETHX, UIC_ETH1); break; #if defined (CONFIG_440GX) case 2: @@ -1512,7 +1630,7 @@ 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) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) mal_ier = MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE | MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ; diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index c563457..baecf70 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -1,5 +1,5 @@ # -# (C) Copyright 2000 +# (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -23,28 +23,31 @@ include $(TOPDIR)/config.mk -LIB = lib$(CPU).a +LIB = $(obj)lib$(CPU).a START = start.o resetvec.o kgdb.o -AOBJS = dcr.o +SOBJS = dcr.o COBJS = 405gp_pci.o 4xx_enet.o \ bedbug_405.o commproc.o \ cpu.o cpu_init.o i2c.o interrupts.o \ - miiphy.o sdram.o serial.o \ - spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o + miiphy.o ndfc.o sdram.o serial.o \ + spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o \ + 440spe_pcie.o -OBJS = $(AOBJS) $(COBJS) +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +START := $(addprefix $(obj),$(START)) -all: .depend $(START) $(LIB) +all: $(obj).depend $(START) $(LIB) $(LIB): $(OBJS) - $(AR) crv $@ $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) ######################################################################### -.depend: Makefile $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c) - $(CC) -M $(CFLAGS) $(START:.o=.S) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ +# defines $(obj).depend target +include $(SRCTREE)/rules.mk -sinclude .depend +sinclude $(obj).depend ######################################################################### diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index 71303bc..f4a7208 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -41,14 +41,15 @@ DECLARE_GLOBAL_DATA_PTR; #endif - #if defined(CONFIG_440) #define FREQ_EBC (sys_info.freqEPB) #else #define FREQ_EBC (sys_info.freqPLB / sys_info.pllExtBusDiv) #endif -#if defined(CONFIG_405GP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +#if defined(CONFIG_405GP) || \ + defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) #define PCI_ASYNC @@ -58,7 +59,8 @@ int pci_async_enabled(void) return (mfdcr(strap) & PSR_PCI_ASYNC_EN); #endif -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) unsigned long val; mfsdr(sdr_sdstp1, val); @@ -82,9 +84,10 @@ int pci_arbiter_enabled(void) return (mfdcr(cpc0_strp1) & CPC0_STRP1_PAE_MASK); #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || \ + defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) unsigned long val; mfsdr(sdr_sdstp1, val); @@ -93,8 +96,10 @@ int pci_arbiter_enabled(void) } #endif -#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ - defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#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) #define I2C_BOOTROM @@ -102,17 +107,75 @@ int i2c_bootrom_enabled(void) { #if defined(CONFIG_405EP) return (mfdcr(cpc0_boot) & CPC0_BOOT_SEP); -#endif - -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) +#else unsigned long val; mfsdr(sdr_sdcs, val); return (val & SDR0_SDCS_SDD); #endif } + +#if defined(CONFIG_440GX) +#define SDR0_PINSTP_SHIFT 29 +static char *bootstrap_str[] = { + "EBC (16 bits)", + "EBC (8 bits)", + "EBC (32 bits)", + "EBC (8 bits)", + "PCI", + "I2C (Addr 0x54)", + "Reserved", + "I2C (Addr 0x50)", +}; +#endif + +#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#define SDR0_PINSTP_SHIFT 30 +static char *bootstrap_str[] = { + "EBC (8 bits)", + "PCI", + "I2C (Addr 0x54)", + "I2C (Addr 0x50)", +}; +#endif + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) +#define SDR0_PINSTP_SHIFT 29 +static char *bootstrap_str[] = { + "EBC (8 bits)", + "PCI", + "NAND (8 bits)", + "EBC (16 bits)", + "EBC (16 bits)", + "I2C (Addr 0x54)", + "PCI", + "I2C (Addr 0x52)", +}; +#endif + +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_PINSTP_SHIFT 29 +static char *bootstrap_str[] = { + "EBC (8 bits)", + "EBC (16 bits)", + "EBC (16 bits)", + "NAND (8 bits)", + "PCI", + "I2C (Addr 0x54)", + "PCI", + "I2C (Addr 0x52)", +}; +#endif + +#if defined(SDR0_PINSTP_SHIFT) +static int bootstrap_option(void) +{ + unsigned long val; + + mfsdr(sdr_pinstp, val); + return ((val & 0xe0000000) >> SDR0_PINSTP_SHIFT); +} +#endif /* SDR0_PINSTP_SHIFT */ #endif @@ -129,6 +192,7 @@ int checkcpu (void) char buf[32]; #if !defined(CONFIG_IOP480) + char addstr[64] = ""; sys_info_t sys_info; puts ("CPU: "); @@ -244,6 +308,26 @@ int checkcpu (void) #endif /* CONFIG_440GR */ #endif /* CONFIG_440 */ + case PVR_440EPX1_RA: + puts("EPx Rev. A"); + strcpy(addstr, "Security/Kasumi support"); + break; + + case PVR_440EPX2_RA: + puts("EPx Rev. A"); + strcpy(addstr, "No Security/Kasumi support"); + break; + + case PVR_440GRX1_RA: + puts("GRx Rev. A"); + strcpy(addstr, "Security/Kasumi support"); + break; + + case PVR_440GRX2_RA: + puts("GRx Rev. A"); + strcpy(addstr, "No Security/Kasumi support"); + break; + case PVR_440SP_RA: puts("SP Rev. A"); break; @@ -270,9 +354,16 @@ int checkcpu (void) sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, FREQ_EBC / 1000000); + if (addstr[0] != 0) + printf(" %s\n", addstr); + #if defined(I2C_BOOTROM) printf (" I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis"); -#endif +#if defined(SDR0_PINSTP_SHIFT) + printf (" Bootstrap Option %c - ", (char)bootstrap_option() + 'A'); + printf ("Boot ROM Location %s\n", bootstrap_str[bootstrap_option()]); +#endif /* SDR0_PINSTP_SHIFT */ +#endif /* I2C_BOOTROM */ #if defined(CONFIG_PCI) printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis"); @@ -315,6 +406,17 @@ int checkcpu (void) return 0; } +#if defined (CONFIG_440SPE) +int ppc440spe_revB() { + unsigned int pvr; + + pvr = get_pvr(); + if (pvr == PVR_440SPe_RB) + return 1; + else + return 0; +} +#endif /* ------------------------------------------------------------------------- */ diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index b27567f..def46f1 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -226,13 +226,19 @@ cpu_init_f (void) /* * GPIO0 setup (select GPIO or alternate function) */ - out32(GPIO0_OSRH, CFG_GPIO0_OSRH); /* output select */ +#if defined(CFG_GPIO0_OR) + out32(GPIO0_OR, CFG_GPIO0_OR); /* set initial state of output pins */ +#endif +#if defined(CFG_GPIO0_ODR) + out32(GPIO0_ODR, CFG_GPIO0_ODR); /* open-drain select */ +#endif + out32(GPIO0_OSRH, CFG_GPIO0_OSRH); /* output select */ out32(GPIO0_OSRL, CFG_GPIO0_OSRL); - out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H); /* input select */ + out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H); /* input select */ out32(GPIO0_ISR1L, CFG_GPIO0_ISR1L); - out32(GPIO0_TSRH, CFG_GPIO0_TSRH); /* three-state select */ + out32(GPIO0_TSRH, CFG_GPIO0_TSRH); /* three-state select */ out32(GPIO0_TSRL, CFG_GPIO0_TSRL); - out32(GPIO0_TCR, CFG_GPIO0_TCR); /* enable output driver for outputs */ + out32(GPIO0_TCR, CFG_GPIO0_TCR); /* enable output driver for outputs */ /* * Set EMAC noise filter bits diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 886f405..c5a9f02 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -57,12 +57,13 @@ static struct irq_action irq_vecs1[32]; /* For UIC1 */ void uic1_interrupt( void * parms); /* UIC1 handler */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) static struct irq_action irq_vecs2[32]; /* For UIC2 */ void uic2_interrupt( void * parms); /* UIC2 handler */ #endif /* CONFIG_440GX CONFIG_440SPE */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) static struct irq_action irq_vecs3[32]; /* For UIC3 */ void uic3_interrupt( void * parms); /* UIC3 handler */ #endif /* CONFIG_440SPE */ @@ -119,12 +120,13 @@ int interrupt_init_cpu (unsigned *decrementer_count) irq_vecs1[vec].handler = NULL; irq_vecs1[vec].arg = NULL; irq_vecs1[vec].count = 0; -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) irq_vecs2[vec].handler = NULL; irq_vecs2[vec].arg = NULL; irq_vecs2[vec].count = 0; #endif /* CONFIG_440GX */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) irq_vecs3[vec].handler = NULL; irq_vecs3[vec].arg = NULL; irq_vecs3[vec].count = 0; @@ -230,6 +232,32 @@ void external_interrupt(struct pt_regs *regs) } /* external_interrupt CONFIG_440GX */ +#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +void external_interrupt(struct pt_regs *regs) +{ + ulong uic_msr; + + /* + * Read masked interrupt status register to determine interrupt source + */ + /* 440 SPe uses base uic register */ + uic_msr = mfdcr(uic0msr); + + if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) ) + uic1_interrupt(0); + + if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) ) + uic2_interrupt(0); + + if (uic_msr & ~(UICB0_ALL)) + uic0_interrupt(0); + + mtdcr(uic0sr, uic_msr); + + return; + +} /* external_interrupt CONFIG_440EPX & CONFIG_440GRX */ + #elif defined(CONFIG_440SPE) void external_interrupt(struct pt_regs *regs) { @@ -303,7 +331,8 @@ void external_interrupt(struct pt_regs *regs) } #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* Handler for UIC0 interrupt */ void uic0_interrupt( void * parms) { @@ -394,7 +423,8 @@ void uic1_interrupt( void * parms) } #endif /* defined(CONFIG_440) */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) /* Handler for UIC2 interrupt */ void uic2_interrupt( void * parms) { @@ -496,7 +526,8 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) int i = vec; #if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) { i = vec - 32; irqa = irq_vecs1; @@ -523,7 +554,8 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) irqa[i].arg = arg; #if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i)); else if (vec > 63) @@ -546,7 +578,8 @@ void irq_free_handler (int vec) int i = vec; #if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) { irqa = irq_vecs1; i = vec - 32; @@ -567,7 +600,8 @@ void irq_free_handler (int vec) #endif #if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) if ((vec > 31) && (vec < 64)) mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i)); else if (vec > 63) @@ -635,7 +669,8 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf("\n"); #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) printf ("\nUIC 2\n"); printf ("Nr Routine Arg Count\n"); diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index aa580ed..6b98025 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -173,7 +173,8 @@ 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) +#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; #else @@ -183,7 +184,9 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ; #endif -#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && !defined(CONFIG__440SP) && !defined(CONFIG__440SPE) +#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ + !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; #endif sta_reg = sta_reg | (addr << 5); /* Phy address */ @@ -244,7 +247,8 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, sta_reg = 0; sta_reg = reg; /* reg address */ /* set clock (50Mhz) and read flags */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) +#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; #else @@ -254,7 +258,9 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ; #endif -#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && !defined(CONFIG__440SP) && !defined(CONFIG__440SPE) +#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ + !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ + !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) 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 */ diff --git a/cpu/ppc4xx/ndfc.c b/cpu/ppc4xx/ndfc.c new file mode 100644 index 0000000..3521731 --- /dev/null +++ b/cpu/ppc4xx/ndfc.c @@ -0,0 +1,193 @@ +/* + * Overview: + * Platform independend driver for NDFC (NanD Flash Controller) + * integrated into EP440 cores + * + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Based on original work by + * Thomas Gleixner + * Copyright 2006 IBM + * + * 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 (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \ + (defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX)) + +#include <nand.h> +#include <linux/mtd/ndfc.h> +#include <asm/processor.h> +#include <ppc440.h> + +static u8 hwctl = 0; + +static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) +{ + switch (cmd) { + case NAND_CTL_SETCLE: + hwctl |= 0x1; + break; + + case NAND_CTL_CLRCLE: + hwctl &= ~0x1; + break; + + case NAND_CTL_SETALE: + hwctl |= 0x2; + break; + + case NAND_CTL_CLRALE: + hwctl &= ~0x2; + break; + } +} + +static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + + if (hwctl & 0x1) + out8(base + NDFC_CMD, byte); + else if (hwctl & 0x2) + out8(base + NDFC_ALE, byte); + else + out8(base + NDFC_DATA, byte); +} + +static u_char ndfc_read_byte(struct mtd_info *mtdinfo) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + + return (in8(base + NDFC_DATA)); +} + +static int ndfc_dev_ready(struct mtd_info *mtdinfo) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + + while (!(in32(base + NDFC_STAT) & NDFC_STAT_IS_READY)) + ; + + return 1; +} + +#ifndef CONFIG_NAND_SPL +/* + * Don't use these speedup functions in NAND boot image, since the image + * has to fit into 4kByte. + */ + +/* + * Speedups for buffer read/write/verify + * + * NDFC allows 32bit read/write of data. So we can speed up the buffer + * functions. No further checking, as nand_base will always read/write + * page aligned. + */ +static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + uint32_t *p = (uint32_t *) buf; + + for (;len > 0; len -= 4) + *p++ = in32(base + NDFC_DATA); +} + +static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + uint32_t *p = (uint32_t *) buf; + + for (; len > 0; len -= 4) + out32(base + NDFC_DATA, *p++); +} + +static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len) +{ + struct nand_chip *this = mtdinfo->priv; + ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc; + uint32_t *p = (uint32_t *) buf; + + for (; len > 0; len -= 4) + if (*p++ != in32(base + NDFC_DATA)) + return -1; + + return 0; +} +#endif /* #ifndef CONFIG_NAND_SPL */ + +void board_nand_select_device(struct nand_chip *nand, int chip) +{ + /* + * Don't use "chip" to address the NAND device, + * generate the cs from the address where it is encoded. + */ + int cs = (ulong)nand->IO_ADDR_W & 0x00000003; + ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + + /* Set NandFlash Core Configuration Register */ + /* 1col x 2 rows */ + out32(base + NDFC_CCR, 0x00000000 | (cs << 24)); +} + +void board_nand_init(struct nand_chip *nand) +{ + int cs = (ulong)nand->IO_ADDR_W & 0x00000003; + ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc; + + nand->eccmode = NAND_ECC_SOFT; + + nand->hwcontrol = ndfc_hwcontrol; + nand->read_byte = ndfc_read_byte; + nand->write_byte = ndfc_write_byte; + nand->dev_ready = ndfc_dev_ready; + +#ifndef CONFIG_NAND_SPL + nand->write_buf = ndfc_write_buf; + nand->read_buf = ndfc_read_buf; + nand->verify_buf = ndfc_verify_buf; +#else + /* + * Setup EBC (CS0 only right now) + */ + mtdcr(ebccfga, xbcfg); + mtdcr(ebccfgd, 0xb8400000); + + mtebc(pb0cr, CFG_EBC_PB0CR); + mtebc(pb0ap, CFG_EBC_PB0AP); +#endif + + /* + * Select required NAND chip in NDFC + */ + board_nand_select_device(nand, cs); + out32(base + NDFC_BCFG0 + (cs << 2), 0x80002222); +} + +#endif diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c index ad3ca6e..fab0d95 100644 --- a/cpu/ppc4xx/serial.c +++ b/cpu/ppc4xx/serial.c @@ -264,10 +264,12 @@ int serial_tstc () #endif /* CONFIG_IOP480 */ /*****************************************************************************/ -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405EP) +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) || \ + defined(CONFIG_440) #if defined(CONFIG_440) -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) #define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000300 #define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000400 #else @@ -279,15 +281,34 @@ int serial_tstc () #define UART2_BASE CFG_PERIPHERAL_BASE + 0x00000600 #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) -#define CR0_MASK 0xdfffffff -#define CR0_EXTCLK_ENA 0x00800000 -#define CR0_UDIV_POS 0 -#else +#if defined(CONFIG_440GP) #define CR0_MASK 0x3fff0000 #define CR0_EXTCLK_ENA 0x00600000 #define CR0_UDIV_POS 16 -#endif /* CONFIG_440GX */ +#define UDIV_SUBTRACT 1 +#define UART0_SDR cntrl0 +#define MFREG(a, d) d = mfdcr(a) +#define MTREG(a, d) mtdcr(a, d) +#else /* #if defined(CONFIG_440GP) */ +/* all other 440 PPC's access clock divider via sdr register */ +#define CR0_MASK 0xdfffffff +#define CR0_EXTCLK_ENA 0x00800000 +#define CR0_UDIV_POS 0 +#define UDIV_SUBTRACT 0 +#define UART0_SDR sdr_uart0 +#define UART1_SDR sdr_uart1 +#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPe) +#define UART2_SDR sdr_uart2 +#endif +#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRx) +#define UART3_SDR sdr_uart3 +#endif +#define MFREG(a, d) mfsdr(a, d) +#define MTREG(a, d) mtsdr(a, d) +#endif /* #if defined(CONFIG_440GP) */ #elif defined(CONFIG_405EP) #define UART0_BASE 0xef600300 #define UART1_BASE 0xef600400 @@ -309,21 +330,15 @@ int serial_tstc () #if defined(CONFIG_UART1_CONSOLE) #define ACTING_UART0_BASE UART1_BASE #define ACTING_UART1_BASE UART0_BASE -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) -#define UART0_SDR sdr_uart1 -#define UART1_SDR sdr_uart0 -#endif /* CONFIG_440GX */ #else #define ACTING_UART0_BASE UART0_BASE #define ACTING_UART1_BASE UART1_BASE -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) -#define UART0_SDR sdr_uart0 -#define UART1_SDR sdr_uart1 -#endif /* CONFIG_440GX */ +#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) @@ -419,7 +434,7 @@ static void serial_divs (int baudrate, unsigned long *pudiv, *pbdiv = div/udiv; } -#endif /* defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLK */ +#endif /* defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLK) */ /* * Minimal serial functions needed to use one of the SMC ports @@ -441,23 +456,9 @@ int serial_init(void) unsigned long tmp; #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) -#if defined(CONFIG_SERIAL_MULTI) - if (UART0_BASE == dev_base) { - mfsdr(UART0_SDR,reg); - reg &= ~CR0_MASK; - } else { - mfsdr(UART1_SDR,reg); - reg &= ~CR0_MASK; - } -#else - mfsdr(UART0_SDR,reg); + MFREG(UART0_SDR, reg); reg &= ~CR0_MASK; -#endif -#else - reg = mfdcr(cntrl0) & ~CR0_MASK; -#endif /* CONFIG_440GX */ + #ifdef CFG_EXT_SERIAL_CLOCK reg |= CR0_EXTCLK_ENA; udiv = 1; @@ -471,47 +472,34 @@ int serial_init(void) serial_divs (gd->baudrate, &udiv, &bdiv); #endif -#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) - reg |= udiv << CR0_UDIV_POS; /* set the UART divisor */ -#if defined(CONFIG_SERIAL_MULTI) - if (UART0_BASE == dev_base) { - mtsdr (UART0_SDR,reg); - } else { - mtsdr (UART1_SDR,reg); - } -#else - mtsdr (UART0_SDR,reg); + reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */ + + /* + * Configure input clock to baudrate generator for all + * available serial ports here + */ + MTREG(UART0_SDR, reg); +#if defined(UART1_SDR) + MTREG(UART1_SDR, reg); #endif -#else - reg |= (udiv - 1) << CR0_UDIV_POS; /* set the UART divisor */ - mtdcr (cntrl0, reg); +#if defined(UART2_SDR) + MTREG(UART2_SDR, reg); #endif - -#if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_LCR, 0x80); /* set DLAB bit */ - out8 (dev_base + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (dev_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8 (dev_base + UART_FCR, 0x00); /* disable FIFO */ - out8 (dev_base + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8 (dev_base + UART_LSR); /* clear line status */ - val = in8 (dev_base + UART_RBR); /* read receive buffer */ - out8 (dev_base + UART_SCR, 0x00); /* set scratchpad */ - out8 (dev_base + UART_IER, 0x00); /* set interrupt enable reg */ -#else - out8 (ACTING_UART0_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8 (ACTING_UART0_BASE + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8 (ACTING_UART0_BASE + UART_FCR, 0x00); /* disable FIFO */ - out8 (ACTING_UART0_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8 (ACTING_UART0_BASE + UART_LSR); /* clear line status */ - val = in8 (ACTING_UART0_BASE + UART_RBR); /* read receive buffer */ - out8 (ACTING_UART0_BASE + UART_SCR, 0x00); /* set scratchpad */ - out8 (ACTING_UART0_BASE + UART_IER, 0x00); /* set interrupt enable reg */ +#if defined(UART3_SDR) + 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 */ + return (0); } @@ -564,29 +552,17 @@ int serial_init (void) tmp = gd->baudrate * udiv * 16; bdiv = (clk + tmp / 2) / tmp; -#if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_LCR, 0x80); /* set DLAB bit */ - out8 (dev_base + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (dev_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8 (dev_base + UART_FCR, 0x00); /* disable FIFO */ - out8 (dev_base + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8 (dev_base + UART_LSR); /* clear line status */ - val = in8 (dev_base + UART_RBR); /* read receive buffer */ - out8 (dev_base + UART_SCR, 0x00); /* set scratchpad */ - out8 (dev_base + UART_IER, 0x00); /* set interrupt enable reg */ -#else - out8 (ACTING_UART0_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8 (ACTING_UART0_BASE + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ - out8 (ACTING_UART0_BASE + UART_FCR, 0x00); /* disable FIFO */ - out8 (ACTING_UART0_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */ - val = in8 (ACTING_UART0_BASE + UART_LSR); /* clear line status */ - val = in8 (ACTING_UART0_BASE + UART_RBR); /* read receive buffer */ - out8 (ACTING_UART0_BASE + UART_SCR, 0x00); /* set scratchpad */ - out8 (ACTING_UART0_BASE + UART_IER, 0x00); /* set interrupt enable 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 */ + return (0); } @@ -598,55 +574,10 @@ void serial_setbrg_dev (unsigned long dev_base) void serial_setbrg (void) #endif { - unsigned long tmp; - unsigned long clk; - unsigned long udiv; - unsigned short bdiv; - -#ifdef CFG_EXT_SERIAL_CLOCK - clk = CFG_EXT_SERIAL_CLOCK; -#else - clk = gd->cpu_clk; -#endif - -#ifdef CONFIG_405EP - udiv = ((mfdcr (cpc0_ucr) & UCR0_MASK) >> UCR0_UDIV_POS); -#else - udiv = ((mfdcr (cntrl0) & 0x3e) >> 1) + 1; -#endif /* CONFIG_405EP */ - -#if !defined(CFG_EXT_SERIAL_CLOCK) && \ - ( defined(CONFIG_440GX) || defined(CONFIG_440EP) || \ - defined(CONFIG_440GR) || defined(CONFIG_440SP) || \ - defined(CONFIG_440SPE) ) - serial_divs (gd->baudrate, &udiv, &bdiv); - tmp = udiv << CR0_UDIV_POS; /* set the UART divisor */ -#if defined(CONFIG_SERIAL_MULTI) - if (UART0_BASE == dev_base) { - mtsdr (UART0_SDR, tmp); - } else { - mtsdr (UART1_SDR, tmp); - } -#else - mtsdr (UART0_SDR, tmp); -#endif - -#else - - tmp = gd->baudrate * udiv * 16; - bdiv = (clk + tmp / 2) / tmp; -#endif /* !defined(CFG_EXT_SERIAL_CLOCK) && (...) */ - #if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_LCR, 0x80); /* set DLAB bit */ - out8 (dev_base + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (dev_base + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ + serial_init_dev(dev_base); #else - out8 (ACTING_UART0_BASE + UART_LCR, 0x80); /* set DLAB bit */ - out8 (ACTING_UART0_BASE + UART_DLL, bdiv); /* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */ - out8 (ACTING_UART0_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */ + serial_init(); #endif } @@ -667,19 +598,11 @@ void serial_putc (const char c) /* check THRE bit, wait for transmiter available */ for (i = 1; i < 3500; i++) { -#if defined(CONFIG_SERIAL_MULTI) - if ((in8 (dev_base + UART_LSR) & 0x20) == 0x20) -#else - if ((in8 (ACTING_UART0_BASE + UART_LSR) & 0x20) == 0x20) -#endif + if ((in8 (UART_BASE + UART_LSR) & 0x20) == 0x20) break; udelay (100); } -#if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_THR, c); /* put character out */ -#else - out8 (ACTING_UART0_BASE + UART_THR, c); /* put character out */ -#endif + out8 (UART_BASE + UART_THR, c); /* put character out */ } #if defined(CONFIG_SERIAL_MULTI) @@ -709,11 +632,7 @@ int serial_getc (void) #if defined(CONFIG_HW_WATCHDOG) WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ #endif /* CONFIG_HW_WATCHDOG */ -#if defined(CONFIG_SERIAL_MULTI) - status = in8 (dev_base + UART_LSR); -#else - status = in8 (ACTING_UART0_BASE + UART_LSR); -#endif + status = in8 (UART_BASE + UART_LSR); if ((status & asyncLSRDataReady1) != 0x0) { break; } @@ -721,22 +640,14 @@ int serial_getc (void) asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1 )) != 0) { -#if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_LSR, -#else - out8 (ACTING_UART0_BASE + UART_LSR, -#endif + out8 (UART_BASE + UART_LSR, asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1); } } -#if defined(CONFIG_SERIAL_MULTI) - return (0x000000ff & (int) in8 (dev_base)); -#else - return (0x000000ff & (int) in8 (ACTING_UART0_BASE)); -#endif + return (0x000000ff & (int) in8 (UART_BASE)); } #if defined(CONFIG_SERIAL_MULTI) @@ -747,11 +658,7 @@ int serial_tstc (void) { unsigned char status; -#if defined(CONFIG_SERIAL_MULTI) - status = in8 (dev_base + UART_LSR); -#else - status = in8 (ACTING_UART0_BASE + UART_LSR); -#endif + status = in8 (UART_BASE + UART_LSR); if ((status & asyncLSRDataReady1) != 0x0) { return (1); } @@ -759,11 +666,7 @@ int serial_tstc (void) asyncLSROverrunError1 | asyncLSRParityError1 | asyncLSRBreakInterrupt1 )) != 0) { -#if defined(CONFIG_SERIAL_MULTI) - out8 (dev_base + UART_LSR, -#else - out8 (ACTING_UART0_BASE + UART_LSR, -#endif + out8 (UART_BASE + UART_LSR, asyncLSRFramingError1 | asyncLSROverrunError1 | asyncLSRParityError1 | diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index e552c03..2d16a83 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -199,7 +199,8 @@ ulong get_PCI_freq (void) #elif defined(CONFIG_440) -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) void get_sys_info (sys_info_t *sysInfo) { unsigned long temp; diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 699fa7f..8e000d3 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -117,12 +117,16 @@ .extern ext_bus_cntlr_init .extern sdram_init +#ifdef CONFIG_NAND_U_BOOT + .extern reconfig_tlb0 +#endif /* * Set up GOT: Global Offset Table * * Use r14 to access the GOT */ +#if !defined(CONFIG_NAND_SPL) START_GOT GOT_ENTRY(_GOT2_TABLE_) GOT_ENTRY(_FIXUP_TABLE_) @@ -136,6 +140,18 @@ GOT_ENTRY(_end) GOT_ENTRY(__bss_start) END_GOT +#endif /* CONFIG_NAND_SPL */ + +#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) + /* + * NAND U-Boot image is started from offset 0 + */ + .text + bl reconfig_tlb0 + GET_GOT + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + bl board_init_f +#endif /* * 440 Startup -- on reset only the top 4k of the effective @@ -150,11 +166,21 @@ */ #if defined(CONFIG_440) +#if !defined(CONFIG_NAND_SPL) .section .bootpg,"ax" +#endif .globl _start_440 /**************************************************************************/ _start_440: + /*--------------------------------------------------------------------+ + | 440EPX BUP Change - Hardware team request + +--------------------------------------------------------------------*/ +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) + sync + nop + nop +#endif /*----------------------------------------------------------------+ | Core bug fix. Clear the esr +-----------------------------------------------------------------*/ @@ -171,15 +197,31 @@ _start_440: mtspr srr1,r0 mtspr csrr0,r0 mtspr csrr1,r0 -#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) /* NOTE: 440GX adds machine check status regs */ + /* NOTE: 440GX adds machine check status regs */ +#if defined(CONFIG_440) && !defined(CONFIG_440GP) mtspr mcsrr0,r0 mtspr mcsrr1,r0 - mfspr r1, mcsr + mfspr r1,mcsr mtspr mcsr,r1 #endif + + /*----------------------------------------------------------------*/ + /* CCR0 init */ + /*----------------------------------------------------------------*/ + /* Disable store gathering & broadcast, guarantee inst/data + * cache block touch, force load/store alignment + * (see errata 1.12: 440_33) + */ + lis r1,0x0030 /* store gathering & broadcast disable */ + ori r1,r1,0x6000 /* cache touch */ + mtspr ccr0,r1 + /*----------------------------------------------------------------*/ /* Initialize debug */ /*----------------------------------------------------------------*/ + mfspr r1,dbcr0 + andis. r1, r1, 0x8000 /* test DBCR0[EDM] bit */ + bne skip_debug_init /* if set, don't clear debug register */ mtspr dbcr0,r0 mtspr dbcr1,r0 mtspr dbcr2,r0 @@ -193,17 +235,7 @@ _start_440: mfspr r1,dbsr mtspr dbsr,r1 /* Clear all valid bits */ - - /*----------------------------------------------------------------*/ - /* CCR0 init */ - /*----------------------------------------------------------------*/ - /* Disable store gathering & broadcast, guarantee inst/data - * cache block touch, force load/store alignment - * (see errata 1.12: 440_33) - */ - lis r1,0x0030 /* store gathering & broadcast disable */ - ori r1,r1,0x6000 /* cache touch */ - mtspr ccr0,r1 +skip_debug_init: #if defined (CONFIG_440SPE) /*----------------------------------------------------------------+ @@ -315,7 +347,23 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/ /*----------------------------------------------------------------*/ /* TLB entry setup -- step thru tlbtab */ /*----------------------------------------------------------------*/ +#if defined(CONFIG_440SPE) + /*----------------------------------------------------------------*/ + /* We have different TLB tables for revA and rev B of 440SPe */ + /*----------------------------------------------------------------*/ + mfspr r1, PVR + lis r0,0x5342 + ori r0,r0,0x1891 + cmpw r7,r1,r0 + bne r7,..revA + bl tlbtabB + b ..goon +..revA: + bl tlbtabA +..goon: +#else bl tlbtab /* Get tlbtab pointer */ +#endif mr r5,r0 li r1,0x003f /* 64 TLB entries max */ mtctr r1 @@ -336,7 +384,53 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/ /*----------------------------------------------------------------*/ /* Continue from 'normal' start */ /*----------------------------------------------------------------*/ -2: bl 3f +2: + +#if defined(CONFIG_NAND_SPL) + /* + * Enable internal SRAM + */ + lis r2,0x7fff + ori r2,r2,0xffff + mfdcr r1,isram0_dpc + and r1,r1,r2 /* Disable parity check */ + mtdcr isram0_dpc,r1 + mfdcr r1,isram0_pmeg + and r1,r1,r2 /* Disable pwr mgmt */ + mtdcr isram0_pmeg,r1 + + /* + * Copy SPL from cache into internal SRAM + */ + li r4,(CFG_NAND_BOOT_SPL_SIZE >> 2) - 1 + mtctr r4 + lis r2,CFG_NAND_BOOT_SPL_SRC@h + ori r2,r2,CFG_NAND_BOOT_SPL_SRC@l + lis r3,CFG_NAND_BOOT_SPL_DST@h + ori r3,r3,CFG_NAND_BOOT_SPL_DST@l +spl_loop: + lwzu r4,4(r2) + stwu r4,4(r3) + bdnz spl_loop + + /* + * Jump to code in RAM + */ + bl 00f +00: mflr r10 + lis r3,(CFG_NAND_BOOT_SPL_SRC - CFG_NAND_BOOT_SPL_DST)@h + ori r3,r3,(CFG_NAND_BOOT_SPL_SRC - CFG_NAND_BOOT_SPL_DST)@l + sub r10,r10,r3 + addi r10,r10,28 + mtlr r10 + blr + +start_ram: + sync + isync +#endif + + bl 3f b _start 3: li r0,0 @@ -350,6 +444,7 @@ rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/ * r3 - 1st arg to board_init(): IMMP pointer * r4 - 2nd arg to board_init(): boot flag */ +#ifndef CONFIG_NAND_SPL .text .long 0x27051956 /* U-Boot Magic Number */ .globl version_string @@ -363,6 +458,7 @@ version_string: * location (0x100) is where the CriticalInput Execption should be. */ . = EXC_OFF_SYS_RESET +#endif .globl _start _start: @@ -401,7 +497,8 @@ _start: /* Setup the internal SRAM */ /*----------------------------------------------------------------*/ li r0,0 -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) + +#ifdef CFG_INIT_RAM_DCACHE /* Clear Dcache to use as RAM */ addis r3,r0,CFG_INIT_RAM_ADDR@h ori r3,r3,CFG_INIT_RAM_ADDR@l @@ -417,19 +514,22 @@ _start: dcbz r0,r3 addi r3,r3,32 bdnz ..d_ag -#else -#if defined (CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) +#endif /* CFG_INIT_RAM_DCACHE */ + + /* 440EP & 440GR are only 440er PPC's without internal SRAM */ +#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) + /* not all PPC's have internal SRAM usable as L2-cache */ +#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */ #endif - mtdcr isram0_sb1cr,r0 /* Disable bank 1 */ - li r2,0x7fff + lis r2,0x7fff ori r2,r2,0xffff mfdcr r1,isram0_dpc and r1,r1,r2 /* Disable parity check */ mtdcr isram0_dpc,r1 mfdcr r1,isram0_pmeg - andis. r1,r1,r2 /* Disable pwr mgmt */ + and r1,r1,r2 /* Disable pwr mgmt */ mtdcr isram0_pmeg,r1 lis r1,0x8000 /* BAS = 8000_0000 */ @@ -458,11 +558,12 @@ _start: lis r1, 0x0003 ori r1,r1, 0x0984 /* fourth 64k */ mtdcr isram0_sb3cr,r1 -#else +#elif defined(CONFIG_440GP) ori r1,r1,0x0380 /* 8k rw */ mtdcr isram0_sb0cr,r1 + mtdcr isram0_sb1cr,r0 /* Disable bank 1 */ #endif -#endif +#endif /* #if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) */ /*----------------------------------------------------------------*/ /* Setup the stack in internal SRAM */ @@ -479,10 +580,14 @@ _start: stwu r1,-8(r1) /* Save back chain and move SP */ stw r0,+12(r1) /* Save return addr (underflow vect) */ +#ifdef CONFIG_NAND_SPL + bl nand_boot /* will not return */ +#else GET_GOT bl cpu_init_f /* run low-level CPU init code (from Flash) */ bl board_init_f +#endif #endif /* CONFIG_440 */ @@ -792,6 +897,7 @@ _start: /*----------------------------------------------------------------------- */ +#ifndef CONFIG_NAND_SPL /*****************************************************************************/ .globl _start_of_vectors _start_of_vectors: @@ -997,6 +1103,7 @@ crit_return: lwz r1,GPR1(r1) SYNC rfci +#endif /* CONFIG_NAND_SPL */ /* Cache functions. */ @@ -1238,6 +1345,7 @@ ppcSync: /*------------------------------------------------------------------------------*/ +#ifndef CONFIG_NAND_SPL /* * void relocate_code (addr_sp, gd, addr_moni) * @@ -1251,7 +1359,9 @@ ppcSync: */ .globl relocate_code relocate_code: -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SPE) +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SPE) /* * On some 440er platforms the cache is enabled in the first TLB (Boot-CS) * to speed up the boot process. Now this cache needs to be disabled. @@ -1466,22 +1576,22 @@ trap_init: cmplw 0, r7, r8 blt 4b -#if !defined(CONFIG_440GX) && !defined(CONFIG_440SPE) +#if !defined(CONFIG_440) addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ mtmsr r7 /* change MSR */ #else - bl __440gx_msr_set - b __440gx_msr_continue + bl __440_msr_set + b __440_msr_continue -__440gx_msr_set: +__440_msr_set: addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ mtspr srr1,r7 mflr r7 mtspr srr0,r7 rfi -__440gx_msr_continue: +__440_msr_continue: #endif mtlr r4 /* restore link register */ @@ -1500,6 +1610,7 @@ trap_reloc: stw r0, 4(r7) blr +#endif /* CONFIG_NAND_SPL */ /**************************************************************************/ @@ -1587,7 +1698,8 @@ ppc405ep_init: mtdcr ebccfgd,r3 #endif - addi r3,0,CPC0_PCI_HOST_CFG_EN +#ifndef CFG_CPC0_PCI + li r3,CPC0_PCI_HOST_CFG_EN #ifdef CONFIG_BUBINGA /* !----------------------------------------------------------------------- @@ -1602,6 +1714,9 @@ ppc405ep_init: beq ..pci_cfg_set /* if not set, then bypass reg write*/ #endif ori r3,r3,CPC0_PCI_ARBIT_EN +#else /* CFG_CPC0_PCI */ + li r3,CFG_CPC0_PCI +#endif /* CFG_CPC0_PCI */ ..pci_cfg_set: mtdcr CPC0_PCI, r3 /* Enable internal arbiter*/ diff --git a/cpu/ppc4xx/usb_ohci.c b/cpu/ppc4xx/usb_ohci.c index bb57658..ab852c5 100644 --- a/cpu/ppc4xx/usb_ohci.c +++ b/cpu/ppc4xx/usb_ohci.c @@ -76,7 +76,7 @@ #define m16_swap(x) swap_16(x) #define m32_swap(x) swap_32(x) -#ifdef CONFIG_440EP +#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) #define ohci_cpu_to_le16(x) (x) #define ohci_cpu_to_le32(x) (x) #else @@ -1599,7 +1599,11 @@ int usb_lowlevel_init(void) gohci.disabled = 1; gohci.sleeping = 0; gohci.irq = -1; - gohci.regs = (struct ohci_regs *)(CFG_PERIPHERAL_BASE | 0x1000); +#if defined(CONFIG_440EP) + gohci.regs = (struct ohci_regs *)(CFG_PERIPHERAL_BASE | 0x1000); +#elif defined(CONFIG_440EPX) + gohci.regs = (struct ohci_regs *)(CFG_USB_HOST); +#endif gohci.flags = 0; gohci.slot_name = "ppc440"; diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c index 8262c54..6140d2a 100644 --- a/cpu/ppc4xx/usbdev.c +++ b/cpu/ppc4xx/usbdev.c @@ -3,7 +3,7 @@ #include <common.h> #include <asm/processor.h> -#ifdef CONFIG_440EP +#if (defined(CONFIG_440EP) || defined(CONFIG_440EPX)) && (CONFIG_COMMANDS & CFG_CMD_USB) #include <usb.h> #include "usbdev.h" @@ -186,6 +186,21 @@ int usbInt(void) return 0; } +#if defined(CONFIG_440EPX) +void usb_dev_init() +{ + printf("USB 2.0 Device init\n"); + + /*usb dev init */ + *(unsigned char *)USB2D0_POWER_8 = 0xa1; /* 2.0 */ + + /*enable interrupts */ + *(unsigned char *)USB2D0_INTRUSBE_8 = 0x0f; + + irq_install_handler(VECNUM_HSB2D, (interrupt_handler_t *) usbInt, + NULL); +} +#else void usb_dev_init() { #ifdef USB_2_0_DEVICE @@ -210,5 +225,6 @@ void usb_dev_init() irq_install_handler(VECNUM_USBDEV, (interrupt_handler_t *) usbInt, NULL); } +#endif -#endif /*CONFIG_440EP */ +#endif /* CONFIG_440EP || CONFIG_440EPX */ diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h index 93cef02..685d48b 100644 --- a/cpu/ppc4xx/vecnum.h +++ b/cpu/ppc4xx/vecnum.h @@ -31,7 +31,94 @@ #ifndef _VECNUMS_H_ #define _VECNUMS_H_ -#if defined(CONFIG_440SPE) +#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 */ |