aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-06-26 11:12:50 -0400
committerNicolas Pitre <nico@cam.org>2008-06-30 16:04:44 -0400
commitda01bba3cb8814b17d809e09c301e1dad86fec87 (patch)
tree0605379dac7ae8b9de458b2d46230c839b319c34 /arch/arm
parent1338760329c586e0141831099e15f5c336dd9c1d (diff)
[ARM] Orion: make PCI handling code deal with Cardbus slots
The Cardbus connector does not have an IDSEL signal, and Cardbus cards are always the intended target of configuration transactions on their local PCI bus. This means that if the Orion's PCI bus signals are hooked up to a Cardbus slot, the same set of PCI functions will will appear 31 times, for each of the PCI device IDs 1-31 (ID 0 is the host bridge). This patch adds a function to the Orion PCI handling code that board support code can call to enable Cardbus mode. When Cardbus mode is enabled, configuration transactions on the PCI local bus are only allowed to PCI IDs 0 (host bridge) and 1 (cardbus device). Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-orion5x/common.h1
-rw-r--r--arch/arm/mach-orion5x/pci.c36
2 files changed, 30 insertions, 7 deletions
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 97db8d88f3db..f72cf0e77544 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -40,6 +40,7 @@ struct pci_bus;
40struct pci_sys_data; 40struct pci_sys_data;
41 41
42void orion5x_pcie_id(u32 *dev, u32 *rev); 42void orion5x_pcie_id(u32 *dev, u32 *rev);
43void orion5x_pci_set_cardbus_mode(void);
43int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); 44int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
44struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); 45struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
45int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); 46int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index 025ef63b1ddb..256a4f680935 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -266,6 +266,8 @@ static int __init pcie_setup(struct pci_sys_data *sys)
266 */ 266 */
267static DEFINE_SPINLOCK(orion5x_pci_lock); 267static DEFINE_SPINLOCK(orion5x_pci_lock);
268 268
269static int orion5x_pci_cardbus_mode;
270
269static int orion5x_pci_local_bus_nr(void) 271static int orion5x_pci_local_bus_nr(void)
270{ 272{
271 u32 conf = readl(PCI_P2P_CONF); 273 u32 conf = readl(PCI_P2P_CONF);
@@ -321,14 +323,30 @@ static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func,
321 return ret; 323 return ret;
322} 324}
323 325
326static int orion5x_pci_valid_config(int bus, u32 devfn)
327{
328 if (bus == orion5x_pci_local_bus_nr()) {
329 /*
330 * Don't go out for local device
331 */
332 if (PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
333 return 0;
334
335 /*
336 * When the PCI signals are directly connected to a
337 * Cardbus slot, ignore all but device IDs 0 and 1.
338 */
339 if (orion5x_pci_cardbus_mode && PCI_SLOT(devfn) > 1)
340 return 0;
341 }
342
343 return 1;
344}
345
324static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn, 346static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
325 int where, int size, u32 *val) 347 int where, int size, u32 *val)
326{ 348{
327 /* 349 if (!orion5x_pci_valid_config(bus->number, devfn)) {
328 * Don't go out for local device
329 */
330 if (bus->number == orion5x_pci_local_bus_nr() &&
331 PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) {
332 *val = 0xffffffff; 350 *val = 0xffffffff;
333 return PCIBIOS_DEVICE_NOT_FOUND; 351 return PCIBIOS_DEVICE_NOT_FOUND;
334 } 352 }
@@ -340,8 +358,7 @@ static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
340static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn, 358static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn,
341 int where, int size, u32 val) 359 int where, int size, u32 val)
342{ 360{
343 if (bus->number == orion5x_pci_local_bus_nr() && 361 if (!orion5x_pci_valid_config(bus->number, devfn))
344 PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
345 return PCIBIOS_DEVICE_NOT_FOUND; 362 return PCIBIOS_DEVICE_NOT_FOUND;
346 363
347 return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), 364 return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
@@ -524,6 +541,11 @@ static void __devinit rc_pci_fixup(struct pci_dev *dev)
524} 541}
525DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); 542DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
526 543
544void __init orion5x_pci_set_cardbus_mode(void)
545{
546 orion5x_pci_cardbus_mode = 1;
547}
548
527int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys) 549int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
528{ 550{
529 int ret = 0; 551 int ret = 0;