• Home
  • Raw
  • Download

Lines Matching +full:power +full:- +full:domain +full:- +full:node

1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <linux/clk-provider.h>
19 #include "mt6795-pm-domains.h"
20 #include "mt8167-pm-domains.h"
21 #include "mt8173-pm-domains.h"
22 #include "mt8183-pm-domains.h"
23 #include "mt8186-pm-domains.h"
24 #include "mt8188-pm-domains.h"
25 #include "mt8192-pm-domains.h"
26 #include "mt8195-pm-domains.h"
64 struct scpsys *scpsys = pd->scpsys; in scpsys_domain_is_on()
67 regmap_read(scpsys->base, pd->data->pwr_sta_offs, &status); in scpsys_domain_is_on()
68 status &= pd->data->sta_mask; in scpsys_domain_is_on()
70 regmap_read(scpsys->base, pd->data->pwr_sta2nd_offs, &status2); in scpsys_domain_is_on()
71 status2 &= pd->data->sta_mask; in scpsys_domain_is_on()
73 /* A domain is on when both status bits are set. */ in scpsys_domain_is_on()
79 u32 pdn_ack = pd->data->sram_pdn_ack_bits; in scpsys_sram_enable()
80 struct scpsys *scpsys = pd->scpsys; in scpsys_sram_enable()
84 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); in scpsys_sram_enable()
87 ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, in scpsys_sram_enable()
93 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); in scpsys_sram_enable()
95 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); in scpsys_sram_enable()
103 u32 pdn_ack = pd->data->sram_pdn_ack_bits; in scpsys_sram_disable()
104 struct scpsys *scpsys = pd->scpsys; in scpsys_sram_disable()
108 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT); in scpsys_sram_disable()
110 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT); in scpsys_sram_disable()
113 regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits); in scpsys_sram_disable()
116 return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp, in scpsys_sram_disable()
150 ret = _scpsys_bus_protect_enable(pd->data->bp_infracfg, pd->infracfg); in scpsys_bus_protect_enable()
154 return _scpsys_bus_protect_enable(pd->data->bp_smi, pd->smi); in scpsys_bus_protect_enable()
162 for (i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) { in _scpsys_bus_protect_disable()
190 ret = _scpsys_bus_protect_disable(pd->data->bp_smi, pd->smi); in scpsys_bus_protect_disable()
194 return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg); in scpsys_bus_protect_disable()
210 struct scpsys *scpsys = pd->scpsys; in scpsys_power_on()
214 ret = scpsys_regulator_enable(pd->supply); in scpsys_power_on()
218 ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks); in scpsys_power_on()
222 if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) in scpsys_power_on()
223 regmap_clear_bits(scpsys->base, pd->data->ext_buck_iso_offs, in scpsys_power_on()
224 pd->data->ext_buck_iso_mask); in scpsys_power_on()
226 /* subsys power on */ in scpsys_power_on()
227 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); in scpsys_power_on()
228 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); in scpsys_power_on()
236 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); in scpsys_power_on()
237 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); in scpsys_power_on()
238 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); in scpsys_power_on()
240 ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks); in scpsys_power_on()
257 clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); in scpsys_power_on()
259 clk_bulk_disable_unprepare(pd->num_clks, pd->clks); in scpsys_power_on()
261 scpsys_regulator_disable(pd->supply); in scpsys_power_on()
268 struct scpsys *scpsys = pd->scpsys; in scpsys_power_off()
280 if (pd->data->ext_buck_iso_offs && MTK_SCPD_CAPS(pd, MTK_SCPD_EXT_BUCK_ISO)) in scpsys_power_off()
281 regmap_set_bits(scpsys->base, pd->data->ext_buck_iso_offs, in scpsys_power_off()
282 pd->data->ext_buck_iso_mask); in scpsys_power_off()
284 clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); in scpsys_power_off()
286 /* subsys power off */ in scpsys_power_off()
287 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); in scpsys_power_off()
288 regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); in scpsys_power_off()
289 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); in scpsys_power_off()
290 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); in scpsys_power_off()
291 regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); in scpsys_power_off()
299 clk_bulk_disable_unprepare(pd->num_clks, pd->clks); in scpsys_power_off()
301 scpsys_regulator_disable(pd->supply); in scpsys_power_off()
307 generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node) in scpsys_add_one_domain() argument
311 struct device_node *root_node = scpsys->dev->of_node; in scpsys_add_one_domain()
320 ret = of_property_read_u32(node, "reg", &id); in scpsys_add_one_domain()
322 dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n", in scpsys_add_one_domain()
323 node, ret); in scpsys_add_one_domain()
324 return ERR_PTR(-EINVAL); in scpsys_add_one_domain()
327 if (id >= scpsys->soc_data->num_domains) { in scpsys_add_one_domain()
328 dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id); in scpsys_add_one_domain()
329 return ERR_PTR(-EINVAL); in scpsys_add_one_domain()
332 domain_data = &scpsys->soc_data->domains_data[id]; in scpsys_add_one_domain()
333 if (domain_data->sta_mask == 0) { in scpsys_add_one_domain()
334 dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id); in scpsys_add_one_domain()
335 return ERR_PTR(-EINVAL); in scpsys_add_one_domain()
338 pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL); in scpsys_add_one_domain()
340 return ERR_PTR(-ENOMEM); in scpsys_add_one_domain()
342 pd->data = domain_data; in scpsys_add_one_domain()
343 pd->scpsys = scpsys; in scpsys_add_one_domain()
347 * Find regulator in current power domain node. in scpsys_add_one_domain()
348 * devm_regulator_get() finds regulator in a node and its child in scpsys_add_one_domain()
349 * node, so set of_node to current power domain node then change in scpsys_add_one_domain()
350 * back to original node after regulator is found for current in scpsys_add_one_domain()
351 * power domain node. in scpsys_add_one_domain()
353 scpsys->dev->of_node = node; in scpsys_add_one_domain()
354 pd->supply = devm_regulator_get(scpsys->dev, "domain"); in scpsys_add_one_domain()
355 scpsys->dev->of_node = root_node; in scpsys_add_one_domain()
356 if (IS_ERR(pd->supply)) { in scpsys_add_one_domain()
357 dev_err_probe(scpsys->dev, PTR_ERR(pd->supply), in scpsys_add_one_domain()
358 "%pOF: failed to get power supply.\n", in scpsys_add_one_domain()
359 node); in scpsys_add_one_domain()
360 return ERR_CAST(pd->supply); in scpsys_add_one_domain()
364 pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); in scpsys_add_one_domain()
365 if (IS_ERR(pd->infracfg)) in scpsys_add_one_domain()
366 return ERR_CAST(pd->infracfg); in scpsys_add_one_domain()
368 smi_node = of_parse_phandle(node, "mediatek,smi", 0); in scpsys_add_one_domain()
370 pd->smi = device_node_to_regmap(smi_node); in scpsys_add_one_domain()
372 if (IS_ERR(pd->smi)) in scpsys_add_one_domain()
373 return ERR_CAST(pd->smi); in scpsys_add_one_domain()
376 num_clks = of_clk_get_parent_count(node); in scpsys_add_one_domain()
379 of_property_for_each_string(node, "clock-names", prop, clk_name) { in scpsys_add_one_domain()
382 subsys = strchr(clk_name, '-'); in scpsys_add_one_domain()
384 pd->num_subsys_clks++; in scpsys_add_one_domain()
386 pd->num_clks++; in scpsys_add_one_domain()
389 pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL); in scpsys_add_one_domain()
390 if (!pd->clks) in scpsys_add_one_domain()
391 return ERR_PTR(-ENOMEM); in scpsys_add_one_domain()
393 pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks, in scpsys_add_one_domain()
394 sizeof(*pd->subsys_clks), GFP_KERNEL); in scpsys_add_one_domain()
395 if (!pd->subsys_clks) in scpsys_add_one_domain()
396 return ERR_PTR(-ENOMEM); in scpsys_add_one_domain()
400 for (i = 0; i < pd->num_clks; i++) { in scpsys_add_one_domain()
401 clk = of_clk_get(node, i); in scpsys_add_one_domain()
404 dev_err_probe(scpsys->dev, ret, in scpsys_add_one_domain()
405 "%pOF: failed to get clk at index %d\n", node, i); in scpsys_add_one_domain()
409 pd->clks[clk_ind++].clk = clk; in scpsys_add_one_domain()
412 for (i = 0; i < pd->num_subsys_clks; i++) { in scpsys_add_one_domain()
413 clk = of_clk_get(node, i + clk_ind); in scpsys_add_one_domain()
416 dev_err_probe(scpsys->dev, ret, in scpsys_add_one_domain()
417 "%pOF: failed to get clk at index %d\n", node, in scpsys_add_one_domain()
422 pd->subsys_clks[i].clk = clk; in scpsys_add_one_domain()
433 dev_warn(scpsys->dev, in scpsys_add_one_domain()
434 "%pOF: A default off power domain has been ON\n", node); in scpsys_add_one_domain()
436 ret = scpsys_power_on(&pd->genpd); in scpsys_add_one_domain()
438 dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret); in scpsys_add_one_domain()
443 pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; in scpsys_add_one_domain()
446 if (scpsys->domains[id]) { in scpsys_add_one_domain()
447 ret = -EINVAL; in scpsys_add_one_domain()
448 dev_err(scpsys->dev, in scpsys_add_one_domain()
449 "power domain with id %d already exists, check your device-tree\n", id); in scpsys_add_one_domain()
453 if (!pd->data->name) in scpsys_add_one_domain()
454 pd->genpd.name = node->name; in scpsys_add_one_domain()
456 pd->genpd.name = pd->data->name; in scpsys_add_one_domain()
458 pd->genpd.power_off = scpsys_power_off; in scpsys_add_one_domain()
459 pd->genpd.power_on = scpsys_power_on; in scpsys_add_one_domain()
462 pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; in scpsys_add_one_domain()
465 pm_genpd_init(&pd->genpd, NULL, true); in scpsys_add_one_domain()
467 pm_genpd_init(&pd->genpd, NULL, false); in scpsys_add_one_domain()
469 scpsys->domains[id] = &pd->genpd; in scpsys_add_one_domain()
471 return scpsys->pd_data.domains[id]; in scpsys_add_one_domain()
474 clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); in scpsys_add_one_domain()
476 clk_bulk_put(pd->num_clks, pd->clks); in scpsys_add_one_domain()
491 dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child); in scpsys_add_subdomain()
495 if (!scpsys->pd_data.domains[id]) { in scpsys_add_subdomain()
496 ret = -EINVAL; in scpsys_add_subdomain()
497 dev_err(scpsys->dev, "power domain with id %d does not exist\n", id); in scpsys_add_subdomain()
501 parent_pd = scpsys->pd_data.domains[id]; in scpsys_add_subdomain()
506 dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n", in scpsys_add_subdomain()
518 dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n", in scpsys_add_subdomain()
519 child_pd->name, parent_pd->name); in scpsys_add_subdomain()
522 dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name, in scpsys_add_subdomain()
523 child_pd->name); in scpsys_add_subdomain()
542 ret = pm_genpd_remove(&pd->genpd); in scpsys_remove_one_domain()
544 dev_err(pd->scpsys->dev, in scpsys_remove_one_domain()
545 "failed to remove domain '%s' : %d - state may be inconsistent\n", in scpsys_remove_one_domain()
546 pd->genpd.name, ret); in scpsys_remove_one_domain()
548 scpsys_power_off(&pd->genpd); in scpsys_remove_one_domain()
550 clk_bulk_put(pd->num_clks, pd->clks); in scpsys_remove_one_domain()
551 clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks); in scpsys_remove_one_domain()
560 for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) { in scpsys_domain_cleanup()
561 genpd = scpsys->pd_data.domains[i]; in scpsys_domain_cleanup()
571 .compatible = "mediatek,mt6795-power-controller",
575 .compatible = "mediatek,mt8167-power-controller",
579 .compatible = "mediatek,mt8173-power-controller",
583 .compatible = "mediatek,mt8183-power-controller",
587 .compatible = "mediatek,mt8186-power-controller",
591 .compatible = "mediatek,mt8188-power-controller",
595 .compatible = "mediatek,mt8192-power-controller",
599 .compatible = "mediatek,mt8195-power-controller",
607 struct device *dev = &pdev->dev; in scpsys_probe()
608 struct device_node *np = dev->of_node; in scpsys_probe()
610 struct device_node *node; in scpsys_probe() local
615 soc = of_device_get_match_data(&pdev->dev); in scpsys_probe()
617 dev_err(&pdev->dev, "no power controller data\n"); in scpsys_probe()
618 return -EINVAL; in scpsys_probe()
621 scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL); in scpsys_probe()
623 return -ENOMEM; in scpsys_probe()
625 scpsys->dev = dev; in scpsys_probe()
626 scpsys->soc_data = soc; in scpsys_probe()
628 scpsys->pd_data.domains = scpsys->domains; in scpsys_probe()
629 scpsys->pd_data.num_domains = soc->num_domains; in scpsys_probe()
631 parent = dev->parent; in scpsys_probe()
634 return -ENODEV; in scpsys_probe()
637 scpsys->base = syscon_node_to_regmap(parent->of_node); in scpsys_probe()
638 if (IS_ERR(scpsys->base)) { in scpsys_probe()
640 return PTR_ERR(scpsys->base); in scpsys_probe()
643 ret = -ENODEV; in scpsys_probe()
644 for_each_available_child_of_node(np, node) { in scpsys_probe()
645 struct generic_pm_domain *domain; in scpsys_probe() local
647 domain = scpsys_add_one_domain(scpsys, node); in scpsys_probe()
648 if (IS_ERR(domain)) { in scpsys_probe()
649 ret = PTR_ERR(domain); in scpsys_probe()
650 of_node_put(node); in scpsys_probe()
654 ret = scpsys_add_subdomain(scpsys, node); in scpsys_probe()
656 of_node_put(node); in scpsys_probe()
662 dev_dbg(dev, "no power domains present\n"); in scpsys_probe()
666 ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data); in scpsys_probe()
682 .name = "mtk-power-controller",