diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2008-03-27 14:51:41 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@marvell.com> | 2008-03-27 14:51:41 -0400 |
commit | d50c60a87a95a42f1bc984150d3eebc77a0b0c14 (patch) | |
tree | e6ad641c497fb150aaf2ffa0f8fa6e4604f64aaf /arch/arm | |
parent | a99842704a031ac23d4f7344e412a44bb3beb3b3 (diff) |
Orion: enable access to local config space
This patch enables access to the local PCIe/PCI configuration
space, and is necessary for such things as PCI Advanced Error
Recovery to work.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Reviewed-by: Tzachi Perelstein <tzachi@marvell.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-orion/pci.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c index 18cdf3b505a5..e3aab14b943c 100644 --- a/arch/arm/mach-orion/pci.c +++ b/arch/arm/mach-orion/pci.c | |||
@@ -50,15 +50,18 @@ static int pcie_valid_config(int bus, int dev) | |||
50 | { | 50 | { |
51 | /* | 51 | /* |
52 | * Don't go out when trying to access -- | 52 | * Don't go out when trying to access -- |
53 | * 1. our own device / nonexisting device on local bus | 53 | * 1. nonexisting device on local bus |
54 | * 2. where there's no device connected (no link) | 54 | * 2. where there's no device connected (no link) |
55 | */ | 55 | */ |
56 | if (bus == 0 && dev != 1) | 56 | if (bus == 0 && dev == 0) |
57 | return 0; | 57 | return 1; |
58 | 58 | ||
59 | if (!orion_pcie_link_up(PCIE_BASE)) | 59 | if (!orion_pcie_link_up(PCIE_BASE)) |
60 | return 0; | 60 | return 0; |
61 | 61 | ||
62 | if (bus == 0 && dev != 1) | ||
63 | return 0; | ||
64 | |||
62 | return 1; | 65 | return 1; |
63 | } | 66 | } |
64 | 67 | ||
@@ -272,12 +275,6 @@ int orion_pci_local_bus_nr(void) | |||
272 | return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); | 275 | return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); |
273 | } | 276 | } |
274 | 277 | ||
275 | static int orion_pci_local_dev_nr(void) | ||
276 | { | ||
277 | u32 conf = orion_read(PCI_P2P_CONF); | ||
278 | return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS); | ||
279 | } | ||
280 | |||
281 | static int orion_pci_hw_rd_conf(int bus, int dev, u32 func, | 278 | static int orion_pci_hw_rd_conf(int bus, int dev, u32 func, |
282 | u32 where, u32 size, u32 *val) | 279 | u32 where, u32 size, u32 *val) |
283 | { | 280 | { |
@@ -333,8 +330,8 @@ static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn, | |||
333 | /* | 330 | /* |
334 | * Don't go out for local device | 331 | * Don't go out for local device |
335 | */ | 332 | */ |
336 | if ((orion_pci_local_bus_nr() == bus->number) && | 333 | if (bus->number == orion_pci_local_bus_nr() && |
337 | (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) { | 334 | PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) { |
338 | *val = 0xffffffff; | 335 | *val = 0xffffffff; |
339 | return PCIBIOS_DEVICE_NOT_FOUND; | 336 | return PCIBIOS_DEVICE_NOT_FOUND; |
340 | } | 337 | } |
@@ -346,11 +343,8 @@ static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn, | |||
346 | static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn, | 343 | static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn, |
347 | int where, int size, u32 val) | 344 | int where, int size, u32 val) |
348 | { | 345 | { |
349 | /* | 346 | if (bus->number == orion_pci_local_bus_nr() && |
350 | * Don't go out for local device | 347 | PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) |
351 | */ | ||
352 | if ((orion_pci_local_bus_nr() == bus->number) && | ||
353 | (orion_pci_local_dev_nr() == PCI_SLOT(devfn))) | ||
354 | return PCIBIOS_DEVICE_NOT_FOUND; | 348 | return PCIBIOS_DEVICE_NOT_FOUND; |
355 | 349 | ||
356 | return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), | 350 | return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), |
@@ -389,23 +383,21 @@ static void __init orion_pci_set_bus_nr(int nr) | |||
389 | 383 | ||
390 | static void __init orion_pci_master_slave_enable(void) | 384 | static void __init orion_pci_master_slave_enable(void) |
391 | { | 385 | { |
392 | int bus_nr, dev_nr, func, reg; | 386 | int bus_nr, func, reg; |
393 | u32 val; | 387 | u32 val; |
394 | 388 | ||
395 | bus_nr = orion_pci_local_bus_nr(); | 389 | bus_nr = orion_pci_local_bus_nr(); |
396 | dev_nr = orion_pci_local_dev_nr(); | ||
397 | func = PCI_CONF_FUNC_STAT_CMD; | 390 | func = PCI_CONF_FUNC_STAT_CMD; |
398 | reg = PCI_CONF_REG_STAT_CMD; | 391 | reg = PCI_CONF_REG_STAT_CMD; |
399 | orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val); | 392 | orion_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val); |
400 | val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | 393 | val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); |
401 | orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); | 394 | orion_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7); |
402 | } | 395 | } |
403 | 396 | ||
404 | static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram) | 397 | static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram) |
405 | { | 398 | { |
406 | u32 win_enable; | 399 | u32 win_enable; |
407 | int bus; | 400 | int bus; |
408 | int dev; | ||
409 | int i; | 401 | int i; |
410 | 402 | ||
411 | /* | 403 | /* |
@@ -418,7 +410,6 @@ static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram) | |||
418 | * Setup windows for DDR banks. | 410 | * Setup windows for DDR banks. |
419 | */ | 411 | */ |
420 | bus = orion_pci_local_bus_nr(); | 412 | bus = orion_pci_local_bus_nr(); |
421 | dev = orion_pci_local_dev_nr(); | ||
422 | 413 | ||
423 | for (i = 0; i < dram->num_cs; i++) { | 414 | for (i = 0; i < dram->num_cs; i++) { |
424 | struct mbus_dram_window *cs = dram->cs + i; | 415 | struct mbus_dram_window *cs = dram->cs + i; |
@@ -430,15 +421,15 @@ static void __init orion_setup_pci_wins(struct mbus_dram_target_info *dram) | |||
430 | * Write DRAM bank base address register. | 421 | * Write DRAM bank base address register. |
431 | */ | 422 | */ |
432 | reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index); | 423 | reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index); |
433 | orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val); | 424 | orion_pci_hw_rd_conf(bus, 0, func, reg, 4, &val); |
434 | val = (cs->base & 0xfffff000) | (val & 0xfff); | 425 | val = (cs->base & 0xfffff000) | (val & 0xfff); |
435 | orion_pci_hw_wr_conf(bus, dev, func, reg, 4, val); | 426 | orion_pci_hw_wr_conf(bus, 0, func, reg, 4, val); |
436 | 427 | ||
437 | /* | 428 | /* |
438 | * Write DRAM bank size register. | 429 | * Write DRAM bank size register. |
439 | */ | 430 | */ |
440 | reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index); | 431 | reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index); |
441 | orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0); | 432 | orion_pci_hw_wr_conf(bus, 0, func, reg, 4, 0); |
442 | orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index), | 433 | orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index), |
443 | (cs->size - 1) & 0xfffff000); | 434 | (cs->size - 1) & 0xfffff000); |
444 | orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index), | 435 | orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index), |
@@ -519,6 +510,23 @@ static int __init pci_setup(struct pci_sys_data *sys) | |||
519 | /***************************************************************************** | 510 | /***************************************************************************** |
520 | * General PCIE + PCI | 511 | * General PCIE + PCI |
521 | ****************************************************************************/ | 512 | ****************************************************************************/ |
513 | static void __devinit rc_pci_fixup(struct pci_dev *dev) | ||
514 | { | ||
515 | /* | ||
516 | * Prevent enumeration of root complex. | ||
517 | */ | ||
518 | if (dev->bus->parent == NULL && dev->devfn == 0) { | ||
519 | int i; | ||
520 | |||
521 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
522 | dev->resource[i].start = 0; | ||
523 | dev->resource[i].end = 0; | ||
524 | dev->resource[i].flags = 0; | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); | ||
529 | |||
522 | int __init orion_pci_sys_setup(int nr, struct pci_sys_data *sys) | 530 | int __init orion_pci_sys_setup(int nr, struct pci_sys_data *sys) |
523 | { | 531 | { |
524 | int ret = 0; | 532 | int ret = 0; |