diff options
Diffstat (limited to 'arch/arm/mach-orion5x/pci.c')
-rw-r--r-- | arch/arm/mach-orion5x/pci.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c index 9d5d39fa19c3..256a4f680935 100644 --- a/arch/arm/mach-orion5x/pci.c +++ b/arch/arm/mach-orion5x/pci.c | |||
@@ -152,6 +152,8 @@ static int __init pcie_setup(struct pci_sys_data *sys) | |||
152 | if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) { | 152 | if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) { |
153 | printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config " | 153 | printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config " |
154 | "read transaction workaround\n"); | 154 | "read transaction workaround\n"); |
155 | orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE, | ||
156 | ORION5X_PCIE_WA_SIZE); | ||
155 | pcie_ops.read = pcie_rd_conf_wa; | 157 | pcie_ops.read = pcie_rd_conf_wa; |
156 | } | 158 | } |
157 | 159 | ||
@@ -240,13 +242,13 @@ static int __init pcie_setup(struct pci_sys_data *sys) | |||
240 | * PCI Address Decode Windows registers | 242 | * PCI Address Decode Windows registers |
241 | */ | 243 | */ |
242 | #define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \ | 244 | #define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \ |
243 | ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \ | 245 | ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \ |
244 | ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \ | 246 | ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \ |
245 | ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0) | 247 | ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0) |
246 | #define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION5X_PCI_REG(0xc48) : \ | 248 | #define PCI_BAR_REMAP_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc48) : \ |
247 | ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \ | 249 | ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \ |
248 | ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \ | 250 | ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \ |
249 | ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0) | 251 | ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0) |
250 | #define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c) | 252 | #define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c) |
251 | #define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c) | 253 | #define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c) |
252 | 254 | ||
@@ -264,9 +266,11 @@ static int __init pcie_setup(struct pci_sys_data *sys) | |||
264 | */ | 266 | */ |
265 | static DEFINE_SPINLOCK(orion5x_pci_lock); | 267 | static DEFINE_SPINLOCK(orion5x_pci_lock); |
266 | 268 | ||
269 | static int orion5x_pci_cardbus_mode; | ||
270 | |||
267 | static int orion5x_pci_local_bus_nr(void) | 271 | static int orion5x_pci_local_bus_nr(void) |
268 | { | 272 | { |
269 | u32 conf = orion5x_read(PCI_P2P_CONF); | 273 | u32 conf = readl(PCI_P2P_CONF); |
270 | return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); | 274 | return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); |
271 | } | 275 | } |
272 | 276 | ||
@@ -276,11 +280,11 @@ static int orion5x_pci_hw_rd_conf(int bus, int dev, u32 func, | |||
276 | unsigned long flags; | 280 | unsigned long flags; |
277 | spin_lock_irqsave(&orion5x_pci_lock, flags); | 281 | spin_lock_irqsave(&orion5x_pci_lock, flags); |
278 | 282 | ||
279 | orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | | 283 | writel(PCI_CONF_BUS(bus) | |
280 | PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | | 284 | PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | |
281 | PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); | 285 | PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN, PCI_CONF_ADDR); |
282 | 286 | ||
283 | *val = orion5x_read(PCI_CONF_DATA); | 287 | *val = readl(PCI_CONF_DATA); |
284 | 288 | ||
285 | if (size == 1) | 289 | if (size == 1) |
286 | *val = (*val >> (8*(where & 0x3))) & 0xff; | 290 | *val = (*val >> (8*(where & 0x3))) & 0xff; |
@@ -300,9 +304,9 @@ static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func, | |||
300 | 304 | ||
301 | spin_lock_irqsave(&orion5x_pci_lock, flags); | 305 | spin_lock_irqsave(&orion5x_pci_lock, flags); |
302 | 306 | ||
303 | orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) | | 307 | writel(PCI_CONF_BUS(bus) | |
304 | PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | | 308 | PCI_CONF_DEV(dev) | PCI_CONF_REG(where) | |
305 | PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN); | 309 | PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN, PCI_CONF_ADDR); |
306 | 310 | ||
307 | if (size == 4) { | 311 | if (size == 4) { |
308 | __raw_writel(val, PCI_CONF_DATA); | 312 | __raw_writel(val, PCI_CONF_DATA); |
@@ -319,14 +323,30 @@ static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func, | |||
319 | return ret; | 323 | return ret; |
320 | } | 324 | } |
321 | 325 | ||
326 | static 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 | |||
322 | static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn, | 346 | static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn, |
323 | int where, int size, u32 *val) | 347 | int where, int size, u32 *val) |
324 | { | 348 | { |
325 | /* | 349 | if (!orion5x_pci_valid_config(bus->number, devfn)) { |
326 | * Don't go out for local device | ||
327 | */ | ||
328 | if (bus->number == orion5x_pci_local_bus_nr() && | ||
329 | PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) { | ||
330 | *val = 0xffffffff; | 350 | *val = 0xffffffff; |
331 | return PCIBIOS_DEVICE_NOT_FOUND; | 351 | return PCIBIOS_DEVICE_NOT_FOUND; |
332 | } | 352 | } |
@@ -338,8 +358,7 @@ static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn, | |||
338 | static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn, | 358 | static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn, |
339 | int where, int size, u32 val) | 359 | int where, int size, u32 val) |
340 | { | 360 | { |
341 | if (bus->number == orion5x_pci_local_bus_nr() && | 361 | if (!orion5x_pci_valid_config(bus->number, devfn)) |
342 | PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) | ||
343 | return PCIBIOS_DEVICE_NOT_FOUND; | 362 | return PCIBIOS_DEVICE_NOT_FOUND; |
344 | 363 | ||
345 | return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), | 364 | return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn), |
@@ -353,9 +372,9 @@ static struct pci_ops pci_ops = { | |||
353 | 372 | ||
354 | static void __init orion5x_pci_set_bus_nr(int nr) | 373 | static void __init orion5x_pci_set_bus_nr(int nr) |
355 | { | 374 | { |
356 | u32 p2p = orion5x_read(PCI_P2P_CONF); | 375 | u32 p2p = readl(PCI_P2P_CONF); |
357 | 376 | ||
358 | if (orion5x_read(PCI_MODE) & PCI_MODE_PCIX) { | 377 | if (readl(PCI_MODE) & PCI_MODE_PCIX) { |
359 | /* | 378 | /* |
360 | * PCI-X mode | 379 | * PCI-X mode |
361 | */ | 380 | */ |
@@ -372,7 +391,7 @@ static void __init orion5x_pci_set_bus_nr(int nr) | |||
372 | */ | 391 | */ |
373 | p2p &= ~PCI_P2P_BUS_MASK; | 392 | p2p &= ~PCI_P2P_BUS_MASK; |
374 | p2p |= (nr << PCI_P2P_BUS_OFFS); | 393 | p2p |= (nr << PCI_P2P_BUS_OFFS); |
375 | orion5x_write(PCI_P2P_CONF, p2p); | 394 | writel(p2p, PCI_P2P_CONF); |
376 | } | 395 | } |
377 | } | 396 | } |
378 | 397 | ||
@@ -399,7 +418,7 @@ static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram) | |||
399 | * First, disable windows. | 418 | * First, disable windows. |
400 | */ | 419 | */ |
401 | win_enable = 0xffffffff; | 420 | win_enable = 0xffffffff; |
402 | orion5x_write(PCI_BAR_ENABLE, win_enable); | 421 | writel(win_enable, PCI_BAR_ENABLE); |
403 | 422 | ||
404 | /* | 423 | /* |
405 | * Setup windows for DDR banks. | 424 | * Setup windows for DDR banks. |
@@ -425,10 +444,10 @@ static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram) | |||
425 | */ | 444 | */ |
426 | reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index); | 445 | reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index); |
427 | orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0); | 446 | orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0); |
428 | orion5x_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index), | 447 | writel((cs->size - 1) & 0xfffff000, |
429 | (cs->size - 1) & 0xfffff000); | 448 | PCI_BAR_SIZE_DDR_CS(cs->cs_index)); |
430 | orion5x_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index), | 449 | writel(cs->base & 0xfffff000, |
431 | cs->base & 0xfffff000); | 450 | PCI_BAR_REMAP_DDR_CS(cs->cs_index)); |
432 | 451 | ||
433 | /* | 452 | /* |
434 | * Enable decode window for this chip select. | 453 | * Enable decode window for this chip select. |
@@ -439,7 +458,7 @@ static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram) | |||
439 | /* | 458 | /* |
440 | * Re-enable decode windows. | 459 | * Re-enable decode windows. |
441 | */ | 460 | */ |
442 | orion5x_write(PCI_BAR_ENABLE, win_enable); | 461 | writel(win_enable, PCI_BAR_ENABLE); |
443 | 462 | ||
444 | /* | 463 | /* |
445 | * Disable automatic update of address remaping when writing to BARs. | 464 | * Disable automatic update of address remaping when writing to BARs. |
@@ -522,6 +541,11 @@ static void __devinit rc_pci_fixup(struct pci_dev *dev) | |||
522 | } | 541 | } |
523 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); | 542 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); |
524 | 543 | ||
544 | void __init orion5x_pci_set_cardbus_mode(void) | ||
545 | { | ||
546 | orion5x_pci_cardbus_mode = 1; | ||
547 | } | ||
548 | |||
525 | int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys) | 549 | int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys) |
526 | { | 550 | { |
527 | int ret = 0; | 551 | int ret = 0; |