From 77acb18b46a9464521f4f9af26f87d8a5f644515 Mon Sep 17 00:00:00 2001
From: Pavel Golikov <Paullo612@ya.ru>
Date: Fri, 24 Jun 2022 15:56:41 +0000
Subject: [PATCH 04/21] WIP: soc: samsung: pm_domains: Bring back old driver
 implementation

Using new implementation decreases Mali GPU performance significantly
(with both KBase and Panfrost drivers).

Signed-off-by: Pavel Golikov <Paullo612@ya.ru>
---
 drivers/pmdomain/samsung/exynos-pm-domains.c | 97 ++++++++++++++++----------------
 1 file changed, 49 insertions(+), 48 deletions(-)

diff --git a/drivers/pmdomain/samsung/exynos-pm-domains.c b/drivers/pmdomain/samsung/exynos-pm-domains.c
index d07f3c9d6903..1022d40eb700 100644
--- a/drivers/pmdomain/samsung/exynos-pm-domains.c
+++ b/drivers/pmdomain/samsung/exynos-pm-domains.c
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/pm_runtime.h>
+#include <linux/sched.h>
 
 struct exynos_pm_domain_config {
 	/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
@@ -72,15 +72,15 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
 	return exynos_pd_power(domain, false);
 }
 
-static const struct exynos_pm_domain_config exynos4210_cfg = {
+static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
 	.local_pwr_cfg		= 0x7,
 };
 
-static const struct exynos_pm_domain_config exynos5433_cfg = {
+static const struct exynos_pm_domain_config exynos5433_cfg __initconst = {
 	.local_pwr_cfg		= 0xf,
 };
 
-static const struct of_device_id exynos_pm_domain_of_match[] = {
+static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
 	{
 		.compatible = "samsung,exynos4210-pd",
 		.data = &exynos4210_cfg,
@@ -91,7 +91,7 @@ static const struct of_device_id exynos_pm_domain_of_match[] = {
 	{ },
 };
 
-static const char *exynos_get_domain_name(struct device_node *node)
+static __init const char *exynos_get_domain_name(struct device_node *node)
 {
 	const char *name;
 
@@ -100,44 +100,60 @@ static const char *exynos_get_domain_name(struct device_node *node)
 	return kstrdup_const(name, GFP_KERNEL);
 }
 
-static int exynos_pd_probe(struct platform_device *pdev)
+static __init int exynos4_pm_init_power_domain(void)
 {
-	const struct exynos_pm_domain_config *pm_domain_cfg;
-	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
-	struct of_phandle_args child, parent;
-	struct exynos_pm_domain *pd;
-	int on, ret;
+	struct device_node *np;
+	const struct of_device_id *match;
 
-	pm_domain_cfg = of_device_get_match_data(dev);
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd)
-		return -ENOMEM;
+	for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
+		const struct exynos_pm_domain_config *pm_domain_cfg;
+		struct exynos_pm_domain *pd;
+		int on;
 
-	pd->pd.name = exynos_get_domain_name(np);
-	if (!pd->pd.name)
-		return -ENOMEM;
+		pm_domain_cfg = match->data;
 
-	pd->base = of_iomap(np, 0);
-	if (!pd->base) {
-		kfree_const(pd->pd.name);
-		return -ENODEV;
-	}
+		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+		if (!pd) {
+			of_node_put(np);
+			return -ENOMEM;
+		}
+		pd->pd.name = exynos_get_domain_name(np);
+		if (!pd->pd.name) {
+			kfree(pd);
+			of_node_put(np);
+			return -ENOMEM;
+		}
 
-	pd->pd.power_off = exynos_pd_power_off;
-	pd->pd.power_on = exynos_pd_power_on;
-	pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
+		pd->base = of_iomap(np, 0);
+		if (!pd->base) {
+			pr_warn("%s: failed to map memory\n", __func__);
+			kfree_const(pd->pd.name);
+			kfree(pd);
+			continue;
+		}
+
+		pd->pd.power_off = exynos_pd_power_off;
+		pd->pd.power_on = exynos_pd_power_on;
+		pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
 
-	on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
+		on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
+
+		pm_genpd_init(&pd->pd, NULL, !on);
+		of_genpd_add_provider_simple(np, &pd->pd);
+	}
 
-	pm_genpd_init(&pd->pd, NULL, !on);
-	ret = of_genpd_add_provider_simple(np, &pd->pd);
+	/* Assign the child power domains to their parents */
+	for_each_matching_node(np, exynos_pm_domain_of_match) {
+		struct of_phandle_args child, parent;
 
-	if (ret == 0 && of_parse_phandle_with_args(np, "power-domains",
-				      "#power-domain-cells", 0, &parent) == 0) {
 		child.np = np;
 		child.args_count = 0;
 
+		if (of_parse_phandle_with_args(np, "power-domains",
+					       "#power-domain-cells", 0,
+					       &parent) != 0)
+			continue;
+
 		if (of_genpd_add_subdomain(&parent, &child))
 			pr_warn("%pOF failed to add subdomain: %pOF\n",
 				parent.np, child.np);
@@ -146,21 +162,6 @@ static int exynos_pd_probe(struct platform_device *pdev)
 				parent.np, child.np);
 	}
 
-	pm_runtime_enable(dev);
-	return ret;
-}
-
-static struct platform_driver exynos_pd_driver = {
-	.probe	= exynos_pd_probe,
-	.driver	= {
-		.name		= "exynos-pd",
-		.of_match_table	= exynos_pm_domain_of_match,
-		.suppress_bind_attrs = true,
-	}
-};
-
-static __init int exynos4_pm_init_power_domain(void)
-{
-	return platform_driver_register(&exynos_pd_driver);
+	return 0;
 }
 core_initcall(exynos4_pm_init_power_domain);
-- 
2.17.1

