xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright 2020-2021 NXP
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  *
6*54fd6939SJiyong Park  */
7*54fd6939SJiyong Park 
8*54fd6939SJiyong Park #include <common/debug.h>
9*54fd6939SJiyong Park #include "dcfg.h"
10*54fd6939SJiyong Park #include <lib/mmio.h>
11*54fd6939SJiyong Park #ifdef NXP_SFP_ENABLED
12*54fd6939SJiyong Park #include <sfp.h>
13*54fd6939SJiyong Park #endif
14*54fd6939SJiyong Park 
15*54fd6939SJiyong Park static soc_info_t soc_info = {0};
16*54fd6939SJiyong Park static devdisr5_info_t devdisr5_info = {0};
17*54fd6939SJiyong Park static dcfg_init_info_t *dcfg_init_info;
18*54fd6939SJiyong Park 
19*54fd6939SJiyong Park /* Read the PORSR1 register */
read_reg_porsr1(void)20*54fd6939SJiyong Park uint32_t read_reg_porsr1(void)
21*54fd6939SJiyong Park {
22*54fd6939SJiyong Park 	unsigned int *porsr1_addr = NULL;
23*54fd6939SJiyong Park 
24*54fd6939SJiyong Park 	if (dcfg_init_info->porsr1 != 0U) {
25*54fd6939SJiyong Park 		return dcfg_init_info->porsr1;
26*54fd6939SJiyong Park 	}
27*54fd6939SJiyong Park 
28*54fd6939SJiyong Park 	porsr1_addr = (void *)
29*54fd6939SJiyong Park 			(dcfg_init_info->g_nxp_dcfg_addr + DCFG_PORSR1_OFFSET);
30*54fd6939SJiyong Park 	dcfg_init_info->porsr1 = gur_in32(porsr1_addr);
31*54fd6939SJiyong Park 
32*54fd6939SJiyong Park 	return dcfg_init_info->porsr1;
33*54fd6939SJiyong Park }
34*54fd6939SJiyong Park 
35*54fd6939SJiyong Park 
get_soc_info(void)36*54fd6939SJiyong Park const soc_info_t *get_soc_info(void)
37*54fd6939SJiyong Park {
38*54fd6939SJiyong Park 	uint32_t reg;
39*54fd6939SJiyong Park 
40*54fd6939SJiyong Park 	if (soc_info.is_populated == true) {
41*54fd6939SJiyong Park 		return (const soc_info_t *) &soc_info;
42*54fd6939SJiyong Park 	}
43*54fd6939SJiyong Park 
44*54fd6939SJiyong Park 	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET);
45*54fd6939SJiyong Park 
46*54fd6939SJiyong Park 	soc_info.svr_reg.val = reg;
47*54fd6939SJiyong Park 
48*54fd6939SJiyong Park 	/* zero means SEC enabled. */
49*54fd6939SJiyong Park 	soc_info.sec_enabled =
50*54fd6939SJiyong Park 		(((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false;
51*54fd6939SJiyong Park 
52*54fd6939SJiyong Park 	soc_info.is_populated = true;
53*54fd6939SJiyong Park 	return (const soc_info_t *) &soc_info;
54*54fd6939SJiyong Park }
55*54fd6939SJiyong Park 
dcfg_init(dcfg_init_info_t * dcfg_init_data)56*54fd6939SJiyong Park void dcfg_init(dcfg_init_info_t *dcfg_init_data)
57*54fd6939SJiyong Park {
58*54fd6939SJiyong Park 	dcfg_init_info = dcfg_init_data;
59*54fd6939SJiyong Park 	read_reg_porsr1();
60*54fd6939SJiyong Park 	get_soc_info();
61*54fd6939SJiyong Park }
62*54fd6939SJiyong Park 
is_sec_enabled(void)63*54fd6939SJiyong Park bool is_sec_enabled(void)
64*54fd6939SJiyong Park {
65*54fd6939SJiyong Park 	return soc_info.sec_enabled;
66*54fd6939SJiyong Park }
67*54fd6939SJiyong Park 
get_devdisr5_info(void)68*54fd6939SJiyong Park const devdisr5_info_t *get_devdisr5_info(void)
69*54fd6939SJiyong Park {
70*54fd6939SJiyong Park 	uint32_t reg;
71*54fd6939SJiyong Park 
72*54fd6939SJiyong Park 	if (devdisr5_info.is_populated == true)
73*54fd6939SJiyong Park 		return (const devdisr5_info_t *) &devdisr5_info;
74*54fd6939SJiyong Park 
75*54fd6939SJiyong Park 	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_DEVDISR5_OFFSET);
76*54fd6939SJiyong Park 
77*54fd6939SJiyong Park #if defined(CONFIG_CHASSIS_3_2)
78*54fd6939SJiyong Park 	devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
79*54fd6939SJiyong Park 	devdisr5_info.ddrc2_present = (reg & DISR5_DDRC2_MASK) ? 0 : 1;
80*54fd6939SJiyong Park 	devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
81*54fd6939SJiyong Park #elif defined(CONFIG_CHASSIS_2)
82*54fd6939SJiyong Park 	devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
83*54fd6939SJiyong Park 	devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
84*54fd6939SJiyong Park #endif
85*54fd6939SJiyong Park 	devdisr5_info.is_populated = true;
86*54fd6939SJiyong Park 
87*54fd6939SJiyong Park 	return (const devdisr5_info_t *) &devdisr5_info;
88*54fd6939SJiyong Park }
89*54fd6939SJiyong Park 
get_clocks(struct sysinfo * sys)90*54fd6939SJiyong Park int get_clocks(struct sysinfo *sys)
91*54fd6939SJiyong Park {
92*54fd6939SJiyong Park 	unsigned int *rcwsr0 = NULL;
93*54fd6939SJiyong Park 	const unsigned long sysclk = dcfg_init_info->nxp_sysclk_freq;
94*54fd6939SJiyong Park 	const unsigned long ddrclk = dcfg_init_info->nxp_ddrclk_freq;
95*54fd6939SJiyong Park 
96*54fd6939SJiyong Park 	rcwsr0 = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR0_OFFSET);
97*54fd6939SJiyong Park 	sys->freq_platform = sysclk;
98*54fd6939SJiyong Park 	sys->freq_ddr_pll0 = ddrclk;
99*54fd6939SJiyong Park 	sys->freq_ddr_pll1 = ddrclk;
100*54fd6939SJiyong Park 
101*54fd6939SJiyong Park 	sys->freq_platform *= (gur_in32(rcwsr0) >>
102*54fd6939SJiyong Park 				RCWSR0_SYS_PLL_RAT_SHIFT) &
103*54fd6939SJiyong Park 				RCWSR0_SYS_PLL_RAT_MASK;
104*54fd6939SJiyong Park 
105*54fd6939SJiyong Park 	sys->freq_platform /= dcfg_init_info->nxp_plat_clk_divider;
106*54fd6939SJiyong Park 
107*54fd6939SJiyong Park 	sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >>
108*54fd6939SJiyong Park 				RCWSR0_MEM_PLL_RAT_SHIFT) &
109*54fd6939SJiyong Park 				RCWSR0_MEM_PLL_RAT_MASK;
110*54fd6939SJiyong Park 	sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >>
111*54fd6939SJiyong Park 				RCWSR0_MEM2_PLL_RAT_SHIFT) &
112*54fd6939SJiyong Park 				RCWSR0_MEM2_PLL_RAT_MASK;
113*54fd6939SJiyong Park 	if (sys->freq_platform == 0) {
114*54fd6939SJiyong Park 		return 1;
115*54fd6939SJiyong Park 	} else {
116*54fd6939SJiyong Park 		return 0;
117*54fd6939SJiyong Park 	}
118*54fd6939SJiyong Park }
119*54fd6939SJiyong Park 
120*54fd6939SJiyong Park #ifdef NXP_SFP_ENABLED
121*54fd6939SJiyong Park /*******************************************************************************
122*54fd6939SJiyong Park  * Returns true if secur eboot is enabled on board
123*54fd6939SJiyong Park  * mode = 0  (development mode - sb_en = 1)
124*54fd6939SJiyong Park  * mode = 1 (production mode - ITS = 1)
125*54fd6939SJiyong Park  ******************************************************************************/
check_boot_mode_secure(uint32_t * mode)126*54fd6939SJiyong Park bool check_boot_mode_secure(uint32_t *mode)
127*54fd6939SJiyong Park {
128*54fd6939SJiyong Park 	uint32_t val = 0U;
129*54fd6939SJiyong Park 	uint32_t *rcwsr = NULL;
130*54fd6939SJiyong Park 	*mode = 0U;
131*54fd6939SJiyong Park 
132*54fd6939SJiyong Park 	if (sfp_check_its() == 1) {
133*54fd6939SJiyong Park 		/* ITS =1 , Production mode */
134*54fd6939SJiyong Park 		*mode = 1U;
135*54fd6939SJiyong Park 		return true;
136*54fd6939SJiyong Park 	}
137*54fd6939SJiyong Park 
138*54fd6939SJiyong Park 	rcwsr = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR_SB_EN_OFFSET);
139*54fd6939SJiyong Park 
140*54fd6939SJiyong Park 	val = (gur_in32(rcwsr) >> RCWSR_SBEN_SHIFT) &
141*54fd6939SJiyong Park 				RCWSR_SBEN_MASK;
142*54fd6939SJiyong Park 
143*54fd6939SJiyong Park 	if (val == RCWSR_SBEN_MASK) {
144*54fd6939SJiyong Park 		*mode = 0U;
145*54fd6939SJiyong Park 		return true;
146*54fd6939SJiyong Park 	}
147*54fd6939SJiyong Park 
148*54fd6939SJiyong Park 	return false;
149*54fd6939SJiyong Park }
150*54fd6939SJiyong Park #endif
151*54fd6939SJiyong Park 
error_handler(int error_code)152*54fd6939SJiyong Park void error_handler(int error_code)
153*54fd6939SJiyong Park {
154*54fd6939SJiyong Park 	 /* Dump error code in SCRATCH4 register */
155*54fd6939SJiyong Park 	INFO("Error in Fuse Provisioning: %x\n", error_code);
156*54fd6939SJiyong Park 	gur_out32((void *)
157*54fd6939SJiyong Park 		  (dcfg_init_info->g_nxp_dcfg_addr + DCFG_SCRATCH4_OFFSET),
158*54fd6939SJiyong Park 		  error_code);
159*54fd6939SJiyong Park }
160