]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00288406 pcie: imx: enable pcie switch support
authorRichard Zhu <r65037@freescale.com>
Wed, 13 Nov 2013 08:42:06 +0000 (16:42 +0800)
committerRichard Zhu <r65037@freescale.com>
Wed, 20 Nov 2013 06:10:33 +0000 (14:10 +0800)
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>
drivers/pci/host/pci-imx6.c
drivers/pci/host/pcie-designware.c

index fbd75bf0d7418d7383bb553817a1f519c39cda8b..bb91b2274506a7aacc6493a40d9f400fdac21305 100644 (file)
@@ -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);
index c6218ff5cf38c0b210a094e4dd2a41b3ada9fad4..f4101cff0df840465bc9f54f8227e3d85da8c23f 100644 (file)
@@ -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)