[PATCH] soc: imx: gpcv2: Assert reset before ungating clock
Peng Fan
peng.fan at nxp.com
Wed Jun 30 18:53:22 PDT 2021
> Subject: [PATCH] soc: imx: gpcv2: Assert reset before ungating clock
>
> In case the power domain clock are ungated before the reset is asserted, the
> system might freeze completely. However, the MX8MM GPUMIX and VPUMIX
> domains require different reset deassertion timing, and incorrect reset
> deassertion timing also leads to hang.
>
> Add per-domain reset_{,de}assert_early flags which allow fine-grained control
> of the reset assertion and deassertion sequence. Currently, on MX8MM, the
> behavior is as follows and aligned with NXP downstream ATF
> fork:
> - VPUMIX: reset assert, reset deassert, domain power up
> - GPUMIX: reset assert, domain power on, reset deassert
In 2.4 ATF, only VPU_H1/G1/G2 needs reset assert/deassert early,
but actually in first power on, it is in reset assert, so I think no need
reset assert again. I think only need to reset assert when power off.
Would the following patch help you hang case?
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 34a9ac1f2b9b..b5f9daff8b1c 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -358,6 +358,8 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
}
}
+ reset_control_assert(domain->reset);
+
/* Disable reset clocks for all devices in the domain */
clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
Thanks,
Peng.
>
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Fabio Estevam <festevam at gmail.com>
> Cc: Frieder Schrempf <frieder.schrempf at kontron.de>
> Cc: NXP Linux Team <linux-imx at nxp.com>
> Cc: Peng Fan <peng.fan at nxp.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> To: linux-arm-kernel at lists.infradead.org
> ---
> drivers/soc/imx/gpcv2.c | 41
> +++++++++++++++++++++++++++++++++--------
> 1 file changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index
> 34a9ac1f2b9b1..388c4c729c95b 100644
> --- a/drivers/soc/imx/gpcv2.c
> +++ b/drivers/soc/imx/gpcv2.c
> @@ -201,6 +201,9 @@ struct imx_pgc_domain {
> u32 hskack;
> } bits;
>
> + bool reset_assert_early;
> + bool reset_deassert_early;
> +
> const int voltage;
> struct device *dev;
> };
> @@ -237,6 +240,17 @@ static int imx_pgc_power_up(struct
> generic_pm_domain *genpd)
> }
> }
>
> + /* delays for reset to propagate */
> + if (domain->reset_assert_early) {
> + reset_control_assert(domain->reset);
> + udelay(5);
> + }
> +
> + if (domain->reset_deassert_early) {
> + reset_control_deassert(domain->reset);
> + udelay(5);
> + }
> +
> /* Enable reset clocks for all devices in the domain */
> ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
> if (ret) {
> @@ -245,6 +259,10 @@ static int imx_pgc_power_up(struct
> generic_pm_domain *genpd)
> }
>
> if (domain->bits.pxx) {
> + /* disable power control */
> + regmap_clear_bits(domain->regmap,
> GPC_PGC_CTRL(domain->pgc),
> + GPC_PGC_CTRL_PCR);
> +
> /* request the domain to power up */
> regmap_update_bits(domain->regmap,
> GPC_PU_PGC_SW_PUP_REQ,
> domain->bits.pxx, domain->bits.pxx); @@ -260,18
> +278,19 @@ static int imx_pgc_power_up(struct generic_pm_domain
> *genpd)
> dev_err(domain->dev, "failed to command PGC\n");
> goto out_clk_disable;
> }
> -
> - /* disable power control */
> - regmap_clear_bits(domain->regmap,
> GPC_PGC_CTRL(domain->pgc),
> - GPC_PGC_CTRL_PCR);
> }
>
> - reset_control_assert(domain->reset);
>
> - /* delay for reset to propagate */
> - udelay(5);
> + /* delays for reset to propagate */
> + if (!domain->reset_assert_early) {
> + reset_control_assert(domain->reset);
> + udelay(5);
> + }
>
> - reset_control_deassert(domain->reset);
> + if (!domain->reset_deassert_early) {
> + reset_control_deassert(domain->reset);
> + udelay(5);
> + }
>
> /* request the ADB400 to power up */
> if (domain->bits.hskreq) {
> @@ -676,6 +695,9 @@ static const struct imx_pgc_domain
> imx8mm_pgc_domains[] = {
> .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
> },
> .pgc = IMX8MM_PGC_GPU2D,
> + /* Assert reset, power up domain, deassert reset */
> + .reset_assert_early = true,
> + .reset_deassert_early = false,
> },
>
> [IMX8MM_POWER_DOMAIN_VPUMIX] = {
> @@ -689,6 +711,9 @@ static const struct imx_pgc_domain
> imx8mm_pgc_domains[] = {
> .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
> },
> .pgc = IMX8MM_PGC_VPUMIX,
> + /* Assert reset, deassert reset, power up domain */
> + .reset_assert_early = true,
> + .reset_deassert_early = true,
> },
>
> [IMX8MM_POWER_DOMAIN_VPUG1] = {
> --
> 2.30.2
More information about the linux-arm-kernel
mailing list