From 9ec165166850930dc3079bfa39f4c1397abd7337 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 7 Sep 2010 16:09:14 +0900 Subject: [PATCH 1/6] sh: Additional register definitions for SH7786 PCIe. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.h | 56 +++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/arch/sh/drivers/pci/pcie-sh7786.h b/arch/sh/drivers/pci/pcie-sh7786.h index 90a6992576b0..1ee054e47eae 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.h +++ b/arch/sh/drivers/pci/pcie-sh7786.h @@ -55,8 +55,11 @@ #define BITS_ERRRCV (0) /* 0 ERRRCV 0 */ #define MASK_ERRRCV (1< Date: Tue, 7 Sep 2010 16:11:04 +0900 Subject: [PATCH 2/6] sh: Make SH7786 PCIe port reset logic more aggressive. This attempts a more complete port reset, building on top of the existing approach. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 03e6d8217b0c..40b0ed042236 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -204,6 +204,16 @@ static int phy_init(struct pci_channel *chan) return -ETIMEDOUT; } +static void pcie_reset(struct sh7786_pcie_port *port) +{ + struct pci_channel *chan = port->hose; + + pci_write_reg(chan, 1, SH4A_PCIESRSTR); + pci_write_reg(chan, 0, SH4A_PCIETCTLR); + pci_write_reg(chan, 0, SH4A_PCIESRSTR); + pci_write_reg(chan, 0, SH4A_PCIETXVC0SR); +} + static int pcie_init(struct sh7786_pcie_port *port) { struct pci_channel *chan = port->hose; @@ -213,7 +223,7 @@ static int pcie_init(struct sh7786_pcie_port *port) int ret, i; /* Begin initialization */ - pci_write_reg(chan, 0, SH4A_PCIETCTLR); + pcie_reset(port); /* Initialize as type1. */ data = pci_read_reg(chan, SH4A_PCIEPCICONF3); From 2c5f674339d5e4c02cca7af13ec02bd9b5a96b60 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 7 Sep 2010 16:12:26 +0900 Subject: [PATCH 3/6] sh: Establish a SuperHyway<->PCIe window mapping on SH7786 PCIe. This bumps up the low address to match the physical memory windows for SHway<->PCIe transfers. The previous implementation was banking on a 1:1 virt<->phys SHway mapping, which doesn't apply here. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 40b0ed042236..4cd83140579b 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -354,8 +354,8 @@ static int pcie_init(struct sh7786_pcie_port *port) __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18, chan->reg_base + SH4A_PCIEPAMR(i)); + pci_write_reg(chan, res->start, SH4A_PCIEPARL(i)); pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i)); - pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL(i)); enable_mask = MASK_PARE; if (res->flags & IORESOURCE_IO) From da03a63ac843711887a85e5d90dd69399b1b9164 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 7 Sep 2010 17:03:10 +0900 Subject: [PATCH 4/6] sh: Ignore 32-bit windows in 29-bit mode for SH7786 PCIe. Certain memory windows are only available for 32-bit space, so skip over these in 29-bit mode. This will severely restrict the amount of memory that can be mapped, but since a boot loader bug makes booting in 29-bit mode close to impossible anyways, everything is ok. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 4cd83140579b..4f79fd9059e0 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -220,7 +220,7 @@ static int pcie_init(struct sh7786_pcie_port *port) unsigned int data; phys_addr_t memphys; size_t memsize; - int ret, i; + int ret, i, win; /* Begin initialization */ pcie_reset(port); @@ -337,13 +337,19 @@ static int pcie_init(struct sh7786_pcie_port *port) printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n", port->index, (data >> 20) & 0x3f); - - for (i = 0; i < chan->nr_resources; i++) { + for (i = win = 0; i < chan->nr_resources; i++) { struct resource *res = chan->resources + i; resource_size_t size; u32 enable_mask; - pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(i)); + /* + * We can't use the 32-bit mode windows in legacy 29-bit + * mode, so just skip them entirely. + */ + if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode()) + continue; + + pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(win)); size = resource_size(res); @@ -352,16 +358,18 @@ static int pcie_init(struct sh7786_pcie_port *port) * keeps things pretty simple. */ __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18, - chan->reg_base + SH4A_PCIEPAMR(i)); + chan->reg_base + SH4A_PCIEPAMR(win)); - pci_write_reg(chan, res->start, SH4A_PCIEPARL(i)); - pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i)); + pci_write_reg(chan, res->start, SH4A_PCIEPARL(win)); + pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(win)); enable_mask = MASK_PARE; if (res->flags & IORESOURCE_IO) enable_mask |= MASK_SPC; - pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(i)); + pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(win)); + + win++; } return 0; From f048519309dbaedd03807ddbb9fa22f5616cfd43 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 7 Sep 2010 17:05:08 +0900 Subject: [PATCH 5/6] sh: Properly wire up channel 2's I/O window on SH7786 PCIe. An IORESOURCE_IO was missing here, which meant that we weren't properly establishing the I/O window for this particular slot. With this corrected, cards with I/O BARs have them actually assigned and accessible. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 4f79fd9059e0..c1e862af9b63 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -82,6 +82,7 @@ static struct resource sh7786_pci2_resources[] = { .name = "PCIe2 IO", .start = 0xfc800000, .end = 0xfc800000 + SZ_4M - 1, + .flags = IORESOURCE_IO, }, { .name = "PCIe2 MEM 0", .start = 0x80000000, From 1c3bb3871af53a2a8620bc48b5535f6d83386773 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 7 Sep 2010 17:07:05 +0900 Subject: [PATCH 6/6] sh: Hook up 3rd memory window for all SH7786 PCIe channels. Now that the resource assignment issues are resolved, we can finally wire up the small third memory window -- in the future we may reclaim this for MSI. Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pcie-sh7786.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index c1e862af9b63..5acbaa2dc08e 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c @@ -51,6 +51,7 @@ static struct resource sh7786_pci0_resources[] = { .name = "PCIe0 MEM 2", .start = 0xfe100000, .end = 0xfe100000 + SZ_1M - 1, + .flags = IORESOURCE_MEM, }, }; @@ -74,6 +75,7 @@ static struct resource sh7786_pci1_resources[] = { .name = "PCIe1 MEM 2", .start = 0xfe300000, .end = 0xfe300000 + SZ_1M - 1, + .flags = IORESOURCE_MEM, }, }; @@ -97,6 +99,7 @@ static struct resource sh7786_pci2_resources[] = { .name = "PCIe2 MEM 2", .start = 0xfcd00000, .end = 0xfcd00000 + SZ_1M - 1, + .flags = IORESOURCE_MEM, }, };