• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Aspeed Technology Inc.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 #include <arch.h>
9 #include <common/debug.h>
10 #include <common/desc_image_load.h>
11 #include <drivers/arm/gicv3.h>
12 #include <drivers/console.h>
13 #include <drivers/ti/uart/uart_16550.h>
14 #include <lib/mmio.h>
15 #include <lib/xlat_tables/xlat_tables_v2.h>
16 #include <plat/common/platform.h>
17 #include <platform_def.h>
18 
19 static console_t console;
20 
21 static entry_point_info_t bl32_ep_info;
22 static entry_point_info_t bl33_ep_info;
23 
24 static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
25 
plat_mpidr_to_core_pos(u_register_t mpidr)26 static unsigned int plat_mpidr_to_core_pos(u_register_t mpidr)
27 {
28 	/* to workaround the return type mismatch */
29 	return plat_core_pos_by_mpidr(mpidr);
30 }
31 
32 static const gicv3_driver_data_t plat_gic_data = {
33 	.gicd_base = GICD_BASE,
34 	.gicr_base = GICR_BASE,
35 	.rdistif_num = PLATFORM_CORE_COUNT,
36 	.rdistif_base_addrs = rdistif_base_addrs,
37 	.mpidr_to_core_pos = plat_mpidr_to_core_pos,
38 };
39 
40 static const mmap_region_t plat_mmap[] = {
41 	MAP_REGION_FLAT(GICD_BASE, GICD_SIZE,
42 			MT_DEVICE | MT_RW | MT_SECURE),
43 	MAP_REGION_FLAT(GICR_BASE, GICR_SIZE,
44 			MT_DEVICE | MT_RW | MT_SECURE),
45 	MAP_REGION_FLAT(UART_BASE, PAGE_SIZE,
46 			MT_DEVICE | MT_RW | MT_SECURE),
47 	MAP_REGION_FLAT(SCU_CPU_BASE, PAGE_SIZE,
48 			MT_DEVICE | MT_RW | MT_SECURE),
49 	{ 0 }
50 };
51 
bl31_early_platform_setup2(u_register_t arg0,u_register_t arg1,u_register_t arg2,u_register_t arg3)52 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
53 				u_register_t arg2, u_register_t arg3)
54 {
55 	console_16550_register(CONSOLE_UART_BASE, CONSOLE_UART_CLKIN_HZ,
56 			       CONSOLE_UART_BAUDRATE, &console);
57 
58 	console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
59 
60 	SET_PARAM_HEAD(&bl32_ep_info, PARAM_EP, VERSION_2, 0);
61 	bl32_ep_info.pc = BL32_BASE;
62 	SET_SECURITY_STATE(bl32_ep_info.h.attr, SECURE);
63 
64 	SET_PARAM_HEAD(&bl33_ep_info, PARAM_EP, VERSION_2, 0);
65 	bl33_ep_info.pc = mmio_read_64(SCU_CPU_SMP_EP0);
66 	bl33_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
67 	SET_SECURITY_STATE(bl33_ep_info.h.attr, NON_SECURE);
68 }
69 
bl31_plat_arch_setup(void)70 void bl31_plat_arch_setup(void)
71 {
72 	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
73 			BL_CODE_END - BL_CODE_BASE,
74 			MT_CODE | MT_SECURE);
75 
76 	mmap_add_region(BL_CODE_END, BL_CODE_END,
77 			BL_END - BL_CODE_END,
78 			MT_RW_DATA | MT_SECURE);
79 
80 #if USE_COHERENT_MEM
81 	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
82 			BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
83 			MT_DEVICE | MT_RW | MT_SECURE);
84 #endif
85 
86 	mmap_add_region(BL32_BASE, BL32_BASE, BL32_SIZE,
87 			MT_MEMORY | MT_RW);
88 
89 	mmap_add(plat_mmap);
90 
91 	init_xlat_tables();
92 
93 	enable_mmu_el3(0);
94 }
95 
bl31_platform_setup(void)96 void bl31_platform_setup(void)
97 {
98 	gicv3_driver_init(&plat_gic_data);
99 	gicv3_distif_init();
100 	gicv3_rdistif_init(plat_my_core_pos());
101 	gicv3_cpuif_enable(plat_my_core_pos());
102 }
103 
bl31_plat_get_next_image_ep_info(uint32_t type)104 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
105 {
106 	entry_point_info_t *ep_info;
107 
108 	ep_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
109 
110 	if (!ep_info->pc) {
111 		return NULL;
112 	}
113 
114 	return ep_info;
115 }
116 
117 /*
118  * Clock divider/multiplier configuration struct.
119  * For H-PLL and M-PLL the formula is
120  * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1)
121  * M - Numerator
122  * N - Denumerator
123  * P - Post Divider
124  * They have the same layout in their control register.
125  *
126  */
127 union plat_pll_reg {
128 	uint32_t w;
129 	struct {
130 		uint16_t m : 13;		/* bit[12:0]	*/
131 		uint8_t n : 6;			/* bit[18:13]	*/
132 		uint8_t p : 4;			/* bit[22:19]	*/
133 		uint8_t off : 1;		/* bit[23]	*/
134 		uint8_t bypass : 1;		/* bit[24]	*/
135 		uint8_t reset : 1;		/* bit[25]	*/
136 		uint8_t reserved : 6;		/* bit[31:26]	*/
137 	} b;
138 };
139 
plat_get_pll_rate(int pll_idx)140 static uint32_t plat_get_pll_rate(int pll_idx)
141 {
142 	union plat_pll_reg pll_reg;
143 	uint32_t mul = 1, div = 1;
144 	uint32_t rate = 0;
145 
146 	switch (pll_idx) {
147 	case PLAT_CLK_HPLL:
148 		pll_reg.w = mmio_read_32(SCU_CPU_HPLL);
149 		break;
150 	case PLAT_CLK_DPLL:
151 		pll_reg.w = mmio_read_32(SCU_CPU_DPLL);
152 		break;
153 	case PLAT_CLK_MPLL:
154 		pll_reg.w = mmio_read_32(SCU_CPU_MPLL);
155 		break;
156 	default:
157 		ERROR("%s: invalid PSP clock source (%d)\n", __func__, pll_idx);
158 		return -EINVAL;
159 	}
160 
161 	if (pll_idx == PLAT_CLK_HPLL && ((mmio_read_32(SCU_CPU_HW_STRAP1) & GENMASK(3, 2)) != 0U)) {
162 		switch ((mmio_read_32(SCU_CPU_HW_STRAP1) & GENMASK(3, 2)) >> 2) {
163 		case 1U:
164 			rate = 1900000000;
165 			break;
166 		case 2U:
167 			rate = 1800000000;
168 			break;
169 		case 3U:
170 			rate = 1700000000;
171 			break;
172 		default:
173 			rate = 2000000000;
174 			break;
175 		}
176 	} else {
177 		if (pll_reg.b.bypass == 0U) {
178 			if (pll_idx == PLAT_CLK_MPLL) {
179 				/* F = 25Mhz * [M / (n + 1)] / (p + 1) */
180 				mul = (pll_reg.b.m) / ((pll_reg.b.n + 1));
181 				div = (pll_reg.b.p + 1);
182 			} else {
183 				/* F = 25Mhz * [(M + 2) / 2 * (n + 1)] / (p + 1) */
184 				mul = (pll_reg.b.m + 1) / ((pll_reg.b.n + 1) * 2);
185 				div = (pll_reg.b.p + 1);
186 			}
187 		}
188 
189 		rate = ((CLKIN_25M * mul) / div);
190 	}
191 
192 	return rate;
193 }
194 
plat_get_syscnt_freq2(void)195 unsigned int plat_get_syscnt_freq2(void)
196 {
197 	if (mmio_read_32(SCU_CPU_HW_STRAP1) & BIT(4)) {
198 		return plat_get_pll_rate(PLAT_CLK_HPLL);
199 	} else {
200 		return plat_get_pll_rate(PLAT_CLK_MPLL);
201 	}
202 }
203