nxp: add dcfg driver

NXP SoC needs Device Configuration driver to
fetch the current SoC configuration.

Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com>
Change-Id: Ie17cca01a8eb9a6f5feebb093756f577692432bf
diff --git a/drivers/nxp/dcfg/dcfg.c b/drivers/nxp/dcfg/dcfg.c
new file mode 100644
index 0000000..2e813e7
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+#include "dcfg.h"
+#include <lib/mmio.h>
+#ifdef NXP_SFP_ENABLED
+#include <sfp.h>
+#endif
+
+static soc_info_t soc_info = {0};
+static devdisr5_info_t devdisr5_info = {0};
+static dcfg_init_info_t *dcfg_init_info;
+
+/* Read the PORSR1 register */
+uint32_t read_reg_porsr1(void)
+{
+	unsigned int *porsr1_addr = NULL;
+
+	if (dcfg_init_info->porsr1 != 0U) {
+		return dcfg_init_info->porsr1;
+	}
+
+	porsr1_addr = (void *)
+			(dcfg_init_info->g_nxp_dcfg_addr + DCFG_PORSR1_OFFSET);
+	dcfg_init_info->porsr1 = gur_in32(porsr1_addr);
+
+	return dcfg_init_info->porsr1;
+}
+
+
+const soc_info_t *get_soc_info(void)
+{
+	uint32_t reg;
+
+	if (soc_info.is_populated == true) {
+		return (const soc_info_t *) &soc_info;
+	}
+
+	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET);
+
+	soc_info.mfr_id = (reg & SVR_MFR_ID_MASK) >> SVR_MFR_ID_SHIFT;
+#if defined(CONFIG_CHASSIS_3_2)
+	soc_info.family = (reg & SVR_FAMILY_MASK) >> SVR_FAMILY_SHIFT;
+	soc_info.dev_id = (reg & SVR_DEV_ID_MASK) >> SVR_DEV_ID_SHIFT;
+#endif
+	/* zero means SEC enabled. */
+	soc_info.sec_enabled =
+		(((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false;
+
+	soc_info.personality = (reg & SVR_PERSONALITY_MASK)
+				>> SVR_PERSONALITY_SHIFT;
+	soc_info.maj_ver = (reg & SVR_MAJ_VER_MASK) >> SVR_MAJ_VER_SHIFT;
+	soc_info.min_ver = reg & SVR_MIN_VER_MASK;
+
+	soc_info.is_populated = true;
+	return (const soc_info_t *) &soc_info;
+}
+
+void dcfg_init(dcfg_init_info_t *dcfg_init_data)
+{
+	dcfg_init_info = dcfg_init_data;
+	read_reg_porsr1();
+	get_soc_info();
+}
+
+bool is_sec_enabled(void)
+{
+	return soc_info.sec_enabled;
+}
+
+const devdisr5_info_t *get_devdisr5_info(void)
+{
+	uint32_t reg;
+
+	if (devdisr5_info.is_populated == true)
+		return (const devdisr5_info_t *) &devdisr5_info;
+
+	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_DEVDISR5_OFFSET);
+
+#if defined(CONFIG_CHASSIS_3_2)
+	devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
+	devdisr5_info.ddrc2_present = (reg & DISR5_DDRC2_MASK) ? 0 : 1;
+	devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
+#elif defined(CONFIG_CHASSIS_2)
+	devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
+	devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
+#endif
+	devdisr5_info.is_populated = true;
+
+	return (const devdisr5_info_t *) &devdisr5_info;
+}
+
+int get_clocks(struct sysinfo *sys)
+{
+	unsigned int *rcwsr0 = NULL;
+	const unsigned long sysclk = dcfg_init_info->nxp_sysclk_freq;
+	const unsigned long ddrclk = dcfg_init_info->nxp_ddrclk_freq;
+
+	rcwsr0 = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR0_OFFSET);
+	sys->freq_platform = sysclk;
+	sys->freq_ddr_pll0 = ddrclk;
+	sys->freq_ddr_pll1 = ddrclk;
+
+	sys->freq_platform *= (gur_in32(rcwsr0) >>
+				RCWSR0_SYS_PLL_RAT_SHIFT) &
+				RCWSR0_SYS_PLL_RAT_MASK;
+
+	sys->freq_platform /= dcfg_init_info->nxp_plat_clk_divider;
+
+	sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >>
+				RCWSR0_MEM_PLL_RAT_SHIFT) &
+				RCWSR0_MEM_PLL_RAT_MASK;
+	sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >>
+				RCWSR0_MEM2_PLL_RAT_SHIFT) &
+				RCWSR0_MEM2_PLL_RAT_MASK;
+	if (sys->freq_platform == 0) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+#ifdef NXP_SFP_ENABLED
+/*******************************************************************************
+ * Returns true if secur eboot is enabled on board
+ * mode = 0  (development mode - sb_en = 1)
+ * mode = 1 (production mode - ITS = 1)
+ ******************************************************************************/
+bool check_boot_mode_secure(uint32_t *mode)
+{
+	uint32_t val = 0U;
+	uint32_t *rcwsr = NULL;
+	*mode = 0U;
+
+	if (sfp_check_its() == 1) {
+		/* ITS =1 , Production mode */
+		*mode = 1U;
+		return true;
+	}
+
+	rcwsr = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR_SB_EN_OFFSET);
+
+	val = (gur_in32(rcwsr) >> RCWSR_SBEN_SHIFT) &
+				RCWSR_SBEN_MASK;
+
+	if (val == RCWSR_SBEN_MASK) {
+		*mode = 0U;
+		return true;
+	}
+
+	return false;
+}
+#endif
+
+void error_handler(int error_code)
+{
+	 /* Dump error code in SCRATCH4 register */
+	INFO("Error in Fuse Provisioning: %x\n", error_code);
+	gur_out32((void *)
+		  (dcfg_init_info->g_nxp_dcfg_addr + DCFG_SCRATCH4_OFFSET),
+		  error_code);
+}
diff --git a/drivers/nxp/dcfg/dcfg.h b/drivers/nxp/dcfg/dcfg.h
new file mode 100644
index 0000000..161e295
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_H
+#define DCFG_H
+
+#include <endian.h>
+
+#if defined(CONFIG_CHASSIS_2)
+#include <dcfg_lsch2.h>
+#elif defined(CONFIG_CHASSIS_3_2)
+#include <dcfg_lsch3.h>
+#endif
+
+#ifdef NXP_GUR_BE
+#define gur_in32(a)		bswap32(mmio_read_32((uintptr_t)(a)))
+#define gur_out32(a, v)		mmio_write_32((uintptr_t)(a), bswap32(v))
+#elif defined(NXP_GUR_LE)
+#define gur_in32(a)		mmio_read_32((uintptr_t)(a))
+#define gur_out32(a, v)		mmio_write_32((uintptr_t)(a), v)
+#else
+#error Please define CCSR GUR register endianness
+#endif
+
+typedef struct {
+	bool is_populated;
+	uint8_t mfr_id;
+#if defined(CONFIG_CHASSIS_3_2)
+	uint8_t family;
+	uint8_t dev_id;
+#endif
+	uint8_t personality;
+	bool sec_enabled;
+	uint8_t maj_ver;
+	uint8_t min_ver;
+} soc_info_t;
+
+typedef struct {
+	bool is_populated;
+	uint8_t ocram_present;
+	uint8_t ddrc1_present;
+#if defined(CONFIG_CHASSIS_3_2)
+	uint8_t ddrc2_present;
+#endif
+} devdisr5_info_t;
+
+typedef struct {
+	uint32_t porsr1;
+	uintptr_t g_nxp_dcfg_addr;
+	unsigned long nxp_sysclk_freq;
+	unsigned long nxp_ddrclk_freq;
+	unsigned int nxp_plat_clk_divider;
+} dcfg_init_info_t;
+
+
+struct sysinfo {
+	unsigned long freq_platform;
+	unsigned long freq_ddr_pll0;
+	unsigned long freq_ddr_pll1;
+};
+
+int get_clocks(struct sysinfo *sys);
+
+/* Read the PORSR1 register */
+uint32_t read_reg_porsr1(void);
+
+/*******************************************************************************
+ * Returns true if secur eboot is enabled on board
+ * mode = 0  (development mode - sb_en = 1)
+ * mode = 1 (production mode - ITS = 1)
+ ******************************************************************************/
+bool check_boot_mode_secure(uint32_t *mode);
+
+const soc_info_t *get_soc_info();
+const devdisr5_info_t *get_devdisr5_info();
+
+void dcfg_init(dcfg_init_info_t *dcfg_init_data);
+bool is_sec_enabled(void);
+
+void error_handler(int error_code);
+#endif /*	DCFG_H	*/
diff --git a/drivers/nxp/dcfg/dcfg.mk b/drivers/nxp/dcfg/dcfg.mk
new file mode 100644
index 0000000..61d1850
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.mk
@@ -0,0 +1,28 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq (${ADD_DCFG},)
+
+ADD_DCFG		:= 1
+
+DCFG_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/dcfg
+
+PLAT_INCLUDES		+= -I$(DCFG_DRIVERS_PATH)
+
+DCFG_SOURCES		+= $(DCFG_DRIVERS_PATH)/dcfg.c
+
+ifeq (${BL_COMM_DCFG_NEEDED},yes)
+BL_COMMON_SOURCES	+= ${DCFG_SOURCES}
+else
+ifeq (${BL2_DCFG_NEEDED},yes)
+BL2_SOURCES		+= ${DCFG_SOURCES}
+endif
+ifeq (${BL31_DCFG_NEEDED},yes)
+BL31_SOURCES		+= ${DCFG_SOURCES}
+endif
+endif
+
+endif
diff --git a/drivers/nxp/dcfg/dcfg_lsch2.h b/drivers/nxp/dcfg/dcfg_lsch2.h
new file mode 100644
index 0000000..c021aa1
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg_lsch2.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_LSCH2_H
+#define DCFG_LSCH2_H
+
+/* dcfg block register offsets and bitfields */
+#define DCFG_PORSR1_OFFSET		0x00
+#define DCFG_DEVDISR1_OFFSET		0x070
+#define DCFG_DEVDISR4_OFFSET		0x07C
+#define DCFG_DEVDISR5_OFFSET		0x080
+#define DCFG_COREDISR_OFFSET		0x094
+#define RCWSR0_OFFSET			0x100
+#define RCWSR5_OFFSET			0x118
+#define DCFG_BOOTLOCPTRL_OFFSET		0x400
+#define DCFG_BOOTLOCPTRH_OFFSET		0x404
+#define DCFG_COREDISABLEDSR_OFFSET	0x990
+#define DCFG_SCRATCH4_OFFSET		0x20C
+#define DCFG_SVR_OFFSET			0x0A4
+#define DCFG_BRR_OFFSET			0x0E4
+
+#define DCFG_RSTCR_OFFSET		0x0B0
+#define RSTCR_RESET_REQ			0x2
+
+#define DCFG_RSTRQSR1_OFFSET		0x0C8
+#define DCFG_RSTRQMR1_OFFSET		0x0C0
+
+/* DCFG DCSR Macros */
+#define DCFG_DCSR_PORCR1_OFFSET		0x0
+
+#define SVR_MFR_ID_MASK			0xF0000000
+#define SVR_MFR_ID_SHIFT		28
+#define SVR_FAMILY_MASK			0xF000000
+#define SVR_FAMILY_SHIFT		24
+#define SVR_DEV_ID_MASK			0x3F0000
+#define SVR_DEV_ID_SHIFT		16
+#define SVR_PERSONALITY_MASK		0x3E00
+#define SVR_PERSONALITY_SHIFT		9
+#define SVR_SEC_MASK			0x100
+#define SVR_SEC_SHIFT			8
+#define SVR_MAJ_VER_MASK		0xF0
+#define SVR_MAJ_VER_SHIFT		4
+#define SVR_MIN_VER_MASK		0xF
+
+#define DISR5_DDRC1_MASK		0x1
+#define DISR5_OCRAM_MASK		0x40
+
+/* DCFG regsiters bit masks */
+#define RCWSR0_SYS_PLL_RAT_SHIFT	25
+#define RCWSR0_SYS_PLL_RAT_MASK		0x1f
+#define RCWSR0_MEM_PLL_RAT_SHIFT	16
+#define RCWSR0_MEM_PLL_RAT_MASK		0x3f
+#define RCWSR0_MEM2_PLL_RAT_SHIFT	18
+#define RCWSR0_MEM2_PLL_RAT_MASK	0x3f
+
+#define RCWSR_SB_EN_OFFSET		RCWSR5_OFFSET
+#define RCWSR_SBEN_MASK			0x1
+#define RCWSR_SBEN_SHIFT		21
+
+/* RCW SRC NAND */
+#define RCW_SRC_NAND_MASK		(0x100)
+#define RCW_SRC_NAND_VAL		(0x100)
+#define NAND_RESERVED_MASK		(0xFC)
+#define NAND_RESERVED_1			(0x0)
+#define NAND_RESERVED_2			(0x80)
+
+/* RCW SRC NOR */
+#define RCW_SRC_NOR_MASK		(0x1F0)
+#define NOR_8B_VAL			(0x10)
+#define NOR_16B_VAL			(0x20)
+#define SD_VAL				(0x40)
+#define QSPI_VAL1			(0x44)
+#define QSPI_VAL2			(0x45)
+
+#endif /*	DCFG_LSCH2_H	*/
diff --git a/drivers/nxp/dcfg/dcfg_lsch3.h b/drivers/nxp/dcfg/dcfg_lsch3.h
new file mode 100644
index 0000000..8144542
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg_lsch3.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_LSCH3_H
+#define DCFG_LSCH3_H
+
+/* dcfg block register offsets and bitfields */
+#define DCFG_PORSR1_OFFSET			0x00
+
+#define DCFG_DEVDISR1_OFFSET			0x70
+#define DCFG_DEVDISR1_SEC	(1 << 22)
+
+#define DCFG_DEVDISR2_OFFSET			0x74
+
+#define DCFG_DEVDISR3_OFFSET			0x78
+#define DCFG_DEVDISR3_QBMAIN	(1 << 12)
+
+#define DCFG_DEVDISR4_OFFSET			0x7C
+#define DCFG_DEVDISR4_SPI_QSPI	(1 << 4 | 1 << 5)
+
+#define DCFG_DEVDISR5_OFFSET			0x80
+#define DISR5_DDRC1_MASK	0x1
+#define DISR5_DDRC2_MASK	0x2
+#define DISR5_OCRAM_MASK	0x1000
+#define DEVDISR5_MASK_ALL_MEM	0x00001003
+#define DEVDISR5_MASK_DDR	0x00000003
+#define DEVDISR5_MASK_DBG	0x00000400
+
+#define DCFG_DEVDISR6_OFFSET			0x84
+//#define DEVDISR6_MASK             0x00000001
+
+#define DCFG_COREDISR_OFFSET			0x94
+
+#define DCFG_SVR_OFFSET				0x0A4
+#define SVR_MFR_ID_MASK		0xF0000000
+#define SVR_MFR_ID_SHIFT	28
+#define SVR_FAMILY_MASK		0xF000000
+#define SVR_FAMILY_SHIFT	24
+#define SVR_DEV_ID_MASK		0x3F0000
+#define SVR_DEV_ID_SHIFT	16
+#define SVR_PERSONALITY_MASK	0x3E00
+#define SVR_PERSONALITY_SHIFT	9
+#define SVR_SEC_MASK		0x100
+#define SVR_SEC_SHIFT		8
+#define SVR_MAJ_VER_MASK	0xF0
+#define SVR_MAJ_VER_SHIFT	4
+#define SVR_MIN_VER_MASK	0xF
+
+#define RCWSR0_OFFSET				0x100
+#define RCWSR0_SYS_PLL_RAT_SHIFT	2
+#define RCWSR0_SYS_PLL_RAT_MASK		0x1f
+#define RCWSR0_MEM_PLL_RAT_SHIFT	10
+#define RCWSR0_MEM_PLL_RAT_MASK		0x3f
+#define RCWSR0_MEM2_PLL_RAT_SHIFT	18
+#define RCWSR0_MEM2_PLL_RAT_MASK	0x3f
+
+#define RCWSR5_OFFSET				0x110
+#define RCWSR9_OFFSET				0x120
+#define RCWSR_SB_EN_OFFSET	RCWSR9_OFFSET
+#define RCWSR_SBEN_MASK		0x1
+#define RCWSR_SBEN_SHIFT	10
+
+#define RCW_SR27_OFFSET				0x168
+/* DCFG register to dump error code */
+#define DCFG_SCRATCH4_OFFSET			0x20C
+#define DCFG_SCRATCHRW5_OFFSET			0x210
+#define DCFG_SCRATCHRW6_OFFSET			0x214
+#define DCFG_SCRATCHRW7_OFFSET			0x218
+#define DCFG_BOOTLOCPTRL_OFFSET			0x400
+#define DCFG_BOOTLOCPTRH_OFFSET			0x404
+#define DCFG_COREDISABLEDSR_OFFSET		0x990
+
+#endif /*	DCFG_LSCH3_H	*/
diff --git a/drivers/nxp/dcfg/scfg.h b/drivers/nxp/dcfg/scfg.h
new file mode 100644
index 0000000..81df9a6
--- /dev/null
+++ b/drivers/nxp/dcfg/scfg.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SCFG_H
+#define SCFG_H
+
+#ifdef CONFIG_CHASSIS_2
+
+/* SCFG register offsets */
+#define SCFG_CORE0_SFT_RST_OFFSET	0x0130
+#define SCFG_SNPCNFGCR_OFFSET		0x01A4
+#define SCFG_CORESRENCR_OFFSET		0x0204
+#define SCFG_RVBAR0_0_OFFSET		0x0220
+#define SCFG_RVBAR0_1_OFFSET		0x0224
+#define SCFG_COREBCR_OFFSET		0x0680
+#define SCFG_RETREQCR_OFFSET		0x0424
+
+#define SCFG_COREPMCR_OFFSET		0x042C
+#define COREPMCR_WFIL2			0x1
+
+#define SCFG_GIC400_ADDR_ALIGN_OFFSET	0x0188
+#define SCFG_BOOTLOCPTRH_OFFSET		0x0600
+#define SCFG_BOOTLOCPTRL_OFFSET		0x0604
+#define SCFG_SCRATCHRW2_OFFSET		0x0608
+#define SCFG_SCRATCHRW3_OFFSET		0x060C
+
+/* SCFG bit fields */
+#define SCFG_SNPCNFGCR_SECRDSNP		0x80000000
+#define SCFG_SNPCNFGCR_SECWRSNP         0x40000000
+#endif /* CONFIG_CHASSIS_2 */
+
+#ifndef __ASSEMBLER__
+#include <endian.h>
+#include <lib/mmio.h>
+
+#ifdef NXP_SCFG_BE
+#define scfg_in32(a)		bswap32(mmio_read_32((uintptr_t)(a)))
+#define scfg_out32(a, v)	mmio_write_32((uintptr_t)(a), bswap32(v))
+#define scfg_setbits32(a, v)	mmio_setbits_32((uintptr_t)(a), v)
+#define scfg_clrbits32(a, v)	mmio_clrbits_32((uintptr_t)(a), v)
+#define scfg_clrsetbits32(a, clear, set)	\
+				mmio_clrsetbits_32((uintptr_t)(a), clear, set)
+#elif defined(NXP_GUR_LE)
+#define scfg_in32(a)		mmio_read_32((uintptr_t)(a))
+#define scfg_out32(a, v)	mmio_write_32((uintptr_t)(a), v)
+#define scfg_setbits32(a, v)	mmio_setbits_32((uintptr_t)(a), v)
+#define scfg_clrbits32(a, v)	mmio_clrbits_32((uintptr_t)(a), v)
+#define scfg_clrsetbits32(a, clear, set)	\
+				mmio_clrsetbits_32((uintptr_t)(a), clear, set)
+#else
+#error Please define CCSR SCFG register endianness
+#endif
+#endif	/*	__ASSEMBLER__	*/
+
+#endif	/* SCFG_H */