aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/drivers/pci
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-09-20 02:39:54 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-09-20 02:39:54 -0400
commit2c65d75ec4dde5e619a462e70cdd7b67e0e64bb8 (patch)
tree92bf4545d694888073a39c963b1d4f278785642c /arch/sh/drivers/pci
parentcabdf8bf488bfa3b565360b9fa1322d2db7747eb (diff)
sh: pci: Support root complex config accesses on SH7786 PCIe.
The SH7786 PCIe is presently unable to enumerate itself in root complex mode, and has no visibility through either type 0 or type 1 accesses, despite having a mostly sensible extended config space for each port. Attempts to generate type 0 or type 1 config cycles result in completer aborts, so we're ultimately forced to use SuperHyway transactions instead. As each port has a single port <-> device mapping that resolves for any PCI_SLOT definition, we simply hijack devfn 0 for the SuperHyway transaction and bump up the devfn limit. With enumeration of the root complex now possible, we also need to insert an early fixup to hide the BARs from the kernel. With all of that done, it's now possible to use the pcieport services with all of the PCIe ports, which is the first step to power management support. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/drivers/pci')
-rw-r--r--arch/sh/drivers/pci/ops-sh7786.c35
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c29
2 files changed, 55 insertions, 9 deletions
diff --git a/arch/sh/drivers/pci/ops-sh7786.c b/arch/sh/drivers/pci/ops-sh7786.c
index 4728199f71a6..01cb70fbd803 100644
--- a/arch/sh/drivers/pci/ops-sh7786.c
+++ b/arch/sh/drivers/pci/ops-sh7786.c
@@ -25,23 +25,49 @@ static int sh7786_pcie_config_access(unsigned char access_type,
25 struct pci_bus *bus, unsigned int devfn, int where, u32 *data) 25 struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
26{ 26{
27 struct pci_channel *chan = bus->sysdata; 27 struct pci_channel *chan = bus->sysdata;
28 int dev, func, type; 28 int dev, func, type, reg;
29 29
30 dev = PCI_SLOT(devfn); 30 dev = PCI_SLOT(devfn);
31 func = PCI_FUNC(devfn); 31 func = PCI_FUNC(devfn);
32 type = !!bus->parent; 32 type = !!bus->parent;
33 reg = where & ~3;
33 34
34 if (bus->number > 255 || dev > 31 || func > 7) 35 if (bus->number > 255 || dev > 31 || func > 7)
35 return PCIBIOS_FUNC_NOT_SUPPORTED; 36 return PCIBIOS_FUNC_NOT_SUPPORTED;
36 if (bus->parent == NULL && dev) 37
37 return PCIBIOS_DEVICE_NOT_FOUND; 38 /*
39 * While each channel has its own memory-mapped extended config
40 * space, it's generally only accessible when in endpoint mode.
41 * When in root complex mode, the controller is unable to target
42 * itself with either type 0 or type 1 accesses, and indeed, any
43 * controller initiated target transfer to its own config space
44 * result in a completer abort.
45 *
46 * Each channel effectively only supports a single device, but as
47 * the same channel <-> device access works for any PCI_SLOT()
48 * value, we cheat a bit here and bind the controller's config
49 * space to devfn 0 in order to enable self-enumeration. In this
50 * case the regular PAR/PDR path is sidelined and the mangled
51 * config access itself is initiated as a SuperHyway transaction.
52 */
53 if (pci_is_root_bus(bus)) {
54 if (dev == 0) {
55 if (access_type == PCI_ACCESS_READ)
56 *data = pci_read_reg(chan, PCI_REG(reg));
57 else
58 pci_write_reg(chan, *data, PCI_REG(reg));
59
60 return PCIBIOS_SUCCESSFUL;
61 } else if (dev > 1)
62 return PCIBIOS_DEVICE_NOT_FOUND;
63 }
38 64
39 /* Clear errors */ 65 /* Clear errors */
40 pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR); 66 pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
41 67
42 /* Set the PIO address */ 68 /* Set the PIO address */
43 pci_write_reg(chan, (bus->number << 24) | (dev << 19) | 69 pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
44 (func << 16) | (where & ~3), SH4A_PCIEPAR); 70 (func << 16) | reg, SH4A_PCIEPAR);
45 71
46 /* Enable the configuration access */ 72 /* Enable the configuration access */
47 pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR); 73 pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
@@ -49,6 +75,7 @@ static int sh7786_pcie_config_access(unsigned char access_type,
49 /* Check for errors */ 75 /* Check for errors */
50 if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10) 76 if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
51 return PCIBIOS_DEVICE_NOT_FOUND; 77 return PCIBIOS_DEVICE_NOT_FOUND;
78
52 /* Check for master and target aborts */ 79 /* Check for master and target aborts */
53 if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28))) 80 if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
54 return PCIBIOS_DEVICE_NOT_FOUND; 81 return PCIBIOS_DEVICE_NOT_FOUND;
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index 4e6cf8804979..3dfc250b897a 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -121,6 +121,24 @@ static struct pci_channel sh7786_pci_channels[] = {
121 DEFINE_CONTROLLER(0xfcc00000, 2), 121 DEFINE_CONTROLLER(0xfcc00000, 2),
122}; 122};
123 123
124static void __devinit sh7786_pci_fixup(struct pci_dev *dev)
125{
126 /*
127 * Prevent enumeration of root complex resources.
128 */
129 if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
130 int i;
131
132 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
133 dev->resource[i].start = 0;
134 dev->resource[i].end = 0;
135 dev->resource[i].flags = 0;
136 }
137 }
138}
139DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
140 sh7786_pci_fixup);
141
124static int phy_wait_for_ack(struct pci_channel *chan) 142static int phy_wait_for_ack(struct pci_channel *chan)
125{ 143{
126 unsigned int timeout = 100; 144 unsigned int timeout = 100;
@@ -229,11 +247,12 @@ static int pcie_init(struct sh7786_pcie_port *port)
229 /* Begin initialization */ 247 /* Begin initialization */
230 pcie_reset(port); 248 pcie_reset(port);
231 249
232 /* Initialize as type1. */ 250 /*
233 data = pci_read_reg(chan, SH4A_PCIEPCICONF3); 251 * Initial header for port config space is type 1, set the device
234 data &= ~(0x7f << 16); 252 * class to match. Hardware takes care of propagating the IDSETR
235 data |= PCI_HEADER_TYPE_BRIDGE << 16; 253 * settings, so there is no need to bother with a quirk.
236 pci_write_reg(chan, data, SH4A_PCIEPCICONF3); 254 */
255 pci_write_reg(chan, PCI_CLASS_BRIDGE_PCI << 16, SH4A_PCIEIDSETR1);
237 256
238 /* Initialize default capabilities. */ 257 /* Initialize default capabilities. */
239 data = pci_read_reg(chan, SH4A_PCIEEXPCAP0); 258 data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);