diff mbox

[v4,02/10] PCI: imx6: add imx6sx pcie support

Message ID 1412069804-17162-3-git-send-email-r65037@freescale.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Richard Zhu Sept. 30, 2014, 9:36 a.m. UTC
- 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.
- disp_axi clock is required by pcie inbound axi port actually.
Add one more clock named pcie_inbound_axi for imx6sx pcie.

Signed-off-by: Richard Zhu <r65037@freescale.com>
---
 drivers/pci/host/pci-imx6.c | 163 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 144 insertions(+), 19 deletions(-)

Comments

Lucas Stach Sept. 30, 2014, 2:54 p.m. UTC | #1
Am Dienstag, den 30.09.2014, 17:36 +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.
> - Register one PM call-back, enter/exit L2 state of the ASPM
> during system suspend/resume.
> - disp_axi clock is required by pcie inbound axi port actually.
> Add one more clock named pcie_inbound_axi for imx6sx pcie.
> 
> Signed-off-by: Richard Zhu <r65037@freescale.com>
> ---
>  drivers/pci/host/pci-imx6.c | 163 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 144 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index eac96fb..c74e87d 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -22,8 +22,10 @@
>  #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>
>  
> @@ -35,11 +37,15 @@ struct imx6_pcie {
>  	int			reset_gpio;
>  	struct clk		*pcie_bus;
>  	struct clk		*pcie_phy;
> +	struct clk		*pcie_inbound_axi;
>  	struct clk		*pcie;
>  	struct pcie_port	pp;
>  	struct regmap		*iomuxc_gpr;
> +	struct regmap		*gpc_ips_reg;
> +	struct regulator	*pcie_regulator;

I would expect this to be named pcie_phy_regulator.

>  	void __iomem		*mem_base;
>  };
> +static struct imx6_pcie *imx6_pcie;

No. This is just bad style. You have the pointer available embedded in
other structures at all relevant places. No global statics please.

>  
>  /* PCIe Root Complex registers (memory-mapped) */
>  #define PCIE_RC_LCR				0x7c
> @@ -77,6 +83,18 @@ 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)
>  
> +/* GPC PCIE PHY bit definitions */
> +#define GPC_CNTR			0
> +#define GPC_CNTR_PCIE_PHY_PUP_REQ	BIT(7)
> +
> +static inline bool is_imx6sx_pcie(struct imx6_pcie *imx6_pcie)
> +{
> +	struct pcie_port *pp = &imx6_pcie->pp;
> +	struct device_node *np = pp->dev->of_node;
> +
> +	return of_device_is_compatible(np, "fsl,imx6sx-pcie");
> +}
> +
>  static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
>  {
>  	u32 val;
> @@ -275,18 +293,29 @@ 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);
> -	/*
> -	 * the async reset input need ref clock to sync internally,
> -	 * when the ref clock comes after reset, internal synced
> -	 * reset time is too short , cannot meet the requirement.
> -	 * add one ~10us delay here.
> -	 */
> -	udelay(10);
> -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -			IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
> +	if (is_imx6sx_pcie(imx6_pcie)) {
> +		ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
> +		if (ret) {
> +			dev_err(pp->dev, "unable to enable pcie clock\n");
> +			goto err_inbound_axi;
> +		}
> +
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> +				IMX6SX_GPR12_PCIE_TEST_PD, 0);
> +	} else {
> +		/* power up core phy and enable ref clock */
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> +				IMX6Q_GPR1_PCIE_TEST_PD, 0);
> +		/*
> +		 * the async reset input need ref clock to sync internally,
> +		 * when the ref clock comes after reset, internal synced
> +		 * reset time is too short , cannot meet the requirement.
> +		 * add one ~10us delay here.
> +		 */
> +		udelay(10);
> +		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);
> @@ -297,8 +326,19 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
>  		msleep(100);
>  		gpio_set_value(imx6_pcie->reset_gpio, 1);
>  	}
> +
> +	/*
> +	 * Release the PCIe PHY reset here, that we have set in
> +	 * imx6_pcie_init_phy() now
> +	 */
> +	if (is_imx6sx_pcie(imx6_pcie))
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
> +				IMX6SX_GPR5_PCIE_BTNRST, 0);
> +
>  	return 0;
>  
> +err_inbound_axi:
> +	clk_disable_unprepare(imx6_pcie->pcie);
>  err_pcie:
>  	clk_disable_unprepare(imx6_pcie->pcie_bus);
>  err_pcie_bus:
> @@ -311,6 +351,26 @@ err_pcie_phy:
>  static void imx6_pcie_init_phy(struct pcie_port *pp)
>  {
>  	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
> +	int ret;
> +
> +	/* Power up the separate domain available on i.MX6SX */
> +	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, GPC_CNTR,
> +				GPC_CNTR_PCIE_PHY_PUP_REQ,
> +				GPC_CNTR_PCIE_PHY_PUP_REQ);
> +		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);
> @@ -319,7 +379,7 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
>  	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);
> @@ -377,7 +437,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)
> @@ -553,9 +614,50 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
>  	return 0;
>  }
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int pci_imx_suspend(void)
> +{
> +	if (is_imx6sx_pcie(imx6_pcie)) {
> +		/* PM_TURN_OFF */
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> +				IMX6SX_GPR12_PCIE_PM_TURN_OFF,
> +				IMX6SX_GPR12_PCIE_PM_TURN_OFF);
> +		udelay(10);
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> +				IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +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,
> +				IMX6SX_GPR5_PCIE_PERST, IMX6SX_GPR5_PCIE_PERST);
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
> +				IMX6SX_GPR5_PCIE_PERST, 0);
> +		/*
> +		 * controller maybe turn off, re-configure again
> +		 */
> +		dw_pcie_setup_rc(pp);
> +
> +		if (IS_ENABLED(CONFIG_PCI_MSI))
> +			dw_pcie_msi_cfg_restore(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;
>  	struct device_node *np = pdev->dev.of_node;
>  	struct resource *dbi_base;
> @@ -572,7 +674,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
>  	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
>  		"imprecise external abort");
>  
> -	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");

You are breaking old devicetrees here. "rc_dbi" isn't a documented name
and isn't available on old DTs. Besides the imx6q DT uses just "dbi" as
the name. Don't touch this code, it does exactly the right thing by
grabbing the first reg resource.

>  	pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
>  	if (IS_ERR(pp->dbi_base))
>  		return PTR_ERR(pp->dbi_base);
> @@ -610,9 +712,28 @@ 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_inbound_axi = devm_clk_get(&pdev->dev,
> +				"pcie_inbound_axi");
> +		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
> +			dev_err(&pdev->dev,
> +				"pcie clock source missing or invalid\n");
> +			return PTR_ERR(imx6_pcie->pcie_inbound_axi);
> +		}
> +
> +		imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev,
> +				"pcie-phy");
> +
> +		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);
> @@ -623,6 +744,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;
>  }
>  
> @@ -636,6 +760,7 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
>  
>  static const struct of_device_id imx6_pcie_of_match[] = {
>  	{ .compatible = "fsl,imx6q-pcie", },
> +	{ .compatible = "fsl,imx6sx-pcie", },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
Richard Zhu Oct. 2, 2014, 2:38 a.m. UTC | #2
> ? 2014?9?30????10:54?"Lucas Stach" <l.stach@pengutronix.de> ???

> 

> Am Dienstag, den 30.09.2014, 17:36 +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.

>> - Register one PM call-back, enter/exit L2 state of the ASPM

>> during system suspend/resume.

>> - disp_axi clock is required by pcie inbound axi port actually.

>> Add one more clock named pcie_inbound_axi for imx6sx pcie.

>> 

>> Signed-off-by: Richard Zhu <r65037@freescale.com>

>> ---

>> drivers/pci/host/pci-imx6.c | 163 ++++++++++++++++++++++++++++++++++++++------

>> 1 file changed, 144 insertions(+), 19 deletions(-)

>> 

>> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c

>> index eac96fb..c74e87d 100644

>> --- a/drivers/pci/host/pci-imx6.c

>> +++ b/drivers/pci/host/pci-imx6.c

>> @@ -22,8 +22,10 @@

>> #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>

>> 

>> @@ -35,11 +37,15 @@ struct imx6_pcie {

>>    int            reset_gpio;

>>    struct clk        *pcie_bus;

>>    struct clk        *pcie_phy;

>> +    struct clk        *pcie_inbound_axi;

>>    struct clk        *pcie;

>>    struct pcie_port    pp;

>>    struct regmap        *iomuxc_gpr;

>> +    struct regmap        *gpc_ips_reg;

>> +    struct regulator    *pcie_regulator;

> 

> I would expect this to be named pcie_phy_regulator.

Ok.
> 

>>    void __iomem        *mem_base;

>> };

>> +static struct imx6_pcie *imx6_pcie;

> 

> No. This is just bad style. You have the pointer available embedded in

> other structures at all relevant places. No global statics please.

Ok.
> 

>> 

>> /* PCIe Root Complex registers (memory-mapped) */

>> #define PCIE_RC_LCR                0x7c

>> @@ -77,6 +83,18 @@ 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)

>> 

>> +/* GPC PCIE PHY bit definitions */

>> +#define GPC_CNTR            0

>> +#define GPC_CNTR_PCIE_PHY_PUP_REQ    BIT(7)

>> +

>> +static inline bool is_imx6sx_pcie(struct imx6_pcie *imx6_pcie)

>> +{

>> +    struct pcie_port *pp = &imx6_pcie->pp;

>> +    struct device_node *np = pp->dev->of_node;

>> +

>> +    return of_device_is_compatible(np, "fsl,imx6sx-pcie");

>> +}

>> +

>> static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)

>> {

>>    u32 val;

>> @@ -275,18 +293,29 @@ 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);

>> -    /*

>> -     * the async reset input need ref clock to sync internally,

>> -     * when the ref clock comes after reset, internal synced

>> -     * reset time is too short , cannot meet the requirement.

>> -     * add one ~10us delay here.

>> -     */

>> -    udelay(10);

>> -    regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,

>> -            IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);

>> +    if (is_imx6sx_pcie(imx6_pcie)) {

>> +        ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);

>> +        if (ret) {

>> +            dev_err(pp->dev, "unable to enable pcie clock\n");

>> +            goto err_inbound_axi;

>> +        }

>> +

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,

>> +                IMX6SX_GPR12_PCIE_TEST_PD, 0);

>> +    } else {

>> +        /* power up core phy and enable ref clock */

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,

>> +                IMX6Q_GPR1_PCIE_TEST_PD, 0);

>> +        /*

>> +         * the async reset input need ref clock to sync internally,

>> +         * when the ref clock comes after reset, internal synced

>> +         * reset time is too short , cannot meet the requirement.

>> +         * add one ~10us delay here.

>> +         */

>> +        udelay(10);

>> +        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);

>> @@ -297,8 +326,19 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)

>>        msleep(100);

>>        gpio_set_value(imx6_pcie->reset_gpio, 1);

>>    }

>> +

>> +    /*

>> +     * Release the PCIe PHY reset here, that we have set in

>> +     * imx6_pcie_init_phy() now

>> +     */

>> +    if (is_imx6sx_pcie(imx6_pcie))

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,

>> +                IMX6SX_GPR5_PCIE_BTNRST, 0);

>> +

>>    return 0;

>> 

>> +err_inbound_axi:

>> +    clk_disable_unprepare(imx6_pcie->pcie);

>> err_pcie:

>>    clk_disable_unprepare(imx6_pcie->pcie_bus);

>> err_pcie_bus:

>> @@ -311,6 +351,26 @@ err_pcie_phy:

>> static void imx6_pcie_init_phy(struct pcie_port *pp)

>> {

>>    struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);

>> +    int ret;

>> +

>> +    /* Power up the separate domain available on i.MX6SX */

>> +    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, GPC_CNTR,

>> +                GPC_CNTR_PCIE_PHY_PUP_REQ,

>> +                GPC_CNTR_PCIE_PHY_PUP_REQ);

>> +        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);

>> @@ -319,7 +379,7 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)

>>    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);

>> @@ -377,7 +437,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)

>> @@ -553,9 +614,50 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,

>>    return 0;

>> }

>> 

>> +#ifdef CONFIG_PM_SLEEP

>> +static int pci_imx_suspend(void)

>> +{

>> +    if (is_imx6sx_pcie(imx6_pcie)) {

>> +        /* PM_TURN_OFF */

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,

>> +                IMX6SX_GPR12_PCIE_PM_TURN_OFF,

>> +                IMX6SX_GPR12_PCIE_PM_TURN_OFF);

>> +        udelay(10);

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,

>> +                IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);

>> +    }

>> +

>> +    return 0;

>> +}

>> +

>> +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,

>> +                IMX6SX_GPR5_PCIE_PERST, IMX6SX_GPR5_PCIE_PERST);

>> +        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,

>> +                IMX6SX_GPR5_PCIE_PERST, 0);

>> +        /*

>> +         * controller maybe turn off, re-configure again

>> +         */

>> +        dw_pcie_setup_rc(pp);

>> +

>> +        if (IS_ENABLED(CONFIG_PCI_MSI))

>> +            dw_pcie_msi_cfg_restore(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;

>>    struct device_node *np = pdev->dev.of_node;

>>    struct resource *dbi_base;

>> @@ -572,7 +674,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)

>>    hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,

>>        "imprecise external abort");

>> 

>> -    dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);

>> +    dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");

> 

> You are breaking old devicetrees here. "rc_dbi" isn't a documented name

> and isn't available on old DTs. Besides the imx6q DT uses just "dbi" as

> the name. Don't touch this code, it does exactly the right thing by

> grabbing the first reg resource.


Ok, changes would be removed.

> 

>>    pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);

>>    if (IS_ERR(pp->dbi_base))

>>        return PTR_ERR(pp->dbi_base);

>> @@ -610,9 +712,28 @@ 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_inbound_axi = devm_clk_get(&pdev->dev,

>> +                "pcie_inbound_axi");

>> +        if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {

>> +            dev_err(&pdev->dev,

>> +                "pcie clock source missing or invalid\n");

>> +            return PTR_ERR(imx6_pcie->pcie_inbound_axi);

>> +        }

>> +

>> +        imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev,

>> +                "pcie-phy");

>> +

>> +        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);

>> @@ -623,6 +744,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;

>> }

>> 

>> @@ -636,6 +760,7 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)

>> 

>> static const struct of_device_id imx6_pcie_of_match[] = {

>>    { .compatible = "fsl,imx6q-pcie", },

>> +    { .compatible = "fsl,imx6sx-pcie", },

>>    {},

>> };

>> MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);

> 

> -- 

> Pengutronix e.K.             | Lucas Stach                 |

> Industrial Linux Solutions   | http://www.pengutronix.de/  |

> 

> 

Best regards
Richard
Richard Zhu Oct. 8, 2014, 7:30 a.m. UTC | #3
DQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IFpodSBSaWNoYXJkLVI2NTAz
Nw0KPiBTZW50OiBUaHVyc2RheSwgT2N0b2JlciAwMiwgMjAxNCAxMDozOSBBTQ0KPiBUbzogTHVj
YXMgU3RhY2gNCj4gQ2M6IFpodSBSaWNoYXJkLVI2NTAzNzsgbGludXgtcGNpLW93bmVyQHZnZXIu
a2VybmVsLm9yZzsgbGludXgtDQo+IHBjaUB2Z2VyLmtlcm5lbC5vcmc7IEd1byBTaGF3bi1SNjUw
NzM7IGZlc3RldmFtQGdtYWlsLmNvbTsNCj4gdGhhcnZleUBnYXRld29ya3MuY29tDQo+IFN1Ympl
Y3Q6IFJlOiBbUEFUQ0ggdjQgMDIvMTBdIFBDSTogaW14NjogYWRkIGlteDZzeCBwY2llIHN1cHBv
cnQNCj4gDQo+IA0KPiANCj4gDQo+ID4g1NogMjAxNMTqOdTCMzDI1aOsz8LO5zEwOjU0o6wiTHVj
YXMgU3RhY2giIDxsLnN0YWNoQHBlbmd1dHJvbml4LmRlPiDQtLXAo7oNCj4gPg0KPiA+IEFtIERp
ZW5zdGFnLCBkZW4gMzAuMDkuMjAxNCwgMTc6MzYgKzA4MDAgc2NocmllYiBSaWNoYXJkIFpodToN
Cj4gPj4gLSBpbXg2c3ggcGNpZSBoYXMgaXRzIG93biBzdGFuZGFsb25lIHBjaWUgcG93ZXIgc3Vw
cGx5Lg0KPiA+PiBJbiBvcmRlciB0byB0dXJuIG9uIHRoZSBpbXg2c3ggcGNpZSBwb3dlciBkdXJp
bmcgaW5pdGlhbGl6YXRpb24uIEFkZA0KPiA+PiB0aGUgcGNpZSByZWd1bGF0b3IgYW5kIHRoZSBn
cGMgcmVnbWFwIGludG8gdGhlIGlteDZzeCBwY2llIHN0cnVjdHVyZS4NCj4gPj4gLSBpbXg2c3gg
cGNpZSBoYXMgdGhlIG5ldyBhZGRlZCByZXNldCBtZWNoYW5pc20sIGFkZCB0aGUgcmVzZXQNCj4g
Pj4gb3BlcmF0aW9ucyBpbnRvIHRoZSBpbml0aWFsaXphdGlvbi4NCj4gPj4gLSBSZWdpc3RlciBv
bmUgUE0gY2FsbC1iYWNrLCBlbnRlci9leGl0IEwyIHN0YXRlIG9mIHRoZSBBU1BNIGR1cmluZw0K
PiA+PiBzeXN0ZW0gc3VzcGVuZC9yZXN1bWUuDQo+ID4+IC0gZGlzcF9heGkgY2xvY2sgaXMgcmVx
dWlyZWQgYnkgcGNpZSBpbmJvdW5kIGF4aSBwb3J0IGFjdHVhbGx5Lg0KPiA+PiBBZGQgb25lIG1v
cmUgY2xvY2sgbmFtZWQgcGNpZV9pbmJvdW5kX2F4aSBmb3IgaW14NnN4IHBjaWUuDQo+ID4+DQo+
ID4+IFNpZ25lZC1vZmYtYnk6IFJpY2hhcmQgWmh1IDxyNjUwMzdAZnJlZXNjYWxlLmNvbT4NCj4g
Pj4gLS0tDQo+ID4+IGRyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYyB8IDE2Mw0KPiA+PiArKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tLS0tLQ0KPiA+PiAxIGZpbGUgY2hh
bmdlZCwgMTQ0IGluc2VydGlvbnMoKyksIDE5IGRlbGV0aW9ucygtKQ0KPiA+Pg0KPiA+PiBkaWZm
IC0tZ2l0IGEvZHJpdmVycy9wY2kvaG9zdC9wY2ktaW14Ni5jDQo+ID4+IGIvZHJpdmVycy9wY2kv
aG9zdC9wY2ktaW14Ni5jIGluZGV4IGVhYzk2ZmIuLmM3NGU4N2QgMTAwNjQ0DQo+ID4+IC0tLSBh
L2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KPiA+PiArKysgYi9kcml2ZXJzL3BjaS9ob3N0
L3BjaS1pbXg2LmMNCj4gPj4gQEAgLTIyLDggKzIyLDEwIEBADQo+ID4+ICNpbmNsdWRlIDxsaW51
eC9wY2kuaD4NCj4gPj4gI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPg0KPiA+PiAj
aW5jbHVkZSA8bGludXgvcmVnbWFwLmg+DQo+ID4+ICsjaW5jbHVkZSA8bGludXgvcmVndWxhdG9y
L2NvbnN1bWVyLmg+DQo+ID4+ICNpbmNsdWRlIDxsaW51eC9yZXNvdXJjZS5oPg0KPiA+PiAjaW5j
bHVkZSA8bGludXgvc2lnbmFsLmg+DQo+ID4+ICsjaW5jbHVkZSA8bGludXgvc3lzY29yZV9vcHMu
aD4NCj4gPj4gI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+DQo+ID4+ICNpbmNsdWRlIDxsaW51eC9p
bnRlcnJ1cHQuaD4NCj4gPj4NCj4gPj4gQEAgLTM1LDExICszNywxNSBAQCBzdHJ1Y3QgaW14Nl9w
Y2llIHsNCj4gPj4gICAgaW50ICAgICAgICAgICAgcmVzZXRfZ3BpbzsNCj4gPj4gICAgc3RydWN0
IGNsayAgICAgICAgKnBjaWVfYnVzOw0KPiA+PiAgICBzdHJ1Y3QgY2xrICAgICAgICAqcGNpZV9w
aHk7DQo+ID4+ICsgICAgc3RydWN0IGNsayAgICAgICAgKnBjaWVfaW5ib3VuZF9heGk7DQo+ID4+
ICAgIHN0cnVjdCBjbGsgICAgICAgICpwY2llOw0KPiA+PiAgICBzdHJ1Y3QgcGNpZV9wb3J0ICAg
IHBwOw0KPiA+PiAgICBzdHJ1Y3QgcmVnbWFwICAgICAgICAqaW9tdXhjX2dwcjsNCj4gPj4gKyAg
ICBzdHJ1Y3QgcmVnbWFwICAgICAgICAqZ3BjX2lwc19yZWc7DQo+ID4+ICsgICAgc3RydWN0IHJl
Z3VsYXRvciAgICAqcGNpZV9yZWd1bGF0b3I7DQo+ID4NCj4gPiBJIHdvdWxkIGV4cGVjdCB0aGlz
IHRvIGJlIG5hbWVkIHBjaWVfcGh5X3JlZ3VsYXRvci4NCj4gT2suDQo+ID4NCj4gPj4gICAgdm9p
ZCBfX2lvbWVtICAgICAgICAqbWVtX2Jhc2U7DQo+ID4+IH07DQo+ID4+ICtzdGF0aWMgc3RydWN0
IGlteDZfcGNpZSAqaW14Nl9wY2llOw0KPiA+DQo+ID4gTm8uIFRoaXMgaXMganVzdCBiYWQgc3R5
bGUuIFlvdSBoYXZlIHRoZSBwb2ludGVyIGF2YWlsYWJsZSBlbWJlZGRlZCBpbg0KPiA+IG90aGVy
IHN0cnVjdHVyZXMgYXQgYWxsIHJlbGV2YW50IHBsYWNlcy4gTm8gZ2xvYmFsIHN0YXRpY3MgcGxl
YXNlLg0KPiBPay4NCkhpIEx1Y2FzOg0KUmVnYXJkaW5nIHRvIHRoZSBkZWZpbml0aW9ucyhwYXN0
ZWQgYmVsb3cpIG9mIHRoZSBzdHJ1Y3Qgc3lzY29yZV9vcHMsIGJvdGggc3VzcGVuZCBhbmQgcmVz
dW1lDQpvZiB0aGUgc3lzY29yZV9vcHMgaXMgdm9pZCB0eXBlIGZ1bmN0aW9ucy4NCklmIHRoZXJl
IGlzIG5vIHRoZSBzdGF0aWMgZ2xvYmFsIHN0cnVjdCBpbXg2X3BjaWUsIEkgZG9uJ3Qga25vdyBo
b3cgaXQgY2FuIGJlIHVzZWQgaW4gc3VzcGVuZC9yZXN1bWUgb2YgcGNpX2lteF9zeXNjb3JlX29w
cy4NCnN0cnVjdCBzeXNjb3JlX29wcyB7DQogICAgICAgIHN0cnVjdCBsaXN0X2hlYWQgbm9kZTsN
CiAgICAgICAgaW50ICgqc3VzcGVuZCkodm9pZCk7DQogICAgICAgIHZvaWQgKCpyZXN1bWUpKHZv
aWQpOw0KICAgICAgICB2b2lkICgqc2h1dGRvd24pKHZvaWQpOw0KfTsNCg0KQmVzdCBSZWdhcmRz
DQpSaWNoYXJkIFpodQ0KDQo+ID4NCj4gPj4NCj4gPj4gLyogUENJZSBSb290IENvbXBsZXggcmVn
aXN0ZXJzIChtZW1vcnktbWFwcGVkKSAqLw0KPiA+PiAjZGVmaW5lIFBDSUVfUkNfTENSICAgICAg
ICAgICAgICAgIDB4N2MNCj4gPj4gQEAgLTc3LDYgKzgzLDE4IEBAIHN0cnVjdCBpbXg2X3BjaWUg
eyAjZGVmaW5lDQo+ID4+IFBIWV9SWF9PVlJEX0lOX0xPX1JYX0RBVEFfRU4gKDEgPDwgNSkgI2Rl
ZmluZQ0KPiA+PiBQSFlfUlhfT1ZSRF9JTl9MT19SWF9QTExfRU4gKDEgPDwgMykNCj4gPj4NCj4g
Pj4gKy8qIEdQQyBQQ0lFIFBIWSBiaXQgZGVmaW5pdGlvbnMgKi8NCj4gPj4gKyNkZWZpbmUgR1BD
X0NOVFIgICAgICAgICAgICAwDQo+ID4+ICsjZGVmaW5lIEdQQ19DTlRSX1BDSUVfUEhZX1BVUF9S
RVEgICAgQklUKDcpDQo+ID4+ICsNCj4gPj4gK3N0YXRpYyBpbmxpbmUgYm9vbCBpc19pbXg2c3hf
cGNpZShzdHJ1Y3QgaW14Nl9wY2llICppbXg2X3BjaWUpIHsNCj4gPj4gKyAgICBzdHJ1Y3QgcGNp
ZV9wb3J0ICpwcCA9ICZpbXg2X3BjaWUtPnBwOw0KPiA+PiArICAgIHN0cnVjdCBkZXZpY2Vfbm9k
ZSAqbnAgPSBwcC0+ZGV2LT5vZl9ub2RlOw0KPiA+PiArDQo+ID4+ICsgICAgcmV0dXJuIG9mX2Rl
dmljZV9pc19jb21wYXRpYmxlKG5wLCAiZnNsLGlteDZzeC1wY2llIik7IH0NCj4gPj4gKw0KPiA+
PiBzdGF0aWMgaW50IHBjaWVfcGh5X3BvbGxfYWNrKHZvaWQgX19pb21lbSAqZGJpX2Jhc2UsIGlu
dCBleHBfdmFsKSB7DQo+ID4+ICAgIHUzMiB2YWw7DQo+ID4+IEBAIC0yNzUsMTggKzI5MywyOSBA
QCBzdGF0aWMgaW50IGlteDZfcGNpZV9kZWFzc2VydF9jb3JlX3Jlc2V0KHN0cnVjdA0KPiBwY2ll
X3BvcnQgKnBwKQ0KPiA+PiAgICAgICAgZ290byBlcnJfcGNpZTsNCj4gPj4gICAgfQ0KPiA+Pg0K
PiA+PiAtICAgIC8qIHBvd2VyIHVwIGNvcmUgcGh5IGFuZCBlbmFibGUgcmVmIGNsb2NrICovDQo+
ID4+IC0gICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhD
X0dQUjEsDQo+ID4+IC0gICAgICAgICAgICBJTVg2UV9HUFIxX1BDSUVfVEVTVF9QRCwgMCA8PCAx
OCk7DQo+ID4+IC0gICAgLyoNCj4gPj4gLSAgICAgKiB0aGUgYXN5bmMgcmVzZXQgaW5wdXQgbmVl
ZCByZWYgY2xvY2sgdG8gc3luYyBpbnRlcm5hbGx5LA0KPiA+PiAtICAgICAqIHdoZW4gdGhlIHJl
ZiBjbG9jayBjb21lcyBhZnRlciByZXNldCwgaW50ZXJuYWwgc3luY2VkDQo+ID4+IC0gICAgICog
cmVzZXQgdGltZSBpcyB0b28gc2hvcnQgLCBjYW5ub3QgbWVldCB0aGUgcmVxdWlyZW1lbnQuDQo+
ID4+IC0gICAgICogYWRkIG9uZSB+MTB1cyBkZWxheSBoZXJlLg0KPiA+PiAtICAgICAqLw0KPiA+
PiAtICAgIHVkZWxheSgxMCk7DQo+ID4+IC0gICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNp
ZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEsDQo+ID4+IC0gICAgICAgICAgICBJTVg2UV9HUFIx
X1BDSUVfUkVGX0NMS19FTiwgMSA8PCAxNik7DQo+ID4+ICsgICAgaWYgKGlzX2lteDZzeF9wY2ll
KGlteDZfcGNpZSkpIHsNCj4gPj4gKyAgICAgICAgcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGlt
eDZfcGNpZS0+cGNpZV9pbmJvdW5kX2F4aSk7DQo+ID4+ICsgICAgICAgIGlmIChyZXQpIHsNCj4g
Pj4gKyAgICAgICAgICAgIGRldl9lcnIocHAtPmRldiwgInVuYWJsZSB0byBlbmFibGUgcGNpZSBj
bG9ja1xuIik7DQo+ID4+ICsgICAgICAgICAgICBnb3RvIGVycl9pbmJvdW5kX2F4aTsNCj4gPj4g
KyAgICAgICAgfQ0KPiA+PiArDQo+ID4+ICsgICAgICAgIHJlZ21hcF91cGRhdGVfYml0cyhpbXg2
X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxMiwNCj4gPj4gKyAgICAgICAgICAgICAgICBJ
TVg2U1hfR1BSMTJfUENJRV9URVNUX1BELCAwKTsNCj4gPj4gKyAgICB9IGVsc2Ugew0KPiA+PiAr
ICAgICAgICAvKiBwb3dlciB1cCBjb3JlIHBoeSBhbmQgZW5hYmxlIHJlZiBjbG9jayAqLw0KPiA+
PiArICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01V
WENfR1BSMSwNCj4gPj4gKyAgICAgICAgICAgICAgICBJTVg2UV9HUFIxX1BDSUVfVEVTVF9QRCwg
MCk7DQo+ID4+ICsgICAgICAgIC8qDQo+ID4+ICsgICAgICAgICAqIHRoZSBhc3luYyByZXNldCBp
bnB1dCBuZWVkIHJlZiBjbG9jayB0byBzeW5jIGludGVybmFsbHksDQo+ID4+ICsgICAgICAgICAq
IHdoZW4gdGhlIHJlZiBjbG9jayBjb21lcyBhZnRlciByZXNldCwgaW50ZXJuYWwgc3luY2VkDQo+
ID4+ICsgICAgICAgICAqIHJlc2V0IHRpbWUgaXMgdG9vIHNob3J0ICwgY2Fubm90IG1lZXQgdGhl
IHJlcXVpcmVtZW50Lg0KPiA+PiArICAgICAgICAgKiBhZGQgb25lIH4xMHVzIGRlbGF5IGhlcmUu
DQo+ID4+ICsgICAgICAgICAqLw0KPiA+PiArICAgICAgICB1ZGVsYXkoMTApOw0KPiA+PiArICAg
ICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BS
MSwNCj4gPj4gKyAgICAgICAgICAgICAgICBJTVg2UV9HUFIxX1BDSUVfUkVGX0NMS19FTiwgMSA8
PCAxNik7DQo+ID4+ICsgICAgfQ0KPiA+Pg0KPiA+PiAgICAvKiBhbGxvdyB0aGUgY2xvY2tzIHRv
IHN0YWJpbGl6ZSAqLw0KPiA+PiAgICB1c2xlZXBfcmFuZ2UoMjAwLCA1MDApOw0KPiA+PiBAQCAt
Mjk3LDggKzMyNiwxOSBAQCBzdGF0aWMgaW50IGlteDZfcGNpZV9kZWFzc2VydF9jb3JlX3Jlc2V0
KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBwKQ0KPiA+PiAgICAgICAgbXNsZWVwKDEwMCk7DQo+ID4+
ICAgICAgICBncGlvX3NldF92YWx1ZShpbXg2X3BjaWUtPnJlc2V0X2dwaW8sIDEpOw0KPiA+PiAg
ICB9DQo+ID4+ICsNCj4gPj4gKyAgICAvKg0KPiA+PiArICAgICAqIFJlbGVhc2UgdGhlIFBDSWUg
UEhZIHJlc2V0IGhlcmUsIHRoYXQgd2UgaGF2ZSBzZXQgaW4NCj4gPj4gKyAgICAgKiBpbXg2X3Bj
aWVfaW5pdF9waHkoKSBub3cNCj4gPj4gKyAgICAgKi8NCj4gPj4gKyAgICBpZiAoaXNfaW14NnN4
X3BjaWUoaW14Nl9wY2llKSkNCj4gPj4gKyAgICAgICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZf
cGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjUsDQo+ID4+ICsgICAgICAgICAgICAgICAgSU1Y
NlNYX0dQUjVfUENJRV9CVE5SU1QsIDApOw0KPiA+PiArDQo+ID4+ICAgIHJldHVybiAwOw0KPiA+
Pg0KPiA+PiArZXJyX2luYm91bmRfYXhpOg0KPiA+PiArICAgIGNsa19kaXNhYmxlX3VucHJlcGFy
ZShpbXg2X3BjaWUtPnBjaWUpOw0KPiA+PiBlcnJfcGNpZToNCj4gPj4gICAgY2xrX2Rpc2FibGVf
dW5wcmVwYXJlKGlteDZfcGNpZS0+cGNpZV9idXMpOw0KPiA+PiBlcnJfcGNpZV9idXM6DQo+ID4+
IEBAIC0zMTEsNiArMzUxLDI2IEBAIGVycl9wY2llX3BoeToNCj4gPj4gc3RhdGljIHZvaWQgaW14
Nl9wY2llX2luaXRfcGh5KHN0cnVjdCBwY2llX3BvcnQgKnBwKSB7DQo+ID4+ICAgIHN0cnVjdCBp
bXg2X3BjaWUgKmlteDZfcGNpZSA9IHRvX2lteDZfcGNpZShwcCk7DQo+ID4+ICsgICAgaW50IHJl
dDsNCj4gPj4gKw0KPiA+PiArICAgIC8qIFBvd2VyIHVwIHRoZSBzZXBhcmF0ZSBkb21haW4gYXZh
aWxhYmxlIG9uIGkuTVg2U1ggKi8NCj4gPj4gKyAgICBpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9w
Y2llKSkgew0KPiA+PiArICAgICAgICAvKiBGb3JjZSBQQ0llIFBIWSByZXNldCAqLw0KPiA+PiAr
ICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENf
R1BSNSwNCj4gPj4gKyAgICAgICAgICAgICAgICBJTVg2U1hfR1BSNV9QQ0lFX0JUTlJTVCwNCj4g
Pj4gKyAgICAgICAgICAgICAgICBJTVg2U1hfR1BSNV9QQ0lFX0JUTlJTVCk7DQo+ID4+ICsNCj4g
Pj4gKyAgICAgICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+Z3BjX2lwc19yZWcsIEdQ
Q19DTlRSLA0KPiA+PiArICAgICAgICAgICAgICAgIEdQQ19DTlRSX1BDSUVfUEhZX1BVUF9SRVEs
DQo+ID4+ICsgICAgICAgICAgICAgICAgR1BDX0NOVFJfUENJRV9QSFlfUFVQX1JFUSk7DQo+ID4+
ICsgICAgICAgIHJlZ3VsYXRvcl9zZXRfdm9sdGFnZShpbXg2X3BjaWUtPnBjaWVfcmVndWxhdG9y
LA0KPiA+PiArICAgICAgICAgICAgICAgIDExMDAwMDAsIDExMDAwMDApOw0KPiA+PiArICAgICAg
ICByZXQgPSByZWd1bGF0b3JfZW5hYmxlKGlteDZfcGNpZS0+cGNpZV9yZWd1bGF0b3IpOw0KPiA+
PiArICAgICAgICBpZiAocmV0KQ0KPiA+PiArICAgICAgICAgICAgZGV2X2luZm8ocHAtPmRldiwg
ImZhaWxlZCB0byBlbmFibGUgcGNpZSByZWd1bGF0b3IuXG4iKTsNCj4gPj4gKyAgICAgICAgcmVn
bWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+
PiArICAgICAgICAgICAgICAgIElNWDZTWF9HUFIxMl9SWF9FUV9NQVNLLCBJTVg2U1hfR1BSMTJf
UlhfRVFfMik7DQo+ID4+ICsgICAgfQ0KPiA+Pg0KPiA+PiAgICByZWdtYXBfdXBkYXRlX2JpdHMo
aW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4+ICAgICAgICAgICAgSU1Y
NlFfR1BSMTJfUENJRV9DVExfMiwgMCA8PCAxMCk7IEBAIC0zMTksNyArMzc5LDcgQEANCj4gPj4g
c3RhdGljIHZvaWQgaW14Nl9wY2llX2luaXRfcGh5KHN0cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+
PiAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BS
MTIsDQo+ID4+ICAgICAgICAgICAgSU1YNlFfR1BSMTJfREVWSUNFX1RZUEUsIFBDSV9FWFBfVFlQ
RV9ST09UX1BPUlQgPDwgMTIpOw0KPiA+PiAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2ll
LT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4+IC0gICAgICAgICAgICBJTVg2UV9HUFIx
Ml9MT1NfTEVWRUwsIDkgPDwgNCk7DQo+ID4+ICsgICAgICAgICAgICBJTVg2UV9HUFIxMl9MT1Nf
TEVWRUwsIElNWDZRX0dQUjEyX0xPU19MRVZFTF85KTsNCj4gPj4NCj4gPj4gICAgcmVnbWFwX3Vw
ZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjgsDQo+ID4+ICAgICAg
ICAgICAgSU1YNlFfR1BSOF9UWF9ERUVNUEhfR0VOMSwgMCA8PCAwKTsgQEAgLTM3Nyw3ICs0Mzcs
OCBAQA0KPiA+PiBzdGF0aWMgaW50IGlteDZfcGNpZV9zdGFydF9saW5rKHN0cnVjdCBwY2llX3Bv
cnQgKnBwKQ0KPiA+Pg0KPiA+PiAgICAvKiBTdGFydCBMVFNTTS4gKi8NCj4gPj4gICAgcmVnbWFw
X3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+PiAt
ICAgICAgICAgICAgSU1YNlFfR1BSMTJfUENJRV9DVExfMiwgMSA8PCAxMCk7DQo+ID4+ICsgICAg
ICAgICAgICBJTVg2UV9HUFIxMl9QQ0lFX0NUTF8yLA0KPiA+PiArICAgICAgICAgICAgSU1YNlFf
R1BSMTJfUENJRV9DVExfMik7DQo+ID4+DQo+ID4+ICAgIHJldCA9IGlteDZfcGNpZV93YWl0X2Zv
cl9saW5rKHBwKTsNCj4gPj4gICAgaWYgKHJldCkNCj4gPj4gQEAgLTU1Myw5ICs2MTQsNTAgQEAg
c3RhdGljIGludCBfX2luaXQgaW14Nl9hZGRfcGNpZV9wb3J0KHN0cnVjdCBwY2llX3BvcnQNCj4g
KnBwLA0KPiA+PiAgICByZXR1cm4gMDsNCj4gPj4gfQ0KPiA+Pg0KPiA+PiArI2lmZGVmIENPTkZJ
R19QTV9TTEVFUA0KPiA+PiArc3RhdGljIGludCBwY2lfaW14X3N1c3BlbmQodm9pZCkNCj4gPj4g
K3sNCj4gPj4gKyAgICBpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9wY2llKSkgew0KPiA+PiArICAg
ICAgICAvKiBQTV9UVVJOX09GRiAqLw0KPiA+PiArICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMo
aW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4+ICsgICAgICAgICAgICAg
ICAgSU1YNlNYX0dQUjEyX1BDSUVfUE1fVFVSTl9PRkYsDQo+ID4+ICsgICAgICAgICAgICAgICAg
SU1YNlNYX0dQUjEyX1BDSUVfUE1fVFVSTl9PRkYpOw0KPiA+PiArICAgICAgICB1ZGVsYXkoMTAp
Ow0KPiA+PiArICAgICAgICByZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3By
LCBJT01VWENfR1BSMTIsDQo+ID4+ICsgICAgICAgICAgICAgICAgSU1YNlNYX0dQUjEyX1BDSUVf
UE1fVFVSTl9PRkYsIDApOw0KPiA+PiArICAgIH0NCj4gPj4gKw0KPiA+PiArICAgIHJldHVybiAw
Ow0KPiA+PiArfQ0KPiA+PiArDQo+ID4+ICtzdGF0aWMgdm9pZCBwY2lfaW14X3Jlc3VtZSh2b2lk
KQ0KPiA+PiArew0KPiA+PiArICAgIHN0cnVjdCBwY2llX3BvcnQgKnBwID0gJmlteDZfcGNpZS0+
cHA7DQo+ID4+ICsNCj4gPj4gKyAgICBpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9wY2llKSkgew0K
PiA+PiArICAgICAgICAvKiBSZXNldCBpTVg2U1ggUENJZSAqLw0KPiA+PiArICAgICAgICByZWdt
YXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSNSwNCj4gPj4g
KyAgICAgICAgICAgICAgICBJTVg2U1hfR1BSNV9QQ0lFX1BFUlNULCBJTVg2U1hfR1BSNV9QQ0lF
X1BFUlNUKTsNCj4gPj4gKyAgICAgICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9t
dXhjX2dwciwgSU9NVVhDX0dQUjUsDQo+ID4+ICsgICAgICAgICAgICAgICAgSU1YNlNYX0dQUjVf
UENJRV9QRVJTVCwgMCk7DQo+ID4+ICsgICAgICAgIC8qDQo+ID4+ICsgICAgICAgICAqIGNvbnRy
b2xsZXIgbWF5YmUgdHVybiBvZmYsIHJlLWNvbmZpZ3VyZSBhZ2Fpbg0KPiA+PiArICAgICAgICAg
Ki8NCj4gPj4gKyAgICAgICAgZHdfcGNpZV9zZXR1cF9yYyhwcCk7DQo+ID4+ICsNCj4gPj4gKyAg
ICAgICAgaWYgKElTX0VOQUJMRUQoQ09ORklHX1BDSV9NU0kpKQ0KPiA+PiArICAgICAgICAgICAg
ZHdfcGNpZV9tc2lfY2ZnX3Jlc3RvcmUocHApOw0KPiA+PiArICAgIH0NCj4gPj4gK30NCj4gPj4g
Kw0KPiA+PiArc3RhdGljIHN0cnVjdCBzeXNjb3JlX29wcyBwY2lfaW14X3N5c2NvcmVfb3BzID0g
ew0KPiA+PiArICAgIC5zdXNwZW5kID0gcGNpX2lteF9zdXNwZW5kLA0KPiA+PiArICAgIC5yZXN1
bWUgPSBwY2lfaW14X3Jlc3VtZSwNCj4gPj4gK307DQo+ID4+ICsjZW5kaWYNCj4gPj4gKw0KPiA+
PiBzdGF0aWMgaW50IF9faW5pdCBpbXg2X3BjaWVfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj
ZSAqcGRldikgew0KPiA+PiAtICAgIHN0cnVjdCBpbXg2X3BjaWUgKmlteDZfcGNpZTsNCj4gPj4g
ICAgc3RydWN0IHBjaWVfcG9ydCAqcHA7DQo+ID4+ICAgIHN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAg
PSBwZGV2LT5kZXYub2Zfbm9kZTsNCj4gPj4gICAgc3RydWN0IHJlc291cmNlICpkYmlfYmFzZTsN
Cj4gPj4gQEAgLTU3Miw3ICs2NzQsNyBAQCBzdGF0aWMgaW50IF9faW5pdCBpbXg2X3BjaWVfcHJv
YmUoc3RydWN0DQo+IHBsYXRmb3JtX2RldmljZSAqcGRldikNCj4gPj4gICAgaG9va19mYXVsdF9j
b2RlKDE2ICsgNiwgaW14NnFfcGNpZV9hYm9ydF9oYW5kbGVyLCBTSUdCVVMsIDAsDQo+ID4+ICAg
ICAgICAiaW1wcmVjaXNlIGV4dGVybmFsIGFib3J0Iik7DQo+ID4+DQo+ID4+IC0gICAgZGJpX2Jh
c2UgPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOw0KPiA+
PiArICAgIGRiaV9iYXNlID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlX2J5bmFtZShwZGV2LCBJT1JF
U09VUkNFX01FTSwNCj4gPj4gKyAicmNfZGJpIik7DQo+ID4NCj4gPiBZb3UgYXJlIGJyZWFraW5n
IG9sZCBkZXZpY2V0cmVlcyBoZXJlLiAicmNfZGJpIiBpc24ndCBhIGRvY3VtZW50ZWQNCj4gPiBu
YW1lIGFuZCBpc24ndCBhdmFpbGFibGUgb24gb2xkIERUcy4gQmVzaWRlcyB0aGUgaW14NnEgRFQg
dXNlcyBqdXN0DQo+ID4gImRiaSIgYXMgdGhlIG5hbWUuIERvbid0IHRvdWNoIHRoaXMgY29kZSwg
aXQgZG9lcyBleGFjdGx5IHRoZSByaWdodA0KPiA+IHRoaW5nIGJ5IGdyYWJiaW5nIHRoZSBmaXJz
dCByZWcgcmVzb3VyY2UuDQo+IA0KPiBPaywgY2hhbmdlcyB3b3VsZCBiZSByZW1vdmVkLg0KPiAN
Cj4gPg0KPiA+PiAgICBwcC0+ZGJpX2Jhc2UgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoJnBkZXYt
PmRldiwgZGJpX2Jhc2UpOw0KPiA+PiAgICBpZiAoSVNfRVJSKHBwLT5kYmlfYmFzZSkpDQo+ID4+
ICAgICAgICByZXR1cm4gUFRSX0VSUihwcC0+ZGJpX2Jhc2UpOw0KPiA+PiBAQCAtNjEwLDkgKzcx
MiwyOCBAQCBzdGF0aWMgaW50IF9faW5pdCBpbXg2X3BjaWVfcHJvYmUoc3RydWN0DQo+IHBsYXRm
b3JtX2RldmljZSAqcGRldikNCj4gPj4gICAgICAgIHJldHVybiBQVFJfRVJSKGlteDZfcGNpZS0+
cGNpZSk7DQo+ID4+ICAgIH0NCj4gPj4NCj4gPj4gLSAgICAvKiBHcmFiIEdQUiBjb25maWcgcmVn
aXN0ZXIgcmFuZ2UgKi8NCj4gPj4gLSAgICBpbXg2X3BjaWUtPmlvbXV4Y19ncHIgPQ0KPiA+PiAt
ICAgICAgICAgc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZSgiZnNsLGlteDZxLWlv
bXV4Yy1ncHIiKTsNCj4gPj4gKyAgICBpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9wY2llKSkgew0K
PiA+PiArICAgICAgICBpbXg2X3BjaWUtPnBjaWVfaW5ib3VuZF9heGkgPSBkZXZtX2Nsa19nZXQo
JnBkZXYtPmRldiwNCj4gPj4gKyAgICAgICAgICAgICAgICAicGNpZV9pbmJvdW5kX2F4aSIpOw0K
PiA+PiArICAgICAgICBpZiAoSVNfRVJSKGlteDZfcGNpZS0+cGNpZV9pbmJvdW5kX2F4aSkpIHsN
Cj4gPj4gKyAgICAgICAgICAgIGRldl9lcnIoJnBkZXYtPmRldiwNCj4gPj4gKyAgICAgICAgICAg
ICAgICAicGNpZSBjbG9jayBzb3VyY2UgbWlzc2luZyBvciBpbnZhbGlkXG4iKTsNCj4gPj4gKyAg
ICAgICAgICAgIHJldHVybiBQVFJfRVJSKGlteDZfcGNpZS0+cGNpZV9pbmJvdW5kX2F4aSk7DQo+
ID4+ICsgICAgICAgIH0NCj4gPj4gKw0KPiA+PiArICAgICAgICBpbXg2X3BjaWUtPnBjaWVfcmVn
dWxhdG9yID0gZGV2bV9yZWd1bGF0b3JfZ2V0KHBwLT5kZXYsDQo+ID4+ICsgICAgICAgICAgICAg
ICAgInBjaWUtcGh5Iik7DQo+ID4+ICsNCj4gPj4gKyAgICAgICAgaW14Nl9wY2llLT5pb211eGNf
Z3ByID0NCj4gPj4gKyAgICAgICAgICAgICBzeXNjb25fcmVnbWFwX2xvb2t1cF9ieV9jb21wYXRp
YmxlDQo+ID4+ICsgICAgICAgICAgICAgKCJmc2wsaW14NnN4LWlvbXV4Yy1ncHIiKTsNCj4gPj4g
KyAgICAgICAgaW14Nl9wY2llLT5ncGNfaXBzX3JlZyA9DQo+ID4+ICsgICAgICAgICAgICAgc3lz
Y29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZSgiZnNsLGlteDZzeC1ncGMiKTsNCj4gPj4g
KyAgICB9IGVsc2Ugew0KPiA+PiArICAgICAgICBpbXg2X3BjaWUtPmlvbXV4Y19ncHIgPQ0KPiA+
PiArICAgICAgICAgICAgc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZQ0KPiA+PiAr
ICAgICAgICAgICAgKCJmc2wsaW14NnEtaW9tdXhjLWdwciIpOw0KPiA+PiArICAgIH0NCj4gPj4g
ICAgaWYgKElTX0VSUihpbXg2X3BjaWUtPmlvbXV4Y19ncHIpKSB7DQo+ID4+ICAgICAgICBkZXZf
ZXJyKCZwZGV2LT5kZXYsICJ1bmFibGUgdG8gZmluZCBpb211eGMgcmVnaXN0ZXJzXG4iKTsNCj4g
Pj4gICAgICAgIHJldHVybiBQVFJfRVJSKGlteDZfcGNpZS0+aW9tdXhjX2dwcik7IEBAIC02MjMs
NiArNzQ0LDkgQEANCj4gPj4gc3RhdGljIGludCBfX2luaXQgaW14Nl9wY2llX3Byb2JlKHN0cnVj
dCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4+ICAgICAgICByZXR1cm4gcmV0Ow0KPiA+Pg0K
PiA+PiAgICBwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBpbXg2X3BjaWUpOw0KPiA+PiArI2lm
ZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+PiArICAgIHJlZ2lzdGVyX3N5c2NvcmVfb3BzKCZwY2lf
aW14X3N5c2NvcmVfb3BzKTsNCj4gPj4gKyNlbmRpZg0KPiA+PiAgICByZXR1cm4gMDsNCj4gPj4g
fQ0KPiA+Pg0KPiA+PiBAQCAtNjM2LDYgKzc2MCw3IEBAIHN0YXRpYyB2b2lkIGlteDZfcGNpZV9z
aHV0ZG93bihzdHJ1Y3QNCj4gPj4gcGxhdGZvcm1fZGV2aWNlICpwZGV2KQ0KPiA+Pg0KPiA+PiBz
dGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBpbXg2X3BjaWVfb2ZfbWF0Y2hbXSA9IHsN
Cj4gPj4gICAgeyAuY29tcGF0aWJsZSA9ICJmc2wsaW14NnEtcGNpZSIsIH0sDQo+ID4+ICsgICAg
eyAuY29tcGF0aWJsZSA9ICJmc2wsaW14NnN4LXBjaWUiLCB9LA0KPiA+PiAgICB7fSwNCj4gPj4g
fTsNCj4gPj4gTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgaW14Nl9wY2llX29mX21hdGNoKTsNCj4g
Pg0KPiA+IC0tDQo+ID4gUGVuZ3V0cm9uaXggZS5LLiAgICAgICAgICAgICB8IEx1Y2FzIFN0YWNo
ICAgICAgICAgICAgICAgICB8DQo+ID4gSW5kdXN0cmlhbCBMaW51eCBTb2x1dGlvbnMgICB8IGh0
dHA6Ly93d3cucGVuZ3V0cm9uaXguZGUvICB8DQo+ID4NCj4gPg0KPiBCZXN0IHJlZ2FyZHMNCj4g
UmljaGFyZA0K
--
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 mbox

Patch

diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index eac96fb..c74e87d 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -22,8 +22,10 @@ 
 #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>
 
@@ -35,11 +37,15 @@  struct imx6_pcie {
 	int			reset_gpio;
 	struct clk		*pcie_bus;
 	struct clk		*pcie_phy;
+	struct clk		*pcie_inbound_axi;
 	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 +83,18 @@  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)
 
+/* GPC PCIE PHY bit definitions */
+#define GPC_CNTR			0
+#define GPC_CNTR_PCIE_PHY_PUP_REQ	BIT(7)
+
+static inline bool is_imx6sx_pcie(struct imx6_pcie *imx6_pcie)
+{
+	struct pcie_port *pp = &imx6_pcie->pp;
+	struct device_node *np = pp->dev->of_node;
+
+	return of_device_is_compatible(np, "fsl,imx6sx-pcie");
+}
+
 static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
 {
 	u32 val;
@@ -275,18 +293,29 @@  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);
-	/*
-	 * the async reset input need ref clock to sync internally,
-	 * when the ref clock comes after reset, internal synced
-	 * reset time is too short , cannot meet the requirement.
-	 * add one ~10us delay here.
-	 */
-	udelay(10);
-	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
-			IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+	if (is_imx6sx_pcie(imx6_pcie)) {
+		ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
+		if (ret) {
+			dev_err(pp->dev, "unable to enable pcie clock\n");
+			goto err_inbound_axi;
+		}
+
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+				IMX6SX_GPR12_PCIE_TEST_PD, 0);
+	} else {
+		/* power up core phy and enable ref clock */
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+				IMX6Q_GPR1_PCIE_TEST_PD, 0);
+		/*
+		 * the async reset input need ref clock to sync internally,
+		 * when the ref clock comes after reset, internal synced
+		 * reset time is too short , cannot meet the requirement.
+		 * add one ~10us delay here.
+		 */
+		udelay(10);
+		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);
@@ -297,8 +326,19 @@  static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
 		msleep(100);
 		gpio_set_value(imx6_pcie->reset_gpio, 1);
 	}
+
+	/*
+	 * Release the PCIe PHY reset here, that we have set in
+	 * imx6_pcie_init_phy() now
+	 */
+	if (is_imx6sx_pcie(imx6_pcie))
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+				IMX6SX_GPR5_PCIE_BTNRST, 0);
+
 	return 0;
 
+err_inbound_axi:
+	clk_disable_unprepare(imx6_pcie->pcie);
 err_pcie:
 	clk_disable_unprepare(imx6_pcie->pcie_bus);
 err_pcie_bus:
@@ -311,6 +351,26 @@  err_pcie_phy:
 static void imx6_pcie_init_phy(struct pcie_port *pp)
 {
 	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+	int ret;
+
+	/* Power up the separate domain available on i.MX6SX */
+	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, GPC_CNTR,
+				GPC_CNTR_PCIE_PHY_PUP_REQ,
+				GPC_CNTR_PCIE_PHY_PUP_REQ);
+		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);
@@ -319,7 +379,7 @@  static void imx6_pcie_init_phy(struct pcie_port *pp)
 	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);
@@ -377,7 +437,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)
@@ -553,9 +614,50 @@  static int __init imx6_add_pcie_port(struct pcie_port *pp,
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pci_imx_suspend(void)
+{
+	if (is_imx6sx_pcie(imx6_pcie)) {
+		/* PM_TURN_OFF */
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+				IMX6SX_GPR12_PCIE_PM_TURN_OFF,
+				IMX6SX_GPR12_PCIE_PM_TURN_OFF);
+		udelay(10);
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+				IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
+	}
+
+	return 0;
+}
+
+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,
+				IMX6SX_GPR5_PCIE_PERST, IMX6SX_GPR5_PCIE_PERST);
+		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
+				IMX6SX_GPR5_PCIE_PERST, 0);
+		/*
+		 * controller maybe turn off, re-configure again
+		 */
+		dw_pcie_setup_rc(pp);
+
+		if (IS_ENABLED(CONFIG_PCI_MSI))
+			dw_pcie_msi_cfg_restore(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;
 	struct device_node *np = pdev->dev.of_node;
 	struct resource *dbi_base;
@@ -572,7 +674,7 @@  static int __init imx6_pcie_probe(struct platform_device *pdev)
 	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
 		"imprecise external abort");
 
-	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
 	pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
 	if (IS_ERR(pp->dbi_base))
 		return PTR_ERR(pp->dbi_base);
@@ -610,9 +712,28 @@  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_inbound_axi = devm_clk_get(&pdev->dev,
+				"pcie_inbound_axi");
+		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
+			dev_err(&pdev->dev,
+				"pcie clock source missing or invalid\n");
+			return PTR_ERR(imx6_pcie->pcie_inbound_axi);
+		}
+
+		imx6_pcie->pcie_regulator = devm_regulator_get(pp->dev,
+				"pcie-phy");
+
+		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);
@@ -623,6 +744,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;
 }
 
@@ -636,6 +760,7 @@  static void imx6_pcie_shutdown(struct platform_device *pdev)
 
 static const struct of_device_id imx6_pcie_of_match[] = {
 	{ .compatible = "fsl,imx6q-pcie", },
+	{ .compatible = "fsl,imx6sx-pcie", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);