xref: /rk3399_ARM-atf/drivers/arm/tzc/tzc_dmc620.c (revision 9d3b191a4846e42070ca35b032db0501b910690b)
1*9d3b191aSVijayenthiran Subramaniam /*
2*9d3b191aSVijayenthiran Subramaniam  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3*9d3b191aSVijayenthiran Subramaniam  *
4*9d3b191aSVijayenthiran Subramaniam  * SPDX-License-Identifier: BSD-3-Clause
5*9d3b191aSVijayenthiran Subramaniam  */
6*9d3b191aSVijayenthiran Subramaniam 
7*9d3b191aSVijayenthiran Subramaniam #include <assert.h>
8*9d3b191aSVijayenthiran Subramaniam #include <debug.h>
9*9d3b191aSVijayenthiran Subramaniam #include <mmio.h>
10*9d3b191aSVijayenthiran Subramaniam #include <tzc_dmc620.h>
11*9d3b191aSVijayenthiran Subramaniam 
12*9d3b191aSVijayenthiran Subramaniam /* Mask to extract bit 31 to 16 */
13*9d3b191aSVijayenthiran Subramaniam #define MASK_31_16 UINT64_C(0x0000ffff0000)
14*9d3b191aSVijayenthiran Subramaniam /* Mask to extract bit 47 to 32 */
15*9d3b191aSVijayenthiran Subramaniam #define MASK_47_32 UINT64_C(0xffff00000000)
16*9d3b191aSVijayenthiran Subramaniam 
17*9d3b191aSVijayenthiran Subramaniam /* Helper macro for getting dmc_base addr of a dmc_inst */
18*9d3b191aSVijayenthiran Subramaniam #define DMC_BASE(plat_data, dmc_inst) \
19*9d3b191aSVijayenthiran Subramaniam 	((uintptr_t)(plat_data->dmc_base[dmc_inst]))
20*9d3b191aSVijayenthiran Subramaniam 
21*9d3b191aSVijayenthiran Subramaniam /* Pointer to the tzc_dmc620_config_data structure populated by the platform */
22*9d3b191aSVijayenthiran Subramaniam static const tzc_dmc620_config_data_t *g_plat_config_data;
23*9d3b191aSVijayenthiran Subramaniam 
24*9d3b191aSVijayenthiran Subramaniam #if ENABLE_ASSERTIONS
25*9d3b191aSVijayenthiran Subramaniam /*
26*9d3b191aSVijayenthiran Subramaniam  * Helper function to check if the DMC-620 instance is present at the
27*9d3b191aSVijayenthiran Subramaniam  * base address provided by the platform and also check if at least
28*9d3b191aSVijayenthiran Subramaniam  * one dmc instance is present.
29*9d3b191aSVijayenthiran Subramaniam  */
30*9d3b191aSVijayenthiran Subramaniam static void tzc_dmc620_validate_plat_driver_data(
31*9d3b191aSVijayenthiran Subramaniam 			const tzc_dmc620_driver_data_t *plat_driver_data)
32*9d3b191aSVijayenthiran Subramaniam {
33*9d3b191aSVijayenthiran Subramaniam 	uint8_t dmc_inst, dmc_count;
34*9d3b191aSVijayenthiran Subramaniam 	unsigned int dmc_id;
35*9d3b191aSVijayenthiran Subramaniam 	uintptr_t base;
36*9d3b191aSVijayenthiran Subramaniam 
37*9d3b191aSVijayenthiran Subramaniam 	assert(plat_driver_data != NULL);
38*9d3b191aSVijayenthiran Subramaniam 
39*9d3b191aSVijayenthiran Subramaniam 	dmc_count = plat_driver_data->dmc_count;
40*9d3b191aSVijayenthiran Subramaniam 	assert(dmc_count > 0U);
41*9d3b191aSVijayenthiran Subramaniam 
42*9d3b191aSVijayenthiran Subramaniam 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
43*9d3b191aSVijayenthiran Subramaniam 		base = DMC_BASE(plat_driver_data, dmc_inst);
44*9d3b191aSVijayenthiran Subramaniam 		dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0);
45*9d3b191aSVijayenthiran Subramaniam 		assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE);
46*9d3b191aSVijayenthiran Subramaniam 	}
47*9d3b191aSVijayenthiran Subramaniam }
48*9d3b191aSVijayenthiran Subramaniam #endif
49*9d3b191aSVijayenthiran Subramaniam 
50*9d3b191aSVijayenthiran Subramaniam /*
51*9d3b191aSVijayenthiran Subramaniam  * Program a region with region base and region top addresses of all
52*9d3b191aSVijayenthiran Subramaniam  * DMC-620 instances.
53*9d3b191aSVijayenthiran Subramaniam  */
54*9d3b191aSVijayenthiran Subramaniam static void tzc_dmc620_configure_region(int region_no,
55*9d3b191aSVijayenthiran Subramaniam 					unsigned long long region_base,
56*9d3b191aSVijayenthiran Subramaniam 					unsigned long long region_top,
57*9d3b191aSVijayenthiran Subramaniam 					unsigned int sec_attr)
58*9d3b191aSVijayenthiran Subramaniam {
59*9d3b191aSVijayenthiran Subramaniam 	uint32_t min_31_00, min_47_32;
60*9d3b191aSVijayenthiran Subramaniam 	uint32_t max_31_00, max_47_32;
61*9d3b191aSVijayenthiran Subramaniam 	uint8_t dmc_inst, dmc_count;
62*9d3b191aSVijayenthiran Subramaniam 	uintptr_t base;
63*9d3b191aSVijayenthiran Subramaniam 	const tzc_dmc620_driver_data_t *plat_driver_data;
64*9d3b191aSVijayenthiran Subramaniam 
65*9d3b191aSVijayenthiran Subramaniam 	plat_driver_data = g_plat_config_data->plat_drv_data;
66*9d3b191aSVijayenthiran Subramaniam 	assert(plat_driver_data != NULL);
67*9d3b191aSVijayenthiran Subramaniam 
68*9d3b191aSVijayenthiran Subramaniam 	/* Do range checks on regions. */
69*9d3b191aSVijayenthiran Subramaniam 	assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
70*9d3b191aSVijayenthiran Subramaniam 
71*9d3b191aSVijayenthiran Subramaniam 	/* region_base and (region_top + 1) must be 4KB aligned */
72*9d3b191aSVijayenthiran Subramaniam 	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
73*9d3b191aSVijayenthiran Subramaniam 
74*9d3b191aSVijayenthiran Subramaniam 	dmc_count = plat_driver_data->dmc_count;
75*9d3b191aSVijayenthiran Subramaniam 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
76*9d3b191aSVijayenthiran Subramaniam 		min_31_00 = (region_base & MASK_31_16) | sec_attr;
77*9d3b191aSVijayenthiran Subramaniam 		min_47_32 = (region_base & MASK_47_32)
78*9d3b191aSVijayenthiran Subramaniam 				>> DMC620_ACC_ADDR_WIDTH;
79*9d3b191aSVijayenthiran Subramaniam 		max_31_00 = (region_top  & MASK_31_16);
80*9d3b191aSVijayenthiran Subramaniam 		max_47_32 = (region_top  & MASK_47_32)
81*9d3b191aSVijayenthiran Subramaniam 				>> DMC620_ACC_ADDR_WIDTH;
82*9d3b191aSVijayenthiran Subramaniam 
83*9d3b191aSVijayenthiran Subramaniam 		/* Extract the base address of the DMC-620 instance */
84*9d3b191aSVijayenthiran Subramaniam 		base = DMC_BASE(plat_driver_data, dmc_inst);
85*9d3b191aSVijayenthiran Subramaniam 		/* Configure access address region registers */
86*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no),
87*9d3b191aSVijayenthiran Subramaniam 				min_31_00);
88*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no),
89*9d3b191aSVijayenthiran Subramaniam 				min_47_32);
90*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no),
91*9d3b191aSVijayenthiran Subramaniam 				max_31_00);
92*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no),
93*9d3b191aSVijayenthiran Subramaniam 				max_47_32);
94*9d3b191aSVijayenthiran Subramaniam 	}
95*9d3b191aSVijayenthiran Subramaniam }
96*9d3b191aSVijayenthiran Subramaniam 
97*9d3b191aSVijayenthiran Subramaniam /*
98*9d3b191aSVijayenthiran Subramaniam  * Set the action value for all the DMC-620 instances.
99*9d3b191aSVijayenthiran Subramaniam  */
100*9d3b191aSVijayenthiran Subramaniam static void tzc_dmc620_set_action(void)
101*9d3b191aSVijayenthiran Subramaniam {
102*9d3b191aSVijayenthiran Subramaniam 	uint8_t dmc_inst, dmc_count;
103*9d3b191aSVijayenthiran Subramaniam 	uintptr_t base;
104*9d3b191aSVijayenthiran Subramaniam 	const tzc_dmc620_driver_data_t *plat_driver_data;
105*9d3b191aSVijayenthiran Subramaniam 
106*9d3b191aSVijayenthiran Subramaniam 	plat_driver_data = g_plat_config_data->plat_drv_data;
107*9d3b191aSVijayenthiran Subramaniam 	dmc_count = plat_driver_data->dmc_count;
108*9d3b191aSVijayenthiran Subramaniam 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
109*9d3b191aSVijayenthiran Subramaniam 		/* Extract the base address of the DMC-620 instance */
110*9d3b191aSVijayenthiran Subramaniam 		base = DMC_BASE(plat_driver_data, dmc_inst);
111*9d3b191aSVijayenthiran Subramaniam 		/* Switch to READY */
112*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO);
113*9d3b191aSVijayenthiran Subramaniam 		mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE);
114*9d3b191aSVijayenthiran Subramaniam 	}
115*9d3b191aSVijayenthiran Subramaniam }
116*9d3b191aSVijayenthiran Subramaniam 
117*9d3b191aSVijayenthiran Subramaniam /*
118*9d3b191aSVijayenthiran Subramaniam  * Verify whether the DMC-620 configuration is complete by reading back
119*9d3b191aSVijayenthiran Subramaniam  * configuration registers and comparing it with the configured value. If
120*9d3b191aSVijayenthiran Subramaniam  * configuration is incomplete, loop till the configured value is reflected in
121*9d3b191aSVijayenthiran Subramaniam  * the register.
122*9d3b191aSVijayenthiran Subramaniam  */
123*9d3b191aSVijayenthiran Subramaniam static void tzc_dmc620_verify_complete(void)
124*9d3b191aSVijayenthiran Subramaniam {
125*9d3b191aSVijayenthiran Subramaniam 	uint8_t dmc_inst, dmc_count;
126*9d3b191aSVijayenthiran Subramaniam 	uintptr_t base;
127*9d3b191aSVijayenthiran Subramaniam 	const tzc_dmc620_driver_data_t *plat_driver_data;
128*9d3b191aSVijayenthiran Subramaniam 
129*9d3b191aSVijayenthiran Subramaniam 	plat_driver_data = g_plat_config_data->plat_drv_data;
130*9d3b191aSVijayenthiran Subramaniam 	dmc_count = plat_driver_data->dmc_count;
131*9d3b191aSVijayenthiran Subramaniam 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
132*9d3b191aSVijayenthiran Subramaniam 		/* Extract the base address of the DMC-620 instance */
133*9d3b191aSVijayenthiran Subramaniam 		base = DMC_BASE(plat_driver_data, dmc_inst);
134*9d3b191aSVijayenthiran Subramaniam 		while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
135*9d3b191aSVijayenthiran Subramaniam 				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
136*9d3b191aSVijayenthiran Subramaniam 			continue;
137*9d3b191aSVijayenthiran Subramaniam 	}
138*9d3b191aSVijayenthiran Subramaniam }
139*9d3b191aSVijayenthiran Subramaniam 
140*9d3b191aSVijayenthiran Subramaniam /*
141*9d3b191aSVijayenthiran Subramaniam  * Initialize the DMC-620 TrustZone Controller using the region configuration
142*9d3b191aSVijayenthiran Subramaniam  * supplied by the platform. The DMC620 controller should be enabled elsewhere
143*9d3b191aSVijayenthiran Subramaniam  * before invoking this function.
144*9d3b191aSVijayenthiran Subramaniam  */
145*9d3b191aSVijayenthiran Subramaniam void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
146*9d3b191aSVijayenthiran Subramaniam {
147*9d3b191aSVijayenthiran Subramaniam 	int i;
148*9d3b191aSVijayenthiran Subramaniam 
149*9d3b191aSVijayenthiran Subramaniam 	/* Check if valid pointer is passed */
150*9d3b191aSVijayenthiran Subramaniam 	assert(plat_config_data != NULL);
151*9d3b191aSVijayenthiran Subramaniam 
152*9d3b191aSVijayenthiran Subramaniam 	/*
153*9d3b191aSVijayenthiran Subramaniam 	 * Check if access address count passed by the platform is less than or
154*9d3b191aSVijayenthiran Subramaniam 	 * equal to DMC620's access address count
155*9d3b191aSVijayenthiran Subramaniam 	 */
156*9d3b191aSVijayenthiran Subramaniam 	assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT);
157*9d3b191aSVijayenthiran Subramaniam 
158*9d3b191aSVijayenthiran Subramaniam #if ENABLE_ASSERTIONS
159*9d3b191aSVijayenthiran Subramaniam 	/* Validates the information passed by platform */
160*9d3b191aSVijayenthiran Subramaniam 	tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data);
161*9d3b191aSVijayenthiran Subramaniam #endif
162*9d3b191aSVijayenthiran Subramaniam 
163*9d3b191aSVijayenthiran Subramaniam 	g_plat_config_data = plat_config_data;
164*9d3b191aSVijayenthiran Subramaniam 
165*9d3b191aSVijayenthiran Subramaniam 	INFO("Configuring DMC-620 TZC settings\n");
166*9d3b191aSVijayenthiran Subramaniam 	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
167*9d3b191aSVijayenthiran Subramaniam 		tzc_dmc620_configure_region(i,
168*9d3b191aSVijayenthiran Subramaniam 			g_plat_config_data->plat_acc_addr_data[i].region_base,
169*9d3b191aSVijayenthiran Subramaniam 			g_plat_config_data->plat_acc_addr_data[i].region_top,
170*9d3b191aSVijayenthiran Subramaniam 			g_plat_config_data->plat_acc_addr_data[i].sec_attr);
171*9d3b191aSVijayenthiran Subramaniam 
172*9d3b191aSVijayenthiran Subramaniam 	tzc_dmc620_set_action();
173*9d3b191aSVijayenthiran Subramaniam 	tzc_dmc620_verify_complete();
174*9d3b191aSVijayenthiran Subramaniam 	INFO("DMC-620 TZC setup completed\n");
175*9d3b191aSVijayenthiran Subramaniam }
176