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 | |
| 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>
| -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; |
