diff options
author | Richard Zhu <r65037@freescale.com> | 2013-11-13 16:42:06 +0800 |
---|---|---|
committer | Richard Zhu <r65037@freescale.com> | 2013-11-20 14:10:33 +0800 |
commit | 65e8b2c472bd1270f5811e07362e8f0fda62225f (patch) | |
tree | 51116e77676b7fc2b6663d66612d77a295851453 | |
parent | 06b60b45f851c1e3c710c8253b3183eed46d1172 (diff) |
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 <r65037@freescale.com>
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 27 | ||||
-rw-r--r-- | 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 <linux/resource.h> #include <linux/signal.h> #include <linux/types.h> +#include <linux/busfreq-imx6.h> #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) |