| From 7e59316516a45a9df353b159a205445df52084e2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 13 Mar 2020 11:09:12 +0100 |
| Subject: soc: imx: gpc: fix power up sequencing |
| |
| From: Lucas Stach <l.stach@pengutronix.de> |
| |
| [ Upstream commit e0ea2d11f8a08ba7066ff897e16c5217215d1e68 ] |
| |
| Currently we wait only until the PGC inverts the isolation setting |
| before disabling the peripheral clocks. This doesn't ensure that the |
| reset is properly propagated through the peripheral devices in the |
| power domain. |
| |
| Wait until the PGC signals that the power up request is done and |
| wait a bit for resets to propagate before disabling the clocks. |
| |
| Signed-off-by: Lucas Stach <l.stach@pengutronix.de> |
| Signed-off-by: Shawn Guo <shawnguo@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/soc/imx/gpc.c | 24 +++++++++++++----------- |
| 1 file changed, 13 insertions(+), 11 deletions(-) |
| |
| diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c |
| index 3a12123de4662..0e083fe8b893f 100644 |
| --- a/drivers/soc/imx/gpc.c |
| +++ b/drivers/soc/imx/gpc.c |
| @@ -97,8 +97,8 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) |
| static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) |
| { |
| struct imx_pm_domain *pd = to_imx_pm_domain(genpd); |
| - int i, ret, sw, sw2iso; |
| - u32 val; |
| + int i, ret; |
| + u32 val, req; |
| |
| if (pd->supply) { |
| ret = regulator_enable(pd->supply); |
| @@ -117,17 +117,18 @@ static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) |
| regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS, |
| 0x1, 0x1); |
| |
| - /* Read ISO and ISO2SW power up delays */ |
| - regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); |
| - sw = val & 0x3f; |
| - sw2iso = (val >> 8) & 0x3f; |
| - |
| /* Request GPC to power up domain */ |
| - val = BIT(pd->cntr_pdn_bit + 1); |
| - regmap_update_bits(pd->regmap, GPC_CNTR, val, val); |
| + req = BIT(pd->cntr_pdn_bit + 1); |
| + regmap_update_bits(pd->regmap, GPC_CNTR, req, req); |
| |
| - /* Wait ISO + ISO2SW IPG clock cycles */ |
| - udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz)); |
| + /* Wait for the PGC to handle the request */ |
| + ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req), |
| + 1, 50); |
| + if (ret) |
| + pr_err("powerup request on domain %s timed out\n", genpd->name); |
| + |
| + /* Wait for reset to propagate through peripherals */ |
| + usleep_range(5, 10); |
| |
| /* Disable reset clocks for all devices in the domain */ |
| for (i = 0; i < pd->num_clks; i++) |
| @@ -329,6 +330,7 @@ static const struct regmap_config imx_gpc_regmap_config = { |
| .rd_table = &access_table, |
| .wr_table = &access_table, |
| .max_register = 0x2ac, |
| + .fast_io = true, |
| }; |
| |
| static struct generic_pm_domain *imx_gpc_onecell_domains[] = { |
| -- |
| 2.20.1 |
| |