diff options
Diffstat (limited to 'drivers/pci/dwc/pci-imx6.c')
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 128 |
1 files changed, 69 insertions, 59 deletions
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 6e5d06fb3b10..70fa380ea077 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -30,7 +30,7 @@ #include "pcie-designware.h" -#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) +#define to_imx6_pcie(x) dev_get_drvdata((x)->dev) enum imx6_pcie_variants { IMX6Q, @@ -39,7 +39,7 @@ enum imx6_pcie_variants { }; struct imx6_pcie { - struct pcie_port pp; /* pp.dbi_base is DT 0th resource */ + struct dw_pcie *pci; int reset_gpio; bool gpio_active_high; struct clk *pcie_bus; @@ -97,13 +97,13 @@ struct imx6_pcie { static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val; u32 max_iterations = 10; u32 wait_counter = 0; do { - val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT); + val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; wait_counter++; @@ -118,22 +118,22 @@ static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val; int ret; val = addr << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); ret = pcie_phy_poll_ack(imx6_pcie, 1); if (ret) return ret; val = addr << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); return pcie_phy_poll_ack(imx6_pcie, 0); } @@ -141,7 +141,7 @@ static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr) /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val, phy_ctl; int ret; @@ -151,24 +151,24 @@ static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data) /* assert Read signal */ phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, phy_ctl); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl); ret = pcie_phy_poll_ack(imx6_pcie, 1); if (ret) return ret; - val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT); + val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); *data = val & 0xffff; /* deassert Read signal */ - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x00); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00); return pcie_phy_poll_ack(imx6_pcie, 0); } static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 var; int ret; @@ -179,11 +179,11 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) return ret; var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* capture data */ var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); ret = pcie_phy_poll_ack(imx6_pcie, 1); if (ret) @@ -191,7 +191,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* deassert cap data */ var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* wait for ack de-assertion */ ret = pcie_phy_poll_ack(imx6_pcie, 0); @@ -200,7 +200,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* assert wr signal */ var = 0x1 << PCIE_PHY_CTRL_WR_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* wait for ack */ ret = pcie_phy_poll_ack(imx6_pcie, 1); @@ -209,14 +209,14 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* deassert wr signal */ var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* wait for ack de-assertion */ ret = pcie_phy_poll_ack(imx6_pcie, 0); if (ret) return ret; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x0); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x0); return 0; } @@ -247,7 +247,7 @@ static int imx6q_pcie_abort_handler(unsigned long addr, static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val, gpr1, gpr12; switch (imx6_pcie->variant) { @@ -284,10 +284,10 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) && (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) { - val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); + val = dw_pcie_readl_dbi(pci, PCIE_PL_PFLR); val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; val |= PCIE_PL_PFLR_FORCE_LINK; - dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val); + dw_pcie_writel_dbi(pci, PCIE_PL_PFLR, val); regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); @@ -303,8 +303,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; int ret = 0; switch (imx6_pcie->variant) { @@ -340,8 +340,8 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; int ret; ret = clk_prepare_enable(imx6_pcie->pcie_phy); @@ -440,28 +440,28 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; /* check if the link is up or not */ - if (!dw_pcie_wait_for_link(pp)) + if (!dw_pcie_wait_for_link(pci)) return 0; dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", - dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0), - dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1)); + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); return -ETIMEDOUT; } static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; u32 tmp; unsigned int retries; for (retries = 0; retries < 200; retries++) { - tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); /* Test if the speed change finished. */ if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) return 0; @@ -475,15 +475,16 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie) static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg) { struct imx6_pcie *imx6_pcie = arg; - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; + struct pcie_port *pp = &pci->pp; return dw_handle_msi_irq(pp); } static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; u32 tmp; int ret; @@ -492,10 +493,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) * started in Gen2 mode, there is a possibility the devices on the * bus will not be detected at all. This happens with PCIe switches. */ - tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR); + tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; - dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp); + dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); /* Start LTSSM. */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, @@ -509,10 +510,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) if (imx6_pcie->link_gen == 2) { /* Allow Gen2 mode after the link is up. */ - tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR); + tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; - dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp); + dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); } else { dev_info(dev, "Link: Gen2 disabled\n"); } @@ -521,9 +522,9 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) * Start Directed Speed Change so the best possible speed both link * partners support can be negotiated. */ - tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); tmp |= PORT_LOGIC_SPEED_CHANGE; - dw_pcie_writel_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); ret = imx6_pcie_wait_for_speed_change(imx6_pcie); if (ret) { @@ -538,21 +539,22 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) goto err_reset_phy; } - tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCSR); + tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf); return 0; err_reset_phy: dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", - dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0), - dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1)); + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); imx6_pcie_reset_phy(imx6_pcie); return ret; } static void imx6_pcie_host_init(struct pcie_port *pp) { - struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); imx6_pcie_assert_core_reset(imx6_pcie); imx6_pcie_init_phy(imx6_pcie); @@ -564,22 +566,22 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_msi_init(pp); } -static int imx6_pcie_link_up(struct pcie_port *pp) +static int imx6_pcie_link_up(struct dw_pcie *pci) { - return dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1) & + return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; } -static struct pcie_host_ops imx6_pcie_host_ops = { - .link_up = imx6_pcie_link_up, +static struct dw_pcie_host_ops imx6_pcie_host_ops = { .host_init = imx6_pcie_host_init, }; static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, struct platform_device *pdev) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; if (IS_ENABLED(CONFIG_PCI_MSI)) { @@ -611,11 +613,15 @@ static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = imx6_pcie_link_up, +}; + static int __init imx6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct imx6_pcie *imx6_pcie; - struct pcie_port *pp; struct resource *dbi_base; struct device_node *node = dev->of_node; int ret; @@ -624,8 +630,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) if (!imx6_pcie) return -ENOMEM; - pp = &imx6_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; imx6_pcie->variant = (enum imx6_pcie_variants)of_device_get_match_data(dev); @@ -635,9 +645,9 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "imprecise external abort"); dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pp->dbi_base = devm_ioremap_resource(dev, dbi_base); - if (IS_ERR(pp->dbi_base)) - return PTR_ERR(pp->dbi_base); + pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); /* Fetch GPIOs */ imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); |