diff options
-rw-r--r-- | CHANGELOG | 17 | ||||
-rw-r--r-- | board/amcc/yucca/init.S | 56 | ||||
-rw-r--r-- | board/amcc/yucca/yucca.c | 130 | ||||
-rw-r--r-- | board/trab/trab.c | 8 | ||||
-rw-r--r-- | common/cmd_usb.c | 7 | ||||
-rw-r--r-- | common/usb.c | 91 | ||||
-rw-r--r-- | cpu/ppc4xx/405gp_pci.c | 5 | ||||
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.c | 592 | ||||
-rw-r--r-- | cpu/ppc4xx/440spe_pcie.h | 162 | ||||
-rw-r--r-- | cpu/ppc4xx/Makefile | 3 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu.c | 11 | ||||
-rw-r--r-- | cpu/ppc4xx/start.S | 16 | ||||
-rw-r--r-- | include/common.h | 4 | ||||
-rw-r--r-- | include/configs/TQM85xx.h | 4 | ||||
-rw-r--r-- | include/configs/yucca.h | 26 | ||||
-rw-r--r-- | include/usb.h | 1 |
16 files changed, 1075 insertions, 58 deletions
@@ -15,6 +15,23 @@ Changes since U-Boot 1.1.4: * Change "mii info" to not print an error upon missing PHY at address Patch by Stefan Roese, 07 Aug 2006 +* Fix PCI-Express on PPC440SPe rev. A. + +* Fix preboot message on TQM85xx after switching to hush parser. + +* Adapt TQM85xx ramdisk address to Linux kernel memory map + +* Add initial support for PCI-Express on PPC440SPe (Yucca board). + +* Fix compiler warning for TRAB board. + Patch by Martin Krause, 07 Aug 2006 + +* Prevent USB commands from working when USB is stopped. + +* Add rudimentary handling of alternate settings of USB interfaces. + This is in order to fix issues with some USB sticks timing out + during initialization. Some code readability improvements. + * PPC440 DDR setup: Set SDRAM0_CFG0[PMU]=0 for best performance AMCC suggested to set the PMU bit to 0 for best performace on the PPC440 DDR controller. diff --git a/board/amcc/yucca/init.S b/board/amcc/yucca/init.S index cb28936..c9eca68 100644 --- a/board/amcc/yucca/init.S +++ b/board/amcc/yucca/init.S @@ -82,9 +82,49 @@ *************************************************************************/ .section .bootpg,"ax" - .globl tlbtab -tlbtab: +/************************************************************************** + * TLB table for revA + *************************************************************************/ + .globl tlbtabA +tlbtabA: + tlbtab_start + tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G) + + tlbentry(CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_SDRAM_BASE + 0x10000000, SZ_256M, 0x10000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_SDRAM_BASE + 0x20000000, SZ_256M, 0x20000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) + + tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) + tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I) + + tlbentry(CFG_OPER_FLASH, SZ_16M, 0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_BASE, SZ_16K, 0x20000000, 0xC, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x40000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x80000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0xC0000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x50000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x90000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0xD0000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbtab_end + +/************************************************************************** + * TLB table for revB + * + * Notice: revB of the 440SPe chip is very strict about PLB real addresses + * 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. + *************************************************************************/ + .globl tlbtabB +tlbtabB: tlbtab_start tlbentry(0xfff00000, SZ_16M, 0xfff00000, 4, AC_R|AC_W|AC_X|SA_G) @@ -94,11 +134,19 @@ tlbtab: tlbentry(CFG_SDRAM_BASE + 0x30000000, SZ_256M, 0x30000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I) tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) - tlbentry(CFG_FPGA_BASE,SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I) + tlbentry(CFG_FPGA_BASE, SZ_1K, 0xE2000000, 4,AC_R|AC_W|SA_I) - tlbentry(CFG_OPER_FLASH,SZ_16M,0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry(CFG_OPER_FLASH, SZ_16M, 0xE7000000, 4,AC_R|AC_W|AC_X|SA_G|SA_I) tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) + + tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x00100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x20100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0x40100000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x10000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x30000000, 0xD, AC_R|AC_W|SA_G|SA_I) + tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0x50000000, 0xD, AC_R|AC_W|SA_G|SA_I) tlbtab_end diff --git a/board/amcc/yucca/yucca.c b/board/amcc/yucca/yucca.c index ce1312c..af12839 100644 --- a/board/amcc/yucca/yucca.c +++ b/board/amcc/yucca/yucca.c @@ -21,12 +21,16 @@ * MA 02111-1307 USA * * Port to AMCC-440SPE Evaluation Board SOP - April 2005 + * + * PCIe supporting routines derived from Linux 440SPe PCIe driver. */ #include <common.h> #include <ppc4xx.h> #include <asm/processor.h> #include <i2c.h> +#include <asm-ppc/io.h> + #include "yucca.h" void fpga_init (void); @@ -39,6 +43,9 @@ int get_console_port(void); unsigned long ppcMfcpr(unsigned long cpr_reg); unsigned long ppcMfsdr(unsigned long sdr_reg); +int ppc440spe_init_pcie_rootport(int port); +void ppc440spe_setup_pcie(struct pci_controller *hose, int port); + #define DEBUG_ENV #ifdef DEBUG_ENV #define DEBUGF(fmt,args...) printf(fmt ,##args) @@ -908,6 +915,7 @@ void pci_target_init(struct pci_controller * hose ) } #endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ +#if defined(CONFIG_PCI) /************************************************************************* * is_pci_host * @@ -923,12 +931,132 @@ void pci_target_init(struct pci_controller * hose ) * * ************************************************************************/ -#if defined(CONFIG_PCI) int is_pci_host(struct pci_controller *hose) { /* The yucca board is always configured as host. */ return 1; } + + +int yucca_pcie_card_present(int port) +{ + u16 reg; + + reg = in_be16((u16 *)FPGA_REG1C); + switch(port) { + case 0: + return !(reg & FPGA_REG1C_PE0_PRSNT); + case 1: + return !(reg & FPGA_REG1C_PE1_PRSNT); + case 2: + return !(reg & FPGA_REG1C_PE2_PRSNT); + default: + return 0; + } +} + +/* + * For the given slot, set rootpoint mode, send power to the slot, + * turn on the green LED and turn off the yellow LED, enable the clock + * and turn off reset. + */ +void yucca_setup_pcie_fpga_rootpoint(int port) +{ + u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint; + + switch(port) { + case 0: + rootpoint = FPGA_REG1C_PE0_ROOTPOINT; + endpoint = 0; + power = FPGA_REG1A_PE0_PWRON; + green_led = FPGA_REG1A_PE0_GLED; + clock = FPGA_REG1A_PE0_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE0_YLED; + reset_off = FPGA_REG1C_PE0_PERST; + break; + case 1: + rootpoint = 0; + endpoint = FPGA_REG1C_PE1_ENDPOINT; + power = FPGA_REG1A_PE1_PWRON; + green_led = FPGA_REG1A_PE1_GLED; + clock = FPGA_REG1A_PE1_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE1_YLED; + reset_off = FPGA_REG1C_PE1_PERST; + break; + case 2: + rootpoint = 0; + endpoint = FPGA_REG1C_PE2_ENDPOINT; + power = FPGA_REG1A_PE2_PWRON; + green_led = FPGA_REG1A_PE2_GLED; + clock = FPGA_REG1A_PE2_REFCLK_ENABLE; + yellow_led = FPGA_REG1A_PE2_YLED; + reset_off = FPGA_REG1C_PE2_PERST; + break; + + default: + return; + } + + out_be16((u16 *)FPGA_REG1A, + ~(power | clock | green_led) & + (yellow_led | in_be16((u16 *)FPGA_REG1A))); + + out_be16((u16 *)FPGA_REG1C, + ~(endpoint | reset_off) & + (rootpoint | in_be16((u16 *)FPGA_REG1C))); + /* + * Leave device in reset for a while after powering on the + * slot to give it a chance to initialize. + */ + udelay(250 * 1000); + + out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C)); +} + + +static struct pci_controller pcie_hose[3] = {{0},{0},{0}}; + +void pcie_setup_hoses(void) +{ + struct pci_controller *hose; + int i, bus; + + /* + * assume we're called after the PCIX hose is initialized, which takes + * bus ID 0 and therefore start numbering PCIe's from 1. + */ + bus = 1; + for (i = 0; i <= 2; i++) { + /* Check for yucca card presence */ + if (!yucca_pcie_card_present(i)) + continue; + + yucca_setup_pcie_fpga_rootpoint(i); + + if (ppc440spe_init_pcie_rootport(i)) { + printf("PCIE%d: initialization failed\n", i); + continue; + } + + hose = &pcie_hose[i]; + hose->first_busno = bus; + hose->last_busno = bus; + bus++; + + /* setup mem resource */ + pci_set_region(hose->regions + 0, + CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, + CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, + CFG_PCIE_MEMSIZE, + PCI_REGION_MEM + ); + hose->region_count = 1; + pci_register_hose(hose); + + ppc440spe_setup_pcie(hose, i); + hose->last_busno = pci_hose_scan(hose); + } +} #endif /* defined(CONFIG_PCI) */ int misc_init_f (void) diff --git a/board/trab/trab.c b/board/trab/trab.c index 26e52d2..d8a726b 100644 --- a/board/trab/trab.c +++ b/board/trab/trab.c @@ -175,9 +175,11 @@ int misc_init_r (void) #endif /* CONFIG_VERSION_VARIABLE */ #ifdef CONFIG_AUTO_UPDATE - extern int do_auto_update(void); - /* this has priority over all else */ - do_auto_update(); + { + extern int do_auto_update(void); + /* this has priority over all else */ + do_auto_update(); + } #endif for (i = 0; i < KEYBD_KEY_NUM; ++i) { diff --git a/common/cmd_usb.c b/common/cmd_usb.c index fdfd042..28c05aa 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -186,7 +186,7 @@ void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_devic void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,struct usb_device *dev) { printf(" Interface: %d\n",ifdesc->bInterfaceNumber); - printf(" - Alternate Settings %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints); + printf(" - Alternate Setting %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints); printf(" - Class "); usb_display_class_sub(ifdesc->bInterfaceClass,ifdesc->bInterfaceSubClass,ifdesc->bInterfaceProtocol); printf("\n"); @@ -444,6 +444,7 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int i; struct usb_device *dev = NULL; + extern char usb_started; #ifdef CONFIG_USB_STORAGE block_dev_desc_t *stor_dev; #endif @@ -477,6 +478,10 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) usb_stop(); return 0; } + if (!usb_started) { + printf("USB is stopped. Please issue 'usb start' first.\n"); + return 1; + } if (strncmp(argv[1],"tree",4) == 0) { printf("\nDevice Tree:\n"); usb_show_tree(usb_get_dev_index(0)); diff --git a/common/usb.c b/common/usb.c index d9515e6..0857494 100644 --- a/common/usb.c +++ b/common/usb.c @@ -72,6 +72,8 @@ static int running; static int asynch_allowed; static struct devrequest setup_packet; +char usb_started; /* flag for the started/stopped USB status */ + /********************************************************************** * some forward declerations... */ @@ -110,10 +112,12 @@ int usb_init(void) printf("scanning bus for devices... "); running=1; usb_scan_devices(); + usb_started = 1; return 0; } else { printf("Error, couldn't init Lowlevel part\n"); + usb_started = 0; return -1; } } @@ -124,6 +128,7 @@ int usb_init(void) int usb_stop(void) { asynch_allowed=1; + usb_started = 0; usb_hub_reset(); return usb_lowlevel_stop(); } @@ -280,56 +285,68 @@ int usb_set_maxpacket(struct usb_device *dev) int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) { struct usb_descriptor_header *head; - int index,ifno,epno; - ifno=-1; - epno=-1; - - dev->configno=cfgno; - head =(struct usb_descriptor_header *)&buffer[0]; - if(head->bDescriptorType!=USB_DT_CONFIG) { - printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType); + int index, ifno, epno, curr_if_num; + int i; + unsigned char *ch; + + ifno = -1; + epno = -1; + curr_if_num = -1; + + dev->configno = cfgno; + head = (struct usb_descriptor_header *) &buffer[0]; + if(head->bDescriptorType != USB_DT_CONFIG) { + printf(" ERROR: NOT USB_CONFIG_DESC %x\n", head->bDescriptorType); return -1; } - memcpy(&dev->config,buffer,buffer[0]); - dev->config.wTotalLength=swap_16(dev->config.wTotalLength); - dev->config.no_of_if=0; + memcpy(&dev->config, buffer, buffer[0]); + dev->config.wTotalLength = swap_16(dev->config.wTotalLength); + dev->config.no_of_if = 0; - index=dev->config.bLength; + index = dev->config.bLength; /* Ok the first entry must be a configuration entry, now process the others */ - head=(struct usb_descriptor_header *)&buffer[index]; - while(index+1 < dev->config.wTotalLength) { + head = (struct usb_descriptor_header *) &buffer[index]; + while(index + 1 < dev->config.wTotalLength) { switch(head->bDescriptorType) { case USB_DT_INTERFACE: - ifno=dev->config.no_of_if; - dev->config.no_of_if++; /* found an interface desc, increase numbers */ - memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */ - dev->config.if_desc[ifno].no_of_ep=0; - + if(((struct usb_interface_descriptor *) &buffer[index])-> + bInterfaceNumber != curr_if_num) { + /* this is a new interface, copy new desc */ + ifno = dev->config.no_of_if; + dev->config.no_of_if++; + memcpy(&dev->config.if_desc[ifno], + &buffer[index], buffer[index]); + dev->config.if_desc[ifno].no_of_ep = 0; + dev->config.if_desc[ifno].num_altsetting = 1; + curr_if_num = dev->config.if_desc[ifno].bInterfaceNumber; + } else { + /* found alternate setting for the interface */ + dev->config.if_desc[ifno].num_altsetting++; + } break; case USB_DT_ENDPOINT: - epno=dev->config.if_desc[ifno].no_of_ep; + epno = dev->config.if_desc[ifno].no_of_ep; dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */ - memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]); - dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize - =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize); - USB_PRINTF("if %d, ep %d\n",ifno,epno); + memcpy(&dev->config.if_desc[ifno].ep_desc[epno], + &buffer[index], buffer[index]); + dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize = + swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize); + USB_PRINTF("if %d, ep %d\n", ifno, epno); break; default: - if(head->bLength==0) + if(head->bLength == 0) return 1; - USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType); + USB_PRINTF("unknown Description Type : %x\n", head->bDescriptorType); { - int i; - unsigned char *ch; - ch=(unsigned char *)head; - for(i=0;i<head->bLength; i++) - USB_PRINTF("%02X ",*ch++); + ch = (unsigned char *)head; + for(i = 0; i < head->bLength; i++) + USB_PRINTF("%02X ", *ch++); USB_PRINTF("\n\n\n"); } break; } - index+=head->bLength; - head=(struct usb_descriptor_header *)&buffer[index]; + index += head->bLength; + head = (struct usb_descriptor_header *)&buffer[index]; } return 1; } @@ -443,6 +460,14 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) printf("selecting invalid interface %d", interface); return -1; } + /* + * We should return now for devices with only one alternate setting. + * According to 9.4.10 of the Universal Serial Bus Specification Revision 2.0 + * such devices can return with a STALL. This results in some USB sticks + * timeouting during initialization and then being unusable in U-Boot. + */ + if (if_face->num_altsetting == 1) + return 0; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index cf5eccb..0b0686b 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 */ @@ -563,10 +562,12 @@ void pci_440_init (struct pci_controller *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..2e920aa --- /dev/null +++ b/cpu/ppc4xx/440spe_pcie.c @@ -0,0 +1,592 @@ +/* + * (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; +} + +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; +} + +void ppc440spe_setup_pcie(struct pci_controller *hose, int port) +{ + volatile void *mbase = 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; + 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 bus numbers on our root port + */ + if (ppc440spe_revB()) { + out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); + out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); + out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); + } else { + out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); + out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0); + } + + /* + * 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, (CFG_PCIE_MEMBASE + + port * CFG_PCIE_MEMSIZE)); + + 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, 0); + out_le32(mbase + PECFG_PIM0LAH, 0); + 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); +} +#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..47df762 --- /dev/null +++ b/cpu/ppc4xx/440spe_pcie.h @@ -0,0 +1,162 @@ +/* + * 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_PIMEN 0x33c +#define PECFG_PIM0LAL 0x340 +#define PECFG_PIM0LAH 0x344 +#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(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/Makefile b/cpu/ppc4xx/Makefile index c563457..7d6990f 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -31,7 +31,8 @@ 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 + spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o \ + 440spe_pcie.o OBJS = $(AOBJS) $(COBJS) diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index 71303bc..bc51fbf 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -315,6 +315,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/start.S b/cpu/ppc4xx/start.S index 699fa7f..60ed2d5 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -315,7 +315,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 diff --git a/include/common.h b/include/common.h index e4637ad..bd41ae1 100644 --- a/include/common.h +++ b/include/common.h @@ -245,6 +245,9 @@ void pciinfo (int, int); void pci_master_init (struct pci_controller *); # endif int is_pci_host (struct pci_controller *); +#if defined(CONFIG_440SPE) + void pcie_setup_hoses(void); +#endif #endif int misc_init_f (void); @@ -462,6 +465,7 @@ void get_sys_info ( sys_info_t * ); # if defined(CONFIG_440SPE) unsigned long determine_sysper(void); unsigned long determine_pci_clock_per(void); + int ppc440spe_revB(void); # endif # else typedef PPC405_SYS_INFO sys_info_t; diff --git a/include/configs/TQM85xx.h b/include/configs/TQM85xx.h index 780f274..bc3b9aa 100644 --- a/include/configs/TQM85xx.h +++ b/include/configs/TQM85xx.h @@ -424,7 +424,7 @@ #define CONFIG_BOOTDELAY 5 /* -1 disables auto-boot */ #define CONFIG_PREBOOT "echo;" \ - "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo Type \\\"run flash_nfs\\\" to mount root filesystem over NFS;" \ "echo" #undef CONFIG_BOOTARGS /* the boot command will set bootargs */ @@ -449,7 +449,7 @@ "run nfsargs addip addcons;bootm\0" \ "rootpath=/opt/eldk/ppc_85xx\0" \ "kernel_addr=FE000000\0" \ - "ramdisk_addr=FE100000\0" \ + "ramdisk_addr=FE180000\0" \ "load=tftp 100000 /tftpboot/$hostname/u-boot.bin\0" \ "update=protect off fffc0000 ffffffff;era fffc0000 ffffffff;" \ "cp.b 100000 fffc0000 40000;" \ diff --git a/include/configs/yucca.h b/include/configs/yucca.h index f027d72..884f85c 100644 --- a/include/configs/yucca.h +++ b/include/configs/yucca.h @@ -63,17 +63,20 @@ #define CFG_PERIPHERAL_BASE 0xa0000000 /* internal peripherals */ #define CFG_ISRAM_BASE 0x90000000 /* internal SRAM */ -#define CFG_PCI_MEMBASE 0x80000000 /* mapped pci memory */ -#define CFG_PCI_MEMBASE1 0x90000000 /* mapped pci memory */ -#define CFG_PCI_MEMBASE2 0xa0000000 /* mapped pci memory */ -#define CFG_PCI_MEMBASE3 0xb0000000 /* mapped pci memory */ - +#define CFG_PCI_MEMBASE 0x80000000 /* mapped PCI memory */ #define CFG_PCI_BASE 0xd0000000 /* internal PCI regs */ -#define CFG_PCI_TARGBASE 0x80000000 /*PCIaddr mapped to CFG_PCI_MEMBASE*/ +#define CFG_PCI_TARGBASE CFG_PCI_MEMBASE + +#define CFG_PCIE_MEMBASE 0xb0000000 /* mapped PCIe memory */ +#define CFG_PCIE_MEMSIZE 0x01000000 +#define CFG_PCIE_BASE 0xe0000000 /* PCIe UTL regs */ -/* #define CFG_PCI_BASE_IO 0xB8000000 */ /* internal PCI I-O */ -/* #define CFG_PCI_BASE_REGS 0xBEC00000 */ /* internal PCI regs */ -/* #define CFG_PCI_BASE_CYCLE 0xBED00000 */ /* internal PCI regs */ +#define CFG_PCIE0_CFGBASE 0xc0000000 +#define CFG_PCIE0_XCFGBASE 0xc0000400 +#define CFG_PCIE1_CFGBASE 0xc0001000 +#define CFG_PCIE1_XCFGBASE 0xc0001400 +#define CFG_PCIE2_CFGBASE 0xc0002000 +#define CFG_PCIE2_XCFGBASE 0xc0002400 /* System RAM mapped to PCI space */ #define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE @@ -301,6 +304,7 @@ */ /* Support for Intel 82557/82559/82559ER chips. */ #define CONFIG_EEPRO100 + /* * For booting Linux, the board info and command line data * have to be in the first 8 MB of memory, since this is @@ -515,8 +519,8 @@ #define FPGA_REG1C_PE1_WAKE 0x0040 #define FPGA_REG1C_PE2_WAKE 0x0020 #define FPGA_REG1C_PE0_PERST 0x0010 -#define FPGA_REG1C_PE1_PERST 0x0080 -#define FPGA_REG1C_PE2_PERST 0x0040 +#define FPGA_REG1C_PE1_PERST 0x0008 +#define FPGA_REG1C_PE2_PERST 0x0004 /*----------------------------------------------------------------------------+ | Defines diff --git a/include/usb.h b/include/usb.h index 39d7f23..bf71554 100644 --- a/include/usb.h +++ b/include/usb.h @@ -108,6 +108,7 @@ struct usb_interface_descriptor { unsigned char iInterface; unsigned char no_of_ep; + unsigned char num_altsetting; unsigned char act_altsetting; struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; } __attribute__ ((packed)); |