On Tue, Sep 15, 2026 at 12:45 PM Jiaxing Hu <[email protected]> wrote: > > Some Rockchip domains come out of power-on with their bus interface in an > undefined state. On the RK3576 NPU this shows up as a hang on the first > register access after the domain is switched on, and pulsing the domain's > resets at this point clears it. > > Take the domain node's resets if it has any, and pulse them between > releasing idle and restoring QoS. The resets are optional, so domains that > do not list any are unaffected.
Please drop the below from the commit message, the above is clear enough I think! > > The cycle goes before the settle delay 9/14 adds, not after it. A domain > that asks for both is asking to settle before the QoS registers answer, and > a reset deasserted after the delay would leave nothing between the deassert > and rockchip_pmu_restore_qos(). On RK3576 PD_NPU0 and PD_NPU1 ask for both, > and the reset they cycle is SRST_A_RKNN0/1_BIU, the bus interface those QoS > writes go through. > > It only runs when the domain actually changes state: rockchip_pd_power() > returns early when the hardware already reads the state being asked for. A > bootloader that leaves the NPU powered would therefore skip both this and > the delay, which is why 9/14 gives RK3576_PD_NPU need_regulator and forces > the domain off at probe. > > No in-tree DTS puts resets in a power-domain node today, so every other > Rockchip SoC takes the optional get's NULL and is unchanged. > > Signed-off-by: Jiaxing Hu <[email protected]> > Reviewed-by: Abel Vesa <[email protected]> Kind regards Uffe > --- > drivers/pmdomain/rockchip/pm-domains.c | 27 ++++++++++++++++++++++++++ > 1 file changed, 27 insertions(+) > > diff --git a/drivers/pmdomain/rockchip/pm-domains.c > b/drivers/pmdomain/rockchip/pm-domains.c > index 39988efd8..6cc8d6efd 100644 > --- a/drivers/pmdomain/rockchip/pm-domains.c > +++ b/drivers/pmdomain/rockchip/pm-domains.c > @@ -19,6 +19,7 @@ > #include <linux/of_clk.h> > #include <linux/clk.h> > #include <linux/delay.h> > +#include <linux/reset.h> > #include <linux/regmap.h> > #include <linux/regulator/consumer.h> > #include <linux/mfd/syscon.h> > @@ -103,6 +104,7 @@ struct rockchip_pm_domain { > struct clk_bulk_data *clks; > struct device_node *node; > struct regulator *supply; > + struct reset_control *resets; > }; > > struct rockchip_pmu { > @@ -688,6 +690,21 @@ static int rockchip_pd_power(struct rockchip_pm_domain > *pd, bool power_on) > if (ret < 0) > goto out; > > + /* > + * Optional: some domains need their resets cycled once power > + * is on. This goes BEFORE the settle delay, not after: a > + * domain that asks for both is asking to settle before the > + * QoS registers answer, and a reset deasserted after the > + * delay would leave nothing between it and the QoS writes. > + * On RK3576 the reset being cycled is the NPU core's bus > + * interface, which is what those writes go through. > + */ > + if (pd->resets) { > + reset_control_assert(pd->resets); > + usleep_range(10, 20); > + reset_control_deassert(pd->resets); > + } > + > /* Some domains need to settle before the QoS registers > answer. */ > if (pd->info->delay_us) > udelay(pd->info->delay_us); > @@ -861,6 +878,14 @@ static int rockchip_pm_add_one_domain(struct > rockchip_pmu *pmu, > if (error) > goto err_put_clocks; > > + pd->resets = of_reset_control_array_get_optional_exclusive(node); > + if (IS_ERR(pd->resets)) { > + error = dev_err_probe(pmu->dev, PTR_ERR(pd->resets), > + "%pOFn: failed to get resets\n", node); > + pd->resets = NULL; > + goto err_unprepare_clocks; > + } > + > pd->num_qos = of_count_phandle_with_args(node, "pm_qos", > NULL); > > @@ -931,6 +956,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu > *pmu, > clk_bulk_unprepare(pd->num_clks, pd->clks); > err_put_clocks: > clk_bulk_put(pd->num_clks, pd->clks); > + reset_control_put(pd->resets); > return error; > } > > @@ -949,6 +975,7 @@ static void rockchip_pm_remove_one_domain(struct > rockchip_pm_domain *pd) > > clk_bulk_unprepare(pd->num_clks, pd->clks); > clk_bulk_put(pd->num_clks, pd->clks); > + reset_control_put(pd->resets); > > /* protect the zeroing of pm->num_clks */ > mutex_lock(&pd->pmu->mutex); > -- > 2.43.0 >
