Message ID | 1411966997-27118-8-git-send-email-r65037@freescale.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Bjorn Helgaas |
Headers | show |
Am Montag, den 29.09.2014, 13:03 +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 for imx6sx pcie. > > Signed-off-by: Richard Zhu <r65037@freescale.com> > --- > drivers/pci/host/pci-imx6.c | 162 +++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 144 insertions(+), 18 deletions(-) > > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c > index eac96fb..be953aa 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> Why do you need this include? > +#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> > > @@ -35,11 +39,15 @@ struct imx6_pcie { > int reset_gpio; > struct clk *pcie_bus; > struct clk *pcie_phy; > + struct clk *disp_axi; This needs a more descriptive name, just like the binding. > 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 +85,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 +295,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->disp_axi); > + if (ret) { > + dev_err(pp->dev, "unable to enable pcie clock\n"); > + goto err_disp; > + } > + > + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, > + IMX6SX_GPR12_PCIE_TEST_PD, 0 << 30); > + } 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); > + /* > + * 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 +328,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 << 19); > + > return 0; > > +err_disp: > + clk_disable_unprepare(imx6_pcie->pcie); > err_pcie: > clk_disable_unprepare(imx6_pcie->pcie_bus); > err_pcie_bus: > @@ -311,6 +353,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 +381,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 +439,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 +616,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 << 16); Just use 0 as the last argument. Those shifts aren't adding anything and I would like to get rid of them long term, so please don't introduce new ones. > + } > + > + 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 << 18); > + /* > + * 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; > @@ -610,9 +714,27 @@ 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->disp_axi = devm_clk_get(&pdev->dev, "disp_axi"); > + if (IS_ERR(imx6_pcie->disp_axi)) { > + dev_err(&pdev->dev, > + "pcie clock source missing or invalid\n"); > + return PTR_ERR(imx6_pcie->disp_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 +745,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 +761,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);
SGkgTHVjYXM6DQpUaGFua3MgZm9yIHlvdXIgcmV2aWV3IGNvbW1lbnRzLg0KDQo+IC0tLS0tT3Jp Z2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IEx1Y2FzIFN0YWNoIFttYWlsdG86bC5zdGFjaEBw ZW5ndXRyb25peC5kZV0NCj4gU2VudDogTW9uZGF5LCBTZXB0ZW1iZXIgMjksIDIwMTQgNjoxOSBQ TQ0KPiBUbzogWmh1IFJpY2hhcmQtUjY1MDM3DQo+IENjOiBsaW51eC1wY2ktb3duZXJAdmdlci5r ZXJuZWwub3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOyBHdW8gU2hhd24tDQo+IFI2NTA3 MzsgZmVzdGV2YW1AZ21haWwuY29tOyB0aGFydmV5QGdhdGV3b3Jrcy5jb20NCj4gU3ViamVjdDog UmU6IFtQQVRDSCB2MyA3LzldIFBDSTogaW14NjogYWRkIGlteDZzeCBwY2llIHN1cHBvcnQNCj4g DQo+IEFtIE1vbnRhZywgZGVuIDI5LjA5LjIwMTQsIDEzOjAzICswODAwIHNjaHJpZWIgUmljaGFy ZCBaaHU6DQo+ID4gLSBpbXg2c3ggcGNpZSBoYXMgaXRzIG93biBzdGFuZGFsb25lIHBjaWUgcG93 ZXIgc3VwcGx5Lg0KPiA+IEluIG9yZGVyIHRvIHR1cm4gb24gdGhlIGlteDZzeCBwY2llIHBvd2Vy IGR1cmluZyBpbml0aWFsaXphdGlvbi4gQWRkDQo+ID4gdGhlIHBjaWUgcmVndWxhdG9yIGFuZCB0 aGUgZ3BjIHJlZ21hcCBpbnRvIHRoZSBpbXg2c3ggcGNpZSBzdHJ1Y3R1cmUuDQo+ID4gLSBpbXg2 c3ggcGNpZSBoYXMgdGhlIG5ldyBhZGRlZCByZXNldCBtZWNoYW5pc20sIGFkZCB0aGUgcmVzZXQN Cj4gPiBvcGVyYXRpb25zIGludG8gdGhlIGluaXRpYWxpemF0aW9uLg0KPiA+IC0gUmVnaXN0ZXIg b25lIFBNIGNhbGwtYmFjaywgZW50ZXIvZXhpdCBMMiBzdGF0ZSBvZiB0aGUgQVNQTSBkdXJpbmcN Cj4gPiBzeXN0ZW0gc3VzcGVuZC9yZXN1bWUuDQo+ID4gLSBkaXNwX2F4aSBjbG9jayBpcyByZXF1 aXJlZCBieSBwY2llIGluYm91bmQgYXhpIHBvcnQgYWN0dWFsbHkuDQo+ID4gQWRkIG9uZSBtb3Jl IGNsb2NrIGZvciBpbXg2c3ggcGNpZS4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IFJpY2hhcmQg Wmh1IDxyNjUwMzdAZnJlZXNjYWxlLmNvbT4NCj4gPiAtLS0NCj4gPiAgZHJpdmVycy9wY2kvaG9z dC9wY2ktaW14Ni5jIHwgMTYyDQo+ID4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrLS0tLS0NCj4gPiAgMSBmaWxlIGNoYW5nZWQsIDE0NCBpbnNlcnRpb25zKCspLCAxOCBk ZWxldGlvbnMoLSkNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3BjaS9ob3N0L3BjaS1p bXg2LmMgYi9kcml2ZXJzL3BjaS9ob3N0L3BjaS1pbXg2LmMNCj4gPiBpbmRleCBlYWM5NmZiLi5i ZTk1M2FhIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KPiA+ ICsrKyBiL2RyaXZlcnMvcGNpL2hvc3QvcGNpLWlteDYuYw0KPiA+IEBAIC0xOCwxMiArMTgsMTYg QEANCj4gPiAgI2luY2x1ZGUgPGxpbnV4L21mZC9zeXNjb24uaD4NCj4gPiAgI2luY2x1ZGUgPGxp bnV4L21mZC9zeXNjb24vaW14NnEtaW9tdXhjLWdwci5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZl9hZGRyZXNzLmg+DQo+IA0KPiBXaHkg ZG8geW91IG5lZWQgdGhpcyBpbmNsdWRlPw0KW1JpY2hhcmRdSXQncyBub3QgcmVxdWlyZWQgYW55 bW9yZSwgd291bGQgYmUgcmVtb3ZlZCBsYXRlci4NCj4gDQo+ID4gKyNpbmNsdWRlIDxsaW51eC9v Zl9kZXZpY2UuaD4NCj4gPiAgI2luY2x1ZGUgPGxpbnV4L29mX2dwaW8uaD4NCj4gPiAgI2luY2x1 ZGUgPGxpbnV4L3BjaS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+ DQo+ID4gICNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3Jl Z3VsYXRvci9jb25zdW1lci5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvcmVzb3VyY2UuaD4NCj4g PiAgI2luY2x1ZGUgPGxpbnV4L3NpZ25hbC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvc3lzY29y ZV9vcHMuaD4NCj4gPiAgI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+DQo+ID4gICNpbmNsdWRlIDxs aW51eC9pbnRlcnJ1cHQuaD4NCj4gPg0KPiA+IEBAIC0zNSwxMSArMzksMTUgQEAgc3RydWN0IGlt eDZfcGNpZSB7DQo+ID4gIAlpbnQJCQlyZXNldF9ncGlvOw0KPiA+ICAJc3RydWN0IGNsawkJKnBj aWVfYnVzOw0KPiA+ICAJc3RydWN0IGNsawkJKnBjaWVfcGh5Ow0KPiA+ICsJc3RydWN0IGNsawkJ KmRpc3BfYXhpOw0KPiANCj4gVGhpcyBuZWVkcyBhIG1vcmUgZGVzY3JpcHRpdmUgbmFtZSwganVz dCBsaWtlIHRoZSBiaW5kaW5nLg0KW1JpY2hhcmRdaG93IGFib3V0IGxpa2UgInBjaWVfYXhpX2lu Ym91bmQiPw0KPiANCj4gPiAgCXN0cnVjdCBjbGsJCSpwY2llOw0KPiA+ICAJc3RydWN0IHBjaWVf cG9ydAlwcDsNCj4gPiAgCXN0cnVjdCByZWdtYXAJCSppb211eGNfZ3ByOw0KPiA+ICsJc3RydWN0 IHJlZ21hcAkJKmdwY19pcHNfcmVnOw0KPiA+ICsJc3RydWN0IHJlZ3VsYXRvcgkqcGNpZV9yZWd1 bGF0b3I7DQo+ID4gIAl2b2lkIF9faW9tZW0JCSptZW1fYmFzZTsNCj4gPiAgfTsNCj4gPiArc3Rh dGljIHN0cnVjdCBpbXg2X3BjaWUgKmlteDZfcGNpZTsNCj4gPg0KPiA+ICAvKiBQQ0llIFJvb3Qg Q29tcGxleCByZWdpc3RlcnMgKG1lbW9yeS1tYXBwZWQpICovDQo+ID4gICNkZWZpbmUgUENJRV9S Q19MQ1IJCQkJMHg3Yw0KPiA+IEBAIC03Nyw2ICs4NSwxOCBAQCBzdHJ1Y3QgaW14Nl9wY2llIHsN Cj4gPiAgI2RlZmluZSBQSFlfUlhfT1ZSRF9JTl9MT19SWF9EQVRBX0VOICgxIDw8IDUpICAjZGVm aW5lDQo+ID4gUEhZX1JYX09WUkRfSU5fTE9fUlhfUExMX0VOICgxIDw8IDMpDQo+ID4NCj4gPiAr LyogR1BDIFBDSUUgUEhZIGJpdCBkZWZpbml0aW9ucyAqLw0KPiA+ICsjZGVmaW5lIEdQQ19DTlRS CQkJMA0KPiA+ICsjZGVmaW5lIEdQQ19DTlRSX1BDSUVfUEhZX1BVUF9SRVEJQklUKDcpDQo+ID4g Kw0KPiA+ICtzdGF0aWMgaW5saW5lIGJvb2wgaXNfaW14NnN4X3BjaWUoc3RydWN0IGlteDZfcGNp ZSAqaW14Nl9wY2llKSB7DQo+ID4gKwlzdHJ1Y3QgcGNpZV9wb3J0ICpwcCA9ICZpbXg2X3BjaWUt PnBwOw0KPiA+ICsJc3RydWN0IGRldmljZV9ub2RlICpucCA9IHBwLT5kZXYtPm9mX25vZGU7DQo+ ID4gKw0KPiA+ICsJcmV0dXJuIG9mX2RldmljZV9pc19jb21wYXRpYmxlKG5wLCAiZnNsLGlteDZz eC1wY2llIik7IH0NCj4gPiArDQo+ID4gIHN0YXRpYyBpbnQgcGNpZV9waHlfcG9sbF9hY2sodm9p ZCBfX2lvbWVtICpkYmlfYmFzZSwgaW50IGV4cF92YWwpICB7DQo+ID4gIAl1MzIgdmFsOw0KPiA+ IEBAIC0yNzUsMTggKzI5NSwyOSBAQCBzdGF0aWMgaW50IGlteDZfcGNpZV9kZWFzc2VydF9jb3Jl X3Jlc2V0KHN0cnVjdA0KPiBwY2llX3BvcnQgKnBwKQ0KPiA+ICAJCWdvdG8gZXJyX3BjaWU7DQo+ ID4gIAl9DQo+ID4NCj4gPiAtCS8qIHBvd2VyIHVwIGNvcmUgcGh5IGFuZCBlbmFibGUgcmVmIGNs b2NrICovDQo+ID4gLQlyZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJ T01VWENfR1BSMSwNCj4gPiAtCQkJSU1YNlFfR1BSMV9QQ0lFX1RFU1RfUEQsIDAgPDwgMTgpOw0K PiA+IC0JLyoNCj4gPiAtCSAqIHRoZSBhc3luYyByZXNldCBpbnB1dCBuZWVkIHJlZiBjbG9jayB0 byBzeW5jIGludGVybmFsbHksDQo+ID4gLQkgKiB3aGVuIHRoZSByZWYgY2xvY2sgY29tZXMgYWZ0 ZXIgcmVzZXQsIGludGVybmFsIHN5bmNlZA0KPiA+IC0JICogcmVzZXQgdGltZSBpcyB0b28gc2hv cnQgLCBjYW5ub3QgbWVldCB0aGUgcmVxdWlyZW1lbnQuDQo+ID4gLQkgKiBhZGQgb25lIH4xMHVz IGRlbGF5IGhlcmUuDQo+ID4gLQkgKi8NCj4gPiAtCXVkZWxheSgxMCk7DQo+ID4gLQlyZWdtYXBf dXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMSwNCj4gPiAtCQkJ SU1YNlFfR1BSMV9QQ0lFX1JFRl9DTEtfRU4sIDEgPDwgMTYpOw0KPiA+ICsJaWYgKGlzX2lteDZz eF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoaW14 Nl9wY2llLT5kaXNwX2F4aSk7DQo+ID4gKwkJaWYgKHJldCkgew0KPiA+ICsJCQlkZXZfZXJyKHBw LT5kZXYsICJ1bmFibGUgdG8gZW5hYmxlIHBjaWUgY2xvY2tcbiIpOw0KPiA+ICsJCQlnb3RvIGVy cl9kaXNwOw0KPiA+ICsJCX0NCj4gPiArDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZf cGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+ICsJCQkJSU1YNlNYX0dQUjEyX1BD SUVfVEVTVF9QRCwgMCA8PCAzMCk7DQo+ID4gKwl9IGVsc2Ugew0KPiA+ICsJCS8qIHBvd2VyIHVw IGNvcmUgcGh5IGFuZCBlbmFibGUgcmVmIGNsb2NrICovDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9i aXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEsDQo+ID4gKwkJCQlJTVg2UV9H UFIxX1BDSUVfVEVTVF9QRCwgMCA8PCAxOCk7DQo+ID4gKwkJLyoNCj4gPiArCQkgKiB0aGUgYXN5 bmMgcmVzZXQgaW5wdXQgbmVlZCByZWYgY2xvY2sgdG8gc3luYyBpbnRlcm5hbGx5LA0KPiA+ICsJ CSAqIHdoZW4gdGhlIHJlZiBjbG9jayBjb21lcyBhZnRlciByZXNldCwgaW50ZXJuYWwgc3luY2Vk DQo+ID4gKwkJICogcmVzZXQgdGltZSBpcyB0b28gc2hvcnQgLCBjYW5ub3QgbWVldCB0aGUgcmVx dWlyZW1lbnQuDQo+ID4gKwkJICogYWRkIG9uZSB+MTB1cyBkZWxheSBoZXJlLg0KPiA+ICsJCSAq Lw0KPiA+ICsJCXVkZWxheSgxMCk7DQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNp ZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEsDQo+ID4gKwkJCQlJTVg2UV9HUFIxX1BDSUVfUkVG X0NMS19FTiwgMSA8PCAxNik7DQo+ID4gKwl9DQo+ID4NCj4gPiAgCS8qIGFsbG93IHRoZSBjbG9j a3MgdG8gc3RhYmlsaXplICovDQo+ID4gIAl1c2xlZXBfcmFuZ2UoMjAwLCA1MDApOw0KPiA+IEBA IC0yOTcsOCArMzI4LDE5IEBAIHN0YXRpYyBpbnQgaW14Nl9wY2llX2RlYXNzZXJ0X2NvcmVfcmVz ZXQoc3RydWN0DQo+IHBjaWVfcG9ydCAqcHApDQo+ID4gIAkJbXNsZWVwKDEwMCk7DQo+ID4gIAkJ Z3Bpb19zZXRfdmFsdWUoaW14Nl9wY2llLT5yZXNldF9ncGlvLCAxKTsNCj4gPiAgCX0NCj4gPiAr DQo+ID4gKwkvKg0KPiA+ICsJICogUmVsZWFzZSB0aGUgUENJZSBQSFkgcmVzZXQgaGVyZSwgdGhh dCB3ZSBoYXZlIHNldCBpbg0KPiA+ICsJICogaW14Nl9wY2llX2luaXRfcGh5KCkgbm93DQo+ID4g KwkgKi8NCj4gPiArCWlmIChpc19pbXg2c3hfcGNpZShpbXg2X3BjaWUpKQ0KPiA+ICsJCXJlZ21h cF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFI1LA0KPiA+ICsJ CQkJSU1YNlNYX0dQUjVfUENJRV9CVE5SU1QsIDAgPDwgMTkpOw0KPiA+ICsNCj4gPiAgCXJldHVy biAwOw0KPiA+DQo+ID4gK2Vycl9kaXNwOg0KPiA+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGlt eDZfcGNpZS0+cGNpZSk7DQo+ID4gIGVycl9wY2llOg0KPiA+ICAJY2xrX2Rpc2FibGVfdW5wcmVw YXJlKGlteDZfcGNpZS0+cGNpZV9idXMpOw0KPiA+ICBlcnJfcGNpZV9idXM6DQo+ID4gQEAgLTMx MSw2ICszNTMsMjYgQEAgZXJyX3BjaWVfcGh5Og0KPiA+ICBzdGF0aWMgdm9pZCBpbXg2X3BjaWVf aW5pdF9waHkoc3RydWN0IHBjaWVfcG9ydCAqcHApICB7DQo+ID4gIAlzdHJ1Y3QgaW14Nl9wY2ll ICppbXg2X3BjaWUgPSB0b19pbXg2X3BjaWUocHApOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ ID4gKwkvKiBQb3dlciB1cCB0aGUgc2VwYXJhdGUgZG9tYWluIGF2YWlsYWJsZSBvbiBpLk1YNlNY ICovDQo+ID4gKwlpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9wY2llKSkgew0KPiA+ICsJCS8qIEZv cmNlIFBDSWUgUEhZIHJlc2V0ICovDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNp ZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjUsDQo+ID4gKwkJCQlJTVg2U1hfR1BSNV9QQ0lFX0JU TlJTVCwNCj4gPiArCQkJCUlNWDZTWF9HUFI1X1BDSUVfQlROUlNUKTsNCj4gPiArDQo+ID4gKwkJ cmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+Z3BjX2lwc19yZWcsIEdQQ19DTlRSLA0KPiA+ ICsJCQkJR1BDX0NOVFJfUENJRV9QSFlfUFVQX1JFUSwNCj4gPiArCQkJCUdQQ19DTlRSX1BDSUVf UEhZX1BVUF9SRVEpOw0KPiA+ICsJCXJlZ3VsYXRvcl9zZXRfdm9sdGFnZShpbXg2X3BjaWUtPnBj aWVfcmVndWxhdG9yLA0KPiA+ICsJCQkJMTEwMDAwMCwgMTEwMDAwMCk7DQo+ID4gKwkJcmV0ID0g cmVndWxhdG9yX2VuYWJsZShpbXg2X3BjaWUtPnBjaWVfcmVndWxhdG9yKTsNCj4gPiArCQlpZiAo cmV0KQ0KPiA+ICsJCQlkZXZfaW5mbyhwcC0+ZGV2LCAiZmFpbGVkIHRvIGVuYWJsZSBwY2llIHJl Z3VsYXRvci5cbiIpOw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4 Y19ncHIsIElPTVVYQ19HUFIxMiwNCj4gPiArCQkJCUlNWDZTWF9HUFIxMl9SWF9FUV9NQVNLLCBJ TVg2U1hfR1BSMTJfUlhfRVFfMik7DQo+ID4gKwl9DQo+ID4NCj4gPiAgCXJlZ21hcF91cGRhdGVf Yml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxMiwNCj4gPiAgCQkJSU1YNlFf R1BSMTJfUENJRV9DVExfMiwgMCA8PCAxMCk7DQo+ID4gQEAgLTMxOSw3ICszODEsNyBAQCBzdGF0 aWMgdm9pZCBpbXg2X3BjaWVfaW5pdF9waHkoc3RydWN0IHBjaWVfcG9ydCAqcHApDQo+ID4gIAly ZWdtYXBfdXBkYXRlX2JpdHMoaW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ ID4gIAkJCUlNWDZRX0dQUjEyX0RFVklDRV9UWVBFLCBQQ0lfRVhQX1RZUEVfUk9PVF9QT1JUIDw8 IDEyKTsNCj4gPiAgCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElP TVVYQ19HUFIxMiwNCj4gPiAtCQkJSU1YNlFfR1BSMTJfTE9TX0xFVkVMLCA5IDw8IDQpOw0KPiA+ ICsJCQlJTVg2UV9HUFIxMl9MT1NfTEVWRUwsIElNWDZRX0dQUjEyX0xPU19MRVZFTF85KTsNCj4g Pg0KPiA+ICAJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhD X0dQUjgsDQo+ID4gIAkJCUlNWDZRX0dQUjhfVFhfREVFTVBIX0dFTjEsIDAgPDwgMCk7IEBAIC0z NzcsNyArNDM5LDggQEAgc3RhdGljDQo+IGludA0KPiA+IGlteDZfcGNpZV9zdGFydF9saW5rKHN0 cnVjdCBwY2llX3BvcnQgKnBwKQ0KPiA+DQo+ID4gIAkvKiBTdGFydCBMVFNTTS4gKi8NCj4gPiAg CXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4Y19ncHIsIElPTVVYQ19HUFIxMiwN Cj4gPiAtCQkJSU1YNlFfR1BSMTJfUENJRV9DVExfMiwgMSA8PCAxMCk7DQo+ID4gKwkJCUlNWDZR X0dQUjEyX1BDSUVfQ1RMXzIsDQo+ID4gKwkJCUlNWDZRX0dQUjEyX1BDSUVfQ1RMXzIpOw0KPiA+ DQo+ID4gIAlyZXQgPSBpbXg2X3BjaWVfd2FpdF9mb3JfbGluayhwcCk7DQo+ID4gIAlpZiAocmV0 KQ0KPiA+IEBAIC01NTMsOSArNjE2LDUwIEBAIHN0YXRpYyBpbnQgX19pbml0IGlteDZfYWRkX3Bj aWVfcG9ydChzdHJ1Y3QgcGNpZV9wb3J0DQo+ICpwcCwNCj4gPiAgCXJldHVybiAwOw0KPiA+ICB9 DQo+ID4NCj4gPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+ICtzdGF0aWMgaW50IHBjaV9p bXhfc3VzcGVuZCh2b2lkKQ0KPiA+ICt7DQo+ID4gKwlpZiAoaXNfaW14NnN4X3BjaWUoaW14Nl9w Y2llKSkgew0KPiA+ICsJCS8qIFBNX1RVUk5fT0ZGICovDQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9i aXRzKGlteDZfcGNpZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjEyLA0KPiA+ICsJCQkJSU1YNlNY X0dQUjEyX1BDSUVfUE1fVFVSTl9PRkYsDQo+ID4gKwkJCQlJTVg2U1hfR1BSMTJfUENJRV9QTV9U VVJOX09GRik7DQo+ID4gKwkJdWRlbGF5KDEwKTsNCj4gPiArCQlyZWdtYXBfdXBkYXRlX2JpdHMo aW14Nl9wY2llLT5pb211eGNfZ3ByLCBJT01VWENfR1BSMTIsDQo+ID4gKwkJCQlJTVg2U1hfR1BS MTJfUENJRV9QTV9UVVJOX09GRiwgMCA8PCAxNik7DQo+IA0KPiBKdXN0IHVzZSAwIGFzIHRoZSBs YXN0IGFyZ3VtZW50LiBUaG9zZSBzaGlmdHMgYXJlbid0IGFkZGluZyBhbnl0aGluZyBhbmQgSQ0K PiB3b3VsZCBsaWtlIHRvIGdldCByaWQgb2YgdGhlbSBsb25nIHRlcm0sIHNvIHBsZWFzZSBkb24n dCBpbnRyb2R1Y2UgbmV3IG9uZXMuDQo+IA0KW1JpY2hhcmRdIE9rLCBhbGwgdGhlc2Ugc2hpZnRz IHdvdWxkbid0IGJlIHJlbW92ZWQuDQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIHBjaV9pbXhfcmVzdW1lKHZvaWQpDQo+ID4g K3sNCj4gPiArCXN0cnVjdCBwY2llX3BvcnQgKnBwID0gJmlteDZfcGNpZS0+cHA7DQo+ID4gKw0K PiA+ICsJaWYgKGlzX2lteDZzeF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQkvKiBSZXNldCBp TVg2U1ggUENJZSAqLw0KPiA+ICsJCXJlZ21hcF91cGRhdGVfYml0cyhpbXg2X3BjaWUtPmlvbXV4 Y19ncHIsIElPTVVYQ19HUFI1LA0KPiA+ICsJCQkJSU1YNlNYX0dQUjVfUENJRV9QRVJTVCwgSU1Y NlNYX0dQUjVfUENJRV9QRVJTVCk7DQo+ID4gKwkJcmVnbWFwX3VwZGF0ZV9iaXRzKGlteDZfcGNp ZS0+aW9tdXhjX2dwciwgSU9NVVhDX0dQUjUsDQo+ID4gKwkJCQlJTVg2U1hfR1BSNV9QQ0lFX1BF UlNULCAwIDw8IDE4KTsNCj4gPiArCQkvKg0KPiA+ICsJCSAqIGNvbnRyb2xsZXIgbWF5YmUgdHVy biBvZmYsIHJlLWNvbmZpZ3VyZSBhZ2Fpbg0KPiA+ICsJCSAqLw0KPiA+ICsJCWR3X3BjaWVfc2V0 dXBfcmMocHApOw0KPiA+ICsNCj4gPiArCQlpZiAoSVNfRU5BQkxFRChDT05GSUdfUENJX01TSSkp DQo+ID4gKwkJCWR3X3BjaWVfbXNpX2NmZ19yZXN0b3JlKHBwKTsNCj4gPiArCX0NCj4gPiArfQ0K PiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBzeXNjb3JlX29wcyBwY2lfaW14X3N5c2NvcmVfb3Bz ID0gew0KPiA+ICsJLnN1c3BlbmQgPSBwY2lfaW14X3N1c3BlbmQsDQo+ID4gKwkucmVzdW1lID0g cGNpX2lteF9yZXN1bWUsDQo+ID4gK307DQo+ID4gKyNlbmRpZg0KPiA+ICsNCj4gPiAgc3RhdGlj IGludCBfX2luaXQgaW14Nl9wY2llX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYp ICB7DQo+ID4gLQlzdHJ1Y3QgaW14Nl9wY2llICppbXg2X3BjaWU7DQo+ID4gIAlzdHJ1Y3QgcGNp ZV9wb3J0ICpwcDsNCj4gPiAgCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBwZGV2LT5kZXYub2Zf bm9kZTsNCj4gPiAgCXN0cnVjdCByZXNvdXJjZSAqZGJpX2Jhc2U7DQo+ID4gQEAgLTYxMCw5ICs3 MTQsMjcgQEAgc3RhdGljIGludCBfX2luaXQgaW14Nl9wY2llX3Byb2JlKHN0cnVjdA0KPiBwbGF0 Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4gIAkJcmV0dXJuIFBUUl9FUlIoaW14Nl9wY2llLT5wY2ll KTsNCj4gPiAgCX0NCj4gPg0KPiA+IC0JLyogR3JhYiBHUFIgY29uZmlnIHJlZ2lzdGVyIHJhbmdl ICovDQo+ID4gLQlpbXg2X3BjaWUtPmlvbXV4Y19ncHIgPQ0KPiA+IC0JCSBzeXNjb25fcmVnbWFw X2xvb2t1cF9ieV9jb21wYXRpYmxlKCJmc2wsaW14NnEtaW9tdXhjLWdwciIpOw0KPiA+ICsJaWYg KGlzX2lteDZzeF9wY2llKGlteDZfcGNpZSkpIHsNCj4gPiArCQlpbXg2X3BjaWUtPmRpc3BfYXhp ID0gZGV2bV9jbGtfZ2V0KCZwZGV2LT5kZXYsICJkaXNwX2F4aSIpOw0KPiA+ICsJCWlmIChJU19F UlIoaW14Nl9wY2llLT5kaXNwX2F4aSkpIHsNCj4gPiArCQkJZGV2X2VycigmcGRldi0+ZGV2LA0K PiA+ICsJCQkJInBjaWUgY2xvY2sgc291cmNlIG1pc3Npbmcgb3IgaW52YWxpZFxuIik7DQo+ID4g KwkJCXJldHVybiBQVFJfRVJSKGlteDZfcGNpZS0+ZGlzcF9heGkpOw0KPiA+ICsJCX0NCj4gPiAr DQo+ID4gKwkJaW14Nl9wY2llLT5wY2llX3JlZ3VsYXRvciA9IGRldm1fcmVndWxhdG9yX2dldChw cC0+ZGV2LA0KPiA+ICsJCQkJInBjaWVfcGh5Iik7DQo+ID4gKw0KPiA+ICsJCWlteDZfcGNpZS0+ aW9tdXhjX2dwciA9DQo+ID4gKwkJCSBzeXNjb25fcmVnbWFwX2xvb2t1cF9ieV9jb21wYXRpYmxl DQo+ID4gKwkJCSAoImZzbCxpbXg2c3gtaW9tdXhjLWdwciIpOw0KPiA+ICsJCWlteDZfcGNpZS0+ Z3BjX2lwc19yZWcgPQ0KPiA+ICsJCQkgc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJs ZSgiZnNsLGlteDZzeC1ncGMiKTsNCj4gPiArCX0gZWxzZSB7DQo+ID4gKwkJaW14Nl9wY2llLT5p b211eGNfZ3ByID0NCj4gPiArCQkJc3lzY29uX3JlZ21hcF9sb29rdXBfYnlfY29tcGF0aWJsZQ0K PiA+ICsJCQkoImZzbCxpbXg2cS1pb211eGMtZ3ByIik7DQo+ID4gKwl9DQo+ID4gIAlpZiAoSVNf RVJSKGlteDZfcGNpZS0+aW9tdXhjX2dwcikpIHsNCj4gPiAgCQlkZXZfZXJyKCZwZGV2LT5kZXYs ICJ1bmFibGUgdG8gZmluZCBpb211eGMgcmVnaXN0ZXJzXG4iKTsNCj4gPiAgCQlyZXR1cm4gUFRS X0VSUihpbXg2X3BjaWUtPmlvbXV4Y19ncHIpOyBAQCAtNjIzLDYgKzc0NSw5IEBAIHN0YXRpYw0K PiA+IGludCBfX2luaXQgaW14Nl9wY2llX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBk ZXYpDQo+ID4gIAkJcmV0dXJuIHJldDsNCj4gPg0KPiA+ICAJcGxhdGZvcm1fc2V0X2RydmRhdGEo cGRldiwgaW14Nl9wY2llKTsNCj4gPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUA0KPiA+ICsJcmVn aXN0ZXJfc3lzY29yZV9vcHMoJnBjaV9pbXhfc3lzY29yZV9vcHMpOw0KPiA+ICsjZW5kaWYNCj4g PiAgCXJldHVybiAwOw0KPiA+ICB9DQo+ID4NCj4gPiBAQCAtNjM2LDYgKzc2MSw3IEBAIHN0YXRp YyB2b2lkIGlteDZfcGNpZV9zaHV0ZG93bihzdHJ1Y3QNCj4gPiBwbGF0Zm9ybV9kZXZpY2UgKnBk ZXYpDQo+ID4NCj4gPiAgc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgaW14Nl9wY2ll X29mX21hdGNoW10gPSB7DQo+ID4gIAl7IC5jb21wYXRpYmxlID0gImZzbCxpbXg2cS1wY2llIiwg fSwNCj4gPiArCXsgLmNvbXBhdGlibGUgPSAiZnNsLGlteDZzeC1wY2llIiwgfSwNCj4gPiAgCXt9 LA0KPiA+ICB9Ow0KPiA+ICBNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBpbXg2X3BjaWVfb2ZfbWF0 Y2gpOw0KPiANCj4gLS0NCj4gUGVuZ3V0cm9uaXggZS5LLiAgICAgICAgICAgICB8IEx1Y2FzIFN0 YWNoICAgICAgICAgICAgICAgICB8DQo+IEluZHVzdHJpYWwgTGludXggU29sdXRpb25zICAgfCBo dHRwOi8vd3d3LnBlbmd1dHJvbml4LmRlLyAgfA0KDQoNCkJlc3QgUmVnYXJkcw0KUmljaGFyZCBa aHUNCg0K -- 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/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index eac96fb..be953aa 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> @@ -35,11 +39,15 @@ struct imx6_pcie { int reset_gpio; struct clk *pcie_bus; struct clk *pcie_phy; + struct clk *disp_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 +85,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 +295,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->disp_axi); + if (ret) { + dev_err(pp->dev, "unable to enable pcie clock\n"); + goto err_disp; + } + + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6SX_GPR12_PCIE_TEST_PD, 0 << 30); + } 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); + /* + * 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 +328,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 << 19); + return 0; +err_disp: + clk_disable_unprepare(imx6_pcie->pcie); err_pcie: clk_disable_unprepare(imx6_pcie->pcie_bus); err_pcie_bus: @@ -311,6 +353,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 +381,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 +439,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 +616,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 << 16); + } + + 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 << 18); + /* + * 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; @@ -610,9 +714,27 @@ 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->disp_axi = devm_clk_get(&pdev->dev, "disp_axi"); + if (IS_ERR(imx6_pcie->disp_axi)) { + dev_err(&pdev->dev, + "pcie clock source missing or invalid\n"); + return PTR_ERR(imx6_pcie->disp_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 +745,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 +761,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);
- 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 for imx6sx pcie. Signed-off-by: Richard Zhu <r65037@freescale.com> --- drivers/pci/host/pci-imx6.c | 162 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 18 deletions(-)