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

soc: imx: gpcv2: add support for i.MX8MM power domains



This adds support for the power domains found on i.MX8MM. The 2D and 3D
GPU domains are abstracted as a single domain in the driver, as they can't
be powered up/down individually due to a shared reset.

Tested-by: default avatarFrieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-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 30af8513
Loading
Loading
Loading
Loading
+168 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/sizes.h>
#include <dt-bindings/power/imx7-power.h>
#include <dt-bindings/power/imx8mq-power.h>
#include <dt-bindings/power/imx8mm-power.h>

#define GPC_LPCR_A_CORE_BSC			0x000

@@ -44,6 +45,19 @@
#define IMX8M_PCIE1_A53_DOMAIN			BIT(3)
#define IMX8M_MIPI_A53_DOMAIN			BIT(2)

#define IMX8MM_VPUH1_A53_DOMAIN			BIT(15)
#define IMX8MM_VPUG2_A53_DOMAIN			BIT(14)
#define IMX8MM_VPUG1_A53_DOMAIN			BIT(13)
#define IMX8MM_DISPMIX_A53_DOMAIN		BIT(12)
#define IMX8MM_VPUMIX_A53_DOMAIN		BIT(10)
#define IMX8MM_GPUMIX_A53_DOMAIN		BIT(9)
#define IMX8MM_GPU_A53_DOMAIN			(BIT(8) | BIT(11))
#define IMX8MM_DDR1_A53_DOMAIN			BIT(7)
#define IMX8MM_OTG2_A53_DOMAIN			BIT(5)
#define IMX8MM_OTG1_A53_DOMAIN			BIT(4)
#define IMX8MM_PCIE_A53_DOMAIN			BIT(3)
#define IMX8MM_MIPI_A53_DOMAIN			BIT(2)

#define GPC_PU_PGC_SW_PUP_REQ		0x0f8
#define GPC_PU_PGC_SW_PDN_REQ		0x104

@@ -67,6 +81,19 @@
#define IMX8M_PCIE1_SW_Pxx_REQ			BIT(1)
#define IMX8M_MIPI_SW_Pxx_REQ			BIT(0)

#define IMX8MM_VPUH1_SW_Pxx_REQ			BIT(13)
#define IMX8MM_VPUG2_SW_Pxx_REQ			BIT(12)
#define IMX8MM_VPUG1_SW_Pxx_REQ			BIT(11)
#define IMX8MM_DISPMIX_SW_Pxx_REQ		BIT(10)
#define IMX8MM_VPUMIX_SW_Pxx_REQ		BIT(8)
#define IMX8MM_GPUMIX_SW_Pxx_REQ		BIT(7)
#define IMX8MM_GPU_SW_Pxx_REQ			(BIT(6) | BIT(9))
#define IMX8MM_DDR1_SW_Pxx_REQ			BIT(5)
#define IMX8MM_OTG2_SW_Pxx_REQ			BIT(3)
#define IMX8MM_OTG1_SW_Pxx_REQ			BIT(2)
#define IMX8MM_PCIE_SW_Pxx_REQ			BIT(1)
#define IMX8MM_MIPI_SW_Pxx_REQ			BIT(0)

#define GPC_M4_PU_PDN_FLG		0x1bc

#define GPC_PU_PWRHSK			0x1fc
@@ -78,6 +105,17 @@
#define IMX8M_VPU_HSK_PWRDNREQN			BIT(5)
#define IMX8M_DISP_HSK_PWRDNREQN		BIT(4)


#define IMX8MM_GPUMIX_HSK_PWRDNACKN		BIT(29)
#define IMX8MM_GPU_HSK_PWRDNACKN		(BIT(27) | BIT(28))
#define IMX8MM_VPUMIX_HSK_PWRDNACKN		BIT(26)
#define IMX8MM_DISPMIX_HSK_PWRDNACKN		BIT(25)
#define IMX8MM_HSIO_HSK_PWRDNACKN		(BIT(23) | BIT(24))
#define IMX8MM_GPUMIX_HSK_PWRDNREQN		BIT(11)
#define IMX8MM_GPU_HSK_PWRDNREQN		(BIT(9) | BIT(10))
#define IMX8MM_VPUMIX_HSK_PWRDNREQN		BIT(8)
#define IMX8MM_DISPMIX_HSK_PWRDNREQN		BIT(7)
#define IMX8MM_HSIO_HSK_PWRDNREQN		(BIT(5) | BIT(6))
/*
 * The PGC offset values in Reference Manual
 * (Rev. 1, 01/2018 and the older ones) GPC chapter's
@@ -100,6 +138,20 @@
#define IMX8M_PGC_MIPI_CSI2		28
#define IMX8M_PGC_PCIE2			29

#define IMX8MM_PGC_MIPI			16
#define IMX8MM_PGC_PCIE			17
#define IMX8MM_PGC_OTG1			18
#define IMX8MM_PGC_OTG2			19
#define IMX8MM_PGC_DDR1			21
#define IMX8MM_PGC_GPU2D		22
#define IMX8MM_PGC_GPUMIX		23
#define IMX8MM_PGC_VPUMIX		24
#define IMX8MM_PGC_GPU3D		25
#define IMX8MM_PGC_DISPMIX		26
#define IMX8MM_PGC_VPUG1		27
#define IMX8MM_PGC_VPUG2		28
#define IMX8MM_PGC_VPUH1		29

#define GPC_PGC_CTRL(n)			(0x800 + (n) * 0x40)
#define GPC_PGC_SR(n)			(GPC_PGC_CTRL(n) + 0xc)

@@ -527,6 +579,121 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
	.reg_access_table = &imx8m_access_table,
};

static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
	[IMX8MM_POWER_DOMAIN_HSIOMIX] = {
		.genpd = {
			.name = "hsiomix",
		},
		.bits  = {
			.pxx = 0, /* no power sequence control */
			.map = 0, /* no power sequence control */
			.hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
			.hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
		},
	},

	[IMX8MM_POWER_DOMAIN_PCIE] = {
		.genpd = {
			.name = "pcie",
		},
		.bits  = {
			.pxx = IMX8MM_PCIE_SW_Pxx_REQ,
			.map = IMX8MM_PCIE_A53_DOMAIN,
		},
		.pgc   = IMX8MM_PGC_PCIE,
	},

	[IMX8MM_POWER_DOMAIN_OTG1] = {
		.genpd = {
			.name = "usb-otg1",
		},
		.bits  = {
			.pxx = IMX8MM_OTG1_SW_Pxx_REQ,
			.map = IMX8MM_OTG1_A53_DOMAIN,
		},
		.pgc   = IMX8MM_PGC_OTG1,
	},

	[IMX8MM_POWER_DOMAIN_OTG2] = {
		.genpd = {
			.name = "usb-otg2",
		},
		.bits  = {
			.pxx = IMX8MM_OTG2_SW_Pxx_REQ,
			.map = IMX8MM_OTG2_A53_DOMAIN,
		},
		.pgc   = IMX8MM_PGC_OTG2,
	},

	[IMX8MM_POWER_DOMAIN_GPUMIX] = {
		.genpd = {
			.name = "gpumix",
		},
		.bits  = {
			.pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
			.map = IMX8MM_GPUMIX_A53_DOMAIN,
			.hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
			.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
		},
		.pgc   = IMX8MM_PGC_GPUMIX,
	},

	[IMX8MM_POWER_DOMAIN_GPU] = {
		.genpd = {
			.name = "gpu",
		},
		.bits  = {
			.pxx = IMX8MM_GPU_SW_Pxx_REQ,
			.map = IMX8MM_GPU_A53_DOMAIN,
			.hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
			.hskack = IMX8MM_GPU_HSK_PWRDNACKN,
		},
		.pgc   = IMX8MM_PGC_GPU2D,
	},
};

static const struct regmap_range imx8mm_yes_ranges[] = {
		regmap_reg_range(GPC_LPCR_A_CORE_BSC,
				 GPC_PU_PWRHSK),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_MIPI),
				 GPC_PGC_SR(IMX8MM_PGC_MIPI)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_PCIE),
				 GPC_PGC_SR(IMX8MM_PGC_PCIE)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG1),
				 GPC_PGC_SR(IMX8MM_PGC_OTG1)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_OTG2),
				 GPC_PGC_SR(IMX8MM_PGC_OTG2)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DDR1),
				 GPC_PGC_SR(IMX8MM_PGC_DDR1)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU2D),
				 GPC_PGC_SR(IMX8MM_PGC_GPU2D)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPUMIX),
				 GPC_PGC_SR(IMX8MM_PGC_GPUMIX)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUMIX),
				 GPC_PGC_SR(IMX8MM_PGC_VPUMIX)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_GPU3D),
				 GPC_PGC_SR(IMX8MM_PGC_GPU3D)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_DISPMIX),
				 GPC_PGC_SR(IMX8MM_PGC_DISPMIX)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG1),
				 GPC_PGC_SR(IMX8MM_PGC_VPUG1)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUG2),
				 GPC_PGC_SR(IMX8MM_PGC_VPUG2)),
		regmap_reg_range(GPC_PGC_CTRL(IMX8MM_PGC_VPUH1),
				 GPC_PGC_SR(IMX8MM_PGC_VPUH1)),
};

static const struct regmap_access_table imx8mm_access_table = {
	.yes_ranges	= imx8mm_yes_ranges,
	.n_yes_ranges	= ARRAY_SIZE(imx8mm_yes_ranges),
};

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,
};

static int imx_pgc_domain_probe(struct platform_device *pdev)
{
	struct imx_pgc_domain *domain = pdev->dev.platform_data;
@@ -710,6 +877,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)

static const struct of_device_id imx_gpcv2_dt_ids[] = {
	{ .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
	{ .compatible = "fsl,imx8mm-gpc", .data = &imx8mm_pgc_domain_data, },
	{ .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
	{ }
};