162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2019 BayLibre, SAS
462306a36Sopenharmony_ci * Author: Neil Armstrong <narmstrong@baylibre.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/platform_device.h>
862306a36Sopenharmony_ci#include <linux/pm_domain.h>
962306a36Sopenharmony_ci#include <linux/bitfield.h>
1062306a36Sopenharmony_ci#include <linux/regmap.h>
1162306a36Sopenharmony_ci#include <linux/mfd/syscon.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/reset-controller.h>
1462306a36Sopenharmony_ci#include <linux/reset.h>
1562306a36Sopenharmony_ci#include <linux/clk.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <dt-bindings/power/meson8-power.h>
1862306a36Sopenharmony_ci#include <dt-bindings/power/meson-axg-power.h>
1962306a36Sopenharmony_ci#include <dt-bindings/power/meson-g12a-power.h>
2062306a36Sopenharmony_ci#include <dt-bindings/power/meson-gxbb-power.h>
2162306a36Sopenharmony_ci#include <dt-bindings/power/meson-sm1-power.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* AO Offsets */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define GX_AO_RTI_GEN_PWR_SLEEP0	(0x3a << 2)
2662306a36Sopenharmony_ci#define GX_AO_RTI_GEN_PWR_ISO0		(0x3b << 2)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Meson8/Meson8b/Meson8m2 only expose the power management registers of the
3062306a36Sopenharmony_ci * AO-bus as syscon. 0x3a from GX translates to 0x02, 0x3b translates to 0x03
3162306a36Sopenharmony_ci * and so on.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci#define MESON8_AO_RTI_GEN_PWR_SLEEP0	(0x02 << 2)
3462306a36Sopenharmony_ci#define MESON8_AO_RTI_GEN_PWR_ISO0	(0x03 << 2)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/* HHI Offsets */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define HHI_MEM_PD_REG0			(0x40 << 2)
3962306a36Sopenharmony_ci#define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
4062306a36Sopenharmony_ci#define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
4162306a36Sopenharmony_ci#define HHI_VPU_MEM_PD_REG3		(0x43 << 2)
4262306a36Sopenharmony_ci#define HHI_VPU_MEM_PD_REG4		(0x44 << 2)
4362306a36Sopenharmony_ci#define HHI_AUDIO_MEM_PD_REG0		(0x45 << 2)
4462306a36Sopenharmony_ci#define HHI_NANOQ_MEM_PD_REG0		(0x46 << 2)
4562306a36Sopenharmony_ci#define HHI_NANOQ_MEM_PD_REG1		(0x47 << 2)
4662306a36Sopenharmony_ci#define HHI_VPU_MEM_PD_REG2		(0x4d << 2)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define G12A_HHI_NANOQ_MEM_PD_REG0	(0x43 << 2)
4962306a36Sopenharmony_ci#define G12A_HHI_NANOQ_MEM_PD_REG1	(0x44 << 2)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistruct meson_ee_pwrc;
5262306a36Sopenharmony_cistruct meson_ee_pwrc_domain;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct meson_ee_pwrc_mem_domain {
5562306a36Sopenharmony_ci	unsigned int reg;
5662306a36Sopenharmony_ci	unsigned int mask;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct meson_ee_pwrc_top_domain {
6062306a36Sopenharmony_ci	unsigned int sleep_reg;
6162306a36Sopenharmony_ci	unsigned int sleep_mask;
6262306a36Sopenharmony_ci	unsigned int iso_reg;
6362306a36Sopenharmony_ci	unsigned int iso_mask;
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct meson_ee_pwrc_domain_desc {
6762306a36Sopenharmony_ci	char *name;
6862306a36Sopenharmony_ci	unsigned int reset_names_count;
6962306a36Sopenharmony_ci	unsigned int clk_names_count;
7062306a36Sopenharmony_ci	struct meson_ee_pwrc_top_domain *top_pd;
7162306a36Sopenharmony_ci	unsigned int mem_pd_count;
7262306a36Sopenharmony_ci	struct meson_ee_pwrc_mem_domain *mem_pd;
7362306a36Sopenharmony_ci	bool (*is_powered_off)(struct meson_ee_pwrc_domain *pwrc_domain);
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct meson_ee_pwrc_domain_data {
7762306a36Sopenharmony_ci	unsigned int count;
7862306a36Sopenharmony_ci	struct meson_ee_pwrc_domain_desc *domains;
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* TOP Power Domains */
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain gx_pwrc_vpu = {
8462306a36Sopenharmony_ci	.sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
8562306a36Sopenharmony_ci	.sleep_mask = BIT(8),
8662306a36Sopenharmony_ci	.iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
8762306a36Sopenharmony_ci	.iso_mask = BIT(9),
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = {
9162306a36Sopenharmony_ci	.sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
9262306a36Sopenharmony_ci	.sleep_mask = BIT(8),
9362306a36Sopenharmony_ci	.iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
9462306a36Sopenharmony_ci	.iso_mask = BIT(9),
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci#define SM1_EE_PD(__bit)					\
9862306a36Sopenharmony_ci	{							\
9962306a36Sopenharmony_ci		.sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, 		\
10062306a36Sopenharmony_ci		.sleep_mask = BIT(__bit), 			\
10162306a36Sopenharmony_ci		.iso_reg = GX_AO_RTI_GEN_PWR_ISO0, 		\
10262306a36Sopenharmony_ci		.iso_mask = BIT(__bit), 			\
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8);
10662306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16);
10762306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17);
10862306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18);
10962306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic struct meson_ee_pwrc_top_domain g12a_pwrc_nna = {
11262306a36Sopenharmony_ci	.sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
11362306a36Sopenharmony_ci	.sleep_mask = BIT(16) | BIT(17),
11462306a36Sopenharmony_ci	.iso_reg = GX_AO_RTI_GEN_PWR_ISO0,
11562306a36Sopenharmony_ci	.iso_mask = BIT(16) | BIT(17),
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/* Memory PD Domains */
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define VPU_MEMPD(__reg)					\
12162306a36Sopenharmony_ci	{ __reg, GENMASK(1, 0) },				\
12262306a36Sopenharmony_ci	{ __reg, GENMASK(3, 2) },				\
12362306a36Sopenharmony_ci	{ __reg, GENMASK(5, 4) },				\
12462306a36Sopenharmony_ci	{ __reg, GENMASK(7, 6) },				\
12562306a36Sopenharmony_ci	{ __reg, GENMASK(9, 8) },				\
12662306a36Sopenharmony_ci	{ __reg, GENMASK(11, 10) },				\
12762306a36Sopenharmony_ci	{ __reg, GENMASK(13, 12) },				\
12862306a36Sopenharmony_ci	{ __reg, GENMASK(15, 14) },				\
12962306a36Sopenharmony_ci	{ __reg, GENMASK(17, 16) },				\
13062306a36Sopenharmony_ci	{ __reg, GENMASK(19, 18) },				\
13162306a36Sopenharmony_ci	{ __reg, GENMASK(21, 20) },				\
13262306a36Sopenharmony_ci	{ __reg, GENMASK(23, 22) },				\
13362306a36Sopenharmony_ci	{ __reg, GENMASK(25, 24) },				\
13462306a36Sopenharmony_ci	{ __reg, GENMASK(27, 26) },				\
13562306a36Sopenharmony_ci	{ __reg, GENMASK(29, 28) },				\
13662306a36Sopenharmony_ci	{ __reg, GENMASK(31, 30) }
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#define VPU_HHI_MEMPD(__reg)					\
13962306a36Sopenharmony_ci	{ __reg, BIT(8) },					\
14062306a36Sopenharmony_ci	{ __reg, BIT(9) },					\
14162306a36Sopenharmony_ci	{ __reg, BIT(10) },					\
14262306a36Sopenharmony_ci	{ __reg, BIT(11) },					\
14362306a36Sopenharmony_ci	{ __reg, BIT(12) },					\
14462306a36Sopenharmony_ci	{ __reg, BIT(13) },					\
14562306a36Sopenharmony_ci	{ __reg, BIT(14) },					\
14662306a36Sopenharmony_ci	{ __reg, BIT(15) }
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain axg_pwrc_mem_vpu[] = {
14962306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
15062306a36Sopenharmony_ci	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
15462306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
15562306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
15662306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
15762306a36Sopenharmony_ci	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = {
16162306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
16262306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
16362306a36Sopenharmony_ci	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
16462306a36Sopenharmony_ci};
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
16762306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(3, 2) },
16862306a36Sopenharmony_ci};
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = {
17162306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(1, 0) },
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = {
17562306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
17662306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
17762306a36Sopenharmony_ci	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
18162306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
18262306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
18362306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG2),
18462306a36Sopenharmony_ci	VPU_MEMPD(HHI_VPU_MEM_PD_REG3),
18562306a36Sopenharmony_ci	{ HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) },
18662306a36Sopenharmony_ci	{ HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) },
18762306a36Sopenharmony_ci	{ HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) },
18862306a36Sopenharmony_ci	{ HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) },
18962306a36Sopenharmony_ci	VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
19062306a36Sopenharmony_ci};
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = {
19362306a36Sopenharmony_ci	{ HHI_NANOQ_MEM_PD_REG0, 0xff },
19462306a36Sopenharmony_ci	{ HHI_NANOQ_MEM_PD_REG1, 0xff },
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = {
19862306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(31, 30) },
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = {
20262306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(29, 26) },
20362306a36Sopenharmony_ci};
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = {
20662306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(25, 18) },
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain axg_pwrc_mem_audio[] = {
21062306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(5, 4) },
21162306a36Sopenharmony_ci};
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
21462306a36Sopenharmony_ci	{ HHI_MEM_PD_REG0, GENMASK(5, 4) },
21562306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) },
21662306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) },
21762306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) },
21862306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) },
21962306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) },
22062306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) },
22162306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) },
22262306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) },
22362306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) },
22462306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) },
22562306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) },
22662306a36Sopenharmony_ci	{ HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_nna[] = {
23062306a36Sopenharmony_ci	{ G12A_HHI_NANOQ_MEM_PD_REG0, GENMASK(31, 0) },
23162306a36Sopenharmony_ci	{ G12A_HHI_NANOQ_MEM_PD_REG1, GENMASK(31, 0) },
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#define VPU_PD(__name, __top_pd, __mem, __is_pwr_off, __resets, __clks)	\
23562306a36Sopenharmony_ci	{								\
23662306a36Sopenharmony_ci		.name = __name,						\
23762306a36Sopenharmony_ci		.reset_names_count = __resets,				\
23862306a36Sopenharmony_ci		.clk_names_count = __clks,				\
23962306a36Sopenharmony_ci		.top_pd = __top_pd,					\
24062306a36Sopenharmony_ci		.mem_pd_count = ARRAY_SIZE(__mem),			\
24162306a36Sopenharmony_ci		.mem_pd = __mem,					\
24262306a36Sopenharmony_ci		.is_powered_off = __is_pwr_off,				\
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci#define TOP_PD(__name, __top_pd, __mem, __is_pwr_off)			\
24662306a36Sopenharmony_ci	{								\
24762306a36Sopenharmony_ci		.name = __name,						\
24862306a36Sopenharmony_ci		.top_pd = __top_pd,					\
24962306a36Sopenharmony_ci		.mem_pd_count = ARRAY_SIZE(__mem),			\
25062306a36Sopenharmony_ci		.mem_pd = __mem,					\
25162306a36Sopenharmony_ci		.is_powered_off = __is_pwr_off,				\
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci#define MEM_PD(__name, __mem)						\
25562306a36Sopenharmony_ci	TOP_PD(__name, NULL, __mem, NULL)
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc axg_pwrc_domains[] = {
26062306a36Sopenharmony_ci	[PWRC_AXG_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, axg_pwrc_mem_vpu,
26162306a36Sopenharmony_ci				     pwrc_ee_is_powered_off, 5, 2),
26262306a36Sopenharmony_ci	[PWRC_AXG_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
26362306a36Sopenharmony_ci	[PWRC_AXG_AUDIO_ID] = MEM_PD("AUDIO", axg_pwrc_mem_audio),
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
26762306a36Sopenharmony_ci	[PWRC_G12A_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
26862306a36Sopenharmony_ci				     pwrc_ee_is_powered_off, 11, 2),
26962306a36Sopenharmony_ci	[PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
27062306a36Sopenharmony_ci	[PWRC_G12A_NNA_ID] = TOP_PD("NNA", &g12a_pwrc_nna, g12a_pwrc_mem_nna,
27162306a36Sopenharmony_ci				    pwrc_ee_is_powered_off),
27262306a36Sopenharmony_ci};
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
27562306a36Sopenharmony_ci	[PWRC_GXBB_VPU_ID]  = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu,
27662306a36Sopenharmony_ci				     pwrc_ee_is_powered_off, 12, 2),
27762306a36Sopenharmony_ci	[PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
28162306a36Sopenharmony_ci	[PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
28262306a36Sopenharmony_ci				       meson8_pwrc_mem_vpu,
28362306a36Sopenharmony_ci				       pwrc_ee_is_powered_off, 0, 1),
28462306a36Sopenharmony_ci	[PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
28562306a36Sopenharmony_ci					       meson_pwrc_mem_eth),
28662306a36Sopenharmony_ci	[PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
28762306a36Sopenharmony_ci						meson8_pwrc_audio_dsp_mem),
28862306a36Sopenharmony_ci};
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = {
29162306a36Sopenharmony_ci	[PWRC_MESON8_VPU_ID]  = VPU_PD("VPU", &meson8_pwrc_vpu,
29262306a36Sopenharmony_ci				       meson8_pwrc_mem_vpu,
29362306a36Sopenharmony_ci				       pwrc_ee_is_powered_off, 11, 1),
29462306a36Sopenharmony_ci	[PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
29562306a36Sopenharmony_ci					       meson_pwrc_mem_eth),
29662306a36Sopenharmony_ci	[PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
29762306a36Sopenharmony_ci						meson8_pwrc_audio_dsp_mem),
29862306a36Sopenharmony_ci};
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
30162306a36Sopenharmony_ci	[PWRC_SM1_VPU_ID]  = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
30262306a36Sopenharmony_ci				    pwrc_ee_is_powered_off, 11, 2),
30362306a36Sopenharmony_ci	[PWRC_SM1_NNA_ID]  = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
30462306a36Sopenharmony_ci				    pwrc_ee_is_powered_off),
30562306a36Sopenharmony_ci	[PWRC_SM1_USB_ID]  = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
30662306a36Sopenharmony_ci				    pwrc_ee_is_powered_off),
30762306a36Sopenharmony_ci	[PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
30862306a36Sopenharmony_ci				    pwrc_ee_is_powered_off),
30962306a36Sopenharmony_ci	[PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
31062306a36Sopenharmony_ci				    pwrc_ee_is_powered_off),
31162306a36Sopenharmony_ci	[PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
31262306a36Sopenharmony_ci	[PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
31362306a36Sopenharmony_ci};
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistruct meson_ee_pwrc_domain {
31662306a36Sopenharmony_ci	struct generic_pm_domain base;
31762306a36Sopenharmony_ci	bool enabled;
31862306a36Sopenharmony_ci	struct meson_ee_pwrc *pwrc;
31962306a36Sopenharmony_ci	struct meson_ee_pwrc_domain_desc desc;
32062306a36Sopenharmony_ci	struct clk_bulk_data *clks;
32162306a36Sopenharmony_ci	int num_clks;
32262306a36Sopenharmony_ci	struct reset_control *rstc;
32362306a36Sopenharmony_ci	int num_rstc;
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistruct meson_ee_pwrc {
32762306a36Sopenharmony_ci	struct regmap *regmap_ao;
32862306a36Sopenharmony_ci	struct regmap *regmap_hhi;
32962306a36Sopenharmony_ci	struct meson_ee_pwrc_domain *domains;
33062306a36Sopenharmony_ci	struct genpd_onecell_data xlate;
33162306a36Sopenharmony_ci};
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic bool pwrc_ee_is_powered_off(struct meson_ee_pwrc_domain *pwrc_domain)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	u32 reg;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	regmap_read(pwrc_domain->pwrc->regmap_ao,
33862306a36Sopenharmony_ci		    pwrc_domain->desc.top_pd->sleep_reg, &reg);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return (reg & pwrc_domain->desc.top_pd->sleep_mask);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int meson_ee_pwrc_off(struct generic_pm_domain *domain)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct meson_ee_pwrc_domain *pwrc_domain =
34662306a36Sopenharmony_ci		container_of(domain, struct meson_ee_pwrc_domain, base);
34762306a36Sopenharmony_ci	int i;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (pwrc_domain->desc.top_pd)
35062306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
35162306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->sleep_reg,
35262306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->sleep_mask,
35362306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->sleep_mask);
35462306a36Sopenharmony_ci	udelay(20);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
35762306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
35862306a36Sopenharmony_ci				   pwrc_domain->desc.mem_pd[i].reg,
35962306a36Sopenharmony_ci				   pwrc_domain->desc.mem_pd[i].mask,
36062306a36Sopenharmony_ci				   pwrc_domain->desc.mem_pd[i].mask);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	udelay(20);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (pwrc_domain->desc.top_pd)
36562306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
36662306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->iso_reg,
36762306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->iso_mask,
36862306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->iso_mask);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (pwrc_domain->num_clks) {
37162306a36Sopenharmony_ci		msleep(20);
37262306a36Sopenharmony_ci		clk_bulk_disable_unprepare(pwrc_domain->num_clks,
37362306a36Sopenharmony_ci					   pwrc_domain->clks);
37462306a36Sopenharmony_ci	}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	return 0;
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cistatic int meson_ee_pwrc_on(struct generic_pm_domain *domain)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	struct meson_ee_pwrc_domain *pwrc_domain =
38262306a36Sopenharmony_ci		container_of(domain, struct meson_ee_pwrc_domain, base);
38362306a36Sopenharmony_ci	int i, ret;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (pwrc_domain->desc.top_pd)
38662306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
38762306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->sleep_reg,
38862306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->sleep_mask, 0);
38962306a36Sopenharmony_ci	udelay(20);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	for (i = 0 ; i < pwrc_domain->desc.mem_pd_count ; ++i)
39262306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_hhi,
39362306a36Sopenharmony_ci				   pwrc_domain->desc.mem_pd[i].reg,
39462306a36Sopenharmony_ci				   pwrc_domain->desc.mem_pd[i].mask, 0);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	udelay(20);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	ret = reset_control_assert(pwrc_domain->rstc);
39962306a36Sopenharmony_ci	if (ret)
40062306a36Sopenharmony_ci		return ret;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	if (pwrc_domain->desc.top_pd)
40362306a36Sopenharmony_ci		regmap_update_bits(pwrc_domain->pwrc->regmap_ao,
40462306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->iso_reg,
40562306a36Sopenharmony_ci				   pwrc_domain->desc.top_pd->iso_mask, 0);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	ret = reset_control_deassert(pwrc_domain->rstc);
40862306a36Sopenharmony_ci	if (ret)
40962306a36Sopenharmony_ci		return ret;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	return clk_bulk_prepare_enable(pwrc_domain->num_clks,
41262306a36Sopenharmony_ci				       pwrc_domain->clks);
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cistatic int meson_ee_pwrc_init_domain(struct platform_device *pdev,
41662306a36Sopenharmony_ci				     struct meson_ee_pwrc *pwrc,
41762306a36Sopenharmony_ci				     struct meson_ee_pwrc_domain *dom)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	int ret;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	dom->pwrc = pwrc;
42262306a36Sopenharmony_ci	dom->num_rstc = dom->desc.reset_names_count;
42362306a36Sopenharmony_ci	dom->num_clks = dom->desc.clk_names_count;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	if (dom->num_rstc) {
42662306a36Sopenharmony_ci		int count = reset_control_get_count(&pdev->dev);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci		if (count != dom->num_rstc)
42962306a36Sopenharmony_ci			dev_warn(&pdev->dev, "Invalid resets count %d for domain %s\n",
43062306a36Sopenharmony_ci				 count, dom->desc.name);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci		dom->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
43362306a36Sopenharmony_ci		if (IS_ERR(dom->rstc))
43462306a36Sopenharmony_ci			return PTR_ERR(dom->rstc);
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	if (dom->num_clks) {
43862306a36Sopenharmony_ci		int ret = devm_clk_bulk_get_all(&pdev->dev, &dom->clks);
43962306a36Sopenharmony_ci		if (ret < 0)
44062306a36Sopenharmony_ci			return ret;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci		if (dom->num_clks != ret) {
44362306a36Sopenharmony_ci			dev_warn(&pdev->dev, "Invalid clocks count %d for domain %s\n",
44462306a36Sopenharmony_ci				 ret, dom->desc.name);
44562306a36Sopenharmony_ci			dom->num_clks = ret;
44662306a36Sopenharmony_ci		}
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	dom->base.name = dom->desc.name;
45062306a36Sopenharmony_ci	dom->base.power_on = meson_ee_pwrc_on;
45162306a36Sopenharmony_ci	dom->base.power_off = meson_ee_pwrc_off;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/*
45462306a36Sopenharmony_ci         * TOFIX: This is a special case for the VPU power domain, which can
45562306a36Sopenharmony_ci	 * be enabled previously by the bootloader. In this case the VPU
45662306a36Sopenharmony_ci         * pipeline may be functional but no driver maybe never attach
45762306a36Sopenharmony_ci         * to this power domain, and if the domain is disabled it could
45862306a36Sopenharmony_ci         * cause system errors. This is why the pm_domain_always_on_gov
45962306a36Sopenharmony_ci         * is used here.
46062306a36Sopenharmony_ci         * For the same reason, the clocks should be enabled in case
46162306a36Sopenharmony_ci         * we need to power the domain off, otherwise the internal clocks
46262306a36Sopenharmony_ci         * prepare/enable counters won't be in sync.
46362306a36Sopenharmony_ci         */
46462306a36Sopenharmony_ci	if (dom->num_clks && dom->desc.is_powered_off && !dom->desc.is_powered_off(dom)) {
46562306a36Sopenharmony_ci		ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
46662306a36Sopenharmony_ci		if (ret)
46762306a36Sopenharmony_ci			return ret;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci		dom->base.flags = GENPD_FLAG_ALWAYS_ON;
47062306a36Sopenharmony_ci		ret = pm_genpd_init(&dom->base, NULL, false);
47162306a36Sopenharmony_ci		if (ret)
47262306a36Sopenharmony_ci			return ret;
47362306a36Sopenharmony_ci	} else {
47462306a36Sopenharmony_ci		ret = pm_genpd_init(&dom->base, NULL,
47562306a36Sopenharmony_ci				    (dom->desc.is_powered_off ?
47662306a36Sopenharmony_ci				     dom->desc.is_powered_off(dom) : true));
47762306a36Sopenharmony_ci		if (ret)
47862306a36Sopenharmony_ci			return ret;
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	return 0;
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cistatic int meson_ee_pwrc_probe(struct platform_device *pdev)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	const struct meson_ee_pwrc_domain_data *match;
48762306a36Sopenharmony_ci	struct regmap *regmap_ao, *regmap_hhi;
48862306a36Sopenharmony_ci	struct device_node *parent_np;
48962306a36Sopenharmony_ci	struct meson_ee_pwrc *pwrc;
49062306a36Sopenharmony_ci	int i, ret;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	match = of_device_get_match_data(&pdev->dev);
49362306a36Sopenharmony_ci	if (!match) {
49462306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to get match data\n");
49562306a36Sopenharmony_ci		return -ENODEV;
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
49962306a36Sopenharmony_ci	if (!pwrc)
50062306a36Sopenharmony_ci		return -ENOMEM;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
50362306a36Sopenharmony_ci					   sizeof(*pwrc->xlate.domains),
50462306a36Sopenharmony_ci					   GFP_KERNEL);
50562306a36Sopenharmony_ci	if (!pwrc->xlate.domains)
50662306a36Sopenharmony_ci		return -ENOMEM;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
50962306a36Sopenharmony_ci				     sizeof(*pwrc->domains), GFP_KERNEL);
51062306a36Sopenharmony_ci	if (!pwrc->domains)
51162306a36Sopenharmony_ci		return -ENOMEM;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	pwrc->xlate.num_domains = match->count;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	parent_np = of_get_parent(pdev->dev.of_node);
51662306a36Sopenharmony_ci	regmap_hhi = syscon_node_to_regmap(parent_np);
51762306a36Sopenharmony_ci	of_node_put(parent_np);
51862306a36Sopenharmony_ci	if (IS_ERR(regmap_hhi)) {
51962306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to get HHI regmap\n");
52062306a36Sopenharmony_ci		return PTR_ERR(regmap_hhi);
52162306a36Sopenharmony_ci	}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	regmap_ao = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
52462306a36Sopenharmony_ci						    "amlogic,ao-sysctrl");
52562306a36Sopenharmony_ci	if (IS_ERR(regmap_ao)) {
52662306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to get AO regmap\n");
52762306a36Sopenharmony_ci		return PTR_ERR(regmap_ao);
52862306a36Sopenharmony_ci	}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	pwrc->regmap_ao = regmap_ao;
53162306a36Sopenharmony_ci	pwrc->regmap_hhi = regmap_hhi;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	platform_set_drvdata(pdev, pwrc);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	for (i = 0 ; i < match->count ; ++i) {
53662306a36Sopenharmony_ci		struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci		memcpy(&dom->desc, &match->domains[i], sizeof(dom->desc));
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci		ret = meson_ee_pwrc_init_domain(pdev, pwrc, dom);
54162306a36Sopenharmony_ci		if (ret)
54262306a36Sopenharmony_ci			return ret;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci		pwrc->xlate.domains[i] = &dom->base;
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
54862306a36Sopenharmony_ci}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_cistatic void meson_ee_pwrc_shutdown(struct platform_device *pdev)
55162306a36Sopenharmony_ci{
55262306a36Sopenharmony_ci	struct meson_ee_pwrc *pwrc = platform_get_drvdata(pdev);
55362306a36Sopenharmony_ci	int i;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
55662306a36Sopenharmony_ci		struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci		if (dom->desc.is_powered_off && !dom->desc.is_powered_off(dom))
55962306a36Sopenharmony_ci			meson_ee_pwrc_off(&dom->base);
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
56462306a36Sopenharmony_ci	.count = ARRAY_SIZE(g12a_pwrc_domains),
56562306a36Sopenharmony_ci	.domains = g12a_pwrc_domains,
56662306a36Sopenharmony_ci};
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_axg_pwrc_data = {
56962306a36Sopenharmony_ci	.count = ARRAY_SIZE(axg_pwrc_domains),
57062306a36Sopenharmony_ci	.domains = axg_pwrc_domains,
57162306a36Sopenharmony_ci};
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
57462306a36Sopenharmony_ci	.count = ARRAY_SIZE(gxbb_pwrc_domains),
57562306a36Sopenharmony_ci	.domains = gxbb_pwrc_domains,
57662306a36Sopenharmony_ci};
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
57962306a36Sopenharmony_ci	.count = ARRAY_SIZE(meson8_pwrc_domains),
58062306a36Sopenharmony_ci	.domains = meson8_pwrc_domains,
58162306a36Sopenharmony_ci};
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = {
58462306a36Sopenharmony_ci	.count = ARRAY_SIZE(meson8b_pwrc_domains),
58562306a36Sopenharmony_ci	.domains = meson8b_pwrc_domains,
58662306a36Sopenharmony_ci};
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_cistatic struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
58962306a36Sopenharmony_ci	.count = ARRAY_SIZE(sm1_pwrc_domains),
59062306a36Sopenharmony_ci	.domains = sm1_pwrc_domains,
59162306a36Sopenharmony_ci};
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic const struct of_device_id meson_ee_pwrc_match_table[] = {
59462306a36Sopenharmony_ci	{
59562306a36Sopenharmony_ci		.compatible = "amlogic,meson8-pwrc",
59662306a36Sopenharmony_ci		.data = &meson_ee_m8_pwrc_data,
59762306a36Sopenharmony_ci	},
59862306a36Sopenharmony_ci	{
59962306a36Sopenharmony_ci		.compatible = "amlogic,meson8b-pwrc",
60062306a36Sopenharmony_ci		.data = &meson_ee_m8b_pwrc_data,
60162306a36Sopenharmony_ci	},
60262306a36Sopenharmony_ci	{
60362306a36Sopenharmony_ci		.compatible = "amlogic,meson8m2-pwrc",
60462306a36Sopenharmony_ci		.data = &meson_ee_m8b_pwrc_data,
60562306a36Sopenharmony_ci	},
60662306a36Sopenharmony_ci	{
60762306a36Sopenharmony_ci		.compatible = "amlogic,meson-axg-pwrc",
60862306a36Sopenharmony_ci		.data = &meson_ee_axg_pwrc_data,
60962306a36Sopenharmony_ci	},
61062306a36Sopenharmony_ci	{
61162306a36Sopenharmony_ci		.compatible = "amlogic,meson-gxbb-pwrc",
61262306a36Sopenharmony_ci		.data = &meson_ee_gxbb_pwrc_data,
61362306a36Sopenharmony_ci	},
61462306a36Sopenharmony_ci	{
61562306a36Sopenharmony_ci		.compatible = "amlogic,meson-g12a-pwrc",
61662306a36Sopenharmony_ci		.data = &meson_ee_g12a_pwrc_data,
61762306a36Sopenharmony_ci	},
61862306a36Sopenharmony_ci	{
61962306a36Sopenharmony_ci		.compatible = "amlogic,meson-sm1-pwrc",
62062306a36Sopenharmony_ci		.data = &meson_ee_sm1_pwrc_data,
62162306a36Sopenharmony_ci	},
62262306a36Sopenharmony_ci	{ /* sentinel */ }
62362306a36Sopenharmony_ci};
62462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, meson_ee_pwrc_match_table);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistatic struct platform_driver meson_ee_pwrc_driver = {
62762306a36Sopenharmony_ci	.probe = meson_ee_pwrc_probe,
62862306a36Sopenharmony_ci	.shutdown = meson_ee_pwrc_shutdown,
62962306a36Sopenharmony_ci	.driver = {
63062306a36Sopenharmony_ci		.name		= "meson_ee_pwrc",
63162306a36Sopenharmony_ci		.of_match_table	= meson_ee_pwrc_match_table,
63262306a36Sopenharmony_ci	},
63362306a36Sopenharmony_ci};
63462306a36Sopenharmony_cimodule_platform_driver(meson_ee_pwrc_driver);
63562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
636