[PATCH v4 01/10] power-domain: Return 0 if ops unimplemented and remove empty functions

In case the ops is not implemented, return 0 in the core right away. This is better than having multiple copies of functions which just return 0 in each power domain driver. Drop all those empty functions.
Signed-off-by: Marek Vasut marex@denx.de Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org --- V2: Skipped to align the Vx scheme V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/power/domain/apple-pmgr.c | 30 ------------------- drivers/power/domain/bcm6328-power-domain.c | 6 ---- .../power/domain/imx8-power-domain-legacy.c | 16 ---------- drivers/power/domain/imx8-power-domain.c | 24 --------------- drivers/power/domain/imx8m-power-domain.c | 18 ----------- drivers/power/domain/meson-ee-pwrc.c | 12 -------- drivers/power/domain/meson-gx-pwrc-vpu.c | 12 -------- drivers/power/domain/mtk-power-domain.c | 6 ---- drivers/power/domain/power-domain-uclass.c | 8 ++--- drivers/power/domain/tegra186-power-domain.c | 26 ---------------- drivers/power/domain/ti-power-domain.c | 13 -------- drivers/power/domain/ti-sci-power-domain.c | 14 --------- 12 files changed, 4 insertions(+), 181 deletions(-)
diff --git a/drivers/power/domain/apple-pmgr.c b/drivers/power/domain/apple-pmgr.c index 4d06e76ff5e..402c5b1fd18 100644 --- a/drivers/power/domain/apple-pmgr.c +++ b/drivers/power/domain/apple-pmgr.c @@ -42,16 +42,6 @@ static int apple_reset_of_xlate(struct reset_ctl *reset_ctl, return 0; }
-static int apple_reset_request(struct reset_ctl *reset_ctl) -{ - return 0; -} - -static int apple_reset_free(struct reset_ctl *reset_ctl) -{ - return 0; -} - static int apple_reset_assert(struct reset_ctl *reset_ctl) { struct apple_pmgr_priv *priv = dev_get_priv(reset_ctl->dev->parent); @@ -80,8 +70,6 @@ static int apple_reset_deassert(struct reset_ctl *reset_ctl)
struct reset_ops apple_reset_ops = { .of_xlate = apple_reset_of_xlate, - .request = apple_reset_request, - .rfree = apple_reset_free, .rst_assert = apple_reset_assert, .rst_deassert = apple_reset_deassert, }; @@ -92,16 +80,6 @@ static struct driver apple_reset_driver = { .ops = &apple_reset_ops, };
-static int apple_pmgr_request(struct power_domain *power_domain) -{ - return 0; -} - -static int apple_pmgr_rfree(struct power_domain *power_domain) -{ - return 0; -} - static int apple_pmgr_ps_set(struct power_domain *power_domain, u32 pstate) { struct apple_pmgr_priv *priv = dev_get_priv(power_domain->dev); @@ -121,11 +99,6 @@ static int apple_pmgr_on(struct power_domain *power_domain) return apple_pmgr_ps_set(power_domain, APPLE_PMGR_PS_ACTIVE); }
-static int apple_pmgr_off(struct power_domain *power_domain) -{ - return 0; -} - static int apple_pmgr_of_xlate(struct power_domain *power_domain, struct ofnode_phandle_args *args) { @@ -167,10 +140,7 @@ static int apple_pmgr_probe(struct udevice *dev) }
struct power_domain_ops apple_pmgr_ops = { - .request = apple_pmgr_request, - .rfree = apple_pmgr_rfree, .on = apple_pmgr_on, - .off = apple_pmgr_off, .of_xlate = apple_pmgr_of_xlate, };
diff --git a/drivers/power/domain/bcm6328-power-domain.c b/drivers/power/domain/bcm6328-power-domain.c index 6e720e0798c..80144dd9772 100644 --- a/drivers/power/domain/bcm6328-power-domain.c +++ b/drivers/power/domain/bcm6328-power-domain.c @@ -24,11 +24,6 @@ static int bcm6328_power_domain_request(struct power_domain *power_domain) return 0; }
-static int bcm6328_power_domain_free(struct power_domain *power_domain) -{ - return 0; -} - static int bcm6328_power_domain_on(struct power_domain *power_domain) { struct bcm6328_power_domain *priv = dev_get_priv(power_domain->dev); @@ -64,7 +59,6 @@ static const struct udevice_id bcm6328_power_domain_ids[] = { };
struct power_domain_ops bcm6328_power_domain_ops = { - .rfree = bcm6328_power_domain_free, .off = bcm6328_power_domain_off, .on = bcm6328_power_domain_on, .request = bcm6328_power_domain_request, diff --git a/drivers/power/domain/imx8-power-domain-legacy.c b/drivers/power/domain/imx8-power-domain-legacy.c index e2fae2dbc86..bf45891bccd 100644 --- a/drivers/power/domain/imx8-power-domain-legacy.c +++ b/drivers/power/domain/imx8-power-domain-legacy.c @@ -84,20 +84,6 @@ int imx8_power_domain_lookup_name(const char *name, return 0; }
-static int imx8_power_domain_request(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p)\n", __func__, power_domain); - - return 0; -} - -static int imx8_power_domain_free(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p)\n", __func__, power_domain); - - return 0; -} - static int imx8_power_domain_on(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev; @@ -364,8 +350,6 @@ static const struct udevice_id imx8_power_domain_ids[] = { };
struct power_domain_ops imx8_power_domain_ops = { - .request = imx8_power_domain_request, - .rfree = imx8_power_domain_free, .on = imx8_power_domain_on, .off = imx8_power_domain_off, .of_xlate = imx8_power_domain_of_xlate, diff --git a/drivers/power/domain/imx8-power-domain.c b/drivers/power/domain/imx8-power-domain.c index 6461ab23d62..17b5d57b19b 100644 --- a/drivers/power/domain/imx8-power-domain.c +++ b/drivers/power/domain/imx8-power-domain.c @@ -12,20 +12,6 @@ #include <asm/arch/power-domain.h> #include <asm/arch/sci/sci.h>
-static int imx8_power_domain_request(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p)\n", __func__, power_domain); - - return 0; -} - -static int imx8_power_domain_free(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p)\n", __func__, power_domain); - - return 0; -} - static int imx8_power_domain_on(struct power_domain *power_domain) { u32 resource_id = power_domain->id; @@ -60,13 +46,6 @@ static int imx8_power_domain_off(struct power_domain *power_domain) return 0; }
-static int imx8_power_domain_probe(struct udevice *dev) -{ - debug("%s(dev=%s)\n", __func__, dev->name); - - return 0; -} - static const struct udevice_id imx8_power_domain_ids[] = { { .compatible = "fsl,imx8qxp-scu-pd" }, { .compatible = "fsl,scu-pd" }, @@ -74,8 +53,6 @@ static const struct udevice_id imx8_power_domain_ids[] = { };
struct power_domain_ops imx8_power_domain_ops_v2 = { - .request = imx8_power_domain_request, - .rfree = imx8_power_domain_free, .on = imx8_power_domain_on, .off = imx8_power_domain_off, }; @@ -84,6 +61,5 @@ U_BOOT_DRIVER(imx8_power_domain_v2) = { .name = "imx8_power_domain_v2", .id = UCLASS_POWER_DOMAIN, .of_match = imx8_power_domain_ids, - .probe = imx8_power_domain_probe, .ops = &imx8_power_domain_ops_v2, }; diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index 5d34bc12902..6082ee6ff8c 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -18,16 +18,6 @@
DECLARE_GLOBAL_DATA_PTR;
-static int imx8m_power_domain_request(struct power_domain *power_domain) -{ - return 0; -} - -static int imx8m_power_domain_free(struct power_domain *power_domain) -{ - return 0; -} - static int imx8m_power_domain_on(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev; @@ -100,11 +90,6 @@ static int imx8m_power_domain_bind(struct udevice *dev) return 0; }
-static int imx8m_power_domain_probe(struct udevice *dev) -{ - return 0; -} - static int imx8m_power_domain_of_to_plat(struct udevice *dev) { struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); @@ -126,8 +111,6 @@ static const struct udevice_id imx8m_power_domain_ids[] = { };
struct power_domain_ops imx8m_power_domain_ops = { - .request = imx8m_power_domain_request, - .rfree = imx8m_power_domain_free, .on = imx8m_power_domain_on, .off = imx8m_power_domain_off, .of_xlate = imx8m_power_domain_of_xlate, @@ -138,7 +121,6 @@ U_BOOT_DRIVER(imx8m_power_domain) = { .id = UCLASS_POWER_DOMAIN, .of_match = imx8m_power_domain_ids, .bind = imx8m_power_domain_bind, - .probe = imx8m_power_domain_probe, .of_to_plat = imx8m_power_domain_of_to_plat, .plat_auto = sizeof(struct imx8m_power_domain_plat), .ops = &imx8m_power_domain_ops, diff --git a/drivers/power/domain/meson-ee-pwrc.c b/drivers/power/domain/meson-ee-pwrc.c index a4d50e701ae..676fded8080 100644 --- a/drivers/power/domain/meson-ee-pwrc.c +++ b/drivers/power/domain/meson-ee-pwrc.c @@ -273,16 +273,6 @@ static bool pwrc_ee_get_power(struct power_domain *power_domain) return (reg & pwrc_domain->top_pd->sleep_mask); }
-static int meson_ee_pwrc_request(struct power_domain *power_domain) -{ - return 0; -} - -static int meson_ee_pwrc_free(struct power_domain *power_domain) -{ - return 0; -} - static int meson_ee_pwrc_off(struct power_domain *power_domain) { struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev); @@ -387,10 +377,8 @@ static int meson_ee_pwrc_of_xlate(struct power_domain *power_domain, }
struct power_domain_ops meson_ee_pwrc_ops = { - .rfree = meson_ee_pwrc_free, .off = meson_ee_pwrc_off, .on = meson_ee_pwrc_on, - .request = meson_ee_pwrc_request, .of_xlate = meson_ee_pwrc_of_xlate, };
diff --git a/drivers/power/domain/meson-gx-pwrc-vpu.c b/drivers/power/domain/meson-gx-pwrc-vpu.c index eb94af2cf83..612660ce89f 100644 --- a/drivers/power/domain/meson-gx-pwrc-vpu.c +++ b/drivers/power/domain/meson-gx-pwrc-vpu.c @@ -45,16 +45,6 @@ struct meson_gx_pwrc_vpu_priv { struct clk_bulk clks; };
-static int meson_pwrc_vpu_request(struct power_domain *power_domain) -{ - return 0; -} - -static int meson_pwrc_vpu_free(struct power_domain *power_domain) -{ - return 0; -} - static int meson_gx_pwrc_vpu_on(struct power_domain *power_domain) { struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev); @@ -274,10 +264,8 @@ static int meson_pwrc_vpu_of_xlate(struct power_domain *power_domain, }
struct power_domain_ops meson_gx_pwrc_vpu_ops = { - .rfree = meson_pwrc_vpu_free, .off = meson_pwrc_vpu_off, .on = meson_pwrc_vpu_on, - .request = meson_pwrc_vpu_request, .of_xlate = meson_pwrc_vpu_of_xlate, };
diff --git a/drivers/power/domain/mtk-power-domain.c b/drivers/power/domain/mtk-power-domain.c index ca2ded00efa..3b84147d481 100644 --- a/drivers/power/domain/mtk-power-domain.c +++ b/drivers/power/domain/mtk-power-domain.c @@ -317,11 +317,6 @@ static int scpsys_power_request(struct power_domain *power_domain) return 0; }
-static int scpsys_power_free(struct power_domain *power_domain) -{ - return 0; -} - static int mtk_power_domain_hook(struct udevice *dev) { struct scp_domain *scpd = dev_get_priv(dev); @@ -399,7 +394,6 @@ static const struct udevice_id mtk_power_domain_ids[] = { };
struct power_domain_ops mtk_power_domain_ops = { - .rfree = scpsys_power_free, .off = scpsys_power_off, .on = scpsys_power_on, .request = scpsys_power_request, diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c index 33f9206bd09..0c5823ceddf 100644 --- a/drivers/power/domain/power-domain-uclass.c +++ b/drivers/power/domain/power-domain-uclass.c @@ -71,7 +71,7 @@ int power_domain_get_by_index(struct udevice *dev, return ret; }
- ret = ops->request(power_domain); + ret = ops->request ? ops->request(power_domain) : 0; if (ret) { debug("ops->request() failed: %d\n", ret); return ret; @@ -91,7 +91,7 @@ int power_domain_free(struct power_domain *power_domain)
debug("%s(power_domain=%p)\n", __func__, power_domain);
- return ops->rfree(power_domain); + return ops->rfree ? ops->rfree(power_domain) : 0; }
int power_domain_on(struct power_domain *power_domain) @@ -100,7 +100,7 @@ int power_domain_on(struct power_domain *power_domain)
debug("%s(power_domain=%p)\n", __func__, power_domain);
- return ops->on(power_domain); + return ops->on ? ops->on(power_domain) : 0; }
int power_domain_off(struct power_domain *power_domain) @@ -109,7 +109,7 @@ int power_domain_off(struct power_domain *power_domain)
debug("%s(power_domain=%p)\n", __func__, power_domain);
- return ops->off(power_domain); + return ops->off ? ops->off(power_domain) : 0; }
#if CONFIG_IS_ENABLED(OF_REAL) diff --git a/drivers/power/domain/tegra186-power-domain.c b/drivers/power/domain/tegra186-power-domain.c index 707735cf851..46da541b75a 100644 --- a/drivers/power/domain/tegra186-power-domain.c +++ b/drivers/power/domain/tegra186-power-domain.c @@ -15,22 +15,6 @@ #define UPDATE BIT(0) #define ON BIT(1)
-static int tegra186_power_domain_request(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__, - power_domain, power_domain->dev, power_domain->id); - - return 0; -} - -static int tegra186_power_domain_free(struct power_domain *power_domain) -{ - debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__, - power_domain, power_domain->dev, power_domain->id); - - return 0; -} - static int tegra186_power_domain_common(struct power_domain *power_domain, bool on) { @@ -73,22 +57,12 @@ static int tegra186_power_domain_off(struct power_domain *power_domain) }
struct power_domain_ops tegra186_power_domain_ops = { - .request = tegra186_power_domain_request, - .rfree = tegra186_power_domain_free, .on = tegra186_power_domain_on, .off = tegra186_power_domain_off, };
-static int tegra186_power_domain_probe(struct udevice *dev) -{ - debug("%s(dev=%p)\n", __func__, dev); - - return 0; -} - U_BOOT_DRIVER(tegra186_power_domain) = { .name = "tegra186_power_domain", .id = UCLASS_POWER_DOMAIN, - .probe = tegra186_power_domain_probe, .ops = &tegra186_power_domain_ops, }; diff --git a/drivers/power/domain/ti-power-domain.c b/drivers/power/domain/ti-power-domain.c index a7dadf2eea7..89e229b36f3 100644 --- a/drivers/power/domain/ti-power-domain.c +++ b/drivers/power/domain/ti-power-domain.c @@ -339,17 +339,6 @@ static int ti_power_domain_of_xlate(struct power_domain *pd,
return 0; } - -static int ti_power_domain_request(struct power_domain *pd) -{ - return 0; -} - -static int ti_power_domain_free(struct power_domain *pd) -{ - return 0; -} - static const struct udevice_id ti_power_domain_of_match[] = { { .compatible = "ti,sci-pm-domain" }, { /* sentinel */ } @@ -359,8 +348,6 @@ static struct power_domain_ops ti_power_domain_ops = { .on = ti_power_domain_on, .off = ti_power_domain_off, .of_xlate = ti_power_domain_of_xlate, - .request = ti_power_domain_request, - .rfree = ti_power_domain_free, };
U_BOOT_DRIVER(ti_pm_domains) = { diff --git a/drivers/power/domain/ti-sci-power-domain.c b/drivers/power/domain/ti-sci-power-domain.c index f18e45617a1..0140e5e5217 100644 --- a/drivers/power/domain/ti-sci-power-domain.c +++ b/drivers/power/domain/ti-sci-power-domain.c @@ -44,18 +44,6 @@ static int ti_sci_power_domain_probe(struct udevice *dev) return 0; }
-static int ti_sci_power_domain_request(struct power_domain *pd) -{ - debug("%s(pd=%p)\n", __func__, pd); - return 0; -} - -static int ti_sci_power_domain_free(struct power_domain *pd) -{ - debug("%s(pd=%p)\n", __func__, pd); - return 0; -} - static int ti_sci_power_domain_on(struct power_domain *pd) { struct ti_sci_power_domain_data *data = dev_get_priv(pd->dev); @@ -123,8 +111,6 @@ static const struct udevice_id ti_sci_power_domain_of_match[] = { };
static struct power_domain_ops ti_sci_power_domain_ops = { - .request = ti_sci_power_domain_request, - .rfree = ti_sci_power_domain_free, .on = ti_sci_power_domain_on, .off = ti_sci_power_domain_off, .of_xlate = ti_sci_power_domain_of_xlate,

In case the power domain node structure is gpc@303a0000/pgc/power-domain@N, do not bind power domain driver to the 'pgc' node, but rather descend into it and only bind power domain drivers to power-domain@N subnodes. This way we do not waste one useless driver instance associated with 'pgc' node.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/power/domain/imx8m-power-domain.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index 6082ee6ff8c..ac7411f8327 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -73,6 +73,12 @@ static int imx8m_power_domain_bind(struct udevice *dev) /* Bind the subnode to this driver */ name = fdt_get_name(gd->fdt_blob, offset, NULL);
+ /* Descend into 'pgc' subnode */ + if (!strstr(name, "power-domain")) { + offset = fdt_first_subnode(gd->fdt_blob, offset); + name = fdt_get_name(gd->fdt_blob, offset, NULL); + } + ret = device_bind_with_driver_data(dev, dev->driver, name, dev->driver_data, offset_to_ofnode(offset),

In case the power domain node structure is gpc@303a0000/pgc/power-domain@N, do not bind power domain driver to the 'pgc' node, but rather descend into it and only bind power domain drivers to power-domain@N subnodes. This way we do not waste one useless driver instance associated with 'pgc' node. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

The arch/arm/include/asm/arch-imx8m/power-domain.h is not included anywhere except in drivers/power/domain/imx8m-power-domain.c, just inline the content and drop the header. No functional change.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- arch/arm/include/asm/arch-imx8m/power-domain.h | 15 --------------- drivers/power/domain/imx8m-power-domain.c | 7 ++++++- 2 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 arch/arm/include/asm/arch-imx8m/power-domain.h
diff --git a/arch/arm/include/asm/arch-imx8m/power-domain.h b/arch/arm/include/asm/arch-imx8m/power-domain.h deleted file mode 100644 index 7a833e564b5..00000000000 --- a/arch/arm/include/asm/arch-imx8m/power-domain.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright 2017 NXP - */ - -#ifndef _ASM_ARCH_IMX8M_POWER_DOMAIN_H -#define _ASM_ARCH_IMX8M_POWER_DOMAIN_H - -struct imx8m_power_domain_plat { - int resource_id; - int has_pd; - struct power_domain pd; -}; - -#endif diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index ac7411f8327..c32dbcc31ae 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -9,7 +9,6 @@ #include <power-domain-uclass.h> #include <asm/global_data.h> #include <asm/io.h> -#include <asm/arch/power-domain.h> #include <asm/mach-imx/sys_proto.h> #include <dm/device-internal.h> #include <dm/device.h> @@ -18,6 +17,12 @@
DECLARE_GLOBAL_DATA_PTR;
+struct imx8m_power_domain_plat { + int resource_id; + int has_pd; + struct power_domain pd; +}; + static int imx8m_power_domain_on(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev;

The arch/arm/include/asm/arch-imx8m/power-domain.h is not included anywhere except in drivers/power/domain/imx8m-power-domain.c, just inline the content and drop the header. No functional change. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

This driver is the only SMCCC dependency in iMX8M U-Boot port. Rework the driver based on Linux GPCv2 driver to directly control the GPCv2 block instead of using SMCCC calls. This way, U-Boot can operate the i.MX8M power domains without depending on anything else.
This is losely based on Linux GPCv2 driver. The GPU, VPU, MIPI power domains are not supported to save space, since they are not useful in the bootloader. The only domains kept are ones for HSIO, PCIe, USB.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/power/domain/Kconfig | 1 + drivers/power/domain/imx8m-power-domain.c | 379 ++++++++++++++++++++-- 2 files changed, 361 insertions(+), 19 deletions(-)
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 93d2599d83c..04fc0054323 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -35,6 +35,7 @@ config IMX8_POWER_DOMAIN config IMX8M_POWER_DOMAIN bool "Enable i.MX8M power domain driver" depends on POWER_DOMAIN && ARCH_IMX8M + select CLK help Enable support for manipulating NXP i.MX8M on-SoC power domains via requests to the ATF. diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index c32dbcc31ae..e2e41cf5fee 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> #include <malloc.h> #include <power-domain-uclass.h> @@ -12,52 +13,361 @@ #include <asm/mach-imx/sys_proto.h> #include <dm/device-internal.h> #include <dm/device.h> +#include <dm/device_compat.h> #include <imx_sip.h> -#include <linux/arm-smccc.h> +#include <linux/bitmap.h> +#include <wait_bit.h> + +#include <dt-bindings/power/imx8mm-power.h> +#include <dt-bindings/power/imx8mn-power.h> +#include <dt-bindings/power/imx8mq-power.h>
DECLARE_GLOBAL_DATA_PTR;
+#define GPC_PGC_CPU_MAPPING 0x0ec + +#define IMX8M_PCIE2_A53_DOMAIN BIT(15) +#define IMX8M_OTG2_A53_DOMAIN BIT(5) +#define IMX8M_OTG1_A53_DOMAIN BIT(4) +#define IMX8M_PCIE1_A53_DOMAIN BIT(3) + +#define IMX8MM_OTG2_A53_DOMAIN BIT(5) +#define IMX8MM_OTG1_A53_DOMAIN BIT(4) +#define IMX8MM_PCIE_A53_DOMAIN BIT(3) + +#define IMX8MN_OTG1_A53_DOMAIN BIT(4) +#define IMX8MN_MIPI_A53_DOMAIN BIT(2) + +#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 +#define GPC_PU_PGC_SW_PDN_REQ 0x104 + +#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) +#define IMX8M_OTG2_SW_Pxx_REQ BIT(3) +#define IMX8M_OTG1_SW_Pxx_REQ BIT(2) +#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) + +#define IMX8MM_OTG2_SW_Pxx_REQ BIT(3) +#define IMX8MM_OTG1_SW_Pxx_REQ BIT(2) +#define IMX8MM_PCIE_SW_Pxx_REQ BIT(1) + +#define IMX8MN_OTG1_SW_Pxx_REQ BIT(2) +#define IMX8MN_MIPI_SW_Pxx_REQ BIT(0) + +#define GPC_M4_PU_PDN_FLG 0x1bc + +#define GPC_PU_PWRHSK 0x1fc + +#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) +#define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6)) + +#define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23) +#define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5) + +/* + * The PGC offset values in Reference Manual + * (Rev. 1, 01/2018 and the older ones) GPC chapter's + * GPC_PGC memory map are incorrect, below offset + * values are from design RTL. + */ +#define IMX8M_PGC_PCIE1 17 +#define IMX8M_PGC_OTG1 18 +#define IMX8M_PGC_OTG2 19 +#define IMX8M_PGC_PCIE2 29 + +#define IMX8MM_PGC_PCIE 17 +#define IMX8MM_PGC_OTG1 18 +#define IMX8MM_PGC_OTG2 19 + +#define IMX8MN_PGC_OTG1 18 + +#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) +#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) + +#define GPC_PGC_CTRL_PCR BIT(0) + +struct imx_pgc_regs { + u16 map; + u16 pup; + u16 pdn; + u16 hsk; +}; + +struct imx_pgc_domain { + unsigned long pgc; + + const struct { + u32 pxx; + u32 map; + u32 hskreq; + u32 hskack; + } bits; + + const bool keep_clocks; +}; + +struct imx_pgc_domain_data { + const struct imx_pgc_domain *domains; + size_t domains_num; + const struct imx_pgc_regs *pgc_regs; +}; + struct imx8m_power_domain_plat { + struct power_domain pd; + const struct imx_pgc_domain *domain; + const struct imx_pgc_regs *regs; + struct clk_bulk clk; + void __iomem *base; int resource_id; int has_pd; - struct power_domain pd; };
+#if defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MQ) +static const struct imx_pgc_regs imx7_pgc_regs = { + .map = GPC_PGC_CPU_MAPPING, + .pup = GPC_PU_PGC_SW_PUP_REQ, + .pdn = GPC_PU_PGC_SW_PDN_REQ, + .hsk = GPC_PU_PWRHSK, +}; +#endif + +#ifdef CONFIG_IMX8MQ +static const struct imx_pgc_domain imx8m_pgc_domains[] = { + [IMX8M_POWER_DOMAIN_PCIE1] = { + .bits = { + .pxx = IMX8M_PCIE1_SW_Pxx_REQ, + .map = IMX8M_PCIE1_A53_DOMAIN, + }, + .pgc = BIT(IMX8M_PGC_PCIE1), + }, + + [IMX8M_POWER_DOMAIN_USB_OTG1] = { + .bits = { + .pxx = IMX8M_OTG1_SW_Pxx_REQ, + .map = IMX8M_OTG1_A53_DOMAIN, + }, + .pgc = BIT(IMX8M_PGC_OTG1), + }, + + [IMX8M_POWER_DOMAIN_USB_OTG2] = { + .bits = { + .pxx = IMX8M_OTG2_SW_Pxx_REQ, + .map = IMX8M_OTG2_A53_DOMAIN, + }, + .pgc = BIT(IMX8M_PGC_OTG2), + }, + + [IMX8M_POWER_DOMAIN_PCIE2] = { + .bits = { + .pxx = IMX8M_PCIE2_SW_Pxx_REQ, + .map = IMX8M_PCIE2_A53_DOMAIN, + }, + .pgc = BIT(IMX8M_PGC_PCIE2), + }, +}; + +static const struct imx_pgc_domain_data imx8m_pgc_domain_data = { + .domains = imx8m_pgc_domains, + .domains_num = ARRAY_SIZE(imx8m_pgc_domains), + .pgc_regs = &imx7_pgc_regs, +}; +#endif + +#ifdef CONFIG_IMX8MM +static const struct imx_pgc_domain imx8mm_pgc_domains[] = { + [IMX8MM_POWER_DOMAIN_HSIOMIX] = { + .bits = { + .pxx = 0, /* no power sequence control */ + .map = 0, /* no power sequence control */ + .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN, + .hskack = IMX8MM_HSIO_HSK_PWRDNACKN, + }, + .keep_clocks = true, + }, + + [IMX8MM_POWER_DOMAIN_PCIE] = { + .bits = { + .pxx = IMX8MM_PCIE_SW_Pxx_REQ, + .map = IMX8MM_PCIE_A53_DOMAIN, + }, + .pgc = BIT(IMX8MM_PGC_PCIE), + }, + + [IMX8MM_POWER_DOMAIN_OTG1] = { + .bits = { + .pxx = IMX8MM_OTG1_SW_Pxx_REQ, + .map = IMX8MM_OTG1_A53_DOMAIN, + }, + .pgc = BIT(IMX8MM_PGC_OTG1), + }, + + [IMX8MM_POWER_DOMAIN_OTG2] = { + .bits = { + .pxx = IMX8MM_OTG2_SW_Pxx_REQ, + .map = IMX8MM_OTG2_A53_DOMAIN, + }, + .pgc = BIT(IMX8MM_PGC_OTG2), + }, +}; + +static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = { + .domains = imx8mm_pgc_domains, + .domains_num = ARRAY_SIZE(imx8mm_pgc_domains), + .pgc_regs = &imx7_pgc_regs, +}; +#endif + +#ifdef CONFIG_IMX8MN +static const struct imx_pgc_domain imx8mn_pgc_domains[] = { + [IMX8MN_POWER_DOMAIN_HSIOMIX] = { + .bits = { + .pxx = 0, /* no power sequence control */ + .map = 0, /* no power sequence control */ + .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN, + .hskack = IMX8MN_HSIO_HSK_PWRDNACKN, + }, + .keep_clocks = true, + }, + + [IMX8MN_POWER_DOMAIN_OTG1] = { + .bits = { + .pxx = IMX8MN_OTG1_SW_Pxx_REQ, + .map = IMX8MN_OTG1_A53_DOMAIN, + }, + .pgc = BIT(IMX8MN_PGC_OTG1), + }, +}; + +static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = { + .domains = imx8mn_pgc_domains, + .domains_num = ARRAY_SIZE(imx8mn_pgc_domains), + .pgc_regs = &imx7_pgc_regs, +}; +#endif + static int imx8m_power_domain_on(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev; - struct imx8m_power_domain_plat *pdata; + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); + const struct imx_pgc_domain *domain = pdata->domain; + const struct imx_pgc_regs *regs = pdata->regs; + void __iomem *base = pdata->base; + u32 pgc; + int ret; + + if (pdata->clk.count) { + ret = clk_enable_bulk(&pdata->clk); + if (ret) { + dev_err(dev, "failed to enable reset clocks\n"); + return ret; + } + }
- pdata = dev_get_plat(dev); + if (domain->bits.pxx) { + /* request the domain to power up */ + setbits_le32(base + regs->pup, domain->bits.pxx);
- if (pdata->resource_id < 0) - return -EINVAL; + /* + * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait + * for PUP_REQ/PDN_REQ bit to be cleared + */ + ret = wait_for_bit_le32(base + regs->pup, domain->bits.pxx, + false, 1000, false); + if (ret) { + dev_err(dev, "failed to command PGC\n"); + goto out_clk_disable; + }
- if (pdata->has_pd) - power_domain_on(&pdata->pd); + /* disable power control */ + for_each_set_bit(pgc, &domain->pgc, 32) { + clrbits_le32(base + GPC_PGC_CTRL(pgc), + GPC_PGC_CTRL_PCR); + } + } + + /* delay for reset to propagate */ + udelay(5);
- arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, - pdata->resource_id, 1, 0, 0, 0, 0, NULL); + /* request the ADB400 to power up */ + if (domain->bits.hskreq) + setbits_le32(base + regs->hsk, domain->bits.hskreq); + + /* Disable reset clocks for all devices in the domain */ + if (!domain->keep_clocks && pdata->clk.count) + clk_disable_bulk(&pdata->clk);
return 0; + +out_clk_disable: + if (pdata->clk.count) + clk_disable_bulk(&pdata->clk); + return ret; }
static int imx8m_power_domain_off(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev; - struct imx8m_power_domain_plat *pdata; - pdata = dev_get_plat(dev); + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); + const struct imx_pgc_domain *domain = pdata->domain; + const struct imx_pgc_regs *regs = pdata->regs; + void __iomem *base = pdata->base; + u32 pgc; + int ret;
- if (pdata->resource_id < 0) - return -EINVAL; + /* Enable reset clocks for all devices in the domain */ + if (!domain->keep_clocks && pdata->clk.count) { + ret = clk_enable_bulk(&pdata->clk); + if (ret) + return ret; + }
- arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, - pdata->resource_id, 0, 0, 0, 0, 0, NULL); + /* request the ADB400 to power down */ + if (domain->bits.hskreq) { + clrbits_le32(base + regs->hsk, domain->bits.hskreq); + + ret = wait_for_bit_le32(base + regs->hsk, domain->bits.hskack, + false, 1000, false); + if (ret) { + dev_err(dev, "failed to power down ADB400\n"); + goto out_clk_disable; + } + } + + if (domain->bits.pxx) { + /* enable power control */ + for_each_set_bit(pgc, &domain->pgc, 32) { + setbits_le32(base + GPC_PGC_CTRL(pgc), + GPC_PGC_CTRL_PCR); + } + + /* request the domain to power down */ + setbits_le32(base + regs->pdn, domain->bits.pxx); + + /* + * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait + * for PUP_REQ/PDN_REQ bit to be cleared + */ + ret = wait_for_bit_le32(base + regs->pdn, domain->bits.pxx, + false, 1000, false); + if (ret) { + dev_err(dev, "failed to command PGC\n"); + goto out_clk_disable; + } + } + + /* Disable reset clocks for all devices in the domain */ + if (pdata->clk.count) + clk_disable_bulk(&pdata->clk);
if (pdata->has_pd) power_domain_off(&pdata->pd);
return 0; + +out_clk_disable: + if (!domain->keep_clocks && pdata->clk.count) + clk_disable_bulk(&pdata->clk); + + return ret; }
static int imx8m_power_domain_of_xlate(struct power_domain *power_domain, @@ -101,12 +411,36 @@ static int imx8m_power_domain_bind(struct udevice *dev) return 0; }
+static int imx8m_power_domain_probe(struct udevice *dev) +{ + struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); + int ret; + + /* Nothing to do for non-"power-domain" driver instances. */ + if (!strstr(dev->name, "power-domain")) + return 0; + + /* Grab optional power domain clock. */ + ret = clk_get_bulk(dev, &pdata->clk); + if (ret && ret != -ENOENT) { + dev_err(dev, "Failed to get domain clock (%d)\n", ret); + return ret; + } + + return 0; +} + static int imx8m_power_domain_of_to_plat(struct udevice *dev) { struct imx8m_power_domain_plat *pdata = dev_get_plat(dev); + struct imx_pgc_domain_data *domain_data = + (struct imx_pgc_domain_data *)dev_get_driver_data(dev);
pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1); + pdata->domain = &domain_data->domains[pdata->resource_id]; + pdata->regs = domain_data->pgc_regs; + pdata->base = dev_read_addr_ptr(dev->parent);
if (!power_domain_get(dev, &pdata->pd)) pdata->has_pd = 1; @@ -115,9 +449,15 @@ static int imx8m_power_domain_of_to_plat(struct udevice *dev) }
static const struct udevice_id imx8m_power_domain_ids[] = { - { .compatible = "fsl,imx8mq-gpc" }, - { .compatible = "fsl,imx8mm-gpc" }, - { .compatible = "fsl,imx8mn-gpc" }, +#ifdef CONFIG_IMX8MQ + { .compatible = "fsl,imx8mq-gpc", .data = (long)&imx8m_pgc_domain_data }, +#endif +#ifdef CONFIG_IMX8MM + { .compatible = "fsl,imx8mm-gpc", .data = (long)&imx8mm_pgc_domain_data }, +#endif +#ifdef CONFIG_IMX8MN + { .compatible = "fsl,imx8mn-gpc", .data = (long)&imx8mn_pgc_domain_data }, +#endif { } };
@@ -132,6 +472,7 @@ U_BOOT_DRIVER(imx8m_power_domain) = { .id = UCLASS_POWER_DOMAIN, .of_match = imx8m_power_domain_ids, .bind = imx8m_power_domain_bind, + .probe = imx8m_power_domain_probe, .of_to_plat = imx8m_power_domain_of_to_plat, .plat_auto = sizeof(struct imx8m_power_domain_plat), .ops = &imx8m_power_domain_ops,

This driver is the only SMCCC dependency in iMX8M U-Boot port. Rework the driver based on Linux GPCv2 driver to directly control the GPCv2 block instead of using SMCCC calls. This way, U-Boot can operate the i.MX8M power domains without depending on anything else. This is losely based on Linux GPCv2 driver. The GPU, VPU, MIPI power domains are not supported to save space, since they are not useful in the bootloader. The only domains kept are ones for HSIO, PCIe, USB. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-defconfig Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Implement power_domain_get_by_name() convenience function which parses DT property 'power-domain-names' and looks up power domain by matching name.
Signed-off-by: Marek Vasut marex@denx.de Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org --- V2: Skipped to align the Vx scheme V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/power/domain/power-domain-uclass.c | 14 ++++++++++++++ include/power-domain.h | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+)
diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c index 0c5823ceddf..74c33d4e2e0 100644 --- a/drivers/power/domain/power-domain-uclass.c +++ b/drivers/power/domain/power-domain-uclass.c @@ -80,6 +80,20 @@ int power_domain_get_by_index(struct udevice *dev, return 0; }
+int power_domain_get_by_name(struct udevice *dev, + struct power_domain *power_domain, const char *name) +{ + int index; + + index = dev_read_stringlist_search(dev, "power-domain-names", name); + if (index < 0) { + debug("fdt_stringlist_search() failed: %d\n", index); + return index; + } + + return power_domain_get_by_index(dev, power_domain, index); +} + int power_domain_get(struct udevice *dev, struct power_domain *power_domain) { return power_domain_get_by_index(dev, power_domain, 0); diff --git a/include/power-domain.h b/include/power-domain.h index 113276b5119..2ff6c77cd76 100644 --- a/include/power-domain.h +++ b/include/power-domain.h @@ -107,6 +107,27 @@ int power_domain_get_by_index(struct udevice *dev, } #endif
+/** + * power_domain_get_by_name - Get the named power domain for a device. + * + * @dev: The client device. + * @power_domain: A pointer to a power domain struct to initialize. + * @name: Power domain name to be powered on. + * + * Return: 0 if OK, or a negative error code. + */ +#if CONFIG_IS_ENABLED(POWER_DOMAIN) +int power_domain_get_by_name(struct udevice *dev, + struct power_domain *power_domain, const char *name); +#else +static inline +int power_domain_get_by_name(struct udevice *dev, + struct power_domain *power_domain, const char *name) +{ + return -ENOSYS; +} +#endif + /** * power_domain_free - Free a previously requested power domain. *

Implement power_domain_get_by_name() convenience function which parses DT property 'power-domain-names' and looks up power domain by matching name. Signed-off-by: Marek Vasut marex@denx.de Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Add i.MX8MP power domain handling into the driver. This is based on the Linux GPCv2 driver state which is soon to be in Linux next.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/power/domain/imx8m-power-domain.c | 79 +++++++++++++++++++++++ include/dt-bindings/power/imx8mp-power.h | 46 +++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 include/dt-bindings/power/imx8mp-power.h
diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c index e2e41cf5fee..145f6ec0cd3 100644 --- a/drivers/power/domain/imx8m-power-domain.c +++ b/drivers/power/domain/imx8m-power-domain.c @@ -20,11 +20,13 @@
#include <dt-bindings/power/imx8mm-power.h> #include <dt-bindings/power/imx8mn-power.h> +#include <dt-bindings/power/imx8mp-power.h> #include <dt-bindings/power/imx8mq-power.h>
DECLARE_GLOBAL_DATA_PTR;
#define GPC_PGC_CPU_MAPPING 0x0ec +#define IMX8MP_GPC_PGC_CPU_MAPPING 0x1cc
#define IMX8M_PCIE2_A53_DOMAIN BIT(15) #define IMX8M_OTG2_A53_DOMAIN BIT(5) @@ -38,6 +40,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMX8MN_OTG1_A53_DOMAIN BIT(4) #define IMX8MN_MIPI_A53_DOMAIN BIT(2)
+#define IMX8MP_HSIOMIX_A53_DOMAIN BIT(19) +#define IMX8MP_USB2_PHY_A53_DOMAIN BIT(5) +#define IMX8MP_USB1_PHY_A53_DOMAIN BIT(4) +#define IMX8MP_PCIE_PHY_A53_DOMAIN BIT(3) + +#define IMX8MP_GPC_PU_PGC_SW_PUP_REQ 0x0d8 +#define IMX8MP_GPC_PU_PGC_SW_PDN_REQ 0x0e4 + #define GPC_PU_PGC_SW_PUP_REQ 0x0f8 #define GPC_PU_PGC_SW_PDN_REQ 0x104
@@ -53,8 +63,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMX8MN_OTG1_SW_Pxx_REQ BIT(2) #define IMX8MN_MIPI_SW_Pxx_REQ BIT(0)
+#define IMX8MP_HSIOMIX_Pxx_REQ BIT(17) +#define IMX8MP_USB2_PHY_Pxx_REQ BIT(3) +#define IMX8MP_USB1_PHY_Pxx_REQ BIT(2) +#define IMX8MP_PCIE_PHY_SW_Pxx_REQ BIT(1) + #define GPC_M4_PU_PDN_FLG 0x1bc
+#define IMX8MP_GPC_PU_PWRHSK 0x190 #define GPC_PU_PWRHSK 0x1fc
#define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24)) @@ -63,6 +79,9 @@ DECLARE_GLOBAL_DATA_PTR; #define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23) #define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5)
+#define IMX8MP_HSIOMIX_PWRDNACKN BIT(28) +#define IMX8MP_HSIOMIX_PWRDNREQN BIT(12) + /* * The PGC offset values in Reference Manual * (Rev. 1, 01/2018 and the older ones) GPC chapter's @@ -80,6 +99,11 @@ DECLARE_GLOBAL_DATA_PTR;
#define IMX8MN_PGC_OTG1 18
+#define IMX8MP_PGC_PCIE 13 +#define IMX8MP_PGC_USB1 14 +#define IMX8MP_PGC_USB2 15 +#define IMX8MP_PGC_HSIOMIX 29 + #define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) #define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
@@ -244,6 +268,58 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = { }; #endif
+#ifdef CONFIG_IMX8MP +static const struct imx_pgc_domain imx8mp_pgc_domains[] = { + [IMX8MP_POWER_DOMAIN_PCIE_PHY] = { + .bits = { + .pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ, + .map = IMX8MP_PCIE_PHY_A53_DOMAIN, + }, + .pgc = BIT(IMX8MP_PGC_PCIE), + }, + + [IMX8MP_POWER_DOMAIN_USB1_PHY] = { + .bits = { + .pxx = IMX8MP_USB1_PHY_Pxx_REQ, + .map = IMX8MP_USB1_PHY_A53_DOMAIN, + }, + .pgc = BIT(IMX8MP_PGC_USB1), + }, + + [IMX8MP_POWER_DOMAIN_USB2_PHY] = { + .bits = { + .pxx = IMX8MP_USB2_PHY_Pxx_REQ, + .map = IMX8MP_USB2_PHY_A53_DOMAIN, + }, + .pgc = BIT(IMX8MP_PGC_USB2), + }, + + [IMX8MP_POWER_DOMAIN_HSIOMIX] = { + .bits = { + .pxx = IMX8MP_HSIOMIX_Pxx_REQ, + .map = IMX8MP_HSIOMIX_A53_DOMAIN, + .hskreq = IMX8MP_HSIOMIX_PWRDNREQN, + .hskack = IMX8MP_HSIOMIX_PWRDNACKN, + }, + .pgc = BIT(IMX8MP_PGC_HSIOMIX), + .keep_clocks = true, + }, +}; + +static const struct imx_pgc_regs imx8mp_pgc_regs = { + .map = IMX8MP_GPC_PGC_CPU_MAPPING, + .pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ, + .pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ, + .hsk = IMX8MP_GPC_PU_PWRHSK, +}; + +static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = { + .domains = imx8mp_pgc_domains, + .domains_num = ARRAY_SIZE(imx8mp_pgc_domains), + .pgc_regs = &imx8mp_pgc_regs, +}; +#endif + static int imx8m_power_domain_on(struct power_domain *power_domain) { struct udevice *dev = power_domain->dev; @@ -457,6 +533,9 @@ static const struct udevice_id imx8m_power_domain_ids[] = { #endif #ifdef CONFIG_IMX8MN { .compatible = "fsl,imx8mn-gpc", .data = (long)&imx8mn_pgc_domain_data }, +#endif +#ifdef CONFIG_IMX8MP + { .compatible = "fsl,imx8mp-gpc", .data = (long)&imx8mp_pgc_domain_data }, #endif { } }; diff --git a/include/dt-bindings/power/imx8mp-power.h b/include/dt-bindings/power/imx8mp-power.h new file mode 100644 index 00000000000..3f72bf7818f --- /dev/null +++ b/include/dt-bindings/power/imx8mp-power.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ +/* + * Copyright (C) 2020 Pengutronix, Sascha Hauer kernel@pengutronix.de + */ + +#ifndef __DT_BINDINGS_IMX8MP_POWER_DOMAIN_POWER_H__ +#define __DT_BINDINGS_IMX8MP_POWER_DOMAIN_POWER_H__ + +#define IMX8MP_POWER_DOMAIN_MIPI_PHY1 0 +#define IMX8MP_POWER_DOMAIN_PCIE_PHY 1 +#define IMX8MP_POWER_DOMAIN_USB1_PHY 2 +#define IMX8MP_POWER_DOMAIN_USB2_PHY 3 +#define IMX8MP_POWER_DOMAIN_MLMIX 4 +#define IMX8MP_POWER_DOMAIN_AUDIOMIX 5 +#define IMX8MP_POWER_DOMAIN_GPU2D 6 +#define IMX8MP_POWER_DOMAIN_GPUMIX 7 +#define IMX8MP_POWER_DOMAIN_VPUMIX 8 +#define IMX8MP_POWER_DOMAIN_GPU3D 9 +#define IMX8MP_POWER_DOMAIN_MEDIAMIX 10 +#define IMX8MP_POWER_DOMAIN_VPU_G1 11 +#define IMX8MP_POWER_DOMAIN_VPU_G2 12 +#define IMX8MP_POWER_DOMAIN_VPU_VC8000E 13 +#define IMX8MP_POWER_DOMAIN_HDMIMIX 14 +#define IMX8MP_POWER_DOMAIN_HDMI_PHY 15 +#define IMX8MP_POWER_DOMAIN_MIPI_PHY2 16 +#define IMX8MP_POWER_DOMAIN_HSIOMIX 17 +#define IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP 18 + +#define IMX8MP_HSIOBLK_PD_USB 0 +#define IMX8MP_HSIOBLK_PD_USB_PHY1 1 +#define IMX8MP_HSIOBLK_PD_USB_PHY2 2 +#define IMX8MP_HSIOBLK_PD_PCIE 3 +#define IMX8MP_HSIOBLK_PD_PCIE_PHY 4 + +#define IMX8MP_MEDIABLK_PD_MIPI_DSI_1 0 +#define IMX8MP_MEDIABLK_PD_MIPI_CSI2_1 1 +#define IMX8MP_MEDIABLK_PD_LCDIF_1 2 +#define IMX8MP_MEDIABLK_PD_ISI 3 +#define IMX8MP_MEDIABLK_PD_MIPI_CSI2_2 4 +#define IMX8MP_MEDIABLK_PD_LCDIF_2 5 +#define IMX8MP_MEDIABLK_PD_ISP2 6 +#define IMX8MP_MEDIABLK_PD_ISP1 7 +#define IMX8MP_MEDIABLK_PD_DWE 8 +#define IMX8MP_MEDIABLK_PD_MIPI_DSI_2 9 + +#endif

Add i.MX8MP power domain handling into the driver. This is based on the Linux GPCv2 driver state which is soon to be in Linux next. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Add trivial driver for i.MX8MP HSIOMIX handling. This is responsible for enabling the GPCv2 power domains and clock for USB 3.0 and PCIe in the correct order. Currently supported is the USB 3.0 part which can be tested, PCIe support should be easy to add.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Drop two left over unused variables which triggered build warning V3: Add TB from Tim V4: Rebase on u-boot-imx/master --- drivers/power/domain/Kconfig | 7 ++ drivers/power/domain/Makefile | 1 + drivers/power/domain/imx8mp-hsiomix.c | 159 ++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 drivers/power/domain/imx8mp-hsiomix.c
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 04fc0054323..7e1b8c072fa 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -40,6 +40,13 @@ config IMX8M_POWER_DOMAIN Enable support for manipulating NXP i.MX8M on-SoC power domains via requests to the ATF.
+config IMX8MP_HSIOMIX_BLKCTRL + bool "Enable i.MX8MP HSIOMIX domain driver" + depends on POWER_DOMAIN && IMX8MP + select CLK + help + Enable support for manipulating NXP i.MX8MP on-SoC HSIOMIX block controller. + config MTK_POWER_DOMAIN bool "Enable the MediaTek power domain driver" depends on POWER_DOMAIN && ARCH_MEDIATEK diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 7c8af67dbd6..e6244776216 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_APPLE_PMGR_POWER_DOMAIN) += apple-pmgr.o obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain-legacy.o imx8-power-domain.o obj-$(CONFIG_IMX8M_POWER_DOMAIN) += imx8m-power-domain.o +obj-$(CONFIG_IMX8MP_HSIOMIX_BLKCTRL) += imx8mp-hsiomix.o obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o diff --git a/drivers/power/domain/imx8mp-hsiomix.c b/drivers/power/domain/imx8mp-hsiomix.c new file mode 100644 index 00000000000..6a721a934a7 --- /dev/null +++ b/drivers/power/domain/imx8mp-hsiomix.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Marek Vasut marex@denx.de + */ + +#include <common.h> +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <power-domain-uclass.h> + +#include <dt-bindings/power/imx8mp-power.h> + +#define GPR_REG0 0x0 +#define PCIE_CLOCK_MODULE_EN BIT(0) +#define USB_CLOCK_MODULE_EN BIT(1) + +struct imx8mp_hsiomix_priv { + void __iomem *base; + struct clk clk_usb; + struct power_domain pd_bus; + struct power_domain pd_usb; + struct power_domain pd_usb_phy1; + struct power_domain pd_usb_phy2; +}; + +static int imx8mp_hsiomix_on(struct power_domain *power_domain) +{ + struct udevice *dev = power_domain->dev; + struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); + struct power_domain *domain; + int ret; + + ret = power_domain_on(&priv->pd_bus); + if (ret) + return ret; + + if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) { + domain = &priv->pd_usb; + } else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY1) { + domain = &priv->pd_usb_phy1; + } else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY2) { + domain = &priv->pd_usb_phy2; + } else { + ret = -EINVAL; + goto err_pd; + } + + ret = power_domain_on(domain); + if (ret) + goto err_pd; + + ret = clk_enable(&priv->clk_usb); + if (ret) + goto err_clk; + + if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) + setbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN); + + return 0; + +err_clk: + power_domain_off(domain); +err_pd: + power_domain_off(&priv->pd_bus); + return ret; +} + +static int imx8mp_hsiomix_off(struct power_domain *power_domain) +{ + struct udevice *dev = power_domain->dev; + struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); + + if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) + clrbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN); + + clk_disable(&priv->clk_usb); + + if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) + power_domain_off(&priv->pd_usb); + else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY1) + power_domain_off(&priv->pd_usb_phy1); + else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY2) + power_domain_off(&priv->pd_usb_phy2); + + power_domain_off(&priv->pd_bus); + + return 0; +} + +static int imx8mp_hsiomix_of_xlate(struct power_domain *power_domain, + struct ofnode_phandle_args *args) +{ + power_domain->id = args->args[0]; + + return 0; +} + +static int imx8mp_hsiomix_probe(struct udevice *dev) +{ + struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); + int ret; + + priv->base = dev_read_addr_ptr(dev); + + ret = clk_get_by_name(dev, "usb", &priv->clk_usb); + if (ret < 0) + return ret; + + ret = power_domain_get_by_name(dev, &priv->pd_bus, "bus"); + if (ret < 0) + goto err_pd_bus; + + ret = power_domain_get_by_name(dev, &priv->pd_usb, "usb"); + if (ret < 0) + goto err_pd_usb; + + ret = power_domain_get_by_name(dev, &priv->pd_usb_phy1, "usb-phy1"); + if (ret < 0) + goto err_pd_usb_phy1; + + ret = power_domain_get_by_name(dev, &priv->pd_usb_phy2, "usb-phy2"); + if (ret < 0) + goto err_pd_usb_phy2; + + return 0; + +err_pd_usb_phy2: + power_domain_free(&priv->pd_usb_phy1); +err_pd_usb_phy1: + power_domain_free(&priv->pd_usb); +err_pd_usb: + power_domain_free(&priv->pd_bus); +err_pd_bus: + clk_free(&priv->clk_usb); + return ret; +} + +static const struct udevice_id imx8mp_hsiomix_ids[] = { + { .compatible = "fsl,imx8mp-hsio-blk-ctrl" }, + { } +}; + +struct power_domain_ops imx8mp_hsiomix_ops = { + .on = imx8mp_hsiomix_on, + .off = imx8mp_hsiomix_off, + .of_xlate = imx8mp_hsiomix_of_xlate, +}; + +U_BOOT_DRIVER(imx8mp_hsiomix) = { + .name = "imx8mp_hsiomix", + .id = UCLASS_POWER_DOMAIN, + .of_match = imx8mp_hsiomix_ids, + .probe = imx8mp_hsiomix_probe, + .priv_auto = sizeof(struct imx8mp_hsiomix_priv), + .ops = &imx8mp_hsiomix_ops, +};

Add trivial driver for i.MX8MP HSIOMIX handling. This is responsible for enabling the GPCv2 power domains and clock for USB 3.0 and PCIe in the correct order. Currently supported is the USB 3.0 part which can be tested, PCIe support should be easy to add. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Rename the select_dr_mode callback to glue_configure, the callback is used for more than enforcing controller mode even on the TI chips, so change the name to a more generic one. No functional change.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Angus Ainslie angus@akkea.ca Cc: Bin Meng bmeng.cn@gmail.com Cc: Fabio Estevam festevam@gmail.com Cc: Kunihiko Hayashi hayashi.kunihiko@socionext.com Cc: Michal Simek michal.simek@xilinx.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/usb/dwc3/dwc3-generic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 01bd0ca190e..7e3814207e4 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -219,11 +219,11 @@ U_BOOT_DRIVER(dwc3_generic_host) = { #endif
struct dwc3_glue_ops { - void (*select_dr_mode)(struct udevice *dev, int index, + void (*glue_configure)(struct udevice *dev, int index, enum usb_dr_mode mode); };
-void dwc3_ti_select_dr_mode(struct udevice *dev, int index, +void dwc3_ti_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { #define USBOTGSS_UTMI_OTG_STATUS 0x0084 @@ -304,7 +304,7 @@ enum dwc3_omap_utmi_mode { }
struct dwc3_glue_ops ti_ops = { - .select_dr_mode = dwc3_ti_select_dr_mode, + .glue_configure = dwc3_ti_glue_configure, };
static int dwc3_glue_bind(struct udevice *parent) @@ -435,8 +435,8 @@ static int dwc3_glue_probe(struct udevice *dev)
dr_mode = usb_get_dr_mode(dev_ofnode(child)); device_find_next_child(&child); - if (ops && ops->select_dr_mode) - ops->select_dr_mode(dev, index, dr_mode); + if (ops && ops->glue_configure) + ops->glue_configure(dev, index, dr_mode); index++; }

Rename the select_dr_mode callback to glue_configure, the callback is used for more than enforcing controller mode even on the TI chips, so change the name to a more generic one. No functional change. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Angus Ainslie angus@akkea.ca Cc: Bin Meng bmeng.cn@gmail.com Cc: Fabio Estevam festevam@gmail.com Cc: Kunihiko Hayashi hayashi.kunihiko@socionext.com Cc: Michal Simek michal.simek@xilinx.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

The i.MX8MP glue needs to be configured based on a couple of DT properties, implement .glue_configure callback to parse those DT properties and configure the glue accordingly.
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Angus Ainslie angus@akkea.ca Cc: Bin Meng bmeng.cn@gmail.com Cc: Fabio Estevam festevam@gmail.com Cc: Kunihiko Hayashi hayashi.kunihiko@socionext.com Cc: Michal Simek michal.simek@xilinx.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- drivers/usb/dwc3/dwc3-generic.c | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 7e3814207e4..6cf844cb483 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -223,6 +223,57 @@ struct dwc3_glue_ops { enum usb_dr_mode mode); };
+void dwc3_imx8mp_glue_configure(struct udevice *dev, int index, + enum usb_dr_mode mode) +{ +/* USB glue registers */ +#define USB_CTRL0 0x00 +#define USB_CTRL1 0x04 + +#define USB_CTRL0_PORTPWR_EN BIT(12) /* 1 - PPC enabled (default) */ +#define USB_CTRL0_USB3_FIXED BIT(22) /* 1 - USB3 permanent attached */ +#define USB_CTRL0_USB2_FIXED BIT(23) /* 1 - USB2 permanent attached */ + +#define USB_CTRL1_OC_POLARITY BIT(16) /* 0 - HIGH / 1 - LOW */ +#define USB_CTRL1_PWR_POLARITY BIT(17) /* 0 - HIGH / 1 - LOW */ + fdt_addr_t regs = dev_read_addr_index(dev, 1); + void *base = map_physmem(regs, 0x8, MAP_NOCACHE); + u32 value; + + value = readl(base + USB_CTRL0); + + if (dev_read_bool(dev, "fsl,permanently-attached")) + value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED); + else + value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED); + + if (dev_read_bool(dev, "fsl,disable-port-power-control")) + value &= ~(USB_CTRL0_PORTPWR_EN); + else + value |= USB_CTRL0_PORTPWR_EN; + + writel(value, base + USB_CTRL0); + + value = readl(base + USB_CTRL1); + if (dev_read_bool(dev, "fsl,over-current-active-low")) + value |= USB_CTRL1_OC_POLARITY; + else + value &= ~USB_CTRL1_OC_POLARITY; + + if (dev_read_bool(dev, "fsl,power-active-low")) + value |= USB_CTRL1_PWR_POLARITY; + else + value &= ~USB_CTRL1_PWR_POLARITY; + + writel(value, base + USB_CTRL1); + + unmap_physmem(base, MAP_NOCACHE); +} + +struct dwc3_glue_ops imx8mp_ops = { + .glue_configure = dwc3_imx8mp_glue_configure, +}; + void dwc3_ti_glue_configure(struct udevice *dev, int index, enum usb_dr_mode mode) { @@ -464,6 +515,7 @@ static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "rockchip,rk3328-dwc3" }, { .compatible = "rockchip,rk3399-dwc3" }, { .compatible = "qcom,dwc3" }, + { .compatible = "fsl,imx8mp-dwc3", .data = (ulong)&imx8mp_ops }, { .compatible = "fsl,imx8mq-dwc3" }, { .compatible = "intel,tangier-dwc3" }, { }

The i.MX8MP glue needs to be configured based on a couple of DT properties, implement .glue_configure callback to parse those DT properties and configure the glue accordingly. Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Angus Ainslie angus@akkea.ca Cc: Bin Meng bmeng.cn@gmail.com Cc: Fabio Estevam festevam@gmail.com Cc: Kunihiko Hayashi hayashi.kunihiko@socionext.com Cc: Michal Simek michal.simek@xilinx.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Add DT bindings for a subset of GPCv2 which handles USB and PCIe PDs, HSIOMIX PD controller and missing USB PD properties. This is required to bring up the DWC3 USB controller up.
This is based on linux next and patches which are still pending review, but which are likely going to be part of Linux 5.19: b2d67d7bdf74 ("arm64: dts: imx8mp: disable usb3_phy1") 290918c72a29 ("arm64: dts: imx8mp: Add memory for USB3 glue layer to usb3 nodes") https://www.spinics.net/lists/arm-kernel/msg958501.html
Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de --- V2: Add TB by Tim V3: Skipped to align the Vx scheme V4: Rebase on u-boot-imx/master --- arch/arm/dts/imx8mp.dtsi | 72 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/arch/arm/dts/imx8mp.dtsi b/arch/arm/dts/imx8mp.dtsi index f9d64253c8a..79b65750da9 100644 --- a/arch/arm/dts/imx8mp.dtsi +++ b/arch/arm/dts/imx8mp.dtsi @@ -4,6 +4,7 @@ */
#include <dt-bindings/clock/imx8mp-clock.h> +#include <dt-bindings/power/imx8mp-power.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> @@ -434,6 +435,44 @@ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; #reset-cells = <1>; }; + + gpc: gpc@303a0000 { + compatible = "fsl,imx8mp-gpc"; + reg = <0x303a0000 0x1000>; + interrupt-parent = <&gic>; + interrupt-controller; + #interrupt-cells = <3>; + + pgc { + #address-cells = <1>; + #size-cells = <0>; + + pgc_pcie_phy: power-domain@1 { + #power-domain-cells = <0>; + reg = <IMX8MP_POWER_DOMAIN_PCIE_PHY>; + }; + + pgc_usb1_phy: power-domain@2 { + #power-domain-cells = <0>; + reg = <IMX8MP_POWER_DOMAIN_USB1_PHY>; + }; + + pgc_usb2_phy: power-domain@3 { + #power-domain-cells = <0>; + reg = <IMX8MP_POWER_DOMAIN_USB2_PHY>; + }; + + pgc_hsiomix: power-domains@17 { + #power-domain-cells = <0>; + reg = <IMX8MP_POWER_DOMAIN_HSIOMIX>; + clocks = <&clk IMX8MP_CLK_HSIO_AXI>, + <&clk IMX8MP_CLK_HSIO_ROOT>; + assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>; + assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>; + assigned-clock-rates = <500000000>; + }; + }; + }; };
aips2: bus@30400000 { @@ -842,6 +881,28 @@ }; };
+ aips4: bus@32c00000 { + compatible = "fsl,aips-bus", "simple-bus"; + reg = <0x32c00000 0x400000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + hsio_blk_ctrl: blk-ctrl@32f10000 { + compatible = "fsl,imx8mp-hsio-blk-ctrl", "syscon"; + reg = <0x32f10000 0x24>; + clocks = <&clk IMX8MP_CLK_USB_ROOT>, + <&clk IMX8MP_CLK_PCIE_ROOT>; + clock-names = "usb", "pcie"; + power-domains = <&pgc_hsiomix>, <&pgc_hsiomix>, + <&pgc_usb1_phy>, <&pgc_usb2_phy>, + <&pgc_hsiomix>, <&pgc_pcie_phy>; + power-domain-names = "bus", "usb", "usb-phy1", + "usb-phy2", "pcie", "pcie-phy"; + #power-domain-cells = <1>; + }; + }; + gic: interrupt-controller@38800000 { compatible = "arm,gic-v3"; reg = <0x38800000 0x10000>, @@ -865,17 +926,20 @@ clock-names = "phy"; assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>; assigned-clock-parents = <&clk IMX8MP_CLK_24M>; + power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY1>; #phy-cells = <0>; status = "disabled"; };
usb3_0: usb@32f10100 { compatible = "fsl,imx8mp-dwc3"; - reg = <0x32f10100 0x8>; + reg = <0x32f10100 0x8>, + <0x381f0000 0x20>; clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, <&clk IMX8MP_CLK_USB_ROOT>; clock-names = "hsio", "suspend"; interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>; #address-cells = <1>; #size-cells = <1>; dma-ranges = <0x40000000 0x40000000 0xc0000000>; @@ -907,16 +971,20 @@ clock-names = "phy"; assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>; assigned-clock-parents = <&clk IMX8MP_CLK_24M>; + power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY2>; #phy-cells = <0>; + status = "disabled"; };
usb3_1: usb@32f10108 { compatible = "fsl,imx8mp-dwc3"; - reg = <0x32f10108 0x8>; + reg = <0x32f10108 0x8>, + <0x382f0000 0x20>; clocks = <&clk IMX8MP_CLK_HSIO_ROOT>, <&clk IMX8MP_CLK_USB_ROOT>; clock-names = "hsio", "suspend"; interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>; + power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>; #address-cells = <1>; #size-cells = <1>; dma-ranges = <0x40000000 0x40000000 0xc0000000>;

Add DT bindings for a subset of GPCv2 which handles USB and PCIe PDs, HSIOMIX PD controller and missing USB PD properties. This is required to bring up the DWC3 USB controller up. This is based on linux next and patches which are still pending review, but which are likely going to be part of Linux 5.19: b2d67d7bdf74 ("arm64: dts: imx8mp: disable usb3_phy1") 290918c72a29 ("arm64: dts: imx8mp: Add memory for USB3 glue layer to usb3 nodes") https://www.spinics.net/lists/arm-kernel/msg958501.html Tested-By: Tim Harvey tharvey@gateworks.com #imx8mp-venice-gw74xx Signed-off-by: Marek Vasut marex@denx.de Cc: Fabio Estevam festevam@gmail.com Cc: Peng Fan peng.fan@nxp.com Cc: Stefano Babic sbabic@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

In case the ops is not implemented, return 0 in the core right away. This is better than having multiple copies of functions which just return 0 in each power domain driver. Drop all those empty functions. Signed-off-by: Marek Vasut marex@denx.de Cc: Patrick Delaunay patrick.delaunay@foss.st.com Cc: Simon Glass sjg@chromium.org
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic
participants (2)
-
Marek Vasut
-
sbabic@denx.de