Merge branches 'pci/host-armada', 'pci/host-artpec', 'pci/host-dra7xx', 'pci/host-exynos', 'pci/host-hisi', 'pci/host-imx6', 'pci/host-keystone', 'pci/host-layerscape', 'pci/host-qcom' and 'pci/host-spear' into next
* pci/host-armada: MAINTAINERS: Add maintainer for the PCIe Marvell Armada 8K driver PCI: armada: Reorder struct armada8k_pcie PCI: armada: Pass device-specific struct to internal functions PCI: armada: Use generic DesignWare accessors PCI: armada: Remove redundant struct armada8k_pcie.base PCI: armada: Add local base pointer PCI: armada: Remove unused platform data * pci/host-artpec: PCI: artpec6: Add resource name comments PCI: artpec6: Pass device-specific struct to internal functions PCI: artpec6: Remove unnecessary artpec6_pcie_link_up() PCI: artpec6: Use generic DesignWare accessors PCI: artpec6: Add register accessors PCI: artpec6: Remove unused platform data PCI: artpec6: Add local struct device pointers * pci/host-dra7xx: PCI: dra7xx: Reorder struct dra7xx_pcie PCI: dra7xx: Move struct pcie_port setup to probe function PCI: dra7xx: Pass device-specific struct to internal functions PCI: dra7xx: Use generic DesignWare accessors PCI: dra7xx: Set drvdata at end of probe function PCI: dra7xx: Remove redundant struct device pointer from dra7xx_pcie PCI: dra7xx: Add local struct device pointers * pci/host-exynos: PCI: exynos: Reorder struct exynos_pcie PCI: exynos: Pass device-specific struct to internal functions PCI: exynos: Name private struct pointer "exynos_pcie" consistently PCI: exynos: Uninline register accessors PCI: exynos: Add local struct device pointers * pci/host-hisi: PCI: hisi: Reorder struct hisi_pcie PCI: hisi: Pass device-specific struct to internal functions PCI: hisi: Include register block base in PCIE_SYS_STATE4 address PCI: hisi: Use generic DesignWare accessors PCI: hisi: Remove redundant struct hisi_pcie.reg_base PCI: hisi: Name private struct pointer "hisi_pcie" consistently PCI: hisi: Remove unused platform data PCI: hisi: Add local struct device pointers * pci/host-imx6: PCI: imx6: Remove unused return values PCI: imx6: Reorder struct imx6_pcie PCI: imx6: Use generic DesignWare accessors PCI: imx6: Pass device-specific struct to internal functions PCI: imx6: Pass struct imx6_pcie to PHY accessors PCI: imx6: Removed unused struct imx6_pcie.mem_base PCI: imx6: Remove redundant of_node pointer PCI: imx6: Add local struct device pointers * pci/host-keystone: PCI: keystone: Reorder struct keystone_pcie PCI: keystone: Add app register accessors PCI: keystone: Pass keystone_pcie, not va_app_base, to DBI functions PCI: keystone: Pass keystone_pcie, not address, to IRQ functions PCI: keystone: Use generic DesignWare accessors PCI: keystone: Add local struct device pointers * pci/host-layerscape: PCI: layerscape: Reorder struct ls_pcie PCI: layerscape: Remove unused ls_add_pcie_port() platform_device arg PCI: layerscape: Move struct pcie_port setup to probe function PCI: layerscape: Pass device-specific struct to internal functions PCI: layerscape: Remove redundant struct ls_pcie.dbi PCI: layerscape: Remove unused platform data PCI: layerscape: Add local struct device pointers * pci/host-qcom: PCI: qcom: Reorder struct qcom_pcie PCI: qcom: Remove redundant struct qcom_pcie.dev PCI: qcom: Remove redundant struct qcom_pcie.dbi PCI: qcom: Remove unused platform data * pci/host-spear: PCI: spear: Clean up struct device usage PCI: spear: Reorder struct spear13xx_pcie PCI: spear: Pass device-specific struct to internal functions PCI: spear: Remove unused constants
This commit is contained in:
parent
22c7e1d4b4
3dc9d38c0c
7c62efcfc6
8e5ec4143d
6b1f185a5f
f84cfdf721
9ab021b6cf
4841f3ad0c
6caaa28d92
ee05369412
6a43a425a0
commit
217c6d21e9
|
@ -8936,6 +8936,14 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/pci/versatile.txt
|
||||
F: drivers/pci/host/pci-versatile.c
|
||||
|
||||
PCI DRIVER FOR ARMADA 8K
|
||||
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
L: linux-arm-kernel@lists.infradead.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
|
||||
F: drivers/pci/host/pcie-armada8k.c
|
||||
|
||||
PCI DRIVER FOR APPLIEDMICRO XGENE
|
||||
M: Tanmay Inamdar <tinamdar@apm.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
|
|
|
@ -64,11 +64,10 @@
|
|||
#define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF
|
||||
|
||||
struct dra7xx_pcie {
|
||||
void __iomem *base;
|
||||
struct phy **phy;
|
||||
int phy_count;
|
||||
struct device *dev;
|
||||
struct pcie_port pp;
|
||||
void __iomem *base; /* DT ti_conf */
|
||||
int phy_count; /* DT phy-names count */
|
||||
struct phy **phy;
|
||||
};
|
||||
|
||||
#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp)
|
||||
|
@ -84,17 +83,6 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
|
|||
writel(value, pcie->base + offset);
|
||||
}
|
||||
|
||||
static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset)
|
||||
{
|
||||
return readl(pp->dbi_base + offset);
|
||||
}
|
||||
|
||||
static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset,
|
||||
u32 value)
|
||||
{
|
||||
writel(value, pp->dbi_base + offset);
|
||||
}
|
||||
|
||||
static int dra7xx_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
|
||||
|
@ -103,13 +91,14 @@ static int dra7xx_pcie_link_up(struct pcie_port *pp)
|
|||
return !!(reg & LINK_UP);
|
||||
}
|
||||
|
||||
static int dra7xx_pcie_establish_link(struct pcie_port *pp)
|
||||
static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx)
|
||||
{
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
|
||||
struct pcie_port *pp = &dra7xx->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 reg;
|
||||
|
||||
if (dw_pcie_link_up(pp)) {
|
||||
dev_err(pp->dev, "link is already up\n");
|
||||
dev_err(dev, "link is already up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -120,10 +109,8 @@ static int dra7xx_pcie_establish_link(struct pcie_port *pp)
|
|||
return dw_pcie_wait_for_link(pp);
|
||||
}
|
||||
|
||||
static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
|
||||
static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
|
||||
{
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
|
||||
|
||||
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
|
||||
~INTERRUPTS);
|
||||
dra7xx_pcie_writel(dra7xx,
|
||||
|
@ -142,6 +129,8 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
|
|||
|
||||
static void dra7xx_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
|
||||
|
||||
pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
|
||||
pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
|
||||
pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
|
||||
|
@ -149,10 +138,10 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
|
|||
|
||||
dw_pcie_setup_rc(pp);
|
||||
|
||||
dra7xx_pcie_establish_link(pp);
|
||||
dra7xx_pcie_establish_link(dra7xx);
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
dw_pcie_msi_init(pp);
|
||||
dra7xx_pcie_enable_interrupts(pp);
|
||||
dra7xx_pcie_enable_interrupts(dra7xx);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops dra7xx_pcie_host_ops = {
|
||||
|
@ -196,8 +185,8 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
|
|||
|
||||
static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
|
||||
struct dra7xx_pcie *dra7xx = arg;
|
||||
struct pcie_port *pp = &dra7xx->pp;
|
||||
u32 reg;
|
||||
|
||||
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
|
||||
|
@ -223,51 +212,51 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
|
|||
static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct dra7xx_pcie *dra7xx = arg;
|
||||
struct device *dev = dra7xx->pp.dev;
|
||||
u32 reg;
|
||||
|
||||
reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
|
||||
|
||||
if (reg & ERR_SYS)
|
||||
dev_dbg(dra7xx->dev, "System Error\n");
|
||||
dev_dbg(dev, "System Error\n");
|
||||
|
||||
if (reg & ERR_FATAL)
|
||||
dev_dbg(dra7xx->dev, "Fatal Error\n");
|
||||
dev_dbg(dev, "Fatal Error\n");
|
||||
|
||||
if (reg & ERR_NONFATAL)
|
||||
dev_dbg(dra7xx->dev, "Non Fatal Error\n");
|
||||
dev_dbg(dev, "Non Fatal Error\n");
|
||||
|
||||
if (reg & ERR_COR)
|
||||
dev_dbg(dra7xx->dev, "Correctable Error\n");
|
||||
dev_dbg(dev, "Correctable Error\n");
|
||||
|
||||
if (reg & ERR_AXI)
|
||||
dev_dbg(dra7xx->dev, "AXI tag lookup fatal Error\n");
|
||||
dev_dbg(dev, "AXI tag lookup fatal Error\n");
|
||||
|
||||
if (reg & ERR_ECRC)
|
||||
dev_dbg(dra7xx->dev, "ECRC Error\n");
|
||||
dev_dbg(dev, "ECRC Error\n");
|
||||
|
||||
if (reg & PME_TURN_OFF)
|
||||
dev_dbg(dra7xx->dev,
|
||||
dev_dbg(dev,
|
||||
"Power Management Event Turn-Off message received\n");
|
||||
|
||||
if (reg & PME_TO_ACK)
|
||||
dev_dbg(dra7xx->dev,
|
||||
dev_dbg(dev,
|
||||
"Power Management Turn-Off Ack message received\n");
|
||||
|
||||
if (reg & PM_PME)
|
||||
dev_dbg(dra7xx->dev,
|
||||
"PM Power Management Event message received\n");
|
||||
dev_dbg(dev, "PM Power Management Event message received\n");
|
||||
|
||||
if (reg & LINK_REQ_RST)
|
||||
dev_dbg(dra7xx->dev, "Link Request Reset\n");
|
||||
dev_dbg(dev, "Link Request Reset\n");
|
||||
|
||||
if (reg & LINK_UP_EVT)
|
||||
dev_dbg(dra7xx->dev, "Link-up state change\n");
|
||||
dev_dbg(dev, "Link-up state change\n");
|
||||
|
||||
if (reg & CFG_BME_EVT)
|
||||
dev_dbg(dra7xx->dev, "CFG 'Bus Master Enable' change\n");
|
||||
dev_dbg(dev, "CFG 'Bus Master Enable' change\n");
|
||||
|
||||
if (reg & CFG_MSE_EVT)
|
||||
dev_dbg(dra7xx->dev, "CFG 'Memory Space Enable' change\n");
|
||||
dev_dbg(dev, "CFG 'Memory Space Enable' change\n");
|
||||
|
||||
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg);
|
||||
|
||||
|
@ -278,13 +267,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
|
|||
struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct pcie_port *pp;
|
||||
struct pcie_port *pp = &dra7xx->pp;
|
||||
struct device *dev = pp->dev;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
pp = &dra7xx->pp;
|
||||
pp->dev = dev;
|
||||
pp->ops = &dra7xx_pcie_host_ops;
|
||||
|
||||
pp->irq = platform_get_irq(pdev, 1);
|
||||
if (pp->irq < 0) {
|
||||
|
@ -292,12 +277,11 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->irq,
|
||||
dra7xx_pcie_msi_irq_handler,
|
||||
ret = devm_request_irq(dev, pp->irq, dra7xx_pcie_msi_irq_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"dra7-pcie-msi", pp);
|
||||
"dra7-pcie-msi", dra7xx);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
dev_err(dev, "failed to request irq\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -314,7 +298,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(dra7xx->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -332,6 +316,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
|
|||
void __iomem *base;
|
||||
struct resource *res;
|
||||
struct dra7xx_pcie *dra7xx;
|
||||
struct pcie_port *pp;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
char name[10];
|
||||
|
@ -343,6 +328,10 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
|
|||
if (!dra7xx)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &dra7xx->pp;
|
||||
pp->dev = dev;
|
||||
pp->ops = &dra7xx_pcie_host_ops;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "missing IRQ resource\n");
|
||||
|
@ -390,7 +379,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
|
|||
|
||||
dra7xx->base = base;
|
||||
dra7xx->phy = phy;
|
||||
dra7xx->dev = dev;
|
||||
dra7xx->phy_count = phy_count;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
@ -407,7 +395,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
|
|||
ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
|
||||
"pcie_reset");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "gpio%d request failed, ret %d\n",
|
||||
dev_err(dev, "gpio%d request failed, ret %d\n",
|
||||
gpio_sel, ret);
|
||||
goto err_gpio;
|
||||
}
|
||||
|
@ -420,12 +408,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
|
|||
reg &= ~LTSSM_EN;
|
||||
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
|
||||
|
||||
platform_set_drvdata(pdev, dra7xx);
|
||||
|
||||
ret = dra7xx_add_pcie_port(dra7xx, pdev);
|
||||
if (ret < 0)
|
||||
goto err_gpio;
|
||||
|
||||
platform_set_drvdata(pdev, dra7xx);
|
||||
return 0;
|
||||
|
||||
err_gpio:
|
||||
|
@ -451,9 +438,9 @@ static int dra7xx_pcie_suspend(struct device *dev)
|
|||
u32 val;
|
||||
|
||||
/* clear MSE */
|
||||
val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
|
||||
val = dw_pcie_readl_rc(pp, PCI_COMMAND);
|
||||
val &= ~PCI_COMMAND_MEMORY;
|
||||
dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
|
||||
dw_pcie_writel_rc(pp, PCI_COMMAND, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -465,9 +452,9 @@ static int dra7xx_pcie_resume(struct device *dev)
|
|||
u32 val;
|
||||
|
||||
/* set MSE */
|
||||
val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
|
||||
val = dw_pcie_readl_rc(pp, PCI_COMMAND);
|
||||
val |= PCI_COMMAND_MEMORY;
|
||||
dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);
|
||||
dw_pcie_writel_rc(pp, PCI_COMMAND, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
|
||||
|
||||
struct exynos_pcie {
|
||||
void __iomem *elbi_base;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *block_base;
|
||||
struct pcie_port pp;
|
||||
void __iomem *elbi_base; /* DT 0th resource */
|
||||
void __iomem *phy_base; /* DT 1st resource */
|
||||
void __iomem *block_base; /* DT 2nd resource */
|
||||
int reset_gpio;
|
||||
struct clk *clk;
|
||||
struct clk *bus_clk;
|
||||
struct pcie_port pp;
|
||||
};
|
||||
|
||||
/* PCIe ELBI registers */
|
||||
|
@ -102,40 +102,40 @@ struct exynos_pcie {
|
|||
#define PCIE_PHY_TRSV3_PD_TSV (0x1 << 7)
|
||||
#define PCIE_PHY_TRSV3_LVCC 0x31c
|
||||
|
||||
static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
|
||||
static void exynos_elb_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
|
||||
{
|
||||
writel(val, pcie->elbi_base + reg);
|
||||
writel(val, exynos_pcie->elbi_base + reg);
|
||||
}
|
||||
|
||||
static inline u32 exynos_elb_readl(struct exynos_pcie *pcie, u32 reg)
|
||||
static u32 exynos_elb_readl(struct exynos_pcie *exynos_pcie, u32 reg)
|
||||
{
|
||||
return readl(pcie->elbi_base + reg);
|
||||
return readl(exynos_pcie->elbi_base + reg);
|
||||
}
|
||||
|
||||
static inline void exynos_phy_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
|
||||
static void exynos_phy_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
|
||||
{
|
||||
writel(val, pcie->phy_base + reg);
|
||||
writel(val, exynos_pcie->phy_base + reg);
|
||||
}
|
||||
|
||||
static inline u32 exynos_phy_readl(struct exynos_pcie *pcie, u32 reg)
|
||||
static u32 exynos_phy_readl(struct exynos_pcie *exynos_pcie, u32 reg)
|
||||
{
|
||||
return readl(pcie->phy_base + reg);
|
||||
return readl(exynos_pcie->phy_base + reg);
|
||||
}
|
||||
|
||||
static inline void exynos_blk_writel(struct exynos_pcie *pcie, u32 val, u32 reg)
|
||||
static void exynos_blk_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
|
||||
{
|
||||
writel(val, pcie->block_base + reg);
|
||||
writel(val, exynos_pcie->block_base + reg);
|
||||
}
|
||||
|
||||
static inline u32 exynos_blk_readl(struct exynos_pcie *pcie, u32 reg)
|
||||
static u32 exynos_blk_readl(struct exynos_pcie *exynos_pcie, u32 reg)
|
||||
{
|
||||
return readl(pcie->block_base + reg);
|
||||
return readl(exynos_pcie->block_base + reg);
|
||||
}
|
||||
|
||||
static void exynos_pcie_sideband_dbi_w_mode(struct pcie_port *pp, bool on)
|
||||
static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *exynos_pcie,
|
||||
bool on)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
if (on) {
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC);
|
||||
|
@ -148,10 +148,10 @@ static void exynos_pcie_sideband_dbi_w_mode(struct pcie_port *pp, bool on)
|
|||
}
|
||||
}
|
||||
|
||||
static void exynos_pcie_sideband_dbi_r_mode(struct pcie_port *pp, bool on)
|
||||
static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *exynos_pcie,
|
||||
bool on)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
if (on) {
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC);
|
||||
|
@ -164,10 +164,9 @@ static void exynos_pcie_sideband_dbi_r_mode(struct pcie_port *pp, bool on)
|
|||
}
|
||||
}
|
||||
|
||||
static void exynos_pcie_assert_core_reset(struct pcie_port *pp)
|
||||
static void exynos_pcie_assert_core_reset(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
|
||||
val &= ~PCIE_CORE_RESET_ENABLE;
|
||||
|
@ -177,10 +176,9 @@ static void exynos_pcie_assert_core_reset(struct pcie_port *pp)
|
|||
exynos_elb_writel(exynos_pcie, 0, PCIE_NONSTICKY_RESET);
|
||||
}
|
||||
|
||||
static void exynos_pcie_deassert_core_reset(struct pcie_port *pp)
|
||||
static void exynos_pcie_deassert_core_reset(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
|
||||
val |= PCIE_CORE_RESET_ENABLE;
|
||||
|
@ -193,18 +191,14 @@ static void exynos_pcie_deassert_core_reset(struct pcie_port *pp)
|
|||
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET);
|
||||
}
|
||||
|
||||
static void exynos_pcie_assert_phy_reset(struct pcie_port *pp)
|
||||
static void exynos_pcie_assert_phy_reset(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET);
|
||||
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET);
|
||||
}
|
||||
|
||||
static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
|
||||
static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET);
|
||||
exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
|
||||
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
|
||||
|
@ -213,10 +207,9 @@ static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)
|
|||
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
|
||||
}
|
||||
|
||||
static void exynos_pcie_power_on_phy(struct pcie_port *pp)
|
||||
static void exynos_pcie_power_on_phy(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
|
||||
val &= ~PCIE_PHY_COMMON_PD_CMN;
|
||||
|
@ -239,10 +232,9 @@ static void exynos_pcie_power_on_phy(struct pcie_port *pp)
|
|||
exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
|
||||
}
|
||||
|
||||
static void exynos_pcie_power_off_phy(struct pcie_port *pp)
|
||||
static void exynos_pcie_power_off_phy(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
|
||||
val |= PCIE_PHY_COMMON_PD_CMN;
|
||||
|
@ -265,10 +257,8 @@ static void exynos_pcie_power_off_phy(struct pcie_port *pp)
|
|||
exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
|
||||
}
|
||||
|
||||
static void exynos_pcie_init_phy(struct pcie_port *pp)
|
||||
static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
/* DCC feedback control off */
|
||||
exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK);
|
||||
|
||||
|
@ -305,51 +295,41 @@ static void exynos_pcie_init_phy(struct pcie_port *pp)
|
|||
exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC);
|
||||
}
|
||||
|
||||
static void exynos_pcie_assert_reset(struct pcie_port *pp)
|
||||
static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
struct pcie_port *pp = &exynos_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
|
||||
if (exynos_pcie->reset_gpio >= 0)
|
||||
devm_gpio_request_one(pp->dev, exynos_pcie->reset_gpio,
|
||||
devm_gpio_request_one(dev, exynos_pcie->reset_gpio,
|
||||
GPIOF_OUT_INIT_HIGH, "RESET");
|
||||
}
|
||||
|
||||
static int exynos_pcie_establish_link(struct pcie_port *pp)
|
||||
static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
struct pcie_port *pp = &exynos_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 val;
|
||||
|
||||
if (dw_pcie_link_up(pp)) {
|
||||
dev_err(pp->dev, "Link already up\n");
|
||||
dev_err(dev, "Link already up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* assert reset signals */
|
||||
exynos_pcie_assert_core_reset(pp);
|
||||
exynos_pcie_assert_phy_reset(pp);
|
||||
|
||||
/* de-assert phy reset */
|
||||
exynos_pcie_deassert_phy_reset(pp);
|
||||
|
||||
/* power on phy */
|
||||
exynos_pcie_power_on_phy(pp);
|
||||
|
||||
/* initialize phy */
|
||||
exynos_pcie_init_phy(pp);
|
||||
exynos_pcie_assert_core_reset(exynos_pcie);
|
||||
exynos_pcie_assert_phy_reset(exynos_pcie);
|
||||
exynos_pcie_deassert_phy_reset(exynos_pcie);
|
||||
exynos_pcie_power_on_phy(exynos_pcie);
|
||||
exynos_pcie_init_phy(exynos_pcie);
|
||||
|
||||
/* pulse for common reset */
|
||||
exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET);
|
||||
udelay(500);
|
||||
exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
|
||||
|
||||
/* de-assert core reset */
|
||||
exynos_pcie_deassert_core_reset(pp);
|
||||
|
||||
/* setup root complex */
|
||||
exynos_pcie_deassert_core_reset(exynos_pcie);
|
||||
dw_pcie_setup_rc(pp);
|
||||
|
||||
/* assert reset signal */
|
||||
exynos_pcie_assert_reset(pp);
|
||||
exynos_pcie_assert_reset(exynos_pcie);
|
||||
|
||||
/* assert LTSSM enable */
|
||||
exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE,
|
||||
|
@ -361,27 +341,23 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
|
|||
|
||||
while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) {
|
||||
val = exynos_blk_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED);
|
||||
dev_info(pp->dev, "PLL Locked: 0x%x\n", val);
|
||||
dev_info(dev, "PLL Locked: 0x%x\n", val);
|
||||
}
|
||||
/* power off phy */
|
||||
exynos_pcie_power_off_phy(pp);
|
||||
|
||||
exynos_pcie_power_off_phy(exynos_pcie);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp)
|
||||
static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE);
|
||||
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE);
|
||||
}
|
||||
|
||||
static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
|
||||
static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
/* enable INTX interrupt */
|
||||
val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
|
||||
|
@ -391,23 +367,24 @@ static void exynos_pcie_enable_irq_pulse(struct pcie_port *pp)
|
|||
|
||||
static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct exynos_pcie *exynos_pcie = arg;
|
||||
|
||||
exynos_pcie_clear_irq_pulse(pp);
|
||||
exynos_pcie_clear_irq_pulse(exynos_pcie);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct exynos_pcie *exynos_pcie = arg;
|
||||
struct pcie_port *pp = &exynos_pcie->pp;
|
||||
|
||||
return dw_handle_msi_irq(pp);
|
||||
}
|
||||
|
||||
static void exynos_pcie_msi_init(struct pcie_port *pp)
|
||||
static void exynos_pcie_msi_init(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &exynos_pcie->pp;
|
||||
u32 val;
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
dw_pcie_msi_init(pp);
|
||||
|
||||
|
@ -417,58 +394,64 @@ static void exynos_pcie_msi_init(struct pcie_port *pp)
|
|||
exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL);
|
||||
}
|
||||
|
||||
static void exynos_pcie_enable_interrupts(struct pcie_port *pp)
|
||||
static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
|
||||
{
|
||||
exynos_pcie_enable_irq_pulse(pp);
|
||||
exynos_pcie_enable_irq_pulse(exynos_pcie);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
exynos_pcie_msi_init(pp);
|
||||
exynos_pcie_msi_init(exynos_pcie);
|
||||
}
|
||||
|
||||
static inline u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
|
||||
static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
u32 val;
|
||||
|
||||
exynos_pcie_sideband_dbi_r_mode(pp, true);
|
||||
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
|
||||
val = readl(pp->dbi_base + reg);
|
||||
exynos_pcie_sideband_dbi_r_mode(pp, false);
|
||||
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
|
||||
static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
|
||||
{
|
||||
exynos_pcie_sideband_dbi_w_mode(pp, true);
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
|
||||
writel(val, pp->dbi_base + reg);
|
||||
exynos_pcie_sideband_dbi_w_mode(pp, false);
|
||||
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
|
||||
}
|
||||
|
||||
static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
|
||||
u32 *val)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
int ret;
|
||||
|
||||
exynos_pcie_sideband_dbi_r_mode(pp, true);
|
||||
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
|
||||
ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
|
||||
exynos_pcie_sideband_dbi_r_mode(pp, false);
|
||||
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
|
||||
u32 val)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
int ret;
|
||||
|
||||
exynos_pcie_sideband_dbi_w_mode(pp, true);
|
||||
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
|
||||
ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
|
||||
exynos_pcie_sideband_dbi_w_mode(pp, false);
|
||||
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
u32 val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
|
||||
u32 val;
|
||||
|
||||
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
|
||||
if (val == PCIE_ELBI_LTSSM_ENABLE)
|
||||
return 1;
|
||||
|
||||
|
@ -477,8 +460,10 @@ static int exynos_pcie_link_up(struct pcie_port *pp)
|
|||
|
||||
static void exynos_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
exynos_pcie_establish_link(pp);
|
||||
exynos_pcie_enable_interrupts(pp);
|
||||
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
|
||||
|
||||
exynos_pcie_establish_link(exynos_pcie);
|
||||
exynos_pcie_enable_interrupts(exynos_pcie);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops exynos_pcie_host_ops = {
|
||||
|
@ -490,36 +475,38 @@ static struct pcie_host_ops exynos_pcie_host_ops = {
|
|||
.host_init = exynos_pcie_host_init,
|
||||
};
|
||||
|
||||
static int __init exynos_add_pcie_port(struct pcie_port *pp,
|
||||
static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct pcie_port *pp = &exynos_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
|
||||
pp->irq = platform_get_irq(pdev, 1);
|
||||
if (!pp->irq) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
dev_err(dev, "failed to get irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = devm_request_irq(&pdev->dev, pp->irq, exynos_pcie_irq_handler,
|
||||
IRQF_SHARED, "exynos-pcie", pp);
|
||||
ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler,
|
||||
IRQF_SHARED, "exynos-pcie", exynos_pcie);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
dev_err(dev, "failed to request irq\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
pp->msi_irq = platform_get_irq(pdev, 0);
|
||||
if (!pp->msi_irq) {
|
||||
dev_err(&pdev->dev, "failed to get msi irq\n");
|
||||
dev_err(dev, "failed to get msi irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
|
||||
ret = devm_request_irq(dev, pp->msi_irq,
|
||||
exynos_pcie_msi_irq_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"exynos-pcie", pp);
|
||||
"exynos-pcie", exynos_pcie);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request msi irq\n");
|
||||
dev_err(dev, "failed to request msi irq\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +516,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -538,37 +525,36 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int __init exynos_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct exynos_pcie *exynos_pcie;
|
||||
struct pcie_port *pp;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct resource *elbi_base;
|
||||
struct resource *phy_base;
|
||||
struct resource *block_base;
|
||||
int ret;
|
||||
|
||||
exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),
|
||||
GFP_KERNEL);
|
||||
exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
|
||||
if (!exynos_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &exynos_pcie->pp;
|
||||
|
||||
pp->dev = &pdev->dev;
|
||||
pp->dev = dev;
|
||||
|
||||
exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
|
||||
|
||||
exynos_pcie->clk = devm_clk_get(&pdev->dev, "pcie");
|
||||
exynos_pcie->clk = devm_clk_get(dev, "pcie");
|
||||
if (IS_ERR(exynos_pcie->clk)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie rc clock\n");
|
||||
dev_err(dev, "Failed to get pcie rc clock\n");
|
||||
return PTR_ERR(exynos_pcie->clk);
|
||||
}
|
||||
ret = clk_prepare_enable(exynos_pcie->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
exynos_pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus");
|
||||
exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
|
||||
if (IS_ERR(exynos_pcie->bus_clk)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie bus clock\n");
|
||||
dev_err(dev, "Failed to get pcie bus clock\n");
|
||||
ret = PTR_ERR(exynos_pcie->bus_clk);
|
||||
goto fail_clk;
|
||||
}
|
||||
|
@ -577,27 +563,27 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
|
|||
goto fail_clk;
|
||||
|
||||
elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base);
|
||||
exynos_pcie->elbi_base = devm_ioremap_resource(dev, elbi_base);
|
||||
if (IS_ERR(exynos_pcie->elbi_base)) {
|
||||
ret = PTR_ERR(exynos_pcie->elbi_base);
|
||||
goto fail_bus_clk;
|
||||
}
|
||||
|
||||
phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
exynos_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base);
|
||||
exynos_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
|
||||
if (IS_ERR(exynos_pcie->phy_base)) {
|
||||
ret = PTR_ERR(exynos_pcie->phy_base);
|
||||
goto fail_bus_clk;
|
||||
}
|
||||
|
||||
block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||
exynos_pcie->block_base = devm_ioremap_resource(&pdev->dev, block_base);
|
||||
exynos_pcie->block_base = devm_ioremap_resource(dev, block_base);
|
||||
if (IS_ERR(exynos_pcie->block_base)) {
|
||||
ret = PTR_ERR(exynos_pcie->block_base);
|
||||
goto fail_bus_clk;
|
||||
}
|
||||
|
||||
ret = exynos_add_pcie_port(pp, pdev);
|
||||
ret = exynos_add_pcie_port(exynos_pcie, pdev);
|
||||
if (ret < 0)
|
||||
goto fail_bus_clk;
|
||||
|
||||
|
|
|
@ -39,16 +39,15 @@ enum imx6_pcie_variants {
|
|||
};
|
||||
|
||||
struct imx6_pcie {
|
||||
struct pcie_port pp; /* pp.dbi_base is DT 0th resource */
|
||||
int reset_gpio;
|
||||
bool gpio_active_high;
|
||||
struct clk *pcie_bus;
|
||||
struct clk *pcie_phy;
|
||||
struct clk *pcie_inbound_axi;
|
||||
struct clk *pcie;
|
||||
struct pcie_port pp;
|
||||
struct regmap *iomuxc_gpr;
|
||||
enum imx6_pcie_variants variant;
|
||||
void __iomem *mem_base;
|
||||
u32 tx_deemph_gen1;
|
||||
u32 tx_deemph_gen2_3p5db;
|
||||
u32 tx_deemph_gen2_6db;
|
||||
|
@ -96,14 +95,15 @@ struct imx6_pcie {
|
|||
#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
|
||||
#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
|
||||
|
||||
static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
|
||||
static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
u32 val;
|
||||
u32 max_iterations = 10;
|
||||
u32 wait_counter = 0;
|
||||
|
||||
do {
|
||||
val = readl(dbi_base + PCIE_PHY_STAT);
|
||||
val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT);
|
||||
val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
|
||||
wait_counter++;
|
||||
|
||||
|
@ -116,123 +116,126 @@ static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr)
|
||||
static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
val = addr << PCIE_PHY_CTRL_DATA_LOC;
|
||||
writel(val, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
|
||||
|
||||
val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
|
||||
writel(val, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
|
||||
|
||||
ret = pcie_phy_poll_ack(dbi_base, 1);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = addr << PCIE_PHY_CTRL_DATA_LOC;
|
||||
writel(val, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
|
||||
|
||||
return pcie_phy_poll_ack(dbi_base, 0);
|
||||
return pcie_phy_poll_ack(imx6_pcie, 0);
|
||||
}
|
||||
|
||||
/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
|
||||
static int pcie_phy_read(void __iomem *dbi_base, int addr, int *data)
|
||||
static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
u32 val, phy_ctl;
|
||||
int ret;
|
||||
|
||||
ret = pcie_phy_wait_ack(dbi_base, addr);
|
||||
ret = pcie_phy_wait_ack(imx6_pcie, addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* assert Read signal */
|
||||
phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
|
||||
writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, phy_ctl);
|
||||
|
||||
ret = pcie_phy_poll_ack(dbi_base, 1);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = readl(dbi_base + PCIE_PHY_STAT);
|
||||
val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT);
|
||||
*data = val & 0xffff;
|
||||
|
||||
/* deassert Read signal */
|
||||
writel(0x00, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x00);
|
||||
|
||||
return pcie_phy_poll_ack(dbi_base, 0);
|
||||
return pcie_phy_poll_ack(imx6_pcie, 0);
|
||||
}
|
||||
|
||||
static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
|
||||
static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
u32 var;
|
||||
int ret;
|
||||
|
||||
/* write addr */
|
||||
/* cap addr */
|
||||
ret = pcie_phy_wait_ack(dbi_base, addr);
|
||||
ret = pcie_phy_wait_ack(imx6_pcie, addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
var = data << PCIE_PHY_CTRL_DATA_LOC;
|
||||
writel(var, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
|
||||
|
||||
/* capture data */
|
||||
var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
|
||||
writel(var, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
|
||||
|
||||
ret = pcie_phy_poll_ack(dbi_base, 1);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* deassert cap data */
|
||||
var = data << PCIE_PHY_CTRL_DATA_LOC;
|
||||
writel(var, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
|
||||
|
||||
/* wait for ack de-assertion */
|
||||
ret = pcie_phy_poll_ack(dbi_base, 0);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* assert wr signal */
|
||||
var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
|
||||
writel(var, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
|
||||
|
||||
/* wait for ack */
|
||||
ret = pcie_phy_poll_ack(dbi_base, 1);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* deassert wr signal */
|
||||
var = data << PCIE_PHY_CTRL_DATA_LOC;
|
||||
writel(var, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
|
||||
|
||||
/* wait for ack de-assertion */
|
||||
ret = pcie_phy_poll_ack(dbi_base, 0);
|
||||
ret = pcie_phy_poll_ack(imx6_pcie, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
writel(0x0, dbi_base + PCIE_PHY_CTRL);
|
||||
dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx6_pcie_reset_phy(struct pcie_port *pp)
|
||||
static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
|
||||
pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
|
||||
tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
|
||||
PHY_RX_OVRD_IN_LO_RX_PLL_EN);
|
||||
pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
|
||||
pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
|
||||
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
|
||||
pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
|
||||
tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
|
||||
PHY_RX_OVRD_IN_LO_RX_PLL_EN);
|
||||
pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
|
||||
pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
|
||||
}
|
||||
|
||||
/* Added for PCI abort handling */
|
||||
|
@ -242,9 +245,9 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
|
||||
static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
u32 val, gpr1, gpr12;
|
||||
|
||||
switch (imx6_pcie->variant) {
|
||||
|
@ -281,10 +284,10 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
|
|||
|
||||
if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
|
||||
(gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
|
||||
val = readl(pp->dbi_base + PCIE_PL_PFLR);
|
||||
val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR);
|
||||
val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
|
||||
val |= PCIE_PL_PFLR_FORCE_LINK;
|
||||
writel(val, pp->dbi_base + PCIE_PL_PFLR);
|
||||
dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val);
|
||||
|
||||
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
|
||||
|
@ -296,20 +299,19 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
|
|||
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret = 0;
|
||||
|
||||
switch (imx6_pcie->variant) {
|
||||
case IMX6SX:
|
||||
ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "unable to enable pcie_axi clock\n");
|
||||
dev_err(dev, "unable to enable pcie_axi clock\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -336,32 +338,33 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
|
||||
static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(imx6_pcie->pcie_phy);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "unable to enable pcie_phy clock\n");
|
||||
goto err_pcie_phy;
|
||||
dev_err(dev, "unable to enable pcie_phy clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(imx6_pcie->pcie_bus);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "unable to enable pcie_bus clock\n");
|
||||
dev_err(dev, "unable to enable pcie_bus clock\n");
|
||||
goto err_pcie_bus;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(imx6_pcie->pcie);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "unable to enable pcie clock\n");
|
||||
dev_err(dev, "unable to enable pcie clock\n");
|
||||
goto err_pcie;
|
||||
}
|
||||
|
||||
ret = imx6_pcie_enable_ref_clk(imx6_pcie);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "unable to enable pcie ref clock\n");
|
||||
dev_err(dev, "unable to enable pcie ref clock\n");
|
||||
goto err_ref_clk;
|
||||
}
|
||||
|
||||
|
@ -392,7 +395,7 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
|
|||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
err_ref_clk:
|
||||
clk_disable_unprepare(imx6_pcie->pcie);
|
||||
|
@ -400,14 +403,10 @@ err_pcie:
|
|||
clk_disable_unprepare(imx6_pcie->pcie_bus);
|
||||
err_pcie_bus:
|
||||
clk_disable_unprepare(imx6_pcie->pcie_phy);
|
||||
err_pcie_phy:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void imx6_pcie_init_phy(struct pcie_port *pp)
|
||||
static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
|
||||
|
||||
if (imx6_pcie->variant == IMX6SX)
|
||||
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6SX_GPR12_PCIE_RX_EQ_MASK,
|
||||
|
@ -439,45 +438,52 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
|
|||
imx6_pcie->tx_swing_low << 25);
|
||||
}
|
||||
|
||||
static int imx6_pcie_wait_for_link(struct pcie_port *pp)
|
||||
static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
|
||||
/* check if the link is up or not */
|
||||
if (!dw_pcie_wait_for_link(pp))
|
||||
return 0;
|
||||
|
||||
dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
|
||||
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));
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp)
|
||||
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;
|
||||
u32 tmp;
|
||||
unsigned int retries;
|
||||
|
||||
for (retries = 0; retries < 200; retries++) {
|
||||
tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
/* Test if the speed change finished. */
|
||||
if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
|
||||
return 0;
|
||||
usleep_range(100, 1000);
|
||||
}
|
||||
|
||||
dev_err(pp->dev, "Speed change timeout\n");
|
||||
dev_err(dev, "Speed change timeout\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct imx6_pcie *imx6_pcie = arg;
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
|
||||
return dw_handle_msi_irq(pp);
|
||||
}
|
||||
|
||||
static int imx6_pcie_establish_link(struct pcie_port *pp)
|
||||
static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
|
||||
{
|
||||
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
|
||||
struct pcie_port *pp = &imx6_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
|
@ -486,76 +492,73 @@ static int imx6_pcie_establish_link(struct pcie_port *pp)
|
|||
* 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 = readl(pp->dbi_base + PCIE_RC_LCR);
|
||||
tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
|
||||
tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
|
||||
tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
|
||||
writel(tmp, pp->dbi_base + PCIE_RC_LCR);
|
||||
dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
|
||||
|
||||
/* Start LTSSM. */
|
||||
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
|
||||
|
||||
ret = imx6_pcie_wait_for_link(pp);
|
||||
ret = imx6_pcie_wait_for_link(imx6_pcie);
|
||||
if (ret) {
|
||||
dev_info(pp->dev, "Link never came up\n");
|
||||
dev_info(dev, "Link never came up\n");
|
||||
goto err_reset_phy;
|
||||
}
|
||||
|
||||
if (imx6_pcie->link_gen == 2) {
|
||||
/* Allow Gen2 mode after the link is up. */
|
||||
tmp = readl(pp->dbi_base + PCIE_RC_LCR);
|
||||
tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
|
||||
tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
|
||||
tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
|
||||
writel(tmp, pp->dbi_base + PCIE_RC_LCR);
|
||||
dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
|
||||
} else {
|
||||
dev_info(pp->dev, "Link: Gen2 disabled\n");
|
||||
dev_info(dev, "Link: Gen2 disabled\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Start Directed Speed Change so the best possible speed both link
|
||||
* partners support can be negotiated.
|
||||
*/
|
||||
tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
tmp |= PORT_LOGIC_SPEED_CHANGE;
|
||||
writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||
dw_pcie_writel_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
|
||||
|
||||
ret = imx6_pcie_wait_for_speed_change(pp);
|
||||
ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "Failed to bring link up!\n");
|
||||
dev_err(dev, "Failed to bring link up!\n");
|
||||
goto err_reset_phy;
|
||||
}
|
||||
|
||||
/* Make sure link training is finished as well! */
|
||||
ret = imx6_pcie_wait_for_link(pp);
|
||||
ret = imx6_pcie_wait_for_link(imx6_pcie);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "Failed to bring link up!\n");
|
||||
dev_err(dev, "Failed to bring link up!\n");
|
||||
goto err_reset_phy;
|
||||
}
|
||||
|
||||
tmp = readl(pp->dbi_base + PCIE_RC_LCSR);
|
||||
dev_info(pp->dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
|
||||
tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCSR);
|
||||
dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
|
||||
return 0;
|
||||
|
||||
err_reset_phy:
|
||||
dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
|
||||
imx6_pcie_reset_phy(pp);
|
||||
|
||||
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));
|
||||
imx6_pcie_reset_phy(imx6_pcie);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void imx6_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
imx6_pcie_assert_core_reset(pp);
|
||||
|
||||
imx6_pcie_init_phy(pp);
|
||||
|
||||
imx6_pcie_deassert_core_reset(pp);
|
||||
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
|
||||
|
||||
imx6_pcie_assert_core_reset(imx6_pcie);
|
||||
imx6_pcie_init_phy(imx6_pcie);
|
||||
imx6_pcie_deassert_core_reset(imx6_pcie);
|
||||
dw_pcie_setup_rc(pp);
|
||||
|
||||
imx6_pcie_establish_link(pp);
|
||||
imx6_pcie_establish_link(imx6_pcie);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
dw_pcie_msi_init(pp);
|
||||
|
@ -563,7 +566,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
|
|||
|
||||
static int imx6_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
return readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) &
|
||||
return dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1) &
|
||||
PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
|
||||
}
|
||||
|
||||
|
@ -572,24 +575,26 @@ static struct pcie_host_ops imx6_pcie_host_ops = {
|
|||
.host_init = imx6_pcie_host_init,
|
||||
};
|
||||
|
||||
static int __init imx6_add_pcie_port(struct pcie_port *pp,
|
||||
struct platform_device *pdev)
|
||||
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;
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
|
||||
if (pp->msi_irq <= 0) {
|
||||
dev_err(&pdev->dev, "failed to get MSI irq\n");
|
||||
dev_err(dev, "failed to get MSI irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
|
||||
ret = devm_request_irq(dev, pp->msi_irq,
|
||||
imx6_pcie_msi_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"mx6-pcie-msi", pp);
|
||||
"mx6-pcie-msi", imx6_pcie);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request MSI irq\n");
|
||||
dev_err(dev, "failed to request MSI irq\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +604,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -608,75 +613,72 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int __init imx6_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct imx6_pcie *imx6_pcie;
|
||||
struct pcie_port *pp;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *dbi_base;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device_node *node = dev->of_node;
|
||||
int ret;
|
||||
|
||||
imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
|
||||
imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
|
||||
if (!imx6_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &imx6_pcie->pp;
|
||||
pp->dev = &pdev->dev;
|
||||
pp->dev = dev;
|
||||
|
||||
imx6_pcie->variant =
|
||||
(enum imx6_pcie_variants)of_device_get_match_data(&pdev->dev);
|
||||
(enum imx6_pcie_variants)of_device_get_match_data(dev);
|
||||
|
||||
/* Added for PCI abort handling */
|
||||
hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
|
||||
"imprecise external abort");
|
||||
|
||||
dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
|
||||
pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
|
||||
if (IS_ERR(pp->dbi_base))
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
|
||||
/* Fetch GPIOs */
|
||||
imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
|
||||
imx6_pcie->gpio_active_high = of_property_read_bool(np,
|
||||
imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
|
||||
imx6_pcie->gpio_active_high = of_property_read_bool(node,
|
||||
"reset-gpio-active-high");
|
||||
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
|
||||
ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio,
|
||||
ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
|
||||
imx6_pcie->gpio_active_high ?
|
||||
GPIOF_OUT_INIT_HIGH :
|
||||
GPIOF_OUT_INIT_LOW,
|
||||
"PCIe reset");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to get reset gpio\n");
|
||||
dev_err(dev, "unable to get reset gpio\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch clocks */
|
||||
imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy");
|
||||
imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
|
||||
if (IS_ERR(imx6_pcie->pcie_phy)) {
|
||||
dev_err(&pdev->dev,
|
||||
"pcie_phy clock source missing or invalid\n");
|
||||
dev_err(dev, "pcie_phy clock source missing or invalid\n");
|
||||
return PTR_ERR(imx6_pcie->pcie_phy);
|
||||
}
|
||||
|
||||
imx6_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_bus");
|
||||
imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
|
||||
if (IS_ERR(imx6_pcie->pcie_bus)) {
|
||||
dev_err(&pdev->dev,
|
||||
"pcie_bus clock source missing or invalid\n");
|
||||
dev_err(dev, "pcie_bus clock source missing or invalid\n");
|
||||
return PTR_ERR(imx6_pcie->pcie_bus);
|
||||
}
|
||||
|
||||
imx6_pcie->pcie = devm_clk_get(&pdev->dev, "pcie");
|
||||
imx6_pcie->pcie = devm_clk_get(dev, "pcie");
|
||||
if (IS_ERR(imx6_pcie->pcie)) {
|
||||
dev_err(&pdev->dev,
|
||||
"pcie clock source missing or invalid\n");
|
||||
dev_err(dev, "pcie clock source missing or invalid\n");
|
||||
return PTR_ERR(imx6_pcie->pcie);
|
||||
}
|
||||
|
||||
if (imx6_pcie->variant == IMX6SX) {
|
||||
imx6_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev,
|
||||
imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
|
||||
"pcie_inbound_axi");
|
||||
if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
|
||||
dev_err(&pdev->dev,
|
||||
dev_err(dev,
|
||||
"pcie_incbound_axi clock missing or invalid\n");
|
||||
return PTR_ERR(imx6_pcie->pcie_inbound_axi);
|
||||
}
|
||||
|
@ -686,7 +688,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
|
|||
imx6_pcie->iomuxc_gpr =
|
||||
syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
|
||||
if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
|
||||
dev_err(&pdev->dev, "unable to find iomuxc registers\n");
|
||||
dev_err(dev, "unable to find iomuxc registers\n");
|
||||
return PTR_ERR(imx6_pcie->iomuxc_gpr);
|
||||
}
|
||||
|
||||
|
@ -712,12 +714,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
|
|||
imx6_pcie->tx_swing_low = 127;
|
||||
|
||||
/* Limit link speed */
|
||||
ret = of_property_read_u32(pp->dev->of_node, "fsl,max-link-speed",
|
||||
ret = of_property_read_u32(node, "fsl,max-link-speed",
|
||||
&imx6_pcie->link_gen);
|
||||
if (ret)
|
||||
imx6_pcie->link_gen = 1;
|
||||
|
||||
ret = imx6_add_pcie_port(pp, pdev);
|
||||
ret = imx6_add_pcie_port(imx6_pcie, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -730,7 +732,7 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
|
|||
struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
|
||||
|
||||
/* bring down link, so bootloader gets clean state in case of reboot */
|
||||
imx6_pcie_assert_core_reset(&imx6_pcie->pp);
|
||||
imx6_pcie_assert_core_reset(imx6_pcie);
|
||||
}
|
||||
|
||||
static const struct of_device_id imx6_pcie_of_match[] = {
|
||||
|
|
|
@ -88,13 +88,24 @@ phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
|
|||
return ks_pcie->app.start + MSI_IRQ;
|
||||
}
|
||||
|
||||
static u32 ks_dw_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
|
||||
{
|
||||
return readl(ks_pcie->va_app_base + offset);
|
||||
}
|
||||
|
||||
static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
|
||||
{
|
||||
writel(val, ks_pcie->va_app_base + offset);
|
||||
}
|
||||
|
||||
void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
|
||||
{
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 pending, vector;
|
||||
int src, virq;
|
||||
|
||||
pending = readl(ks_pcie->va_app_base + MSI0_IRQ_STATUS + (offset << 4));
|
||||
pending = ks_dw_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
|
||||
|
||||
/*
|
||||
* MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
|
||||
|
@ -104,7 +115,7 @@ void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
|
|||
if (BIT(src) & pending) {
|
||||
vector = offset + (src << 3);
|
||||
virq = irq_linear_revmap(pp->irq_domain, vector);
|
||||
dev_dbg(pp->dev, "irq: bit %d, vector %d, virq %d\n",
|
||||
dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
|
||||
src, vector, virq);
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
|
@ -124,9 +135,9 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
|
|||
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
|
||||
update_reg_offset_bit_pos(offset, ®_offset, &bit_pos);
|
||||
|
||||
writel(BIT(bit_pos),
|
||||
ks_pcie->va_app_base + MSI0_IRQ_STATUS + (reg_offset << 4));
|
||||
writel(reg_offset + MSI_IRQ_OFFSET, ks_pcie->va_app_base + IRQ_EOI);
|
||||
ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
|
||||
BIT(bit_pos));
|
||||
ks_dw_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
|
||||
}
|
||||
|
||||
void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
|
||||
|
@ -135,8 +146,8 @@ void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
|
|||
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
|
||||
|
||||
update_reg_offset_bit_pos(irq, ®_offset, &bit_pos);
|
||||
writel(BIT(bit_pos),
|
||||
ks_pcie->va_app_base + MSI0_IRQ_ENABLE_SET + (reg_offset << 4));
|
||||
ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
|
||||
BIT(bit_pos));
|
||||
}
|
||||
|
||||
void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
|
||||
|
@ -145,8 +156,8 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
|
|||
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
|
||||
|
||||
update_reg_offset_bit_pos(irq, ®_offset, &bit_pos);
|
||||
writel(BIT(bit_pos),
|
||||
ks_pcie->va_app_base + MSI0_IRQ_ENABLE_CLR + (reg_offset << 4));
|
||||
ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
|
||||
BIT(bit_pos));
|
||||
}
|
||||
|
||||
static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
|
||||
|
@ -215,6 +226,7 @@ static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
|
|||
int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
|
||||
{
|
||||
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
|
||||
struct device *dev = pp->dev;
|
||||
int i;
|
||||
|
||||
pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
|
||||
|
@ -222,7 +234,7 @@ int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
|
|||
&ks_dw_pcie_msi_domain_ops,
|
||||
chip);
|
||||
if (!pp->irq_domain) {
|
||||
dev_err(pp->dev, "irq domain init failed\n");
|
||||
dev_err(dev, "irq domain init failed\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
@ -237,47 +249,47 @@ void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < MAX_LEGACY_IRQS; i++)
|
||||
writel(0x1, ks_pcie->va_app_base + IRQ_ENABLE_SET + (i << 4));
|
||||
ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
|
||||
}
|
||||
|
||||
void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
|
||||
{
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 pending;
|
||||
int virq;
|
||||
|
||||
pending = readl(ks_pcie->va_app_base + IRQ_STATUS + (offset << 4));
|
||||
pending = ks_dw_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
|
||||
|
||||
if (BIT(0) & pending) {
|
||||
virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
|
||||
dev_dbg(pp->dev, ": irq: irq_offset %d, virq %d\n", offset,
|
||||
virq);
|
||||
dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
|
||||
generic_handle_irq(virq);
|
||||
}
|
||||
|
||||
/* EOI the INTx interrupt */
|
||||
writel(offset, ks_pcie->va_app_base + IRQ_EOI);
|
||||
ks_dw_app_writel(ks_pcie, IRQ_EOI, offset);
|
||||
}
|
||||
|
||||
void ks_dw_pcie_enable_error_irq(void __iomem *reg_base)
|
||||
void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
writel(ERR_IRQ_ALL, reg_base + ERR_IRQ_ENABLE_SET);
|
||||
ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
|
||||
}
|
||||
|
||||
irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev,
|
||||
void __iomem *reg_base)
|
||||
irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
status = readl(reg_base + ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
|
||||
status = ks_dw_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (status & ERR_FATAL_IRQ)
|
||||
dev_err(dev, "fatal error (status %#010x)\n", status);
|
||||
dev_err(ks_pcie->pp.dev, "fatal error (status %#010x)\n",
|
||||
status);
|
||||
|
||||
/* Ack the IRQ; status bits are RW1C */
|
||||
writel(status, reg_base + ERR_IRQ_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -322,15 +334,15 @@ static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domain_ops = {
|
|||
* Since modification of dbi_cs2 involves different clock domain, read the
|
||||
* status back to ensure the transition is complete.
|
||||
*/
|
||||
static void ks_dw_pcie_set_dbi_mode(void __iomem *reg_virt)
|
||||
static void ks_dw_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
writel(DBI_CS2_EN_VAL | readl(reg_virt + CMD_STATUS),
|
||||
reg_virt + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
|
||||
|
||||
do {
|
||||
val = readl(reg_virt + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
} while (!(val & DBI_CS2_EN_VAL));
|
||||
}
|
||||
|
||||
|
@ -340,15 +352,15 @@ static void ks_dw_pcie_set_dbi_mode(void __iomem *reg_virt)
|
|||
* Since modification of dbi_cs2 involves different clock domain, read the
|
||||
* status back to ensure the transition is complete.
|
||||
*/
|
||||
static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
|
||||
static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
writel(~DBI_CS2_EN_VAL & readl(reg_virt + CMD_STATUS),
|
||||
reg_virt + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
|
||||
|
||||
do {
|
||||
val = readl(reg_virt + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
} while (val & DBI_CS2_EN_VAL);
|
||||
}
|
||||
|
||||
|
@ -357,28 +369,29 @@ void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
|
|||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
u32 start = pp->mem->start, end = pp->mem->end;
|
||||
int i, tr_size;
|
||||
u32 val;
|
||||
|
||||
/* Disable BARs for inbound access */
|
||||
ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
|
||||
writel(0, pp->dbi_base + PCI_BASE_ADDRESS_0);
|
||||
writel(0, pp->dbi_base + PCI_BASE_ADDRESS_1);
|
||||
ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
|
||||
ks_dw_pcie_set_dbi_mode(ks_pcie);
|
||||
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 0);
|
||||
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_1, 0);
|
||||
ks_dw_pcie_clear_dbi_mode(ks_pcie);
|
||||
|
||||
/* Set outbound translation size per window division */
|
||||
writel(CFG_PCIM_WIN_SZ_IDX & 0x7, ks_pcie->va_app_base + OB_SIZE);
|
||||
ks_dw_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
|
||||
|
||||
tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
|
||||
|
||||
/* Using Direct 1:1 mapping of RC <-> PCI memory space */
|
||||
for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
|
||||
writel(start | 1, ks_pcie->va_app_base + OB_OFFSET_INDEX(i));
|
||||
writel(0, ks_pcie->va_app_base + OB_OFFSET_HI(i));
|
||||
ks_dw_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
|
||||
ks_dw_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
|
||||
start += tr_size;
|
||||
}
|
||||
|
||||
/* Enable OB translation */
|
||||
writel(OB_XLAT_EN_VAL | readl(ks_pcie->va_app_base + CMD_STATUS),
|
||||
ks_pcie->va_app_base + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,7 +431,7 @@ static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
|
|||
if (bus != 1)
|
||||
regval |= BIT(24);
|
||||
|
||||
writel(regval, ks_pcie->va_app_base + CFG_SETUP);
|
||||
ks_dw_app_writel(ks_pcie, CFG_SETUP, regval);
|
||||
return pp->va_cfg0_base;
|
||||
}
|
||||
|
||||
|
@ -456,19 +469,19 @@ void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
|
|||
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
|
||||
|
||||
/* Configure and set up BAR0 */
|
||||
ks_dw_pcie_set_dbi_mode(ks_pcie->va_app_base);
|
||||
ks_dw_pcie_set_dbi_mode(ks_pcie);
|
||||
|
||||
/* Enable BAR0 */
|
||||
writel(1, pp->dbi_base + PCI_BASE_ADDRESS_0);
|
||||
writel(SZ_4K - 1, pp->dbi_base + PCI_BASE_ADDRESS_0);
|
||||
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 1);
|
||||
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, SZ_4K - 1);
|
||||
|
||||
ks_dw_pcie_clear_dbi_mode(ks_pcie->va_app_base);
|
||||
ks_dw_pcie_clear_dbi_mode(ks_pcie);
|
||||
|
||||
/*
|
||||
* For BAR0, just setting bus address for inbound writes (MSI) should
|
||||
* be sufficient. Use physical address to avoid any conflicts.
|
||||
*/
|
||||
writel(ks_pcie->app.start, pp->dbi_base + PCI_BASE_ADDRESS_0);
|
||||
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -476,8 +489,9 @@ void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
|
|||
*/
|
||||
int ks_dw_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
u32 val = readl(pp->dbi_base + DEBUG0);
|
||||
u32 val;
|
||||
|
||||
val = dw_pcie_readl_rc(pp, DEBUG0);
|
||||
return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
|
||||
}
|
||||
|
||||
|
@ -486,13 +500,13 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
|
|||
u32 val;
|
||||
|
||||
/* Disable Link training */
|
||||
val = readl(ks_pcie->va_app_base + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
val &= ~LTSSM_EN_VAL;
|
||||
writel(LTSSM_EN_VAL | val, ks_pcie->va_app_base + CMD_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
|
||||
|
||||
/* Initiate Link Training */
|
||||
val = readl(ks_pcie->va_app_base + CMD_STATUS);
|
||||
writel(LTSSM_EN_VAL | val, ks_pcie->va_app_base + CMD_STATUS);
|
||||
val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
|
||||
ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,12 +520,13 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
|
|||
struct device_node *msi_intc_np)
|
||||
{
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct platform_device *pdev = to_platform_device(pp->dev);
|
||||
struct device *dev = pp->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *res;
|
||||
|
||||
/* Index 0 is the config reg. space address */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pp->dbi_base = devm_ioremap_resource(pp->dev, res);
|
||||
pp->dbi_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pp->dbi_base))
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
|
||||
|
@ -524,7 +539,7 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
|
|||
|
||||
/* Index 1 is the application reg. space address */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
ks_pcie->va_app_base = devm_ioremap_resource(pp->dev, res);
|
||||
ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(ks_pcie->va_app_base))
|
||||
return PTR_ERR(ks_pcie->va_app_base);
|
||||
|
||||
|
@ -537,7 +552,7 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
|
|||
&ks_dw_pcie_legacy_irq_domain_ops,
|
||||
NULL);
|
||||
if (!ks_pcie->legacy_irq_domain) {
|
||||
dev_err(pp->dev, "Failed to add irq domain for legacy irqs\n");
|
||||
dev_err(dev, "Failed to add irq domain for legacy irqs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,12 +89,13 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
|
|||
static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
unsigned int retries;
|
||||
|
||||
dw_pcie_setup_rc(pp);
|
||||
|
||||
if (dw_pcie_link_up(pp)) {
|
||||
dev_err(pp->dev, "Link already up\n");
|
||||
dev_err(dev, "Link already up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
|
|||
return 0;
|
||||
}
|
||||
|
||||
dev_err(pp->dev, "phy link never came up\n");
|
||||
dev_err(dev, "phy link never came up\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -115,9 +116,10 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
|
|||
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
|
||||
u32 offset = irq - ks_pcie->msi_host_irqs[0];
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
|
||||
dev_dbg(pp->dev, "%s, irq %d\n", __func__, irq);
|
||||
dev_dbg(dev, "%s, irq %d\n", __func__, irq);
|
||||
|
||||
/*
|
||||
* The chained irq handler installation would have replaced normal
|
||||
|
@ -142,10 +144,11 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
|
|||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
|
||||
dev_dbg(pp->dev, ": Handling legacy irq %d\n", irq);
|
||||
dev_dbg(dev, ": Handling legacy irq %d\n", irq);
|
||||
|
||||
/*
|
||||
* The chained irq handler installation would have replaced normal
|
||||
|
@ -234,7 +237,7 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
|
|||
}
|
||||
|
||||
if (ks_pcie->error_irq > 0)
|
||||
ks_dw_pcie_enable_error_irq(ks_pcie->va_app_base);
|
||||
ks_dw_pcie_enable_error_irq(ks_pcie);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -302,14 +305,14 @@ static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
|
|||
{
|
||||
struct keystone_pcie *ks_pcie = priv;
|
||||
|
||||
return ks_dw_pcie_handle_error_irq(ks_pcie->pp.dev,
|
||||
ks_pcie->va_app_base);
|
||||
return ks_dw_pcie_handle_error_irq(ks_pcie);
|
||||
}
|
||||
|
||||
static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct pcie_port *pp = &ks_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
|
||||
ret = ks_pcie_get_irq_controller_info(ks_pcie,
|
||||
|
@ -332,12 +335,12 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
|
|||
*/
|
||||
ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
|
||||
if (ks_pcie->error_irq <= 0)
|
||||
dev_info(&pdev->dev, "no error IRQ defined\n");
|
||||
dev_info(dev, "no error IRQ defined\n");
|
||||
else {
|
||||
ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
|
||||
IRQF_SHARED, "pcie-error-irq", ks_pcie);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to request error IRQ %d\n",
|
||||
dev_err(dev, "failed to request error IRQ %d\n",
|
||||
ks_pcie->error_irq);
|
||||
return ret;
|
||||
}
|
||||
|
@ -347,7 +350,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
|
|||
pp->ops = &keystone_pcie_host_ops;
|
||||
ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -381,12 +384,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
|
|||
struct phy *phy;
|
||||
int ret;
|
||||
|
||||
ks_pcie = devm_kzalloc(&pdev->dev, sizeof(*ks_pcie),
|
||||
GFP_KERNEL);
|
||||
ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
|
||||
if (!ks_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &ks_pcie->pp;
|
||||
pp->dev = dev;
|
||||
|
||||
/* initialize SerDes Phy if present */
|
||||
phy = devm_phy_get(dev, "pcie-phy");
|
||||
|
@ -408,7 +411,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
|
|||
devm_iounmap(dev, reg_p);
|
||||
devm_release_mem_region(dev, res->start, resource_size(res));
|
||||
|
||||
pp->dev = dev;
|
||||
ks_pcie->np = dev->of_node;
|
||||
platform_set_drvdata(pdev, ks_pcie);
|
||||
ks_pcie->clk = devm_clk_get(dev, "pcie");
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#define MAX_LEGACY_HOST_IRQS 4
|
||||
|
||||
struct keystone_pcie {
|
||||
struct pcie_port pp; /* pp.dbi_base is DT 0th res */
|
||||
struct clk *clk;
|
||||
struct pcie_port pp;
|
||||
/* PCI Device ID */
|
||||
u32 device_id;
|
||||
int num_legacy_host_irqs;
|
||||
|
@ -34,7 +34,7 @@ struct keystone_pcie {
|
|||
int error_irq;
|
||||
|
||||
/* Application register space */
|
||||
void __iomem *va_app_base;
|
||||
void __iomem *va_app_base; /* DT 1st resource */
|
||||
struct resource app;
|
||||
};
|
||||
|
||||
|
@ -45,9 +45,8 @@ phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
|
|||
/* Keystone specific PCI controller APIs */
|
||||
void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
|
||||
void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
|
||||
void ks_dw_pcie_enable_error_irq(void __iomem *reg_base);
|
||||
irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev,
|
||||
void __iomem *reg_base);
|
||||
void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie);
|
||||
irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie);
|
||||
int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
|
||||
struct device_node *msi_intc_np);
|
||||
int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
|
||||
|
|
|
@ -45,10 +45,9 @@ struct ls_pcie_drvdata {
|
|||
};
|
||||
|
||||
struct ls_pcie {
|
||||
void __iomem *dbi;
|
||||
struct pcie_port pp; /* pp.dbi_base is DT regs */
|
||||
void __iomem *lut;
|
||||
struct regmap *scfg;
|
||||
struct pcie_port pp;
|
||||
const struct ls_pcie_drvdata *drvdata;
|
||||
int index;
|
||||
};
|
||||
|
@ -59,7 +58,7 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
|
|||
{
|
||||
u32 header_type;
|
||||
|
||||
header_type = ioread8(pcie->dbi + PCI_HEADER_TYPE);
|
||||
header_type = ioread8(pcie->pp.dbi_base + PCI_HEADER_TYPE);
|
||||
header_type &= 0x7f;
|
||||
|
||||
return header_type == PCI_HEADER_TYPE_BRIDGE;
|
||||
|
@ -68,13 +67,13 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
|
|||
/* Clear multi-function bit */
|
||||
static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
|
||||
{
|
||||
iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE);
|
||||
iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->pp.dbi_base + PCI_HEADER_TYPE);
|
||||
}
|
||||
|
||||
/* Fix class value */
|
||||
static void ls_pcie_fix_class(struct ls_pcie *pcie)
|
||||
{
|
||||
iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
|
||||
iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->pp.dbi_base + PCI_CLASS_DEVICE);
|
||||
}
|
||||
|
||||
/* Drop MSG TLP except for Vendor MSG */
|
||||
|
@ -82,9 +81,9 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
|
|||
{
|
||||
u32 val;
|
||||
|
||||
val = ioread32(pcie->dbi + PCIE_STRFMR1);
|
||||
val = ioread32(pcie->pp.dbi_base + PCIE_STRFMR1);
|
||||
val &= 0xDFFFFFFF;
|
||||
iowrite32(val, pcie->dbi + PCIE_STRFMR1);
|
||||
iowrite32(val, pcie->pp.dbi_base + PCIE_STRFMR1);
|
||||
}
|
||||
|
||||
static int ls1021_pcie_link_up(struct pcie_port *pp)
|
||||
|
@ -106,18 +105,19 @@ static int ls1021_pcie_link_up(struct pcie_port *pp)
|
|||
|
||||
static void ls1021_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct device *dev = pp->dev;
|
||||
struct ls_pcie *pcie = to_ls_pcie(pp);
|
||||
u32 index[2];
|
||||
|
||||
pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node,
|
||||
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"fsl,pcie-scfg");
|
||||
if (IS_ERR(pcie->scfg)) {
|
||||
dev_err(pp->dev, "No syscfg phandle specified\n");
|
||||
dev_err(dev, "No syscfg phandle specified\n");
|
||||
pcie->scfg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(pp->dev->of_node,
|
||||
if (of_property_read_u32_array(dev->of_node,
|
||||
"fsl,pcie-scfg", index, 2)) {
|
||||
pcie->scfg = NULL;
|
||||
return;
|
||||
|
@ -148,18 +148,19 @@ static void ls_pcie_host_init(struct pcie_port *pp)
|
|||
{
|
||||
struct ls_pcie *pcie = to_ls_pcie(pp);
|
||||
|
||||
iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
|
||||
iowrite32(1, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
|
||||
ls_pcie_fix_class(pcie);
|
||||
ls_pcie_clear_multifunction(pcie);
|
||||
ls_pcie_drop_msg_tlp(pcie);
|
||||
iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
|
||||
iowrite32(0, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
|
||||
}
|
||||
|
||||
static int ls_pcie_msi_host_init(struct pcie_port *pp,
|
||||
struct msi_controller *chip)
|
||||
{
|
||||
struct device *dev = pp->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *msi_node;
|
||||
struct device_node *np = pp->dev->of_node;
|
||||
|
||||
/*
|
||||
* The MSI domain is set by the generic of_msi_configure(). This
|
||||
|
@ -169,7 +170,7 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp,
|
|||
*/
|
||||
msi_node = of_parse_phandle(np, "msi-parent", 0);
|
||||
if (!msi_node) {
|
||||
dev_err(pp->dev, "failed to find msi-parent\n");
|
||||
dev_err(dev, "failed to find msi-parent\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -212,19 +213,15 @@ static const struct of_device_id ls_pcie_of_match[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static int __init ls_add_pcie_port(struct pcie_port *pp,
|
||||
struct platform_device *pdev)
|
||||
static int __init ls_add_pcie_port(struct ls_pcie *pcie)
|
||||
{
|
||||
struct pcie_port *pp = &pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
struct ls_pcie *pcie = to_ls_pcie(pp);
|
||||
|
||||
pp->dev = &pdev->dev;
|
||||
pp->dbi_base = pcie->dbi;
|
||||
pp->ops = pcie->drvdata->ops;
|
||||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(pp->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -233,38 +230,42 @@ static int __init ls_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int __init ls_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *match;
|
||||
struct ls_pcie *pcie;
|
||||
struct pcie_port *pp;
|
||||
struct resource *dbi_base;
|
||||
int ret;
|
||||
|
||||
match = of_match_device(ls_pcie_of_match, &pdev->dev);
|
||||
match = of_match_device(ls_pcie_of_match, dev);
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
|
||||
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
||||
if (!pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &pcie->pp;
|
||||
pp->dev = dev;
|
||||
pp->ops = pcie->drvdata->ops;
|
||||
|
||||
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
||||
pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base);
|
||||
if (IS_ERR(pcie->dbi)) {
|
||||
dev_err(&pdev->dev, "missing *regs* space\n");
|
||||
return PTR_ERR(pcie->dbi);
|
||||
pcie->pp.dbi_base = devm_ioremap_resource(dev, dbi_base);
|
||||
if (IS_ERR(pcie->pp.dbi_base)) {
|
||||
dev_err(dev, "missing *regs* space\n");
|
||||
return PTR_ERR(pcie->pp.dbi_base);
|
||||
}
|
||||
|
||||
pcie->drvdata = match->data;
|
||||
pcie->lut = pcie->dbi + pcie->drvdata->lut_offset;
|
||||
pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
|
||||
|
||||
if (!ls_pcie_is_bridge(pcie))
|
||||
return -ENODEV;
|
||||
|
||||
ret = ls_add_pcie_port(&pcie->pp, pdev);
|
||||
ret = ls_add_pcie_port(pcie);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,34 +29,33 @@
|
|||
#include "pcie-designware.h"
|
||||
|
||||
struct armada8k_pcie {
|
||||
void __iomem *base;
|
||||
struct pcie_port pp; /* pp.dbi_base is DT ctrl */
|
||||
struct clk *clk;
|
||||
struct pcie_port pp;
|
||||
};
|
||||
|
||||
#define PCIE_VENDOR_REGS_OFFSET 0x8000
|
||||
|
||||
#define PCIE_GLOBAL_CONTROL_REG 0x0
|
||||
#define PCIE_GLOBAL_CONTROL_REG (PCIE_VENDOR_REGS_OFFSET + 0x0)
|
||||
#define PCIE_APP_LTSSM_EN BIT(2)
|
||||
#define PCIE_DEVICE_TYPE_SHIFT 4
|
||||
#define PCIE_DEVICE_TYPE_MASK 0xF
|
||||
#define PCIE_DEVICE_TYPE_RC 0x4 /* Root complex */
|
||||
|
||||
#define PCIE_GLOBAL_STATUS_REG 0x8
|
||||
#define PCIE_GLOBAL_STATUS_REG (PCIE_VENDOR_REGS_OFFSET + 0x8)
|
||||
#define PCIE_GLB_STS_RDLH_LINK_UP BIT(1)
|
||||
#define PCIE_GLB_STS_PHY_LINK_UP BIT(9)
|
||||
|
||||
#define PCIE_GLOBAL_INT_CAUSE1_REG 0x1C
|
||||
#define PCIE_GLOBAL_INT_MASK1_REG 0x20
|
||||
#define PCIE_GLOBAL_INT_CAUSE1_REG (PCIE_VENDOR_REGS_OFFSET + 0x1C)
|
||||
#define PCIE_GLOBAL_INT_MASK1_REG (PCIE_VENDOR_REGS_OFFSET + 0x20)
|
||||
#define PCIE_INT_A_ASSERT_MASK BIT(9)
|
||||
#define PCIE_INT_B_ASSERT_MASK BIT(10)
|
||||
#define PCIE_INT_C_ASSERT_MASK BIT(11)
|
||||
#define PCIE_INT_D_ASSERT_MASK BIT(12)
|
||||
|
||||
#define PCIE_ARCACHE_TRC_REG 0x50
|
||||
#define PCIE_AWCACHE_TRC_REG 0x54
|
||||
#define PCIE_ARUSER_REG 0x5C
|
||||
#define PCIE_AWUSER_REG 0x60
|
||||
#define PCIE_ARCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x50)
|
||||
#define PCIE_AWCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x54)
|
||||
#define PCIE_ARUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x5C)
|
||||
#define PCIE_AWUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x60)
|
||||
/*
|
||||
* AR/AW Cache defauls: Normal memory, Write-Back, Read / Write
|
||||
* allocate
|
||||
|
@ -72,11 +71,10 @@ struct armada8k_pcie {
|
|||
|
||||
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);
|
||||
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_STATUS_REG);
|
||||
|
||||
if ((reg & mask) == mask)
|
||||
return 1;
|
||||
|
@ -85,51 +83,50 @@ static int armada8k_pcie_link_up(struct pcie_port *pp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void armada8k_pcie_establish_link(struct pcie_port *pp)
|
||||
static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
|
||||
{
|
||||
struct armada8k_pcie *pcie = to_armada8k_pcie(pp);
|
||||
void __iomem *base = pcie->base;
|
||||
struct pcie_port *pp = &pcie->pp;
|
||||
u32 reg;
|
||||
|
||||
if (!dw_pcie_link_up(pp)) {
|
||||
/* Disable LTSSM state machine to enable configuration */
|
||||
reg = readl(base + PCIE_GLOBAL_CONTROL_REG);
|
||||
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
|
||||
reg &= ~(PCIE_APP_LTSSM_EN);
|
||||
writel(reg, base + PCIE_GLOBAL_CONTROL_REG);
|
||||
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
|
||||
}
|
||||
|
||||
/* Set the device to root complex mode */
|
||||
reg = readl(base + PCIE_GLOBAL_CONTROL_REG);
|
||||
reg = dw_pcie_readl_rc(pp, 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);
|
||||
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, 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);
|
||||
dw_pcie_writel_rc(pp, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE);
|
||||
dw_pcie_writel_rc(pp, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE);
|
||||
|
||||
/* Set the PCIe master AxDomain attributes */
|
||||
reg = readl(base + PCIE_ARUSER_REG);
|
||||
reg = dw_pcie_readl_rc(pp, 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);
|
||||
dw_pcie_writel_rc(pp, PCIE_ARUSER_REG, reg);
|
||||
|
||||
reg = readl(base + PCIE_AWUSER_REG);
|
||||
reg = dw_pcie_readl_rc(pp, 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);
|
||||
dw_pcie_writel_rc(pp, PCIE_AWUSER_REG, reg);
|
||||
|
||||
/* Enable INT A-D interrupts */
|
||||
reg = readl(base + PCIE_GLOBAL_INT_MASK1_REG);
|
||||
reg = dw_pcie_readl_rc(pp, 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);
|
||||
dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_MASK1_REG, reg);
|
||||
|
||||
if (!dw_pcie_link_up(pp)) {
|
||||
/* Configuration done. Start LTSSM */
|
||||
reg = readl(base + PCIE_GLOBAL_CONTROL_REG);
|
||||
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
|
||||
reg |= PCIE_APP_LTSSM_EN;
|
||||
writel(reg, base + PCIE_GLOBAL_CONTROL_REG);
|
||||
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
|
||||
}
|
||||
|
||||
/* Wait until the link becomes active again */
|
||||
|
@ -139,15 +136,16 @@ static void armada8k_pcie_establish_link(struct pcie_port *pp)
|
|||
|
||||
static void armada8k_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct armada8k_pcie *pcie = to_armada8k_pcie(pp);
|
||||
|
||||
dw_pcie_setup_rc(pp);
|
||||
armada8k_pcie_establish_link(pp);
|
||||
armada8k_pcie_establish_link(pcie);
|
||||
}
|
||||
|
||||
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;
|
||||
struct armada8k_pcie *pcie = arg;
|
||||
struct pcie_port *pp = &pcie->pp;
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
|
@ -155,8 +153,8 @@ static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
|
|||
* 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);
|
||||
val = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG);
|
||||
dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG, val);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -166,9 +164,10 @@ static struct pcie_host_ops armada8k_pcie_host_ops = {
|
|||
.host_init = armada8k_pcie_host_init,
|
||||
};
|
||||
|
||||
static int armada8k_add_pcie_port(struct pcie_port *pp,
|
||||
static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct pcie_port *pp = &pcie->pp;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
|
@ -182,7 +181,7 @@ static int armada8k_add_pcie_port(struct pcie_port *pp,
|
|||
}
|
||||
|
||||
ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler,
|
||||
IRQF_SHARED, "armada8k-pcie", pp);
|
||||
IRQF_SHARED, "armada8k-pcie", pcie);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request irq %d\n", pp->irq);
|
||||
return ret;
|
||||
|
@ -217,7 +216,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
|
|||
|
||||
pp = &pcie->pp;
|
||||
pp->dev = dev;
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
/* Get the dw-pcie unit configuration/control registers base. */
|
||||
base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
|
||||
|
@ -228,9 +226,7 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
pcie->base = pp->dbi_base + PCIE_VENDOR_REGS_OFFSET;
|
||||
|
||||
ret = armada8k_add_pcie_port(pp, pdev);
|
||||
ret = armada8k_add_pcie_port(pcie, pdev);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#define to_artpec6_pcie(x) container_of(x, struct artpec6_pcie, pp)
|
||||
|
||||
struct artpec6_pcie {
|
||||
struct pcie_port pp;
|
||||
struct regmap *regmap;
|
||||
void __iomem *phy_base;
|
||||
struct pcie_port pp; /* pp.dbi_base is DT dbi */
|
||||
struct regmap *regmap; /* DT axis,syscon-pcie */
|
||||
void __iomem *phy_base; /* DT phy */
|
||||
};
|
||||
|
||||
/* PCIe Port Logic registers (memory-mapped) */
|
||||
|
@ -65,18 +65,31 @@ struct artpec6_pcie {
|
|||
|
||||
#define ARTPEC6_CPU_TO_BUS_ADDR 0x0fffffff
|
||||
|
||||
static int artpec6_pcie_establish_link(struct pcie_port *pp)
|
||||
static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset)
|
||||
{
|
||||
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp);
|
||||
u32 val;
|
||||
|
||||
regmap_read(artpec6_pcie->regmap, offset, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u32 val)
|
||||
{
|
||||
regmap_write(artpec6_pcie->regmap, offset, val);
|
||||
}
|
||||
|
||||
static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &artpec6_pcie->pp;
|
||||
u32 val;
|
||||
unsigned int retries;
|
||||
|
||||
/* Hold DW core in reset */
|
||||
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
|
||||
val |= PCIECFG_CORE_RESET_REQ;
|
||||
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
|
||||
|
||||
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
|
||||
val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */
|
||||
PCIECFG_MODE_TX_DRV_EN |
|
||||
PCIECFG_CISRREN | /* Reference clock term. 100 Ohm */
|
||||
|
@ -84,27 +97,27 @@ static int artpec6_pcie_establish_link(struct pcie_port *pp)
|
|||
val |= PCIECFG_REFCLK_ENABLE;
|
||||
val &= ~PCIECFG_DBG_OEN;
|
||||
val &= ~PCIECFG_CLKREQ_B;
|
||||
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
|
||||
val |= NOCCFG_ENABLE_CLK_PCIE;
|
||||
regmap_write(artpec6_pcie->regmap, NOCCFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
|
||||
usleep_range(20, 30);
|
||||
|
||||
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
|
||||
val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE;
|
||||
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
|
||||
usleep_range(6000, 7000);
|
||||
|
||||
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
|
||||
val &= ~NOCCFG_POWER_PCIE_IDLEREQ;
|
||||
regmap_write(artpec6_pcie->regmap, NOCCFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
|
||||
|
||||
retries = 50;
|
||||
do {
|
||||
usleep_range(1000, 2000);
|
||||
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
|
||||
retries--;
|
||||
} while (retries &&
|
||||
(val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE)));
|
||||
|
@ -117,16 +130,16 @@ static int artpec6_pcie_establish_link(struct pcie_port *pp)
|
|||
} while (retries && !(val & PHY_COSPLLLOCK));
|
||||
|
||||
/* Take DW core out of reset */
|
||||
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
|
||||
val &= ~PCIECFG_CORE_RESET_REQ;
|
||||
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
|
||||
usleep_range(100, 200);
|
||||
|
||||
/*
|
||||
* Enable writing to config regs. This is required as the Synopsys
|
||||
* driver changes the class code. That register needs DBI write enable.
|
||||
*/
|
||||
writel(DBI_RO_WR_EN, pp->dbi_base + MISC_CONTROL_1_OFF);
|
||||
dw_pcie_writel_rc(pp, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
|
||||
|
||||
pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR;
|
||||
pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR;
|
||||
|
@ -137,78 +150,69 @@ static int artpec6_pcie_establish_link(struct pcie_port *pp)
|
|||
dw_pcie_setup_rc(pp);
|
||||
|
||||
/* assert LTSSM enable */
|
||||
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
|
||||
val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
|
||||
val |= PCIECFG_LTSSM_ENABLE;
|
||||
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
|
||||
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
|
||||
|
||||
/* check if the link is up or not */
|
||||
if (!dw_pcie_wait_for_link(pp))
|
||||
return 0;
|
||||
|
||||
dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
|
||||
readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
|
||||
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
|
||||
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void artpec6_pcie_enable_interrupts(struct pcie_port *pp)
|
||||
static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &artpec6_pcie->pp;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
dw_pcie_msi_init(pp);
|
||||
}
|
||||
|
||||
static void artpec6_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
artpec6_pcie_establish_link(pp);
|
||||
artpec6_pcie_enable_interrupts(pp);
|
||||
}
|
||||
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp);
|
||||
|
||||
static int artpec6_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
u32 rc;
|
||||
|
||||
/*
|
||||
* Get status from Synopsys IP
|
||||
* link is debug bit 36, debug register 1 starts at bit 32
|
||||
*/
|
||||
rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
|
||||
if (rc)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
artpec6_pcie_establish_link(artpec6_pcie);
|
||||
artpec6_pcie_enable_interrupts(artpec6_pcie);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops artpec6_pcie_host_ops = {
|
||||
.link_up = artpec6_pcie_link_up,
|
||||
.host_init = artpec6_pcie_host_init,
|
||||
};
|
||||
|
||||
static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct artpec6_pcie *artpec6_pcie = arg;
|
||||
struct pcie_port *pp = &artpec6_pcie->pp;
|
||||
|
||||
return dw_handle_msi_irq(pp);
|
||||
}
|
||||
|
||||
static int artpec6_add_pcie_port(struct pcie_port *pp,
|
||||
static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct pcie_port *pp = &artpec6_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
|
||||
if (pp->msi_irq <= 0) {
|
||||
dev_err(&pdev->dev, "failed to get MSI irq\n");
|
||||
dev_err(dev, "failed to get MSI irq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
|
||||
ret = devm_request_irq(dev, pp->msi_irq,
|
||||
artpec6_pcie_msi_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"artpec6-pcie-msi", pp);
|
||||
"artpec6-pcie-msi", artpec6_pcie);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request MSI irq\n");
|
||||
dev_err(dev, "failed to request MSI irq\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +222,7 @@ static int artpec6_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -227,41 +231,40 @@ static int artpec6_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int artpec6_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct artpec6_pcie *artpec6_pcie;
|
||||
struct pcie_port *pp;
|
||||
struct resource *dbi_base;
|
||||
struct resource *phy_base;
|
||||
int ret;
|
||||
|
||||
artpec6_pcie = devm_kzalloc(&pdev->dev, sizeof(*artpec6_pcie),
|
||||
GFP_KERNEL);
|
||||
artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL);
|
||||
if (!artpec6_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &artpec6_pcie->pp;
|
||||
pp->dev = &pdev->dev;
|
||||
pp->dev = dev;
|
||||
|
||||
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||||
pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
|
||||
pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
|
||||
if (IS_ERR(pp->dbi_base))
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
|
||||
phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
|
||||
artpec6_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base);
|
||||
artpec6_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
|
||||
if (IS_ERR(artpec6_pcie->phy_base))
|
||||
return PTR_ERR(artpec6_pcie->phy_base);
|
||||
|
||||
artpec6_pcie->regmap =
|
||||
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
||||
syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"axis,syscon-pcie");
|
||||
if (IS_ERR(artpec6_pcie->regmap))
|
||||
return PTR_ERR(artpec6_pcie->regmap);
|
||||
|
||||
ret = artpec6_add_pcie_port(pp, pdev);
|
||||
ret = artpec6_add_pcie_port(artpec6_pcie, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, artpec6_pcie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,51 +22,38 @@
|
|||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
#define PCIE_LTSSM_LINKUP_STATE 0x11
|
||||
#define PCIE_LTSSM_STATE_MASK 0x3F
|
||||
#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
|
||||
#define PCIE_SYS_STATE4 0x31c
|
||||
#define PCIE_HIP06_CTRL_OFF 0x1000
|
||||
#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
|
||||
#define PCIE_HIP06_CTRL_OFF 0x1000
|
||||
#define PCIE_SYS_STATE4 (PCIE_HIP06_CTRL_OFF + 0x31c)
|
||||
#define PCIE_LTSSM_LINKUP_STATE 0x11
|
||||
#define PCIE_LTSSM_STATE_MASK 0x3F
|
||||
|
||||
#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
|
||||
|
||||
struct hisi_pcie;
|
||||
|
||||
struct pcie_soc_ops {
|
||||
int (*hisi_pcie_link_up)(struct hisi_pcie *pcie);
|
||||
int (*hisi_pcie_link_up)(struct hisi_pcie *hisi_pcie);
|
||||
};
|
||||
|
||||
struct hisi_pcie {
|
||||
struct pcie_port pp; /* pp.dbi_base is DT rc_dbi */
|
||||
struct regmap *subctrl;
|
||||
void __iomem *reg_base;
|
||||
u32 port_id;
|
||||
struct pcie_port pp;
|
||||
struct pcie_soc_ops *soc_ops;
|
||||
};
|
||||
|
||||
static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
|
||||
u32 val, u32 reg)
|
||||
{
|
||||
writel(val, pcie->reg_base + reg);
|
||||
}
|
||||
|
||||
static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
|
||||
{
|
||||
return readl(pcie->reg_base + reg);
|
||||
}
|
||||
|
||||
/* HipXX PCIe host only supports 32-bit config access */
|
||||
static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
|
||||
u32 *val)
|
||||
{
|
||||
u32 reg;
|
||||
u32 reg_val;
|
||||
struct hisi_pcie *pcie = to_hisi_pcie(pp);
|
||||
void *walker = ®_val;
|
||||
|
||||
walker += (where & 0x3);
|
||||
reg = where & ~0x3;
|
||||
reg_val = hisi_pcie_apb_readl(pcie, reg);
|
||||
reg_val = dw_pcie_readl_rc(pp, reg);
|
||||
|
||||
if (size == 1)
|
||||
*val = *(u8 __force *) walker;
|
||||
|
@ -86,21 +73,20 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
|
|||
{
|
||||
u32 reg_val;
|
||||
u32 reg;
|
||||
struct hisi_pcie *pcie = to_hisi_pcie(pp);
|
||||
void *walker = ®_val;
|
||||
|
||||
walker += (where & 0x3);
|
||||
reg = where & ~0x3;
|
||||
if (size == 4)
|
||||
hisi_pcie_apb_writel(pcie, val, reg);
|
||||
dw_pcie_writel_rc(pp, reg, val);
|
||||
else if (size == 2) {
|
||||
reg_val = hisi_pcie_apb_readl(pcie, reg);
|
||||
reg_val = dw_pcie_readl_rc(pp, reg);
|
||||
*(u16 __force *) walker = val;
|
||||
hisi_pcie_apb_writel(pcie, reg_val, reg);
|
||||
dw_pcie_writel_rc(pp, reg, reg_val);
|
||||
} else if (size == 1) {
|
||||
reg_val = hisi_pcie_apb_readl(pcie, reg);
|
||||
reg_val = dw_pcie_readl_rc(pp, reg);
|
||||
*(u8 __force *) walker = val;
|
||||
hisi_pcie_apb_writel(pcie, reg_val, reg);
|
||||
dw_pcie_writel_rc(pp, reg, reg_val);
|
||||
} else
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
|
@ -119,10 +105,10 @@ static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie)
|
|||
|
||||
static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
|
||||
{
|
||||
struct pcie_port *pp = &hisi_pcie->pp;
|
||||
u32 val;
|
||||
|
||||
val = hisi_pcie_apb_readl(hisi_pcie, PCIE_HIP06_CTRL_OFF +
|
||||
PCIE_SYS_STATE4);
|
||||
val = dw_pcie_readl_rc(pp, PCIE_SYS_STATE4);
|
||||
|
||||
return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
|
||||
}
|
||||
|
@ -140,19 +126,20 @@ static struct pcie_host_ops hisi_pcie_host_ops = {
|
|||
.link_up = hisi_pcie_link_up,
|
||||
};
|
||||
|
||||
static int hisi_add_pcie_port(struct pcie_port *pp,
|
||||
struct platform_device *pdev)
|
||||
static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct pcie_port *pp = &hisi_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
u32 port_id;
|
||||
struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
|
||||
dev_err(&pdev->dev, "failed to read port-id\n");
|
||||
if (of_property_read_u32(dev->of_node, "port-id", &port_id)) {
|
||||
dev_err(dev, "failed to read port-id\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (port_id > 3) {
|
||||
dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id);
|
||||
dev_err(dev, "Invalid port-id: %d\n", port_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
hisi_pcie->port_id = port_id;
|
||||
|
@ -161,7 +148,7 @@ static int hisi_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize host\n");
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -170,6 +157,7 @@ static int hisi_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int hisi_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct hisi_pcie *hisi_pcie;
|
||||
struct pcie_port *pp;
|
||||
const struct of_device_id *match;
|
||||
|
@ -177,40 +165,36 @@ static int hisi_pcie_probe(struct platform_device *pdev)
|
|||
struct device_driver *driver;
|
||||
int ret;
|
||||
|
||||
hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
|
||||
hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL);
|
||||
if (!hisi_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &hisi_pcie->pp;
|
||||
pp->dev = &pdev->dev;
|
||||
driver = (pdev->dev).driver;
|
||||
pp->dev = dev;
|
||||
driver = dev->driver;
|
||||
|
||||
match = of_match_device(driver->of_match_table, &pdev->dev);
|
||||
match = of_match_device(driver->of_match_table, dev);
|
||||
hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data;
|
||||
|
||||
hisi_pcie->subctrl =
|
||||
syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl");
|
||||
if (IS_ERR(hisi_pcie->subctrl)) {
|
||||
dev_err(pp->dev, "cannot get subctrl base\n");
|
||||
dev_err(dev, "cannot get subctrl base\n");
|
||||
return PTR_ERR(hisi_pcie->subctrl);
|
||||
}
|
||||
|
||||
reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
|
||||
hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
|
||||
if (IS_ERR(hisi_pcie->reg_base)) {
|
||||
dev_err(pp->dev, "cannot get rc_dbi base\n");
|
||||
return PTR_ERR(hisi_pcie->reg_base);
|
||||
pp->dbi_base = devm_ioremap_resource(dev, reg);
|
||||
if (IS_ERR(pp->dbi_base)) {
|
||||
dev_err(dev, "cannot get rc_dbi base\n");
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
}
|
||||
|
||||
hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
|
||||
|
||||
ret = hisi_add_pcie_port(pp, pdev);
|
||||
ret = hisi_add_pcie_port(hisi_pcie, pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, hisi_pcie);
|
||||
|
||||
dev_warn(pp->dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n");
|
||||
dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -86,12 +86,10 @@ struct qcom_pcie_ops {
|
|||
};
|
||||
|
||||
struct qcom_pcie {
|
||||
struct pcie_port pp;
|
||||
struct device *dev;
|
||||
struct pcie_port pp; /* pp.dbi_base is DT dbi */
|
||||
void __iomem *parf; /* DT parf */
|
||||
void __iomem *elbi; /* DT elbi */
|
||||
union qcom_pcie_resources res;
|
||||
void __iomem *parf;
|
||||
void __iomem *dbi;
|
||||
void __iomem *elbi;
|
||||
struct phy *phy;
|
||||
struct gpio_desc *reset;
|
||||
struct qcom_pcie_ops *ops;
|
||||
|
@ -136,7 +134,7 @@ static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
|
|||
static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
struct device *dev = pcie->dev;
|
||||
struct device *dev = pcie->pp.dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
|
@ -188,7 +186,7 @@ static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
|||
static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct device *dev = pcie->dev;
|
||||
struct device *dev = pcie->pp.dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
|
@ -237,7 +235,7 @@ static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
|
|||
static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
struct device *dev = pcie->dev;
|
||||
struct device *dev = pcie->pp.dev;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
|
@ -359,7 +357,7 @@ static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
|
|||
static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct device *dev = pcie->dev;
|
||||
struct device *dev = pcie->pp.dev;
|
||||
int ret;
|
||||
|
||||
ret = reset_control_deassert(res->core);
|
||||
|
@ -426,7 +424,7 @@ err_res:
|
|||
static int qcom_pcie_link_up(struct pcie_port *pp)
|
||||
{
|
||||
struct qcom_pcie *pcie = to_qcom_pcie(pp);
|
||||
u16 val = readw(pcie->dbi + PCIE20_CAP + PCI_EXP_LNKSTA);
|
||||
u16 val = readw(pcie->pp.dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
|
||||
|
||||
return !!(val & PCI_EXP_LNKSTA_DLLLA);
|
||||
}
|
||||
|
@ -509,8 +507,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
if (!pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pp = &pcie->pp;
|
||||
pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
|
||||
pcie->dev = dev;
|
||||
|
||||
pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(pcie->reset))
|
||||
|
@ -522,9 +520,9 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(pcie->parf);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||||
pcie->dbi = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pcie->dbi))
|
||||
return PTR_ERR(pcie->dbi);
|
||||
pp->dbi_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pp->dbi_base))
|
||||
return PTR_ERR(pp->dbi_base);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
|
||||
pcie->elbi = devm_ioremap_resource(dev, res);
|
||||
|
@ -539,9 +537,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pp = &pcie->pp;
|
||||
pp->dev = dev;
|
||||
pp->dbi_base = pcie->dbi;
|
||||
pp->root_bus_nr = -1;
|
||||
pp->ops = &qcom_pcie_dw_ops;
|
||||
|
||||
|
@ -569,8 +565,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#include "pcie-designware.h"
|
||||
|
||||
struct spear13xx_pcie {
|
||||
struct pcie_port pp; /* DT dbi is pp.dbi_base */
|
||||
void __iomem *app_base;
|
||||
struct phy *phy;
|
||||
struct clk *clk;
|
||||
struct pcie_port pp;
|
||||
bool is_gen1;
|
||||
};
|
||||
|
||||
|
@ -57,96 +57,26 @@ struct pcie_app_reg {
|
|||
};
|
||||
|
||||
/* CR0 ID */
|
||||
#define RX_LANE_FLIP_EN_ID 0
|
||||
#define TX_LANE_FLIP_EN_ID 1
|
||||
#define SYS_AUX_PWR_DET_ID 2
|
||||
#define APP_LTSSM_ENABLE_ID 3
|
||||
#define SYS_ATTEN_BUTTON_PRESSED_ID 4
|
||||
#define SYS_MRL_SENSOR_STATE_ID 5
|
||||
#define SYS_PWR_FAULT_DET_ID 6
|
||||
#define SYS_MRL_SENSOR_CHGED_ID 7
|
||||
#define SYS_PRE_DET_CHGED_ID 8
|
||||
#define SYS_CMD_CPLED_INT_ID 9
|
||||
#define APP_INIT_RST_0_ID 11
|
||||
#define APP_REQ_ENTR_L1_ID 12
|
||||
#define APP_READY_ENTR_L23_ID 13
|
||||
#define APP_REQ_EXIT_L1_ID 14
|
||||
#define DEVICE_TYPE_EP (0 << 25)
|
||||
#define DEVICE_TYPE_LEP (1 << 25)
|
||||
#define DEVICE_TYPE_RC (4 << 25)
|
||||
#define SYS_INT_ID 29
|
||||
#define MISCTRL_EN_ID 30
|
||||
#define REG_TRANSLATION_ENABLE 31
|
||||
|
||||
/* CR1 ID */
|
||||
#define APPS_PM_XMT_TURNOFF_ID 2
|
||||
#define APPS_PM_XMT_PME_ID 5
|
||||
|
||||
/* CR3 ID */
|
||||
#define XMLH_LTSSM_STATE_DETECT_QUIET 0x00
|
||||
#define XMLH_LTSSM_STATE_DETECT_ACT 0x01
|
||||
#define XMLH_LTSSM_STATE_POLL_ACTIVE 0x02
|
||||
#define XMLH_LTSSM_STATE_POLL_COMPLIANCE 0x03
|
||||
#define XMLH_LTSSM_STATE_POLL_CONFIG 0x04
|
||||
#define XMLH_LTSSM_STATE_PRE_DETECT_QUIET 0x05
|
||||
#define XMLH_LTSSM_STATE_DETECT_WAIT 0x06
|
||||
#define XMLH_LTSSM_STATE_CFG_LINKWD_START 0x07
|
||||
#define XMLH_LTSSM_STATE_CFG_LINKWD_ACEPT 0x08
|
||||
#define XMLH_LTSSM_STATE_CFG_LANENUM_WAIT 0x09
|
||||
#define XMLH_LTSSM_STATE_CFG_LANENUM_ACEPT 0x0A
|
||||
#define XMLH_LTSSM_STATE_CFG_COMPLETE 0x0B
|
||||
#define XMLH_LTSSM_STATE_CFG_IDLE 0x0C
|
||||
#define XMLH_LTSSM_STATE_RCVRY_LOCK 0x0D
|
||||
#define XMLH_LTSSM_STATE_RCVRY_SPEED 0x0E
|
||||
#define XMLH_LTSSM_STATE_RCVRY_RCVRCFG 0x0F
|
||||
#define XMLH_LTSSM_STATE_RCVRY_IDLE 0x10
|
||||
#define XMLH_LTSSM_STATE_L0 0x11
|
||||
#define XMLH_LTSSM_STATE_L0S 0x12
|
||||
#define XMLH_LTSSM_STATE_L123_SEND_EIDLE 0x13
|
||||
#define XMLH_LTSSM_STATE_L1_IDLE 0x14
|
||||
#define XMLH_LTSSM_STATE_L2_IDLE 0x15
|
||||
#define XMLH_LTSSM_STATE_L2_WAKE 0x16
|
||||
#define XMLH_LTSSM_STATE_DISABLED_ENTRY 0x17
|
||||
#define XMLH_LTSSM_STATE_DISABLED_IDLE 0x18
|
||||
#define XMLH_LTSSM_STATE_DISABLED 0x19
|
||||
#define XMLH_LTSSM_STATE_LPBK_ENTRY 0x1A
|
||||
#define XMLH_LTSSM_STATE_LPBK_ACTIVE 0x1B
|
||||
#define XMLH_LTSSM_STATE_LPBK_EXIT 0x1C
|
||||
#define XMLH_LTSSM_STATE_LPBK_EXIT_TIMEOUT 0x1D
|
||||
#define XMLH_LTSSM_STATE_HOT_RESET_ENTRY 0x1E
|
||||
#define XMLH_LTSSM_STATE_HOT_RESET 0x1F
|
||||
#define XMLH_LTSSM_STATE_MASK 0x3F
|
||||
#define XMLH_LINK_UP (1 << 6)
|
||||
|
||||
/* CR4 ID */
|
||||
#define CFG_MSI_EN_ID 18
|
||||
|
||||
/* CR6 */
|
||||
#define INTA_CTRL_INT (1 << 7)
|
||||
#define INTB_CTRL_INT (1 << 8)
|
||||
#define INTC_CTRL_INT (1 << 9)
|
||||
#define INTD_CTRL_INT (1 << 10)
|
||||
#define MSI_CTRL_INT (1 << 26)
|
||||
|
||||
/* CR19 ID */
|
||||
#define VEN_MSI_REQ_ID 11
|
||||
#define VEN_MSI_FUN_NUM_ID 8
|
||||
#define VEN_MSI_TC_ID 5
|
||||
#define VEN_MSI_VECTOR_ID 0
|
||||
#define VEN_MSI_REQ_EN ((u32)0x1 << VEN_MSI_REQ_ID)
|
||||
#define VEN_MSI_FUN_NUM_MASK ((u32)0x7 << VEN_MSI_FUN_NUM_ID)
|
||||
#define VEN_MSI_TC_MASK ((u32)0x7 << VEN_MSI_TC_ID)
|
||||
#define VEN_MSI_VECTOR_MASK ((u32)0x1F << VEN_MSI_VECTOR_ID)
|
||||
|
||||
#define EXP_CAP_ID_OFFSET 0x70
|
||||
|
||||
#define to_spear13xx_pcie(x) container_of(x, struct spear13xx_pcie, pp)
|
||||
|
||||
static int spear13xx_pcie_establish_link(struct pcie_port *pp)
|
||||
static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
|
||||
{
|
||||
u32 val;
|
||||
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
|
||||
struct pcie_port *pp = &spear13xx_pcie->pp;
|
||||
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
|
||||
u32 val;
|
||||
u32 exp_cap_off = EXP_CAP_ID_OFFSET;
|
||||
|
||||
if (dw_pcie_link_up(pp)) {
|
||||
|
@ -203,9 +133,9 @@ static int spear13xx_pcie_establish_link(struct pcie_port *pp)
|
|||
|
||||
static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct pcie_port *pp = arg;
|
||||
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
|
||||
struct spear13xx_pcie *spear13xx_pcie = arg;
|
||||
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
|
||||
struct pcie_port *pp = &spear13xx_pcie->pp;
|
||||
unsigned int status;
|
||||
|
||||
status = readl(&app_reg->int_sts);
|
||||
|
@ -220,9 +150,9 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void spear13xx_pcie_enable_interrupts(struct pcie_port *pp)
|
||||
static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie)
|
||||
{
|
||||
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
|
||||
struct pcie_port *pp = &spear13xx_pcie->pp;
|
||||
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
|
||||
|
||||
/* Enable MSI interrupt */
|
||||
|
@ -246,8 +176,10 @@ static int spear13xx_pcie_link_up(struct pcie_port *pp)
|
|||
|
||||
static void spear13xx_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
spear13xx_pcie_establish_link(pp);
|
||||
spear13xx_pcie_enable_interrupts(pp);
|
||||
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
|
||||
|
||||
spear13xx_pcie_establish_link(spear13xx_pcie);
|
||||
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
|
||||
}
|
||||
|
||||
static struct pcie_host_ops spear13xx_pcie_host_ops = {
|
||||
|
@ -255,10 +187,11 @@ static struct pcie_host_ops spear13xx_pcie_host_ops = {
|
|||
.host_init = spear13xx_pcie_host_init,
|
||||
};
|
||||
|
||||
static int spear13xx_add_pcie_port(struct pcie_port *pp,
|
||||
struct platform_device *pdev)
|
||||
static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct pcie_port *pp = &spear13xx_pcie->pp;
|
||||
struct device *dev = pp->dev;
|
||||
int ret;
|
||||
|
||||
pp->irq = platform_get_irq(pdev, 0);
|
||||
|
@ -268,7 +201,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
|
|||
}
|
||||
ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
|
||||
IRQF_SHARED | IRQF_NO_THREAD,
|
||||
"spear1340-pcie", pp);
|
||||
"spear1340-pcie", spear13xx_pcie);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request irq %d\n", pp->irq);
|
||||
return ret;
|
||||
|
@ -288,10 +221,10 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
static int spear13xx_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spear13xx_pcie *spear13xx_pcie;
|
||||
struct pcie_port *pp;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct resource *dbi_base;
|
||||
int ret;
|
||||
|
||||
|
@ -323,7 +256,6 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
pp = &spear13xx_pcie->pp;
|
||||
|
||||
pp->dev = dev;
|
||||
|
||||
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||||
|
@ -338,7 +270,7 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)
|
|||
if (of_property_read_bool(np, "st,pcie-is-gen1"))
|
||||
spear13xx_pcie->is_gen1 = true;
|
||||
|
||||
ret = spear13xx_add_pcie_port(pp, pdev);
|
||||
ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev);
|
||||
if (ret < 0)
|
||||
goto fail_clk;
|
||||
|
||||
|
|
Loading…
Reference in New Issue