Lines Matching +full:no +full:- +full:pc +full:- +full:write
3 * Broadcom PCI-core driver
19 static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address);
20 static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data);
21 static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address);
22 static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
26 u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) in pcicore_read32() argument
28 return ssb_read32(pc->dev, offset); in pcicore_read32()
32 void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value) in pcicore_write32() argument
34 ssb_write32(pc->dev, offset, value); in pcicore_write32()
38 u16 pcicore_read16(struct ssb_pcicore *pc, u16 offset) in pcicore_read16() argument
40 return ssb_read16(pc->dev, offset); in pcicore_read16()
44 void pcicore_write16(struct ssb_pcicore *pc, u16 offset, u16 value) in pcicore_write16() argument
46 ssb_write16(pc->dev, offset, value); in pcicore_write16()
61 /* Assume one-hot slot wiring */
70 static u32 get_cfgspace_addr(struct ssb_pcicore *pc, in get_cfgspace_addr() argument
78 if (pc->cardbusmode && (dev > 1)) in get_cfgspace_addr()
88 pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, tmp); in get_cfgspace_addr()
96 pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, in get_cfgspace_addr()
109 static int ssb_extpci_read_config(struct ssb_pcicore *pc, in ssb_extpci_read_config() argument
114 int err = -EINVAL; in ssb_extpci_read_config()
118 WARN_ON(!pc->hostmode); in ssb_extpci_read_config()
121 addr = get_cfgspace_addr(pc, bus, dev, func, off); in ssb_extpci_read_config()
124 err = -ENOMEM; in ssb_extpci_read_config()
155 static int ssb_extpci_write_config(struct ssb_pcicore *pc, in ssb_extpci_write_config() argument
160 int err = -EINVAL; in ssb_extpci_write_config()
164 WARN_ON(!pc->hostmode); in ssb_extpci_write_config()
167 addr = get_cfgspace_addr(pc, bus, dev, func, off); in ssb_extpci_write_config()
170 err = -ENOMEM; in ssb_extpci_write_config()
211 err = ssb_extpci_read_config(extpci_core, bus->number, PCI_SLOT(devfn), in ssb_pcicore_read_config()
225 err = ssb_extpci_write_config(extpci_core, bus->number, PCI_SLOT(devfn), in ssb_pcicore_write_config()
234 .write = ssb_pcicore_write_config,
240 .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
258 * We must first check if the device is a device on the PCI-core bridge. */
261 if (d->bus->ops != &ssb_pcicore_pciops) { in ssb_pcicore_plat_dev_init()
262 /* This is not a device on the PCI-core bridge. */ in ssb_pcicore_plat_dev_init()
263 return -ENODEV; in ssb_pcicore_plat_dev_init()
266 dev_info(&d->dev, "PCI: Fixing up device %s\n", pci_name(d)); in ssb_pcicore_plat_dev_init()
269 d->irq = ssb_mips_irq(extpci_core->dev) + 2; in ssb_pcicore_plat_dev_init()
270 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); in ssb_pcicore_plat_dev_init()
275 /* Early PCI fixup for a device on the PCI-core bridge. */
280 if (dev->bus->ops != &ssb_pcicore_pciops) { in ssb_pcicore_fixup_pcibridge()
281 /* This is not a device on the PCI-core bridge. */ in ssb_pcicore_fixup_pcibridge()
284 if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) in ssb_pcicore_fixup_pcibridge()
287 dev_info(&dev->dev, "PCI: Fixing up bridge %s\n", pci_name(dev)); in ssb_pcicore_fixup_pcibridge()
292 dev_err(&dev->dev, "PCI: SSB bridge enable failed\n"); in ssb_pcicore_fixup_pcibridge()
301 dev_info(&dev->dev, in ssb_pcicore_fixup_pcibridge()
311 if (dev->bus->ops != &ssb_pcicore_pciops) { in ssb_pcicore_pcibios_map_irq()
312 /* This is not a device on the PCI-core bridge. */ in ssb_pcicore_pcibios_map_irq()
313 return -ENODEV; in ssb_pcicore_pcibios_map_irq()
315 return ssb_mips_irq(extpci_core->dev) + 2; in ssb_pcicore_pcibios_map_irq()
318 static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) in ssb_pcicore_init_hostmode() argument
324 extpci_core = pc; in ssb_pcicore_init_hostmode()
326 dev_dbg(pc->dev->dev, "PCIcore in host mode found\n"); in ssb_pcicore_init_hostmode()
330 pcicore_write32(pc, SSB_PCICORE_CTL, val); in ssb_pcicore_init_hostmode()
332 pcicore_write32(pc, SSB_PCICORE_CTL, val); in ssb_pcicore_init_hostmode()
335 pcicore_write32(pc, SSB_PCICORE_CTL, val); in ssb_pcicore_init_hostmode()
337 pcicore_write32(pc, SSB_PCICORE_ARBCTL, val); in ssb_pcicore_init_hostmode()
340 if (pc->dev->bus->has_cardbus_slot) { in ssb_pcicore_init_hostmode()
341 dev_dbg(pc->dev->dev, "CardBus slot detected\n"); in ssb_pcicore_init_hostmode()
342 pc->cardbusmode = 1; in ssb_pcicore_init_hostmode()
344 ssb_gpio_out(pc->dev->bus, 1, 1); in ssb_pcicore_init_hostmode()
345 ssb_gpio_outen(pc->dev->bus, 1, 1); in ssb_pcicore_init_hostmode()
346 pcicore_write16(pc, SSB_PCICORE_SPROM(0), in ssb_pcicore_init_hostmode()
347 pcicore_read16(pc, SSB_PCICORE_SPROM(0)) in ssb_pcicore_init_hostmode()
352 pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, in ssb_pcicore_init_hostmode()
355 pcicore_write32(pc, SSB_PCICORE_SBTOPCI1, in ssb_pcicore_init_hostmode()
358 pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, in ssb_pcicore_init_hostmode()
364 * Tested delay 850 us lowered reboot chance to 50-80%, 1000 us fixed it in ssb_pcicore_init_hostmode()
365 * completely. Flushing all writes was also tested but with no luck. in ssb_pcicore_init_hostmode()
373 ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2); in ssb_pcicore_init_hostmode()
376 ssb_extpci_write_config(pc, 0, 0, 0, PCI_STATUS, &val, 2); in ssb_pcicore_init_hostmode()
379 pcicore_write32(pc, SSB_PCICORE_IMASK, in ssb_pcicore_init_hostmode()
384 * to non-MIPS platform. */ in ssb_pcicore_init_hostmode()
393 static int pcicore_is_in_hostmode(struct ssb_pcicore *pc) in pcicore_is_in_hostmode() argument
395 struct ssb_bus *bus = pc->dev->bus; in pcicore_is_in_hostmode()
399 chipid_top = (bus->chip_id & 0xFF00); in pcicore_is_in_hostmode()
404 if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI) in pcicore_is_in_hostmode()
407 /* The 200-pin BCM4712 package does not bond out PCI. Even when in pcicore_is_in_hostmode()
409 if (bus->chip_id == 0x4712) { in pcicore_is_in_hostmode()
410 if (bus->chip_package == SSB_CHIPPACK_BCM4712S) in pcicore_is_in_hostmode()
412 if (bus->chip_package == SSB_CHIPPACK_BCM4712M) in pcicore_is_in_hostmode()
415 if (bus->chip_id == 0x5350) in pcicore_is_in_hostmode()
418 return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE))); in pcicore_is_in_hostmode()
426 static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc) in ssb_pcicore_fix_sprom_core_index() argument
428 u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0)); in ssb_pcicore_fix_sprom_core_index()
429 if (((tmp & 0xF000) >> 12) != pc->dev->core_index) { in ssb_pcicore_fix_sprom_core_index()
431 tmp |= (pc->dev->core_index << 12); in ssb_pcicore_fix_sprom_core_index()
432 pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp); in ssb_pcicore_fix_sprom_core_index()
436 static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc) in ssb_pcicore_polarity_workaround() argument
438 return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; in ssb_pcicore_polarity_workaround()
441 static void ssb_pcicore_serdes_workaround(struct ssb_pcicore *pc) in ssb_pcicore_serdes_workaround() argument
447 ssb_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, in ssb_pcicore_serdes_workaround()
448 ssb_pcicore_polarity_workaround(pc)); in ssb_pcicore_serdes_workaround()
449 tmp = ssb_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); in ssb_pcicore_serdes_workaround()
451 ssb_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); in ssb_pcicore_serdes_workaround()
454 static void ssb_pcicore_pci_setup_workarounds(struct ssb_pcicore *pc) in ssb_pcicore_pci_setup_workarounds() argument
456 struct ssb_device *pdev = pc->dev; in ssb_pcicore_pci_setup_workarounds()
457 struct ssb_bus *bus = pdev->bus; in ssb_pcicore_pci_setup_workarounds()
460 tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); in ssb_pcicore_pci_setup_workarounds()
463 pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); in ssb_pcicore_pci_setup_workarounds()
465 if (pdev->id.revision < 5) { in ssb_pcicore_pci_setup_workarounds()
473 } else if (pdev->id.revision >= 11) { in ssb_pcicore_pci_setup_workarounds()
474 tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); in ssb_pcicore_pci_setup_workarounds()
476 pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); in ssb_pcicore_pci_setup_workarounds()
480 static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) in ssb_pcicore_pcie_setup_workarounds() argument
483 u8 rev = pc->dev->id.revision; in ssb_pcicore_pcie_setup_workarounds()
487 tmp = ssb_pcie_read(pc, 0x4); in ssb_pcicore_pcie_setup_workarounds()
489 ssb_pcie_write(pc, 0x4, tmp); in ssb_pcicore_pcie_setup_workarounds()
493 tmp = ssb_pcie_read(pc, 0x100); in ssb_pcicore_pcie_setup_workarounds()
495 ssb_pcie_write(pc, 0x100, tmp); in ssb_pcicore_pcie_setup_workarounds()
501 ssb_pcie_mdio_write(pc, serdes_rx_device, in ssb_pcicore_pcie_setup_workarounds()
503 ssb_pcie_mdio_write(pc, serdes_rx_device, in ssb_pcicore_pcie_setup_workarounds()
505 ssb_pcie_mdio_write(pc, serdes_rx_device, in ssb_pcicore_pcie_setup_workarounds()
509 ssb_pcicore_serdes_workaround(pc); in ssb_pcicore_pcie_setup_workarounds()
512 /* TODO: No PLL down */ in ssb_pcicore_pcie_setup_workarounds()
517 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(5)); in ssb_pcicore_pcie_setup_workarounds()
519 pcicore_write16(pc, SSB_PCICORE_SPROM(5), in ssb_pcicore_pcie_setup_workarounds()
528 static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) in ssb_pcicore_init_clientmode() argument
530 struct ssb_device *pdev = pc->dev; in ssb_pcicore_init_clientmode()
531 struct ssb_bus *bus = pdev->bus; in ssb_pcicore_init_clientmode()
533 if (bus->bustype == SSB_BUSTYPE_PCI) in ssb_pcicore_init_clientmode()
534 ssb_pcicore_fix_sprom_core_index(pc); in ssb_pcicore_init_clientmode()
539 /* Additional PCIe always once-executed workarounds */ in ssb_pcicore_init_clientmode()
540 if (pc->dev->id.coreid == SSB_DEV_PCIE) { in ssb_pcicore_init_clientmode()
541 ssb_pcicore_serdes_workaround(pc); in ssb_pcicore_init_clientmode()
547 void ssb_pcicore_init(struct ssb_pcicore *pc) in ssb_pcicore_init() argument
549 struct ssb_device *dev = pc->dev; in ssb_pcicore_init()
557 pc->hostmode = pcicore_is_in_hostmode(pc); in ssb_pcicore_init()
558 if (pc->hostmode) in ssb_pcicore_init()
559 ssb_pcicore_init_hostmode(pc); in ssb_pcicore_init()
561 if (!pc->hostmode) in ssb_pcicore_init()
562 ssb_pcicore_init_clientmode(pc); in ssb_pcicore_init()
565 static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address) in ssb_pcie_read() argument
567 pcicore_write32(pc, 0x130, address); in ssb_pcie_read()
568 return pcicore_read32(pc, 0x134); in ssb_pcie_read()
571 static void ssb_pcie_write(struct ssb_pcicore *pc, u32 address, u32 data) in ssb_pcie_write() argument
573 pcicore_write32(pc, 0x130, address); in ssb_pcie_write()
574 pcicore_write32(pc, 0x134, data); in ssb_pcie_write()
577 static void ssb_pcie_mdio_set_phy(struct ssb_pcicore *pc, u8 phy) in ssb_pcie_mdio_set_phy() argument
585 v |= (1 << 28); /* Write Transaction */ in ssb_pcie_mdio_set_phy()
589 pcicore_write32(pc, mdio_data, v); in ssb_pcie_mdio_set_phy()
593 v = pcicore_read32(pc, mdio_control); in ssb_pcie_mdio_set_phy()
600 static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address) in ssb_pcie_mdio_read() argument
611 pcicore_write32(pc, mdio_control, v); in ssb_pcie_mdio_read()
613 if (pc->dev->id.revision >= 10) { in ssb_pcie_mdio_read()
615 ssb_pcie_mdio_set_phy(pc, device); in ssb_pcie_mdio_read()
621 if (pc->dev->id.revision < 10) in ssb_pcie_mdio_read()
624 pcicore_write32(pc, mdio_data, v); in ssb_pcie_mdio_read()
628 v = pcicore_read32(pc, mdio_control); in ssb_pcie_mdio_read()
631 ret = pcicore_read32(pc, mdio_data); in ssb_pcie_mdio_read()
636 pcicore_write32(pc, mdio_control, 0); in ssb_pcie_mdio_read()
640 static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, in ssb_pcie_mdio_write() argument
651 pcicore_write32(pc, mdio_control, v); in ssb_pcie_mdio_write()
653 if (pc->dev->id.revision >= 10) { in ssb_pcie_mdio_write()
655 ssb_pcie_mdio_set_phy(pc, device); in ssb_pcie_mdio_write()
659 v |= (1 << 28); /* Write Transaction */ in ssb_pcie_mdio_write()
661 if (pc->dev->id.revision < 10) in ssb_pcie_mdio_write()
665 pcicore_write32(pc, mdio_data, v); in ssb_pcie_mdio_write()
669 v = pcicore_read32(pc, mdio_control); in ssb_pcie_mdio_write()
674 pcicore_write32(pc, mdio_control, 0); in ssb_pcie_mdio_write()
677 int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, in ssb_pcicore_dev_irqvecs_enable() argument
680 struct ssb_device *pdev = pc->dev; in ssb_pcicore_dev_irqvecs_enable()
685 if (dev->bus->bustype != SSB_BUSTYPE_PCI) { in ssb_pcicore_dev_irqvecs_enable()
686 /* This SSB device is not on a PCI host-bus. So the IRQs are in ssb_pcicore_dev_irqvecs_enable()
694 bus = pdev->bus; in ssb_pcicore_dev_irqvecs_enable()
696 might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); in ssb_pcicore_dev_irqvecs_enable()
699 if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) { in ssb_pcicore_dev_irqvecs_enable()
703 coremask = (1 << dev->core_index); in ssb_pcicore_dev_irqvecs_enable()
705 WARN_ON(bus->bustype != SSB_BUSTYPE_PCI); in ssb_pcicore_dev_irqvecs_enable()
706 err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); in ssb_pcicore_dev_irqvecs_enable()
710 err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp); in ssb_pcicore_dev_irqvecs_enable()
724 if (pc->setup_done) in ssb_pcicore_dev_irqvecs_enable()
726 if (pdev->id.coreid == SSB_DEV_PCI) { in ssb_pcicore_dev_irqvecs_enable()
727 ssb_pcicore_pci_setup_workarounds(pc); in ssb_pcicore_dev_irqvecs_enable()
729 WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); in ssb_pcicore_dev_irqvecs_enable()
730 ssb_pcicore_pcie_setup_workarounds(pc); in ssb_pcicore_dev_irqvecs_enable()
732 pc->setup_done = 1; in ssb_pcicore_dev_irqvecs_enable()