diff mbox series

[v17,06/12] soc: mediatek: Add support for hierarchical scpsys device node

Message ID 1596705715-15320-7-git-send-email-weiyi.lu@mediatek.com (mailing list archive)
State New, archived
Headers show
Series Mediatek MT8183 scpsys support | expand

Commit Message

Weiyi Lu Aug. 6, 2020, 9:21 a.m. UTC
Try to list all the power domains of under power controller
node to show the dependency between each power domain directly
instead of filling the dependency in scp_soc_data.
And could be more clearly to group subsys clocks into power domain
sub node to introduce subsys clocks of bus protection in next patch.

Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 103 +++++++++++++++++++++++++++++++++++---
 1 file changed, 95 insertions(+), 8 deletions(-)

Comments

Nicolas Boichat Sept. 28, 2020, 7:14 a.m. UTC | #1
On Thu, Aug 6, 2020 at 5:22 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>
> Try to list all the power domains of under power controller
> node to show the dependency between each power domain directly
> instead of filling the dependency in scp_soc_data.
> And could be more clearly to group subsys clocks into power domain
> sub node to introduce subsys clocks of bus protection in next patch.
>
> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> ---
[snip]
> +static int traverse_scp(struct platform_device *pdev, struct scp *scp,
> +                       const struct scp_domain_data *scp_domain_data)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct device_node *sub;
> +       int ret;
> +
> +       INIT_LIST_HEAD(&scp->dep_links);
> +
> +       for_each_available_child_of_node(np, sub) {
> +               ret = scpsys_get_domain(pdev, scp, sub, scp_domain_data);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "failed to handle node %pOFn: %d\n", sub, ret);

minor comment: this error should not be printed if ret ==
-EPROBE_DEFER (use the new dev_err_probe?)

> +                       goto err;
> +               }
> +       }
> +
> +       return 0;
> +
> +err:
> +       of_node_put(sub);
> +       return ret;
> +}
[snip]
Weiyi Lu Sept. 30, 2020, 3:37 a.m. UTC | #2
On Mon, 2020-09-28 at 15:14 +0800, Nicolas Boichat wrote:
> On Thu, Aug 6, 2020 at 5:22 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
> >
> > Try to list all the power domains of under power controller
> > node to show the dependency between each power domain directly
> > instead of filling the dependency in scp_soc_data.
> > And could be more clearly to group subsys clocks into power domain
> > sub node to introduce subsys clocks of bus protection in next patch.
> >
> > Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
> > ---
> [snip]
> > +static int traverse_scp(struct platform_device *pdev, struct scp *scp,
> > +                       const struct scp_domain_data *scp_domain_data)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct device_node *np = dev->of_node;
> > +       struct device_node *sub;
> > +       int ret;
> > +
> > +       INIT_LIST_HEAD(&scp->dep_links);
> > +
> > +       for_each_available_child_of_node(np, sub) {
> > +               ret = scpsys_get_domain(pdev, scp, sub, scp_domain_data);
> > +               if (ret) {
> > +                       dev_err(&pdev->dev, "failed to handle node %pOFn: %d\n", sub, ret);
> 
> minor comment: this error should not be printed if ret ==
> -EPROBE_DEFER (use the new dev_err_probe?)
> 

You're right! I'll use dev_err_probe() instead if anyone is interested
in this series. Thank you!

> > +                       goto err;
> > +               }
> > +       }
> > +
> > +       return 0;
> > +
> > +err:
> > +       of_node_put(sub);
> > +       return ret;
> > +}
> [snip]
Matthias Brugger Oct. 1, 2020, 2:33 p.m. UTC | #3
On 30/09/2020 05:37, Weiyi Lu wrote:
> On Mon, 2020-09-28 at 15:14 +0800, Nicolas Boichat wrote:
>> On Thu, Aug 6, 2020 at 5:22 PM Weiyi Lu <weiyi.lu@mediatek.com> wrote:
>>>
>>> Try to list all the power domains of under power controller
>>> node to show the dependency between each power domain directly
>>> instead of filling the dependency in scp_soc_data.
>>> And could be more clearly to group subsys clocks into power domain
>>> sub node to introduce subsys clocks of bus protection in next patch.
>>>
>>> Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
>>> ---
>> [snip]
>>> +static int traverse_scp(struct platform_device *pdev, struct scp *scp,
>>> +                       const struct scp_domain_data *scp_domain_data)
>>> +{
>>> +       struct device *dev = &pdev->dev;
>>> +       struct device_node *np = dev->of_node;
>>> +       struct device_node *sub;
>>> +       int ret;
>>> +
>>> +       INIT_LIST_HEAD(&scp->dep_links);
>>> +
>>> +       for_each_available_child_of_node(np, sub) {
>>> +               ret = scpsys_get_domain(pdev, scp, sub, scp_domain_data);
>>> +               if (ret) {
>>> +                       dev_err(&pdev->dev, "failed to handle node %pOFn: %d\n", sub, ret);
>>
>> minor comment: this error should not be printed if ret ==
>> -EPROBE_DEFER (use the new dev_err_probe?)
>>
> 
> You're right! I'll use dev_err_probe() instead if anyone is interested
> in this series. Thank you!
> 

I'd propose that we put all our effort of reviewing and testing into the series 
Enric send:
https://lore.kernel.org/linux-mediatek/20200910172826.3074357-1-enric.balletbo@collabora.com/

Regards,
Matthias

>>> +                       goto err;
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +
>>> +err:
>>> +       of_node_put(sub);
>>> +       return ret;
>>> +}
>> [snip]
>
diff mbox series

Patch

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 5a2c323..502b66f 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -182,11 +182,13 @@  struct scp {
 	struct regmap *infracfg;
 	struct regmap *smi_common;
 	struct scp_ctrl_reg ctrl_reg;
+	struct list_head dep_links;
 };
 
 struct scp_subdomain {
 	int origin;
 	int subdomain;
+	struct list_head list;
 };
 
 struct scp_soc_data {
@@ -513,6 +515,79 @@  static int init_basic_clks(struct platform_device *pdev, struct clk **clk,
 	return 0;
 }
 
+static int scpsys_get_domain_id(struct device_node *node, u32 *id)
+{
+	int ret;
+
+	ret = of_property_read_u32(node, "reg", id);
+	if (ret)
+		pr_err("%pOFn: failed to retrieve domain id, ret=%d\n", node, ret);
+
+	return ret;
+}
+
+static int scpsys_get_domain(struct platform_device *pdev, struct scp *scp,
+			struct device_node *node, const struct scp_domain_data *data)
+{
+	struct scp_subdomain *dep_node;
+	struct device_node *sub;
+	u32 parent_id, child_id;
+	int ret;
+
+	ret = scpsys_get_domain_id(node, &parent_id);
+	if (ret)
+		return ret;
+
+	for_each_child_of_node(node, sub) {
+		ret = scpsys_get_domain_id(sub, &child_id);
+		if (ret)
+			goto out;
+
+		dep_node = devm_kzalloc(&pdev->dev, sizeof(*dep_node), GFP_KERNEL);
+		if (!dep_node) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dep_node->origin = parent_id;
+		dep_node->subdomain = child_id;
+		list_add(&dep_node->list, &scp->dep_links);
+
+		scpsys_get_domain(pdev, scp, sub, data);
+	}
+
+	return 0;
+
+out:
+	of_node_put(sub);
+	return ret;
+}
+
+static int traverse_scp(struct platform_device *pdev, struct scp *scp,
+			const struct scp_domain_data *scp_domain_data)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *sub;
+	int ret;
+
+	INIT_LIST_HEAD(&scp->dep_links);
+
+	for_each_available_child_of_node(np, sub) {
+		ret = scpsys_get_domain(pdev, scp, sub, scp_domain_data);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to handle node %pOFn: %d\n", sub, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	of_node_put(sub);
+	return ret;
+}
+
 static struct scp *init_scp(struct platform_device *pdev,
 			const struct scp_domain_data *scp_domain_data, int num,
 			const struct scp_ctrl_reg *scp_ctrl_reg)
@@ -582,6 +657,10 @@  static struct scp *init_scp(struct platform_device *pdev,
 
 	pd_data->num_domains = num;
 
+	ret = traverse_scp(pdev, scp, scp_domain_data);
+	if (ret)
+		return ERR_PTR(ret);
+
 	for (i = 0; i < num; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		struct generic_pm_domain *genpd = &scpd->genpd;
@@ -1208,7 +1287,7 @@  static int scpsys_probe(struct platform_device *pdev)
 	const struct scp_soc_data *soc;
 	struct scp *scp;
 	struct genpd_onecell_data *pd_data;
-	int i, ret;
+	int i, ret = 0;
 
 	soc = of_device_get_match_data(&pdev->dev);
 
@@ -1220,15 +1299,23 @@  static int scpsys_probe(struct platform_device *pdev)
 
 	pd_data = &scp->pd_data;
 
-	for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
-		ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
-					     pd_data->domains[sd->subdomain]);
-		if (ret && IS_ENABLED(CONFIG_PM))
-			dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
-				ret);
+	if (soc->subdomains && soc->num_subdomains) {
+		for (i = 0, sd = soc->subdomains; i < soc->num_subdomains; i++, sd++) {
+			ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
+						     pd_data->domains[sd->subdomain]);
+			if (ret && IS_ENABLED(CONFIG_PM))
+				dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
+		}
+	} else {
+		list_for_each_entry(sd, &scp->dep_links, list) {
+			ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
+						     pd_data->domains[sd->subdomain]);
+			if (ret && IS_ENABLED(CONFIG_PM))
+				dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
+		}
 	}
 
-	return 0;
+	return ret;
 }
 
 static struct platform_driver scpsys_drv = {