static int armada8k_pcie_host_init(struct pcie_port *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct armada8k_pcie *pcie = to_armada8k_pcie(pci); dw_pcie_setup_rc(pp); armada8k_pcie_establish_link(pcie); return 0; }
static void armada8k_pcie_establish_link(struct pcie_port *pp) { struct armada8k_pcie *pcie = to_armada8k_pcie(pp); void __iomem *base = pcie->base; u32 reg; if (!dw_pcie_link_up(pp)) { /* Disable LTSSM state machine to enable configuration */ reg = readl(base + PCIE_GLOBAL_CONTROL_REG); reg &= ~(PCIE_APP_LTSSM_EN); writel(reg, base + PCIE_GLOBAL_CONTROL_REG); } /* Set the device to root complex mode */ reg = readl(base + PCIE_GLOBAL_CONTROL_REG); reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT); reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT; writel(reg, base + PCIE_GLOBAL_CONTROL_REG); /* Set the PCIe master AxCache attributes */ writel(ARCACHE_DEFAULT_VALUE, base + PCIE_ARCACHE_TRC_REG); writel(AWCACHE_DEFAULT_VALUE, base + PCIE_AWCACHE_TRC_REG); /* Set the PCIe master AxDomain attributes */ reg = readl(base + PCIE_ARUSER_REG); reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; writel(reg, base + PCIE_ARUSER_REG); reg = readl(base + PCIE_AWUSER_REG); reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT); reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT; writel(reg, base + PCIE_AWUSER_REG); /* Enable INT A-D interrupts */ reg = readl(base + PCIE_GLOBAL_INT_MASK1_REG); reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK | PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK; writel(reg, base + PCIE_GLOBAL_INT_MASK1_REG); if (!dw_pcie_link_up(pp)) { /* Configuration done. Start LTSSM */ reg = readl(base + PCIE_GLOBAL_CONTROL_REG); reg |= PCIE_APP_LTSSM_EN; writel(reg, base + PCIE_GLOBAL_CONTROL_REG); } /* Wait until the link becomes active again */ if (dw_pcie_wait_for_link(pp)) dev_err(pp->dev, "Link not up after reconfiguration\n"); }
static int armada8k_pcie_link_up(struct pcie_port *pp) { struct armada8k_pcie *pcie = to_armada8k_pcie(pp); u32 reg; u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; reg = readl(pcie->base + PCIE_GLOBAL_STATUS_REG); if ((reg & mask) == mask) return 1; dev_dbg(pp->dev, "No link detected (Global-Status: 0x%08x).\n", reg); return 0; }
static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) { struct pcie_port *pp = arg; struct armada8k_pcie *pcie = to_armada8k_pcie(pp); void __iomem *base = pcie->base; u32 val; /* * Interrupts are directly handled by the device driver of the * PCI device. However, they are also latched into the PCIe * controller, so we simply discard them. */ val = readl(base + PCIE_GLOBAL_INT_CAUSE1_REG); writel(val, base + PCIE_GLOBAL_INT_CAUSE1_REG); return IRQ_HANDLED; }