summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2013-11-13 16:42:06 +0800
committerRichard Zhu <r65037@freescale.com>2013-11-21 09:37:50 +0800
commit5d498c1c784fc3f0e8c420fed8e53686d8a2fed9 (patch)
tree2a21ec8273c9202f1b1c88aee0f2c5149052379c
parentfb0c0b6656b76dde2a01af11beba08a4b09af645 (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.c27
-rw-r--r--drivers/pci/host/pcie-designware.c56
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)