Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pmdomain: mediatek: Refactor bus protection regmaps retrieval

In preparation to add support for new generation SoCs like MT8196,
MT6991 and other variants, which require to set bus protection on
different busses than the ones found on legacy chips, and to also
simplify and reduce memory footprint of this driver, refactor the
mechanism to retrieve and use the bus protection regmaps.

This is done by removing the three pointers to struct regmap from
struct scpsys_domain (allocated for each power domain) and moving
them to the main struct scpsys (allocated per driver instance) as
an array of pointers to regmap named **bus_prot.

That deprecates the old devicetree properties to grab phandles to
the three predefined busses (infracfg, infracfg-nao and smi) and
replaces it with the base property "access-controllers" that is
meant to be an array of phandles holding the same busses where
required (for now - for legacy SoCs).

The new bus protection phandles are indexed by the bus_prot_index
member of struct scpsys, used to map "bus type" (ex.: infra, smi,
etc) to the specific *bus_prot[x] element.

While the old per-power-domain regmap pointers were removed, the
support for old devicetree was retained by still checking if the
new property (in DT) and new-style declaration (in SoC specific
platform data) are both present at probe time.

If those are not present, a lookup for the old properties will be
done in all of the children of the power controller, and pointers
to regmaps will be retrieved with the old properties, but then
will be internally remapped to follow the new style regmap anyway
as to let this driver benefit of the memory footprint reduction.

Finally, it was necessary to change macros in mtk-pm-domains.h and
in mt8365-pm-domains.h to make use of the new style bus protection
declaration, as the actual HW block is now recognized not by flags
but by its own scpsys_bus_prot_block enumeration.

The BUS_PROT_(STA)_COMPONENT_{INFRA,INFRA_NAO,SMI} flags were also
removed since they are now unused, and because that enumeration was
initially meant to vary the logic of bus protection and not the bus
where work is performed, anyway!

Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20250805074746.29457-5-angelogioacchino.delregno@collabora.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

AngeloGioacchino Del Regno and committed by
Ulf Hansson
c29345fa d10c9858

+187 -62
+3 -5
drivers/pmdomain/mediatek/mt8365-pm-domains.h
··· 29 29 MT8365_SMI_COMMON_CLAMP_EN) 30 30 31 31 #define MT8365_BUS_PROT_WAY_EN(_set_mask, _set, _sta_mask, _sta) \ 32 - _BUS_PROT(_set_mask, _set, _set, _sta_mask, _sta, \ 33 - BUS_PROT_COMPONENT_INFRA | \ 34 - BUS_PROT_STA_COMPONENT_INFRA_NAO | \ 35 - BUS_PROT_INVERTED | \ 36 - BUS_PROT_REG_UPDATE) 32 + _BUS_PROT_STA(INFRA, INFRA_NAO, _set_mask, _set, _set, \ 33 + _sta_mask, _sta, \ 34 + BUS_PROT_INVERTED | BUS_PROT_REG_UPDATE) 37 35 38 36 static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = { 39 37 [MT8365_POWER_DOMAIN_MM] = {
+149 -39
drivers/pmdomain/mediatek/mtk-pm-domains.c
··· 47 47 struct clk_bulk_data *clks; 48 48 int num_subsys_clks; 49 49 struct clk_bulk_data *subsys_clks; 50 - struct regmap *infracfg_nao; 51 - struct regmap *infracfg; 52 - struct regmap *smi; 53 50 struct regulator *supply; 54 51 }; 55 52 ··· 54 57 struct device *dev; 55 58 struct regmap *base; 56 59 const struct scpsys_soc_data *soc_data; 60 + u8 bus_prot_index[BUS_PROT_BLOCK_COUNT]; 61 + struct regmap **bus_prot; 57 62 struct genpd_onecell_data pd_data; 58 63 struct generic_pm_domain *domains[]; 59 64 }; ··· 124 125 static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd, 125 126 const struct scpsys_bus_prot_data *bpd) 126 127 { 127 - if (bpd->flags & BUS_PROT_COMPONENT_SMI) 128 - return pd->smi; 129 - else 130 - return pd->infracfg; 128 + struct scpsys *scpsys = pd->scpsys; 129 + unsigned short block_idx = scpsys->bus_prot_index[bpd->bus_prot_block]; 130 + 131 + return scpsys->bus_prot[block_idx]; 131 132 } 132 133 133 134 static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd, 134 135 const struct scpsys_bus_prot_data *bpd) 135 136 { 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); 137 + struct scpsys *scpsys = pd->scpsys; 138 + int block_idx = scpsys->bus_prot_index[bpd->bus_prot_sta_block]; 139 + 140 + return scpsys->bus_prot[block_idx]; 140 141 } 141 142 142 143 static int scpsys_bus_protect_clear(struct scpsys_domain *pd, ··· 148 149 u32 expected_ack; 149 150 u32 val; 150 151 151 - expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0); 152 + expected_ack = (bpd->bus_prot_sta_block == BUS_PROT_BLOCK_INFRA_NAO ? sta_mask : 0); 152 153 153 154 if (bpd->flags & BUS_PROT_REG_UPDATE) 154 155 regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask); ··· 354 355 { 355 356 const struct scpsys_domain_data *domain_data; 356 357 struct scpsys_domain *pd; 357 - struct device_node *smi_node; 358 358 struct property *prop; 359 359 const char *clk_name; 360 360 int i, ret, num_clks; ··· 392 394 return dev_err_cast_probe(scpsys->dev, pd->supply, 393 395 "%pOF: failed to get power supply.\n", 394 396 node); 395 - } 396 - 397 - pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg"); 398 - if (IS_ERR(pd->infracfg)) 399 - return dev_err_cast_probe(scpsys->dev, pd->infracfg, 400 - "%pOF: failed to get infracfg regmap\n", 401 - node); 402 - 403 - smi_node = of_parse_phandle(node, "mediatek,smi", 0); 404 - if (smi_node) { 405 - pd->smi = device_node_to_regmap(smi_node); 406 - of_node_put(smi_node); 407 - if (IS_ERR(pd->smi)) 408 - return dev_err_cast_probe(scpsys->dev, pd->smi, 409 - "%pOF: failed to get SMI regmap\n", 410 - node); 411 - } 412 - 413 - if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) { 414 - pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao"); 415 - if (IS_ERR(pd->infracfg_nao)) 416 - return dev_err_cast_probe(scpsys->dev, pd->infracfg_nao, 417 - "%pOF: failed to get infracfg-nao regmap\n", 418 - node); 419 - } else { 420 - pd->infracfg_nao = NULL; 421 397 } 422 398 423 399 num_clks = of_clk_get_parent_count(node); ··· 587 615 } 588 616 } 589 617 618 + static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys) 619 + { 620 + const u8 bp_blocks[3] = { 621 + BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI, BUS_PROT_BLOCK_INFRA_NAO 622 + }; 623 + struct device_node *np = dev->of_node; 624 + struct device_node *node, *smi_np; 625 + int num_regmaps = 0, i, j; 626 + struct regmap *regmap[3]; 627 + 628 + /* 629 + * Legacy code retrieves a maximum of three bus protection handles: 630 + * some may be optional, or may not be, so the array of bp blocks 631 + * that is normally passed in as platform data must be dynamically 632 + * built in this case. 633 + * 634 + * Here, try to retrieve all of the regmaps that the legacy code 635 + * supported and then count the number of the ones that are present, 636 + * this makes it then possible to allocate the array of bus_prot 637 + * regmaps and convert all to the new style handling. 638 + */ 639 + node = of_find_node_with_property(np, "mediatek,infracfg"); 640 + if (node) { 641 + regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg"); 642 + of_node_put(node); 643 + num_regmaps++; 644 + if (IS_ERR(regmap[0])) 645 + return dev_err_probe(dev, PTR_ERR(regmap[0]), 646 + "%pOF: failed to get infracfg regmap\n", 647 + node); 648 + } else { 649 + regmap[0] = NULL; 650 + } 651 + 652 + node = of_find_node_with_property(np, "mediatek,smi"); 653 + if (node) { 654 + smi_np = of_parse_phandle(node, "mediatek,smi", 0); 655 + of_node_put(node); 656 + if (!smi_np) 657 + return -ENODEV; 658 + 659 + regmap[1] = device_node_to_regmap(smi_np); 660 + num_regmaps++; 661 + of_node_put(smi_np); 662 + if (IS_ERR(regmap[1])) 663 + return dev_err_probe(dev, PTR_ERR(regmap[1]), 664 + "%pOF: failed to get SMI regmap\n", 665 + node); 666 + } else { 667 + regmap[1] = NULL; 668 + } 669 + 670 + node = of_find_node_with_property(np, "mediatek,infracfg-nao"); 671 + if (node) { 672 + regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao"); 673 + num_regmaps++; 674 + of_node_put(node); 675 + if (IS_ERR(regmap[2])) 676 + return dev_err_probe(dev, PTR_ERR(regmap[2]), 677 + "%pOF: failed to get infracfg regmap\n", 678 + node); 679 + } else { 680 + regmap[2] = NULL; 681 + } 682 + 683 + scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps, 684 + sizeof(*scpsys->bus_prot), GFP_KERNEL); 685 + if (!scpsys->bus_prot) 686 + return -ENOMEM; 687 + 688 + for (i = 0, j = 0; i < ARRAY_SIZE(bp_blocks); i++) { 689 + enum scpsys_bus_prot_block bp_type; 690 + 691 + if (!regmap[i]) 692 + continue; 693 + 694 + bp_type = bp_blocks[i]; 695 + scpsys->bus_prot_index[bp_type] = j; 696 + scpsys->bus_prot[j] = regmap[i]; 697 + 698 + j++; 699 + } 700 + 701 + return 0; 702 + } 703 + 704 + static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys) 705 + { 706 + const struct scpsys_soc_data *soc = scpsys->soc_data; 707 + struct device_node *np = dev->of_node; 708 + int i, num_handles; 709 + 710 + num_handles = of_count_phandle_with_args(np, "access-controllers", NULL); 711 + if (num_handles < 0 || num_handles != soc->num_bus_prot_blocks) 712 + return dev_err_probe(dev, -EINVAL, 713 + "Cannot get access controllers: expected %u, got %d\n", 714 + soc->num_bus_prot_blocks, num_handles); 715 + 716 + scpsys->bus_prot = devm_kmalloc_array(dev, soc->num_bus_prot_blocks, 717 + sizeof(*scpsys->bus_prot), GFP_KERNEL); 718 + if (!scpsys->bus_prot) 719 + return -ENOMEM; 720 + 721 + for (i = 0; i < soc->num_bus_prot_blocks; i++) { 722 + enum scpsys_bus_prot_block bp_type; 723 + struct device_node *node; 724 + 725 + node = of_parse_phandle(np, "access-controllers", i); 726 + if (!node) 727 + return -EINVAL; 728 + 729 + /* 730 + * Index the bus protection regmaps so that we don't have to 731 + * find the right one by type with a loop at every execution 732 + * of power sequence(s). 733 + */ 734 + bp_type = soc->bus_prot_blocks[i]; 735 + scpsys->bus_prot_index[bp_type] = i; 736 + 737 + scpsys->bus_prot[i] = device_node_to_regmap(node); 738 + of_node_put(node); 739 + if (IS_ERR_OR_NULL(scpsys->bus_prot[i])) 740 + return dev_err_probe(dev, scpsys->bus_prot[i] ? 741 + PTR_ERR(scpsys->bus_prot[i]) : -ENXIO, 742 + "Cannot get regmap for access controller %d\n", i); 743 + } 744 + 745 + return 0; 746 + } 747 + 590 748 static const struct of_device_id scpsys_of_match[] = { 591 749 { 592 750 .compatible = "mediatek,mt6735-power-controller", ··· 802 700 dev_err(dev, "no regmap available\n"); 803 701 return PTR_ERR(scpsys->base); 804 702 } 703 + 704 + if (of_find_property(np, "access-controllers", NULL)) 705 + ret = scpsys_get_bus_protection(dev, scpsys); 706 + else 707 + ret = scpsys_get_bus_protection_legacy(dev, scpsys); 708 + 709 + if (ret) 710 + return ret; 805 711 806 712 ret = -ENODEV; 807 713 for_each_available_child_of_node(np, node) {
+35 -18
drivers/pmdomain/mediatek/mtk-pm-domains.h
··· 50 50 BUS_PROT_REG_UPDATE = BIT(1), 51 51 BUS_PROT_IGNORE_CLR_ACK = BIT(2), 52 52 BUS_PROT_INVERTED = BIT(3), 53 - BUS_PROT_COMPONENT_INFRA = BIT(4), 54 - BUS_PROT_COMPONENT_SMI = BIT(5), 55 - BUS_PROT_STA_COMPONENT_INFRA_NAO = BIT(6), 56 53 }; 57 54 58 - #define _BUS_PROT(_set_clr_mask, _set, _clr, _sta_mask, _sta, _flags) { \ 59 - .bus_prot_set_clr_mask = (_set_clr_mask), \ 60 - .bus_prot_set = _set, \ 61 - .bus_prot_clr = _clr, \ 62 - .bus_prot_sta_mask = (_sta_mask), \ 63 - .bus_prot_sta = _sta, \ 64 - .flags = _flags \ 55 + enum scpsys_bus_prot_block { 56 + BUS_PROT_BLOCK_INFRA, 57 + BUS_PROT_BLOCK_INFRA_NAO, 58 + BUS_PROT_BLOCK_SMI, 59 + BUS_PROT_BLOCK_COUNT, 60 + }; 61 + 62 + #define _BUS_PROT_STA(_hwip, _sta_hwip, _set_clr_mask, _set, _clr, \ 63 + _sta_mask, _sta, _flags) \ 64 + { \ 65 + .bus_prot_block = BUS_PROT_BLOCK_##_hwip, \ 66 + .bus_prot_sta_block = BUS_PROT_BLOCK_##_sta_hwip, \ 67 + .bus_prot_set_clr_mask = (_set_clr_mask), \ 68 + .bus_prot_set = _set, \ 69 + .bus_prot_clr = _clr, \ 70 + .bus_prot_sta_mask = (_sta_mask), \ 71 + .bus_prot_sta = _sta, \ 72 + .flags = _flags \ 65 73 } 66 74 67 - #define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \ 68 - _BUS_PROT(_mask, _set, _clr, _mask, _sta, BUS_PROT_COMPONENT_##_hwip) 75 + #define _BUS_PROT(_hwip, _set_clr_mask, _set, _clr, _sta_mask, \ 76 + _sta, _flags) \ 77 + _BUS_PROT_STA(_hwip, _hwip, _set_clr_mask, _set, _clr, \ 78 + _sta_mask, _sta, _flags) 69 79 70 - #define BUS_PROT_WR_IGN(_hwip, _mask, _set, _clr, _sta) \ 71 - _BUS_PROT(_mask, _set, _clr, _mask, _sta, \ 72 - BUS_PROT_COMPONENT_##_hwip | BUS_PROT_IGNORE_CLR_ACK) 80 + #define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \ 81 + _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, 0) 73 82 74 - #define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \ 75 - _BUS_PROT(_mask, _set, _clr, _mask, _sta, \ 76 - BUS_PROT_COMPONENT_##_hwip | BUS_PROT_REG_UPDATE) 83 + #define BUS_PROT_WR_IGN(_hwip, _mask, _set, _clr, _sta) \ 84 + _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \ 85 + BUS_PROT_IGNORE_CLR_ACK) 86 + 87 + #define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \ 88 + _BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \ 89 + BUS_PROT_REG_UPDATE) 77 90 78 91 #define BUS_PROT_INFRA_UPDATE_TOPAXI(_mask) \ 79 92 BUS_PROT_UPDATE(INFRA, _mask, \ ··· 95 82 INFRA_TOPAXI_PROTECTSTA1) 96 83 97 84 struct scpsys_bus_prot_data { 85 + u8 bus_prot_block; 86 + u8 bus_prot_sta_block; 98 87 u32 bus_prot_set_clr_mask; 99 88 u32 bus_prot_set; 100 89 u32 bus_prot_clr; ··· 134 119 struct scpsys_soc_data { 135 120 const struct scpsys_domain_data *domains_data; 136 121 int num_domains; 122 + enum scpsys_bus_prot_block *bus_prot_blocks; 123 + int num_bus_prot_blocks; 137 124 }; 138 125 139 126 #endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */