xref: /linux/drivers/pmdomain/mediatek/mtk-pm-domains.c (revision 3fd6c59042dbba50391e30862beac979491145fe)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2020 Collabora Ltd.
4  */
5 #include <linux/clk.h>
6 #include <linux/clk-provider.h>
7 #include <linux/init.h>
8 #include <linux/io.h>
9 #include <linux/iopoll.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/of.h>
12 #include <linux/of_clk.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_domain.h>
15 #include <linux/regmap.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/soc/mediatek/infracfg.h>
18 
19 #include "mt6735-pm-domains.h"
20 #include "mt6795-pm-domains.h"
21 #include "mt8167-pm-domains.h"
22 #include "mt8173-pm-domains.h"
23 #include "mt8183-pm-domains.h"
24 #include "mt8186-pm-domains.h"
25 #include "mt8188-pm-domains.h"
26 #include "mt8192-pm-domains.h"
27 #include "mt8195-pm-domains.h"
28 #include "mt8365-pm-domains.h"
29 
30 #define MTK_POLL_DELAY_US		10
31 #define MTK_POLL_TIMEOUT		USEC_PER_SEC
32 
33 #define PWR_RST_B_BIT			BIT(0)
34 #define PWR_ISO_BIT			BIT(1)
35 #define PWR_ON_BIT			BIT(2)
36 #define PWR_ON_2ND_BIT			BIT(3)
37 #define PWR_CLK_DIS_BIT			BIT(4)
38 #define PWR_SRAM_CLKISO_BIT		BIT(5)
39 #define PWR_SRAM_ISOINT_B_BIT		BIT(6)
40 
41 struct scpsys_domain {
42 	struct generic_pm_domain genpd;
43 	const struct scpsys_domain_data *data;
44 	struct scpsys *scpsys;
45 	int num_clks;
46 	struct clk_bulk_data *clks;
47 	int num_subsys_clks;
48 	struct clk_bulk_data *subsys_clks;
49 	struct regmap *infracfg_nao;
50 	struct regmap *infracfg;
51 	struct regmap *smi;
52 	struct regulator *supply;
53 };
54 
55 struct scpsys {
56 	struct device *dev;
57 	struct regmap *base;
58 	const struct scpsys_soc_data *soc_data;
59 	struct genpd_onecell_data pd_data;
60 	struct generic_pm_domain *domains[];
61 };
62 
63 #define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
64 
scpsys_domain_is_on(struct scpsys_domain * pd)65 static bool scpsys_domain_is_on(struct scpsys_domain *pd)
66 {
67 	struct scpsys *scpsys = pd->scpsys;
68 	u32 status, status2;
69 
70 	regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status);
71 	status &= pd->data->sta_mask;
72 
73 	regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2);
74 	status2 &= pd->data->sta_mask;
75 
76 	/* A domain is on when both status bits are set. */
77 	return status && status2;
78 }
79 
scpsys_sram_enable(struct scpsys_domain * pd)80 static int scpsys_sram_enable(struct scpsys_domain *pd)
81 {
82 	u32 pdn_ack = pd->data->sram_pdn_ack_bits;
83 	struct scpsys *scpsys = pd->scpsys;
84 	unsigned int tmp;
85 	int ret;
86 
87 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
88 
89 	/* Either wait until SRAM_PDN_ACK all 1 or 0 */
90 	ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
91 				       (tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
92 	if (ret < 0)
93 		return ret;
94 
95 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
96 		regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
97 		udelay(1);
98 		regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
99 	}
100 
101 	return 0;
102 }
103 
scpsys_sram_disable(struct scpsys_domain * pd)104 static int scpsys_sram_disable(struct scpsys_domain *pd)
105 {
106 	u32 pdn_ack = pd->data->sram_pdn_ack_bits;
107 	struct scpsys *scpsys = pd->scpsys;
108 	unsigned int tmp;
109 
110 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
111 		regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
112 		udelay(1);
113 		regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
114 	}
115 
116 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
117 
118 	/* Either wait until SRAM_PDN_ACK all 1 or 0 */
119 	return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
120 					(tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
121 					MTK_POLL_TIMEOUT);
122 }
123 
scpsys_bus_protect_get_regmap(struct scpsys_domain * pd,const struct scpsys_bus_prot_data * bpd)124 static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
125 						    const struct scpsys_bus_prot_data *bpd)
126 {
127 	if (bpd->flags & BUS_PROT_COMPONENT_SMI)
128 		return pd->smi;
129 	else
130 		return pd->infracfg;
131 }
132 
scpsys_bus_protect_get_sta_regmap(struct scpsys_domain * pd,const struct scpsys_bus_prot_data * bpd)133 static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
134 							const struct scpsys_bus_prot_data *bpd)
135 {
136 	if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
137 		return pd->infracfg_nao;
138 	else
139 		return scpsys_bus_protect_get_regmap(pd, bpd);
140 }
141 
scpsys_bus_protect_clear(struct scpsys_domain * pd,const struct scpsys_bus_prot_data * bpd)142 static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
143 				    const struct scpsys_bus_prot_data *bpd)
144 {
145 	struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
146 	struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
147 	u32 sta_mask = bpd->bus_prot_sta_mask;
148 	u32 expected_ack;
149 	u32 val;
150 
151 	expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0);
152 
153 	if (bpd->flags & BUS_PROT_REG_UPDATE)
154 		regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
155 	else
156 		regmap_write(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
157 
158 	if (bpd->flags & BUS_PROT_IGNORE_CLR_ACK)
159 		return 0;
160 
161 	return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
162 					val, (val & sta_mask) == expected_ack,
163 					MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
164 }
165 
scpsys_bus_protect_set(struct scpsys_domain * pd,const struct scpsys_bus_prot_data * bpd)166 static int scpsys_bus_protect_set(struct scpsys_domain *pd,
167 				  const struct scpsys_bus_prot_data *bpd)
168 {
169 	struct regmap *sta_regmap = scpsys_bus_protect_get_sta_regmap(pd, bpd);
170 	struct regmap *regmap = scpsys_bus_protect_get_regmap(pd, bpd);
171 	u32 sta_mask = bpd->bus_prot_sta_mask;
172 	u32 val;
173 
174 	if (bpd->flags & BUS_PROT_REG_UPDATE)
175 		regmap_set_bits(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
176 	else
177 		regmap_write(regmap, bpd->bus_prot_set, bpd->bus_prot_set_clr_mask);
178 
179 	return regmap_read_poll_timeout(sta_regmap, bpd->bus_prot_sta,
180 					val, (val & sta_mask) == sta_mask,
181 					MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
182 }
183 
scpsys_bus_protect_enable(struct scpsys_domain * pd)184 static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
185 {
186 	for (int i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
187 		const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
188 		int ret;
189 
190 		if (!bpd->bus_prot_set_clr_mask)
191 			break;
192 
193 		if (bpd->flags & BUS_PROT_INVERTED)
194 			ret = scpsys_bus_protect_clear(pd, bpd);
195 		else
196 			ret = scpsys_bus_protect_set(pd, bpd);
197 		if (ret)
198 			return ret;
199 	}
200 
201 	return 0;
202 }
203 
scpsys_bus_protect_disable(struct scpsys_domain * pd)204 static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
205 {
206 	for (int i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
207 		const struct scpsys_bus_prot_data *bpd = &pd->data->bp_cfg[i];
208 		int ret;
209 
210 		if (!bpd->bus_prot_set_clr_mask)
211 			continue;
212 
213 		if (bpd->flags & BUS_PROT_INVERTED)
214 			ret = scpsys_bus_protect_set(pd, bpd);
215 		else
216 			ret = scpsys_bus_protect_clear(pd, bpd);
217 		if (ret)
218 			return ret;
219 	}
220 
221 	return 0;
222 }
223 
scpsys_regulator_enable(struct regulator * supply)224 static int scpsys_regulator_enable(struct regulator *supply)
225 {
226 	return supply ? regulator_enable(supply) : 0;
227 }
228 
scpsys_regulator_disable(struct regulator * supply)229 static int scpsys_regulator_disable(struct regulator *supply)
230 {
231 	return supply ? regulator_disable(supply) : 0;
232 }
233 
scpsys_power_on(struct generic_pm_domain * genpd)234 static int scpsys_power_on(struct generic_pm_domain *genpd)
235 {
236 	struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
237 	struct scpsys *scpsys = pd->scpsys;
238 	bool tmp;
239 	int ret;
240 
241 	ret = scpsys_regulator_enable(pd->supply);
242 	if (ret)
243 		return ret;
244 
245 	ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
246 	if (ret)
247 		goto err_reg;
248 
249 	if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
250 		regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs,
251 				  pd->data->ext_buck_iso_mask);
252 
253 	/* subsys power on */
254 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
255 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
256 
257 	/* wait until PWR_ACK = 1 */
258 	ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
259 				 MTK_POLL_TIMEOUT);
260 	if (ret < 0)
261 		goto err_pwr_ack;
262 
263 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
264 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
265 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
266 
267 	/*
268 	 * In few Mediatek platforms(e.g. MT6779), the bus protect policy is
269 	 * stricter, which leads to bus protect release must be prior to bus
270 	 * access.
271 	 */
272 	if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
273 		ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
274 					      pd->subsys_clks);
275 		if (ret)
276 			goto err_pwr_ack;
277 	}
278 
279 	ret = scpsys_sram_enable(pd);
280 	if (ret < 0)
281 		goto err_disable_subsys_clks;
282 
283 	ret = scpsys_bus_protect_disable(pd);
284 	if (ret < 0)
285 		goto err_disable_sram;
286 
287 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION)) {
288 		ret = clk_bulk_prepare_enable(pd->num_subsys_clks,
289 					      pd->subsys_clks);
290 		if (ret)
291 			goto err_enable_bus_protect;
292 	}
293 
294 	return 0;
295 
296 err_enable_bus_protect:
297 	scpsys_bus_protect_enable(pd);
298 err_disable_sram:
299 	scpsys_sram_disable(pd);
300 err_disable_subsys_clks:
301 	if (!MTK_SCPD_CAPS(pd, MTK_SCPD_STRICT_BUS_PROTECTION))
302 		clk_bulk_disable_unprepare(pd->num_subsys_clks,
303 					   pd->subsys_clks);
304 err_pwr_ack:
305 	clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
306 err_reg:
307 	scpsys_regulator_disable(pd->supply);
308 	return ret;
309 }
310 
scpsys_power_off(struct generic_pm_domain * genpd)311 static int scpsys_power_off(struct generic_pm_domain *genpd)
312 {
313 	struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
314 	struct scpsys *scpsys = pd->scpsys;
315 	bool tmp;
316 	int ret;
317 
318 	ret = scpsys_bus_protect_enable(pd);
319 	if (ret < 0)
320 		return ret;
321 
322 	ret = scpsys_sram_disable(pd);
323 	if (ret < 0)
324 		return ret;
325 
326 	if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO))
327 		regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs,
328 				pd->data->ext_buck_iso_mask);
329 
330 	clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
331 
332 	/* subsys power off */
333 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
334 	regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
335 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
336 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
337 	regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
338 
339 	/* wait until PWR_ACK = 0 */
340 	ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
341 				 MTK_POLL_TIMEOUT);
342 	if (ret < 0)
343 		return ret;
344 
345 	clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
346 
347 	scpsys_regulator_disable(pd->supply);
348 
349 	return 0;
350 }
351 
352 static struct
scpsys_add_one_domain(struct scpsys * scpsys,struct device_node * node)353 generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
354 {
355 	const struct scpsys_domain_data *domain_data;
356 	struct scpsys_domain *pd;
357 	struct device_node *smi_node;
358 	struct property *prop;
359 	const char *clk_name;
360 	int i, ret, num_clks;
361 	struct clk *clk;
362 	int clk_ind = 0;
363 	u32 id;
364 
365 	ret = of_property_read_u32(node, "reg", &id);
366 	if (ret) {
367 		dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
368 			node, ret);
369 		return ERR_PTR(-EINVAL);
370 	}
371 
372 	if (id >= scpsys->soc_data->num_domains) {
373 		dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
374 		return ERR_PTR(-EINVAL);
375 	}
376 
377 	domain_data = &scpsys->soc_data->domains_data[id];
378 	if (domain_data->sta_mask == 0) {
379 		dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
380 		return ERR_PTR(-EINVAL);
381 	}
382 
383 	pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
384 	if (!pd)
385 		return ERR_PTR(-ENOMEM);
386 
387 	pd->data = domain_data;
388 	pd->scpsys = scpsys;
389 
390 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
391 		pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
392 		if (IS_ERR(pd->supply))
393 			return dev_err_cast_probe(scpsys->dev, pd->supply,
394 				      "%pOF: failed to get power supply.\n",
395 				      node);
396 	}
397 
398 	pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
399 	if (IS_ERR(pd->infracfg))
400 		return ERR_CAST(pd->infracfg);
401 
402 	smi_node = of_parse_phandle(node, "mediatek,smi", 0);
403 	if (smi_node) {
404 		pd->smi = device_node_to_regmap(smi_node);
405 		of_node_put(smi_node);
406 		if (IS_ERR(pd->smi))
407 			return ERR_CAST(pd->smi);
408 	}
409 
410 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
411 		pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
412 		if (IS_ERR(pd->infracfg_nao))
413 			return ERR_CAST(pd->infracfg_nao);
414 	} else {
415 		pd->infracfg_nao = NULL;
416 	}
417 
418 	num_clks = of_clk_get_parent_count(node);
419 	if (num_clks > 0) {
420 		/* Calculate number of subsys_clks */
421 		of_property_for_each_string(node, "clock-names", prop, clk_name) {
422 			char *subsys;
423 
424 			subsys = strchr(clk_name, '-');
425 			if (subsys)
426 				pd->num_subsys_clks++;
427 			else
428 				pd->num_clks++;
429 		}
430 
431 		pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
432 		if (!pd->clks)
433 			return ERR_PTR(-ENOMEM);
434 
435 		pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
436 					       sizeof(*pd->subsys_clks), GFP_KERNEL);
437 		if (!pd->subsys_clks)
438 			return ERR_PTR(-ENOMEM);
439 
440 	}
441 
442 	for (i = 0; i < pd->num_clks; i++) {
443 		clk = of_clk_get(node, i);
444 		if (IS_ERR(clk)) {
445 			ret = PTR_ERR(clk);
446 			dev_err_probe(scpsys->dev, ret,
447 				      "%pOF: failed to get clk at index %d\n", node, i);
448 			goto err_put_clocks;
449 		}
450 
451 		pd->clks[clk_ind++].clk = clk;
452 	}
453 
454 	for (i = 0; i < pd->num_subsys_clks; i++) {
455 		clk = of_clk_get(node, i + clk_ind);
456 		if (IS_ERR(clk)) {
457 			ret = PTR_ERR(clk);
458 			dev_err_probe(scpsys->dev, ret,
459 				      "%pOF: failed to get clk at index %d\n", node,
460 				      i + clk_ind);
461 			goto err_put_subsys_clocks;
462 		}
463 
464 		pd->subsys_clks[i].clk = clk;
465 	}
466 
467 	/*
468 	 * Initially turn on all domains to make the domains usable
469 	 * with !CONFIG_PM and to get the hardware in sync with the
470 	 * software.  The unused domains will be switched off during
471 	 * late_init time.
472 	 */
473 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
474 		if (scpsys_domain_is_on(pd))
475 			dev_warn(scpsys->dev,
476 				 "%pOF: A default off power domain has been ON\n", node);
477 	} else {
478 		ret = scpsys_power_on(&pd->genpd);
479 		if (ret < 0) {
480 			dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
481 			goto err_put_subsys_clocks;
482 		}
483 
484 		if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
485 			pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
486 	}
487 
488 	if (scpsys->domains[id]) {
489 		ret = -EINVAL;
490 		dev_err(scpsys->dev,
491 			"power domain with id %d already exists, check your device-tree\n", id);
492 		goto err_put_subsys_clocks;
493 	}
494 
495 	if (!pd->data->name)
496 		pd->genpd.name = node->name;
497 	else
498 		pd->genpd.name = pd->data->name;
499 
500 	pd->genpd.power_off = scpsys_power_off;
501 	pd->genpd.power_on = scpsys_power_on;
502 
503 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_ACTIVE_WAKEUP))
504 		pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
505 
506 	if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
507 		pm_genpd_init(&pd->genpd, NULL, true);
508 	else
509 		pm_genpd_init(&pd->genpd, NULL, false);
510 
511 	scpsys->domains[id] = &pd->genpd;
512 
513 	return scpsys->pd_data.domains[id];
514 
515 err_put_subsys_clocks:
516 	clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
517 err_put_clocks:
518 	clk_bulk_put(pd->num_clks, pd->clks);
519 	return ERR_PTR(ret);
520 }
521 
scpsys_add_subdomain(struct scpsys * scpsys,struct device_node * parent)522 static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
523 {
524 	struct generic_pm_domain *child_pd, *parent_pd;
525 	struct device_node *child;
526 	int ret;
527 
528 	for_each_child_of_node(parent, child) {
529 		u32 id;
530 
531 		ret = of_property_read_u32(parent, "reg", &id);
532 		if (ret) {
533 			dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
534 			goto err_put_node;
535 		}
536 
537 		if (!scpsys->pd_data.domains[id]) {
538 			ret = -EINVAL;
539 			dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
540 			goto err_put_node;
541 		}
542 
543 		parent_pd = scpsys->pd_data.domains[id];
544 
545 		child_pd = scpsys_add_one_domain(scpsys, child);
546 		if (IS_ERR(child_pd)) {
547 			ret = PTR_ERR(child_pd);
548 			dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n",
549 				      child);
550 			goto err_put_node;
551 		}
552 
553 		/* recursive call to add all subdomains */
554 		ret = scpsys_add_subdomain(scpsys, child);
555 		if (ret)
556 			goto err_put_node;
557 
558 		ret = pm_genpd_add_subdomain(parent_pd, child_pd);
559 		if (ret) {
560 			dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
561 				child_pd->name, parent_pd->name);
562 			goto err_put_node;
563 		} else {
564 			dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
565 				child_pd->name);
566 		}
567 	}
568 
569 	return 0;
570 
571 err_put_node:
572 	of_node_put(child);
573 	return ret;
574 }
575 
scpsys_remove_one_domain(struct scpsys_domain * pd)576 static void scpsys_remove_one_domain(struct scpsys_domain *pd)
577 {
578 	int ret;
579 
580 	/*
581 	 * We're in the error cleanup already, so we only complain,
582 	 * but won't emit another error on top of the original one.
583 	 */
584 	ret = pm_genpd_remove(&pd->genpd);
585 	if (ret < 0)
586 		dev_err(pd->scpsys->dev,
587 			"failed to remove domain '%s' : %d - state may be inconsistent\n",
588 			pd->genpd.name, ret);
589 	if (scpsys_domain_is_on(pd))
590 		scpsys_power_off(&pd->genpd);
591 
592 	clk_bulk_put(pd->num_clks, pd->clks);
593 	clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
594 }
595 
scpsys_domain_cleanup(struct scpsys * scpsys)596 static void scpsys_domain_cleanup(struct scpsys *scpsys)
597 {
598 	struct generic_pm_domain *genpd;
599 	struct scpsys_domain *pd;
600 	int i;
601 
602 	for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
603 		genpd = scpsys->pd_data.domains[i];
604 		if (genpd) {
605 			pd = to_scpsys_domain(genpd);
606 			scpsys_remove_one_domain(pd);
607 		}
608 	}
609 }
610 
611 static const struct of_device_id scpsys_of_match[] = {
612 	{
613 		.compatible = "mediatek,mt6735-power-controller",
614 		.data = &mt6735_scpsys_data,
615 	},
616 	{
617 		.compatible = "mediatek,mt6795-power-controller",
618 		.data = &mt6795_scpsys_data,
619 	},
620 	{
621 		.compatible = "mediatek,mt8167-power-controller",
622 		.data = &mt8167_scpsys_data,
623 	},
624 	{
625 		.compatible = "mediatek,mt8173-power-controller",
626 		.data = &mt8173_scpsys_data,
627 	},
628 	{
629 		.compatible = "mediatek,mt8183-power-controller",
630 		.data = &mt8183_scpsys_data,
631 	},
632 	{
633 		.compatible = "mediatek,mt8186-power-controller",
634 		.data = &mt8186_scpsys_data,
635 	},
636 	{
637 		.compatible = "mediatek,mt8188-power-controller",
638 		.data = &mt8188_scpsys_data,
639 	},
640 	{
641 		.compatible = "mediatek,mt8192-power-controller",
642 		.data = &mt8192_scpsys_data,
643 	},
644 	{
645 		.compatible = "mediatek,mt8195-power-controller",
646 		.data = &mt8195_scpsys_data,
647 	},
648 	{
649 		.compatible = "mediatek,mt8365-power-controller",
650 		.data = &mt8365_scpsys_data,
651 	},
652 	{ }
653 };
654 
scpsys_probe(struct platform_device * pdev)655 static int scpsys_probe(struct platform_device *pdev)
656 {
657 	struct device *dev = &pdev->dev;
658 	struct device_node *np = dev->of_node;
659 	const struct scpsys_soc_data *soc;
660 	struct device_node *node;
661 	struct device *parent;
662 	struct scpsys *scpsys;
663 	int ret;
664 
665 	soc = of_device_get_match_data(&pdev->dev);
666 	if (!soc) {
667 		dev_err(&pdev->dev, "no power controller data\n");
668 		return -EINVAL;
669 	}
670 
671 	scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL);
672 	if (!scpsys)
673 		return -ENOMEM;
674 
675 	scpsys->dev = dev;
676 	scpsys->soc_data = soc;
677 
678 	scpsys->pd_data.domains = scpsys->domains;
679 	scpsys->pd_data.num_domains = soc->num_domains;
680 
681 	parent = dev->parent;
682 	if (!parent) {
683 		dev_err(dev, "no parent for syscon devices\n");
684 		return -ENODEV;
685 	}
686 
687 	scpsys->base = syscon_node_to_regmap(parent->of_node);
688 	if (IS_ERR(scpsys->base)) {
689 		dev_err(dev, "no regmap available\n");
690 		return PTR_ERR(scpsys->base);
691 	}
692 
693 	ret = -ENODEV;
694 	for_each_available_child_of_node(np, node) {
695 		struct generic_pm_domain *domain;
696 
697 		domain = scpsys_add_one_domain(scpsys, node);
698 		if (IS_ERR(domain)) {
699 			ret = PTR_ERR(domain);
700 			of_node_put(node);
701 			goto err_cleanup_domains;
702 		}
703 
704 		ret = scpsys_add_subdomain(scpsys, node);
705 		if (ret) {
706 			of_node_put(node);
707 			goto err_cleanup_domains;
708 		}
709 	}
710 
711 	if (ret) {
712 		dev_dbg(dev, "no power domains present\n");
713 		return ret;
714 	}
715 
716 	ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
717 	if (ret) {
718 		dev_err(dev, "failed to add provider: %d\n", ret);
719 		goto err_cleanup_domains;
720 	}
721 
722 	return 0;
723 
724 err_cleanup_domains:
725 	scpsys_domain_cleanup(scpsys);
726 	return ret;
727 }
728 
729 static struct platform_driver scpsys_pm_domain_driver = {
730 	.probe = scpsys_probe,
731 	.driver = {
732 		.name = "mtk-power-controller",
733 		.suppress_bind_attrs = true,
734 		.of_match_table = scpsys_of_match,
735 	},
736 };
737 builtin_platform_driver(scpsys_pm_domain_driver);
738