Discussion:
[PATCH v1 1/4] PCI: imx6: enable pcie on imx6qdl sabreauto
Richard Zhu
2014-09-22 10:45:02 UTC
Permalink
- enable pcie on imx6qdl sabreauto boards.
- wait the clocks to stabilize after the pcie_ref_en
(IMX6Q_GPR1_PCIE_REF_CLK_EN) is set.

Signed-off-by: Richard Zhu <***@freescale.com>
---
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 4 ++++
drivers/pci/host/pci-imx6.c | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 009abd6..d6040a5 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -410,6 +410,10 @@
};
};

+&pcie {
+ status = "okay";
+};
+
&pwm3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233fe8a..bc4222b 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -275,15 +275,15 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
goto err_pcie;
}

- /* allow the clocks to stabilize */
- usleep_range(200, 500);
-
/* power up core phy and enable ref clock */
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);

+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+
/* Some boards don't have PCIe reset GPIO. */
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpio_set_value(imx6_pcie->reset_gpio, 0);
--
1.9.1
Richard Zhu
2014-09-22 10:45:04 UTC
Permalink
Signed-off-by: Richard Zhu <***@freescale.com>
---
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index ff44374..f02875e 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -113,10 +113,12 @@
#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET 0x0
#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX BIT(19)
#define IMX6Q_GPR1_PCIE_TEST_PD BIT(18)
+#define IMX6Q_GPR1_PCIE_TEST_PD_CLR 0x0
#define IMX6Q_GPR1_IPU_VPU_MUX_MASK BIT(17)
#define IMX6Q_GPR1_IPU_VPU_MUX_IPU1 0x0
#define IMX6Q_GPR1_IPU_VPU_MUX_IPU2 BIT(17)
#define IMX6Q_GPR1_PCIE_REF_CLK_EN BIT(16)
+#define IMX6Q_GPR1_PCIE_REF_CLK_CLR 0x0
#define IMX6Q_GPR1_USB_EXP_MODE BIT(15)
#define IMX6Q_GPR1_PCIE_INT BIT(14)
#define IMX6Q_GPR1_USB_OTG_ID_SEL_MASK BIT(13)
@@ -300,7 +302,9 @@
#define IMX6Q_GPR12_ARMP_APB_CLK_EN BIT(24)
#define IMX6Q_GPR12_DEVICE_TYPE (0xf << 12)
#define IMX6Q_GPR12_PCIE_CTL_2 BIT(10)
+#define IMX6Q_GPR12_PCIE_CTL_2_CLR 0x0
#define IMX6Q_GPR12_LOS_LEVEL (0x1f << 4)
+#define IMX6Q_GPR12_LOS_LEVEL_9 (0x9 << 4)

#define IMX6Q_GPR13_SDMA_STOP_REQ BIT(30)
#define IMX6Q_GPR13_CAN2_STOP_REQ BIT(29)
@@ -395,4 +399,14 @@
#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK (0x3 << 17)
#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK (0x1 << 14)

+/* For imx6sx iomux gpr register field define */
+#define IMX6SX_GPR5_PCIE_BTNRST BIT(19)
+#define IMX6SX_GPR5_PCIE_BTNRST_CLR 0x0
+#define IMX6SX_GPR5_PCIE_PERST BIT(18)
+#define IMX6SX_GPR5_PCIE_PERST_CLR 0x0
+
+#define IMX6SX_GPR12_PCIE_TEST_PD BIT(30)
+#define IMX6SX_GPR12_PCIE_TEST_PD_CLR 0x0
+#define IMX6SX_GPR12_RX_EQ_MASK (0x7 << 0)
+#define IMX6SX_GPR12_RX_EQ_2 (0x2 << 0)
#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
--
1.9.1
Richard Zhu
2014-09-22 10:45:03 UTC
Permalink
- imx6sx pcie has its own power regulator.
add the pcie power suppy into dts and binding.
- enable pcie on imx6sx soc.

Signed-off-by: Richard Zhu <***@freescale.com>
---
.../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 4 ++-
arch/arm/boot/dts/imx6sx-sdb.dts | 13 +++++++++
arch/arm/boot/dts/imx6sx.dtsi | 33 +++++++++++++---------
arch/arm/mach-imx/Kconfig | 1 +
4 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
index 9455fd0..d3b5704 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
@@ -4,7 +4,7 @@ This PCIe host controller is based on the Synopsis Designware PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.

Required properties:
-- compatible: "fsl,imx6q-pcie"
+- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie"
- reg: base addresse and length of the pcie controller
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
@@ -12,6 +12,7 @@ Required properties:
- "msi": The interrupt that is asserted when an MSI is received
- clock-names: Must include the following additional entries:
- "pcie_phy"
+- regulator: regulator used by imx6sx pcie module.

Example:

@@ -35,4 +36,5 @@ Example:
<0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 144>, <&clks 206>, <&clks 189>;
clock-names = "pcie", "pcie_bus", "pcie_phy";
+ pcie-supply = <&reg_pcie>;
};
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index a3980d9..2976913 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -251,6 +251,13 @@
};
};

+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio2 0 0>;
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
@@ -365,6 +372,12 @@
;
};

+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x17059
+ >;
+ };
+
pinctrl_vcc_sd3: vccsd3grp {
fsl,pins = <
MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index f4b9da6..4911160 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -689,9 +689,11 @@
};

gpc: ***@020dc000 {
- compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
+ compatible = "fsl,imx6sx-gpc",
+ "fsl,imx6q-gpc", "syscon";
reg = <0x020dc000 0x4000>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ pcie-supply = <&reg_pcie>;
};

iomuxc: ***@020e0000 {
@@ -1188,20 +1190,23 @@
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
- /* configuration space */
- ranges = <0x00000800 0 0x08f00000 0x08f00000 0 0x00080000
- /* downstream I/O */
- 0x81000000 0 0 0x08f80000 0 0x00010000
- /* non-prefetchable memory */
- 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
+ ranges = <0x00000800 0 0x01f00000 0x08f00000 0 0x00080000 /* configuration space */
+ 0x81000000 0 0 0x08f80000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x01000000 0x08000000 0 0x00f00000>; /* non-prefetchable memory */
num-lanes = <1>;
- interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
- <&clks IMX6SX_CLK_PCIE_AXI>,
- <&clks IMX6SX_CLK_LVDS1_OUT>,
- <&clks IMX6SX_CLK_DISPLAY_AXI>;
- clock-names = "pcie_ref_125m", "pcie_axi",
- "lvds_gate", "display_axi";
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PCIE_AXI>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>,
+ <&clks IMX6SX_CLK_LVDS1_OUT>;
+ clock-names = "pcie", "pcie_phy", "pcie_bus";
+ pcie-supply = <&reg_pcie>;
status = "disabled";
};
};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index be9a51a..0a055f0 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -718,6 +718,7 @@ config SOC_IMX6SL

config SOC_IMX6SX
bool "i.MX6 SoloX support"
+ select PCI_DOMAINS if PCI
select PINCTRL_IMX6SX
select SOC_IMX6
--
1.9.1
Richard Zhu
2014-09-22 10:45:05 UTC
Permalink
- imx6sx pcie has its own standalone pcie power supply.
In order to turn on the imx6sx pcie power during
initialization. Add the pcie regulator and the gpc regmap
into the imx6sx pcie structure.
- imx6sx pcie has the new added reset mechanism, add the
reset operations into the initialization.
- Register one PM call-back, enter/exit L2 state of the ASPM
during system suspend/resume.

Signed-off-by: Richard Zhu <***@freescale.com>
---
drivers/pci/host/pci-imx6.c | 166 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 148 insertions(+), 18 deletions(-)

diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index bc4222b..070f43a 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -18,12 +18,16 @@
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/resource.h>
#include <linux/signal.h>
+#include <linux/syscore_ops.h>
#include <linux/types.h>
#include <linux/interrupt.h>

@@ -31,15 +35,30 @@

#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)

+/* The pcie who have standalone power domain */
+#define PCIE_PHY_HAS_PWR_DOMAIN BIT(0)
+
+struct imx_pcie_data {
+ unsigned int flags;
+};
+
+static const struct imx_pcie_data imx6sx_pcie_data = {
+ .flags = PCIE_PHY_HAS_PWR_DOMAIN,
+};
+
struct imx6_pcie {
int reset_gpio;
+ const struct imx_pcie_data *data;
struct clk *pcie_bus;
struct clk *pcie_phy;
struct clk *pcie;
struct pcie_port pp;
struct regmap *iomuxc_gpr;
+ struct regmap *gpc_ips_reg;
+ struct regulator *pcie_regulator;
void __iomem *mem_base;
};
+static struct imx6_pcie *imx6_pcie;

/* PCIe Root Complex registers (memory-mapped) */
#define PCIE_RC_LCR 0x7c
@@ -77,6 +96,11 @@ 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 inline bool is_imx6sx_pcie(struct imx6_pcie *imx6_pcie)
+{
+ return imx6_pcie->data == &imx6sx_pcie_data;
+}
+
static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
{
u32 val;
@@ -275,11 +299,17 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
goto err_pcie;
}

- /* power up core phy and enable ref clock */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6SX_GPR12_PCIE_TEST_PD,
+ IMX6SX_GPR12_PCIE_TEST_PD_CLR);
+ } else {
+ /* power up core phy and enable ref clock */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+ }

/* allow the clocks to stabilize */
usleep_range(200, 500);
@@ -290,6 +320,18 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
msleep(100);
gpio_set_value(imx6_pcie->reset_gpio, 1);
}
+
+ /*
+ * iMX6SX PCIe has the stand-alone power domain.
+ * refer to the initialization for iMX6SX PCIe,
+ * release the PCIe PHY reset here,
+ * before LTSSM enable is set.
+ */
+ if (is_imx6sx_pcie(imx6_pcie))
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+ IMX6SX_GPR5_PCIE_BTNRST,
+ IMX6SX_GPR5_PCIE_BTNRST_CLR);
+
return 0;

err_pcie:
@@ -304,15 +346,38 @@ err_pcie_phy:
static void imx6_pcie_init_phy(struct pcie_port *pp)
{
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ int ret;
+
+ /*
+ * iMX6SX PCIe has the stand-alone power domain
+ * add the initialization here for iMX6SX PCIe.
+ */
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* Force PCIe PHY reset */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+ IMX6SX_GPR5_PCIE_BTNRST,
+ IMX6SX_GPR5_PCIE_BTNRST);
+
+ regmap_update_bits(imx6_pcie->gpc_ips_reg, 0, 1 << 7, 1 << 7);
+ /* Power up PCIe PHY, ANATOP_REG_CORE offset 0x140, bit13-9 */
+ regulator_set_voltage(imx6_pcie->pcie_regulator,
+ 1100000, 1100000);
+ ret = regulator_enable(imx6_pcie->pcie_regulator);
+ if (ret)
+ dev_info(pp->dev, "failed to enable pcie regulator.\n");
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6SX_GPR12_RX_EQ_MASK, IMX6SX_GPR12_RX_EQ_2);
+ }

regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+ IMX6Q_GPR12_PCIE_CTL_2,
+ IMX6Q_GPR12_PCIE_CTL_2_CLR);

/* configure constant input signal to the pcie ctrl and phy */
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
+ IMX6Q_GPR12_LOS_LEVEL, IMX6Q_GPR12_LOS_LEVEL_9);

regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
@@ -370,7 +435,8 @@ static int imx6_pcie_start_link(struct pcie_port *pp)

/* Start LTSSM. */
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+ IMX6Q_GPR12_PCIE_CTL_2,
+ IMX6Q_GPR12_PCIE_CTL_2);

ret = imx6_pcie_wait_for_link(pp);
if (ret)
@@ -546,10 +612,66 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
return 0;
}

+static const struct of_device_id imx6_pcie_of_match[] = {
+ { .compatible = "fsl,imx6q-pcie", },
+ { .compatible = "fsl,imx6sx-pcie", .data = &imx6sx_pcie_data},
+ {},
+};
+MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
+
+#ifdef CONFIG_PM_SLEEP
+static int pci_imx_suspend(void)
+{
+ int rc = 0;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* PM_TURN_OFF */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 1 << 16);
+ udelay(10);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 0 << 16);
+ }
+
+ return rc;
+}
+
+static void pci_imx_resume(void)
+{
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* reset iMX6SX PCIe */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 1 << 18);
+
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 0 << 18);
+
+ /*
+ * controller maybe turn off, re-configure again
+ * Set the CLASS_REV of RC CFG header to
+ * PCI_CLASS_BRIDGE_PCI
+ */
+ writel(readl(pp->dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_BRIDGE_PCI << 16),
+ pp->dbi_base + PCI_CLASS_REVISION);
+
+ dw_pcie_setup_rc(pp);
+ }
+}
+
+static struct syscore_ops pci_imx_syscore_ops = {
+ .suspend = pci_imx_suspend,
+ .resume = pci_imx_resume,
+};
+#endif
+
static int __init imx6_pcie_probe(struct platform_device *pdev)
{
- struct imx6_pcie *imx6_pcie;
struct pcie_port *pp;
+ const struct of_device_id *of_id =
+ of_match_device(imx6_pcie_of_match, &pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct resource *dbi_base;
int ret;
@@ -560,6 +682,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)

pp = &imx6_pcie->pp;
pp->dev = &pdev->dev;
+ imx6_pcie->data = of_id->data;

/* Added for PCI abort handling */
hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
@@ -603,9 +726,19 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(imx6_pcie->pcie);
}

- /* Grab GPR config register range */
- imx6_pcie->iomuxc_gpr =
- syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev, "pcie");
+
+ imx6_pcie->iomuxc_gpr =
+ syscon_regmap_lookup_by_compatible
+ ("fsl,imx6sx-iomuxc-gpr");
+ imx6_pcie->gpc_ips_reg =
+ syscon_regmap_lookup_by_compatible("fsl,imx6sx-gpc");
+ } else {
+ 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");
return PTR_ERR(imx6_pcie->iomuxc_gpr);
@@ -616,6 +749,9 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
return ret;

platform_set_drvdata(pdev, imx6_pcie);
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&pci_imx_syscore_ops);
+#endif
return 0;
}

@@ -627,12 +763,6 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
imx6_pcie_assert_core_reset(&imx6_pcie->pp);
}

-static const struct of_device_id imx6_pcie_of_match[] = {
- { .compatible = "fsl,imx6q-pcie", },
- {},
-};
-MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
-
static struct platform_driver imx6_pcie_driver = {
.driver = {
.name = "imx6q-pcie",
--
1.9.1
Fabio Estevam
2014-09-22 14:27:08 UTC
Permalink
Hi Richard,
Post by Richard Zhu
+#ifdef CONFIG_PM_SLEEP
+static int pci_imx_suspend(void)
+{
+ int rc = 0;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* PM_TURN_OFF */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 1 << 16);
+ udelay(10);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 0 << 16);
+ }
+
+ return rc;
You could get rid of this 'rc' variable and just return 0.
Post by Richard Zhu
+}
+
+static void pci_imx_resume(void)
+{
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* reset iMX6SX PCIe */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 1 << 18);
+
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 0 << 18);
+
+ /*
+ * controller maybe turn off, re-configure again
+ * Set the CLASS_REV of RC CFG header to
+ * PCI_CLASS_BRIDGE_PCI
+ */
+ writel(readl(pp->dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_BRIDGE_PCI << 16),
+ pp->dbi_base + PCI_CLASS_REVISION);
+
+ dw_pcie_setup_rc(pp);
+ }
+}
Not related to this patch, but on mx6q/dl we still get kernel hang
after doing suspend/resume when a PCI card is inserted.

Is this fixed on mx6solox?

Any idea as to how to fix it for mx6q?
H***@freescale.com
2014-09-23 03:09:30 UTC
Permalink
Hi Fabio:
Thanks for your comments.
-----Original Message-----
Sent: Monday, September 22, 2014 10:27 PM
To: Zhu Richard-R65037
R65073; Lucas Stach
Subject: Re: [PATCH v1 4/4] PCI: imx6: add imx6sx pcie support
Hi Richard,
Post by Richard Zhu
+#ifdef CONFIG_PM_SLEEP
+static int pci_imx_suspend(void)
+{
+ int rc = 0;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* PM_TURN_OFF */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 1 << 16);
+ udelay(10);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ BIT(16), 0 << 16);
+ }
+
+ return rc;
You could get rid of this 'rc' variable and just return 0.
[Richard] OK. Accepted.
Post by Richard Zhu
+}
+
+static void pci_imx_resume(void)
+{
+ struct pcie_port *pp = &imx6_pcie->pp;
+
+ if (is_imx6sx_pcie(imx6_pcie)) {
+ /* reset iMX6SX PCIe */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 1 << 18);
+
+ regmap_update_bits(imx6_pcie->iomuxc_gpr,
+ IOMUXC_GPR5, BIT(18), 0 << 18);
+
+ /*
+ * controller maybe turn off, re-configure again
+ * Set the CLASS_REV of RC CFG header to
+ * PCI_CLASS_BRIDGE_PCI
+ */
+ writel(readl(pp->dbi_base + PCI_CLASS_REVISION)
+ | (PCI_CLASS_BRIDGE_PCI << 16),
+ pp->dbi_base + PCI_CLASS_REVISION);
+
+ dw_pcie_setup_rc(pp);
+ }
+}
Not related to this patch, but on mx6q/dl we still get kernel hang after
doing suspend/resume when a PCI card is inserted.
Is this fixed on mx6solox?
[Richard] this is a part of the fix on imx6solox.
As I know that, there is one similar fix on the next mx6q to.
Any idea as to how to f
Fabio Estevam
2014-09-23 22:18:54 UTC
Permalink
Post by H***@freescale.com
As I know that, there is one similar fix on the next mx6q to.
What about the existing mx6q silicon version? How can we fix the hang?
H***@freescale.com
2014-09-24 02:55:53 UTC
Permalink
-----Original Message-----
Sent: Wednesday, September 24, 2014 6:19 AM
To: Zhu Richard-R65037
R65073; Lucas Stach
Subject: Re: [PATCH v1 4/4] PCI: imx6: add imx6sx pcie support
Post by H***@freescale.com
As I know that, there is one similar fix on the next mx6q to.
What about the existing mx6q silicon version? How can we fix the hang?
[Richard] There is already one SW workaround(toggle the TEST_PD bit in arch/arm/mach-imx/pm.c) for this issue.
It can workaround this issue, although we don't get guarantee from design team.

Best Regards
Richard
Fabio Estevam
2014-09-24 21:12:41 UTC
Permalink
Post by H***@freescale.com
Post by Fabio Estevam
What about the existing mx6q silicon version? How can we fix the hang?
[Richard] There is already one SW workaround(toggle the TEST_PD bit in arch/arm/mach-imx/pm.c) for this issue.
It can workaround this issue, although we don't get guarantee from design team.
This workaround is available in the FSL kernel. However, I am
interested in a solution for the mainline kernel.
H***@freescale.com
2014-09-25 01:23:07 UTC
Permalink
-----Original Message-----
Sent: Thursday, September 25, 2014 5:13 AM
To: Zhu Richard-R65037
R65073; Lucas Stach
Subject: Re: [PATCH v1 4/4] PCI: imx6: add imx6sx pcie support
Post by H***@freescale.com
Post by Fabio Estevam
What about the existing mx6q silicon version? How can we fix the hang?
[Richard] There is already one SW workaround(toggle the TEST_PD bit in
arch/arm/mach-imx/pm.c) for this issue.
Post by H***@freescale.com
It can workaround this issue, although we don't get guarantee from design
team.
This workaround is available in the FSL kernel. However, I am interested in a
solution for the mainline kernel.
[Richard] IMHO, I don't know either.
The SW workaround used in the FSL kernel can works, but it still can't get guarantee
That it can fix this problem for sure from design team yet

Lucas Stach
2014-09-22 12:06:47 UTC
Permalink
Post by Richard Zhu
- enable pcie on imx6qdl sabreauto boards.
- wait the clocks to stabilize after the pcie_ref_en
(IMX6Q_GPR1_PCIE_REF_CLK_EN) is set.
Those are two completely independent changes, even if you enable/fix a
specific board with those. So please split into DT changes (to be merged
by Shawn) and PCI changes (to be merged by Bjorn).
Post by Richard Zhu
---
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 4 ++++
drivers/pci/host/pci-imx6.c | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 009abd6..d6040a5 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -410,6 +410,10 @@
};
};
+&pcie {
+ status = "okay";
+};
+
&pwm3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233fe8a..bc4222b 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -275,15 +275,15 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
goto err_pcie;
}
- /* allow the clocks to stabilize */
- usleep_range(200, 500);
-
/* power up core phy and enable ref clock */
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+
/* Some boards don't have PCIe reset GPIO. */
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpio_set_value(imx6_pcie->reset_gpio, 0);
Are you fixing a specific issue with this? Otherwise this change doesn't
look good to me. The reference manual states that the clock must be
stable before enabling the REF_CLK_EN bit in GPR1. So moving the delay
without proof that it doesn't have adverse effects and without a good
justification seems wrong.

If this fixes a specific issue please mention it in the commit message.
Also I would like at least a confirmation from Tim Harvey that this
doesn't regress his setup. So please take him on CC for the next version
of this patch.

Regards,
Lucas
--
Pengutronix e.K. | Lucas Stach |
Industrial Linux Solutions | http://www.pengutronix.de/ |
H***@freescale.com
2014-09-23 03:25:07 UTC
Permalink
Hi Lucas:
Thanks for your comments.
-----Original Message-----
Sent: Monday, September 22, 2014 8:07 PM
To: Zhu Richard-R65037
Subject: Re: [PATCH v1 1/4] PCI: imx6: enable pcie on imx6qdl sabreauto
Post by Richard Zhu
- enable pcie on imx6qdl sabreauto boards.
- wait the clocks to stabilize after the pcie_ref_en
(IMX6Q_GPR1_PCIE_REF_CLK_EN) is set.
Those are two completely independent changes, even if you enable/fix a
specific board with those. So please split into DT changes (to be merged by
Shawn) and PCI changes (to be merged by Bjorn).
[Richard] Ok, no problem. Would be separated later.
Post by Richard Zhu
---
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 4 ++++
drivers/pci/host/pci-imx6.c | 6 +++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 009abd6..d6040a5 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -410,6 +410,10 @@
};
};
+&pcie {
+ status = "okay";
+};
+
&pwm3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm3>;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 233fe8a..bc4222b 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -275,15 +275,15 @@ static int imx6_pcie_deassert_core_reset(struct
pcie_port *pp)
Post by Richard Zhu
goto err_pcie;
}
- /* allow the clocks to stabilize */
- usleep_range(200, 500);
-
/* power up core phy and enable ref clock */
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+
/* Some boards don't have PCIe reset GPIO. */
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpio_set_value(imx6_pcie->reset_gpio, 0);
Are you fixing a specific issue with this? Otherwise this change doesn't look
good to me. The reference manual states that the clock must be stable before
enabling the REF_CLK_EN bit in GPR1. So moving the delay without proof that it
doesn't have adverse effects and without a good justification seems wrong.
If this fixes a specific issue please mention it in the commit message.
Also I would like at least a confirmation from Tim Harvey that this doesn't
regress his setup. So please take him on CC for the next version of this patch.
[Richard] yes, it is used to fix one issue on imx6qdl ard boards.
Actually, the a while delay is mandatory required after pcie_ref_clk_en is set.
Otherwise, the system would be hang on imx6qdl ard boards, because that imx6qdl boards
don't have the reset_gpio.
BTW, as I know that the clocks should be stable already after the "clk_prepare_enable" is
return.
Ok, I would CC Tim Harvey in the next version of this patch-set.
Thanks.

Best Regards
Richard Zhu
Regards,
Lucas
--
Pengutronix e.K. | Lucas Stach |
Industrial Linux
Loading...