* [PATCH 01/19] drivers: soc: split off powerdomains into new pmdomain directory
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 02/19] pmdomain: use single implementation for dev_pm_domain_attach Ahmad Fatoum
` (18 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Linux v6.6 has moved the pmdomain drivers from drivers/soc to
drivers/pmdomain. Follow its lead in barebox too.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/Kconfig | 1 +
drivers/Makefile | 1 +
drivers/pmdomain/Kconfig | 7 +++++++
drivers/pmdomain/Makefile | 3 +++
drivers/pmdomain/imx/Kconfig | 10 ++++++++++
drivers/pmdomain/imx/Makefile | 2 ++
drivers/{soc => pmdomain}/imx/gpcv2.c | 0
drivers/{soc => pmdomain}/ti/Kconfig | 1 +
drivers/{soc => pmdomain}/ti/Makefile | 1 +
drivers/{soc => pmdomain}/ti/ti_sci_pm_domains.c | 0
drivers/soc/Kconfig | 1 -
drivers/soc/Makefile | 1 -
drivers/soc/imx/Kconfig | 6 ------
drivers/soc/imx/Makefile | 1 -
14 files changed, 26 insertions(+), 9 deletions(-)
create mode 100644 drivers/pmdomain/Kconfig
create mode 100644 drivers/pmdomain/Makefile
create mode 100644 drivers/pmdomain/imx/Kconfig
create mode 100644 drivers/pmdomain/imx/Makefile
rename drivers/{soc => pmdomain}/imx/gpcv2.c (100%)
rename drivers/{soc => pmdomain}/ti/Kconfig (84%)
rename drivers/{soc => pmdomain}/ti/Makefile (57%)
rename drivers/{soc => pmdomain}/ti/ti_sci_pm_domains.c (100%)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b81ee38989e8..04da623aa519 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -42,6 +42,7 @@ source "drivers/phy/Kconfig"
source "drivers/crypto/Kconfig"
source "drivers/memory/Kconfig"
source "drivers/soc/Kconfig"
+source "drivers/pmdomain/Kconfig"
source "drivers/nvme/Kconfig"
source "drivers/ddr/Kconfig"
source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 42a71f73c259..fd85ac91b266 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -42,6 +42,7 @@ obj-y += crypto/
obj-$(CONFIG_AIODEV) += aiodev/
obj-y += memory/
obj-y += soc/
+obj-$(CONFIG_PM_GENERIC_DOMAINS) += pmdomain/
obj-y += nvme/
obj-y += ddr/
obj-y += power/
diff --git a/drivers/pmdomain/Kconfig b/drivers/pmdomain/Kconfig
new file mode 100644
index 000000000000..82095ae078c8
--- /dev/null
+++ b/drivers/pmdomain/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "PM Domains"
+
+source "drivers/pmdomain/imx/Kconfig"
+source "drivers/pmdomain/ti/Kconfig"
+
+endmenu
diff --git a/drivers/pmdomain/Makefile b/drivers/pmdomain/Makefile
new file mode 100644
index 000000000000..25983a67e12f
--- /dev/null
+++ b/drivers/pmdomain/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += imx/
+obj-y += ti/
diff --git a/drivers/pmdomain/imx/Kconfig b/drivers/pmdomain/imx/Kconfig
new file mode 100644
index 000000000000..ba5fffd274fa
--- /dev/null
+++ b/drivers/pmdomain/imx/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "i.MX PM Domains"
+
+config IMX_GPCV2_PM_DOMAINS
+ bool "i.MX GPCv2 PM domains"
+ depends on ARCH_IMX7 || ARCH_IMX8M
+ select PM_GENERIC_DOMAINS
+ default y if ARCH_IMX7 || ARCH_IMX8M
+
+endmenu
diff --git a/drivers/pmdomain/imx/Makefile b/drivers/pmdomain/imx/Makefile
new file mode 100644
index 000000000000..3a8a8d0b00db
--- /dev/null
+++ b/drivers/pmdomain/imx/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
similarity index 100%
rename from drivers/soc/imx/gpcv2.c
rename to drivers/pmdomain/imx/gpcv2.c
diff --git a/drivers/soc/ti/Kconfig b/drivers/pmdomain/ti/Kconfig
similarity index 84%
rename from drivers/soc/ti/Kconfig
rename to drivers/pmdomain/ti/Kconfig
index dc1ec3efb7e3..f34a5146c133 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/pmdomain/ti/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
config TI_SCI_PM_DOMAINS
bool "TI SCI PM Domains Driver"
depends on TI_SCI_PROTOCOL
diff --git a/drivers/soc/ti/Makefile b/drivers/pmdomain/ti/Makefile
similarity index 57%
rename from drivers/soc/ti/Makefile
rename to drivers/pmdomain/ti/Makefile
index f87420e41402..ab582e04a8b3 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/pmdomain/ti/Makefile
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/pmdomain/ti/ti_sci_pm_domains.c
similarity index 100%
rename from drivers/soc/ti/ti_sci_pm_domains.c
rename to drivers/pmdomain/ti/ti_sci_pm_domains.c
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cbde3c35a411..c0fe21442917 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -3,6 +3,5 @@ menu "SoC drivers"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/kvx/Kconfig"
source "drivers/soc/rockchip/Kconfig"
-source "drivers/soc/ti/Kconfig"
endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 75ae4382ff77..9bff737b78c4 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -5,4 +5,3 @@ obj-$(CONFIG_KVX) += kvx/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_CPU_SIFIVE) += sifive/
obj-$(CONFIG_SOC_STARFIVE) += starfive/
-obj-y += ti/
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index 57f5577acec8..333a134d3f9f 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -1,12 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "i.MX SoC drivers"
-config IMX_GPCV2_PM_DOMAINS
- bool "i.MX GPCv2 PM domains"
- depends on ARCH_IMX7 || ARCH_IMX8M
- select PM_GENERIC_DOMAINS
- default y if ARCH_IMX7 || ARCH_IMX8M
-
config IMX8M_FEATCTRL
bool "i.MX8M feature controller"
depends on ARCH_IMX8M
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index bd1717b03883..54d8002a588c 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
obj-$(CONFIG_IMX8M_FEATCTRL) += imx8m-featctrl.o
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 02/19] pmdomain: use single implementation for dev_pm_domain_attach
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 01/19] drivers: soc: split off powerdomains into new pmdomain directory Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 03/19] pmdomain: power: drop unused parameters for internal functions Ahmad Fatoum
` (17 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
genpd_dev_pm_attach already has a stub definition when
!CONFIG_PM_GENERIC_DOMAINS, so we can just call it unconditionally
from dev_pm_domain_attach.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/pm_domain.h | 53 ++++++++++++++++++++-------------------------
1 file changed, 24 insertions(+), 29 deletions(-)
diff --git a/include/pm_domain.h b/include/pm_domain.h
index ac0ec477b6b1..bf122460d0fe 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -30,30 +30,6 @@ void genpd_activate(void);
int genpd_dev_pm_attach(struct device *dev);
-/**
- * dev_pm_domain_attach - Attach a device to its PM domain.
- * @dev: Device to attach.
- * @power_on: Used to indicate whether we should power on the device.
- *
- * The @dev may only be attached to a single PM domain. By iterating through
- * the available alternatives we try to find a valid PM domain for the device.
- * As attachment succeeds, the ->detach() callback in the struct dev_pm_domain
- * should be assigned by the corresponding attach function.
- *
- * This function should typically be invoked from subsystem level code during
- * the probe phase. Especially for those that holds devices which requires
- * power management through PM domains.
- *
- * Callers must ensure proper synchronization of this function with power
- * management callbacks.
- *
- * Returns 0 on successfully attached PM domain or negative error code.
- */
-static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
-{
- return genpd_dev_pm_attach(dev);
-}
-
int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
int of_genpd_add_provider_simple(struct device_node *np,
@@ -87,11 +63,6 @@ static inline int genpd_dev_pm_attach(struct device *dev)
return 0;
}
-static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
-{
- return 0;
-}
-
static inline int
of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
@@ -101,4 +72,28 @@ of_genpd_add_provider_simple(struct device_node *np,
#endif
+/**
+ * dev_pm_domain_attach - Attach a device to its PM domain.
+ * @dev: Device to attach.
+ * @power_on: Used to indicate whether we should power on the device.
+ *
+ * The @dev may only be attached to a single PM domain. By iterating through
+ * the available alternatives we try to find a valid PM domain for the device.
+ * As attachment succeeds, the ->detach() callback in the struct dev_pm_domain
+ * should be assigned by the corresponding attach function.
+ *
+ * This function should typically be invoked from subsystem level code during
+ * the probe phase. Especially for those that holds devices which requires
+ * power management through PM domains.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns 0 on successfully attached PM domain or negative error code.
+ */
+static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
+{
+ return genpd_dev_pm_attach(dev);
+}
+
#endif
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 03/19] pmdomain: power: drop unused parameters for internal functions
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 01/19] drivers: soc: split off powerdomains into new pmdomain directory Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 02/19] pmdomain: use single implementation for dev_pm_domain_attach Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 04/19] pmdomain: associate devices with their power domain Ahmad Fatoum
` (16 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We don't do latency measurements for power domain operations in barebox,
so the timed parameter to indicate whether time measurements should be
done or not is unused. We also don't need locking for the powerdomains,
so maintaining the depth for lockdep is also unnecessary.
Drop both unused function parameters as we are not likely to ever use
them.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 699af3e5a942..e927d0f83ff0 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -249,7 +249,7 @@ static struct generic_pm_domain *genpd_get_from_provider(
return genpd;
}
-static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
+static int _genpd_power_on(struct generic_pm_domain *genpd)
{
if (!genpd->power_on)
return 0;
@@ -260,19 +260,18 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
/**
* genpd_power_on - Restore power to a given PM domain and its masters.
* @genpd: PM domain to power up.
- * @depth: nesting count for lockdep.
*
* Restore power to @genpd and all of its masters so that it is possible to
* resume a device belonging to it.
*/
-static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
+static int genpd_power_on(struct generic_pm_domain *genpd)
{
int ret;
if (!genpd || genpd_status_on(genpd))
return 0;
- ret = _genpd_power_on(genpd, true);
+ ret = _genpd_power_on(genpd);
if (ret)
return ret;
@@ -308,7 +307,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
dev_dbg(dev, "adding to PM domain %s\n", pd ? pd->name : "dummy");
if (power_on)
- ret = genpd_power_on(pd, 0);
+ ret = genpd_power_on(pd);
return ret ?: 1;
}
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 04/19] pmdomain: associate devices with their power domain
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (2 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 03/19] pmdomain: power: drop unused parameters for internal functions Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 05/19] pmdomain: push have_genpd_providers check into __genpd_dev_pm_attach Ahmad Fatoum
` (15 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
In Linux, there is no public consumer API to enable or disable
a struct generic_pm_domain. Operations are instead performed on regular
struct device, each of which has a reference to a single attached
power domain.
Power domain consumer API in barebox was so far limited to automatically
attaching a single power domain and powering it on prior to function probe,
which is never detached and thus no further consumer API is needed.
To support more complex power domain setups, we adopt here the kernel API
of attaching power domains to devices to enable using struct device
as handles for additional power domain operations.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 26 +++++++++++++++++++++++++-
include/driver.h | 3 +++
include/pm_domain.h | 4 ++++
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index e927d0f83ff0..4ff7b055c825 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -10,6 +10,14 @@
static LIST_HEAD(gpd_list);
+static inline struct generic_pm_domain *dev_to_genpd(struct device *dev)
+{
+ if (IS_ERR_OR_NULL(dev->pm_domain))
+ return ERR_PTR(-EINVAL);
+
+ return dev->pm_domain;
+}
+
/**
* pm_genpd_init - Initialize a generic I/O PM domain object.
* @genpd: PM domain object to initialize.
@@ -280,6 +288,17 @@ static int genpd_power_on(struct generic_pm_domain *genpd)
return 0;
}
+static void genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
+{
+ dev->pm_domain = genpd;
+}
+
+static void genpd_remove_device(struct generic_pm_domain *genpd,
+ struct device *dev)
+{
+ dev->pm_domain = NULL;
+}
+
static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
unsigned int index, bool power_on)
{
@@ -306,8 +325,13 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
dev_dbg(dev, "adding to PM domain %s\n", pd ? pd->name : "dummy");
- if (power_on)
+ genpd_add_device(pd, dev);
+
+ if (power_on) {
ret = genpd_power_on(pd);
+ if (ret < 0)
+ genpd_remove_device(pd, dev);
+ }
return ret ?: 1;
}
diff --git a/include/driver.h b/include/driver.h
index 43d002f66dbe..7dfa565b8960 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -19,6 +19,7 @@
struct filep;
struct bus_type;
+struct generic_pm_domain;
struct platform_device_id {
const char *name;
@@ -75,6 +76,8 @@ struct device {
struct device *parent; /* our parent, NULL if not present */
+ struct generic_pm_domain *pm_domain; /* attached power domain */
+
struct bus_type *bus;
/*! The parameters for this device. This is used to carry information
diff --git a/include/pm_domain.h b/include/pm_domain.h
index bf122460d0fe..59932ffee0b9 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -4,6 +4,7 @@
#define _PM_DOMAIN_H
#include <linux/list.h>
+#include <driver.h>
#include <of.h>
enum gpd_status {
@@ -93,6 +94,9 @@ of_genpd_add_provider_simple(struct device_node *np,
*/
static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
{
+ if (dev->pm_domain)
+ return 0;
+
return genpd_dev_pm_attach(dev);
}
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 05/19] pmdomain: push have_genpd_providers check into __genpd_dev_pm_attach
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (3 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 04/19] pmdomain: associate devices with their power domain Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 06/19] pmdomain: drop superfluous parameter to __genpd_dev_pm_attach Ahmad Fatoum
` (14 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
genpd_activate() makes power domains opt-in per platform by considering
power domain attachment a success until gepd_activate() is called the
first time. We currently do that in genpd_dev_pm_attach(), but a follow
up commit will introduce more callers for __genpd_dev_pm_attach, which
likewise should have the same behavior regarding genpd_activate().
Thus push the check into __genpd_dev_pm_attach().
No function change.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 4ff7b055c825..cfee5e793037 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -299,6 +299,13 @@ static void genpd_remove_device(struct generic_pm_domain *genpd,
dev->pm_domain = NULL;
}
+static bool have_genpd_providers;
+
+void genpd_activate(void)
+{
+ have_genpd_providers = true;
+}
+
static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
unsigned int index, bool power_on)
{
@@ -306,6 +313,9 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
struct generic_pm_domain *pd;
int ret;
+ if (!have_genpd_providers)
+ return 0;
+
ret = of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", index, &pd_args);
if (ret < 0)
@@ -336,13 +346,6 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
return ret ?: 1;
}
-static bool have_genpd_providers;
-
-void genpd_activate(void)
-{
- have_genpd_providers = true;
-}
-
/**
* genpd_dev_pm_attach - Attach a device to its PM domain using DT.
* @dev: Device to attach.
@@ -361,9 +364,6 @@ int genpd_dev_pm_attach(struct device *dev)
if (!dev->of_node)
return 0;
- if (!have_genpd_providers)
- return 0;
-
/*
* Devices with multiple PM domains must be attached separately, as we
* can only attach one PM domain per device.
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 06/19] pmdomain: drop superfluous parameter to __genpd_dev_pm_attach
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (4 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 05/19] pmdomain: push have_genpd_providers check into __genpd_dev_pm_attach Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 07/19] pmdomain: implement dev_pm_domain_attach_by_id/name Ahmad Fatoum
` (13 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The Linux prototype of __genpd_dev_pm_attach has the base device as
second argument and retrieves the of_node pointer via the device in the
first argument. As the function isn't exported, we don't have to follow
the Linux API, but we also don't need to keep arguments we don't use,
thus drop the device pointer.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index cfee5e793037..daec443a7000 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -306,7 +306,7 @@ void genpd_activate(void)
have_genpd_providers = true;
}
-static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
+static int __genpd_dev_pm_attach(struct device *dev,
unsigned int index, bool power_on)
{
struct of_phandle_args pd_args;
@@ -316,7 +316,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
if (!have_genpd_providers)
return 0;
- ret = of_parse_phandle_with_args(np, "power-domains",
+ ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
"#power-domain-cells", index, &pd_args);
if (ret < 0)
return ret;
@@ -372,7 +372,7 @@ int genpd_dev_pm_attach(struct device *dev)
"#power-domain-cells") != 1)
return 0;
- return __genpd_dev_pm_attach(dev, dev->of_node, 0, true);
+ return __genpd_dev_pm_attach(dev, 0, true);
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 07/19] pmdomain: implement dev_pm_domain_attach_by_id/name
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (5 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 06/19] pmdomain: drop superfluous parameter to __genpd_dev_pm_attach Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:25 ` [PATCH 08/19] pmdomain: add support for enabling power domains later on Ahmad Fatoum
` (12 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
In Linux, dev_pm_domain_attach() enables a device's sole power domain,
but dev_pm_domain_attach_by_id/name(), attaches the power domain to a
virtual device and returns it for use with runtime PM API.
Import these two functions into barebox, so drivers can use them to
implement more elaborate power up sequences. The power up operation
itself follows in a follow-up commit.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 106 +++++++++++++++++++++++++++++++++++++++++++
include/pm_domain.h | 68 +++++++++++++++++++++++++++
2 files changed, 174 insertions(+)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index daec443a7000..98164431aaeb 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -2,6 +2,7 @@
#include <common.h>
#include <driver.h>
#include <errno.h>
+#include <linux/device.h>
#include <of.h>
#include <pm_domain.h>
@@ -306,6 +307,16 @@ void genpd_activate(void)
have_genpd_providers = true;
}
+static struct bus_type genpd_bus_type = {
+ .name = "genpd",
+};
+
+static int __init genpd_bus_init(void)
+{
+ return bus_register(&genpd_bus_type);
+}
+core_initcall(genpd_bus_init);
+
static int __genpd_dev_pm_attach(struct device *dev,
unsigned int index, bool power_on)
{
@@ -376,6 +387,101 @@ int genpd_dev_pm_attach(struct device *dev)
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+/**
+ * dev_pm_domain_attach_by_id - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @index: The index of the PM domain.
+ *
+ * As @dev may only be attached to a single PM domain, the backend PM domain
+ * provider creates a virtual device to attach instead. If attachment succeeds,
+ * the ->detach() callback in the struct dev_pm_domain are assigned by the
+ * corresponding backend attach function, as to deal with detaching of the
+ * created virtual device.
+ *
+ * This function should typically be invoked by a driver during the probe phase,
+ * in case its device requires power management through multiple PM domains. The
+ * driver may benefit from using the received device, to configure device-links
+ * towards its original device. Depending on the use-case and if needed, the
+ * links may be dynamically changed by the driver, which allows it to control
+ * the power to the PM domains independently from each other.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the virtual created device when successfully attached to its PM
+ * domain, NULL in case @dev don't need a PM domain, else an ERR_PTR().
+ * Note that, to detach the returned virtual device, the driver shall call
+ * dev_pm_domain_detach() on it, typically during the remove phase.
+ */
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ struct device *virt_dev;
+ int num_domains;
+ int ret;
+
+ if (!dev->of_node)
+ return NULL;
+
+ /* Verify that the index is within a valid range. */
+ num_domains = of_count_phandle_with_args(dev->of_node, "power-domains",
+ "#power-domain-cells");
+ if (index >= num_domains)
+ return NULL;
+
+ /* Allocate and register device on the genpd bus. */
+ virt_dev = kzalloc(sizeof(*virt_dev), GFP_KERNEL);
+ if (!virt_dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev_set_name(virt_dev, "genpd");
+ virt_dev->bus = &genpd_bus_type;
+ virt_dev->parent = dev;
+ virt_dev->of_node = dev->of_node;
+ virt_dev->id = index;
+
+ ret = device_register(virt_dev);
+ if (ret) {
+ kfree(dev);
+ return ERR_PTR(ret);
+ }
+
+ /* Try to attach the device to the PM domain at the specified index. */
+ ret = __genpd_dev_pm_attach(virt_dev, index, false);
+ if (ret < 1) {
+ device_unregister(virt_dev);
+ return ret ? ERR_PTR(ret) : NULL;
+ }
+
+ return virt_dev;
+}
+EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_id);
+
+/**
+ * genpd_dev_pm_attach_by_name - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @name: The name of the PM domain.
+ *
+ * Parse device's OF node to find a PM domain specifier using the
+ * power-domain-names DT property. For further description see
+ * genpd_dev_pm_attach_by_id().
+ */
+struct device *genpd_dev_pm_attach_by_name(struct device *dev, const char *name)
+{
+ int index;
+
+ if (!dev->of_node)
+ return NULL;
+
+ index = of_property_match_string(dev->of_node, "power-domain-names",
+ name);
+ if (index < 0)
+ return NULL;
+
+ return genpd_dev_pm_attach_by_id(dev, index);
+}
+EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_name);
+
void pm_genpd_print(void)
{
struct generic_pm_domain *genpd;
diff --git a/include/pm_domain.h b/include/pm_domain.h
index 59932ffee0b9..b02af0d46de0 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -31,6 +31,11 @@ void genpd_activate(void);
int genpd_dev_pm_attach(struct device *dev);
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index);
+struct device *genpd_dev_pm_attach_by_name(struct device *dev,
+ const char *name);
+
int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
int of_genpd_add_provider_simple(struct device_node *np,
@@ -64,6 +69,18 @@ static inline int genpd_dev_pm_attach(struct device *dev)
return 0;
}
+static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ return NULL;
+}
+
+static inline struct device *genpd_dev_pm_attach_by_name(struct device *dev,
+ const char *name)
+{
+ return NULL;
+}
+
static inline int
of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
@@ -100,4 +117,55 @@ static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
return genpd_dev_pm_attach(dev);
}
+/**
+ * dev_pm_domain_attach_by_id - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @index: The index of the PM domain.
+ *
+ * As @dev may only be attached to a single PM domain, the backend PM domain
+ * provider creates a virtual device to attach instead. If attachment succeeds,
+ * the ->detach() callback in the struct dev_pm_domain are assigned by the
+ * corresponding backend attach function, as to deal with detaching of the
+ * created virtual device.
+ *
+ * This function should typically be invoked by a driver during the probe phase,
+ * in case its device requires power management through multiple PM domains. The
+ * driver may benefit from using the received device, to configure device-links
+ * towards its original device. Depending on the use-case and if needed, the
+ * links may be dynamically changed by the driver, which allows it to control
+ * the power to the PM domains independently from each other.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the virtual created device when successfully attached to its PM
+ * domain, NULL in case @dev don't need a PM domain, else an ERR_PTR().
+ * Note that, to detach the returned virtual device, the driver shall call
+ * dev_pm_domain_detach() on it, typically during the remove phase.
+ */
+static inline struct device *dev_pm_domain_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ if (dev->pm_domain)
+ return ERR_PTR(-EEXIST);
+
+ return genpd_dev_pm_attach_by_id(dev, index);
+}
+
+/**
+ * dev_pm_domain_attach_by_name - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @name: The name of the PM domain.
+ *
+ * For a detailed function description, see dev_pm_domain_attach_by_id().
+ */
+static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
+ const char *name)
+{
+ if (dev->pm_domain)
+ return ERR_PTR(-EEXIST);
+
+ return genpd_dev_pm_attach_by_name(dev, name);
+}
+
#endif
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 08/19] pmdomain: add support for enabling power domains later on
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (6 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 07/19] pmdomain: implement dev_pm_domain_attach_by_id/name Ahmad Fatoum
@ 2024-01-19 16:25 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 09/19] pmdomain: imx: gpcv2: enable COMPILE_TEST build Ahmad Fatoum
` (11 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:25 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
When a single power domain is specified platform driver probe takes care
to enable the power domain. When there are multiple power domains
however, each Linux driver must itself enable power domains in the
correct sequence.
In Linux, this is handled by runtime PM. We don't have that in barebox,
so we add the enable function with a _genpd suffix to alert users to
this fact.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 11 +++++++++++
include/pm_domain.h | 8 +++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 98164431aaeb..c4318fa1dfd1 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -289,6 +289,17 @@ static int genpd_power_on(struct generic_pm_domain *genpd)
return 0;
}
+int pm_runtime_resume_and_get_genpd(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ genpd = dev_to_genpd(dev);
+ if (IS_ERR(genpd))
+ return PTR_ERR(genpd);
+
+ return genpd_power_on(genpd);
+}
+
static void genpd_add_device(struct generic_pm_domain *genpd, struct device *dev)
{
dev->pm_domain = genpd;
diff --git a/include/pm_domain.h b/include/pm_domain.h
index b02af0d46de0..f242a05b4934 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -30,12 +30,13 @@ typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
void genpd_activate(void);
int genpd_dev_pm_attach(struct device *dev);
-
struct device *genpd_dev_pm_attach_by_id(struct device *dev,
unsigned int index);
struct device *genpd_dev_pm_attach_by_name(struct device *dev,
const char *name);
+int pm_runtime_resume_and_get_genpd(struct device *dev);
+
int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
int of_genpd_add_provider_simple(struct device_node *np,
@@ -81,6 +82,11 @@ static inline struct device *genpd_dev_pm_attach_by_name(struct device *dev,
return NULL;
}
+static inline int pm_runtime_resume_and_get_genpd(struct device *dev)
+{
+ return 0;
+}
+
static inline int
of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 09/19] pmdomain: imx: gpcv2: enable COMPILE_TEST build
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (7 preceding siblings ...)
2024-01-19 16:25 ` [PATCH 08/19] pmdomain: add support for enabling power domains later on Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 10/19] pmdomain: add stub definition for dev_pm_domain_detach Ahmad Fatoum
` (10 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
While the driver is only useful for i.MX7 and 8M, it can be compiled for
other platforms as well, so add COMPILE_TEST as alternative dependency.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/pmdomain/imx/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pmdomain/imx/Kconfig b/drivers/pmdomain/imx/Kconfig
index ba5fffd274fa..c0d767eb8f3c 100644
--- a/drivers/pmdomain/imx/Kconfig
+++ b/drivers/pmdomain/imx/Kconfig
@@ -3,7 +3,7 @@ menu "i.MX PM Domains"
config IMX_GPCV2_PM_DOMAINS
bool "i.MX GPCv2 PM domains"
- depends on ARCH_IMX7 || ARCH_IMX8M
+ depends on ARCH_IMX7 || ARCH_IMX8M || COMPILE_TEST
select PM_GENERIC_DOMAINS
default y if ARCH_IMX7 || ARCH_IMX8M
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 10/19] pmdomain: add stub definition for dev_pm_domain_detach
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (8 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 09/19] pmdomain: imx: gpcv2: enable COMPILE_TEST build Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 11/19] pmdomain: add stub definition for pm_runtime_put_genpd Ahmad Fatoum
` (9 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Detaching a power domain frees the virtual device if any was allocated
and may power down the domain if no users remain.
We don't do reference counting for users and don't mind power domains
remaining enables as the kernel will enable unused power domains on its
own anyway. Thus implement dev_pm_domain_detach() as empty stub.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/pm_domain.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/pm_domain.h b/include/pm_domain.h
index f242a05b4934..118770023150 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -174,4 +174,10 @@ static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
return genpd_dev_pm_attach_by_name(dev, name);
}
+static inline void dev_pm_domain_detach(struct device *dev, bool power_off)
+{
+ /* Just keep power domain enabled until dev_pm_domain_attach*
+ * start doing reference counting
+ */
+}
#endif
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 11/19] pmdomain: add stub definition for pm_runtime_put_genpd
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (9 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 10/19] pmdomain: add stub definition for dev_pm_domain_detach Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 12/19] pmdomain: implement pm_genpd_remove/of_genpd_del_provider for cleanup Ahmad Fatoum
` (8 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Putting a runtime PM reference will send a device into runtime suspend
once no users remain.
We don't do reference counting for users and don't mind power domains
remaining enabled as the kernel will enable unused power domains on its
own anyway. Thus implement pm_runtime_put_genpd() as empty stub.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/pm_domain.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/pm_domain.h b/include/pm_domain.h
index 118770023150..1fa7f0bdbd3e 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -180,4 +180,11 @@ static inline void dev_pm_domain_detach(struct device *dev, bool power_off)
* start doing reference counting
*/
}
+
+static inline void pm_runtime_put_genpd(struct device *dev)
+{
+ /* Just keep power domain enabled until pm_runtime_resume_and_get_genpd
+ * starts doing reference counting
+ */
+}
#endif
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 12/19] pmdomain: implement pm_genpd_remove/of_genpd_del_provider for cleanup
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (10 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 11/19] pmdomain: add stub definition for pm_runtime_put_genpd Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 13/19] driver: have dev_request_mem_region_err_null warn if resource starts at 0 Ahmad Fatoum
` (7 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We already have pm_genpd_init/of_genpd_add_provider, but lack functions
to deregister them. Port the deregisteration functions over from Linux.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/power.c | 31 +++++++++++++++++++++++++++++++
include/pm_domain.h | 13 +++++++++++++
2 files changed, 44 insertions(+)
diff --git a/drivers/base/power.c b/drivers/base/power.c
index c4318fa1dfd1..f7629f554a72 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -40,6 +40,19 @@ int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off)
}
EXPORT_SYMBOL_GPL(pm_genpd_init);
+int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+ if (IS_ERR_OR_NULL(genpd))
+ return -EINVAL;
+
+ list_del(&genpd->gpd_list_node);
+
+ pr_debug("%s: removed %s\n", __func__, genpd->name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm_genpd_remove);
+
/**
* struct of_genpd_provider - PM domain provider registration structure
* @link: Entry in global list of PM domain providers
@@ -209,6 +222,24 @@ int of_genpd_add_provider_onecell(struct device_node *np,
}
EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
+/**
+ * of_genpd_del_provider() - Remove a previously registered PM domain provider
+ * @np: Device node pointer associated with the PM domain provider
+ */
+void of_genpd_del_provider(struct device_node *np)
+{
+ struct of_genpd_provider *cp, *tmp;
+
+ list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) {
+ if (cp->node == np) {
+ list_del(&cp->link);
+ kfree(cp);
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(of_genpd_del_provider);
+
/**
* genpd_get_from_provider() - Look-up PM domain
* @genpdspec: OF phandle args to use for look-up
diff --git a/include/pm_domain.h b/include/pm_domain.h
index 1fa7f0bdbd3e..f637eb1afa9d 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -39,6 +39,8 @@ int pm_runtime_resume_and_get_genpd(struct device *dev);
int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
+int pm_genpd_remove(struct generic_pm_domain *genpd);
+
int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd);
@@ -51,6 +53,8 @@ struct genpd_onecell_data {
int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data);
+void of_genpd_del_provider(struct device_node *np);
+
void pm_genpd_print(void);
#else
@@ -65,6 +69,11 @@ static inline int pm_genpd_init(struct generic_pm_domain *genpd,
return -ENOSYS;
}
+static inline int pm_genpd_remove(struct generic_pm_domain *genpd);
+{
+ return -EOPNOTSUPP;
+}
+
static inline int genpd_dev_pm_attach(struct device *dev)
{
return 0;
@@ -94,6 +103,10 @@ of_genpd_add_provider_simple(struct device_node *np,
return -ENOTSUPP;
}
+static inline void of_genpd_del_provider(struct device_node *np)
+{
+}
+
#endif
/**
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 13/19] driver: have dev_request_mem_region_err_null warn if resource starts at 0
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (11 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 12/19] pmdomain: implement pm_genpd_remove/of_genpd_del_provider for cleanup Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 14/19] include: linux/device.h: implement dev_platform_ioremap_resource Ahmad Fatoum
` (6 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
dev_request_mem_region_err_null() is used very scarcely, because it
doesn't allow differentiating between NULL and a MMIO region at address 0.
Using it in the latter case is always a bug, so add a WARN_ON that warns
about this. This should make it safe to use at more places, which will
come in handy to implement Linux API that uses NULL as error value.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/base/driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 4f18f5bb8123..6548aec9b27b 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -541,7 +541,7 @@ void __iomem *dev_request_mem_region_err_null(struct device *dev, int num)
struct resource *res;
res = dev_request_mem_resource(dev, num);
- if (IS_ERR(res))
+ if (IS_ERR(res) || WARN_ON(!res->start))
return NULL;
return IOMEM(res->start);
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 14/19] include: linux/device.h: implement dev_platform_ioremap_resource
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (12 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 13/19] driver: have dev_request_mem_region_err_null warn if resource starts at 0 Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 15/19] regmap: include missing header from linux/regmap.h Ahmad Fatoum
` (5 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
There are more than a thousand instances of devm_platform_ioremap_resource
across Linux drivers and porting it to barebox is cumbersome, because
unlike Linux we don't remap, so the MMIO region may be at address zero.
Now that dev_request_mem_region_err_null() prints a warning in that
case, let's just use it to implement dev_platform_ioremap_resource().
Platforms with relevant MMIO at address 0 are scarce anyway and when we
run on such a platform, we can always switch to use normal
dev_request_mem_resource().
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/linux/device.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/include/linux/device.h b/include/linux/device.h
index 0bd61154ac30..d892a9cb0ef5 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -32,6 +32,18 @@
#define driver_register register_driver
#define driver_unregister unregister_driver
+
+static inline void __iomem *dev_platform_ioremap_resource(struct device *dev,
+ int resource)
+{
+ /*
+ * barebox maps everything outside the RAM banks suitably for MMIO,
+ * so we don't need to do anything besides requesting the regions
+ * and can leave the memory attributes unchanged.
+ */
+ return dev_request_mem_region_err_null(dev, resource);
+}
+
static inline void __iomem *devm_ioremap(struct device *dev,
resource_size_t start,
resource_size_t size)
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 15/19] regmap: include missing header from linux/regmap.h
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (13 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 14/19] include: linux/device.h: implement dev_platform_ioremap_resource Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 16/19] clk: define aliases for clk_bulk_prepare_enable/disable_unprepare Ahmad Fatoum
` (4 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The header defines regmap_read_poll_timeout, which requires
<linux/iopoll.h>, thus include the header.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/linux/regmap.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 9e38fbc12e16..3ba0f852f6eb 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -3,6 +3,7 @@
#define __LINUX_REGMAP_H
#include <linux/compiler.h>
+#include <linux/iopoll.h>
#include <linux/types.h>
enum regmap_endian {
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 16/19] clk: define aliases for clk_bulk_prepare_enable/disable_unprepare
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (14 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 15/19] regmap: include missing header from linux/regmap.h Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 17/19] driver: make driver.h header self-contained Ahmad Fatoum
` (3 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We don't have a separate atomic prepare/unprepare step for clocks in
barebox and instead combine it with enable/disable. We have macros to
alias prepare_enable/disable_unprepare for non-bulk API, so add the same
for the bulk API too.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/linux/clk.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b555e40ec459..1bdfb21d509e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -1019,6 +1019,9 @@ static inline void clk_bulk_disable(int num_clks,
#endif
+#define clk_bulk_prepare_enable clk_bulk_enable
+#define clk_bulk_disable_unprepare clk_bulk_disable
+
/**
* clk_get_optional - lookup and obtain a reference to an optional clock
* producer.
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 17/19] driver: make driver.h header self-contained
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (15 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 16/19] clk: define aliases for clk_bulk_prepare_enable/disable_unprepare Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 18/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (2 subsequent siblings)
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The header defines driver registration macros that expand to initcalls,
but doesn't include the definitions for the different initcall leavels.
Fix this to make the header self contained.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/driver.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/driver.h b/include/driver.h
index 7dfa565b8960..638426b9606a 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -11,6 +11,7 @@
#include <linux/uuid.h>
#include <linux/printk.h>
#include <of.h>
+#include <init.h>
#include <filetype.h>
#define FORMAT_DRIVER_NAME_ID "%s%d"
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 18/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (16 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 17/19] driver: make driver.h header self-contained Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-19 16:26 ` [PATCH 19/19] ARM: dts: i.MX8MP: drop barebox,allow-dummy for HSIO blk-ctrl Ahmad Fatoum
2024-01-22 10:12 ` [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Sascha Hauer
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Unlike other i.MX8M variants, TF-A on i.MX8MP enables all power domains
up front, so later software can keep reusing it.
This benefited us because we didn't have a driver for the HSIO blk-ctrl,
which powers the USB PHYs and controllers on the i.MX8MP.
However, not all i.MX8MP SKUs have all power domains, e.g. the lite
variant lacks VPUs, NPU, ISP and DSP and their associated power domains.
Removing power domains altogether in TF-A though would break USB in barebox
when not booted over SDP as neither BootROM or TF-A would enable the HSIO
blk-ctrl.
In order to decouple barebox from prior HSIO initialization, port over the
Linux driver.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/pmdomain/imx/Kconfig | 6 +
drivers/pmdomain/imx/Makefile | 1 +
drivers/pmdomain/imx/imx8mp-blk-ctrl.c | 459 +++++++++++++++++++++++++
3 files changed, 466 insertions(+)
create mode 100644 drivers/pmdomain/imx/imx8mp-blk-ctrl.c
diff --git a/drivers/pmdomain/imx/Kconfig b/drivers/pmdomain/imx/Kconfig
index c0d767eb8f3c..f611a69f78b2 100644
--- a/drivers/pmdomain/imx/Kconfig
+++ b/drivers/pmdomain/imx/Kconfig
@@ -7,4 +7,10 @@ config IMX_GPCV2_PM_DOMAINS
select PM_GENERIC_DOMAINS
default y if ARCH_IMX7 || ARCH_IMX8M
+config IMX8M_BLK_CTRL
+ bool "i.MX8MP HSIO blk-ctrl" if COMPILE_TEST
+ default ARCH_IMX8MP && IMX_GPCV2_PM_DOMAINS
+ depends on PM_GENERIC_DOMAINS
+ depends on COMMON_CLK
+
endmenu
diff --git a/drivers/pmdomain/imx/Makefile b/drivers/pmdomain/imx/Makefile
index 3a8a8d0b00db..1364944d5ac5 100644
--- a/drivers/pmdomain/imx/Makefile
+++ b/drivers/pmdomain/imx/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
new file mode 100644
index 000000000000..38de9d88a139
--- /dev/null
+++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
@@ -0,0 +1,459 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <of.h>
+#include <of_device.h>
+#include <linux/device.h>
+#include <pm_domain.h>
+#include <linux/regmap.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)
+#define PCIE_PHY_APB_RST BIT(4)
+#define PCIE_PHY_INIT_RST BIT(5)
+#define GPR_REG1 0x4
+#define PLL_LOCK BIT(13)
+#define GPR_REG2 0x8
+#define P_PLL_MASK GENMASK(5, 0)
+#define M_PLL_MASK GENMASK(15, 6)
+#define S_PLL_MASK GENMASK(18, 16)
+#define GPR_REG3 0xc
+#define PLL_CKE BIT(17)
+#define PLL_RST BIT(31)
+
+struct imx8mp_blk_ctrl_domain;
+
+struct imx8mp_blk_ctrl {
+ struct device *dev;
+ struct device *bus_power_dev;
+ struct regmap *regmap;
+ struct imx8mp_blk_ctrl_domain *domains;
+ struct genpd_onecell_data onecell_data;
+ void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+ void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+};
+
+struct imx8mp_blk_ctrl_domain_data {
+ const char *name;
+ const char * const *clk_names;
+ int num_clks;
+ const char *gpc_name;
+};
+
+#define DOMAIN_MAX_CLKS 2
+
+struct imx8mp_blk_ctrl_domain {
+ struct generic_pm_domain genpd;
+ const struct imx8mp_blk_ctrl_domain_data *data;
+ struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
+ struct device *power_dev;
+ struct imx8mp_blk_ctrl *bc;
+ int id;
+};
+
+struct imx8mp_blk_ctrl_data {
+ int max_reg;
+ int (*probe) (struct imx8mp_blk_ctrl *bc);
+ void (*power_off) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+ void (*power_on) (struct imx8mp_blk_ctrl *bc, struct imx8mp_blk_ctrl_domain *domain);
+ const struct imx8mp_blk_ctrl_domain_data *domains;
+ int num_domains;
+};
+
+static inline struct imx8mp_blk_ctrl_domain *
+to_imx8mp_blk_ctrl_domain(struct generic_pm_domain *genpd)
+{
+ return container_of(genpd, struct imx8mp_blk_ctrl_domain, genpd);
+}
+
+struct clk_hsio_pll {
+ struct clk_hw hw;
+ struct regmap *regmap;
+};
+
+static inline struct clk_hsio_pll *to_clk_hsio_pll(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_hsio_pll, hw);
+}
+
+static int clk_hsio_pll_prepare(struct clk_hw *hw)
+{
+ struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+ u32 val;
+
+ /* set the PLL configuration */
+ regmap_update_bits(clk->regmap, GPR_REG2,
+ P_PLL_MASK | M_PLL_MASK | S_PLL_MASK,
+ FIELD_PREP(P_PLL_MASK, 12) |
+ FIELD_PREP(M_PLL_MASK, 800) |
+ FIELD_PREP(S_PLL_MASK, 4));
+
+ /* de-assert PLL reset */
+ regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST, PLL_RST);
+
+ /* enable PLL */
+ regmap_update_bits(clk->regmap, GPR_REG3, PLL_CKE, PLL_CKE);
+
+ return regmap_read_poll_timeout(clk->regmap, GPR_REG1, val,
+ val & PLL_LOCK, 100);
+}
+
+static void clk_hsio_pll_unprepare(struct clk_hw *hw)
+{
+ struct clk_hsio_pll *clk = to_clk_hsio_pll(hw);
+
+ regmap_update_bits(clk->regmap, GPR_REG3, PLL_RST | PLL_CKE, 0);
+}
+
+static unsigned long clk_hsio_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return 100000000;
+}
+
+static const struct clk_ops clk_hsio_pll_ops = {
+ .enable = clk_hsio_pll_prepare,
+ .disable = clk_hsio_pll_unprepare,
+ .recalc_rate = clk_hsio_pll_recalc_rate,
+};
+
+static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
+{
+ struct clk_hsio_pll *clk_hsio_pll;
+ struct clk_hw *hw;
+ struct clk_init_data init = {};
+ int ret;
+
+ clk_hsio_pll = devm_kzalloc(bc->dev, sizeof(*clk_hsio_pll), GFP_KERNEL);
+ if (!clk_hsio_pll)
+ return -ENOMEM;
+
+ init.name = "hsio_pll";
+ init.ops = &clk_hsio_pll_ops;
+ init.parent_names = (const char *[]){"osc_24m"};
+ init.num_parents = 1;
+
+ clk_hsio_pll->regmap = bc->regmap;
+ clk_hsio_pll->hw.init = &init;
+
+ hw = &clk_hsio_pll->hw;
+ ret = clk_hw_register(bc->bus_power_dev, hw);
+ if (ret)
+ return ret;
+
+ return of_clk_add_hw_provider(dev_of_node(bc->dev), of_clk_hw_simple_get, hw);
+}
+
+static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
+ struct imx8mp_blk_ctrl_domain *domain)
+{
+ switch (domain->id) {
+ case IMX8MP_HSIOBLK_PD_USB:
+ regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+ break;
+ case IMX8MP_HSIOBLK_PD_PCIE:
+ regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+ break;
+ case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+ regmap_set_bits(bc->regmap, GPR_REG0,
+ PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+ break;
+ default:
+ break;
+ }
+}
+
+static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
+ struct imx8mp_blk_ctrl_domain *domain)
+{
+ switch (domain->id) {
+ case IMX8MP_HSIOBLK_PD_USB:
+ regmap_clear_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+ break;
+ case IMX8MP_HSIOBLK_PD_PCIE:
+ regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
+ break;
+ case IMX8MP_HSIOBLK_PD_PCIE_PHY:
+ regmap_clear_bits(bc->regmap, GPR_REG0,
+ PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
+ break;
+ default:
+ break;
+ }
+}
+
+static int imx8mp_hsio_enable_usb_clk(struct imx8mp_blk_ctrl *bc)
+{
+ int ret;
+ struct clk_bulk_data *usb_clk = bc->domains[IMX8MP_HSIOBLK_PD_USB].clks;
+ int num_clks = bc->domains[IMX8MP_HSIOBLK_PD_USB].data->num_clks;
+
+ ret = clk_bulk_prepare_enable(num_clks, usb_clk);
+ if (ret)
+ return ret;
+
+ regmap_set_bits(bc->regmap, GPR_REG0, USB_CLOCK_MODULE_EN);
+
+ return 0;
+
+}
+
+static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
+ [IMX8MP_HSIOBLK_PD_USB] = {
+ .name = "hsioblk-usb",
+ .clk_names = (const char *[]){ "usb" },
+ .num_clks = 1,
+ .gpc_name = "usb",
+ },
+ [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
+ .name = "hsioblk-usb-phy1",
+ .gpc_name = "usb-phy1",
+ },
+ [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
+ .name = "hsioblk-usb-phy2",
+ .gpc_name = "usb-phy2",
+ },
+ [IMX8MP_HSIOBLK_PD_PCIE] = {
+ .name = "hsioblk-pcie",
+ .clk_names = (const char *[]){ "pcie" },
+ .num_clks = 1,
+ .gpc_name = "pcie",
+ },
+ [IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
+ .name = "hsioblk-pcie-phy",
+ .gpc_name = "pcie-phy",
+ },
+};
+
+static const struct imx8mp_blk_ctrl_data imx8mp_hsio_blk_ctl_dev_data = {
+ .max_reg = 0x24,
+ .probe = imx8mp_hsio_blk_ctrl_probe,
+ .power_on = imx8mp_hsio_blk_ctrl_power_on,
+ .power_off = imx8mp_hsio_blk_ctrl_power_off,
+ .domains = imx8mp_hsio_domain_data,
+ .num_domains = ARRAY_SIZE(imx8mp_hsio_domain_data),
+};
+
+static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
+{
+ struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+ const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+ struct imx8mp_blk_ctrl *bc = domain->bc;
+ int ret;
+
+ ret = imx8mp_hsio_enable_usb_clk(bc);
+ if (ret)
+ return ret;
+
+ /* make sure bus domain is awake */
+ ret = pm_runtime_resume_and_get_genpd(bc->bus_power_dev);
+ if (ret < 0) {
+ dev_err(bc->dev, "failed to power up bus domain\n");
+ return ret;
+ }
+
+ /* enable upstream clocks */
+ ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+ if (ret) {
+ dev_err(bc->dev, "failed to enable clocks\n");
+ goto bus_put;
+ }
+
+ /* domain specific blk-ctrl manipulation */
+ bc->power_on(bc, domain);
+
+ /* power up upstream GPC domain */
+ ret = pm_runtime_resume_and_get_genpd(domain->power_dev);
+ if (ret < 0) {
+ dev_err(bc->dev, "failed to power up peripheral domain\n");
+ goto clk_disable;
+ }
+
+ clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+ return 0;
+
+clk_disable:
+ clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+bus_put:
+ pm_runtime_put_genpd(bc->bus_power_dev);
+
+ return ret;
+}
+
+static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
+{
+ struct imx8mp_blk_ctrl_domain *domain = to_imx8mp_blk_ctrl_domain(genpd);
+ const struct imx8mp_blk_ctrl_domain_data *data = domain->data;
+ struct imx8mp_blk_ctrl *bc = domain->bc;
+ int ret;
+
+ ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
+ if (ret) {
+ dev_err(bc->dev, "failed to enable clocks\n");
+ return ret;
+ }
+
+ /* domain specific blk-ctrl manipulation */
+ bc->power_off(bc, domain);
+
+ clk_bulk_disable_unprepare(data->num_clks, domain->clks);
+
+ /* power down upstream GPC domain */
+ pm_runtime_put_genpd(domain->power_dev);
+
+ /* allow bus domain to suspend */
+ pm_runtime_put_genpd(bc->bus_power_dev);
+
+ return 0;
+}
+
+static int imx8mp_blk_ctrl_probe(struct device *dev)
+{
+ const struct imx8mp_blk_ctrl_data *bc_data;
+ struct imx8mp_blk_ctrl *bc;
+ void __iomem *base;
+ int num_domains, i, ret;
+
+ struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ };
+
+ bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
+ if (!bc)
+ return -ENOMEM;
+
+ bc->dev = dev;
+
+ bc_data = of_device_get_match_data(dev);
+ num_domains = bc_data->num_domains;
+
+ base = dev_platform_ioremap_resource(dev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap_config.max_register = bc_data->max_reg;
+ bc->regmap = regmap_init_mmio(dev, base, ®map_config);
+ if (IS_ERR(bc->regmap))
+ return dev_err_probe(dev, PTR_ERR(bc->regmap),
+ "failed to init regmap\n");
+
+ bc->domains = devm_kcalloc(dev, num_domains,
+ sizeof(struct imx8mp_blk_ctrl_domain),
+ GFP_KERNEL);
+ if (!bc->domains)
+ return -ENOMEM;
+
+ bc->onecell_data.num_domains = num_domains;
+ bc->onecell_data.domains =
+ devm_kcalloc(dev, num_domains,
+ sizeof(struct generic_pm_domain *), GFP_KERNEL);
+ if (!bc->onecell_data.domains)
+ return -ENOMEM;
+
+ bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
+ if (IS_ERR(bc->bus_power_dev))
+ return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
+ "failed to attach bus power domain\n");
+
+ bc->power_off = bc_data->power_off;
+ bc->power_on = bc_data->power_on;
+
+ for (i = 0; i < num_domains; i++) {
+ const struct imx8mp_blk_ctrl_domain_data *data = &bc_data->domains[i];
+ struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+ int j;
+
+ domain->data = data;
+
+ for (j = 0; j < data->num_clks; j++)
+ domain->clks[j].id = data->clk_names[j];
+
+ ret = clk_bulk_get(dev, data->num_clks, domain->clks);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to get clock\n");
+ goto cleanup_pds;
+ }
+
+ domain->power_dev =
+ dev_pm_domain_attach_by_name(dev, data->gpc_name);
+ if (IS_ERR(domain->power_dev)) {
+ dev_err_probe(dev, PTR_ERR(domain->power_dev),
+ "failed to attach power domain %s\n",
+ data->gpc_name);
+ ret = PTR_ERR(domain->power_dev);
+ goto cleanup_pds;
+ }
+
+ domain->genpd.name = data->name;
+ domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
+ domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
+ domain->bc = bc;
+ domain->id = i;
+
+ ret = pm_genpd_init(&domain->genpd, NULL, true);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to init power domain\n");
+ dev_pm_domain_detach(domain->power_dev, true);
+ goto cleanup_pds;
+ }
+
+ bc->onecell_data.domains[i] = &domain->genpd;
+ }
+
+ ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to add power domain provider\n");
+ goto cleanup_pds;
+ }
+
+ if (bc_data->probe) {
+ ret = bc_data->probe(bc);
+ if (ret)
+ goto cleanup_provider;
+ }
+
+ return 0;
+
+cleanup_provider:
+ of_genpd_del_provider(dev->of_node);
+cleanup_pds:
+ for (i--; i >= 0; i--) {
+ pm_genpd_remove(&bc->domains[i].genpd);
+ dev_pm_domain_detach(bc->domains[i].power_dev, true);
+ }
+
+ dev_pm_domain_detach(bc->bus_power_dev, true);
+
+ return ret;
+}
+
+static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
+ {
+ .compatible = "fsl,imx8mp-hsio-blk-ctrl",
+ .data = &imx8mp_hsio_blk_ctl_dev_data,
+ }, {
+ /* Sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
+
+static struct driver imx8mp_blk_ctrl_driver = {
+ .probe = imx8mp_blk_ctrl_probe,
+ .name = "imx8mp-blk-ctrl",
+ .of_match_table = imx8mp_blk_ctrl_of_match,
+};
+coredevice_platform_driver(imx8mp_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 19/19] ARM: dts: i.MX8MP: drop barebox,allow-dummy for HSIO blk-ctrl
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (17 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 18/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
@ 2024-01-19 16:26 ` Ahmad Fatoum
2024-01-22 10:12 ` [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Sascha Hauer
19 siblings, 0 replies; 21+ messages in thread
From: Ahmad Fatoum @ 2024-01-19 16:26 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Now that we have a HSIO blk ctrl driver, there is no need to generally
assume that TF-A or BootROM have left them enabled for us.
Boards that want to continue making use of this assumption can reinstate
the barebox,allow-dummy property, but everyone else should just enable
CONFIG_IMX8M_BLK_CTRL.
While barebox,allow-dummy only has an effect if the driver doesn't
exist (as determined by deep probe), we remove the property for improved
user experience when the TF-A doesn't enable the HSIO power domain.
In that case, barebox,allow-dummy would cause barebox to continue
probe of USB controller and PHY resulting in a bus hang instead of
an error message that tells what's up:
imx8mq-usb-phy 381f0040.usb-phy@381f0040.of: error No such device: power domain attach failed
dwc3-of-simple 32f10100.usb@32f10100.of: error No such device: power domain attach failed
imx8mq-usb-phy 382f0040.usb-phy@382f0040.of: error No such device: power domain attach failed
dwc3-of-simple 32f10108.usb@32f10108.of: error No such device: power domain attach failed
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/dts/imx8mp.dtsi | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/arm/dts/imx8mp.dtsi b/arch/arm/dts/imx8mp.dtsi
index 04767ad382c8..7a038217c468 100644
--- a/arch/arm/dts/imx8mp.dtsi
+++ b/arch/arm/dts/imx8mp.dtsi
@@ -73,7 +73,3 @@ &gpu3d {
&gpu2d {
barebox,feature-gates = <&feat IMX8M_FEAT_GPU>;
};
-
-&hsio_blk_ctrl {
- barebox,allow-dummy;
-};
--
2.39.2
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver
2024-01-19 16:25 [PATCH 00/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver Ahmad Fatoum
` (18 preceding siblings ...)
2024-01-19 16:26 ` [PATCH 19/19] ARM: dts: i.MX8MP: drop barebox,allow-dummy for HSIO blk-ctrl Ahmad Fatoum
@ 2024-01-22 10:12 ` Sascha Hauer
19 siblings, 0 replies; 21+ messages in thread
From: Sascha Hauer @ 2024-01-22 10:12 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Fri, 19 Jan 2024 17:25:51 +0100, Ahmad Fatoum wrote:
> Unlike other i.MX8M variants, TF-A on i.MX8MP enables all power domains
> up front, so later software can keep reusing it.
>
> This benefited us because we didn't have a driver for the HSIO blk-ctrl,
> which powers the USB PHYs and controllers on the i.MX8MP.
>
> However, not all i.MX8MP SKUs have all power domains, e.g. the lite
> variant lacks VPUs, NPU, ISP and DSP and their associated power domains.
>
> [...]
Applied, thanks!
[01/19] drivers: soc: split off powerdomains into new pmdomain directory
https://git.pengutronix.de/cgit/barebox/commit/?id=bea9e101e703 (link may not be stable)
[02/19] pmdomain: use single implementation for dev_pm_domain_attach
https://git.pengutronix.de/cgit/barebox/commit/?id=1fb85a10c6c2 (link may not be stable)
[03/19] pmdomain: power: drop unused parameters for internal functions
https://git.pengutronix.de/cgit/barebox/commit/?id=b32806b04f81 (link may not be stable)
[04/19] pmdomain: associate devices with their power domain
https://git.pengutronix.de/cgit/barebox/commit/?id=ac31020ae43b (link may not be stable)
[05/19] pmdomain: push have_genpd_providers check into __genpd_dev_pm_attach
https://git.pengutronix.de/cgit/barebox/commit/?id=e5f38c818448 (link may not be stable)
[06/19] pmdomain: drop superfluous parameter to __genpd_dev_pm_attach
https://git.pengutronix.de/cgit/barebox/commit/?id=7b23b9c96a59 (link may not be stable)
[07/19] pmdomain: implement dev_pm_domain_attach_by_id/name
https://git.pengutronix.de/cgit/barebox/commit/?id=26c0bb95d255 (link may not be stable)
[08/19] pmdomain: add support for enabling power domains later on
https://git.pengutronix.de/cgit/barebox/commit/?id=9200d8dc5efe (link may not be stable)
[09/19] pmdomain: imx: gpcv2: enable COMPILE_TEST build
https://git.pengutronix.de/cgit/barebox/commit/?id=a0d8f74b6dc3 (link may not be stable)
[10/19] pmdomain: add stub definition for dev_pm_domain_detach
https://git.pengutronix.de/cgit/barebox/commit/?id=7d04ad5ea514 (link may not be stable)
[11/19] pmdomain: add stub definition for pm_runtime_put_genpd
https://git.pengutronix.de/cgit/barebox/commit/?id=46a46b6cc8a2 (link may not be stable)
[12/19] pmdomain: implement pm_genpd_remove/of_genpd_del_provider for cleanup
https://git.pengutronix.de/cgit/barebox/commit/?id=7f516cc60c18 (link may not be stable)
[13/19] driver: have dev_request_mem_region_err_null warn if resource starts at 0
https://git.pengutronix.de/cgit/barebox/commit/?id=c85be7026ca0 (link may not be stable)
[14/19] include: linux/device.h: implement dev_platform_ioremap_resource
https://git.pengutronix.de/cgit/barebox/commit/?id=021cff0a1327 (link may not be stable)
[15/19] regmap: include missing header from linux/regmap.h
https://git.pengutronix.de/cgit/barebox/commit/?id=a608589d0980 (link may not be stable)
[16/19] clk: define aliases for clk_bulk_prepare_enable/disable_unprepare
https://git.pengutronix.de/cgit/barebox/commit/?id=ca05d4e579ef (link may not be stable)
[17/19] driver: make driver.h header self-contained
https://git.pengutronix.de/cgit/barebox/commit/?id=f14ecd34670f (link may not be stable)
[18/19] pmdomain: imx: add i.MX8MP HSIO blk-ctrl driver
https://git.pengutronix.de/cgit/barebox/commit/?id=60624ec572a3 (link may not be stable)
[19/19] ARM: dts: i.MX8MP: drop barebox,allow-dummy for HSIO blk-ctrl
https://git.pengutronix.de/cgit/barebox/commit/?id=09ab7f1c9c0f (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 21+ messages in thread