Skip to content

Commit db6df2e

Browse files
srestorulf
authored andcommitted
pmdomain: rockchip: add regulator support
Some power domains require extra voltages to be applied. For example trying to enable the GPU power domain on RK3588 fails when the SoC does not have VDD GPU enabled. The same is expected to happen for the NPU, which also has a dedicated supply line. We get the regulator using devm_of_regulator_get(), so a missing dependency in the devicetree is handled gracefully by printing a warning and creating a dummy regulator. This is necessary, since existing DTs do not have the regulator described. They might still work if the regulator is marked as always-on. It is also working if the regulator is enabled at boot time and the GPU driver is probed before the kernel disables unused regulators. The regulator itself is not acquired at driver probe time, since that creates an unsolvable circular dependency. The power domain driver must be probed early, since SoC peripherals need it. Regulators on the other hand depend on SoC peripherals like SPI, I2C or GPIO. MediaTek does not run into this, since they have two power domain drivers. Tested-by: Heiko Stuebner <[email protected]> Reviewed-by: Heiko Stuebner <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]> Link: https://lore.kernel.org/r/20250220-rk3588-gpu-pwr-domain-regulator-v6-7-a4f9c24e5b81@kernel.org [Ulf: Fixed conflict when applying] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 6b2690d commit db6df2e

File tree

1 file changed

+79
-34
lines changed

1 file changed

+79
-34
lines changed

drivers/pmdomain/rockchip/pm-domains.c

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/of_clk.h>
2020
#include <linux/clk.h>
2121
#include <linux/regmap.h>
22+
#include <linux/regulator/consumer.h>
2223
#include <linux/mfd/syscon.h>
2324
#include <soc/rockchip/pm_domains.h>
2425
#include <soc/rockchip/rockchip_sip.h>
@@ -46,6 +47,7 @@ struct rockchip_domain_info {
4647
int idle_mask;
4748
int ack_mask;
4849
bool active_wakeup;
50+
bool need_regulator;
4951
int pwr_w_mask;
5052
int req_w_mask;
5153
int clk_ungate_mask;
@@ -94,6 +96,8 @@ struct rockchip_pm_domain {
9496
u32 *qos_save_regs[MAX_QOS_REGS_NUM];
9597
int num_clks;
9698
struct clk_bulk_data *clks;
99+
struct device_node *node;
100+
struct regulator *supply;
97101
};
98102

99103
struct rockchip_pmu {
@@ -131,7 +135,7 @@ struct rockchip_pmu {
131135
.active_wakeup = wakeup, \
132136
}
133137

134-
#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup) \
138+
#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup, regulator) \
135139
{ \
136140
.name = _name, \
137141
.pwr_offset = p_offset, \
@@ -147,6 +151,7 @@ struct rockchip_pmu {
147151
.idle_mask = (idle), \
148152
.ack_mask = (ack), \
149153
.active_wakeup = wakeup, \
154+
.need_regulator = regulator, \
150155
}
151156

152157
#define DOMAIN_M_O_R_G(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, g_mask, wakeup) \
@@ -305,8 +310,8 @@ void rockchip_pmu_unblock(void)
305310
}
306311
EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
307312

308-
#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup) \
309-
DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup)
313+
#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup, regulator) \
314+
DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup, regulator)
310315

311316
static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
312317
{
@@ -632,18 +637,57 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
632637
return ret;
633638
}
634639

640+
static int rockchip_pd_regulator_disable(struct rockchip_pm_domain *pd)
641+
{
642+
return IS_ERR_OR_NULL(pd->supply) ? 0 : regulator_disable(pd->supply);
643+
}
644+
645+
static int rockchip_pd_regulator_enable(struct rockchip_pm_domain *pd)
646+
{
647+
struct rockchip_pmu *pmu = pd->pmu;
648+
649+
if (!pd->info->need_regulator)
650+
return 0;
651+
652+
if (IS_ERR_OR_NULL(pd->supply)) {
653+
pd->supply = devm_of_regulator_get(pmu->dev, pd->node, "domain");
654+
655+
if (IS_ERR(pd->supply))
656+
return PTR_ERR(pd->supply);
657+
}
658+
659+
return regulator_enable(pd->supply);
660+
}
661+
635662
static int rockchip_pd_power_on(struct generic_pm_domain *domain)
636663
{
637664
struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
665+
int ret;
666+
667+
ret = rockchip_pd_regulator_enable(pd);
668+
if (ret) {
669+
dev_err(pd->pmu->dev, "Failed to enable supply: %d\n", ret);
670+
return ret;
671+
}
638672

639-
return rockchip_pd_power(pd, true);
673+
ret = rockchip_pd_power(pd, true);
674+
if (ret)
675+
rockchip_pd_regulator_disable(pd);
676+
677+
return ret;
640678
}
641679

642680
static int rockchip_pd_power_off(struct generic_pm_domain *domain)
643681
{
644682
struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
683+
int ret;
645684

646-
return rockchip_pd_power(pd, false);
685+
ret = rockchip_pd_power(pd, false);
686+
if (ret)
687+
return ret;
688+
689+
rockchip_pd_regulator_disable(pd);
690+
return ret;
647691
}
648692

649693
static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
@@ -724,6 +768,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
724768

725769
pd->info = pd_info;
726770
pd->pmu = pmu;
771+
pd->node = node;
727772

728773
pd->num_clks = of_clk_get_parent_count(node);
729774
if (pd->num_clks > 0) {
@@ -1187,35 +1232,35 @@ static const struct rockchip_domain_info rk3576_pm_domains[] = {
11871232
};
11881233

11891234
static const struct rockchip_domain_info rk3588_pm_domains[] = {
1190-
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false),
1191-
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false),
1192-
[RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false),
1193-
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false),
1194-
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false),
1195-
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false),
1196-
[RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false),
1197-
[RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false),
1198-
[RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false),
1199-
[RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false),
1200-
[RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false),
1201-
[RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false),
1202-
[RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false),
1203-
[RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false),
1204-
[RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false),
1205-
[RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false),
1206-
[RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false),
1207-
[RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
1208-
[RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false),
1209-
[RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false),
1210-
[RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false),
1211-
[RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false),
1212-
[RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false),
1213-
[RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true),
1214-
[RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false),
1215-
[RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false),
1216-
[RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false),
1217-
[RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true),
1218-
[RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false),
1235+
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false, true),
1236+
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false, true),
1237+
[RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false, false),
1238+
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false, false),
1239+
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false, false),
1240+
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false, false),
1241+
[RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false, false),
1242+
[RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false, false),
1243+
[RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false, false),
1244+
[RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false, false),
1245+
[RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false, false),
1246+
[RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false, false),
1247+
[RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false, false),
1248+
[RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false, false),
1249+
[RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false, false),
1250+
[RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false, false),
1251+
[RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false, false),
1252+
[RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false, false),
1253+
[RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false, false),
1254+
[RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false, false),
1255+
[RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false, false),
1256+
[RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false, false),
1257+
[RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false, false),
1258+
[RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true, false),
1259+
[RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false, false),
1260+
[RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false, false),
1261+
[RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false, false),
1262+
[RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true, false),
1263+
[RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false, false),
12191264
};
12201265

12211266
static const struct rockchip_pmu_info px30_pmu = {

0 commit comments

Comments
 (0)