// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
 */

#include <linux/io.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/amlogic/power_domain.h>
#include <dt-bindings/power/a1-pd.h>
#include <dt-bindings/power/cx-pd.h>
#include <dt-bindings/power/sc2-pd.h>
#include <dt-bindings/power/t5-pd.h>
#include <dt-bindings/power/t7-pd.h>
#include <dt-bindings/power/s4-pd.h>
#include <dt-bindings/power/t3-pd.h>
#include <dt-bindings/power/p1-pd.h>
#include <dt-bindings/power/c3-pd.h>
#include <dt-bindings/power/a1-pd.h>
#include <dt-bindings/power/t5m-pd.h>
#include <dt-bindings/power/s5-pd.h>
#include <dt-bindings/power/t3x-pd.h>
#include <dt-bindings/power/txhd2-pd.h>
#include <dt-bindings/power/s1a-pd.h>
#include <linux/kallsyms.h>

struct sec_pm_private_domain {
	const char *name;
	unsigned int flags;
	int pd_index;
	bool pd_status;
	int pd_parent;
};

struct sec_pm_domain {
	struct generic_pm_domain base;
	struct sec_pm_private_domain *private_domain;
};

struct sec_pm_domain_data {
	struct sec_pm_private_domain *domains;
	unsigned int domains_count;
};

static inline struct sec_pm_domain *
to_sec_pm_domain(struct generic_pm_domain *genpd)
{
	return container_of(genpd, struct sec_pm_domain, base);
}

static int sec_pm_domain_power_off(struct generic_pm_domain *genpd)
{
	struct sec_pm_domain *pd = to_sec_pm_domain(genpd);

	pwr_ctrl_psci_smc(pd->private_domain->pd_index, PWR_OFF);

	return 0;
}

static int sec_pm_domain_power_on(struct generic_pm_domain *genpd)
{
	struct sec_pm_domain *pd = to_sec_pm_domain(genpd);

	pwr_ctrl_psci_smc(pd->private_domain->pd_index, PWR_ON);

	return 0;
}

#define TOP_DOMAIN(_name, index, status, flag, parent)		\
{					\
		.name = #_name,					\
		.flags = flag,					\
		.pd_index = index,				\
		.pd_status = status,				\
		.pd_parent = parent,				\
}

#define POWER_DOMAIN(_name, index, status, flag)	\
	TOP_DOMAIN(_name, index, status, flag, 0)

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static struct sec_pm_private_domain a1_pm_domains[] __initdata = {
	[PDID_DSP_A] =  POWER_DOMAIN(dsp_a, PDID_DSP_A, DOMAIN_INIT_ON, GENPD_FLAG_ACTIVE_WAKEUP),
	[PDID_DSP_B] =  POWER_DOMAIN(dsp_b, PDID_DSP_B, DOMAIN_INIT_ON, GENPD_FLAG_ACTIVE_WAKEUP),
	[PDID_UART] =   POWER_DOMAIN(uart, PDID_UART, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_MMC] =    POWER_DOMAIN(mmc, PDID_MMC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_I2C] =    POWER_DOMAIN(i2c, PDID_I2C, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_PSRAM] =  POWER_DOMAIN(psram, PDID_PSRAM, DOMAIN_INIT_OFF, 0),
	[PDID_ACODEC] = POWER_DOMAIN(acodec, PDID_ACODEC, DOMAIN_INIT_ON, 0),
	[PDID_AUDIO] =  POWER_DOMAIN(audio, PDID_AUDIO, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_MKL_OTP] = POWER_DOMAIN(mkl_otp, PDID_MKL_OTP, DOMAIN_INIT_ON,
				      GENPD_FLAG_ALWAYS_ON),
	[PDID_DMA] =    POWER_DOMAIN(dma, PDID_DMA, DOMAIN_INIT_ON,
				     GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
	[PDID_SDEMMC] = POWER_DOMAIN(sdemmc, PDID_SDEMMC, DOMAIN_INIT_OFF, 0),
	[PDID_SRAM_A] = POWER_DOMAIN(sram_a, PDID_SRAM_A, DOMAIN_INIT_OFF, 0),
	[PDID_SRAM_B] = POWER_DOMAIN(sram_b, PDID_SRAM_B, DOMAIN_INIT_OFF, 0),
	[PDID_IR] =     POWER_DOMAIN(ir, PDID_IR, DOMAIN_INIT_ON, 0),
	[PDID_SPICC] =  POWER_DOMAIN(spicc, PDID_SPICC, DOMAIN_INIT_OFF, 0),
	[PDID_SPIFC] =  POWER_DOMAIN(spifc, PDID_SPIFC, DOMAIN_INIT_ON, 0),
	[PDID_USB] =    POWER_DOMAIN(usb, PDID_USB, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_NIC] =    POWER_DOMAIN(nic, PDID_NIC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_PDM] =    POWER_DOMAIN(pdm, PDID_PDM, DOMAIN_INIT_OFF, 0),
	[PDID_RSA] =    POWER_DOMAIN(rsa, PDID_RSA, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data a1_pm_domain_data __initdata = {
	.domains = a1_pm_domains,
	.domains_count = ARRAY_SIZE(a1_pm_domains),
};
#endif

#ifndef CONFIG_AMLOGIC_REMOVE_OLD
static struct sec_pm_private_domain c1_pm_domains[] __initdata = {
	[PDID_CX_DSP_A] = POWER_DOMAIN(dsp_a, PDID_CX_DSP_A, DOMAIN_INIT_OFF, 0),
	[PDID_CX_DSP_B] = POWER_DOMAIN(dsp_b, PDID_CX_DSP_B, DOMAIN_INIT_OFF, 0),
	[PDID_CX_UART] = POWER_DOMAIN(uart, PDID_CX_UART, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DMC] = POWER_DOMAIN(dmc, PDID_CX_DMC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
		/* If there is GENPD_FLAG_ALWAYS_ON, the domain must be initialized to on */
	[PDID_CX_I2C] = POWER_DOMAIN(i2c, PDID_CX_I2C, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SDEMMC_B] = POWER_DOMAIN(sdemmc_b, PDID_CX_SDEMMC_B, DOMAIN_INIT_ON, 0),
	[PDID_CX_ACODEC] = POWER_DOMAIN(acodec, PDID_CX_ACODEC, DOMAIN_INIT_ON, 0),
	[PDID_CX_AUDIO] = POWER_DOMAIN(audio, PDID_CX_AUDIO, DOMAIN_INIT_ON, 0),
	[PDID_CX_MKL_OTP] = POWER_DOMAIN(mkl_otp, PDID_CX_MKL_OTP, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DMA] = POWER_DOMAIN(dma, PDID_CX_DMA, DOMAIN_INIT_ON, GENPD_FLAG_IRQ_SAFE),
	[PDID_CX_SDEMMC_A] = POWER_DOMAIN(sdemmc_a, PDID_CX_SDEMMC_A, DOMAIN_INIT_ON, 0),
	[PDID_CX_SRAM_A] = POWER_DOMAIN(sram_a, PDID_CX_SRAM_A, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SRAM_B] = POWER_DOMAIN(sram_b, PDID_CX_SRAM_B, DOMAIN_INIT_OFF, 0),
	[PDID_CX_IR] = POWER_DOMAIN(ir, PDID_CX_IR, DOMAIN_INIT_ON, 0),
	[PDID_CX_SPICC] = POWER_DOMAIN(spicc, PDID_CX_SPICC, DOMAIN_INIT_OFF, 0),
	[PDID_CX_SPIFC] = POWER_DOMAIN(spifc, PDID_CX_SPIFC, DOMAIN_INIT_ON, 0),
	[PDID_CX_USB] = POWER_DOMAIN(usb, PDID_CX_USB, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_NIC] = POWER_DOMAIN(nic, PDID_CX_NIC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_PDM] = POWER_DOMAIN(pdm, PDID_CX_PDM, DOMAIN_INIT_ON, 0),
	[PDID_CX_RSA] = POWER_DOMAIN(rsa, PDID_CX_RSA, DOMAIN_INIT_OFF, 0),
	[PDID_CX_MIPI_ISP] = POWER_DOMAIN(mipi_isp, PDID_CX_MIPI_ISP, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_HCODEC] = POWER_DOMAIN(hcodec, PDID_CX_HCODEC, DOMAIN_INIT_ON, 0),
	[PDID_CX_WAVE] = POWER_DOMAIN(wave, PDID_CX_WAVE, DOMAIN_INIT_OFF, 0),
	[PDID_CX_SDEMMC_C] = POWER_DOMAIN(sdemmc_c, PDID_CX_SDEMMC_C, DOMAIN_INIT_ON, 0),
	[PDID_CX_SRAM_C] = POWER_DOMAIN(sram_c, PDID_CX_SRAM_C, DOMAIN_INIT_OFF, 0),
	[PDID_CX_GDC] = POWER_DOMAIN(gdc, PDID_CX_GDC, DOMAIN_INIT_OFF, 0),
	[PDID_CX_GE2D] = POWER_DOMAIN(ge2d, PDID_CX_GE2D, DOMAIN_INIT_OFF, 0),
	[PDID_CX_NNA] = POWER_DOMAIN(nna, PDID_CX_NNA, DOMAIN_INIT_OFF, 0),
	[PDID_CX_ETH] = POWER_DOMAIN(eth, PDID_CX_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_GIC] = POWER_DOMAIN(gic, PDID_CX_GIC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DDR] = POWER_DOMAIN(ddr, PDID_CX_DDR, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SPICC_B] = POWER_DOMAIN(spicc_b, PDID_CX_SPICC_B, DOMAIN_INIT_ON,
									 GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data c1_pm_domain_data __initdata = {
	.domains = c1_pm_domains,
	.domains_count = ARRAY_SIZE(c1_pm_domains),
};
#endif

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
/* If there is GENPD_FLAG_ALWAYS_ON, the domain must be initialized to on */
static struct sec_pm_private_domain c2_pm_domains[] __initdata = {
	[PDID_CX_CPU_PWR0] = POWER_DOMAIN(cpu_pwr0, PDID_CX_CPU_PWR0, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_CPU_CORE0] = POWER_DOMAIN(cpu_core0, PDID_CX_CPU_CORE0, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_CPU_CORE1] = POWER_DOMAIN(cpu_core1, PDID_CX_CPU_CORE1, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SPTOP] = POWER_DOMAIN(sptop, PDID_CX_SPTOP, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DSP_A] = POWER_DOMAIN(dsp_a, PDID_CX_DSP_A, DOMAIN_INIT_ON, GENPD_FLAG_ACTIVE_WAKEUP),
	[PDID_CX_DSP_B] = POWER_DOMAIN(dsp_b, PDID_CX_DSP_B, DOMAIN_INIT_ON, GENPD_FLAG_ACTIVE_WAKEUP),
	[PDID_CX_UART] = POWER_DOMAIN(uart, PDID_CX_UART, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DMC] = POWER_DOMAIN(dmc, PDID_CX_DMC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_I2C] = POWER_DOMAIN(i2c, PDID_CX_I2C, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SDEMMC_B] = POWER_DOMAIN(sdemmc_b, PDID_CX_SDEMMC_B, DOMAIN_INIT_ON, 0),
	[PDID_CX_ACODEC] = POWER_DOMAIN(acodec, PDID_CX_ACODEC, DOMAIN_INIT_ON, 0),
	[PDID_CX_AUDIO] = POWER_DOMAIN(audio, PDID_CX_AUDIO, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_MKL_OTP] = POWER_DOMAIN(mkl_otp, PDID_CX_MKL_OTP, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DMA] = POWER_DOMAIN(dma, PDID_CX_DMA, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON | GENPD_FLAG_IRQ_SAFE),
	[PDID_CX_SDEMMC_A] = POWER_DOMAIN(sdemmc_a, PDID_CX_SDEMMC_A, DOMAIN_INIT_ON, 0),
	[PDID_CX_SRAM_A] = POWER_DOMAIN(sram_a, PDID_CX_SRAM_A, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SRAM_B] = POWER_DOMAIN(sram_b, PDID_CX_SRAM_B, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_IR] = POWER_DOMAIN(ir, PDID_CX_IR, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SPICC] = POWER_DOMAIN(spicc, PDID_CX_SPICC, DOMAIN_INIT_OFF, 0),
	[PDID_CX_SPIFC] = POWER_DOMAIN(spifc, PDID_CX_SPIFC, DOMAIN_INIT_ON, 0),
	[PDID_CX_USB] = POWER_DOMAIN(usb, PDID_CX_USB, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_NIC] = POWER_DOMAIN(nic, PDID_CX_NIC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_PDM] = POWER_DOMAIN(pdm, PDID_CX_PDM, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_RSA] = POWER_DOMAIN(rsa, PDID_CX_RSA, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_MIPI_ISP] = POWER_DOMAIN(mipi_isp, PDID_CX_MIPI_ISP, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_HCODEC] = POWER_DOMAIN(hcodec, PDID_CX_HCODEC, DOMAIN_INIT_ON, 0),
	[PDID_CX_WAVE] = POWER_DOMAIN(wave, PDID_CX_WAVE, DOMAIN_INIT_OFF, 0),
	[PDID_CX_SDEMMC_C] = POWER_DOMAIN(sdemmc_c, PDID_CX_SDEMMC_C, DOMAIN_INIT_ON, 0),
	[PDID_CX_SRAM_C] = POWER_DOMAIN(sram_c, PDID_CX_SRAM_C, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_GDC] = POWER_DOMAIN(gdc, PDID_CX_GDC, DOMAIN_INIT_OFF, 0),
	[PDID_CX_GE2D] = POWER_DOMAIN(ge2d, PDID_CX_GE2D, DOMAIN_INIT_OFF, 0),
	[PDID_CX_NNA] = POWER_DOMAIN(nna, PDID_CX_NNA, DOMAIN_INIT_OFF, 0),
	[PDID_CX_ETH] = POWER_DOMAIN(eth, PDID_CX_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_GIC] = POWER_DOMAIN(gic, PDID_CX_GIC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_DDR] = POWER_DOMAIN(ddr, PDID_CX_DDR, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_CX_SPICC_B] = POWER_DOMAIN(spicc_b, PDID_CX_SPICC_B, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data c2_pm_domain_data __initdata = {
	.domains = c2_pm_domains,
	.domains_count = ARRAY_SIZE(c2_pm_domains),
};

static struct sec_pm_private_domain sc2_pm_domains[] __initdata = {
	[PDID_SC2_DSP] = POWER_DOMAIN(dsp, PDID_SC2_DSP, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_DOS_HCODEC] = POWER_DOMAIN(hcodec, PDID_SC2_DOS_HCODEC, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_SC2_DOS_HEVC, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_SC2_DOS_VDEC, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_DOS_WAVE] = POWER_DOMAIN(wave, PDID_SC2_DOS_WAVE, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_SC2_VPU_HDMI, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_SC2_USB_COMB] = POWER_DOMAIN(usb, PDID_SC2_USB_COMB, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_SC2_PCIE] = POWER_DOMAIN(pcie, PDID_SC2_PCIE, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_GE2D] = POWER_DOMAIN(ge2d, PDID_SC2_GE2D, DOMAIN_INIT_OFF, 0),
	[PDID_SC2_ETH] = POWER_DOMAIN(eth, PDID_SC2_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_SC2_AUDIO] = POWER_DOMAIN(audio, PDID_SC2_AUDIO, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data sc2_pm_domain_data __initdata = {
	.domains = sc2_pm_domains,
	.domains_count = ARRAY_SIZE(sc2_pm_domains),
};

static struct sec_pm_private_domain t5_pm_domains[] __initdata = {
	[PDID_T5_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_T5_DOS_HEVC, DOMAIN_INIT_OFF, 0),
	[PDID_T5_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_T5_DOS_VDEC, DOMAIN_INIT_OFF, 0),
	[PDID_T5_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_T5_VPU_HDMI, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_T5_DEMOD] = POWER_DOMAIN(demod, PDID_T5_DEMOD, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data t5_pm_domain_data __initdata = {
	.domains = t5_pm_domains,
	.domains_count = ARRAY_SIZE(t5_pm_domains),
};

static struct sec_pm_private_domain t7_pm_domains[] __initdata = {
	[PDID_T7_DSPA] = POWER_DOMAIN(dspa, PDID_T7_DSPA, DOMAIN_INIT_OFF, 0),
	[PDID_T7_DSPB] = POWER_DOMAIN(dspb, PDID_T7_DSPB, DOMAIN_INIT_OFF, 0),
	[PDID_T7_DOS_HCODEC] = TOP_DOMAIN(hcodec, PDID_T7_DOS_HCODEC, DOMAIN_INIT_OFF, 0,
					  PDID_T7_NIC3),
	[PDID_T7_DOS_HEVC] = TOP_DOMAIN(hevc, PDID_T7_DOS_HEVC, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_DOS_VDEC] = TOP_DOMAIN(vdec, PDID_T7_DOS_VDEC, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_DOS_WAVE] = TOP_DOMAIN(wave, PDID_T7_DOS_WAVE, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_T7_VPU_HDMI, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_USB_COMB] = POWER_DOMAIN(usb, PDID_T7_USB_COMB, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_PCIE] = POWER_DOMAIN(pcie, PDID_T7_PCIE, DOMAIN_INIT_OFF, 0),
	[PDID_T7_GE2D] = TOP_DOMAIN(ge2d, PDID_T7_GE2D, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_SRAMA] = POWER_DOMAIN(srama, PDID_T7_SRAMA, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_SRAMB] = POWER_DOMAIN(sramb, PDID_T7_SRAMB, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_HDMIRX] = POWER_DOMAIN(hdmirx, PDID_T7_HDMIRX, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_VI_CLK1] = POWER_DOMAIN(vi_clk1, PDID_T7_VI_CLK1,
					 DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_VI_CLK2] = POWER_DOMAIN(vi_clk2, PDID_T7_VI_CLK2,
					 DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_ETH] = POWER_DOMAIN(eth, PDID_T7_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_ISP] = POWER_DOMAIN(isp, PDID_T7_ISP, DOMAIN_INIT_OFF, 0),
	[PDID_T7_MIPI_ISP] = POWER_DOMAIN(mipi_isp, PDID_T7_MIPI_ISP, DOMAIN_INIT_OFF, 0),
	[PDID_T7_GDC] = TOP_DOMAIN(gdc, PDID_T7_GDC, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_DEWARP] = TOP_DOMAIN(dewarp, PDID_T7_DEWARP, DOMAIN_INIT_OFF, 0, PDID_T7_NIC3),
	[PDID_T7_SDIO_A] = POWER_DOMAIN(sdio_a, PDID_T7_SDIO_A,
					DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_SDIO_B] = POWER_DOMAIN(sdio_b, PDID_T7_SDIO_B,
					DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_EMMC] = POWER_DOMAIN(emmc, PDID_T7_EMMC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_MALI_SC0] = TOP_DOMAIN(mali_sc0, PDID_T7_MALI_SC0, DOMAIN_INIT_OFF, 0,
					PDID_T7_MALI_TOP),
	[PDID_T7_MALI_SC1] = TOP_DOMAIN(mali_sc1, PDID_T7_MALI_SC1, DOMAIN_INIT_OFF, 0,
					PDID_T7_MALI_TOP),
	[PDID_T7_MALI_SC2] = TOP_DOMAIN(mali_sc2, PDID_T7_MALI_SC2, DOMAIN_INIT_OFF, 0,
					PDID_T7_MALI_TOP),
	[PDID_T7_MALI_SC3] = TOP_DOMAIN(mali_sc3, PDID_T7_MALI_SC3, DOMAIN_INIT_OFF, 0,
					PDID_T7_MALI_TOP),
	[PDID_T7_MALI_TOP] = POWER_DOMAIN(mali_top, PDID_T7_MALI_TOP, DOMAIN_INIT_OFF, 0),
	[PDID_T7_NNA_CORE0] = TOP_DOMAIN(nna_core0, PDID_T7_NNA_CORE0, DOMAIN_INIT_OFF, 0,
					 PDID_T7_NNA_TOP),
	[PDID_T7_NNA_CORE1] = TOP_DOMAIN(nna_core1, PDID_T7_NNA_CORE1, DOMAIN_INIT_OFF, 0,
					 PDID_T7_NNA_TOP),
	[PDID_T7_NNA_CORE2] = TOP_DOMAIN(nna_core2, PDID_T7_NNA_CORE2, DOMAIN_INIT_OFF, 0,
					 PDID_T7_NNA_TOP),
	[PDID_T7_NNA_CORE3] = TOP_DOMAIN(nna_core3, PDID_T7_NNA_CORE3, DOMAIN_INIT_OFF, 0,
					 PDID_T7_NNA_TOP),
	[PDID_T7_NNA_TOP] = POWER_DOMAIN(nna_top, PDID_T7_NNA_TOP, DOMAIN_INIT_OFF, 0),
	[PDID_T7_DDR0] = POWER_DOMAIN(ddr0, PDID_T7_DDR0, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_DDR1] = POWER_DOMAIN(ddr1, PDID_T7_DDR1, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_DMC0] = POWER_DOMAIN(dmc0, PDID_T7_DMC0, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_DMC1] = POWER_DOMAIN(dmc1, PDID_T7_DMC1, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_NOC] = POWER_DOMAIN(noc, PDID_T7_NOC, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_NIC2] = POWER_DOMAIN(nic2, PDID_T7_NIC2, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_NIC3] = POWER_DOMAIN(nic3, PDID_T7_NIC3, DOMAIN_INIT_OFF, 0),
	[PDID_T7_CCI] = POWER_DOMAIN(cci, PDID_T7_CCI, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_MIPI_DSI0] = POWER_DOMAIN(mipi_dsi0, PDID_T7_MIPI_DSI0,
					   DOMAIN_INIT_ON,
					   GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_SPICC0] = POWER_DOMAIN(spicc0, PDID_T7_SPICC0, DOMAIN_INIT_OFF, 0),
	[PDID_T7_SPICC1] = POWER_DOMAIN(spicc1, PDID_T7_SPICC1, DOMAIN_INIT_OFF, 0),
	[PDID_T7_SPICC2] = POWER_DOMAIN(spicc2, PDID_T7_SPICC2, DOMAIN_INIT_OFF, 0),
	[PDID_T7_SPICC3] = POWER_DOMAIN(spicc3, PDID_T7_SPICC3, DOMAIN_INIT_OFF, 0),
	[PDID_T7_SPICC4] = POWER_DOMAIN(spicc4, PDID_T7_SPICC4, DOMAIN_INIT_OFF, 0),
	[PDID_T7_SPICC5] = POWER_DOMAIN(spicc5, PDID_T7_SPICC5, DOMAIN_INIT_OFF, 0),
	[PDID_T7_EDP0] = POWER_DOMAIN(edp0, PDID_T7_EDP0, DOMAIN_INIT_ON,
				      GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_EDP1] = POWER_DOMAIN(edp1, PDID_T7_EDP1, DOMAIN_INIT_ON,
				      GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_MIPI_DSI1] = POWER_DOMAIN(mipi_dsi1, PDID_T7_MIPI_DSI1,
					   DOMAIN_INIT_ON,
					   GENPD_FLAG_ALWAYS_ON),
	[PDID_T7_AUDIO] = POWER_DOMAIN(audio, PDID_T7_AUDIO, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data t7_pm_domain_data __initdata = {
	.domains = t7_pm_domains,
	.domains_count = ARRAY_SIZE(t7_pm_domains),
};
#endif

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT_C1A
static struct sec_pm_private_domain s4_pm_domains[] __initdata = {
	[PDID_S4_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_S4_DOS_HEVC, DOMAIN_INIT_OFF, 0),
	[PDID_S4_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_S4_DOS_VDEC, DOMAIN_INIT_OFF, 0),
	[PDID_S4_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_S4_VPU_HDMI, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_S4_USB_COMB] = POWER_DOMAIN(usb, PDID_S4_USB_COMB, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_S4_GE2D] = POWER_DOMAIN(ge2d, PDID_S4_GE2D, DOMAIN_INIT_OFF, 0),
	[PDID_S4_ETH] = POWER_DOMAIN(eth, PDID_S4_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S4_DEMOD] = POWER_DOMAIN(demod, PDID_S4_DEMOD, DOMAIN_INIT_OFF, 0),
	[PDID_S4_AUDIO] = POWER_DOMAIN(audio, PDID_S4_AUDIO, DOMAIN_INIT_OFF, 0),
};
static struct sec_pm_domain_data s4_pm_domain_data __initdata = {
	.domains = s4_pm_domains,
	.domains_count = ARRAY_SIZE(s4_pm_domains),
};
#endif

#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
static struct sec_pm_private_domain s5_pm_domains[] = {
	[PDID_S5_MALI_0] = TOP_DOMAIN(mali_0, PDID_S5_MALI_0,
			DOMAIN_INIT_OFF, 0, PDID_S5_MALI_TOP),
	[PDID_S5_MALI_1] = TOP_DOMAIN(mali_1, PDID_S5_MALI_1,
			DOMAIN_INIT_OFF, 0, PDID_S5_MALI_TOP),
	[PDID_S5_MALI_2] = TOP_DOMAIN(mali_2, PDID_S5_MALI_2,
			DOMAIN_INIT_OFF, 0, PDID_S5_MALI_TOP),
	[PDID_S5_MALI_TOP] = POWER_DOMAIN(mali_top, PDID_S5_MALI_TOP,
			DOMAIN_INIT_OFF, 0),
	[PDID_S5_DOS_TOP_WRAP] = POWER_DOMAIN(dos_top_wrap, PDID_S5_DOS_TOP_WRAP,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DOS_VDEC] = TOP_DOMAIN(dos_vdec, PDID_S5_DOS_VDEC,
			DOMAIN_INIT_OFF, 0, PDID_S5_DOS_TOP_WRAP),
	[PDID_S5_DOS_HCODEC] = TOP_DOMAIN(dos_hcode, PDID_S5_DOS_HCODEC,
			DOMAIN_INIT_OFF, 0, PDID_S5_DOS_TOP_WRAP),
	[PDID_S5_DOS_HEVC_TOP] = TOP_DOMAIN(dos_hevc_top, PDID_S5_DOS_HEVC_TOP,
			DOMAIN_INIT_OFF, 0, PDID_S5_DOS_TOP_WRAP),
	[PDID_S5_DOS_HEVC_CORE1] = TOP_DOMAIN(dos_hevc_core1, PDID_S5_DOS_HEVC_CORE1,
			DOMAIN_INIT_OFF, 0, PDID_S5_DOS_TOP_WRAP),
	[PDID_S5_USB2] = POWER_DOMAIN(usb2, PDID_S5_USB2,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_PCIE0] = POWER_DOMAIN(pcie0, PDID_S5_PCIE0,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_GE2D] = TOP_DOMAIN(ge2d, PDID_S5_GE2D,
			DOMAIN_INIT_OFF, 0, PDID_S5_VGE_TOP),
	[PDID_S5_VC9000E] = TOP_DOMAIN(vc9000e, PDID_S5_VC9000E,
			DOMAIN_INIT_OFF, 0, PDID_S5_VGE_TOP),
	[PDID_S5_VICP] = TOP_DOMAIN(vicp, PDID_S5_VICP,
			DOMAIN_INIT_OFF, 0, PDID_S5_VGE_TOP),
	[PDID_S5_VGE_TOP] = POWER_DOMAIN(vge_top, PDID_S5_VGE_TOP,
			DOMAIN_INIT_OFF, 0),
	[PDID_S5_VI_CLK1] = TOP_DOMAIN(vi_clk1, PDID_S5_VI_CLK1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON, PDID_S5_VPU_HDMI),
	[PDID_S5_VI_CLK2] = TOP_DOMAIN(vi_clk2, PDID_S5_VI_CLK2,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON, PDID_S5_VPU_HDMI),
	[PDID_S5_VPU_HDMI] = POWER_DOMAIN(vpu_hdmi, PDID_S5_VPU_HDMI,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_ETH] = POWER_DOMAIN(eth, PDID_S5_ETH,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_PCIE1] = POWER_DOMAIN(pcie1, PDID_S5_PCIE1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_VPU_DOLBY] = TOP_DOMAIN(vpu_dolby, PDID_S5_VPU_DOLBY,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON, PDID_S5_VPU_HDMI),
	[PDID_S5_USB30] = POWER_DOMAIN(usb30, PDID_S5_USB30,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_USB31] = POWER_DOMAIN(usb31, PDID_S5_USB31,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_SDCARD] = POWER_DOMAIN(sdcard, PDID_S5_SDCARD,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_SDIO] = POWER_DOMAIN(sdio, PDID_S5_SDIO,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_NAND_EMMC] = POWER_DOMAIN(nand_emmc, PDID_S5_NAND_EMMC,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_NNA_4T] = POWER_DOMAIN(nna_4t, PDID_S5_NNA_4T,
			DOMAIN_INIT_OFF, 0),
	[PDID_S5_DMC00] = POWER_DOMAIN(dmc00, PDID_S5_DMC00,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DMC01] = POWER_DOMAIN(dmc01, PDID_S5_DMC01,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_NOC_DMC_TOP] = POWER_DOMAIN(dmc_top, PDID_S5_NOC_DMC_TOP,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DMC10] = POWER_DOMAIN(dmc10, PDID_S5_DMC10,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DMC11] = POWER_DOMAIN(dmc11, PDID_S5_DMC11,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DDRPHY0] = POWER_DOMAIN(ddrphy0, PDID_S5_DDRPHY0,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_S5_DDRPHY1] = POWER_DOMAIN(ddrphy1, PDID_S5_DDRPHY1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data s5_pm_domain_data = {
	.domains = s5_pm_domains,
	.domains_count = ARRAY_SIZE(s5_pm_domains),
};

static struct sec_pm_private_domain t3_pm_domains[] = {
	[PDID_T3_DSPA] = POWER_DOMAIN(dspa, PDID_T3_DSPA, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_DOS_HCODEC] = POWER_DOMAIN(hcodec, PDID_T3_DOS_HCODEC, DOMAIN_INIT_OFF, 0),
	[PDID_T3_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_T3_DOS_HEVC, DOMAIN_INIT_OFF, 0),
	[PDID_T3_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_T3_DOS_VDEC, DOMAIN_INIT_OFF, 0),
	[PDID_T3_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_T3_VPU_HDMI, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_USB_COMB] = POWER_DOMAIN(usb, PDID_T3_USB_COMB, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_PCIE] = POWER_DOMAIN(pcie, PDID_T3_PCIE, DOMAIN_INIT_OFF, 0),
	[PDID_T3_GE2D] = POWER_DOMAIN(ge2d, PDID_T3_GE2D, DOMAIN_INIT_OFF, 0),
	[PDID_T3_SRAMA] = POWER_DOMAIN(srama, PDID_T3_SRAMA, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_HDMIRX] = POWER_DOMAIN(hdmirx, PDID_T3_HDMIRX, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_VI_CLK1] = POWER_DOMAIN(vi_clk1, PDID_T3_VI_CLK1,
					 DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_VI_CLK2] = POWER_DOMAIN(vi_clk2, PDID_T3_VI_CLK2,
					 DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_ETH] = POWER_DOMAIN(eth, PDID_T3_ETH, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_NNA] = POWER_DOMAIN(nna, PDID_T3_NNA, DOMAIN_INIT_OFF, 0),
	[PDID_T3_DEMOD] = POWER_DOMAIN(demod, PDID_T3_DEMOD, DOMAIN_INIT_OFF, 0),
	[PDID_T3_FRCTOP] = POWER_DOMAIN(frctop, PDID_T3_FRCTOP, DOMAIN_INIT_OFF, 0),
	[PDID_T3_FRCME] = POWER_DOMAIN(frcme, PDID_T3_FRCME, DOMAIN_INIT_OFF, 0),
	[PDID_T3_FRCMC] = POWER_DOMAIN(frcmc, PDID_T3_FRCMC, DOMAIN_INIT_OFF, 0),
	[PDID_T3_SDEMMC_B] = POWER_DOMAIN(sdemmc_b, PDID_T3_SDEMMC_B,
					  DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_SDEMMC_C] = POWER_DOMAIN(sdemmc_c, PDID_T3_SDEMMC_C,
					  DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_NOC_DEV] = POWER_DOMAIN(noc_dev, PDID_T3_NOC_DEV, DOMAIN_INIT_ON,
					 GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_NOC_VPU] = POWER_DOMAIN(noc_vpu, PDID_T3_NOC_VPU, DOMAIN_INIT_ON,
					 GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_SPICC0] = POWER_DOMAIN(spicc0, PDID_T3_SPICC0, DOMAIN_INIT_OFF, 0),
	[PDID_T3_SPICC1] = POWER_DOMAIN(spicc1, PDID_T3_SPICC1, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_T3_SPICC2] = POWER_DOMAIN(spicc2, PDID_T3_SPICC2, DOMAIN_INIT_OFF, 0),
	[PDID_T3_AUDIO] = POWER_DOMAIN(audio, PDID_T3_AUDIO, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data t3_pm_domain_data = {
	.domains = t3_pm_domains,
	.domains_count = ARRAY_SIZE(t3_pm_domains),
};

static struct sec_pm_private_domain p1_pm_domains[] = {
	[PDID_P1_DSPA] = POWER_DOMAIN(dspa, PDID_P1_DSPA, DOMAIN_INIT_OFF, 0),
	[PDID_P1_DSPB] = POWER_DOMAIN(dspb, PDID_P1_DSPB, DOMAIN_INIT_OFF, 0),
	[PDID_P1_M4A] = POWER_DOMAIN(m4a, PDID_P1_M4A, DOMAIN_INIT_OFF, 0),
	[PDID_P1_M4B] = POWER_DOMAIN(m4b, PDID_P1_M4B, DOMAIN_INIT_OFF, 0),
	[PDID_P1_ISP_A] = POWER_DOMAIN(ispa, PDID_P1_ISP_A, DOMAIN_INIT_OFF, 0),
	[PDID_P1_ISP_B] = POWER_DOMAIN(ispb, PDID_P1_ISP_B, DOMAIN_INIT_OFF, 0),
	[PDID_P1_ISP_C] = POWER_DOMAIN(ispc, PDID_P1_ISP_C, DOMAIN_INIT_OFF, 0),
	[PDID_P1_ISP_D] = POWER_DOMAIN(ispd, PDID_P1_ISP_D, DOMAIN_INIT_OFF, 0),
	[PDID_P1_MIPI_ISP_TOP] = POWER_DOMAIN(mipiisptop, PDID_P1_MIPI_ISP_TOP,
			DOMAIN_INIT_OFF, 0),

	[PDID_P1_USB_COMB] = POWER_DOMAIN(usbcomb, PDID_P1_USB_COMB,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_PCIE] = POWER_DOMAIN(pcie, PDID_P1_PCIE,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_ETH] = POWER_DOMAIN(eth, PDID_P1_ETH,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_SDIO] = POWER_DOMAIN(sdio, PDID_P1_SDIO,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),

	[PDID_P1_NAND_EMMC] = POWER_DOMAIN(nandemmc, PDID_P1_NAND_EMMC,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_NNA_A] = TOP_DOMAIN(nnaa, PDID_P1_NNA_A, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_B] = TOP_DOMAIN(nnab, PDID_P1_NNA_B, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_C] = TOP_DOMAIN(nnac, PDID_P1_NNA_C, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_D] = TOP_DOMAIN(nnad, PDID_P1_NNA_D, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_E] = TOP_DOMAIN(nnae, PDID_P1_NNA_E, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_F] = TOP_DOMAIN(nnaf, PDID_P1_NNA_F, DOMAIN_INIT_OFF,
			0, PDID_P1_NNA_TOP),
	[PDID_P1_NNA_TOP] = POWER_DOMAIN(nnatop, PDID_P1_NNA_TOP,
			DOMAIN_INIT_OFF, 0),

	[PDID_P1_GE2D] = TOP_DOMAIN(ge2d, PDID_P1_GE2D, DOMAIN_INIT_OFF,
			0, PDID_P1_FDLE),
	[PDID_P1_DEWA] = TOP_DOMAIN(dewa, PDID_P1_DEWA, DOMAIN_INIT_OFF,
			0, PDID_P1_FDLE),
	[PDID_P1_DEWB] = TOP_DOMAIN(dewb, PDID_P1_DEWB, DOMAIN_INIT_OFF,
			0, PDID_P1_FDLE),
	[PDID_P1_DEWC] = TOP_DOMAIN(dewc, PDID_P1_DEWC, DOMAIN_INIT_OFF,
			0, PDID_P1_FDLE),
	[PDID_P1_FDLE] = POWER_DOMAIN(fdle, PDID_P1_FDLE,
			DOMAIN_INIT_OFF, 0),

	[PDID_P1_DMC0] = TOP_DOMAIN(dmc0, PDID_P1_DMC0,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON, PDID_P1_NOC_DMC_TOP),
	[PDID_P1_DMC1] = TOP_DOMAIN(dmc1, PDID_P1_DMC1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON, PDID_P1_NOC_DMC_TOP),
	[PDID_P1_NOC_DMC_TOP] = POWER_DOMAIN(nocdmctop, PDID_P1_NOC_DMC_TOP,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_SMMU] = POWER_DOMAIN(smmu, PDID_P1_SMMU,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_DDR0] = POWER_DOMAIN(ddr0, PDID_P1_DDR0,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_P1_DDR1] = POWER_DOMAIN(ddr1, PDID_P1_DDR1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data p1_pm_domain_data = {
	.domains = p1_pm_domains,
	.domains_count = ARRAY_SIZE(p1_pm_domains),
};

static struct sec_pm_private_domain t5w_pm_domains[] __initdata = {
	[PDID_T5_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_T5_DOS_HEVC,
		DOMAIN_INIT_OFF, 0),
	[PDID_T5_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_T5_DOS_VDEC,
		DOMAIN_INIT_OFF, 0),
	[PDID_T5_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_T5_VPU_HDMI, DOMAIN_INIT_ON,
		GENPD_FLAG_ALWAYS_ON),
	[PDID_T5_DEMOD] = POWER_DOMAIN(demod, PDID_T5_DEMOD, DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data t5w_pm_domain_data __initdata = {
	.domains = t5w_pm_domains,
	.domains_count = ARRAY_SIZE(t5w_pm_domains),
};

static struct sec_pm_private_domain t5m_pm_domains[] __initdata = {
	[PDID_T5M_DOS_HEVC] = TOP_DOMAIN(hevc, PDID_T5M_DOS_HEVC,
					   DOMAIN_INIT_OFF, 0, PDID_T5M_DOS_GE2D_WRAP),
	[PDID_T5M_DOS_GE2D_WRAP] = POWER_DOMAIN(ge2d, PDID_T5M_DOS_GE2D_WRAP,
						DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T5M_VPU_HDMI] = POWER_DOMAIN(vpu, PDID_T5M_VPU_HDMI,
					DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T5M_DEMOD] = POWER_DOMAIN(demod, PDID_T5M_DEMOD,
					DOMAIN_INIT_OFF, 0),
	[PDID_T5M_FRC_TOP] = POWER_DOMAIN(frc, PDID_T5M_FRC_TOP,
					  DOMAIN_INIT_OFF, 0),
};

static struct sec_pm_domain_data t5m_pm_domain_data __initdata = {
	.domains = t5m_pm_domains,
	.domains_count = ARRAY_SIZE(t5m_pm_domains),
};

static struct sec_pm_private_domain c3_pm_domains[] __initdata = {
	[PDID_C3_NNA] = POWER_DOMAIN(nna, PDID_C3_NNA, DOMAIN_INIT_OFF, 0),
	[PDID_C3_AUDIO] = POWER_DOMAIN(audio, PDID_C3_AUDIO, DOMAIN_INIT_ON,
				       GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_SDIOA] = POWER_DOMAIN(sdioa, PDID_C3_SDIOA, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_EMMC] = POWER_DOMAIN(emmc, PDID_C3_EMMC, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_USB_COMB] = POWER_DOMAIN(usb_comb, PDID_C3_USB_COMB, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_SDCARD] = POWER_DOMAIN(sdcard, PDID_C3_SDCARD, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_ETH] = POWER_DOMAIN(eth, PDID_C3_ETH, DOMAIN_INIT_ON,
				     GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_GE2D] = POWER_DOMAIN(ge2d, PDID_C3_GE2D, DOMAIN_INIT_ON, 0),
	[PDID_C3_CVE] = POWER_DOMAIN(cve, PDID_C3_CVE, DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_GDC_WRAP] = POWER_DOMAIN(cdg_wrap, PDID_C3_GDC_WRAP, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_ISP_TOP] = POWER_DOMAIN(isp_top, PDID_C3_ISP_TOP, DOMAIN_INIT_ON,
					 GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_MIPI_ISP_WRAP] = POWER_DOMAIN(isp_warp, PDID_C3_MIPI_ISP_WRAP, DOMAIN_INIT_ON,
					       GENPD_FLAG_ALWAYS_ON),
	[PDID_C3_VCODEC] = POWER_DOMAIN(vcodec, PDID_C3_VCODEC, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data c3_pm_domain_data __initdata = {
	.domains = c3_pm_domains,
	.domains_count = ARRAY_SIZE(c3_pm_domains),
};

static struct sec_pm_private_domain t3x_pm_domains[] = {
	[PDID_T3X_DSPA] = POWER_DOMAIN(dspa, PDID_T3X_DSPA,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_MALI_0] = POWER_DOMAIN(mali0, PDID_T3X_MALI_0,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_MALI_1] = POWER_DOMAIN(mali1, PDID_T3X_MALI_1,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_MALI_2] = POWER_DOMAIN(mali2, PDID_T3X_MALI_2,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_T3X_DOS_VDEC,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_DOS_HCODEC] = POWER_DOMAIN(hcodec,
			PDID_T3X_DOS_HCODEC, DOMAIN_INIT_OFF, 0),
	[PDID_T3X_DOS_HEVC_TOP] = POWER_DOMAIN(hevc, PDID_T3X_DOS_HEVC_TOP,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_USB2HX2] = POWER_DOMAIN(usb2hx2, PDID_T3X_USB2HX2,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_GE2D] = POWER_DOMAIN(ge2d, PDID_T3X_GE2D,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_VICP] = POWER_DOMAIN(vicp, PDID_T3X_VICP,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_VI_CLK1] = POWER_DOMAIN(clk1, PDID_T3X_VI_CLK1,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_VI_CLK2] = POWER_DOMAIN(clk2, PDID_T3X_VI_CLK2,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_VPU_DOLBY] = POWER_DOMAIN(dolby, PDID_T3X_VPU_DOLBY,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_VPU_HDMI] = POWER_DOMAIN(hdmi, PDID_T3X_VPU_HDMI,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_ETH] = POWER_DOMAIN(eth, PDID_T3X_ETH,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_PCIE] = POWER_DOMAIN(pcie, PDID_T3X_PCIE,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_USB30] = POWER_DOMAIN(usb30, PDID_T3X_USB30,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_USB31] = POWER_DOMAIN(usb31, PDID_T3X_USB31,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_SDCARD] = POWER_DOMAIN(sdcard, PDID_T3X_SDCARD,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_NAND_EMMC] = POWER_DOMAIN(emmc, PDID_T3X_NAND_EMMC,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_NNA_4T] = POWER_DOMAIN(nna, PDID_T3X_NNA_4T,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_FRC_TOP] = POWER_DOMAIN(frc, PDID_T3X_FRC_TOP,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_HDMIRX_WRAP] = POWER_DOMAIN(hdmirx, PDID_T3X_HDMIRX_WRAP,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_DEMOD] = POWER_DOMAIN(demo, PDID_T3X_DEMOD,
			DOMAIN_INIT_OFF, 0),
	[PDID_T3X_AUDIO] = POWER_DOMAIN(audio, PDID_T3X_AUDIO,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_DMC00] = POWER_DOMAIN(dmc00, PDID_T3X_DMC00,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_NOC_DMC_TOP] = POWER_DOMAIN(dmctop, PDID_T3X_NOC_DMC_TOP,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
	[PDID_T3X_DMC10] = POWER_DOMAIN(dmc27, PDID_T3X_DMC10,
			DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
};

static struct sec_pm_domain_data t3x_pm_domain_data = {
	.domains = t3x_pm_domains,
	.domains_count = ARRAY_SIZE(t3x_pm_domains),
};

static struct sec_pm_private_domain txhd2_pm_domains[] __initdata = {
	[PDID_VPU] = POWER_DOMAIN(vpu, PDID_VPU, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_DOS_HEVC, DOMAIN_INIT_OFF,
				       0),
	[PDID_DEMOD] = POWER_DOMAIN(demod, PDID_DEMOD, DOMAIN_INIT_ON,
					  0),
	[PDID_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_DOS_VDEC, DOMAIN_INIT_ON,
					  0),
};

static struct sec_pm_domain_data txhd2_pm_domain_data __initdata = {
	.domains = txhd2_pm_domains,
	.domains_count = ARRAY_SIZE(txhd2_pm_domains),
};

#endif

static struct sec_pm_private_domain s1a_pm_domains[] __initdata = {
	[PDID_S1A_DOS_HEVC] = POWER_DOMAIN(hevc, PDID_S1A_DOS_HEVC,
				DOMAIN_INIT_OFF, 0),
	[PDID_S1A_DOS_VDEC] = POWER_DOMAIN(vdec, PDID_S1A_DOS_VDEC, DOMAIN_INIT_OFF,
				       0),
	[PDID_S1A_VPU_HDMI] = POWER_DOMAIN(hdmi, PDID_S1A_VPU_HDMI, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_S1A_USB_COMB] = POWER_DOMAIN(usb_comb, PDID_S1A_USB_COMB, DOMAIN_INIT_ON,
					  GENPD_FLAG_ALWAYS_ON),
	[PDID_S1A_GE2D] = POWER_DOMAIN(ge2d, PDID_S1A_GE2D, DOMAIN_INIT_OFF,
					  0),
	[PDID_S1A_ETH] = POWER_DOMAIN(eth, PDID_S1A_ETH, DOMAIN_INIT_ON,
					GENPD_FLAG_ALWAYS_ON),
	[PDID_S1A_DEMOD] = POWER_DOMAIN(demod, PDID_S1A_DEMOD, DOMAIN_INIT_OFF,
				     0),
};

static struct sec_pm_domain_data s1a_pm_domain_data __initdata = {
	.domains = s1a_pm_domains,
	.domains_count = ARRAY_SIZE(s1a_pm_domains),
};

static int sec_pd_probe(struct platform_device *pdev)
{
	int ret, i;
	struct sec_pm_private_domain *private_pd, *pri_pd;
	struct sec_pm_domain *pd;
	int init_status;
	const struct sec_pm_domain_data *match;
	struct genpd_onecell_data *sec_pd_onecell_data;

	match = of_device_get_match_data(&pdev->dev);
	if (!match) {
		dev_err(&pdev->dev, "failed to get match data\n");
		return -ENODEV;
	}

	sec_pd_onecell_data = devm_kzalloc(&pdev->dev, sizeof(*sec_pd_onecell_data), GFP_KERNEL);
	if (!sec_pd_onecell_data)
		return -ENOMEM;

	sec_pd_onecell_data->domains = devm_kcalloc(&pdev->dev, match->domains_count,
						    sizeof(*sec_pd_onecell_data->domains),
						    GFP_KERNEL);
	if (!sec_pd_onecell_data->domains)
		return -ENOMEM;

	sec_pd_onecell_data->num_domains = match->domains_count;

	pd = devm_kcalloc(&pdev->dev, match->domains_count, sizeof(*pd), GFP_KERNEL);
	if (!pd)
		return -ENOMEM;
	pri_pd = devm_kcalloc(&pdev->dev, match->domains_count, sizeof(*private_pd), GFP_KERNEL);
	if (!pri_pd)
		return -ENOMEM;

	for (i = 0; i < match->domains_count; i++) {
		private_pd = &match->domains[i];
		/* array might be sparse */
		if (!private_pd->name)
			continue;

		pd[i].base.name = private_pd->name;
		pd[i].base.power_on = sec_pm_domain_power_on;
		pd[i].base.power_off = sec_pm_domain_power_off;
		pd[i].base.flags = private_pd->flags;
		pd[i].private_domain = &pri_pd[i];
		pri_pd[i].pd_index = private_pd->pd_index;
		pri_pd[i].pd_status = private_pd->pd_status;
		pri_pd[i].pd_parent = private_pd->pd_parent;

		init_status = pwr_ctrl_status_psci_smc(private_pd->pd_index);

		if (init_status == DOMAIN_INIT_OFF && private_pd->pd_status == DOMAIN_INIT_ON) {
			if (pd[i].base.flags == GENPD_FLAG_ALWAYS_ON)
				pwr_ctrl_psci_smc(i, PWR_ON);
		}

		if (init_status == -1 || pd[i].base.flags == GENPD_FLAG_ALWAYS_ON)
			init_status = private_pd->pd_status;

		/* Initialize based on pd_status */
		pm_genpd_init(&pd[i].base, NULL, init_status);
		sec_pd_onecell_data->domains[i] = &pd[i].base;
	}

	for (i = 0; i < match->domains_count; i++) {
		private_pd = &match->domains[i];

		if (!private_pd->pd_parent)
			continue;

		pm_genpd_add_subdomain(&pd[private_pd->pd_parent].base, &pd[i].base);
	}

	pd_dev_create_file(&pdev->dev, 0, sec_pd_onecell_data->num_domains,
			   sec_pd_onecell_data->domains);

	ret = of_genpd_add_provider_onecell(pdev->dev.of_node,
					    sec_pd_onecell_data);

	if (ret)
		goto out;

	return 0;

out:
	pd_dev_remove_file(&pdev->dev);
	return ret;
}

static const struct of_device_id pd_match_table[] = {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
	{
		.compatible = "amlogic,c1-power-domain",
		.data = &c1_pm_domain_data,
	},
#endif
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	{
		.compatible = "amlogic,c2-power-domain",
		.data = &c2_pm_domain_data,
	},
	{
		.compatible = "amlogic,sc2-power-domain",
		.data = &sc2_pm_domain_data,
	},
	{
		.compatible = "amlogic,t5-power-domain",
		.data = &t5_pm_domain_data,
	},
	{
		.compatible = "amlogic,t7-power-domain",
		.data = &t7_pm_domain_data,
	},
#endif
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT_C1A
	{
		.compatible = "amlogic,s4-power-domain",
		.data = &s4_pm_domain_data,
	},
#endif
#ifndef CONFIG_AMLOGIC_ZAPPER_CUT
	{
		.compatible = "amlogic,t3-power-domain",
		.data = &t3_pm_domain_data,
	},
	{
		.compatible = "amlogic,p1-power-domain",
		.data = &p1_pm_domain_data,
	},
	{
		.compatible = "amlogic,t5w-power-domain",
		.data = &t5w_pm_domain_data,
	},
	{
		.compatible = "amlogic,c3-power-domain",
		.data = &c3_pm_domain_data,
	},
	{
		.compatible = "amlogic,a1-power-domain",
		.data = &a1_pm_domain_data,
	},
	{
		.compatible = "amlogic,t5m-power-domain",
		.data = &t5m_pm_domain_data,
	},
	{
		.compatible = "amlogic,s5-power-domain",
		.data = &s5_pm_domain_data,
	},
	{
		.compatible = "amlogic,t3x-power-domain",
		.data = &t3x_pm_domain_data,
	},
	{
		.compatible = "amlogic,txhd2-power-domain",
		.data = &txhd2_pm_domain_data,
	},
#endif
	{
		.compatible = "amlogic,s1a-power-domain",
		.data = &s1a_pm_domain_data,
	},
	{}
};

static struct platform_driver sec_pd_driver = {
	.probe		= sec_pd_probe,
	.driver		= {
		.name	= "sec_pd",
		.of_match_table = pd_match_table,
	},
};

int __init sec_power_domain_init(void)
{
	return platform_driver_register(&sec_pd_driver);
}

void __exit sec_power_domain_exit(void)
{
	platform_driver_unregister(&sec_pd_driver);
}
