diff options
-rw-r--r-- | drivers/soc/imx/gpcv2.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index bcf1f338b0bf..c449cd0e1499 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -69,6 +69,9 @@ #define GPC_PU_PWRHSK 0x1fc +#define IMX8M_GPU_HSK_PWRDNACKN BIT(26) +#define IMX8M_VPU_HSK_PWRDNACKN BIT(25) +#define IMX8M_DISP_HSK_PWRDNACKN BIT(24) #define IMX8M_GPU_HSK_PWRDNREQN BIT(6) #define IMX8M_VPU_HSK_PWRDNREQN BIT(5) #define IMX8M_DISP_HSK_PWRDNREQN BIT(4) @@ -112,7 +115,8 @@ struct imx_pgc_domain { const struct { u32 pxx; u32 map; - u32 hsk; + u32 hskreq; + u32 hskack; } bits; const int voltage; @@ -172,9 +176,23 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) GPC_PGC_CTRL_PCR); /* request the ADB400 to power up */ - if (domain->bits.hsk) + if (domain->bits.hskreq) { regmap_update_bits(domain->regmap, GPC_PU_PWRHSK, - domain->bits.hsk, domain->bits.hsk); + domain->bits.hskreq, domain->bits.hskreq); + + /* + * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val, + * (reg_val & domain->bits.hskack), 0, + * USEC_PER_MSEC); + * Technically we need the commented code to wait handshake. But that needs + * the BLK-CTL module BUS clk-en bit being set. + * + * There is a separate BLK-CTL module and we will have such a driver for it, + * that driver will set the BUS clk-en bit and handshake will be triggered + * automatically there. Just add a delay and suppose the handshake finish + * after that. + */ + } /* Disable reset clocks for all devices in the domain */ clk_bulk_disable_unprepare(domain->num_clks, domain->clks); @@ -204,9 +222,19 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd) } /* request the ADB400 to power down */ - if (domain->bits.hsk) + if (domain->bits.hskreq) { regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK, - domain->bits.hsk); + domain->bits.hskreq); + + ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, + reg_val, + !(reg_val & domain->bits.hskack), + 0, USEC_PER_MSEC); + if (ret) { + dev_err(domain->dev, "failed to power down ADB400\n"); + goto out_clk_disable; + } + } /* enable power control */ regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), @@ -369,7 +397,8 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .bits = { .pxx = IMX8M_GPU_SW_Pxx_REQ, .map = IMX8M_GPU_A53_DOMAIN, - .hsk = IMX8M_GPU_HSK_PWRDNREQN, + .hskreq = IMX8M_GPU_HSK_PWRDNREQN, + .hskack = IMX8M_GPU_HSK_PWRDNACKN, }, .pgc = IMX8M_PGC_GPU, }, @@ -381,7 +410,8 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .bits = { .pxx = IMX8M_VPU_SW_Pxx_REQ, .map = IMX8M_VPU_A53_DOMAIN, - .hsk = IMX8M_VPU_HSK_PWRDNREQN, + .hskreq = IMX8M_VPU_HSK_PWRDNREQN, + .hskack = IMX8M_VPU_HSK_PWRDNACKN, }, .pgc = IMX8M_PGC_VPU, }, @@ -393,7 +423,8 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = { .bits = { .pxx = IMX8M_DISP_SW_Pxx_REQ, .map = IMX8M_DISP_A53_DOMAIN, - .hsk = IMX8M_DISP_HSK_PWRDNREQN, + .hskreq = IMX8M_DISP_HSK_PWRDNREQN, + .hskack = IMX8M_DISP_HSK_PWRDNACKN, }, .pgc = IMX8M_PGC_DISP, }, |