From 65e8b2c472bd1270f5811e07362e8f0fda62225f Mon Sep 17 00:00:00 2001 From: Richard Zhu Date: Wed, 13 Nov 2013 16:42:06 +0800 Subject: ENGR00288406 pcie: imx: enable pcie switch support Fix the pcie switch no detection issue Root cause why the switch can't be detected before: * The initialization sequence is not properly, 100ms reset should be just issue before ltssm enable. * Lagency INTx mapping is wrong * remove un-correct IO/MEM iATU outbound mapping. Signed-off-by: Richard Zhu --- drivers/pci/host/pci-imx6.c | 27 +++++------------- drivers/pci/host/pcie-designware.c | 56 +++++--------------------------------- 2 files changed, 14 insertions(+), 69 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index fbd75bf0d741..bb91b2274506 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "pcie-designware.h" @@ -204,24 +205,6 @@ static int imx6q_pcie_abort_handler(unsigned long addr, return 0; } -static int imx6_pcie_assert_core_reset(struct pcie_port *pp) -{ - struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); - - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); - - gpio_set_value(imx6_pcie->reset_gpio, 0); - msleep(100); - gpio_set_value(imx6_pcie->reset_gpio, 1); - - return 0; -} - static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); @@ -234,6 +217,7 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); + request_bus_freq(BUS_FREQ_HIGH); ret = clk_prepare_enable(imx6_pcie->sata_ref_100m); if (ret) { @@ -262,6 +246,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) /* allow the clocks to stabilize */ usleep_range(200, 500); + gpio_set_value(imx6_pcie->reset_gpio, 0); + msleep(100); + gpio_set_value(imx6_pcie->reset_gpio, 1); + return 0; err_pcie_axi: @@ -271,6 +259,7 @@ err_lvds_gate: err_pcie_ref: clk_disable_unprepare(imx6_pcie->sata_ref_100m); err_sata_ref: + release_bus_freq(BUS_FREQ_HIGH); return ret; } @@ -314,8 +303,6 @@ static void imx6_pcie_host_init(struct pcie_port *pp) int count = 0; struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); - imx6_pcie_assert_core_reset(pp); - imx6_pcie_init_phy(pp); imx6_pcie_deassert_core_reset(pp); diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index c6218ff5cf38..f4101cff0df8 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -545,50 +545,6 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) dw_pcie_writel_rc(pp, 0, dbi_base + PCIE_ATU_UPPER_TARGET); } -static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) -{ - u32 val; - void __iomem *dbi_base = pp->dbi_base; - - /* Program viewport 0 : OUTBOUND : MEM */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); - dw_pcie_writel_rc(pp, pp->mem_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->mem_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); - dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, - dbi_base + PCIE_ATU_LOWER_TARGET); - dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), - dbi_base + PCIE_ATU_UPPER_TARGET); -} - -static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) -{ - u32 val; - void __iomem *dbi_base = pp->dbi_base; - - /* Program viewport 1 : OUTBOUND : IO */ - val = PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_VIEWPORT); - dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1); - val = PCIE_ATU_ENABLE; - dw_pcie_writel_rc(pp, val, dbi_base + PCIE_ATU_CR2); - dw_pcie_writel_rc(pp, pp->io_base, dbi_base + PCIE_ATU_LOWER_BASE); - dw_pcie_writel_rc(pp, (pp->io_base >> 32), - dbi_base + PCIE_ATU_UPPER_BASE); - dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, - dbi_base + PCIE_ATU_LIMIT); - dw_pcie_writel_rc(pp, pp->config.io_bus_addr, - dbi_base + PCIE_ATU_LOWER_TARGET); - dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), - dbi_base + PCIE_ATU_UPPER_TARGET); -} - static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, u32 devfn, int where, int size, u32 *val) { @@ -602,11 +558,9 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, if (bus->parent->number == pp->root_bus_nr) { dw_pcie_prog_viewport_cfg0(pp, busdev); ret = cfg_read(pp->va_cfg0_base + address, where, size, val); - dw_pcie_prog_viewport_mem_outbound(pp); } else { dw_pcie_prog_viewport_cfg1(pp, busdev); ret = cfg_read(pp->va_cfg1_base + address, where, size, val); - dw_pcie_prog_viewport_io_outbound(pp); } return ret; @@ -625,11 +579,9 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, if (bus->parent->number == pp->root_bus_nr) { dw_pcie_prog_viewport_cfg0(pp, busdev); ret = cfg_write(pp->va_cfg0_base + address, where, size, val); - dw_pcie_prog_viewport_mem_outbound(pp); } else { dw_pcie_prog_viewport_cfg1(pp, busdev); ret = cfg_write(pp->va_cfg1_base + address, where, size, val); - dw_pcie_prog_viewport_io_outbound(pp); } return ret; @@ -762,7 +714,13 @@ static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); - return pp->irq; + switch (pin) { + case 1: return pp->irq; + case 2: return pp->irq - 1; + case 3: return pp->irq - 2; + case 4: return pp->irq - 3; + default: return -1; + } } static void dw_pcie_add_bus(struct pci_bus *bus) -- cgit v1.2.3