Message ID | 1411376498-14653-3-git-send-email-r65037@freescale.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Bjorn Helgaas |
Headers | show |
Hi Richard, This commit smashes lots of things together. It would be much easier to review this if the changes were broken out appropriately. Also why are you sending RFC patches to stable? A few quick comments below, this isn't a full review yet. Am Montag, den 22.09.2014, 17:01 +0800 schrieb Richard Zhu: > - 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. > - another dis_axi clk is mandatory required by imx6sx pcie. > Add one new clk named pcie_sec into imx6_pcie structure. > - pcie_ref_125m is not used as pcie_phy clk anymore on imx6sx. > The parent clk (pcie_ref) of the pcie_bus(lvds1_gate) > is used as pcie_phy clk. You remove this clock from the binding. I don't see a reason why, just fill in pcie_ref for both pcie_bus and pcie_phy. No need to implement different code paths for this. > - Register one PM call-back, enter/exit L2 state of the ASPM > during system suspend/resume. > - wait the clocks to stabilize after the pcie_ref_en > (IMX6Q_GPR1_PCIE_REF_CLK_EN) is set. > Signed-off-by: Richard Zhu <r65037@freescale.com> > --- > arch/arm/boot/dts/imx6sx-sdb.dts | 15 ++ > arch/arm/boot/dts/imx6sx.dtsi | 33 ++-- > arch/arm/mach-imx/Kconfig | 1 + > drivers/pci/host/pci-imx6.c | 228 ++++++++++++++++++++++++---- > include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++ > 5 files changed, 249 insertions(+), 42 deletions(-) > > diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts > index a3980d9..83d0892 100644 > --- a/arch/arm/boot/dts/imx6sx-sdb.dts > +++ b/arch/arm/boot/dts/imx6sx-sdb.dts > @@ -251,6 +251,14 @@ > }; > }; > > +&pcie { > + pinctrl-names = "default"; > + pinctrl-0 = <&pinctrl_pcie>; > + power-on-gpio = <&gpio2 1 0>; No such GPIO in the binding. > + reset-gpio = <&gpio2 0 0>; > + status = "okay"; > +}; > + > &ssi2 { > status = "okay"; > }; > @@ -365,6 +373,13 @@ > >; > }; > > + pinctrl_pcie: pciegrp { > + fsl,pins = < > + MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x17059 > + MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 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..ec34698 100644 > --- a/arch/arm/boot/dts/imx6sx.dtsi > +++ b/arch/arm/boot/dts/imx6sx.dtsi > @@ -689,9 +689,11 @@ > }; > > gpc: 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 = <®_pcie>; > }; > > iomuxc: 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_sec", "pcie_bus"; > + pcie-supply = <®_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 > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c > index 233fe8a..c9b2f69 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,32 @@ > > #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; > + int power_on_gpio; > + const struct imx_pcie_data *data; > struct clk *pcie_bus; > struct clk *pcie_phy; > + struct clk *pcie_sec; > 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 +98,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; > @@ -257,10 +283,21 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) > struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); > int ret; > > - ret = clk_prepare_enable(imx6_pcie->pcie_phy); > - if (ret) { > - dev_err(pp->dev, "unable to enable pcie_phy clock\n"); > - goto err_pcie_phy; > + if (gpio_is_valid(imx6_pcie->power_on_gpio)) > + gpio_set_value(imx6_pcie->power_on_gpio, 1); > + I won't allow this to creep in again. This needs to be a proper regulator, not some kind of gpio. > + if (is_imx6sx_pcie(imx6_pcie)) { > + ret = clk_prepare_enable(imx6_pcie->pcie_sec); > + if (ret) { > + dev_err(pp->dev, "unable to enable pcie_sec clk.\n"); > + goto err_pcie_sec; > + } > + } else { > + ret = clk_prepare_enable(imx6_pcie->pcie_phy); > + if (ret) { > + dev_err(pp->dev, "unable to enable pcie_phy clock\n"); > + goto err_pcie_phy; > + } > } > > ret = clk_prepare_enable(imx6_pcie->pcie_bus); > @@ -275,28 +312,50 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) > goto err_pcie; > } > > + 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); > > - /* 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); > - > /* Some boards don't have PCIe reset GPIO. */ > if (gpio_is_valid(imx6_pcie->reset_gpio)) { > gpio_set_value(imx6_pcie->reset_gpio, 0); > 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: > clk_disable_unprepare(imx6_pcie->pcie_bus); > err_pcie_bus: > - clk_disable_unprepare(imx6_pcie->pcie_phy); > + if (!is_imx6sx_pcie(imx6_pcie)) > + clk_disable_unprepare(imx6_pcie->pcie_phy); > err_pcie_phy: > + if (is_imx6sx_pcie(imx6_pcie)) > + clk_disable_unprepare(imx6_pcie->pcie_sec); > +err_pcie_sec: > return ret; > > } > @@ -304,15 +363,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); What is this? Is this a regulator? If so, why isn't it abstracted as a proper regulator? > + /* 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"); This regulator gets enabled here, but I don't see any path were we would disable it. Is this a always-on regulator or are you simply missing the calls to disable it in the runtime-pm hooks? > + 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 +452,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 +629,73 @@ 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); Why are there no defines for those bits? I can't really tell what's going on here. Is this some kind of power gating the SoC partition? In that case it should really be implemented as a power-domain and not as some kind of ad-hoc GPR register bashing. > + } > + > + 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); > + > + /* 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); Why the double reset? > + } > +} > + > +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 +706,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, > @@ -581,12 +728,26 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > } > } > > + imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); > + if (gpio_is_valid(imx6_pcie->power_on_gpio)) { > + ret = devm_gpio_request_one(&pdev->dev, > + imx6_pcie->power_on_gpio, > + GPIOF_OUT_INIT_LOW, > + "PCIe power enable"); > + if (ret) { > + dev_err(&pdev->dev, "unable to get power-on gpio\n"); > + return ret; > + } > + } > + > /* Fetch clocks */ > - imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); > - if (IS_ERR(imx6_pcie->pcie_phy)) { > - dev_err(&pdev->dev, > - "pcie_phy clock source missing or invalid\n"); > - return PTR_ERR(imx6_pcie->pcie_phy); > + if (!is_imx6sx_pcie(imx6_pcie)) { > + imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); > + if (IS_ERR(imx6_pcie->pcie_phy)) { > + dev_err(&pdev->dev, > + "pcie_phy clock source missing or invalid\n"); > + return PTR_ERR(imx6_pcie->pcie_phy); > + } > } > Missing binding update for the changed clock handling. Also what is this clock pcie_sec? Is it really a second AXI clock? I highly doubt that the register interface of the core is clocked by two different clocks. What blocks of the dw_pci core does this clock feed? > imx6_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_bus"); > @@ -604,8 +765,22 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > } > > /* Grab GPR config register range */ > - imx6_pcie->iomuxc_gpr = > - syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); > + if (is_imx6sx_pcie(imx6_pcie)) { > + /* Get pcie regulator */ > + imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev, "pcie"); Uh, this has nothing to do with the GPR range, so the comment above is confusing. Also missing binding update for this regulator. > + > + /* Grab GPR config register range */ > + imx6_pcie->iomuxc_gpr = > + syscon_regmap_lookup_by_compatible > + ("fsl,imx6sx-iomuxc-gpr"); > + /* Grab GPC IPS register range */ > + 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 +791,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 +805,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", > 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 */
Hi Lucas: Thanks for your quick review comments. > -----Original Message----- > From: Lucas Stach [mailto:l.stach@pengutronix.de] > Sent: Monday, September 22, 2014 6:02 PM > To: Zhu Richard-R65037 > Cc: linux-pci-owner@vger.kernel.org; stable@vger.kernel.org; linux- > pci@vger.kernel.org > Subject: Re: [PATCH RFC 2/2] PCI: imx6: add imx6sx pcie support > > Hi Richard, > > This commit smashes lots of things together. It would be much easier to review > this if the changes were broken out appropriately. > > Also why are you sending RFC patches to stable? > > A few quick comments below, this isn't a full review yet. > > Am Montag, den 22.09.2014, 17:01 +0800 schrieb Richard Zhu: > > - 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. > > - another dis_axi clk is mandatory required by imx6sx pcie. > > Add one new clk named pcie_sec into imx6_pcie structure. > > - pcie_ref_125m is not used as pcie_phy clk anymore on imx6sx. > > The parent clk (pcie_ref) of the pcie_bus(lvds1_gate) is used as > > pcie_phy clk. > > You remove this clock from the binding. I don't see a reason why, just fill in > pcie_ref for both pcie_bus and pcie_phy. No need to implement different code > paths for this. [Richard] pcie_ref is not only used as pcie_phy, but also as the parent of the pcie_bus. Pcie_phy would be enabled automatically, when pcie_bus is enabled on imx6sx. > > > - Register one PM call-back, enter/exit L2 state of the ASPM during > > system suspend/resume. > > - wait the clocks to stabilize after the pcie_ref_en > > (IMX6Q_GPR1_PCIE_REF_CLK_EN) is set. > > > > Signed-off-by: Richard Zhu <r65037@freescale.com> > > --- > > arch/arm/boot/dts/imx6sx-sdb.dts | 15 ++ > > arch/arm/boot/dts/imx6sx.dtsi | 33 ++-- > > arch/arm/mach-imx/Kconfig | 1 + > > drivers/pci/host/pci-imx6.c | 228 ++++++++++++++++++++++++- > --- > > include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++ > > 5 files changed, 249 insertions(+), 42 deletions(-) > > > > diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts > > b/arch/arm/boot/dts/imx6sx-sdb.dts > > index a3980d9..83d0892 100644 > > --- a/arch/arm/boot/dts/imx6sx-sdb.dts > > +++ b/arch/arm/boot/dts/imx6sx-sdb.dts > > @@ -251,6 +251,14 @@ > > }; > > }; > > > > +&pcie { > > + pinctrl-names = "default"; > > + pinctrl-0 = <&pinctrl_pcie>; > > + power-on-gpio = <&gpio2 1 0>; > > No such GPIO in the binding. [Richard] power-on-gpio would be removed. > > > + reset-gpio = <&gpio2 0 0>; > > + status = "okay"; > > +}; > > + > > &ssi2 { > > status = "okay"; > > }; > > @@ -365,6 +373,13 @@ > > >; > > }; > > > > + pinctrl_pcie: pciegrp { > > + fsl,pins = < > > + MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x17059 > > + MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 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..ec34698 100644 > > --- a/arch/arm/boot/dts/imx6sx.dtsi > > +++ b/arch/arm/boot/dts/imx6sx.dtsi > > @@ -689,9 +689,11 @@ > > }; > > > > gpc: 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 = <®_pcie>; > > }; > > > > iomuxc: 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_sec", "pcie_bus"; > > + pcie-supply = <®_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 > > > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c > > index 233fe8a..c9b2f69 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,32 @@ > > > > #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; > > + int power_on_gpio; > > + const struct imx_pcie_data *data; > > struct clk *pcie_bus; > > struct clk *pcie_phy; > > + struct clk *pcie_sec; > > 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 +98,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; > > @@ -257,10 +283,21 @@ static int imx6_pcie_deassert_core_reset(struct > pcie_port *pp) > > struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); > > int ret; > > > > - ret = clk_prepare_enable(imx6_pcie->pcie_phy); > > - if (ret) { > > - dev_err(pp->dev, "unable to enable pcie_phy clock\n"); > > - goto err_pcie_phy; > > + if (gpio_is_valid(imx6_pcie->power_on_gpio)) > > + gpio_set_value(imx6_pcie->power_on_gpio, 1); > > + > > I won't allow this to creep in again. This needs to be a proper regulator, not > some kind of gpio. [Richard] would be removed. Thanks. > > > + if (is_imx6sx_pcie(imx6_pcie)) { > > + ret = clk_prepare_enable(imx6_pcie->pcie_sec); > > + if (ret) { > > + dev_err(pp->dev, "unable to enable pcie_sec clk.\n"); > > + goto err_pcie_sec; > > + } > > + } else { > > + ret = clk_prepare_enable(imx6_pcie->pcie_phy); > > + if (ret) { > > + dev_err(pp->dev, "unable to enable pcie_phy clock\n"); > > + goto err_pcie_phy; > > + } > > } > > > > ret = clk_prepare_enable(imx6_pcie->pcie_bus); > > @@ -275,28 +312,50 @@ static int imx6_pcie_deassert_core_reset(struct > pcie_port *pp) > > goto err_pcie; > > } > > > > + 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); > > > > - /* 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); > > - > > /* Some boards don't have PCIe reset GPIO. */ > > if (gpio_is_valid(imx6_pcie->reset_gpio)) { > > gpio_set_value(imx6_pcie->reset_gpio, 0); > > 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: > > clk_disable_unprepare(imx6_pcie->pcie_bus); > > err_pcie_bus: > > - clk_disable_unprepare(imx6_pcie->pcie_phy); > > + if (!is_imx6sx_pcie(imx6_pcie)) > > + clk_disable_unprepare(imx6_pcie->pcie_phy); > > err_pcie_phy: > > + if (is_imx6sx_pcie(imx6_pcie)) > > + clk_disable_unprepare(imx6_pcie->pcie_sec); > > +err_pcie_sec: > > return ret; > > > > } > > @@ -304,15 +363,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); > > What is this? Is this a regulator? If so, why isn't it abstracted as a proper > regulator? > [Richard]No, it's a pre-condition before enable the pcie regulator. > > + /* 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"); > > This regulator gets enabled here, but I don't see any path were we would > disable it. Is this a always-on regulator or are you simply missing the calls > to disable it in the runtime-pm hooks? [Richard]This regulator is enabled-once during pcie initialization. imx pcie has to be re-initialized completely if this regulator is disabled once. It's a always on regulator after the imx pcie is initialized. > > > + 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 +452,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 +629,73 @@ 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); > > Why are there no defines for those bits? I can't really tell what's going on > here. Is this some kind of power gating the SoC partition? In that case it > should really be implemented as a power-domain and not as some kind of ad-hoc > GPR register bashing. [Richard] Not a power-domain. This bit is just used as RC to kick-off the PM_TURN_OFF message to EP. It's is used to indicated to EP that the RC is ready to ENTER into L2 state of ASPM. > > > + } > > + > > + 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); > > + > > + /* 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); > > Why the double reset? [Richard] The second one would be removed. Thanks. > > > + } > > +} > > + > > +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 +706,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, @@ > > -581,12 +728,26 @@ static int __init imx6_pcie_probe(struct platform_device > *pdev) > > } > > } > > > > + imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); > > + if (gpio_is_valid(imx6_pcie->power_on_gpio)) { > > + ret = devm_gpio_request_one(&pdev->dev, > > + imx6_pcie->power_on_gpio, > > + GPIOF_OUT_INIT_LOW, > > + "PCIe power enable"); > > + if (ret) { > > + dev_err(&pdev->dev, "unable to get power-on gpio\n"); > > + return ret; > > + } > > + } > > + > > /* Fetch clocks */ > > - imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); > > - if (IS_ERR(imx6_pcie->pcie_phy)) { > > - dev_err(&pdev->dev, > > - "pcie_phy clock source missing or invalid\n"); > > - return PTR_ERR(imx6_pcie->pcie_phy); > > + if (!is_imx6sx_pcie(imx6_pcie)) { > > + imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); > > + if (IS_ERR(imx6_pcie->pcie_phy)) { > > + dev_err(&pdev->dev, > > + "pcie_phy clock source missing or invalid\n"); > > + return PTR_ERR(imx6_pcie->pcie_phy); > > + } > > } > > > > Missing binding update for the changed clock handling. Also what is this clock > pcie_sec? Is it really a second AXI clock? I highly doubt that the register > interface of the core is clocked by two different clocks. What blocks of the > dw_pci core does this clock feed? [Richard] As I know that imx6sx pcie axi clock is contained in the dis_axi domain. Dis_axi should be turned-on, if pcie is enabled. How about use the pcie_bus binding dis_axi on imx6sx? Since the pcie_ref is not only used as pcie_ref but also as the parent of the pcie_phy on imx6sx. In this case, we can keep alignment the clocks binding with other imx6 pcie. > > > imx6_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_bus"); @@ > > -604,8 +765,22 @@ static int __init imx6_pcie_probe(struct platform_device > *pdev) > > } > > > > /* Grab GPR config register range */ > > - imx6_pcie->iomuxc_gpr = > > - syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); > > + if (is_imx6sx_pcie(imx6_pcie)) { > > + /* Get pcie regulator */ > > + imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev, "pcie"); > > Uh, this has nothing to do with the GPR range, so the comment above is > confusing. Also missing binding update for this regulator. [Richard] The comment would be removed. Binding update for this regulator would be added later. > > > + > > + /* Grab GPR config register range */ > > + imx6_pcie->iomuxc_gpr = > > + syscon_regmap_lookup_by_compatible > > + ("fsl,imx6sx-iomuxc-gpr"); > > + /* Grab GPC IPS register range */ > > + 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 +791,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 +805,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", > > 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 */ > > -- > Pengutronix e.K. | Lucas Stach | > Industrial Linux Solutions | http://www.pengutronix.de/ | Best Regards Richard Zhu
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBMdWNhcyBTdGFjaCBbbWFpbHRv Omwuc3RhY2hAcGVuZ3V0cm9uaXguZGVdDQo+IFNlbnQ6IE1vbmRheSwgU2VwdGVtYmVyIDIyLCAy MDE0IDY6MDIgUE0NCj4gVG86IFpodSBSaWNoYXJkLVI2NTAzNw0KPiBDYzogbGludXgtcGNpLW93 bmVyQHZnZXIua2VybmVsLm9yZzsgc3RhYmxlQHZnZXIua2VybmVsLm9yZzsgbGludXgtDQo+IHBj aUB2Z2VyLmtlcm5lbC5vcmcNCj4gU3ViamVjdDogUmU6IFtQQVRDSCBSRkMgMi8yXSBQQ0k6IGlt eDY6IGFkZCBpbXg2c3ggcGNpZSBzdXBwb3J0DQo+IA0KPiBIaSBSaWNoYXJkLA0KPiANCj4gVGhp cyBjb21taXQgc21hc2hlcyBsb3RzIG9mIHRoaW5ncyB0b2dldGhlci4gSXQgd291bGQgYmUgbXVj aCBlYXNpZXIgdG8gcmV2aWV3DQo+IHRoaXMgaWYgdGhlIGNoYW5nZXMgd2VyZSBicm9rZW4gb3V0 IGFwcHJvcHJpYXRlbHkuDQo+IA0KPiBBbHNvIHdoeSBhcmUgeW91IHNlbmRpbmcgUkZDIHBhdGNo ZXMgdG8gc3RhYmxlPw0KPiANCj4gQSBmZXcgcXVpY2sgY29tbWVudHMgYmVsb3csIHRoaXMgaXNu J3QgYSBmdWxsIHJldmlldyB5ZXQuDQo+IA0KW1JpY2hhcmRdIFRoaXMgY29tbWVudCBpcyBtaXNz aW5nIGluIGxhc3QgcmVwbHkuIA0KT2ssIGNvbW1pdCB3b3VsZCBiZSBzZXBhcmF0ZWQgaW4gdGhl IG5leHQgcmV2aWV3LWFyb3VuZC4gDQpTdGFibGUgaXMgb25lIG1pc3Rha2Ugd2hlbiBJIGNvcHkv cGFzdCB0aGUgLS1jYyBtYWlsIGxpc3QuIEl0IHdvdWxkIGJlIHJlbW92ZWQgbGF0ZXIuDQoNCkJl c3QgUmVnYXJkcw0KUmljaGFyZCBaaHUNCg0KPiBBbSBNb250YWcsIGRlbiAyMi4wOS4yMDE0LCAx NzowMSArMDgwMCBzY2hyaWViIFJpY2hhcmQgWmh1Og0KPiA+IC0gaW14NnN4IHBjaWUgaGFzIGl0 cyBvd24gc3RhbmRhbG9uZSBwY2llIHBvd2VyIHN1cHBseS4NCj4gPiBJbiBvcmRlciB0byB0dXJu IG9uIHRoZSBpbXg2c3ggcGNpZSBwb3dlciBkdXJpbmcgaW5pdGlhbGl6YXRpb24uIEFkZA0KPiA+ IHRoZSBwY2llIHJlZ3VsYXRvciBhbmQgdGhlIGdwYyByZWdtYXAgaW50byB0aGUgaW14NnN4IHBj aWUgc3RydWN0dXJlLg0KPiA+IC0gaW14NnN4IHBjaWUgaGFzIHRoZSBuZXcgYWRkZWQgcmVzZXQg bWVjaGFuaXNtLCBhZGQgdGhlIHJlc2V0DQo+ID4gb3BlcmF0aW9ucyBpbnRvIHRoZSBpbml0aWFs aXphdGlvbi4NCj4gPiAtIGFub3RoZXIgZGlzX2F4aSBjbGsgaXMgbWFuZGF0b3J5IHJlcXVpcmVk IGJ5IGlteDZzeCBwY2llLg0KPiA+IEFkZCBvbmUgbmV3IGNsayBuYW1lZCBwY2llX3NlYyBpbnRv IGlteDZfcGNpZSBzdHJ1Y3R1cmUuDQo+ID4gLSBwY2llX3JlZl8xMjVtIGlzIG5vdCB1c2VkIGFz IHBjaWVfcGh5IGNsayBhbnltb3JlIG9uIGlteDZzeC4NCj4gPiBUaGUgcGFyZW50IGNsayAocGNp ZV9yZWYpIG9mIHRoZSBwY2llX2J1cyhsdmRzMV9nYXRlKSBpcyB1c2VkIGFzDQo+ID4gcGNpZV9w aHkgY2xrLg0KPiANCj4gWW91IHJlbW92ZSB0aGlzIGNsb2NrIGZyb20gdGhlIGJpbmRpbmcuIEkg ZG9uJ3Qgc2VlIGEgcmVhc29uIHdoeSwganVzdCBmaWxsIGluDQo+IHBjaWVfcmVmIGZvciBib3Ro IHBjaWVfYnVzIGFuZCBwY2llX3BoeS4gTm8gbmVlZCB0byBpbXBsZW1lbnQgZGlmZmVyZW50IGNv ZGUNCj4gcGF0aHMgZm9yIHRoaXMuDQo+IA0KPiA+IC0gUmVnaXN0ZXIgb25lIFBNIGNhbGwtYmFj aywgZW50ZXIvZXhpdCBMMiBzdGF0ZSBvZiB0aGUgQVNQTSBkdXJpbmcNCj4gPiBzeXN0ZW0gc3Vz cGVuZC9yZXN1bWUuDQo+ID4gLSB3YWl0IHRoZSBjbG9ja3MgdG8gc3RhYmlsaXplIGFmdGVyIHRo ZSBwY2llX3JlZl9lbg0KPiA+IChJTVg2UV9HUFIxX1BDSUVfUkVGX0NMS19FTikgaXMgc2V0Lg0K PiANCj4gDQo+ID4gU2lnbmVkLW9mZi1ieTogUmljaGFyZCBaaHUgPHI2NTAzN0BmcmVlc2NhbGUu Y29tPg0KPiA+IC0tLQ0KPiA+ICBhcmNoL2FybS9ib290L2R0cy9pbXg2c3gtc2RiLmR0cyAgICAg ICAgICAgIHwgIDE1ICsrDQo+ID4gIGFyY2gvYXJtL2Jvb3QvZHRzL2lteDZzeC5kdHNpICAgICAg ICAgICAgICAgfCAgMzMgKystLQ0KPiA+ICBhcmNoL2FybS9tYWNoLWlteC9LY29uZmlnICAgICAg ICAgICAgICAgICAgIHwgICAxICsNCj4gPiAgZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jICAg ICAgICAgICAgICAgICB8IDIyOCArKysrKysrKysrKysrKysrKysrKysrKystDQo+IC0tLQ0KPiA+ ICBpbmNsdWRlL2xpbnV4L21mZC9zeXNjb24vaW14NnEtaW9tdXhjLWdwci5oIHwgIDE0ICsrDQo+ ID4gIDUgZmlsZXMgY2hhbmdlZCwgMjQ5IGluc2VydGlvbnMoKyksIDQyIGRlbGV0aW9ucygtKQ0K PiA+DQo+ID4gZGlmZiAtLWdpdCBhL2FyY2gvYXJtL2Jvb3QvZHRzL2lteDZzeC1zZGIuZHRzDQo+ ID4gYi9hcmNoL2FybS9ib290L2R0cy9pbXg2c3gtc2RiLmR0cw0KPiA+IGluZGV4IGEzOTgwZDku LjgzZDA4OTIgMTAwNjQ0DQo+ID4gLS0tIGEvYXJjaC9hcm0vYm9vdC9kdHMvaW14NnN4LXNkYi5k dHMNCj4gPiArKysgYi9hcmNoL2FybS9ib290L2R0cy9pbXg2c3gtc2RiLmR0cw0KPiA+IEBAIC0y NTEsNiArMjUxLDE0IEBADQo+ID4gIAl9Ow0KPiA+ICB9Ow0KPiA+DQo+ID4gKyZwY2llIHsNCj4g PiArCXBpbmN0cmwtbmFtZXMgPSAiZGVmYXVsdCI7DQo+ID4gKwlwaW5jdHJsLTAgPSA8JnBpbmN0 cmxfcGNpZT47DQo+ID4gKwlwb3dlci1vbi1ncGlvID0gPCZncGlvMiAxIDA+Ow0KPiANCj4gTm8g c3VjaCBHUElPIGluIHRoZSBiaW5kaW5nLg0KPiANCj4gPiArCXJlc2V0LWdwaW8gPSA8JmdwaW8y IDAgMD47DQo+ID4gKwlzdGF0dXMgPSAib2theSI7DQo+ID4gK307DQo+ID4gKw0KPiA+ICAmc3Np MiB7DQo+ID4gIAlzdGF0dXMgPSAib2theSI7DQo+ID4gIH07DQo+ID4gQEAgLTM2NSw2ICszNzMs MTMgQEANCj4gPiAgCQkJPjsNCj4gPiAgCQl9Ow0KPiA+DQo+ID4gKwkJcGluY3RybF9wY2llOiBw Y2llZ3JwIHsNCj4gPiArCQkJZnNsLHBpbnMgPSA8DQo+ID4gKwkJCQlNWDZTWF9QQURfRU5FVDFf Q09MX19HUElPMl9JT18wIDB4MTcwNTkNCj4gPiArCQkJCU1YNlNYX1BBRF9FTkVUMV9DUlNfX0dQ SU8yX0lPXzEJMHgxNzA1OQ0KPiA+ICsJCQk+Ow0KPiA+ICsJCX07DQo+ID4gKw0KPiA+ICAJCXBp bmN0cmxfdmNjX3NkMzogdmNjc2QzZ3JwIHsNCj4gPiAgCQkJZnNsLHBpbnMgPSA8DQo+ID4gIAkJ CQlNWDZTWF9QQURfS0VZX0NPTDFfX0dQSU8yX0lPXzExCQkweDE3MDU5DQo+ID4gZGlmZiAtLWdp dCBhL2FyY2gvYXJtL2Jvb3QvZHRzL2lteDZzeC5kdHNpDQo+ID4gYi9hcmNoL2FybS9ib290L2R0 cy9pbXg2c3guZHRzaSBpbmRleCBmNGI5ZGE2Li5lYzM0Njk4IDEwMDY0NA0KPiA+IC0tLSBhL2Fy Y2gvYXJtL2Jvb3QvZHRzL2lteDZzeC5kdHNpDQo+ID4gKysrIGIvYXJjaC9hcm0vYm9vdC9kdHMv aW14NnN4LmR0c2kNCj4gPiBAQCAtNjg5LDkgKzY4OSwxMSBAQA0KPiA+ICAJCQl9Ow0KPiA+DQo+ ID4gIAkJCWdwYzogZ3BjQDAyMGRjMDAwIHsNCj4gPiAtCQkJCWNvbXBhdGlibGUgPSAiZnNsLGlt eDZzeC1ncGMiLCAiZnNsLGlteDZxLWdwYyI7DQo+ID4gKwkJCQljb21wYXRpYmxlID0gImZzbCxp bXg2c3gtZ3BjIiwNCj4gPiArCQkJCQkgICAgICJmc2wsaW14NnEtZ3BjIiwgInN5c2NvbiI7DQo+ ID4gIAkJCQlyZWcgPSA8MHgwMjBkYzAwMCAweDQwMDA+Ow0KPiA+ICAJCQkJaW50ZXJydXB0cyA9 IDxHSUNfU1BJIDg5IElSUV9UWVBFX0xFVkVMX0hJR0g+Ow0KPiA+ICsJCQkJcGNpZS1zdXBwbHkg PSA8JnJlZ19wY2llPjsNCj4gPiAgCQkJfTsNCj4gPg0KPiA+ICAJCQlpb211eGM6IGlvbXV4Y0Aw MjBlMDAwMCB7DQo+ID4gQEAgLTExODgsMjAgKzExOTAsMjMgQEANCj4gPiAgCQkJI2FkZHJlc3Mt Y2VsbHMgPSA8Mz47DQo+ID4gIAkJCSNzaXplLWNlbGxzID0gPDI+Ow0KPiA+ICAJCQlkZXZpY2Vf dHlwZSA9ICJwY2kiOw0KPiA+IC0JCQkJICAvKiBjb25maWd1cmF0aW9uIHNwYWNlICovDQo+ID4g LQkJCXJhbmdlcyA9IDwweDAwMDAwODAwIDAgMHgwOGYwMDAwMCAweDA4ZjAwMDAwIDAgMHgwMDA4 MDAwMA0KPiA+IC0JCQkJICAvKiBkb3duc3RyZWFtIEkvTyAqLw0KPiA+IC0JCQkJICAweDgxMDAw MDAwIDAgMCAgICAgICAgICAweDA4ZjgwMDAwIDAgMHgwMDAxMDAwMA0KPiA+IC0JCQkJICAvKiBu b24tcHJlZmV0Y2hhYmxlIG1lbW9yeSAqLw0KPiA+IC0JCQkJICAweDgyMDAwMDAwIDAgMHgwODAw MDAwMCAweDA4MDAwMDAwIDAgMHgwMGYwMDAwMD47DQo+ID4gKwkJCXJhbmdlcyA9IDwweDAwMDAw ODAwIDAgMHgwMWYwMDAwMCAweDA4ZjAwMDAwIDAgMHgwMDA4MDAwMCAvKg0KPiBjb25maWd1cmF0 aW9uIHNwYWNlICovDQo+ID4gKwkJCQkgIDB4ODEwMDAwMDAgMCAwICAgICAgICAgIDB4MDhmODAw MDAgMCAweDAwMDEwMDAwIC8qDQo+IGRvd25zdHJlYW0gSS9PICovDQo+ID4gKwkJCQkgIDB4ODIw MDAwMDAgMCAweDAxMDAwMDAwIDB4MDgwMDAwMDAgMCAweDAwZjAwMDAwPjsgLyoNCj4gPiArbm9u LXByZWZldGNoYWJsZSBtZW1vcnkgKi8NCj4gPiAgCQkJbnVtLWxhbmVzID0gPDE+Ow0KPiA+IC0J CQlpbnRlcnJ1cHRzID0gPEdJQ19TUEkgMTIzIElSUV9UWVBFX0xFVkVMX0hJR0g+Ow0KPiA+IC0J CQljbG9ja3MgPSA8JmNsa3MgSU1YNlNYX0NMS19QQ0lFX1JFRl8xMjVNPiwNCj4gPiAtCQkJCSA8 JmNsa3MgSU1YNlNYX0NMS19QQ0lFX0FYST4sDQo+ID4gLQkJCQkgPCZjbGtzIElNWDZTWF9DTEtf TFZEUzFfT1VUPiwNCj4gPiAtCQkJCSA8JmNsa3MgSU1YNlNYX0NMS19ESVNQTEFZX0FYST47DQo+ ID4gLQkJCWNsb2NrLW5hbWVzID0gInBjaWVfcmVmXzEyNW0iLCAicGNpZV9heGkiLA0KPiA+IC0J CQkJICAgICAgImx2ZHNfZ2F0ZSIsICJkaXNwbGF5X2F4aSI7DQo+ID4gKwkJCWludGVycnVwdHMg PSA8R0lDX1NQSSAxMjAgSVJRX1RZUEVfTEVWRUxfSElHSD47DQo+ID4gKwkJCWludGVycnVwdC1u YW1lcyA9ICJtc2kiOw0KPiA+ICsJCQkjaW50ZXJydXB0LWNlbGxzID0gPDE+Ow0KPiA+ICsJCQlp bnRlcnJ1cHQtbWFwLW1hc2sgPSA8MCAwIDAgMHg3PjsNCj4gPiArCQkJaW50ZXJydXB0LW1hcCA9 IDwwIDAgMCAxICZpbnRjIEdJQ19TUEkgMTIzIElSUV9UWVBFX0xFVkVMX0hJR0g+LA0KPiA+ICsJ CQkgICAgICAgICAgICAgICAgPDAgMCAwIDIgJmludGMgR0lDX1NQSSAxMjIgSVJRX1RZUEVfTEVW RUxfSElHSD4sDQo+ID4gKwkJCSAgICAgICAgICAgICAgICA8MCAwIDAgMyAmaW50YyBHSUNfU1BJ IDEyMSBJUlFfVFlQRV9MRVZFTF9ISUdIPiwNCj4gPiArCQkJICAgICAgICAgICAgICAgIDwwIDAg MCA0ICZpbnRjIEdJQ19TUEkgMTIwIElSUV9UWVBFX0xFVkVMX0hJR0g+Ow0KPiA+ICsJCQljbG9j a3MgPSA8JmNsa3MgSU1YNlNYX0NMS19QQ0lFX0FYST4sDQo+ID4gKwkJCQkgPCZjbGtzIElNWDZT WF9DTEtfRElTUExBWV9BWEk+LA0KPiA+ICsJCQkJIDwmY2xrcyBJTVg2U1hfQ0xLX0xWRFMxX09V VD47DQo+ID4gKwkJCWNsb2NrLW5hbWVzID0gInBjaWUiLCAicGNpZV9zZWMiLCAicGNpZV9idXMi Ow0KPiA+ICsJCQlwY2llLXN1cHBseSA9IDwmcmVnX3BjaWU+Ow0KPiA+ICAJCQlzdGF0dXMgPSAi ZGlzYWJsZWQiOw0KPiA+ICAJCX07DQo+ID4gIAl9Ow0KPiA+IGRpZmYgLS1naXQgYS9hcmNoL2Fy bS9tYWNoLWlteC9LY29uZmlnIGIvYXJjaC9hcm0vbWFjaC1pbXgvS2NvbmZpZw0KPiA+IGluZGV4 IGJlOWE1MWEuLjBhMDU1ZjAgMTAwNjQ0DQo+ID4gLS0tIGEvYXJjaC9hcm0vbWFjaC1pbXgvS2Nv bmZpZw0KPiA+ICsrKyBiL2FyY2gvYXJtL21hY2gtaW14L0tjb25maWcNCj4gPiBAQCAtNzE4LDYg KzcxOCw3IEBAIGNvbmZpZyBTT0NfSU1YNlNMDQo+ID4NCj4gPiAgY29uZmlnIFNPQ19JTVg2U1gN Cj4gPiAgCWJvb2wgImkuTVg2IFNvbG9YIHN1cHBvcnQiDQo+ID4gKwlzZWxlY3QgUENJX0RPTUFJ TlMgaWYgUENJDQo+ID4gIAlzZWxlY3QgUElOQ1RSTF9JTVg2U1gNCj4gPiAgCXNlbGVjdCBTT0Nf SU1YNg0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYyBi L2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KPiA+IGluZGV4IDIzM2ZlOGEuLmM5YjJmNjkg MTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jDQo+ID4gKysrIGIv ZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jDQo+ID4gQEAgLTE4LDEyICsxOCwxNiBAQA0KPiA+ ICAjaW5jbHVkZSA8bGludXgvbWZkL3N5c2Nvbi5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvbWZk L3N5c2Nvbi9pbXg2cS1pb211eGMtZ3ByLmg+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9tb2R1bGUu aD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L29mX2FkZHJlc3MuaD4NCj4gPiArI2luY2x1ZGUgPGxp bnV4L29mX2RldmljZS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvb2ZfZ3Bpby5oPg0KPiA+ICAj aW5jbHVkZSA8bGludXgvcGNpLmg+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZp Y2UuaD4NCj4gPiAgI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPg0KPiA+ICsjaW5jbHVkZSA8bGlu dXgvcmVndWxhdG9yL2NvbnN1bWVyLmg+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9yZXNvdXJjZS5o Pg0KPiA+ICAjaW5jbHVkZSA8bGludXgvc2lnbmFsLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9z eXNjb3JlX29wcy5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4NCj4gPiAgI2luY2x1 ZGUgPGxpbnV4L2ludGVycnVwdC5oPg0KPiA+DQo+ID4gQEAgLTMxLDE1ICszNSwzMiBAQA0KPiA+ DQo+ID4gICNkZWZpbmUgdG9faW14Nl9wY2llKHgpCWNvbnRhaW5lcl9vZih4LCBzdHJ1Y3QgaW14 Nl9wY2llLCBwcCkNCj4gPg0KPiA+ICsvKiBUaGUgcGNpZSB3aG8gaGF2ZSBzdGFuZGFsb25lIHBv d2VyIGRvbWFpbiAqLw0KPiA+ICsjZGVmaW5lIFBDSUVfUEhZX0hBU19QV1JfRE9NQUlOCQlCSVQo MCkNCj4gPiArDQo+ID4gK3N0cnVjdCBpbXhfcGNpZV9kYXRhIHsNCj4gPiArCXVuc2lnbmVkIGlu dCBmbGFnczsNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaW14X3Bj aWVfZGF0YSBpbXg2c3hfcGNpZV9kYXRhID0gew0KPiA+ICsJLmZsYWdzID0gUENJRV9QSFlfSEFT X1BXUl9ET01BSU4sDQo+ID4gK307DQo+ID4gKw0KPiA+ICBzdHJ1Y3QgaW14Nl9wY2llIHsNCj4g PiAgCWludAkJCXJlc2V0X2dwaW87DQo+ID4gKwlpbnQJCQlwb3dlcl9vbl9ncGlvOw0KPiA+ICsJ Y29uc3Qgc3RydWN0CQlpbXhfcGNpZV9kYXRhICpkYXRhOw0KPiA+ICAJc3RydWN0IGNsawkJKnBj aWVfYnVzOw0KPiA+ICAJc3RydWN0IGNsawkJKnBjaWVfcGh5Ow0KPiA+ICsJc3RydWN0IGNsawkJ KnBjaWVfc2VjOw0KPiA+ICAJc3RydWN0IGNsawkJKnBjaWU7DQo+ID4gIAlzdHJ1Y3QgcGNpZV9w b3J0CXBwOw0KPiA+ICAJc3RydWN0IHJlZ21hcAkJKmlvbXV4Y19ncHI7DQo+ID4gKwlzdHJ1Y3Qg cmVnbWFwCQkqZ3BjX2lwc19yZWc7DQo+ID4gKwlzdHJ1Y3QgcmVndWxhdG9yCSpwY2llX3JlZ3Vs YXRvcjsNCj4gPiAgCXZvaWQgX19pb21lbQkJKm1lbV9iYXNlOw0KPiA+ICB9Ow0KPiA+ICtzdGF0 aWMgc3RydWN0IGlteDZfcGNpZSAqaW14Nl9wY2llOw0KPiA+DQo+ID4gIC8qIFBDSWUgUm9vdCBD b21wbGV4IHJlZ2lzdGVycyAobWVtb3J5LW1hcHBlZCkgKi8NCj4gPiAgI2RlZmluZSBQQ0lFX1JD X0xDUgkJCQkweDdjDQo+ID4gQEAgLTc3LDYgKzk4LDExIEBAIHN0cnVjdCBpbXg2X3BjaWUgew0K PiA+ICAjZGVmaW5lIFBIWV9SWF9PVlJEX0lOX0xPX1JYX0RBVEFfRU4gKDEgPDwgNSkgICNkZWZp bmUNCj4gPiBQSFlfUlhfT1ZSRF9JTl9MT19SWF9QTExfRU4gKDEgPDwgMykNCj4gPg0KPiA+ICtz dGF0aWMgaW5saW5lIGJvb2wgaXNfaW14NnN4X3BjaWUoc3RydWN0IGlteDZfcGNpZSAqaW14Nl9w Y2llKSB7DQo+ID4gKwlyZXR1cm4gaW14Nl9wY2llLT5kYXRhID09ICZpbXg2c3hfcGNpZV9kYXRh OyB9DQo+ID4gKw0KPiA+ICBzdGF0aWMgaW50IHBjaWVfcGh5X3BvbGxfYWNrKHZvaWQgX19pb21l bSAqZGJpX2Jhc2UsIGludCBleHBfdmFsKSAgew0KPiA+ICAJdTMyIHZhbDsNCj4gPiBAQCAtMjU3 LDEwICsyODMsMjEgQEAgc3RhdGljIGludCBpbXg2X3BjaWVfZGVhc3NlcnRfY29yZV9yZXNldChz dHJ1Y3QNCj4gcGNpZV9wb3J0ICpwcCkNCj4gPiAgCXN0cnVjdCBpbXg2X3BjaWUgKmlteDZfcGNp ZSA9IHRvX2lteDZfcGNpZShwcCk7DQo+ID4gIAlpbnQgcmV0Ow0KPiA+DQo+ID4gLQlyZXQgPSBj bGtfcHJlcGFyZV9lbmFibGUoaW14Nl9wY2llLT5wY2llX3BoeSk7DQo+ID4gLQlpZiAocmV0KSB7 DQo+ID4gLQkJZGV2X2VycihwcC0+ZGV2LCAidW5hYmxlIHRvIGVuYWJsZSBwY2llX3BoeSBjbG9j a1xuIik7DQo+ID4gLQkJZ290byBlcnJfcGNpZV9waHk7DQo+ID4gKwlpZiAoZ3Bpb19pc192YWxp ZChpbXg2X3BjaWUtPnBvd2VyX29uX2dwaW8pKQ0KPiA+ICsJCWdwaW9fc2V0X3ZhbHVlKGlteDZf cGNpZS0+cG93ZXJfb25fZ3BpbywgMSk7DQo+ID4gKw0KPiANCj4gSSB3b24ndCBhbGxvdyB0aGlz IHRvIGNyZWVwIGluIGFnYWluLiBUaGlzIG5lZWRzIHRvIGJlIGEgcHJvcGVyIHJlZ3VsYXRvciwg bm90DQo+IHNvbWUga2luZCBvZiBncGlvLg0KPiANCj4gPiArCWlmIChpc19pbXg2c3hfcGNpZShp bXg2X3BjaWUpKSB7DQo+ID4gKwkJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGlteDZfcGNpZS0+ cGNpZV9zZWMpOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiArCQkJZGV2X2VycihwcC0+ZGV2LCAi dW5hYmxlIHRvIGVuYWJsZSBwY2llX3NlYyBjbGsuXG4iKTsNCj4gPiArCQkJZ290byBlcnJfcGNp ZV9zZWM7DQo+ID4gKwkJfQ0KPiA+ICsJfSBlbHNlIHsNCj4gPiArCQlyZXQgPSBjbGtfcHJlcGFy ZV9lbmFibGUoaW14Nl9wY2llLT5wY2llX3BoeSk7DQo+ID4gKwkJaWYgKHJldCkgew0KPiA+ICsJ CQlkZXZfZXJyKHBwLT5kZXYsICJ1bmFibGUgdG8gZW5hYmxlIHBjaWVfcGh5IGNsb2NrXG4iKTsN Cj4gPiArCQkJZ290byBlcnJfcGNpZV9waHk7DQo+ID4gKwkJfQ0KPiA+ICAJfQ0KPiA+DQo+ID4g IAlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoaW14Nl9wY2llLT5wY2llX2J1cyk7DQo+ID4gQEAg LTI3NSwyOCArMzEyLDUwIEBAIHN0YXRpYyBpbnQgaW14Nl9wY2llX2RlYXNzZXJ0X2NvcmVfcmVz ZXQoc3RydWN0DQo+IHBjaWVfcG9ydCAqcHApDQo+ID4gIAkJZ290byBlcnJfcGNpZTsNCj4gPiAg CX0NCj4gPg0KPiA+ICsJaWYgKGlzX2lteDZzeF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQly ZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ ID4gKwkJCQlJTVg2U1hfR1BSMTJfUENJRV9URVNUX1BELA0KPiA+ICsJCQkJSU1YNlNYX0dQUjEy X1BDSUVfVEVTVF9QRF9DTFIpOw0KPiA+ICsJfSBlbHNlIHsNCj4gPiArCQkvKiBwb3dlciB1cCBj b3JlIHBoeSBhbmQgZW5hYmxlIHJlZiBjbG9jayAqLw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0 cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxLA0KPiA+ICsJCQkJSU1YNlFfR1BS MV9QQ0lFX1RFU1RfUEQsIDAgPDwgMTgpOw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2 X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxLA0KPiA+ICsJCQkJSU1YNlFfR1BSMV9QQ0lF X1JFRl9DTEtfRU4sIDEgPDwgMTYpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiAgCS8qIGFsbG93IHRo ZSBjbG9ja3MgdG8gc3RhYmlsaXplICovDQo+ID4gIAl1c2xlZXBfcmFuZ2UoMjAwLCA1MDApOw0K PiA+DQo+ID4gLQkvKiBwb3dlciB1cCBjb3JlIHBoeSBhbmQgZW5hYmxlIHJlZiBjbG9jayAqLw0K PiA+IC0JcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQ UjEsDQo+ID4gLQkJCUlNWDZRX0dQUjFfUENJRV9URVNUX1BELCAwIDw8IDE4KTsNCj4gPiAtCXJl Z21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxLA0KPiA+ IC0JCQlJTVg2UV9HUFIxX1BDSUVfUkVGX0NMS19FTiwgMSA8PCAxNik7DQo+ID4gLQ0KPiA+ICAJ LyogU29tZSBib2FyZHMgZG9uJ3QgaGF2ZSBQQ0llIHJlc2V0IEdQSU8uICovDQo+ID4gIAlpZiAo Z3Bpb19pc192YWxpZChpbXg2X3BjaWUtPnJlc2V0X2dwaW8pKSB7DQo+ID4gIAkJZ3Bpb19zZXRf dmFsdWUoaW14Nl9wY2llLT5yZXNldF9ncGlvLCAwKTsNCj4gPiAgCQltc2xlZXAoMTAwKTsNCj4g PiAgCQlncGlvX3NldF92YWx1ZShpbXg2X3BjaWUtPnJlc2V0X2dwaW8sIDEpOw0KPiA+ICAJfQ0K PiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBpTVg2U1ggUENJZSBoYXMgdGhlIHN0YW5kLWFsb25l IHBvd2VyIGRvbWFpbi4NCj4gPiArCSAqIHJlZmVyIHRvIHRoZSBpbml0aWFsaXphdGlvbiBmb3Ig aU1YNlNYIFBDSWUsDQo+ID4gKwkgKiByZWxlYXNlIHRoZSBQQ0llIFBIWSByZXNldCBoZXJlLA0K PiA+ICsJICogYmVmb3JlIExUU1NNIGVuYWJsZSBpcyBzZXQuDQo+ID4gKwkgKi8NCj4gPiArCWlm IChpc19pbXg2c3hfcGNpZShpbXg2X3BjaWUpKQ0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhp bXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFI1LA0KPiA+ICsJCQkJSU1YNlNYX0dQUjVf UENJRV9CVE5SU1QsDQo+ID4gKwkJCQlJTVg2U1hfR1BSNV9QQ0lFX0JUTlJTVF9DTFIpOw0KPiA+ ICsNCj4gPiAgCXJldHVybiAwOw0KPiA+DQo+ID4gIGVycl9wY2llOg0KPiA+ICAJY2xrX2Rpc2Fi bGVfdW5wcmVwYXJlKGlteDZfcGNpZS0+cGNpZV9idXMpOw0KPiA+ICBlcnJfcGNpZV9idXM6DQo+ ID4gLQljbGtfZGlzYWJsZV91bnByZXBhcmUoaW14Nl9wY2llLT5wY2llX3BoeSk7DQo+ID4gKwlp ZiAoIWlzX2lteDZzeF9wY2llKGlteDZfcGNpZSkpDQo+ID4gKwkJY2xrX2Rpc2FibGVfdW5wcmVw YXJlKGlteDZfcGNpZS0+cGNpZV9waHkpOw0KPiA+ICBlcnJfcGNpZV9waHk6DQo+ID4gKwlpZiAo aXNfaW14NnN4X3BjaWUoaW14Nl9wY2llKSkNCj4gPiArCQljbGtfZGlzYWJsZV91bnByZXBhcmUo aW14Nl9wY2llLT5wY2llX3NlYyk7DQo+ID4gK2Vycl9wY2llX3NlYzoNCj4gPiAgCXJldHVybiBy ZXQ7DQo+ID4NCj4gPiAgfQ0KPiA+IEBAIC0zMDQsMTUgKzM2MywzOCBAQCBlcnJfcGNpZV9waHk6 DQo+ID4gIHN0YXRpYyB2b2lkIGlteDZfcGNpZV9pbml0X3BoeShzdHJ1Y3QgcGNpZV9wb3J0ICpw cCkgIHsNCj4gPiAgCXN0cnVjdCBpbXg2X3BjaWUgKmlteDZfcGNpZSA9IHRvX2lteDZfcGNpZShw cCk7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBpTVg2U1ggUENJ ZSBoYXMgdGhlIHN0YW5kLWFsb25lIHBvd2VyIGRvbWFpbg0KPiA+ICsJICogYWRkIHRoZSBpbml0 aWFsaXphdGlvbiBoZXJlIGZvciBpTVg2U1ggUENJZS4NCj4gPiArCSAqLw0KPiA+ICsJaWYgKGlz X2lteDZzeF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQkvKiBGb3JjZSBQQ0llIFBIWSByZXNl dCAqLw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElP TVVYQ19HUFI1LA0KPiA+ICsJCQkJSU1YNlNYX0dQUjVfUENJRV9CVE5SU1QsDQo+ID4gKwkJCQlJ TVg2U1hfR1BSNV9QQ0lFX0JUTlJTVCk7DQo+ID4gKw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0 cyhpbXg2X3BjaWUtPmdwY19pcHNfcmVnLCAwLCAxIDw8IDcsIDEgPDwgNyk7DQo+IA0KPiBXaGF0 IGlzIHRoaXM/IElzIHRoaXMgYSByZWd1bGF0b3I/IElmIHNvLCB3aHkgaXNuJ3QgaXQgYWJzdHJh Y3RlZCBhcyBhIHByb3Blcg0KPiByZWd1bGF0b3I/DQo+IA0KPiA+ICsJCS8qIFBvd2VyIHVwIFBD SWUgUEhZLCBBTkFUT1BfUkVHX0NPUkUgb2Zmc2V0IDB4MTQwLCBiaXQxMy05ICovDQo+ID4gKwkJ cmVndWxhdG9yX3NldF92b2x0YWdlKGlteDZfcGNpZS0+cGNpZV9yZWd1bGF0b3IsDQo+ID4gKwkJ CQkxMTAwMDAwLCAxMTAwMDAwKTsNCj4gPiArCQlyZXQgPSByZWd1bGF0b3JfZW5hYmxlKGlteDZf cGNpZS0+cGNpZV9yZWd1bGF0b3IpOw0KPiA+ICsJCWlmIChyZXQpDQo+ID4gKwkJCWRldl9pbmZv KHBwLT5kZXYsICJmYWlsZWQgdG8gZW5hYmxlIHBjaWUgcmVndWxhdG9yLlxuIik7DQo+IA0KPiBU aGlzIHJlZ3VsYXRvciBnZXRzIGVuYWJsZWQgaGVyZSwgYnV0IEkgZG9uJ3Qgc2VlIGFueSBwYXRo IHdlcmUgd2Ugd291bGQNCj4gZGlzYWJsZSBpdC4gSXMgdGhpcyBhIGFsd2F5cy1vbiByZWd1bGF0 b3Igb3IgYXJlIHlvdSBzaW1wbHkgbWlzc2luZyB0aGUgY2FsbHMNCj4gdG8gZGlzYWJsZSBpdCBp biB0aGUgcnVudGltZS1wbSBob29rcz8NCj4gDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlt eDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+ICsJCQkJSU1YNlNYX0dQUjEy X1JYX0VRX01BU0ssIElNWDZTWF9HUFIxMl9SWF9FUV8yKTsNCj4gPiArCX0NCj4gPg0KPiA+ICAJ cmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0K PiA+IC0JCQlJTVg2UV9HUFIxMl9QQ0lFX0NUTF8yLCAwIDw8IDEwKTsNCj4gPiArCQkJSU1YNlFf R1BSMTJfUENJRV9DVExfMiwNCj4gPiArCQkJSU1YNlFfR1BSMTJfUENJRV9DVExfMl9DTFIpOw0K PiA+DQo+ID4gIAkvKiBjb25maWd1cmUgY29uc3RhbnQgaW5wdXQgc2lnbmFsIHRvIHRoZSBwY2ll IGN0cmwgYW5kIHBoeSAqLw0KPiA+ICAJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9t dXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+ICAJCQlJTVg2UV9HUFIxMl9ERVZJQ0VfVFlQRSwg UENJX0VYUF9UWVBFX1JPT1RfUE9SVCA8PCAxMik7DQo+ID4gIAlyZWdtYXBfdXBkYXRlX2JpdHMo aW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4gLQkJCUlNWDZRX0dQUjEy X0xPU19MRVZFTCwgOSA8PCA0KTsNCj4gPiArCQkJSU1YNlFfR1BSMTJfTE9TX0xFVkVMLCBJTVg2 UV9HUFIxMl9MT1NfTEVWRUxfOSk7DQo+ID4NCj4gPiAgCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2 X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFI4LA0KPiA+ICAJCQlJTVg2UV9HUFI4X1RYX0RF RU1QSF9HRU4xLCAwIDw8IDApOyBAQCAtMzcwLDcgKzQ1Miw4IEBAIHN0YXRpYw0KPiBpbnQNCj4g PiBpbXg2X3BjaWVfc3RhcnRfbGluayhzdHJ1Y3QgcGNpZV9wb3J0ICpwcCkNCj4gPg0KPiA+ICAJ LyogU3RhcnQgTFRTU00uICovDQo+ID4gIAlyZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5p b211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4gLQkJCUlNWDZRX0dQUjEyX1BDSUVfQ1RMXzIs IDEgPDwgMTApOw0KPiA+ICsJCQlJTVg2UV9HUFIxMl9QQ0lFX0NUTF8yLA0KPiA+ICsJCQlJTVg2 UV9HUFIxMl9QQ0lFX0NUTF8yKTsNCj4gPg0KPiA+ICAJcmV0ID0gaW14Nl9wY2llX3dhaXRfZm9y X2xpbmsocHApOw0KPiA+ICAJaWYgKHJldCkNCj4gPiBAQCAtNTQ2LDEwICs2MjksNzMgQEAgc3Rh dGljIGludCBfX2luaXQgaW14Nl9hZGRfcGNpZV9wb3J0KHN0cnVjdCBwY2llX3BvcnQNCj4gKnBw LA0KPiA+ICAJcmV0dXJuIDA7DQo+ID4gIH0NCj4gPg0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IG9mX2RldmljZV9pZCBpbXg2X3BjaWVfb2ZfbWF0Y2hbXSA9IHsNCj4gPiArCXsgLmNvbXBhdGli bGUgPSAiZnNsLGlteDZxLXBjaWUiLCB9LA0KPiA+ICsJeyAuY29tcGF0aWJsZSA9ICJmc2wsaW14 NnN4LXBjaWUiLCAuZGF0YSA9ICZpbXg2c3hfcGNpZV9kYXRhfSwNCj4gPiArCXt9LA0KPiA+ICt9 Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBpbXg2X3BjaWVfb2ZfbWF0Y2gpOw0KPiA+ ICsNCj4gPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+ICtzdGF0aWMgaW50IHBjaV9pbXhf c3VzcGVuZCh2b2lkKQ0KPiA+ICt7DQo+ID4gKwlpbnQgcmMgPSAwOw0KPiA+ICsNCj4gPiArCWlm IChpc19pbXg2c3hfcGNpZShpbXg2X3BjaWUpKSB7DQo+ID4gKwkJLyogUE1fVFVSTl9PRkYgKi8N Cj4gPiArCQlyZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENf R1BSMTIsDQo+ID4gKwkJCQlCSVQoMTYpLCAxIDw8IDE2KTsNCj4gPiArCQl1ZGVsYXkoMTApOw0K PiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19H UFIxMiwNCj4gPiArCQkJCUJJVCgxNiksIDAgPDwgMTYpOw0KPiANCj4gV2h5IGFyZSB0aGVyZSBu byBkZWZpbmVzIGZvciB0aG9zZSBiaXRzPyBJIGNhbid0IHJlYWxseSB0ZWxsIHdoYXQncyBnb2lu ZyBvbg0KPiBoZXJlLiBJcyB0aGlzIHNvbWUga2luZCBvZiBwb3dlciBnYXRpbmcgdGhlIFNvQyBw YXJ0aXRpb24/IEluIHRoYXQgY2FzZSBpdA0KPiBzaG91bGQgcmVhbGx5IGJlIGltcGxlbWVudGVk IGFzIGEgcG93ZXItZG9tYWluIGFuZCBub3QgYXMgc29tZSBraW5kIG9mIGFkLWhvYw0KPiBHUFIg cmVnaXN0ZXIgYmFzaGluZy4NCj4gDQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJjOw0K PiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBwY2lfaW14X3Jlc3VtZSh2b2lkKQ0KPiA+ ICt7DQo+ID4gKwlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9ICZpbXg2X3BjaWUtPnBwOw0KPiA+ICsN Cj4gPiArCWlmIChpc19pbXg2c3hfcGNpZShpbXg2X3BjaWUpKSB7DQo+ID4gKwkJLyogcmVzZXQg aU1YNlNYIFBDSWUgKi8NCj4gPiArCQlyZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211 eGNfZ3ByLA0KPiA+ICsJCQkJSU9NVVhDX0dQUjUsIEJJVCgxOCksIDEgPDwgMTgpOw0KPiA+ICsN Cj4gPiArCQlyZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLA0KPiA+ICsJ CQkJSU9NVVhDX0dQUjUsIEJJVCgxOCksIDAgPDwgMTgpOw0KPiA+ICsNCj4gPiArCQkvKg0KPiA+ ICsJCSAqIGNvbnRyb2xsZXIgbWF5YmUgdHVybiBvZmYsIHJlLWNvbmZpZ3VyZSBhZ2Fpbg0KPiA+ ICsJCSAqIFNldCB0aGUgQ0xBU1NfUkVWIG9mIFJDIENGRyBoZWFkZXIgdG8NCj4gPiArCQkgKiBQ Q0lfQ0xBU1NfQlJJREdFX1BDSQ0KPiA+ICsJCSAqLw0KPiA+ICsJCXdyaXRlbChyZWFkbChwcC0+ ZGJpX2Jhc2UgKyBQQ0lfQ0xBU1NfUkVWSVNJT04pDQo+ID4gKwkJCXwgKFBDSV9DTEFTU19CUklE R0VfUENJIDw8IDE2KSwNCj4gPiArCQkJcHAtPmRiaV9iYXNlICsgUENJX0NMQVNTX1JFVklTSU9O KTsNCj4gPiArDQo+ID4gKwkJZHdfcGNpZV9zZXR1cF9yYyhwcCk7DQo+ID4gKw0KPiA+ICsJCS8q IHJlc2V0IGlNWDZTWCBQQ0llICovDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNp ZS0+aW9tdXhjX2dwciwNCj4gPiArCQkJCUlPTVVYQ19HUFI1LCBCSVQoMTgpLCAxIDw8IDE4KTsN Cj4gPiArDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwN Cj4gPiArCQkJCUlPTVVYQ19HUFI1LCBCSVQoMTgpLCAwIDw8IDE4KTsNCj4gDQo+IFdoeSB0aGUg ZG91YmxlIHJlc2V0Pw0KPiANCj4gPiArCX0NCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHN0 cnVjdCBzeXNjb3JlX29wcyBwY2lfaW14X3N5c2NvcmVfb3BzID0gew0KPiA+ICsJLnN1c3BlbmQg PSBwY2lfaW14X3N1c3BlbmQsDQo+ID4gKwkucmVzdW1lID0gcGNpX2lteF9yZXN1bWUsDQo+ID4g K307DQo+ID4gKyNlbmRpZg0KPiA+ICsNCj4gPiAgc3RhdGljIGludCBfX2luaXQgaW14Nl9wY2ll X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpICB7DQo+ID4gLQlzdHJ1Y3QgaW14 Nl9wY2llICppbXg2X3BjaWU7DQo+ID4gIAlzdHJ1Y3QgcGNpZV9wb3J0ICpwcDsNCj4gPiArCWNv bnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgKm9mX2lkID0NCj4gPiArCQkJb2ZfbWF0Y2hfZGV2aWNl KGlteDZfcGNpZV9vZl9tYXRjaCwgJnBkZXYtPmRldik7DQo+ID4gIAlzdHJ1Y3QgZGV2aWNlX25v ZGUgKm5wID0gcGRldi0+ZGV2Lm9mX25vZGU7DQo+ID4gIAlzdHJ1Y3QgcmVzb3VyY2UgKmRiaV9i YXNlOw0KPiA+ICAJaW50IHJldDsNCj4gPiBAQCAtNTYwLDYgKzcwNiw3IEBAIHN0YXRpYyBpbnQg X19pbml0IGlteDZfcGNpZV9wcm9iZShzdHJ1Y3QNCj4gPiBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYp DQo+ID4NCj4gPiAgCXBwID0gJmlteDZfcGNpZS0+cHA7DQo+ID4gIAlwcC0+ZGV2ID0gJnBkZXYt PmRldjsNCj4gPiArCWlteDZfcGNpZS0+ZGF0YSA9IG9mX2lkLT5kYXRhOw0KPiA+DQo+ID4gIAkv KiBBZGRlZCBmb3IgUENJIGFib3J0IGhhbmRsaW5nICovDQo+ID4gIAlob29rX2ZhdWx0X2NvZGUo MTYgKyA2LCBpbXg2cV9wY2llX2Fib3J0X2hhbmRsZXIsIFNJR0JVUywgMCwgQEANCj4gPiAtNTgx LDEyICs3MjgsMjYgQEAgc3RhdGljIGludCBfX2luaXQgaW14Nl9wY2llX3Byb2JlKHN0cnVjdCBw bGF0Zm9ybV9kZXZpY2UNCj4gKnBkZXYpDQo+ID4gIAkJfQ0KPiA+ICAJfQ0KPiA+DQo+ID4gKwlp bXg2X3BjaWUtPnBvd2VyX29uX2dwaW8gPSBvZl9nZXRfbmFtZWRfZ3BpbyhucCwgInBvd2VyLW9u LWdwaW8iLCAwKTsNCj4gPiArCWlmIChncGlvX2lzX3ZhbGlkKGlteDZfcGNpZS0+cG93ZXJfb25f Z3BpbykpIHsNCj4gPiArCQlyZXQgPSBkZXZtX2dwaW9fcmVxdWVzdF9vbmUoJnBkZXYtPmRldiwN Cj4gPiArCQkJCQlpbXg2X3BjaWUtPnBvd2VyX29uX2dwaW8sDQo+ID4gKwkJCQkJR1BJT0ZfT1VU X0lOSVRfTE9XLA0KPiA+ICsJCQkJCSJQQ0llIHBvd2VyIGVuYWJsZSIpOw0KPiA+ICsJCWlmIChy ZXQpIHsNCj4gPiArCQkJZGV2X2VycigmcGRldi0+ZGV2LCAidW5hYmxlIHRvIGdldCBwb3dlci1v biBncGlvXG4iKTsNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArCQl9DQo+ID4gKwl9DQo+ID4g Kw0KPiA+ICAJLyogRmV0Y2ggY2xvY2tzICovDQo+ID4gLQlpbXg2X3BjaWUtPnBjaWVfcGh5ID0g ZGV2bV9jbGtfZ2V0KCZwZGV2LT5kZXYsICJwY2llX3BoeSIpOw0KPiA+IC0JaWYgKElTX0VSUihp bXg2X3BjaWUtPnBjaWVfcGh5KSkgew0KPiA+IC0JCWRldl9lcnIoJnBkZXYtPmRldiwNCj4gPiAt CQkJInBjaWVfcGh5IGNsb2NrIHNvdXJjZSBtaXNzaW5nIG9yIGludmFsaWRcbiIpOw0KPiA+IC0J CXJldHVybiBQVFJfRVJSKGlteDZfcGNpZS0+cGNpZV9waHkpOw0KPiA+ICsJaWYgKCFpc19pbXg2 c3hfcGNpZShpbXg2X3BjaWUpKSB7DQo+ID4gKwkJaW14Nl9wY2llLT5wY2llX3BoeSA9IGRldm1f Y2xrX2dldCgmcGRldi0+ZGV2LCAicGNpZV9waHkiKTsNCj4gPiArCQlpZiAoSVNfRVJSKGlteDZf cGNpZS0+cGNpZV9waHkpKSB7DQo+ID4gKwkJCWRldl9lcnIoJnBkZXYtPmRldiwNCj4gPiArCQkJ CSJwY2llX3BoeSBjbG9jayBzb3VyY2UgbWlzc2luZyBvciBpbnZhbGlkXG4iKTsNCj4gPiArCQkJ cmV0dXJuIFBUUl9FUlIoaW14Nl9wY2llLT5wY2llX3BoeSk7DQo+ID4gKwkJfQ0KPiA+ICAJfQ0K PiA+DQo+IA0KPiBNaXNzaW5nIGJpbmRpbmcgdXBkYXRlIGZvciB0aGUgY2hhbmdlZCBjbG9jayBo YW5kbGluZy4gQWxzbyB3aGF0IGlzIHRoaXMgY2xvY2sNCj4gcGNpZV9zZWM/IElzIGl0IHJlYWxs eSBhIHNlY29uZCBBWEkgY2xvY2s/IEkgaGlnaGx5IGRvdWJ0IHRoYXQgdGhlIHJlZ2lzdGVyDQo+ IGludGVyZmFjZSBvZiB0aGUgY29yZSBpcyBjbG9ja2VkIGJ5IHR3byBkaWZmZXJlbnQgY2xvY2tz LiBXaGF0IGJsb2NrcyBvZiB0aGUNCj4gZHdfcGNpIGNvcmUgZG9lcyB0aGlzIGNsb2NrIGZlZWQ/ DQo+IA0KPiA+ICAJaW14Nl9wY2llLT5wY2llX2J1cyA9IGRldm1fY2xrX2dldCgmcGRldi0+ZGV2 LCAicGNpZV9idXMiKTsgQEANCj4gPiAtNjA0LDggKzc2NSwyMiBAQCBzdGF0aWMgaW50IF9faW5p dCBpbXg2X3BjaWVfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZQ0KPiAqcGRldikNCj4gPiAg CX0NCj4gPg0KPiA+ICAJLyogR3JhYiBHUFIgY29uZmlnIHJlZ2lzdGVyIHJhbmdlICovDQo+ID4g LQlpbXg2X3BjaWUtPmlvbXV4Y19ncHIgPQ0KPiA+IC0JCSBzeXNjb25fcmVnbWFwX2xvb2t1cF9i eV9jb21wYXRpYmxlKCJmc2wsaW14NnEtaW9tdXhjLWdwciIpOw0KPiA+ICsJaWYgKGlzX2lteDZz eF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQkvKiBHZXQgcGNpZSByZWd1bGF0b3IgKi8NCj4g PiArCQlpbXg2X3BjaWUtPnBjaWVfcmVndWxhdG9yID0gZGV2bV9yZWd1bGF0b3JfZ2V0KHBwLT5k ZXYsICJwY2llIik7DQo+IA0KPiBVaCwgdGhpcyBoYXMgbm90aGluZyB0byBkbyB3aXRoIHRoZSBH UFIgcmFuZ2UsIHNvIHRoZSBjb21tZW50IGFib3ZlIGlzDQo+IGNvbmZ1c2luZy4gQWxzbyBtaXNz aW5nIGJpbmRpbmcgdXBkYXRlIGZvciB0aGlzIHJlZ3VsYXRvci4NCj4gDQo+ID4gKw0KPiA+ICsJ CS8qIEdyYWIgR1BSIGNvbmZpZyByZWdpc3RlciByYW5nZSAqLw0KPiA+ICsJCWlteDZfcGNpZS0+ aW9tdXhjX2dwciA9DQo+ID4gKwkJCSBzeXNjb25fcmVnbWFwX2xvb2t1cF9ieV9jb21wYXRpYmxl DQo+ID4gKwkJCSAoImZzbCxpbXg2c3gtaW9tdXhjLWdwciIpOw0KPiA+ICsJCS8qIEdyYWIgR1BD IElQUyByZWdpc3RlciByYW5nZSAqLw0KPiA+ICsJCWlteDZfcGNpZS0+Z3BjX2lwc19yZWcgPQ0K PiA+ICsJCQkgc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZSgiZnNsLGlteDZzeC1n cGMiKTsNCj4gPiArCX0gZWxzZSB7DQo+ID4gKwkJaW14Nl9wY2llLT5pb211eGNfZ3ByID0NCj4g PiArCQkJc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZQ0KPiA+ICsJCQkoImZzbCxp bXg2cS1pb211eGMtZ3ByIik7DQo+ID4gKwl9DQo+ID4gIAlpZiAoSVNfRVJSKGlteDZfcGNpZS0+ aW9tdXhjX2dwcikpIHsNCj4gPiAgCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJ1bmFibGUgdG8gZmlu ZCBpb211eGMgcmVnaXN0ZXJzXG4iKTsNCj4gPiAgCQlyZXR1cm4gUFRSX0VSUihpbXg2X3BjaWUt PmlvbXV4Y19ncHIpOyBAQCAtNjE2LDYgKzc5MSw5IEBAIHN0YXRpYw0KPiA+IGludCBfX2luaXQg aW14Nl9wY2llX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4gIAkJcmV0 dXJuIHJldDsNCj4gPg0KPiA+ICAJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgaW14Nl9wY2ll KTsNCj4gPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+ICsJcmVnaXN0ZXJfc3lzY29yZV9v cHMoJnBjaV9pbXhfc3lzY29yZV9vcHMpOw0KPiA+ICsjZW5kaWYNCj4gPiAgCXJldHVybiAwOw0K PiA+ICB9DQo+ID4NCj4gPiBAQCAtNjI3LDEyICs4MDUsNiBAQCBzdGF0aWMgdm9pZCBpbXg2X3Bj aWVfc2h1dGRvd24oc3RydWN0IHBsYXRmb3JtX2RldmljZQ0KPiAqcGRldikNCj4gPiAgCWlteDZf cGNpZV9hc3NlcnRfY29yZV9yZXNldCgmaW14Nl9wY2llLT5wcCk7DQo+ID4gIH0NCj4gPg0KPiA+ IC1zdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBpbXg2X3BjaWVfb2ZfbWF0Y2hbXSA9 IHsNCj4gPiAtCXsgLmNvbXBhdGlibGUgPSAiZnNsLGlteDZxLXBjaWUiLCB9LA0KPiA+IC0Je30s DQo+ID4gLX07DQo+ID4gLU1PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIGlteDZfcGNpZV9vZl9tYXRj aCk7DQo+ID4gLQ0KPiA+ICBzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpbXg2X3BjaWVf ZHJpdmVyID0gew0KPiA+ICAJLmRyaXZlciA9IHsNCj4gPiAgCQkubmFtZQk9ICJpbXg2cS1wY2ll IiwNCj4gPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9tZmQvc3lzY29uL2lteDZxLWlvbXV4 Yy1ncHIuaA0KPiA+IGIvaW5jbHVkZS9saW51eC9tZmQvc3lzY29uL2lteDZxLWlvbXV4Yy1ncHIu aA0KPiA+IGluZGV4IGZmNDQzNzQuLmYwMjg3NWUgMTAwNjQ0DQo+ID4gLS0tIGEvaW5jbHVkZS9s aW51eC9tZmQvc3lzY29uL2lteDZxLWlvbXV4Yy1ncHIuaA0KPiA+ICsrKyBiL2luY2x1ZGUvbGlu dXgvbWZkL3N5c2Nvbi9pbXg2cS1pb211eGMtZ3ByLmgNCj4gPiBAQCAtMTEzLDEwICsxMTMsMTIg QEANCj4gPiAgI2RlZmluZSBJTVg2UV9HUFIxX01JUElfSVBVMV9NVVhfR0FTS0VUCQkweDANCj4g PiAgI2RlZmluZSBJTVg2UV9HUFIxX01JUElfSVBVMV9NVVhfSU9NVVgJCUJJVCgxOSkNCj4gPiAg I2RlZmluZSBJTVg2UV9HUFIxX1BDSUVfVEVTVF9QRAkJCUJJVCgxOCkNCj4gPiArI2RlZmluZSBJ TVg2UV9HUFIxX1BDSUVfVEVTVF9QRF9DTFIJCTB4MA0KPiA+ICAjZGVmaW5lIElNWDZRX0dQUjFf SVBVX1ZQVV9NVVhfTUFTSwkJQklUKDE3KQ0KPiA+ICAjZGVmaW5lIElNWDZRX0dQUjFfSVBVX1ZQ VV9NVVhfSVBVMQkJMHgwDQo+ID4gICNkZWZpbmUgSU1YNlFfR1BSMV9JUFVfVlBVX01VWF9JUFUy CQlCSVQoMTcpDQo+ID4gICNkZWZpbmUgSU1YNlFfR1BSMV9QQ0lFX1JFRl9DTEtfRU4JCUJJVCgx NikNCj4gPiArI2RlZmluZSBJTVg2UV9HUFIxX1BDSUVfUkVGX0NMS19DTFIJCTB4MA0KPiA+ICAj ZGVmaW5lIElNWDZRX0dQUjFfVVNCX0VYUF9NT0RFCQkJQklUKDE1KQ0KPiA+ICAjZGVmaW5lIElN WDZRX0dQUjFfUENJRV9JTlQJCQlCSVQoMTQpDQo+ID4gICNkZWZpbmUgSU1YNlFfR1BSMV9VU0Jf T1RHX0lEX1NFTF9NQVNLCQlCSVQoMTMpDQo+ID4gQEAgLTMwMCw3ICszMDIsOSBAQA0KPiA+ICAj ZGVmaW5lIElNWDZRX0dQUjEyX0FSTVBfQVBCX0NMS19FTgkJQklUKDI0KQ0KPiA+ICAjZGVmaW5l IElNWDZRX0dQUjEyX0RFVklDRV9UWVBFCQkJKDB4ZiA8PCAxMikNCj4gPiAgI2RlZmluZSBJTVg2 UV9HUFIxMl9QQ0lFX0NUTF8yCQkJQklUKDEwKQ0KPiA+ICsjZGVmaW5lIElNWDZRX0dQUjEyX1BD SUVfQ1RMXzJfQ0xSCQkweDANCj4gPiAgI2RlZmluZSBJTVg2UV9HUFIxMl9MT1NfTEVWRUwJCQko MHgxZiA8PCA0KQ0KPiA+ICsjZGVmaW5lIElNWDZRX0dQUjEyX0xPU19MRVZFTF85CQkJKDB4OSA8 PCA0KQ0KPiA+DQo+ID4gICNkZWZpbmUgSU1YNlFfR1BSMTNfU0RNQV9TVE9QX1JFUQkJQklUKDMw KQ0KPiA+ICAjZGVmaW5lIElNWDZRX0dQUjEzX0NBTjJfU1RPUF9SRVEJCUJJVCgyOSkNCj4gPiBA QCAtMzk1LDQgKzM5OSwxNCBAQA0KPiA+ICAjZGVmaW5lIElNWDZTTF9HUFIxX0ZFQ19DTE9DS19N VVgxX1NFTF9NQVNLICAgICgweDMgPDwgMTcpDQo+ID4gICNkZWZpbmUgSU1YNlNMX0dQUjFfRkVD X0NMT0NLX01VWDJfU0VMX01BU0sgICAgKDB4MSA8PCAxNCkNCj4gPg0KPiA+ICsvKiBGb3IgaW14 NnN4IGlvbXV4IGdwciByZWdpc3RlciBmaWVsZCBkZWZpbmUgKi8NCj4gPiArI2RlZmluZSBJTVg2 U1hfR1BSNV9QQ0lFX0JUTlJTVAkJCUJJVCgxOSkNCj4gPiArI2RlZmluZSBJTVg2U1hfR1BSNV9Q Q0lFX0JUTlJTVF9DTFIJCTB4MA0KPiA+ICsjZGVmaW5lIElNWDZTWF9HUFI1X1BDSUVfUEVSU1QJ CQlCSVQoMTgpDQo+ID4gKyNkZWZpbmUgSU1YNlNYX0dQUjVfUENJRV9QRVJTVF9DTFIJCTB4MA0K PiA+ICsNCj4gPiArI2RlZmluZSBJTVg2U1hfR1BSMTJfUENJRV9URVNUX1BECQlCSVQoMzApDQo+ ID4gKyNkZWZpbmUgSU1YNlNYX0dQUjEyX1BDSUVfVEVTVF9QRF9DTFIJCTB4MA0KPiA+ICsjZGVm aW5lIElNWDZTWF9HUFIxMl9SWF9FUV9NQVNLCQkJKDB4NyA8PCAwKQ0KPiA+ICsjZGVmaW5lIElN WDZTWF9HUFIxMl9SWF9FUV8yCQkJKDB4MiA8PCAwKQ0KPiA+ICAjZW5kaWYgLyogX19MSU5VWF9J TVg2UV9JT01VWENfR1BSX0ggKi8NCj4gDQo+IC0tDQo+IFBlbmd1dHJvbml4IGUuSy4gICAgICAg ICAgICAgfCBMdWNhcyBTdGFjaCAgICAgICAgICAgICAgICAgfA0KPiBJbmR1c3RyaWFsIExpbnV4 IFNvbHV0aW9ucyAgIHwgaHR0cDovL3d3dy5wZW5ndXRyb25peC5kZS8gIHwNCg0K -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Sep 22, 2014 at 05:01:38PM +0800, Richard Zhu wrote: > - 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. > - another dis_axi clk is mandatory required by imx6sx pcie. > Add one new clk named pcie_sec into imx6_pcie structure. > - pcie_ref_125m is not used as pcie_phy clk anymore on imx6sx. > The parent clk (pcie_ref) of the pcie_bus(lvds1_gate) > is used as pcie_phy clk. > - Register one PM call-back, enter/exit L2 state of the ASPM > during system suspend/resume. > - wait the clocks to stabilize after the pcie_ref_en > (IMX6Q_GPR1_PCIE_REF_CLK_EN) is set. > > Signed-off-by: Richard Zhu <r65037@freescale.com> > --- > arch/arm/boot/dts/imx6sx-sdb.dts | 15 ++ > arch/arm/boot/dts/imx6sx.dtsi | 33 ++-- > arch/arm/mach-imx/Kconfig | 1 + > drivers/pci/host/pci-imx6.c | 228 ++++++++++++++++++++++++---- > include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++ > 5 files changed, 249 insertions(+), 42 deletions(-) <formletter> This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read Documentation/stable_kernel_rules.txt for how to do this properly. </formletter> -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> -----Original Message----- > From: Greg KH [mailto:gregkh@linuxfoundation.org] > Sent: Monday, September 22, 2014 9:16 PM > To: Zhu Richard-R65037 > Cc: linux-pci-owner@vger.kernel.org; stable@vger.kernel.org; linux- > pci@vger.kernel.org; l.stach@pengutronix.de > Subject: Re: [PATCH RFC 2/2] PCI: imx6: add imx6sx pcie support > > On Mon, Sep 22, 2014 at 05:01:38PM +0800, Richard Zhu wrote: > > - 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. > > - another dis_axi clk is mandatory required by imx6sx pcie. > > Add one new clk named pcie_sec into imx6_pcie structure. > > - pcie_ref_125m is not used as pcie_phy clk anymore on imx6sx. > > The parent clk (pcie_ref) of the pcie_bus(lvds1_gate) is used as > > pcie_phy clk. > > - Register one PM call-back, enter/exit L2 state of the ASPM during > > system suspend/resume. > > - wait the clocks to stabilize after the pcie_ref_en > > (IMX6Q_GPR1_PCIE_REF_CLK_EN) is set. > > > > Signed-off-by: Richard Zhu <r65037@freescale.com> > > --- > > arch/arm/boot/dts/imx6sx-sdb.dts | 15 ++ > > arch/arm/boot/dts/imx6sx.dtsi | 33 ++-- > > arch/arm/mach-imx/Kconfig | 1 + > > drivers/pci/host/pci-imx6.c | 228 ++++++++++++++++++++++++- > --- > > include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++ > > 5 files changed, 249 insertions(+), 42 deletions(-) > > <formletter> > > This is not the correct way to submit patches for inclusion in the stable > kernel tree. Please read Documentation/stable_kernel_rules.txt > for how to do this properly. > > </formletter> [Richard] Roger that, thanks for your reminder. It's my fault to make a mistake to send the patch review to table kernel mail-list. Sorry about that. Best Regards Richard Zhu -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts index a3980d9..83d0892 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dts +++ b/arch/arm/boot/dts/imx6sx-sdb.dts @@ -251,6 +251,14 @@ }; }; +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcie>; + power-on-gpio = <&gpio2 1 0>; + reset-gpio = <&gpio2 0 0>; + status = "okay"; +}; + &ssi2 { status = "okay"; }; @@ -365,6 +373,13 @@ >; }; + pinctrl_pcie: pciegrp { + fsl,pins = < + MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x17059 + MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 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..ec34698 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -689,9 +689,11 @@ }; gpc: 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 = <®_pcie>; }; iomuxc: 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_sec", "pcie_bus"; + pcie-supply = <®_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 diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 233fe8a..c9b2f69 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,32 @@ #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; + int power_on_gpio; + const struct imx_pcie_data *data; struct clk *pcie_bus; struct clk *pcie_phy; + struct clk *pcie_sec; 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 +98,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; @@ -257,10 +283,21 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); int ret; - ret = clk_prepare_enable(imx6_pcie->pcie_phy); - if (ret) { - dev_err(pp->dev, "unable to enable pcie_phy clock\n"); - goto err_pcie_phy; + if (gpio_is_valid(imx6_pcie->power_on_gpio)) + gpio_set_value(imx6_pcie->power_on_gpio, 1); + + if (is_imx6sx_pcie(imx6_pcie)) { + ret = clk_prepare_enable(imx6_pcie->pcie_sec); + if (ret) { + dev_err(pp->dev, "unable to enable pcie_sec clk.\n"); + goto err_pcie_sec; + } + } else { + ret = clk_prepare_enable(imx6_pcie->pcie_phy); + if (ret) { + dev_err(pp->dev, "unable to enable pcie_phy clock\n"); + goto err_pcie_phy; + } } ret = clk_prepare_enable(imx6_pcie->pcie_bus); @@ -275,28 +312,50 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) goto err_pcie; } + 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); - /* 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); - /* Some boards don't have PCIe reset GPIO. */ if (gpio_is_valid(imx6_pcie->reset_gpio)) { gpio_set_value(imx6_pcie->reset_gpio, 0); 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: clk_disable_unprepare(imx6_pcie->pcie_bus); err_pcie_bus: - clk_disable_unprepare(imx6_pcie->pcie_phy); + if (!is_imx6sx_pcie(imx6_pcie)) + clk_disable_unprepare(imx6_pcie->pcie_phy); err_pcie_phy: + if (is_imx6sx_pcie(imx6_pcie)) + clk_disable_unprepare(imx6_pcie->pcie_sec); +err_pcie_sec: return ret; } @@ -304,15 +363,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 +452,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 +629,73 @@ 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); + + /* 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); + } +} + +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 +706,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, @@ -581,12 +728,26 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) } } + imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); + if (gpio_is_valid(imx6_pcie->power_on_gpio)) { + ret = devm_gpio_request_one(&pdev->dev, + imx6_pcie->power_on_gpio, + GPIOF_OUT_INIT_LOW, + "PCIe power enable"); + if (ret) { + dev_err(&pdev->dev, "unable to get power-on gpio\n"); + return ret; + } + } + /* Fetch clocks */ - imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); - if (IS_ERR(imx6_pcie->pcie_phy)) { - dev_err(&pdev->dev, - "pcie_phy clock source missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie_phy); + if (!is_imx6sx_pcie(imx6_pcie)) { + imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); + if (IS_ERR(imx6_pcie->pcie_phy)) { + dev_err(&pdev->dev, + "pcie_phy clock source missing or invalid\n"); + return PTR_ERR(imx6_pcie->pcie_phy); + } } imx6_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_bus"); @@ -604,8 +765,22 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) } /* Grab GPR config register range */ - imx6_pcie->iomuxc_gpr = - syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (is_imx6sx_pcie(imx6_pcie)) { + /* Get pcie regulator */ + imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev, "pcie"); + + /* Grab GPR config register range */ + imx6_pcie->iomuxc_gpr = + syscon_regmap_lookup_by_compatible + ("fsl,imx6sx-iomuxc-gpr"); + /* Grab GPC IPS register range */ + 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 +791,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 +805,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", 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 */
- 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. - another dis_axi clk is mandatory required by imx6sx pcie. Add one new clk named pcie_sec into imx6_pcie structure. - pcie_ref_125m is not used as pcie_phy clk anymore on imx6sx. The parent clk (pcie_ref) of the pcie_bus(lvds1_gate) is used as pcie_phy clk. - Register one PM call-back, enter/exit L2 state of the ASPM during system suspend/resume. - wait the clocks to stabilize after the pcie_ref_en (IMX6Q_GPR1_PCIE_REF_CLK_EN) is set. Signed-off-by: Richard Zhu <r65037@freescale.com> --- arch/arm/boot/dts/imx6sx-sdb.dts | 15 ++ arch/arm/boot/dts/imx6sx.dtsi | 33 ++-- arch/arm/mach-imx/Kconfig | 1 + drivers/pci/host/pci-imx6.c | 228 ++++++++++++++++++++++++---- include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 14 ++ 5 files changed, 249 insertions(+), 42 deletions(-)