int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, struct ssb_device *dev) { struct ssb_device *pdev = pc->dev; struct ssb_bus *bus; int err = 0; u32 tmp; might_sleep(); if (!pdev) goto out; bus = pdev->bus; /* Enable interrupts for this device. */ if (bus->host_pci && ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { u32 coremask; /* Calculate the "coremask" for the device. */ coremask = (1 << dev->core_index); err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); if (err) goto out; tmp |= coremask << 8; err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp); if (err) goto out; } else { u32 intvec; intvec = ssb_read32(pdev, SSB_INTVEC); if ((bus->chip_id & 0xFF00) == 0x4400) { /* Workaround: On the BCM44XX the BPFLAG routing * bit is wrong. Use a hardcoded constant. */ intvec |= 0x00000002; } else { tmp = ssb_read32(dev, SSB_TPSFLAG); tmp &= SSB_TPSFLAG_BPFLAG; intvec |= tmp; } ssb_write32(pdev, SSB_INTVEC, intvec); } /* Setup PCIcore operation. */ if (pc->setup_done) goto out; if (pdev->id.coreid == SSB_DEV_PCI) { tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); tmp |= SSB_PCICORE_SBTOPCI_PREF; tmp |= SSB_PCICORE_SBTOPCI_BURST; pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); if (pdev->id.revision < 5) { tmp = ssb_read32(pdev, SSB_IMCFGLO); tmp &= ~SSB_IMCFGLO_SERTO; tmp |= 2; tmp &= ~SSB_IMCFGLO_REQTO; tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; ssb_write32(pdev, SSB_IMCFGLO, tmp); ssb_commit_settings(bus); } else if (pdev->id.revision >= 11) { tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); tmp |= SSB_PCICORE_SBTOPCI_MRM; pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); } } else { WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); //TODO: Better make defines for all these magic PCIE values. if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { /* TLP Workaround register. */ tmp = ssb_pcie_read(pc, 0x4); tmp |= 0x8; ssb_pcie_write(pc, 0x4, tmp); } if (pdev->id.revision == 0) { const u8 serdes_rx_device = 0x1F; ssb_pcie_mdio_write(pc, serdes_rx_device, 2 /* Timer */, 0x8128); ssb_pcie_mdio_write(pc, serdes_rx_device, 6 /* CDR */, 0x0100); ssb_pcie_mdio_write(pc, serdes_rx_device, 7 /* CDR BW */, 0x1466); } else if (pdev->id.revision == 1) { /* DLLP Link Control register. */ tmp = ssb_pcie_read(pc, 0x100); tmp |= 0x40; ssb_pcie_write(pc, 0x100, tmp); } } pc->setup_done = 1; out: return err; }
int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, struct ssb_device *dev) { struct ssb_device *pdev = pc->dev; struct ssb_bus *bus; int err = 0; u32 tmp; if (dev->bus->bustype != SSB_BUSTYPE_PCI) { goto out; } if (!pdev) goto out; bus = pdev->bus; might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); if (bus->host_pci && ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { u32 coremask; coremask = (1 << dev->core_index); err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); if (err) goto out; tmp |= coremask << 8; err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp); if (err) goto out; } else { u32 intvec; intvec = ssb_read32(pdev, SSB_INTVEC); tmp = ssb_read32(dev, SSB_TPSFLAG); tmp &= SSB_TPSFLAG_BPFLAG; intvec |= (1 << tmp); ssb_write32(pdev, SSB_INTVEC, intvec); } if (pc->setup_done) goto out; if (pdev->id.coreid == SSB_DEV_PCI) { tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); tmp |= SSB_PCICORE_SBTOPCI_PREF; tmp |= SSB_PCICORE_SBTOPCI_BURST; pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); if (pdev->id.revision < 5) { tmp = ssb_read32(pdev, SSB_IMCFGLO); tmp &= ~SSB_IMCFGLO_SERTO; tmp |= 2; tmp &= ~SSB_IMCFGLO_REQTO; tmp |= 3 << SSB_IMCFGLO_REQTO_SHIFT; ssb_write32(pdev, SSB_IMCFGLO, tmp); ssb_commit_settings(bus); } else if (pdev->id.revision >= 11) { tmp = pcicore_read32(pc, SSB_PCICORE_SBTOPCI2); tmp |= SSB_PCICORE_SBTOPCI_MRM; pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); } } else { WARN_ON(pdev->id.coreid != SSB_DEV_PCIE); if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { tmp = ssb_pcie_read(pc, 0x4); tmp |= 0x8; ssb_pcie_write(pc, 0x4, tmp); } if (pdev->id.revision == 0) { const u8 serdes_rx_device = 0x1F; ssb_pcie_mdio_write(pc, serdes_rx_device, 2 , 0x8128); ssb_pcie_mdio_write(pc, serdes_rx_device, 6 , 0x0100); ssb_pcie_mdio_write(pc, serdes_rx_device, 7 , 0x1466); } else if (pdev->id.revision == 1) { tmp = ssb_pcie_read(pc, 0x100); tmp |= 0x40; ssb_pcie_write(pc, 0x100, tmp); } } pc->setup_done = 1; out: return err; }