[U-Boot] [PATCH 0/7] Some PCIe patches for MPC83xx

Hi all,
Here are some PCI-E fixes and a patch that adds PCI-E support for MPC837XERDB boards.
Thanks,

The SerDes initialization should be finished before negating the reset signal according to the reference manual. This isn't an issue on real hardware, but we'd better stick to the specifications anyway.
Suggested-by: Liu Dave DaveLiu@freescale.com Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- board/freescale/mpc837xemds/pci.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/board/freescale/mpc837xemds/pci.c b/board/freescale/mpc837xemds/pci.c index 31116b3..29de2e7 100644 --- a/board/freescale/mpc837xemds/pci.c +++ b/board/freescale/mpc837xemds/pci.c @@ -115,6 +115,13 @@ skip_pci: if (PARTID_NO_E(spridr) == SPR_8379) return;
+ if (pex2) + fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX_X2, + FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); + else + fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, + FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); + /* Configure the clock for PCIE controller */ clrsetbits_be32(&clk->sccr, SCCR_PCIEXP1CM | SCCR_PCIEXP2CM, SCCR_PCIEXP1CM_1 | SCCR_PCIEXP2CM_1); @@ -132,13 +139,6 @@ skip_pci: out_be32(&pcie_law[1].bar, CONFIG_SYS_PCIE2_BASE & LAWBAR_BAR); out_be32(&pcie_law[1].ar, LBLAWAR_EN | LBLAWAR_512MB);
- if (pex2) - fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX_X2, - FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); - else - fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, - FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); - mpc83xx_pcie_init(pex2 ? 1 : 2, pcie_reg, 0); }

This is just a handy routine that reports last PCI busno: we walk down all the hoses and return last hose's last_busno.
Will be used by PCI/PCIe initialization code.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- drivers/pci/pci.c | 13 +++++++++++++ include/pci.h | 2 ++ 2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index fffca49..d6d2d6e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -165,6 +165,19 @@ struct pci_controller *pci_bus_to_hose (int bus) return NULL; }
+int pci_last_busno(void) +{ + struct pci_controller *hose = hose_head; + + if (!hose) + return -1; + + while (hose->next) + hose = hose->next; + + return hose->last_busno; +} + #ifndef CONFIG_IXP425 pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) { diff --git a/include/pci.h b/include/pci.h index d0594e3..aaa4554 100644 --- a/include/pci.h +++ b/include/pci.h @@ -535,6 +535,8 @@ extern int pci_hose_config_device(struct pci_controller *hose, pci_addr_t mem, unsigned long command);
+int pci_last_busno(void); + #ifdef CONFIG_MPC824X extern void pci_mpc824x_init (struct pci_controller *hose); #endif

Currently we assign first_busno = 0 for the first PCIe hose, but this scheme won't work if we have ordinary PCI hose already registered (its first_busno value is 0 too).
The old code worked fine only because we have PCI disabled on MPC837XEMDS boards in stand-alone mode (see commit 00f7bbae92e3b13f2b3 "mpc83xx: fix PCI scan hang on the standalone MPC837xE-MDS boards"). But on MPC837XERDB boards we have PCI and PCIe, so the bug actually triggers.
So, to fix the issue, we should use pci_last_busno() + 1 for the first_busno (i.e. last available busno).
Reported-by: Huang Changming Chang-Ming.Huang@freescale.com Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- cpu/mpc83xx/pcie.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/cpu/mpc83xx/pcie.c b/cpu/mpc83xx/pcie.c index 12b5f69..1a3b2be 100644 --- a/cpu/mpc83xx/pcie.c +++ b/cpu/mpc83xx/pcie.c @@ -86,7 +86,6 @@ static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg, { extern void disable_addr_trans(void); /* start.S */ static struct pci_controller pcie_hose[PCIE_MAX_BUSES]; - static int max_bus; struct pci_controller *hose = &pcie_hose[bus]; int i;
@@ -117,7 +116,7 @@ static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg, hose->regions[i].size = 0x100000; hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
- hose->first_busno = max_bus; + hose->first_busno = pci_last_busno() + 1; hose->last_busno = 0xff;
if (bus == 0) @@ -145,7 +144,6 @@ static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg, * Hose scan. */ hose->last_busno = pci_hose_scan(hose); - max_bus = hose->last_busno + 1; }
#else

This patch fixes an issue in config space read accessors: we should fill-in the value even if we fail (e.g. skipping devices), otherwise CONFIG_PCI_SCAN_SHOW reports bogus values during boot up.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- cpu/mpc83xx/pcie.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/cpu/mpc83xx/pcie.c b/cpu/mpc83xx/pcie.c index 1a3b2be..77f8906 100644 --- a/cpu/mpc83xx/pcie.c +++ b/cpu/mpc83xx/pcie.c @@ -60,6 +60,9 @@ static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev) #define cfg_write(val, addr, type, op) \ do { op((type *)(addr), (val)); } while (0)
+#define cfg_read_err(val) do { *val = -1; } while (0) +#define cfg_write_err(val) do { } while (0) + #define PCIE_OP(rw, size, type, op) \ static int pcie_##rw##_config_##size(struct pci_controller *hose, \ pci_dev_t dev, int offset, \ @@ -68,8 +71,10 @@ static int pcie_##rw##_config_##size(struct pci_controller *hose, \ int ret; \ \ ret = mpc83xx_pcie_remap_cfg(hose, dev); \ - if (ret) \ - return ret; \ + if (ret) { \ + cfg_##rw##_err(val); \ + return ret; \ + } \ cfg_##rw(val, (void *)hose->cfg_addr + offset, type, op); \ return 0; \ }

This patch fixes copy-paste issue: pci_hose[0]'s first and last busnos were used to fixup pci1's nodes.
We don't see this bug triggering only because Linux reenumerate buses anyway.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- cpu/mpc83xx/pci.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index 5fe8964..8f5017c 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -227,8 +227,8 @@ void ft_pci_setup(void *blob, bd_t *bd)
path = fdt_getprop(blob, nodeoffset, "pci1", NULL); if (path) { - tmp[0] = cpu_to_be32(pci_hose[0].first_busno); - tmp[1] = cpu_to_be32(pci_hose[0].last_busno); + tmp[0] = cpu_to_be32(pci_hose[1].first_busno); + tmp[1] = cpu_to_be32(pci_hose[1].last_busno); do_fixup_by_path(blob, path, "bus-range", &tmp, sizeof(tmp), 1);

We should use pci_last_busno() in pci_init_bus(), otherwise we'll erroneously re-use PCI0's first_busno for PCI1 hoses.
NOTE: The patch is untested. All MPC83xx FSL boards I have have PCI1 in miniPCI form, for which I don't have any cards handy.
But looking in cpu/mpc85xx/pci.c: ... #ifdef CONFIG_MPC85XX_PCI2 hose = &pci_hose[1];
hose->first_busno = pci_hose[0].last_busno + 1;
And considering that we do the same for MPC83xx PCI-E support, I think this patch is correct.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- cpu/mpc83xx/pci.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index 8f5017c..a42b230 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -91,7 +91,7 @@ static void pci_init_bus(int bus, struct pci_region *reg) hose->regions[i].size = gd->ram_size; hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
- hose->first_busno = 0; + hose->first_busno = pci_last_busno() + 1; hose->last_busno = 0xff;
pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80,

On MPC8377E-RDB and MPC8378E-RDB boards we have PCIe and mini-PCIe slots. Let's support them.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- board/freescale/mpc837xerdb/pci.c | 57 +++++++++++++++++++++++++++++++++++++ include/configs/MPC837XERDB.h | 21 +++++++++++++ 2 files changed, 78 insertions(+), 0 deletions(-)
diff --git a/board/freescale/mpc837xerdb/pci.c b/board/freescale/mpc837xerdb/pci.c index 8bb31fc..83e89cf 100644 --- a/board/freescale/mpc837xerdb/pci.c +++ b/board/freescale/mpc837xerdb/pci.c @@ -13,6 +13,7 @@ #include <common.h> #include <mpc83xx.h> #include <pci.h> +#include <asm/io.h>
#if defined(CONFIG_PCI) static struct pci_region pci_regions[] = { @@ -36,12 +37,46 @@ static struct pci_region pci_regions[] = { } };
+static struct pci_region pcie_regions_0[] = { + { + .bus_start = CONFIG_SYS_PCIE1_MEM_BASE, + .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS, + .size = CONFIG_SYS_PCIE1_MEM_SIZE, + .flags = PCI_REGION_MEM, + }, + { + .bus_start = CONFIG_SYS_PCIE1_IO_BASE, + .phys_start = CONFIG_SYS_PCIE1_IO_PHYS, + .size = CONFIG_SYS_PCIE1_IO_SIZE, + .flags = PCI_REGION_IO, + }, +}; + +static struct pci_region pcie_regions_1[] = { + { + .bus_start = CONFIG_SYS_PCIE2_MEM_BASE, + .phys_start = CONFIG_SYS_PCIE2_MEM_PHYS, + .size = CONFIG_SYS_PCIE2_MEM_SIZE, + .flags = PCI_REGION_MEM, + }, + { + .bus_start = CONFIG_SYS_PCIE2_IO_BASE, + .phys_start = CONFIG_SYS_PCIE2_IO_PHYS, + .size = CONFIG_SYS_PCIE2_IO_SIZE, + .flags = PCI_REGION_IO, + }, +}; + void pci_init_board(void) { volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR; + volatile sysconf83xx_t *sysconf = &immr->sysconf; volatile clk83xx_t *clk = (volatile clk83xx_t *)&immr->clk; volatile law83xx_t *pci_law = immr->sysconf.pcilaw; + volatile law83xx_t *pcie_law = sysconf->pcielaw; struct pci_region *reg[] = { pci_regions }; + struct pci_region *pcie_reg[] = { pcie_regions_0, pcie_regions_1, }; + u32 spridr = in_be32(&immr->sysconf.spridr);
/* Enable all 5 PCI_CLK_OUTPUTS */ clk->occr |= 0xf8000000; @@ -55,5 +90,27 @@ void pci_init_board(void) pci_law[1].ar = LBLAWAR_EN | LBLAWAR_1MB;
mpc83xx_pci_init(1, reg, 0); + + /* There is no PEX in MPC8379 parts. */ + if (PARTID_NO_E(spridr) == SPR_8379) + return; + + /* Configure the clock for PCIE controller */ + clrsetbits_be32(&clk->sccr, SCCR_PCIEXP1CM | SCCR_PCIEXP2CM, + SCCR_PCIEXP1CM_1 | SCCR_PCIEXP2CM_1); + + /* Deassert the resets in the control register */ + out_be32(&sysconf->pecr1, 0xE0008000); + out_be32(&sysconf->pecr2, 0xE0008000); + udelay(2000); + + /* Configure PCI Express Local Access Windows */ + out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR); + out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB); + + out_be32(&pcie_law[1].bar, CONFIG_SYS_PCIE2_BASE & LAWBAR_BAR); + out_be32(&pcie_law[1].ar, LBLAWAR_EN | LBLAWAR_512MB); + + mpc83xx_pcie_init(2, pcie_reg, 0); } #endif /* CONFIG_PCI */ diff --git a/include/configs/MPC837XERDB.h b/include/configs/MPC837XERDB.h index 2e31dd0..8d0c93b 100644 --- a/include/configs/MPC837XERDB.h +++ b/include/configs/MPC837XERDB.h @@ -49,6 +49,7 @@ #else #define CONFIG_83XX_CLKIN 66666667 /* in Hz */ #define CONFIG_83XX_GENERIC_PCI 1 +#define CONFIG_83XX_GENERIC_PCIE 1 #endif
#ifndef CONFIG_SYS_CLK_FREQ @@ -375,6 +376,26 @@ #define CONFIG_SYS_PCI_SLV_MEM_BUS 0x00000000 #define CONFIG_SYS_PCI_SLV_MEM_SIZE 0x80000000
+#define CONFIG_SYS_PCIE1_BASE 0xA0000000 +#define CONFIG_SYS_PCIE1_CFG_BASE 0xA0000000 +#define CONFIG_SYS_PCIE1_CFG_SIZE 0x08000000 +#define CONFIG_SYS_PCIE1_MEM_BASE 0xA8000000 +#define CONFIG_SYS_PCIE1_MEM_PHYS 0xA8000000 +#define CONFIG_SYS_PCIE1_MEM_SIZE 0x10000000 +#define CONFIG_SYS_PCIE1_IO_BASE 0x00000000 +#define CONFIG_SYS_PCIE1_IO_PHYS 0xB8000000 +#define CONFIG_SYS_PCIE1_IO_SIZE 0x00800000 + +#define CONFIG_SYS_PCIE2_BASE 0xC0000000 +#define CONFIG_SYS_PCIE2_CFG_BASE 0xC0000000 +#define CONFIG_SYS_PCIE2_CFG_SIZE 0x08000000 +#define CONFIG_SYS_PCIE2_MEM_BASE 0xC8000000 +#define CONFIG_SYS_PCIE2_MEM_PHYS 0xC8000000 +#define CONFIG_SYS_PCIE2_MEM_SIZE 0x10000000 +#define CONFIG_SYS_PCIE2_IO_BASE 0x00000000 +#define CONFIG_SYS_PCIE2_IO_PHYS 0xD8000000 +#define CONFIG_SYS_PCIE2_IO_SIZE 0x00800000 + #ifdef CONFIG_PCI #define CONFIG_NET_MULTI #define CONFIG_PCI_PNP /* do pci plug-and-play */

On Thu, 19 Feb 2009 18:19:43 +0300 Anton Vorontsov avorontsov@ru.mvista.com wrote:
Hi all,
Here are some PCI-E fixes and a patch that adds PCI-E support for MPC837XERDB boards.
applied 1-7.
Thanks Anton.
Kim
participants (2)
-
Anton Vorontsov
-
Kim Phillips