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

soc: imx: gpcv2: add PGC control register indirection



The PGC control registers in the shared (not per-PGC) region of the
GPC address space have different offsets on i.MX8MP to make space for
additional interrupt control registers.

Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: default avatarPeng Fan <peng.fan@nxp.com>
Signed-off-by: default avatarShawn Guo <shawnguo@kernel.org>
parent 31231092
Loading
Loading
Loading
Loading
+32 −11
Original line number Diff line number Diff line
@@ -184,9 +184,17 @@

#define GPC_PGC_CTRL_PCR		BIT(0)

struct imx_pgc_regs {
	u16 map;
	u16 pup;
	u16 pdn;
	u16 hsk;
};

struct imx_pgc_domain {
	struct generic_pm_domain genpd;
	struct regmap *regmap;
	const struct imx_pgc_regs *regs;
	struct regulator *regulator;
	struct reset_control *reset;
	struct clk_bulk_data *clks;
@@ -210,6 +218,7 @@ struct imx_pgc_domain_data {
	const struct imx_pgc_domain *domains;
	size_t domains_num;
	const struct regmap_access_table *reg_access_table;
	const struct imx_pgc_regs *pgc_regs;
};

static inline struct imx_pgc_domain *
@@ -249,14 +258,14 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)

	if (domain->bits.pxx) {
		/* request the domain to power up */
		regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
		regmap_update_bits(domain->regmap, domain->regs->pup,
				   domain->bits.pxx, domain->bits.pxx);
		/*
		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
		 * for PUP_REQ/PDN_REQ bit to be cleared
		 */
		ret = regmap_read_poll_timeout(domain->regmap,
					       GPC_PU_PGC_SW_PUP_REQ, reg_val,
					       domain->regs->pup, reg_val,
					       !(reg_val & domain->bits.pxx),
					       0, USEC_PER_MSEC);
		if (ret) {
@@ -278,11 +287,11 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)

	/* request the ADB400 to power up */
	if (domain->bits.hskreq) {
		regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
		regmap_update_bits(domain->regmap, domain->regs->hsk,
				   domain->bits.hskreq, domain->bits.hskreq);

		/*
		 * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val,
		 * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
		 *				  (reg_val & domain->bits.hskack), 0,
		 *				  USEC_PER_MSEC);
		 * Technically we need the commented code to wait handshake. But that needs
@@ -329,10 +338,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)

	/* request the ADB400 to power down */
	if (domain->bits.hskreq) {
		regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK,
		regmap_clear_bits(domain->regmap, domain->regs->hsk,
				  domain->bits.hskreq);

		ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK,
		ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
					       reg_val,
					       !(reg_val & domain->bits.hskack),
					       0, USEC_PER_MSEC);
@@ -350,14 +359,14 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
		}

		/* request the domain to power down */
		regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
		regmap_update_bits(domain->regmap, domain->regs->pdn,
				   domain->bits.pxx, domain->bits.pxx);
		/*
		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
		 * for PUP_REQ/PDN_REQ bit to be cleared
		 */
		ret = regmap_read_poll_timeout(domain->regmap,
					       GPC_PU_PGC_SW_PDN_REQ, reg_val,
					       domain->regs->pdn, reg_val,
					       !(reg_val & domain->bits.pxx),
					       0, USEC_PER_MSEC);
		if (ret) {
@@ -442,10 +451,18 @@ static const struct regmap_access_table imx7_access_table = {
	.n_yes_ranges	= ARRAY_SIZE(imx7_yes_ranges),
};

static const struct imx_pgc_regs imx7_pgc_regs = {
	.map = GPC_PGC_CPU_MAPPING,
	.pup = GPC_PU_PGC_SW_PUP_REQ,
	.pdn = GPC_PU_PGC_SW_PDN_REQ,
	.hsk = GPC_PU_PWRHSK,
};

static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
	.domains = imx7_pgc_domains,
	.domains_num = ARRAY_SIZE(imx7_pgc_domains),
	.reg_access_table = &imx7_access_table,
	.pgc_regs = &imx7_pgc_regs,
};

static const struct imx_pgc_domain imx8m_pgc_domains[] = {
@@ -614,6 +631,7 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
	.domains = imx8m_pgc_domains,
	.domains_num = ARRAY_SIZE(imx8m_pgc_domains),
	.reg_access_table = &imx8m_access_table,
	.pgc_regs = &imx7_pgc_regs,
};

static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
@@ -804,6 +822,7 @@ static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
	.domains = imx8mm_pgc_domains,
	.domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
	.reg_access_table = &imx8mm_access_table,
	.pgc_regs = &imx7_pgc_regs,
};

static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
@@ -895,6 +914,7 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
	.domains = imx8mn_pgc_domains,
	.domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
	.reg_access_table = &imx8mn_access_table,
	.pgc_regs = &imx7_pgc_regs,
};

static int imx_pgc_domain_probe(struct platform_device *pdev)
@@ -927,7 +947,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
	pm_runtime_enable(domain->dev);

	if (domain->bits.map)
		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
		regmap_update_bits(domain->regmap, domain->regs->map,
				   domain->bits.map, domain->bits.map);

	ret = pm_genpd_init(&domain->genpd, NULL, true);
@@ -953,7 +973,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
	pm_genpd_remove(&domain->genpd);
out_domain_unmap:
	if (domain->bits.map)
		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
		regmap_update_bits(domain->regmap, domain->regs->map,
				   domain->bits.map, 0);
	pm_runtime_disable(domain->dev);

@@ -968,7 +988,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
	pm_genpd_remove(&domain->genpd);

	if (domain->bits.map)
		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
		regmap_update_bits(domain->regmap, domain->regs->map,
				   domain->bits.map, 0);

	pm_runtime_disable(domain->dev);
@@ -1099,6 +1119,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)

		domain = pd_pdev->dev.platform_data;
		domain->regmap = regmap;
		domain->regs = domain_data->pgc_regs;
		domain->genpd.power_on  = imx_pgc_power_up;
		domain->genpd.power_off = imx_pgc_power_down;