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