Contributors: 3
Author Tokens Token Proportion Commits Commit Proportion
Yao Zi 3836 86.34% 2 50.00%
Michal Wilczynski 495 11.14% 1 25.00%
Icenowy Zheng 112 2.52% 1 25.00%
Total 4443 4


// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
 * Author: Michal Wilczynski <m.wilczynski@samsung.com>
 */

#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/regmap.h>

#include <dt-bindings/reset/thead,th1520-reset.h>

 /* register offset in RSTGEN_R */
#define TH1520_BROM_RST_CFG		0x0
#define TH1520_C910_RST_CFG		0x4
#define TH1520_CHIP_DBG_RST_CFG		0xc
#define TH1520_AXI4_CPUSYS2_RST_CFG	0x10
#define TH1520_X2H_CPUSYS_RST_CFG	0x18
#define TH1520_AHB2_CPUSYS_RST_CFG	0x1c
#define TH1520_APB3_CPUSYS_RST_CFG	0x20
#define TH1520_MBOX0_RST_CFG		0x24
#define TH1520_MBOX1_RST_CFG		0x28
#define TH1520_MBOX2_RST_CFG		0x2c
#define TH1520_MBOX3_RST_CFG		0x30
#define TH1520_WDT0_RST_CFG		0x34
#define TH1520_WDT1_RST_CFG		0x38
#define TH1520_TIMER0_RST_CFG		0x3c
#define TH1520_TIMER1_RST_CFG		0x40
#define TH1520_PERISYS_AHB_RST_CFG	0x44
#define TH1520_PERISYS_APB1_RST_CFG	0x48
#define TH1520_PERISYS_APB2_RST_CFG	0x4c
#define TH1520_GMAC0_RST_CFG		0x68
#define TH1520_UART0_RST_CFG		0x70
#define TH1520_UART1_RST_CFG		0x74
#define TH1520_UART2_RST_CFG		0x78
#define TH1520_UART3_RST_CFG		0x7c
#define TH1520_UART4_RST_CFG		0x80
#define TH1520_UART5_RST_CFG		0x84
#define TH1520_QSPI0_RST_CFG		0x8c
#define TH1520_QSPI1_RST_CFG		0x90
#define TH1520_SPI_RST_CFG		0x94
#define TH1520_I2C0_RST_CFG		0x98
#define TH1520_I2C1_RST_CFG		0x9c
#define TH1520_I2C2_RST_CFG		0xa0
#define TH1520_I2C3_RST_CFG		0xa4
#define TH1520_I2C4_RST_CFG		0xa8
#define TH1520_I2C5_RST_CFG		0xac
#define TH1520_GPIO0_RST_CFG		0xb0
#define TH1520_GPIO1_RST_CFG		0xb4
#define TH1520_GPIO2_RST_CFG		0xb8
#define TH1520_PWM_RST_CFG		0xc0
#define TH1520_PADCTRL0_APSYS_RST_CFG	0xc4
#define TH1520_CPU2PERI_X2H_RST_CFG	0xcc
#define TH1520_CPU2AON_X2H_RST_CFG	0xe4
#define TH1520_AON2CPU_A2X_RST_CFG	0xfc
#define TH1520_NPUSYS_AXI_RST_CFG	0x128
#define TH1520_CPU2VP_X2P_RST_CFG	0x12c
#define TH1520_CPU2VI_X2H_RST_CFG	0x138
#define TH1520_BMU_C910_RST_CFG		0x148
#define TH1520_DMAC_CPUSYS_RST_CFG	0x14c
#define TH1520_SPINLOCK_RST_CFG		0x178
#define TH1520_CFG2TEE_X2H_RST_CFG	0x188
#define TH1520_DSMART_RST_CFG		0x18c
#define TH1520_GPIO3_RST_CFG		0x1a8
#define TH1520_I2S_RST_CFG		0x1ac
#define TH1520_IMG_NNA_RST_CFG		0x1b0
#define TH1520_PERI_APB3_RST_CFG	0x1dc
#define TH1520_VP_SUBSYS_RST_CFG	0x1ec
#define TH1520_PERISYS_APB4_RST_CFG	0x1f8
#define TH1520_GMAC1_RST_CFG		0x204
#define TH1520_GMAC_AXI_RST_CFG		0x208
#define TH1520_PADCTRL1_APSYS_RST_CFG	0x20c
#define TH1520_VOSYS_AXI_RST_CFG	0x210
#define TH1520_VOSYS_X2X_RST_CFG	0x214
#define TH1520_MISC2VP_X2X_RST_CFG	0x218
#define TH1520_SUBSYS_RST_CFG		0x220

 /* register offset in DSP_REGMAP */
#define TH1520_DSPSYS_RST_CFG		0x0

 /* register offset in MISCSYS_REGMAP */
#define TH1520_EMMC_RST_CFG		0x0
#define TH1520_MISCSYS_AXI_RST_CFG	0x8
#define TH1520_SDIO0_RST_CFG		0xc
#define TH1520_SDIO1_RST_CFG		0x10
#define TH1520_USB3_DRD_RST_CFG		0x14

 /* register offset in VISYS_REGMAP */
#define TH1520_VISYS_RST_CFG		0x0
#define TH1520_VISYS_2_RST_CFG		0x4

 /* register offset in VOSYS_REGMAP */
#define TH1520_GPU_RST_CFG		0x0
#define TH1520_GPU_RST_CFG_MASK		GENMASK(1, 0)
#define TH1520_DPU_RST_CFG		0x4
#define TH1520_DSI0_RST_CFG		0x8
#define TH1520_DSI1_RST_CFG		0xc
#define TH1520_HDMI_RST_CFG		0x14
#define TH1520_AXI4_VO_DW_AXI_RST_CFG	0x18
#define TH1520_X2H_X4_VOSYS_DW_RST_CFG	0x20

/* register values */
#define TH1520_GPU_SW_GPU_RST		BIT(0)
#define TH1520_GPU_SW_CLKGEN_RST	BIT(1)
#define TH1520_DPU_SW_DPU_HRST		BIT(0)
#define TH1520_DPU_SW_DPU_ARST		BIT(1)
#define TH1520_DPU_SW_DPU_CRST		BIT(2)
#define TH1520_DSI_SW_DSI_PRST		BIT(0)
#define TH1520_HDMI_SW_MAIN_RST		BIT(0)
#define TH1520_HDMI_SW_PRST		BIT(1)

 /* register offset in VPSYS_REGMAP */
#define TH1520_AXIBUS_RST_CFG		0x0
#define TH1520_FCE_RST_CFG		0x4
#define TH1520_G2D_RST_CFG		0x8
#define TH1520_VDEC_RST_CFG		0xc
#define TH1520_VENC_RST_CFG		0x10

struct th1520_reset_map {
	u32 bit;
	u32 reg;
};

struct th1520_reset_priv {
	struct reset_controller_dev rcdev;
	struct regmap *map;
	const struct th1520_reset_map *resets;
};

struct th1520_reset_data {
	const struct th1520_reset_map *resets;
	size_t num;
};

static const struct th1520_reset_map th1520_resets[] = {
	[TH1520_RESET_ID_GPU] = {
		.bit = TH1520_GPU_SW_GPU_RST,
		.reg = TH1520_GPU_RST_CFG,
	},
	[TH1520_RESET_ID_GPU_CLKGEN] = {
		.bit = TH1520_GPU_SW_CLKGEN_RST,
		.reg = TH1520_GPU_RST_CFG,
	},
	[TH1520_RESET_ID_DPU_AHB] = {
		.bit = TH1520_DPU_SW_DPU_HRST,
		.reg = TH1520_DPU_RST_CFG,
	},
	[TH1520_RESET_ID_DPU_AXI] = {
		.bit = TH1520_DPU_SW_DPU_ARST,
		.reg = TH1520_DPU_RST_CFG,
	},
	[TH1520_RESET_ID_DPU_CORE] = {
		.bit = TH1520_DPU_SW_DPU_CRST,
		.reg = TH1520_DPU_RST_CFG,
	},
	[TH1520_RESET_ID_DSI0_APB] = {
		.bit = TH1520_DSI_SW_DSI_PRST,
		.reg = TH1520_DSI0_RST_CFG,
	},
	[TH1520_RESET_ID_DSI1_APB] = {
		.bit = TH1520_DSI_SW_DSI_PRST,
		.reg = TH1520_DSI1_RST_CFG,
	},
	[TH1520_RESET_ID_HDMI] = {
		.bit = TH1520_HDMI_SW_MAIN_RST,
		.reg = TH1520_HDMI_RST_CFG,
	},
	[TH1520_RESET_ID_HDMI_APB] = {
		.bit = TH1520_HDMI_SW_PRST,
		.reg = TH1520_HDMI_RST_CFG,
	},
	[TH1520_RESET_ID_VOAXI] = {
		.bit = BIT(0),
		.reg = TH1520_AXI4_VO_DW_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_VOAXI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_AXI4_VO_DW_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_X2H_DPU_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_X2H_X4_VOSYS_DW_RST_CFG,
	},
	[TH1520_RESET_ID_X2H_DPU_AHB] = {
		.bit = BIT(1),
		.reg = TH1520_X2H_X4_VOSYS_DW_RST_CFG,
	},
	[TH1520_RESET_ID_X2H_DPU1_AXI] = {
		.bit = BIT(2),
		.reg = TH1520_X2H_X4_VOSYS_DW_RST_CFG,
	},
	[TH1520_RESET_ID_X2H_DPU1_AHB] = {
		.bit = BIT(3),
		.reg = TH1520_X2H_X4_VOSYS_DW_RST_CFG,
	},
};

static const struct th1520_reset_map th1520_ap_resets[] = {
	[TH1520_RESET_ID_BROM] = {
		.bit = BIT(0),
		.reg = TH1520_BROM_RST_CFG,
	},
	[TH1520_RESET_ID_C910_TOP] = {
		.bit = BIT(0),
		.reg = TH1520_C910_RST_CFG,
	},
	[TH1520_RESET_ID_NPU] =  {
		.bit = BIT(0),
		.reg = TH1520_IMG_NNA_RST_CFG,
	},
	[TH1520_RESET_ID_WDT0] = {
		.bit = BIT(0),
		.reg = TH1520_WDT0_RST_CFG,
	},
	[TH1520_RESET_ID_WDT1] = {
		.bit = BIT(0),
		.reg = TH1520_WDT1_RST_CFG,
	},
	[TH1520_RESET_ID_C910_C0] = {
		.bit = BIT(1),
		.reg = TH1520_C910_RST_CFG,
	},
	[TH1520_RESET_ID_C910_C1] = {
		.bit = BIT(2),
		.reg = TH1520_C910_RST_CFG,
	},
	[TH1520_RESET_ID_C910_C2] = {
		.bit = BIT(3),
		.reg = TH1520_C910_RST_CFG,
	},
	[TH1520_RESET_ID_C910_C3] = {
		.bit = BIT(4),
		.reg = TH1520_C910_RST_CFG,
	},
	[TH1520_RESET_ID_CHIP_DBG_CORE] = {
		.bit = BIT(0),
		.reg = TH1520_CHIP_DBG_RST_CFG,
	},
	[TH1520_RESET_ID_CHIP_DBG_AXI] = {
		.bit = BIT(1),
		.reg = TH1520_CHIP_DBG_RST_CFG,
	},
	[TH1520_RESET_ID_AXI4_CPUSYS2_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_AXI4_CPUSYS2_RST_CFG,
	},
	[TH1520_RESET_ID_AXI4_CPUSYS2_APB] = {
		.bit = BIT(1),
		.reg = TH1520_AXI4_CPUSYS2_RST_CFG,
	},
	[TH1520_RESET_ID_X2H_CPUSYS] = {
		.bit = BIT(0),
		.reg = TH1520_X2H_CPUSYS_RST_CFG,
	},
	[TH1520_RESET_ID_AHB2_CPUSYS] = {
		.bit = BIT(0),
		.reg = TH1520_AHB2_CPUSYS_RST_CFG,
	},
	[TH1520_RESET_ID_APB3_CPUSYS] = {
		.bit = BIT(0),
		.reg = TH1520_APB3_CPUSYS_RST_CFG,
	},
	[TH1520_RESET_ID_MBOX0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_MBOX0_RST_CFG,
	},
	[TH1520_RESET_ID_MBOX1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_MBOX1_RST_CFG,
	},
	[TH1520_RESET_ID_MBOX2_APB] = {
		.bit = BIT(0),
		.reg = TH1520_MBOX2_RST_CFG,
	},
	[TH1520_RESET_ID_MBOX3_APB] = {
		.bit = BIT(0),
		.reg = TH1520_MBOX3_RST_CFG,
	},
	[TH1520_RESET_ID_TIMER0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_TIMER0_RST_CFG,
	},
	[TH1520_RESET_ID_TIMER0_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_TIMER0_RST_CFG,
	},
	[TH1520_RESET_ID_TIMER1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_TIMER1_RST_CFG,
	},
	[TH1520_RESET_ID_TIMER1_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_TIMER1_RST_CFG,
	},
	[TH1520_RESET_ID_PERISYS_AHB] = {
		.bit = BIT(0),
		.reg = TH1520_PERISYS_AHB_RST_CFG,
	},
	[TH1520_RESET_ID_PERISYS_APB1] = {
		.bit = BIT(0),
		.reg = TH1520_PERISYS_APB1_RST_CFG,
	},
	[TH1520_RESET_ID_PERISYS_APB2] = {
		.bit = BIT(0),
		.reg = TH1520_PERISYS_APB2_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_GMAC0_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC0_AHB] = {
		.bit = BIT(1),
		.reg = TH1520_GMAC0_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC0_CLKGEN] = {
		.bit = BIT(2),
		.reg = TH1520_GMAC0_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC0_AXI] = {
		.bit = BIT(3),
		.reg = TH1520_GMAC0_RST_CFG,
	},
	[TH1520_RESET_ID_UART0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART0_RST_CFG,
	},
	[TH1520_RESET_ID_UART0_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART0_RST_CFG,
	},
	[TH1520_RESET_ID_UART1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART1_RST_CFG,
	},
	[TH1520_RESET_ID_UART1_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART1_RST_CFG,
	},
	[TH1520_RESET_ID_UART2_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART2_RST_CFG,
	},
	[TH1520_RESET_ID_UART2_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART2_RST_CFG,
	},
	[TH1520_RESET_ID_UART3_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART3_RST_CFG,
	},
	[TH1520_RESET_ID_UART3_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART3_RST_CFG,
	},
	[TH1520_RESET_ID_UART4_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART4_RST_CFG,
	},
	[TH1520_RESET_ID_UART4_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART4_RST_CFG,
	},
	[TH1520_RESET_ID_UART5_APB] = {
		.bit = BIT(0),
		.reg = TH1520_UART5_RST_CFG,
	},
	[TH1520_RESET_ID_UART5_IF] = {
		.bit = BIT(1),
		.reg = TH1520_UART5_RST_CFG,
	},
	[TH1520_RESET_ID_QSPI0_IF] = {
		.bit = BIT(0),
		.reg = TH1520_QSPI0_RST_CFG,
	},
	[TH1520_RESET_ID_QSPI0_APB] = {
		.bit = BIT(1),
		.reg = TH1520_QSPI0_RST_CFG,
	},
	[TH1520_RESET_ID_QSPI1_IF] = {
		.bit = BIT(0),
		.reg = TH1520_QSPI1_RST_CFG,
	},
	[TH1520_RESET_ID_QSPI1_APB] = {
		.bit = BIT(1),
		.reg = TH1520_QSPI1_RST_CFG,
	},
	[TH1520_RESET_ID_SPI_IF] = {
		.bit = BIT(0),
		.reg = TH1520_SPI_RST_CFG,
	},
	[TH1520_RESET_ID_SPI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_SPI_RST_CFG,
	},
	[TH1520_RESET_ID_I2C0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C0_RST_CFG,
	},
	[TH1520_RESET_ID_I2C0_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C0_RST_CFG,
	},
	[TH1520_RESET_ID_I2C1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C1_RST_CFG,
	},
	[TH1520_RESET_ID_I2C1_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C1_RST_CFG,
	},
	[TH1520_RESET_ID_I2C2_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C2_RST_CFG,
	},
	[TH1520_RESET_ID_I2C2_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C2_RST_CFG,
	},
	[TH1520_RESET_ID_I2C3_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C3_RST_CFG,
	},
	[TH1520_RESET_ID_I2C3_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C3_RST_CFG,
	},
	[TH1520_RESET_ID_I2C4_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C4_RST_CFG,
	},
	[TH1520_RESET_ID_I2C4_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C4_RST_CFG,
	},
	[TH1520_RESET_ID_I2C5_APB] = {
		.bit = BIT(0),
		.reg = TH1520_I2C5_RST_CFG,
	},
	[TH1520_RESET_ID_I2C5_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_I2C5_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO0_DB] = {
		.bit = BIT(0),
		.reg = TH1520_GPIO0_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO0_APB] = {
		.bit = BIT(1),
		.reg = TH1520_GPIO0_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO1_DB] = {
		.bit = BIT(0),
		.reg = TH1520_GPIO1_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO1_APB] = {
		.bit = BIT(1),
		.reg = TH1520_GPIO1_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO2_DB] = {
		.bit = BIT(0),
		.reg = TH1520_GPIO2_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO2_APB] = {
		.bit = BIT(1),
		.reg = TH1520_GPIO2_RST_CFG,
	},
	[TH1520_RESET_ID_PWM_COUNTER] = {
		.bit = BIT(0),
		.reg = TH1520_PWM_RST_CFG,
	},
	[TH1520_RESET_ID_PWM_APB] = {
		.bit = BIT(1),
		.reg = TH1520_PWM_RST_CFG,
	},
	[TH1520_RESET_ID_PADCTRL0_APB] = {
		.bit = BIT(0),
		.reg = TH1520_PADCTRL0_APSYS_RST_CFG,
	},
	[TH1520_RESET_ID_CPU2PERI_X2H] = {
		.bit = BIT(1),
		.reg = TH1520_CPU2PERI_X2H_RST_CFG,
	},
	[TH1520_RESET_ID_CPU2AON_X2H] = {
		.bit = BIT(0),
		.reg = TH1520_CPU2AON_X2H_RST_CFG,
	},
	[TH1520_RESET_ID_AON2CPU_A2X] = {
		.bit = BIT(0),
		.reg = TH1520_AON2CPU_A2X_RST_CFG,
	},
	[TH1520_RESET_ID_NPUSYS_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_NPUSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_NPUSYS_AXI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_NPUSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_CPU2VP_X2P] = {
		.bit = BIT(0),
		.reg = TH1520_CPU2VP_X2P_RST_CFG,
	},
	[TH1520_RESET_ID_CPU2VI_X2H] = {
		.bit = BIT(0),
		.reg = TH1520_CPU2VI_X2H_RST_CFG,
	},
	[TH1520_RESET_ID_BMU_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_BMU_C910_RST_CFG,
	},
	[TH1520_RESET_ID_BMU_APB] = {
		.bit = BIT(1),
		.reg = TH1520_BMU_C910_RST_CFG,
	},
	[TH1520_RESET_ID_DMAC_CPUSYS_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_DMAC_CPUSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DMAC_CPUSYS_AHB] = {
		.bit = BIT(1),
		.reg = TH1520_DMAC_CPUSYS_RST_CFG,
	},
	[TH1520_RESET_ID_SPINLOCK] = {
		.bit = BIT(0),
		.reg = TH1520_SPINLOCK_RST_CFG,
	},
	[TH1520_RESET_ID_CFG2TEE] = {
		.bit = BIT(0),
		.reg = TH1520_CFG2TEE_X2H_RST_CFG,
	},
	[TH1520_RESET_ID_DSMART] = {
		.bit = BIT(0),
		.reg = TH1520_DSMART_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO3_DB] = {
		.bit = BIT(0),
		.reg = TH1520_GPIO3_RST_CFG,
	},
	[TH1520_RESET_ID_GPIO3_APB] = {
		.bit = BIT(1),
		.reg = TH1520_GPIO3_RST_CFG,
	},
	[TH1520_RESET_ID_PERI_I2S] = {
		.bit = BIT(0),
		.reg = TH1520_I2S_RST_CFG,
	},
	[TH1520_RESET_ID_PERI_APB3] = {
		.bit = BIT(0),
		.reg = TH1520_PERI_APB3_RST_CFG,
	},
	[TH1520_RESET_ID_PERI2PERI1_APB] = {
		.bit = BIT(1),
		.reg = TH1520_PERI_APB3_RST_CFG,
	},
	[TH1520_RESET_ID_VPSYS_APB] = {
		.bit = BIT(0),
		.reg = TH1520_VP_SUBSYS_RST_CFG,
	},
	[TH1520_RESET_ID_PERISYS_APB4] = {
		.bit = BIT(0),
		.reg = TH1520_PERISYS_APB4_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_GMAC1_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC1_AHB] = {
		.bit = BIT(1),
		.reg = TH1520_GMAC1_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC1_CLKGEN] = {
		.bit = BIT(2),
		.reg = TH1520_GMAC1_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC1_AXI] = {
		.bit = BIT(3),
		.reg = TH1520_GMAC1_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_GMAC_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_GMAC_AXI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_GMAC_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_PADCTRL1_APB] = {
		.bit = BIT(0),
		.reg = TH1520_PADCTRL1_APSYS_RST_CFG,
	},
	[TH1520_RESET_ID_VOSYS_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_VOSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_VOSYS_AXI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_VOSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_VOSYS_AXI_X2X] = {
		.bit = BIT(0),
		.reg = TH1520_VOSYS_X2X_RST_CFG,
	},
	[TH1520_RESET_ID_MISC2VP_X2X] = {
		.bit = BIT(0),
		.reg = TH1520_MISC2VP_X2X_RST_CFG,
	},
	[TH1520_RESET_ID_DSPSYS] = {
		.bit = BIT(0),
		.reg = TH1520_SUBSYS_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS] = {
		.bit = BIT(1),
		.reg = TH1520_SUBSYS_RST_CFG,
	},
	[TH1520_RESET_ID_VOSYS] = {
		.bit = BIT(2),
		.reg = TH1520_SUBSYS_RST_CFG,
	},
	[TH1520_RESET_ID_VPSYS] = {
		.bit = BIT(3),
		.reg = TH1520_SUBSYS_RST_CFG,
	},
};

static const struct th1520_reset_map th1520_dsp_resets[] = {
	[TH1520_RESET_ID_X2X_DSP1] = {
		.bit = BIT(0),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_X2X_DSP0] = {
		.bit = BIT(1),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_X2X_SLAVE_DSP1] = {
		.bit = BIT(2),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_X2X_SLAVE_DSP0] = {
		.bit = BIT(3),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP0_CORE] = {
		.bit = BIT(8),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP0_DEBUG] = {
		.bit = BIT(9),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP0_APB] = {
		.bit = BIT(10),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP1_CORE] = {
		.bit = BIT(12),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP1_DEBUG] = {
		.bit = BIT(13),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSP1_APB] = {
		.bit = BIT(14),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_DSPSYS_APB] = {
		.bit = BIT(16),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_AXI4_DSPSYS_SLV] = {
		.bit = BIT(20),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_AXI4_DSPSYS] = {
		.bit = BIT(24),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
	[TH1520_RESET_ID_AXI4_DSP_RS] = {
		.bit = BIT(26),
		.reg = TH1520_DSPSYS_RST_CFG,
	},
};

static const struct th1520_reset_map th1520_misc_resets[] = {
	[TH1520_RESET_ID_EMMC_SDIO_CLKGEN] = {
		.bit = BIT(0),
		.reg = TH1520_EMMC_RST_CFG,
	},
	[TH1520_RESET_ID_EMMC] = {
		.bit = BIT(1),
		.reg = TH1520_EMMC_RST_CFG,
	},
	[TH1520_RESET_ID_MISCSYS_AXI] = {
		.bit = BIT(0),
		.reg = TH1520_MISCSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_MISCSYS_AXI_APB] = {
		.bit = BIT(1),
		.reg = TH1520_MISCSYS_AXI_RST_CFG,
	},
	[TH1520_RESET_ID_SDIO0] = {
		.bit = BIT(0),
		.reg = TH1520_SDIO0_RST_CFG,
	},
	[TH1520_RESET_ID_SDIO1] = {
		.bit = BIT(1),
		.reg = TH1520_SDIO1_RST_CFG,
	},
	[TH1520_RESET_ID_USB3_APB] = {
		.bit = BIT(0),
		.reg = TH1520_USB3_DRD_RST_CFG,
	},
	[TH1520_RESET_ID_USB3_PHY] = {
		.bit = BIT(1),
		.reg = TH1520_USB3_DRD_RST_CFG,
	},
	[TH1520_RESET_ID_USB3_VCC] = {
		.bit = BIT(2),
		.reg = TH1520_USB3_DRD_RST_CFG,
	},
};

static const struct th1520_reset_map th1520_vi_resets[] = {
	[TH1520_RESET_ID_ISP0] = {
		.bit = BIT(0),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_ISP1] = {
		.bit = BIT(4),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_CSI0_APB] = {
		.bit = BIT(16),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_CSI1_APB] = {
		.bit = BIT(17),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_CSI2_APB] = {
		.bit = BIT(18),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_MIPI_FIFO] = {
		.bit = BIT(20),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_ISP_VENC_APB] = {
		.bit = BIT(24),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_VIPRE_APB] = {
		.bit = BIT(28),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_VIPRE_AXI] = {
		.bit = BIT(29),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_DW200_APB] = {
		.bit = BIT(31),
		.reg = TH1520_VISYS_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS3_AXI] = {
		.bit = BIT(8),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS2_AXI] = {
		.bit = BIT(9),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS1_AXI] = {
		.bit = BIT(10),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS_AXI] = {
		.bit = BIT(12),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
	[TH1520_RESET_ID_VISYS_APB] = {
		.bit = BIT(16),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
	[TH1520_RESET_ID_ISP_VENC_AXI] = {
		.bit = BIT(20),
		.reg = TH1520_VISYS_2_RST_CFG,
	},
};

static const struct th1520_reset_map th1520_vp_resets[] = {
	[TH1520_RESET_ID_VPSYS_AXI_APB] = {
		.bit = BIT(0),
		.reg = TH1520_AXIBUS_RST_CFG,
	},
	[TH1520_RESET_ID_VPSYS_AXI] = {
		.bit = BIT(1),
		.reg = TH1520_AXIBUS_RST_CFG,
	},
	[TH1520_RESET_ID_FCE_APB] = {
		.bit = BIT(0),
		.reg = TH1520_FCE_RST_CFG,
	},
	[TH1520_RESET_ID_FCE_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_FCE_RST_CFG,
	},
	[TH1520_RESET_ID_FCE_X2X_MASTER] = {
		.bit = BIT(4),
		.reg = TH1520_FCE_RST_CFG,
	},
	[TH1520_RESET_ID_FCE_X2X_SLAVE] = {
		.bit = BIT(5),
		.reg = TH1520_FCE_RST_CFG,
	},
	[TH1520_RESET_ID_G2D_APB] = {
		.bit = BIT(0),
		.reg = TH1520_G2D_RST_CFG,
	},
	[TH1520_RESET_ID_G2D_ACLK] = {
		.bit = BIT(1),
		.reg = TH1520_G2D_RST_CFG,
	},
	[TH1520_RESET_ID_G2D_CORE] = {
		.bit = BIT(2),
		.reg = TH1520_G2D_RST_CFG,
	},
	[TH1520_RESET_ID_VDEC_APB] = {
		.bit = BIT(0),
		.reg = TH1520_VDEC_RST_CFG,
	},
	[TH1520_RESET_ID_VDEC_ACLK] = {
		.bit = BIT(1),
		.reg = TH1520_VDEC_RST_CFG,
	},
	[TH1520_RESET_ID_VDEC_CORE] = {
		.bit = BIT(2),
		.reg = TH1520_VDEC_RST_CFG,
	},
	[TH1520_RESET_ID_VENC_APB] = {
		.bit = BIT(0),
		.reg = TH1520_VENC_RST_CFG,
	},
	[TH1520_RESET_ID_VENC_CORE] = {
		.bit = BIT(1),
		.reg = TH1520_VENC_RST_CFG,
	},
};

static inline struct th1520_reset_priv *
to_th1520_reset(struct reset_controller_dev *rcdev)
{
	return container_of(rcdev, struct th1520_reset_priv, rcdev);
}

static int th1520_reset_assert(struct reset_controller_dev *rcdev,
			       unsigned long id)
{
	struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
	const struct th1520_reset_map *reset;

	reset = &priv->resets[id];

	return regmap_update_bits(priv->map, reset->reg, reset->bit, 0);
}

static int th1520_reset_deassert(struct reset_controller_dev *rcdev,
				 unsigned long id)
{
	struct th1520_reset_priv *priv = to_th1520_reset(rcdev);
	const struct th1520_reset_map *reset;

	reset = &priv->resets[id];

	return regmap_update_bits(priv->map, reset->reg, reset->bit,
				  reset->bit);
}

static const struct reset_control_ops th1520_reset_ops = {
	.assert	= th1520_reset_assert,
	.deassert = th1520_reset_deassert,
};

static const struct regmap_config th1520_reset_regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
};

static int th1520_reset_probe(struct platform_device *pdev)
{
	const struct th1520_reset_data *data;
	struct device *dev = &pdev->dev;
	struct th1520_reset_priv *priv;
	void __iomem *base;
	int ret;

	data = device_get_match_data(dev);

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	priv->map = devm_regmap_init_mmio(dev, base,
					  &th1520_reset_regmap_config);
	if (IS_ERR(priv->map))
		return PTR_ERR(priv->map);

	if (of_device_is_compatible(dev->of_node, "thead,th1520-reset")) {
		/* Initialize GPU resets to asserted state */
		ret = regmap_update_bits(priv->map, TH1520_GPU_RST_CFG,
					 TH1520_GPU_RST_CFG_MASK, 0);
		if (ret)
			return ret;
	}

	priv->rcdev.owner = THIS_MODULE;
	priv->rcdev.nr_resets = data->num;
	priv->rcdev.ops = &th1520_reset_ops;
	priv->rcdev.of_node = dev->of_node;

	priv->resets = data->resets;

	return devm_reset_controller_register(dev, &priv->rcdev);
}

static const struct th1520_reset_data th1520_reset_data = {
	.resets = th1520_resets,
	.num = ARRAY_SIZE(th1520_resets),
};

static const struct th1520_reset_data th1520_ap_reset_data = {
	.resets = th1520_ap_resets,
	.num = ARRAY_SIZE(th1520_ap_resets),
};

static const struct th1520_reset_data th1520_dsp_reset_data = {
	.resets = th1520_dsp_resets,
	.num = ARRAY_SIZE(th1520_dsp_resets),
};

static const struct th1520_reset_data th1520_misc_reset_data = {
	.resets = th1520_misc_resets,
	.num = ARRAY_SIZE(th1520_misc_resets),
};

static const struct th1520_reset_data th1520_vi_reset_data = {
	.resets = th1520_vi_resets,
	.num = ARRAY_SIZE(th1520_vi_resets),
};

static const struct th1520_reset_data th1520_vp_reset_data = {
	.resets = th1520_vp_resets,
	.num = ARRAY_SIZE(th1520_vp_resets),
};

static const struct of_device_id th1520_reset_match[] = {
	{ .compatible = "thead,th1520-reset", .data = &th1520_reset_data },
	{ .compatible = "thead,th1520-reset-ap", .data = &th1520_ap_reset_data },
	{ .compatible = "thead,th1520-reset-dsp", .data = &th1520_dsp_reset_data },
	{ .compatible = "thead,th1520-reset-misc", .data = &th1520_misc_reset_data },
	{ .compatible = "thead,th1520-reset-vi", .data = &th1520_vi_reset_data },
	{ .compatible = "thead,th1520-reset-vp", .data = &th1520_vp_reset_data },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, th1520_reset_match);

static struct platform_driver th1520_reset_driver = {
	.driver = {
		.name = "th1520-reset",
		.of_match_table = th1520_reset_match,
	},
	.probe = th1520_reset_probe,
};
module_platform_driver(th1520_reset_driver);

MODULE_AUTHOR("Michal Wilczynski <m.wilczynski@samsung.com>");
MODULE_DESCRIPTION("T-HEAD TH1520 SoC reset controller");
MODULE_LICENSE("GPL");