Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-28 Thread Sumit Garg
On Wed, 28 Feb 2024 at 22:07, Tim Harvey  wrote:
>
> On Tue, Feb 27, 2024 at 3:19 PM Adam Ford  wrote:
> >
> > On Mon, Feb 26, 2024 at 2:05 AM Sumit Garg  wrote:
> > >
> > > pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
> > > tied to quite old port of pcie_designware driver from Linux which
> > > suffices only iMX6 specific needs.
> > >
> > > But currently we have the common DWC specific bits which alligns pretty
> > > well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
> > > bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
> > > add support for other iMX8 variants to this driver.
> > >
> > > iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
> > > can reuse the generic PHY infrastructure to power on PCIe PHY.
> > >
> > > Signed-off-by: Sumit Garg 
> > > ---
> > >  drivers/pci/Kconfig   |   8 +
> > >  drivers/pci/Makefile  |   1 +
> > >  drivers/pci/pcie_dw_imx.c | 314 ++
> > >  3 files changed, 323 insertions(+)
> > >  create mode 100644 drivers/pci/pcie_dw_imx.c
> > >
> > > diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> > > index 463ec47eb92d..7edbf35004a9 100644
> > > --- a/drivers/pci/Kconfig
> > > +++ b/drivers/pci/Kconfig
> > > @@ -413,4 +413,12 @@ config PCIE_STARFIVE_JH7110
> > >   Say Y here if you want to enable PLDA XpressRich PCIe controller
> > >   support on StarFive JH7110 SoC.
> > >
> > > +config PCIE_DW_IMX
> > > +   bool "i.MX DW PCIe controller support"
> > > +   depends on ARCH_IMX8M
> >
> > I think this also needs to depend on REGMAP to prevent build errors.
> >
>
> Sumit,
>
> both REGMAP and SYSCON are needed to build.
>

Ack.

-Sumit


Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-28 Thread Tim Harvey
On Tue, Feb 27, 2024 at 3:19 PM Adam Ford  wrote:
>
> On Mon, Feb 26, 2024 at 2:05 AM Sumit Garg  wrote:
> >
> > pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
> > tied to quite old port of pcie_designware driver from Linux which
> > suffices only iMX6 specific needs.
> >
> > But currently we have the common DWC specific bits which alligns pretty
> > well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
> > bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
> > add support for other iMX8 variants to this driver.
> >
> > iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
> > can reuse the generic PHY infrastructure to power on PCIe PHY.
> >
> > Signed-off-by: Sumit Garg 
> > ---
> >  drivers/pci/Kconfig   |   8 +
> >  drivers/pci/Makefile  |   1 +
> >  drivers/pci/pcie_dw_imx.c | 314 ++
> >  3 files changed, 323 insertions(+)
> >  create mode 100644 drivers/pci/pcie_dw_imx.c
> >
> > diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> > index 463ec47eb92d..7edbf35004a9 100644
> > --- a/drivers/pci/Kconfig
> > +++ b/drivers/pci/Kconfig
> > @@ -413,4 +413,12 @@ config PCIE_STARFIVE_JH7110
> >   Say Y here if you want to enable PLDA XpressRich PCIe controller
> >   support on StarFive JH7110 SoC.
> >
> > +config PCIE_DW_IMX
> > +   bool "i.MX DW PCIe controller support"
> > +   depends on ARCH_IMX8M
>
> I think this also needs to depend on REGMAP to prevent build errors.
>

Sumit,

both REGMAP and SYSCON are needed to build.

Best Regards,

Tim


Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-27 Thread Sumit Garg
On Wed, 28 Feb 2024 at 04:44, Adam Ford  wrote:
>
> On Mon, Feb 26, 2024 at 2:05 AM Sumit Garg  wrote:
> >
> > pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
> > tied to quite old port of pcie_designware driver from Linux which
> > suffices only iMX6 specific needs.
> >
> > But currently we have the common DWC specific bits which alligns pretty
> > well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
> > bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
> > add support for other iMX8 variants to this driver.
> >
> > iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
> > can reuse the generic PHY infrastructure to power on PCIe PHY.
> >
> > Signed-off-by: Sumit Garg 
> > ---
> >  drivers/pci/Kconfig   |   8 +
> >  drivers/pci/Makefile  |   1 +
> >  drivers/pci/pcie_dw_imx.c | 314 ++
> >  3 files changed, 323 insertions(+)
> >  create mode 100644 drivers/pci/pcie_dw_imx.c
> >
> > diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> > index 463ec47eb92d..7edbf35004a9 100644
> > --- a/drivers/pci/Kconfig
> > +++ b/drivers/pci/Kconfig
> > @@ -413,4 +413,12 @@ config PCIE_STARFIVE_JH7110
> >   Say Y here if you want to enable PLDA XpressRich PCIe controller
> >   support on StarFive JH7110 SoC.
> >
> > +config PCIE_DW_IMX
> > +   bool "i.MX DW PCIe controller support"
> > +   depends on ARCH_IMX8M
>
> I think this also needs to depend on REGMAP to prevent build errors.
>

Ack, I will add that.

-Sumit

>
> adam
>
> > +   select PCIE_DW_COMMON
> > +   help
> > + Say Y here if you want to enable DW PCIe controller support on
> > + iMX SoCs.
> > +
> >  endif
> > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> > index 72ef8b4bc772..2927c519129b 100644
> > --- a/drivers/pci/Makefile
> > +++ b/drivers/pci/Makefile
> > @@ -53,3 +53,4 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
> >  obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
> >  obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
> >  obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o
> > +obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o
> > diff --git a/drivers/pci/pcie_dw_imx.c b/drivers/pci/pcie_dw_imx.c
> > new file mode 100644
> > index ..7856823c9188
> > --- /dev/null
> > +++ b/drivers/pci/pcie_dw_imx.c
> > @@ -0,0 +1,314 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2024 Linaro Ltd.
> > + *
> > + * Author: Sumit Garg 
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "pcie_dw_common.h"
> > +
> > +#define PCIE_LINK_CAPABILITY   0x7c
> > +#define TARGET_LINK_SPEED_MASK 0xf
> > +#define LINK_SPEED_GEN_1   0x1
> > +#define LINK_SPEED_GEN_2   0x2
> > +#define LINK_SPEED_GEN_3   0x3
> > +
> > +#define PCIE_MISC_CONTROL_1_OFF0x8bc
> > +#define PCIE_DBI_RO_WR_EN  BIT(0)
> > +
> > +#define PCIE_PORT_DEBUG0   0x728
> > +#define PCIE_PORT_DEBUG1   0x72c
> > +#define PCIE_PORT_DEBUG1_LINK_UP   BIT(4)
> > +#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING  BIT(29)
> > +
> > +#define PCIE_LINK_UP_TIMEOUT_MS100
> > +
> > +#define IOMUXC_GPR14_OFFSET0x38
> > +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10)
> > +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDEBIT(11)
> > +
> > +struct pcie_dw_imx {
> > +   /* Must be first member of the struct */
> > +   struct pcie_dw  dw;
> > +   struct regmap   *iomuxc_gpr;
> > +   struct clk_bulk clks;
> > +   struct gpio_descreset_gpio;
> > +   struct reset_ctlapps_reset;
> > +   struct phy  phy;
> > +};
> > +
> > +static void pcie_dw_configure(struct pcie_dw_imx *priv, u32 cap_speed)
> > +{
> > +   dw_pcie_dbi_write_enable(&priv->dw, true);
> > +
> > +   clrsetbits_le32(priv->dw.dbi_base + PCIE_LINK_CAPABILITY,
> > +   TARGET_LINK_SPEED_MASK, cap_speed);
> > +
> > +   dw_pcie_dbi_write_enable(&priv->dw, false);
> > +}
> > +
> > +static void imx_pcie_ltssm_enable(struct pcie_dw_imx *priv)
> > +{
> > +   reset_deassert(&priv->apps_reset);
> > +}
> > +
> > +static void imx_pcie_ltssm_disable(struct pcie_dw_imx *priv)
> > +{
> > +   reset_assert(&priv->apps_reset);
> > +}
> > +
> > +static bool is_link_up(u32 val)
> > +{
> > +   return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
> > +   (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
> > +}
> > +
> > +static int wait_link_up(struct pcie_dw_imx *priv)
> > +{
> > +   u32 val;
> 

Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-27 Thread Adam Ford
On Mon, Feb 26, 2024 at 2:05 AM Sumit Garg  wrote:
>
> pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
> tied to quite old port of pcie_designware driver from Linux which
> suffices only iMX6 specific needs.
>
> But currently we have the common DWC specific bits which alligns pretty
> well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
> bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
> add support for other iMX8 variants to this driver.
>
> iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
> can reuse the generic PHY infrastructure to power on PCIe PHY.
>
> Signed-off-by: Sumit Garg 
> ---
>  drivers/pci/Kconfig   |   8 +
>  drivers/pci/Makefile  |   1 +
>  drivers/pci/pcie_dw_imx.c | 314 ++
>  3 files changed, 323 insertions(+)
>  create mode 100644 drivers/pci/pcie_dw_imx.c
>
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 463ec47eb92d..7edbf35004a9 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -413,4 +413,12 @@ config PCIE_STARFIVE_JH7110
>   Say Y here if you want to enable PLDA XpressRich PCIe controller
>   support on StarFive JH7110 SoC.
>
> +config PCIE_DW_IMX
> +   bool "i.MX DW PCIe controller support"
> +   depends on ARCH_IMX8M

I think this also needs to depend on REGMAP to prevent build errors.


adam

> +   select PCIE_DW_COMMON
> +   help
> + Say Y here if you want to enable DW PCIe controller support on
> + iMX SoCs.
> +
>  endif
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index 72ef8b4bc772..2927c519129b 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -53,3 +53,4 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
>  obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
>  obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
>  obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o
> +obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o
> diff --git a/drivers/pci/pcie_dw_imx.c b/drivers/pci/pcie_dw_imx.c
> new file mode 100644
> index ..7856823c9188
> --- /dev/null
> +++ b/drivers/pci/pcie_dw_imx.c
> @@ -0,0 +1,314 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2024 Linaro Ltd.
> + *
> + * Author: Sumit Garg 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "pcie_dw_common.h"
> +
> +#define PCIE_LINK_CAPABILITY   0x7c
> +#define TARGET_LINK_SPEED_MASK 0xf
> +#define LINK_SPEED_GEN_1   0x1
> +#define LINK_SPEED_GEN_2   0x2
> +#define LINK_SPEED_GEN_3   0x3
> +
> +#define PCIE_MISC_CONTROL_1_OFF0x8bc
> +#define PCIE_DBI_RO_WR_EN  BIT(0)
> +
> +#define PCIE_PORT_DEBUG0   0x728
> +#define PCIE_PORT_DEBUG1   0x72c
> +#define PCIE_PORT_DEBUG1_LINK_UP   BIT(4)
> +#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING  BIT(29)
> +
> +#define PCIE_LINK_UP_TIMEOUT_MS100
> +
> +#define IOMUXC_GPR14_OFFSET0x38
> +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10)
> +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDEBIT(11)
> +
> +struct pcie_dw_imx {
> +   /* Must be first member of the struct */
> +   struct pcie_dw  dw;
> +   struct regmap   *iomuxc_gpr;
> +   struct clk_bulk clks;
> +   struct gpio_descreset_gpio;
> +   struct reset_ctlapps_reset;
> +   struct phy  phy;
> +};
> +
> +static void pcie_dw_configure(struct pcie_dw_imx *priv, u32 cap_speed)
> +{
> +   dw_pcie_dbi_write_enable(&priv->dw, true);
> +
> +   clrsetbits_le32(priv->dw.dbi_base + PCIE_LINK_CAPABILITY,
> +   TARGET_LINK_SPEED_MASK, cap_speed);
> +
> +   dw_pcie_dbi_write_enable(&priv->dw, false);
> +}
> +
> +static void imx_pcie_ltssm_enable(struct pcie_dw_imx *priv)
> +{
> +   reset_deassert(&priv->apps_reset);
> +}
> +
> +static void imx_pcie_ltssm_disable(struct pcie_dw_imx *priv)
> +{
> +   reset_assert(&priv->apps_reset);
> +}
> +
> +static bool is_link_up(u32 val)
> +{
> +   return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
> +   (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
> +}
> +
> +static int wait_link_up(struct pcie_dw_imx *priv)
> +{
> +   u32 val;
> +
> +   return readl_poll_sleep_timeout(priv->dw.dbi_base + PCIE_PORT_DEBUG1,
> +   val, is_link_up(val), 1, 10);
> +}
> +
> +static int pcie_link_up(struct pcie_dw_imx *priv, u32 cap_speed)
> +{
> +   int ret;
> +
> +   /* DW pre link configurations */
> +   pcie_dw_configure(priv, cap_speed);
> +
> + 

Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-26 Thread Sumit Garg
On Mon, 26 Feb 2024 at 14:24, Marek Vasut  wrote:
>
> On 2/26/24 9:04 AM, Sumit Garg wrote:
> > pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
> > tied to quite old port of pcie_designware driver from Linux which
> > suffices only iMX6 specific needs.
>
> It is probably hand-rolled, but it does suck, that's true.
>
> > But currently we have the common DWC specific bits which alligns pretty
> > well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
> > bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
> > add support for other iMX8 variants to this driver.
> >
> > iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
> > can reuse the generic PHY infrastructure to power on PCIe PHY.
>
> [...]
>
> > +static int pcie_dw_imx_of_to_plat(struct udevice *dev)
> > +{
> > + struct pcie_dw_imx *priv = dev_get_priv(dev);
> > + ofnode gpr;
> > + int ret;
> > +
> > + /* Get the controller base address */
> > + priv->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbi");
> > + if ((fdt_addr_t)priv->dw.dbi_base == FDT_ADDR_T_NONE) {
> > + dev_err(dev, "failed to get dbi_base address\n");
> > + return -EINVAL;
> > + }
> > +
> > + /* Get the config space base address and size */
> > + priv->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config",
> > + 
> > &priv->dw.cfg_size);
> > + if ((fdt_addr_t)priv->dw.cfg_base == FDT_ADDR_T_NONE) {
> > + dev_err(dev, "failed to get cfg_base address\n");
> > + return -EINVAL;
> > + }
> > +
> > + ret = clk_get_bulk(dev, &priv->clks);
> > + if (ret) {
> > + dev_err(dev, "failed to get PCIe clks\n");
> > + return ret;
> > + }
> > +
> > + ret = reset_get_by_name(dev, "apps", &priv->apps_reset);
> > + if (ret) {
> > + dev_err(dev,
> > + "Failed to get PCIe apps reset control\n");
> > + return ret;
> > + }
> > +
> > + ret = gpio_request_by_name(dev, "reset-gpio", 0, &priv->reset_gpio,
> > +(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
> > + if (ret) {
> > + dev_err(dev, "unable to get reset-gpio\n");
> > + return ret;
> > + }
> > +
> > + ret = generic_phy_get_by_name(dev, "pcie-phy", &priv->phy);
> > + if (ret) {
> > + dev_err(dev, "failed to get pcie phy\n");
> > + return ret;
> > + }
> > +
> > + gpr = ofnode_by_compatible(ofnode_null(), "fsl,imx8mp-iomuxc-gpr");
> > + if (ofnode_equal(gpr, ofnode_null())) {
> > + dev_err(dev, "unable to find GPR node\n");
> > + return -ENODEV;
> > + }
>
> You likely need a fail path here too, to undo allocation and co.

Ack.

-Sumit


Re: [PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-26 Thread Marek Vasut

On 2/26/24 9:04 AM, Sumit Garg wrote:

pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
tied to quite old port of pcie_designware driver from Linux which
suffices only iMX6 specific needs.


It is probably hand-rolled, but it does suck, that's true.


But currently we have the common DWC specific bits which alligns pretty
well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
add support for other iMX8 variants to this driver.

iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
can reuse the generic PHY infrastructure to power on PCIe PHY.


[...]


+static int pcie_dw_imx_of_to_plat(struct udevice *dev)
+{
+   struct pcie_dw_imx *priv = dev_get_priv(dev);
+   ofnode gpr;
+   int ret;
+
+   /* Get the controller base address */
+   priv->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbi");
+   if ((fdt_addr_t)priv->dw.dbi_base == FDT_ADDR_T_NONE) {
+   dev_err(dev, "failed to get dbi_base address\n");
+   return -EINVAL;
+   }
+
+   /* Get the config space base address and size */
+   priv->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config",
+   &priv->dw.cfg_size);
+   if ((fdt_addr_t)priv->dw.cfg_base == FDT_ADDR_T_NONE) {
+   dev_err(dev, "failed to get cfg_base address\n");
+   return -EINVAL;
+   }
+
+   ret = clk_get_bulk(dev, &priv->clks);
+   if (ret) {
+   dev_err(dev, "failed to get PCIe clks\n");
+   return ret;
+   }
+
+   ret = reset_get_by_name(dev, "apps", &priv->apps_reset);
+   if (ret) {
+   dev_err(dev,
+   "Failed to get PCIe apps reset control\n");
+   return ret;
+   }
+
+   ret = gpio_request_by_name(dev, "reset-gpio", 0, &priv->reset_gpio,
+  (GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
+   if (ret) {
+   dev_err(dev, "unable to get reset-gpio\n");
+   return ret;
+   }
+
+   ret = generic_phy_get_by_name(dev, "pcie-phy", &priv->phy);
+   if (ret) {
+   dev_err(dev, "failed to get pcie phy\n");
+   return ret;
+   }
+
+   gpr = ofnode_by_compatible(ofnode_null(), "fsl,imx8mp-iomuxc-gpr");
+   if (ofnode_equal(gpr, ofnode_null())) {
+   dev_err(dev, "unable to find GPR node\n");
+   return -ENODEV;
+   }


You likely need a fail path here too, to undo allocation and co.


[PATCH v2 6/8] pci: Add DW PCIe controller support for iMX8MP SoC

2024-02-26 Thread Sumit Garg
pcie_imx doesn't seem to share any useful code for iMX8 SoC and it is
tied to quite old port of pcie_designware driver from Linux which
suffices only iMX6 specific needs.

But currently we have the common DWC specific bits which alligns pretty
well with DW PCIe controller on iMX8MP SoC. So lets reuse those common
bits instead as a new driver for iMX8 SoCs. It should be fairly easy to
add support for other iMX8 variants to this driver.

iMX8MP SoC also comes up with standalone PCIe PHY support, so hence we
can reuse the generic PHY infrastructure to power on PCIe PHY.

Signed-off-by: Sumit Garg 
---
 drivers/pci/Kconfig   |   8 +
 drivers/pci/Makefile  |   1 +
 drivers/pci/pcie_dw_imx.c | 314 ++
 3 files changed, 323 insertions(+)
 create mode 100644 drivers/pci/pcie_dw_imx.c

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 463ec47eb92d..7edbf35004a9 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -413,4 +413,12 @@ config PCIE_STARFIVE_JH7110
  Say Y here if you want to enable PLDA XpressRich PCIe controller
  support on StarFive JH7110 SoC.
 
+config PCIE_DW_IMX
+   bool "i.MX DW PCIe controller support"
+   depends on ARCH_IMX8M
+   select PCIE_DW_COMMON
+   help
+ Say Y here if you want to enable DW PCIe controller support on
+ iMX SoCs.
+
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 72ef8b4bc772..2927c519129b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o
 obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
 obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o
 obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o
+obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o
diff --git a/drivers/pci/pcie_dw_imx.c b/drivers/pci/pcie_dw_imx.c
new file mode 100644
index ..7856823c9188
--- /dev/null
+++ b/drivers/pci/pcie_dw_imx.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Linaro Ltd.
+ *
+ * Author: Sumit Garg 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pcie_dw_common.h"
+
+#define PCIE_LINK_CAPABILITY   0x7c
+#define TARGET_LINK_SPEED_MASK 0xf
+#define LINK_SPEED_GEN_1   0x1
+#define LINK_SPEED_GEN_2   0x2
+#define LINK_SPEED_GEN_3   0x3
+
+#define PCIE_MISC_CONTROL_1_OFF0x8bc
+#define PCIE_DBI_RO_WR_EN  BIT(0)
+
+#define PCIE_PORT_DEBUG0   0x728
+#define PCIE_PORT_DEBUG1   0x72c
+#define PCIE_PORT_DEBUG1_LINK_UP   BIT(4)
+#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING  BIT(29)
+
+#define PCIE_LINK_UP_TIMEOUT_MS100
+
+#define IOMUXC_GPR14_OFFSET0x38
+#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10)
+#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDEBIT(11)
+
+struct pcie_dw_imx {
+   /* Must be first member of the struct */
+   struct pcie_dw  dw;
+   struct regmap   *iomuxc_gpr;
+   struct clk_bulk clks;
+   struct gpio_descreset_gpio;
+   struct reset_ctlapps_reset;
+   struct phy  phy;
+};
+
+static void pcie_dw_configure(struct pcie_dw_imx *priv, u32 cap_speed)
+{
+   dw_pcie_dbi_write_enable(&priv->dw, true);
+
+   clrsetbits_le32(priv->dw.dbi_base + PCIE_LINK_CAPABILITY,
+   TARGET_LINK_SPEED_MASK, cap_speed);
+
+   dw_pcie_dbi_write_enable(&priv->dw, false);
+}
+
+static void imx_pcie_ltssm_enable(struct pcie_dw_imx *priv)
+{
+   reset_deassert(&priv->apps_reset);
+}
+
+static void imx_pcie_ltssm_disable(struct pcie_dw_imx *priv)
+{
+   reset_assert(&priv->apps_reset);
+}
+
+static bool is_link_up(u32 val)
+{
+   return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
+   (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
+}
+
+static int wait_link_up(struct pcie_dw_imx *priv)
+{
+   u32 val;
+
+   return readl_poll_sleep_timeout(priv->dw.dbi_base + PCIE_PORT_DEBUG1,
+   val, is_link_up(val), 1, 10);
+}
+
+static int pcie_link_up(struct pcie_dw_imx *priv, u32 cap_speed)
+{
+   int ret;
+
+   /* DW pre link configurations */
+   pcie_dw_configure(priv, cap_speed);
+
+   /* Initiate link training */
+   imx_pcie_ltssm_enable(priv);
+
+   /* Check that link was established */
+   ret = wait_link_up(priv);
+   if (ret)
+   imx_pcie_ltssm_disable(priv);
+
+   return ret;
+}
+
+static int imx_pcie_assert_core_reset(struct pcie_dw_imx *priv)
+{
+   if (dm_gpio_is_valid(&priv->reset_gpio)) {
+   dm_gpio_set_value(&priv->reset_gpio, 1);
+