/** * imx_pcie_ep_probe - Device Initialization Routine * @pdev: PCI device information struct * @id: entry in id_tbl * * Returns 0 on success, negative on failure **/ static int imx_pcie_ep_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret = 0; struct device *dev = &pdev->dev; struct imx_pcie_ep_priv *priv; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(dev, "can't alloc imx pcie priv\n"); return -ENOMEM; } priv->pci_dev = pdev; if (pci_enable_device(pdev)) { ret = -ENODEV; goto out; } pci_set_master(pdev); pci_set_drvdata(pdev, priv); priv->hw_base = pci_iomap(pdev, 0, 0); if (!priv->hw_base) { ret = -ENODEV; goto out; } pr_info("pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); pr_info("pci_resource_base = %p\n", priv->hw_base); ret = pci_enable_msi(priv->pci_dev); if (ret < 0) { dev_err(dev, "can't enable msi\n"); return ret; } /* * Force to use 0x01FF8000 as the MSI address, * to do the MSI demo */ pci_bus_write_config_dword(pdev->bus, 0, 0x54, 0x01FF8000); pci_bus_write_config_dword(pdev->bus->parent, 0, 0x820, 0x01FF8000); /* configure rc's msi cap */ pci_bus_read_config_dword(pdev->bus->parent, 0, 0x50, &ret); ret |= (PCI_MSI_FLAGS_ENABLE << 16); pci_bus_write_config_dword(pdev->bus->parent, 0, 0x50, ret); pci_bus_write_config_dword(pdev->bus->parent, 0, 0x828, 0x1); pci_bus_write_config_dword(pdev->bus->parent, 0, 0x82C, 0xFFFFFFFE); return 0; out: return ret; }
int pci_write_config_dword(const struct pci_dev *dev, int where, u32 val) { if (pci_dev_is_disconnected(dev)) return PCIBIOS_DEVICE_NOT_FOUND; return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); }
static void piix4_poweroff(void) { int spec_devid; u16 sts; /* Ensure the power button status is clear */ while (1) { sts = inw(io_offset + PIIX4_FUNC3IO_PMSTS); if (!(sts & PIIX4_FUNC3IO_PMSTS_PWRBTN_STS)) break; outw(sts, io_offset + PIIX4_FUNC3IO_PMSTS); } /* Enable entry to suspend */ outw(PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF | PIIX4_FUNC3IO_PMCNTRL_SUS_EN, io_offset + PIIX4_FUNC3IO_PMCNTRL); /* If the special cycle occurs too soon this doesn't work... */ mdelay(10); /* * The PIIX4 will enter the suspend state only after seeing a special * cycle with the correct magic data on the PCI bus. Generate that * cycle now. */ spec_devid = PCI_DEVID(0, PCI_DEVFN(0x1f, 0x7)); pci_bus_write_config_dword(pm_dev->bus, spec_devid, 0, PIIX4_SUSPEND_MAGIC); /* Give the system some time to power down, then error */ mdelay(1000); pr_emerg("Unable to poweroff system\n"); }
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) { u8 hdr_type; u32 link_ctrl; u16 pos, link_status; int link_is_active = 0; /* make sure we are not in EP mode */ pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type); return -EFAULT; } /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI); /* check link status to see if link is active */ pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = 1; if (!link_is_active) { /* try GEN 1 link speed */ #define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc #define PCI_TARGET_LINK_SPEED_MASK 0xf #define PCI_TARGET_LINK_SPEED_GEN2 0x2 #define PCI_TARGET_LINK_SPEED_GEN1 0x1 pci_bus_read_config_dword(bus, 0, PCI_LINK_STATUS_CTRL_2_OFFSET, &link_ctrl); if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == PCI_TARGET_LINK_SPEED_GEN2) { link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; pci_bus_write_config_dword(bus, 0, PCI_LINK_STATUS_CTRL_2_OFFSET, link_ctrl); msleep(100); pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = 1; } } dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); return link_is_active ? 0 : -ENODEV; }
/* allocate mem/pmem/io resource to a new function */ static int init_config_space (struct acpiphp_func *func) { u32 bar, len; u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5, 0 }; int count; struct acpiphp_bridge *bridge; struct pci_resource *res; struct pci_bus *pbus; int bus, device, function; unsigned int devfn; u16 tmp; bridge = func->slot->bridge; pbus = bridge->pci_bus; bus = bridge->bus; device = func->slot->device; function = func->function; devfn = PCI_DEVFN(device, function); for (count = 0; address[count]; count++) { /* for 6 BARs */ pci_bus_write_config_dword(pbus, devfn, address[count], 0xFFFFFFFF); pci_bus_read_config_dword(pbus, devfn, address[count], &bar); if (!bar) /* This BAR is not implemented */ continue; dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar); if (bar & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ len = bar & 0xFFFFFFFC; len = ~len + 1; dbg("len in IO %x, BAR %d\n", len, count); spin_lock(&bridge->res_lock); res = acpiphp_get_io_resource(&bridge->io_head, len); spin_unlock(&bridge->res_lock); if (!res) { err("cannot allocate requested io for %02x:%02x.%d len %x\n", bus, device, function, len); return -1; } pci_bus_write_config_dword(pbus, devfn, address[count], (u32)res->base); res->next = func->io_head; func->io_head = res; } else { /* This is Memory */ if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) { /* pfmem */ len = bar & 0xFFFFFFF0; len = ~len + 1; dbg("len in PFMEM %x, BAR %d\n", len, count); spin_lock(&bridge->res_lock); res = acpiphp_get_resource(&bridge->p_mem_head, len); spin_unlock(&bridge->res_lock); if (!res) { err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n", bus, device, function, len); return -1; } pci_bus_write_config_dword(pbus, devfn, address[count], (u32)res->base); if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ dbg("inside the pfmem 64 case, count %d\n", count); count += 1; pci_bus_write_config_dword(pbus, devfn, address[count], (u32)(res->base >> 32)); } res->next = func->p_mem_head; func->p_mem_head = res; } else {
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) { struct device *dev = pcie->dev; u8 hdr_type; u32 link_ctrl, class, val; u16 pos = PCI_EXP_CAP, link_status; bool link_is_active = false; /* * PAXC connects to emulated endpoint devices directly and does not * have a Serdes. Therefore skip the link detection logic here. */ if (pcie->type == IPROC_PCIE_PAXC) return 0; val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS); if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { dev_err(dev, "PHY or data link is INACTIVE!\n"); return -ENODEV; } /* make sure we are not in EP mode */ pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type); return -EFAULT; } /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ #define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c #define PCI_CLASS_BRIDGE_MASK 0xffff00 #define PCI_CLASS_BRIDGE_SHIFT 8 pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); class &= ~PCI_CLASS_BRIDGE_MASK; class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); /* check link status to see if link is active */ pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = true; if (!link_is_active) { /* try GEN 1 link speed */ #define PCI_TARGET_LINK_SPEED_MASK 0xf #define PCI_TARGET_LINK_SPEED_GEN2 0x2 #define PCI_TARGET_LINK_SPEED_GEN1 0x1 pci_bus_read_config_dword(bus, 0, pos + PCI_EXP_LNKCTL2, &link_ctrl); if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == PCI_TARGET_LINK_SPEED_GEN2) { link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; pci_bus_write_config_dword(bus, 0, pos + PCI_EXP_LNKCTL2, link_ctrl); msleep(100); pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = true; } } dev_info(dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); return link_is_active ? 0 : -ENODEV; }
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) { u8 hdr_type; u32 link_ctrl, class, val; u16 pos, link_status; bool link_is_active = false; val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); return -ENODEV; } /* make sure we are not in EP mode */ pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type); return -EFAULT; } /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ #define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c #define PCI_CLASS_BRIDGE_MASK 0xffff00 #define PCI_CLASS_BRIDGE_SHIFT 8 pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); class &= ~PCI_CLASS_BRIDGE_MASK; class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); /* check link status to see if link is active */ pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = true; if (!link_is_active) { /* try GEN 1 link speed */ #define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc #define PCI_TARGET_LINK_SPEED_MASK 0xf #define PCI_TARGET_LINK_SPEED_GEN2 0x2 #define PCI_TARGET_LINK_SPEED_GEN1 0x1 pci_bus_read_config_dword(bus, 0, PCI_LINK_STATUS_CTRL_2_OFFSET, &link_ctrl); if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == PCI_TARGET_LINK_SPEED_GEN2) { link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; pci_bus_write_config_dword(bus, 0, PCI_LINK_STATUS_CTRL_2_OFFSET, link_ctrl); msleep(100); pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); if (link_status & PCI_EXP_LNKSTA_NLW) link_is_active = true; } } dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN"); return link_is_active ? 0 : -ENODEV; }