Commit 58d26861 authored by Lucas Stach's avatar Lucas Stach Committed by Shawn Guo
Browse files

soc: imx: gpcv2: wait for ADB400 handshake



New reference manuals show that there is actually a status bit for
the ADB400 handshake. Add a poll loop to wait for the ADB400 to
acknowledge our request.

[Peng Fan: i.MX8MM has blk ctl module, the handshake can only finish
 after setting blk ctl. The blk ctl driver will set the bus clk bit and
 the handshake will finish there. we just add a delay and suppose the
 handshake will finish after that.]

Tested-by: default avatarFrieder Schrempf <frieder.schrempf@kontron.de>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
Signed-off-by: default avatarPeng Fan <peng.fan@nxp.com>
Signed-off-by: default avatarShawn Guo <shawnguo@kernel.org>
parent 256f07ed
Loading
Loading
Loading
Loading
+39 −8
Original line number Diff line number Diff line
@@ -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,
	},