diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/mpc86xx/Makefile | 4 | ||||
-rw-r--r-- | cpu/mpc86xx/pci.c | 192 | ||||
-rw-r--r-- | cpu/mpc86xx/pcie_indirect.c | 198 |
3 files changed, 284 insertions, 110 deletions
diff --git a/cpu/mpc86xx/Makefile b/cpu/mpc86xx/Makefile index ab6255a..7995945 100644 --- a/cpu/mpc86xx/Makefile +++ b/cpu/mpc86xx/Makefile @@ -28,9 +28,9 @@ include $(TOPDIR)/config.mk LIB = lib$(CPU).a START = start.o #resetvec.o -ASOBJS = cache.o +ASOBJS = cache.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o \ - pci.o i2c.o spd_sdram.o + pci.o pcie_indirect.o i2c.o spd_sdram.o OBJS = $(COBJS) all: .depend $(START) $(ASOBJS) $(LIB) diff --git a/cpu/mpc86xx/pci.c b/cpu/mpc86xx/pci.c index 05976bd..deb66aa 100644 --- a/cpu/mpc86xx/pci.c +++ b/cpu/mpc86xx/pci.c @@ -1,6 +1,9 @@ /* - * Copyright 2005 Freescale Semiconductor. + * Copyright (C) Freescale Semiconductor,Inc. + * 2005, 2006. All rights reserved. + * * Ed Swarthout (ed.swarthout@freescale.com) + * Jason Jin (Jason.jin@freescale.com) * * See file CREDITS for list of people who contributed to this * project. @@ -22,142 +25,115 @@ */ /* - * PEX Configuration space access support for PEX Bridge + * PCIE Configuration space access support for PCIE Bridge */ #include <common.h> #include <pci.h> - #if defined(CONFIG_PCI) - void pci_mpc86xx_init(struct pci_controller *hose) { volatile immap_t *immap = (immap_t *)CFG_CCSRBAR; - volatile ccsr_pex_t *pex1 = &immap->im_pex1; + volatile ccsr_pex_t *pcie1 = &immap->im_pex1; + u16 temp16; + u32 temp32; + volatile ccsr_gur_t *gur = &immap->im_gur; uint host1_agent = (gur->porbmsr & MPC86xx_PORBMSR_HA) >> 17; - uint pex1_host = (host1_agent == 2) || (host1_agent == 3); - - u16 reg16, reg16_1, reg16_2, reg16_3; - u32 reg32, i; - - ulong addr, data; - - uint pex1_agent = (host1_agent == 0) || (host1_agent == 1); - uint devdisr = gur->devdisr; - uint io_sel = (gur->pordevsr & MPC86xx_PORDEVSR_IO_SEL) >> 16; - - if ((io_sel==2 || io_sel==3 || io_sel==5 - || io_sel==6 || io_sel==7 || io_sel==0xF ) - && !(devdisr & MPC86xx_DEVDISR_PCIEX1)){ - printf ("PCI-EXPRESS 1: Configured as %s \n", - pex1_agent ? "Agent" : "Host"); - printf (" Scanning PCI bus"); - debug("0x%08x=0x%08x ", &pex1->pme_msg_det,pex1->pme_msg_det); - if (pex1->pme_msg_det) { - pex1->pme_msg_det = 0xffffffff; - debug (" with errors. Clearing. Now 0x%08x", - pex1->pme_msg_det); - } - debug ("\n"); - } - - hose->first_busno = 0; - hose->last_busno = 0x7f; - - pci_set_region(hose->regions + 0, - CFG_PCI1_MEM_BASE, - CFG_PCI1_MEM_PHYS, - CFG_PCI1_MEM_SIZE, - PCI_REGION_MEM); - - pci_set_region(hose->regions + 1, - CFG_PCI1_IO_BASE, - CFG_PCI1_IO_PHYS, - CFG_PCI1_IO_SIZE, - PCI_REGION_IO); + uint pcie1_host = (host1_agent == 2) || (host1_agent == 3); + uint pcie1_agent = (host1_agent == 0) || (host1_agent == 1); + uint devdisr = gur->devdisr; + uint io_sel = (gur->pordevsr & MPC86xx_PORDEVSR_IO_SEL) >> 16; + + if ((io_sel ==2 || io_sel == 3 || io_sel == 5 || io_sel == 6 || + io_sel == 7 || io_sel == 0xf) && !(devdisr & MPC86xx_DEVDISR_PCIEX1)){ + printf ("PCI-EXPRESS 1: Configured as %s \n", + pcie1_agent ? "Agent" : "Host"); + if(pcie1_agent) return; /*Don't scan bus when configured as agent*/ + printf (" Scanning PCIE bus"); + debug("0x%08x=0x%08x ", &pcie1->pme_msg_det,pcie1->pme_msg_det); + if (pcie1->pme_msg_det) { + pcie1->pme_msg_det = 0xffffffff; + debug (" with errors. Clearing. Now 0x%08x", + pcie1->pme_msg_det); + } + debug ("\n"); + } + else{ + printf("PCI-EXPRESS 1 disabled!\n"); + return; + } - hose->region_count = 2; + /*set first_bus=0 only skipped B0:D0:F0 which is + * a reserved device in M1575, but make it easy for + * most of the scan process. + */ + hose->first_busno = 0x00; + hose->last_busno = 0xfe; - pci_setup_indirect(hose, + pcie_setup_indirect(hose, (CFG_IMMR+0x8000), (CFG_IMMR+0x8004)); - /* - * Hose scan. - */ - pci_register_hose(hose); + pci_hose_read_config_word(hose, PCI_BDF(0,0,0), PCI_COMMAND, &temp16); + temp16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + pci_hose_write_config_word(hose, PCI_BDF(0,0,0), PCI_COMMAND, temp16); - pci_read_config_word (PCI_BDF(0,0,0), PCI_VENDOR_ID, ®16); - debug("pex_mpc86xx_init: read %2x %4x\n",PCI_VENDOR_ID, reg16); - pci_read_config_word (PCI_BDF(0,0,0), PCI_DEVICE_ID, ®16); - debug("pex_mpc86xx_init: read %2x %4x\n",PCI_DEVICE_ID, reg16); + pci_hose_write_config_word(hose,PCI_BDF(0,0,0), PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, PCI_BDF(0,0,0), PCI_LATENCY_TIMER, 0x80); - pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16); - reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY \ - | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; - pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16); + pci_hose_read_config_dword(hose, PCI_BDF(0,0,0), PCI_PRIMARY_BUS, &temp32); + temp32 = (temp32 & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + pci_hose_write_config_dword(hose, PCI_BDF(0,0,0), PCI_PRIMARY_BUS, temp32); - pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16); - debug("pex_mpc86xx_init: read %2x %4x\n",PCI_COMMAND, reg16); + pcie1->powar1 = 0; + pcie1->powar2 = 0; + pcie1->piwar1 = 0; + pcie1->piwar1 = 0; - /* - * Clear non-reserved bits in status register. - */ - /* - * pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff); - * pci_write_config_byte(PCI_BDF(0,0,0), PCI_LATENCY_TIMER,0x80); - */ + pcie1->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff; + pcie1->powar1 = 0x8004401c; /* 512M MEM space */ + pcie1->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff; + pcie1->potear1 = 0x00000000; - pex1->powbar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff; - pex1->powar1 = 0x8004401c; /* 512M MEM space */ - pex1->potar1 = (CFG_PCI1_MEM_BASE >> 12) & 0x000fffff; - pex1->potear1 = 0x00000000; - - pex1->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff; - pex1->powar2 = 0x80088017; /* 16M IO space */ - pex1->potar2 = 0x00000000; - pex1->potear2 = 0x00000000; - - if (!pex1->piwar1) { - pex1->pitar1 = 0x00000000; - pex1->piwbar1 = (0x80000000 >> 12 ) & 0x000fffff; - pex1->piwar1 = 0xa0f5501e; /* Enable, Prefetch, Local Mem, - * Snoop R/W, 2G */ - } + pcie1->powbar2 = (CFG_PCI1_IO_BASE >> 12) & 0x000fffff; + pcie1->powar2 = 0x80088017; /* 16M IO space */ + pcie1->potar2 = 0x00000000; + pcie1->potear2 = 0x00000000; - pex1->pitar2 = 0x00000000; - pex1->piwbar2 = (0xe2000000 >> 12 ) & 0x000fffff; - pex1->piwar2 = 0xa0f5501e; /* Enable, Prefetch, Local Mem, - * Snoop R/W, 2G */ + pcie1->pitar1 = 0x00000000; + pcie1->piwbar1 = 0x00000000; + /* Enable, Prefetch, Local Mem, * Snoop R/W, 2G */ + pcie1->piwar1 = 0xa0f5501e; - *(u32 *)(0xf8008000)= 0x80000000; - debug("Received data for addr 0x%08lx is 0x%08lx\n", - *(u32*)(0xf8008000), *(u32*)(0xf8008004)); + pci_set_region(hose->regions + 0, + CFG_PCI_MEMORY_BUS, + CFG_PCI_MEMORY_PHYS, + CFG_PCI_MEMORY_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); - pci_write_config_byte(PCI_BDF(0,0,0), PCI_PRIMARY_BUS,0x20); - pci_write_config_byte(PCI_BDF(0,0,0), PCI_SECONDARY_BUS,0x00); - pci_write_config_byte(PCI_BDF(0,0,0), PCI_SUBORDINATE_BUS,0x1F); + pci_set_region(hose->regions + 1, + CFG_PCI1_MEM_BASE, + CFG_PCI1_MEM_PHYS, + CFG_PCI1_MEM_SIZE, + PCI_REGION_MEM); - *(u32 *)(0xf8008000)= 0x80200000; - debug("Received data for addr 0x%08lx is 0x%08lx\n", - *(u32*)(0xf8008000), *(u32*)(0xf8008004)); + pci_set_region(hose->regions + 2, + CFG_PCI1_IO_BASE, + CFG_PCI1_IO_PHYS, + CFG_PCI1_IO_SIZE, + PCI_REGION_IO); - *(u32 *)(0xf8008000)= 0x80200000; - debug("Received data for addr 0x%08lx is 0x%08lx\n", - *(u32*)(0xf8008000), *(u32*)(0xf8008004)); + hose->region_count = 3; - *(u32 *)(0xf8008000)= 0x80200000; - debug("Received data for addr 0x%08lx is 0x%08lx\n", - *(u32*)(0xf8008000), *(u32*)(0xf8008004)); + pci_register_hose(hose); hose->last_busno = pci_hose_scan(hose); - hose->last_busno = 0x21; - debug("pex_mpc86xx_init: last_busno %x\n",hose->last_busno); - debug("pex_mpc86xx init: current_busno %x\n ",hose->current_busno); + debug("pcie_mpc86xx_init: last_busno %x\n",hose->last_busno); + debug("pcie_mpc86xx init: current_busno %x\n ",hose->current_busno); - printf("....PCI scan & enumeration done\n"); + printf("....PCIE1 scan & enumeration done\n"); } - #endif /* CONFIG_PCI */ diff --git a/cpu/mpc86xx/pcie_indirect.c b/cpu/mpc86xx/pcie_indirect.c new file mode 100644 index 0000000..e3cb4be --- /dev/null +++ b/cpu/mpc86xx/pcie_indirect.c @@ -0,0 +1,198 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (c) Freescale Semiconductor, Inc. + * 2006. All rights reserved. + * + * Jason Jin <Jason.jin@freescale.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. + * + * partly derived from + * arch/powerpc/platforms/86xx/mpc86xx_pcie.c + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> + +#define PCI_CFG_OUT out_be32 +#define PEX_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + +static int +indirect_read_config_pcie(struct pci_controller *hose, + pci_dev_t dev, int offset, + int len,u32 *val) +{ + int bus = PCI_BUS(dev); + char devfn = ( (PCI_DEV(dev) << 4 ) | (PCI_FUNC(dev)) ) ; + + unsigned char *cfg_data; + u32 temp; + + PEX_FIX; + if( bus == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000001); + }else { + PCI_CFG_OUT(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); + } + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PEX_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + + return 0; +} + +static int +indirect_write_config_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + int len, + u32 val) +{ + int bus = PCI_BUS(dev); + char devfn = ( (PCI_DEV(dev) << 4 ) | (PCI_FUNC(dev)) ) ; + + unsigned char *cfg_data; + u32 temp; + + PEX_FIX; + if( bus == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000001); + }else { + PCI_CFG_OUT(hose->cfg_addr, dev | (offset & 0xfc) | 0x80000000); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PEX_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PEX_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PEX_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PEX_FIX; + out_le32(cfg_data, temp); + break; + default: + PEX_FIX; + out_le32(cfg_data, val); + break; + } + PEX_FIX; + return 0; +} + +static int +indirect_read_config_byte_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + u8 *val) +{ + u32 val32; + indirect_read_config_pcie(hose,dev,offset,1,&val32); + *val = (u8)val32; + return 0; +} + +static int +indirect_read_config_word_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + u16 *val) +{ + u32 val32; + indirect_read_config_pcie(hose,dev,offset,2,&val32); + *val = (u16)val32; + return 0; +} + +static int +indirect_read_config_dword_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + u32 *val) +{ + return indirect_read_config_pcie(hose,dev, offset,4,val); +} + +static int +indirect_write_config_byte_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + char val) +{ + return indirect_write_config_pcie(hose,dev, offset,1,(u32)val); +} + +static int +indirect_write_config_word_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + unsigned short val) +{ + return indirect_write_config_pcie(hose,dev, offset,2,(u32)val); +} + +static int +indirect_write_config_dword_pcie(struct pci_controller *hose, + pci_dev_t dev, + int offset, + unsigned short val) +{ + return indirect_write_config_pcie(hose,dev, offset,4,val); +} + +void +pcie_setup_indirect(struct pci_controller* hose, + u32 cfg_addr, + u32 cfg_data) +{ + pci_set_ops(hose, + indirect_read_config_byte_pcie, + indirect_read_config_word_pcie, + indirect_read_config_dword_pcie, + indirect_write_config_byte_pcie, + indirect_write_config_word_pcie, + indirect_write_config_dword_pcie); + + hose->cfg_addr = (unsigned int *) cfg_addr; + hose->cfg_data = (unsigned char *) cfg_data; +} + +#endif /* CONFIG_PCI */ |