Skip to content

Commit c29345f

Browse files
AngeloGioacchino Del Regnostorulf
authored andcommitted
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>
1 parent d10c985 commit c29345f

File tree

3 files changed

+187
-62
lines changed

3 files changed

+187
-62
lines changed

drivers/pmdomain/mediatek/mt8365-pm-domains.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@
2929
MT8365_SMI_COMMON_CLAMP_EN)
3030

3131
#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)
3735

3836
static const struct scpsys_domain_data scpsys_domain_data_mt8365[] = {
3937
[MT8365_POWER_DOMAIN_MM] = {

drivers/pmdomain/mediatek/mtk-pm-domains.c

Lines changed: 149 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,15 @@ struct scpsys_domain {
4747
struct clk_bulk_data *clks;
4848
int num_subsys_clks;
4949
struct clk_bulk_data *subsys_clks;
50-
struct regmap *infracfg_nao;
51-
struct regmap *infracfg;
52-
struct regmap *smi;
5350
struct regulator *supply;
5451
};
5552

5653
struct scpsys {
5754
struct device *dev;
5855
struct regmap *base;
5956
const struct scpsys_soc_data *soc_data;
57+
u8 bus_prot_index[BUS_PROT_BLOCK_COUNT];
58+
struct regmap **bus_prot;
6059
struct genpd_onecell_data pd_data;
6160
struct generic_pm_domain *domains[];
6261
};
@@ -125,19 +124,19 @@ static int scpsys_sram_disable(struct scpsys_domain *pd)
125124
static struct regmap *scpsys_bus_protect_get_regmap(struct scpsys_domain *pd,
126125
const struct scpsys_bus_prot_data *bpd)
127126
{
128-
if (bpd->flags & BUS_PROT_COMPONENT_SMI)
129-
return pd->smi;
130-
else
131-
return pd->infracfg;
127+
struct scpsys *scpsys = pd->scpsys;
128+
unsigned short block_idx = scpsys->bus_prot_index[bpd->bus_prot_block];
129+
130+
return scpsys->bus_prot[block_idx];
132131
}
133132

134133
static struct regmap *scpsys_bus_protect_get_sta_regmap(struct scpsys_domain *pd,
135134
const struct scpsys_bus_prot_data *bpd)
136135
{
137-
if (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO)
138-
return pd->infracfg_nao;
139-
else
140-
return scpsys_bus_protect_get_regmap(pd, bpd);
136+
struct scpsys *scpsys = pd->scpsys;
137+
int block_idx = scpsys->bus_prot_index[bpd->bus_prot_sta_block];
138+
139+
return scpsys->bus_prot[block_idx];
141140
}
142141

143142
static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
@@ -149,7 +148,7 @@ static int scpsys_bus_protect_clear(struct scpsys_domain *pd,
149148
u32 expected_ack;
150149
u32 val;
151150

152-
expected_ack = (bpd->flags & BUS_PROT_STA_COMPONENT_INFRA_NAO ? sta_mask : 0);
151+
expected_ack = (bpd->bus_prot_sta_block == BUS_PROT_BLOCK_INFRA_NAO ? sta_mask : 0);
153152

154153
if (bpd->flags & BUS_PROT_REG_UPDATE)
155154
regmap_clear_bits(regmap, bpd->bus_prot_clr, bpd->bus_prot_set_clr_mask);
@@ -355,7 +354,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
355354
{
356355
const struct scpsys_domain_data *domain_data;
357356
struct scpsys_domain *pd;
358-
struct device_node *smi_node;
359357
struct property *prop;
360358
const char *clk_name;
361359
int i, ret, num_clks;
@@ -396,32 +394,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
396394
node);
397395
}
398396

399-
pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
400-
if (IS_ERR(pd->infracfg))
401-
return dev_err_cast_probe(scpsys->dev, pd->infracfg,
402-
"%pOF: failed to get infracfg regmap\n",
403-
node);
404-
405-
smi_node = of_parse_phandle(node, "mediatek,smi", 0);
406-
if (smi_node) {
407-
pd->smi = device_node_to_regmap(smi_node);
408-
of_node_put(smi_node);
409-
if (IS_ERR(pd->smi))
410-
return dev_err_cast_probe(scpsys->dev, pd->smi,
411-
"%pOF: failed to get SMI regmap\n",
412-
node);
413-
}
414-
415-
if (MTK_SCPD_CAPS(pd, MTK_SCPD_HAS_INFRA_NAO)) {
416-
pd->infracfg_nao = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
417-
if (IS_ERR(pd->infracfg_nao))
418-
return dev_err_cast_probe(scpsys->dev, pd->infracfg_nao,
419-
"%pOF: failed to get infracfg-nao regmap\n",
420-
node);
421-
} else {
422-
pd->infracfg_nao = NULL;
423-
}
424-
425397
num_clks = of_clk_get_parent_count(node);
426398
if (num_clks > 0) {
427399
/* Calculate number of subsys_clks */
@@ -615,6 +587,136 @@ static void scpsys_domain_cleanup(struct scpsys *scpsys)
615587
}
616588
}
617589

590+
static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *scpsys)
591+
{
592+
const u8 bp_blocks[3] = {
593+
BUS_PROT_BLOCK_INFRA, BUS_PROT_BLOCK_SMI, BUS_PROT_BLOCK_INFRA_NAO
594+
};
595+
struct device_node *np = dev->of_node;
596+
struct device_node *node, *smi_np;
597+
int num_regmaps = 0, i, j;
598+
struct regmap *regmap[3];
599+
600+
/*
601+
* Legacy code retrieves a maximum of three bus protection handles:
602+
* some may be optional, or may not be, so the array of bp blocks
603+
* that is normally passed in as platform data must be dynamically
604+
* built in this case.
605+
*
606+
* Here, try to retrieve all of the regmaps that the legacy code
607+
* supported and then count the number of the ones that are present,
608+
* this makes it then possible to allocate the array of bus_prot
609+
* regmaps and convert all to the new style handling.
610+
*/
611+
node = of_find_node_with_property(np, "mediatek,infracfg");
612+
if (node) {
613+
regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
614+
of_node_put(node);
615+
num_regmaps++;
616+
if (IS_ERR(regmap[0]))
617+
return dev_err_probe(dev, PTR_ERR(regmap[0]),
618+
"%pOF: failed to get infracfg regmap\n",
619+
node);
620+
} else {
621+
regmap[0] = NULL;
622+
}
623+
624+
node = of_find_node_with_property(np, "mediatek,smi");
625+
if (node) {
626+
smi_np = of_parse_phandle(node, "mediatek,smi", 0);
627+
of_node_put(node);
628+
if (!smi_np)
629+
return -ENODEV;
630+
631+
regmap[1] = device_node_to_regmap(smi_np);
632+
num_regmaps++;
633+
of_node_put(smi_np);
634+
if (IS_ERR(regmap[1]))
635+
return dev_err_probe(dev, PTR_ERR(regmap[1]),
636+
"%pOF: failed to get SMI regmap\n",
637+
node);
638+
} else {
639+
regmap[1] = NULL;
640+
}
641+
642+
node = of_find_node_with_property(np, "mediatek,infracfg-nao");
643+
if (node) {
644+
regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
645+
num_regmaps++;
646+
of_node_put(node);
647+
if (IS_ERR(regmap[2]))
648+
return dev_err_probe(dev, PTR_ERR(regmap[2]),
649+
"%pOF: failed to get infracfg regmap\n",
650+
node);
651+
} else {
652+
regmap[2] = NULL;
653+
}
654+
655+
scpsys->bus_prot = devm_kmalloc_array(dev, num_regmaps,
656+
sizeof(*scpsys->bus_prot), GFP_KERNEL);
657+
if (!scpsys->bus_prot)
658+
return -ENOMEM;
659+
660+
for (i = 0, j = 0; i < ARRAY_SIZE(bp_blocks); i++) {
661+
enum scpsys_bus_prot_block bp_type;
662+
663+
if (!regmap[i])
664+
continue;
665+
666+
bp_type = bp_blocks[i];
667+
scpsys->bus_prot_index[bp_type] = j;
668+
scpsys->bus_prot[j] = regmap[i];
669+
670+
j++;
671+
}
672+
673+
return 0;
674+
}
675+
676+
static int scpsys_get_bus_protection(struct device *dev, struct scpsys *scpsys)
677+
{
678+
const struct scpsys_soc_data *soc = scpsys->soc_data;
679+
struct device_node *np = dev->of_node;
680+
int i, num_handles;
681+
682+
num_handles = of_count_phandle_with_args(np, "access-controllers", NULL);
683+
if (num_handles < 0 || num_handles != soc->num_bus_prot_blocks)
684+
return dev_err_probe(dev, -EINVAL,
685+
"Cannot get access controllers: expected %u, got %d\n",
686+
soc->num_bus_prot_blocks, num_handles);
687+
688+
scpsys->bus_prot = devm_kmalloc_array(dev, soc->num_bus_prot_blocks,
689+
sizeof(*scpsys->bus_prot), GFP_KERNEL);
690+
if (!scpsys->bus_prot)
691+
return -ENOMEM;
692+
693+
for (i = 0; i < soc->num_bus_prot_blocks; i++) {
694+
enum scpsys_bus_prot_block bp_type;
695+
struct device_node *node;
696+
697+
node = of_parse_phandle(np, "access-controllers", i);
698+
if (!node)
699+
return -EINVAL;
700+
701+
/*
702+
* Index the bus protection regmaps so that we don't have to
703+
* find the right one by type with a loop at every execution
704+
* of power sequence(s).
705+
*/
706+
bp_type = soc->bus_prot_blocks[i];
707+
scpsys->bus_prot_index[bp_type] = i;
708+
709+
scpsys->bus_prot[i] = device_node_to_regmap(node);
710+
of_node_put(node);
711+
if (IS_ERR_OR_NULL(scpsys->bus_prot[i]))
712+
return dev_err_probe(dev, scpsys->bus_prot[i] ?
713+
PTR_ERR(scpsys->bus_prot[i]) : -ENXIO,
714+
"Cannot get regmap for access controller %d\n", i);
715+
}
716+
717+
return 0;
718+
}
719+
618720
static const struct of_device_id scpsys_of_match[] = {
619721
{
620722
.compatible = "mediatek,mt6735-power-controller",
@@ -701,6 +803,14 @@ static int scpsys_probe(struct platform_device *pdev)
701803
return PTR_ERR(scpsys->base);
702804
}
703805

806+
if (of_find_property(np, "access-controllers", NULL))
807+
ret = scpsys_get_bus_protection(dev, scpsys);
808+
else
809+
ret = scpsys_get_bus_protection_legacy(dev, scpsys);
810+
811+
if (ret)
812+
return ret;
813+
704814
ret = -ENODEV;
705815
for_each_available_child_of_node(np, node) {
706816
struct generic_pm_domain *domain;

drivers/pmdomain/mediatek/mtk-pm-domains.h

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,30 +50,43 @@ enum scpsys_bus_prot_flags {
5050
BUS_PROT_REG_UPDATE = BIT(1),
5151
BUS_PROT_IGNORE_CLR_ACK = BIT(2),
5252
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),
5653
};
5754

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 \
6573
}
6674

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)
79+
80+
#define BUS_PROT_WR(_hwip, _mask, _set, _clr, _sta) \
81+
_BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, 0)
6982

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)
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)
7386

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)
87+
#define BUS_PROT_UPDATE(_hwip, _mask, _set, _clr, _sta) \
88+
_BUS_PROT(_hwip, _mask, _set, _clr, _mask, _sta, \
89+
BUS_PROT_REG_UPDATE)
7790

7891
#define BUS_PROT_INFRA_UPDATE_TOPAXI(_mask) \
7992
BUS_PROT_UPDATE(INFRA, _mask, \
@@ -82,6 +95,8 @@ enum scpsys_bus_prot_flags {
8295
INFRA_TOPAXI_PROTECTSTA1)
8396

8497
struct scpsys_bus_prot_data {
98+
u8 bus_prot_block;
99+
u8 bus_prot_sta_block;
85100
u32 bus_prot_set_clr_mask;
86101
u32 bus_prot_set;
87102
u32 bus_prot_clr;
@@ -119,6 +134,8 @@ struct scpsys_domain_data {
119134
struct scpsys_soc_data {
120135
const struct scpsys_domain_data *domains_data;
121136
int num_domains;
137+
enum scpsys_bus_prot_block *bus_prot_blocks;
138+
int num_bus_prot_blocks;
122139
};
123140

124141
#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */

0 commit comments

Comments
 (0)