* [PATCH 2/3] pmdomain: rockchip: Add pm_shaping support
2026-03-06 7:40 [PATCH 0/3] Add shaping support for Rockchip platforms Shawn Lin
2026-03-06 7:40 ` [PATCH 1/3] dt-bindings: power: rockchip: Add pm_shaping support Shawn Lin
@ 2026-03-06 7:40 ` Shawn Lin
2026-03-06 7:40 ` [PATCH 3/3] arm64: dts: rockchip: Add shaping nodes for rk3576 Shawn Lin
2026-03-06 10:43 ` [PATCH 0/3] Add shaping support for Rockchip platforms Heiko Stuebner
3 siblings, 0 replies; 8+ messages in thread
From: Shawn Lin @ 2026-03-06 7:40 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner
Cc: linux-pm, linux-rockchip, devicetree, Shawn Lin
pm_shaping is introduced for some platforms to throttle the outstanding
burst requests of each IP to prevent bus monopolization. In general, they
should be set in firmware but given that powering off pm domain will lose
the configurations, so add it support in pmdomain code.
They are defined and used the same way of pm_qos in DT but service with
different purposes.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
drivers/pmdomain/rockchip/pm-domains.c | 97 ++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/pmdomain/rockchip/pm-domains.c b/drivers/pmdomain/rockchip/pm-domains.c
index 490bbb1..56699aa 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -89,14 +89,18 @@ struct rockchip_pmu_info {
#define QOS_BANDWIDTH 0x10
#define QOS_SATURATION 0x14
#define QOS_EXTCONTROL 0x18
+#define SHAPING_NBPKTMAX0 0x0
struct rockchip_pm_domain {
struct generic_pm_domain genpd;
const struct rockchip_domain_info *info;
struct rockchip_pmu *pmu;
int num_qos;
+ int num_shaping;
struct regmap **qos_regmap;
+ struct regmap **shaping_regmap;
u32 *qos_save_regs[MAX_QOS_REGS_NUM];
+ u32 *shaping_save_regs;
int num_clks;
struct clk_bulk_data *clks;
struct device_node *node;
@@ -488,6 +492,28 @@ static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd)
return 0;
}
+static int rockchip_pmu_save_shaping(struct rockchip_pm_domain *pd)
+{
+ int i;
+
+ for (i = 0; i < pd->num_shaping; i++)
+ regmap_read(pd->shaping_regmap[i], SHAPING_NBPKTMAX0,
+ &pd->shaping_save_regs[i]);
+
+ return 0;
+}
+
+static int rockchip_pmu_restore_shaping(struct rockchip_pm_domain *pd)
+{
+ int i;
+
+ for (i = 0; i < pd->num_shaping; i++)
+ regmap_write(pd->shaping_regmap[i], SHAPING_NBPKTMAX0,
+ pd->shaping_save_regs[i]);
+
+ return 0;
+}
+
static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
{
struct rockchip_pmu *pmu = pd->pmu;
@@ -650,6 +676,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
if (!power_on) {
rockchip_pmu_save_qos(pd);
+ rockchip_pmu_save_shaping(pd);
/* if powering down, idle request to NIU first */
ret = rockchip_pmu_set_idle_request(pd, true);
@@ -668,6 +695,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
goto out;
rockchip_pmu_restore_qos(pd);
+ rockchip_pmu_restore_shaping(pd);
}
out:
@@ -767,6 +795,71 @@ static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
pm_clk_destroy(dev);
}
+static int rockchip_pd_of_get_shaping(struct rockchip_pm_domain *pd,
+ struct device_node *node)
+{
+ struct rockchip_pmu *pmu = pd->pmu;
+ struct device_node *shaping_node;
+ int num_shaping = 0, num_shaping_reg = 0;
+ int error, i;
+
+ num_shaping = of_count_phandle_with_args(node, "pm_shaping", NULL);
+
+ /* Count the real available pm_shaping nodes */
+ for (i = 0; i < num_shaping; i++) {
+ shaping_node = of_parse_phandle(node, "pm_shaping", i);
+ if (shaping_node && of_device_is_available(shaping_node))
+ pd->num_shaping++;
+ of_node_put(shaping_node);
+ }
+
+ if (!pd->num_shaping)
+ return 0;
+
+ /* Allocate memory for them */
+ pd->shaping_regmap = devm_kcalloc(pmu->dev, pd->num_shaping,
+ sizeof(*pd->shaping_regmap),
+ GFP_KERNEL);
+ if (!pd->shaping_regmap)
+ return -ENOMEM;
+
+ pd->shaping_save_regs = devm_kmalloc(pmu->dev, sizeof(u32) *
+ pd->num_shaping,
+ GFP_KERNEL);
+ if (!pd->shaping_save_regs)
+ return -ENOMEM;
+
+ /* Record the real available pm_shaping nodes */
+ for (i = 0; i < num_shaping; i++) {
+ shaping_node = of_parse_phandle(node, "pm_shaping", i);
+ if (!shaping_node)
+ return -ENODEV;
+
+ if (of_device_is_available(shaping_node)) {
+ if (num_shaping_reg >= pd->num_shaping) {
+ error = -EINVAL;
+ goto err_put_node;
+ }
+
+ pd->shaping_regmap[num_shaping_reg] =
+ syscon_node_to_regmap(shaping_node);
+ if (IS_ERR(pd->shaping_regmap[num_shaping_reg])) {
+ error = -ENODEV;
+ goto err_put_node;
+ }
+
+ num_shaping_reg++;
+ }
+ of_node_put(shaping_node);
+ }
+
+ return 0;
+
+err_put_node:
+ of_node_put(shaping_node);
+ return error;
+}
+
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
struct device_node *node)
{
@@ -874,6 +967,10 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
}
}
+ error = rockchip_pd_of_get_shaping(pd, node);
+ if (error)
+ dev_warn(pmu->dev, "%pOFn: failed to get shaping\n", node);
+
if (pd->info->name)
pd->genpd.name = pd->info->name;
else
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/3] arm64: dts: rockchip: Add shaping nodes for rk3576
2026-03-06 7:40 [PATCH 0/3] Add shaping support for Rockchip platforms Shawn Lin
2026-03-06 7:40 ` [PATCH 1/3] dt-bindings: power: rockchip: Add pm_shaping support Shawn Lin
2026-03-06 7:40 ` [PATCH 2/3] pmdomain: " Shawn Lin
@ 2026-03-06 7:40 ` Shawn Lin
2026-03-07 15:18 ` Krzysztof Kozlowski
2026-03-06 10:43 ` [PATCH 0/3] Add shaping support for Rockchip platforms Heiko Stuebner
3 siblings, 1 reply; 8+ messages in thread
From: Shawn Lin @ 2026-03-06 7:40 UTC (permalink / raw)
To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Heiko Stuebner
Cc: linux-pm, linux-rockchip, devicetree, Shawn Lin
RK3576 has shaping settings which need to be saved and restored
along with the on/off of pmdomain, so add them in the rk3576.dtsi.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
arch/arm64/boot/dts/rockchip/rk3576.dtsi | 139 +++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
index 53ff6bd..9c28769 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi
@@ -1063,6 +1063,10 @@
<&qos_npu_nsp1>,
<&qos_npu_m0ro>,
<&qos_npu_m1ro>;
+ pm_shaping = <&shaping_npu_nsp0>,
+ <&shaping_npu_nsp1>,
+ <&shaping_npu_m0ro>,
+ <&shaping_npu_m1ro>;
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1072,6 +1076,7 @@
clocks = <&cru HCLK_RKNN_ROOT>,
<&cru ACLK_RKNN0>;
pm_qos = <&qos_npu_m0>;
+ pm_shaping = <&shaping_npu_m0>;
#power-domain-cells = <0>;
};
power-domain@RK3576_PD_NPU1 {
@@ -1079,6 +1084,7 @@
clocks = <&cru HCLK_RKNN_ROOT>,
<&cru ACLK_RKNN1>;
pm_qos = <&qos_npu_m1>;
+ pm_shaping = <&shaping_npu_m1>;
#power-domain-cells = <0>;
};
};
@@ -1088,6 +1094,7 @@
reg = <RK3576_PD_GPU>;
clocks = <&cru CLK_GPU>, <&cru PCLK_GPU_ROOT>;
pm_qos = <&qos_gpu>;
+ pm_shaping = <&shaping_gpu>;
#power-domain-cells = <0>;
};
@@ -1129,6 +1136,9 @@
<&cru ACLK_MMU1>;
pm_qos = <&qos_mmu0>,
<&qos_mmu1>;
+ pm_shaping = <&shaping_mmu0>,
+ <&shaping_mmu1>;
+
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1149,6 +1159,7 @@
clocks = <&cru ACLK_VEPU1>,
<&cru HCLK_VEPU1>;
pm_qos = <&qos_vepu1>;
+ pm_shaping = <&shaping_vepu1>;
#power-domain-cells = <0>;
};
@@ -1169,6 +1180,10 @@
<&qos_rga0>,
<&qos_rga1>,
<&qos_vdpp>;
+ pm_shaping = <&shaping_rga0>,
+ <&shaping_rga1>,
+ <&shaping_jpeg>,
+ <&shaping_vdpp>;
#power-domain-cells = <0>;
};
@@ -1177,6 +1192,7 @@
clocks = <&cru ACLK_RKVDEC_ROOT>,
<&cru HCLK_RKVDEC>;
pm_qos = <&qos_rkvdec>;
+ pm_shaping = <&shaping_rkvdec>;
#power-domain-cells = <0>;
};
@@ -1199,6 +1215,11 @@
<&qos_vicap_m0>,
<&qos_vpss_mro>,
<&qos_vpss_mwo>;
+ pm_shaping = <&shaping_isp_mro>,
+ <&shaping_isp_mwo>,
+ <&shaping_vicap_m0>,
+ <&shaping_vpss_mro>,
+ <&shaping_vpss_mwo>;
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1208,6 +1229,7 @@
clocks = <&cru ACLK_VEPU0>,
<&cru HCLK_VEPU0>;
pm_qos = <&qos_vepu0>;
+ pm_shaping = <&shaping_vepu0>;
#power-domain-cells = <0>;
};
};
@@ -1220,6 +1242,8 @@
<&cru PCLK_VOP_ROOT>;
pm_qos = <&qos_vop_m0>,
<&qos_vop_m1ro>;
+ pm_shaping = <&shaping_vop_m0>,
+ <&shaping_vop_m1ro>;
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1602,11 +1626,21 @@
reg = <0x0 0x27f05000 0x0 0x20>;
};
+ shaping_gpu: shaping@27f05088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f05088 0x0 0x4>;
+ };
+
qos_vepu1: qos@27f06000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f06000 0x0 0x20>;
};
+ shaping_vepu1: shaping@27f06088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f06088 0x0 0x4>;
+ };
+
qos_npu_mcu: qos@27f08000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f08000 0x0 0x20>;
@@ -1622,6 +1656,16 @@
reg = <0x0 0x27f08100 0x0 0x20>;
};
+ shaping_npu_nsp0: shaping@27f08188 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f08188 0x0 0x4>;
+ };
+
+ shaping_npu_nsp1: shaping@27f08208 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f08208 0x0 0x4>;
+ };
+
qos_emmc: qos@27f09000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f09000 0x0 0x20>;
@@ -1642,11 +1686,26 @@
reg = <0x0 0x27f0a080 0x0 0x20>;
};
+ shaping_mmu0: shaping@27f0a108 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f0a108 0x0 0x4>;
+ };
+
+ shaping_mmu1: shaping@27f0a188 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f0a188 0x0 0x4>;
+ };
+
qos_rkvdec: qos@27f0c000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f0c000 0x0 0x20>;
};
+ shaping_rkvdec: shaping@27f0c088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f0c088 0x0 0x4>;
+ };
+
qos_crypto: qos@27f0d000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f0d000 0x0 0x20>;
@@ -1667,6 +1726,11 @@
reg = <0x0 0x27f0f000 0x0 0x20>;
};
+ shaping_vepu0: shaping@27f0f088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f0f088 0x0 0x4>;
+ };
+
qos_isp_mro: qos@27f10000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f10000 0x0 0x20>;
@@ -1692,6 +1756,31 @@
reg = <0x0 0x27f10200 0x0 0x20>;
};
+ shaping_isp_mro: shaping@27f10288 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f10288 0x0 0x4>;
+ };
+
+ shaping_isp_mwo: shaping@27f10308 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f10308 0x0 0x4>;
+ };
+
+ shaping_vicap_m0: shaping@27f10388 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f10388 0x0 0x4>;
+ };
+
+ shaping_vpss_mro: shaping@27f10408 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f10408 0x0 0x4>;
+ };
+
+ shaping_vpss_mwo: shaping@27f10488 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f10488 0x0 0x4>;
+ };
+
qos_hdcp0: qos@27f11000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f11000 0x0 0x20>;
@@ -1707,6 +1796,16 @@
reg = <0x0 0x27f12880 0x0 0x20>;
};
+ shaping_vop_m0: shaping@27f12908 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f12908 0x0 0x4>;
+ };
+
+ shaping_vop_m1ro: shaping@27f12988 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f12988 0x0 0x4>;
+ };
+
qos_ebc: qos@27f13000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f13000 0x0 0x20>;
@@ -1732,16 +1831,46 @@
reg = <0x0 0x27f13200 0x0 0x20>;
};
+ shaping_rga0: shaping@27f13288 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f13288 0x0 0x4>;
+ };
+
+ shaping_rga1: shaping@27f13308 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f13308 0x0 0x4>;
+ };
+
+ shaping_jpeg: shaping@27f13388 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f13388 0x0 0x4>;
+ };
+
+ shaping_vdpp: shaping@27f13408 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f13408 0x0 0x4>;
+ };
+
qos_npu_m0: qos@27f20000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f20000 0x0 0x20>;
};
+ shaping_npu_m0: shaping@27f20088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f20088 0x0 0x4>;
+ };
+
qos_npu_m1: qos@27f21000 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f21000 0x0 0x20>;
};
+ shaping_npu_m1: shaping@27f21088 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f21088 0x0 0x4>;
+ };
+
qos_npu_m0ro: qos@27f22080 {
compatible = "rockchip,rk3576-qos", "syscon";
reg = <0x0 0x27f22080 0x0 0x20>;
@@ -1752,6 +1881,16 @@
reg = <0x0 0x27f22100 0x0 0x20>;
};
+ shaping_npu_m0ro: shaping@27f22188 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f22188 0x0 0x4>;
+ };
+
+ shaping_npu_m1ro: shaping@27f22208 {
+ compatible = "rockchip,rk3576-shaping", "syscon";
+ reg = <0x0 0x27f22208 0x0 0x4>;
+ };
+
gmac0: ethernet@2a220000 {
compatible = "rockchip,rk3576-gmac", "snps,dwmac-4.20a";
reg = <0x0 0x2a220000 0x0 0x10000>;
--
2.7.4
^ permalink raw reply related [flat|nested] 8+ messages in thread