xref: /rk3399_ARM-atf/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c (revision 34d483565078e28b5a31995d9030787b14ad3801)
1 /*
2  * Copyright (C) 2018 Marvell International Ltd.
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <platform_def.h>
9 
10 #include <common/bl_common.h>
11 #include <common/debug.h>
12 #include <drivers/marvell/ccu.h>
13 #include <drivers/marvell/mochi/ap_setup.h>
14 #include <drivers/marvell/mochi/cp110_setup.h>
15 #include <lib/mmio.h>
16 
17 #include <armada_common.h>
18 #include <marvell_plat_priv.h> /* timer functionality */
19 
20 #include "mss_scp_bootloader.h"
21 
22 /* MSS windows configuration */
23 #define MSS_AEBR(base)			(base + 0x160)
24 #define MSS_AIBR(base)			(base + 0x164)
25 #define MSS_AEBR_MASK			0xFFF
26 #define MSS_AIBR_MASK			0xFFF
27 
28 #define MSS_EXTERNAL_SPACE		0x50000000
29 #define MSS_EXTERNAL_ACCESS_BIT		28
30 #define MSS_EXTERNAL_ADDR_MASK		0xfffffff
31 #define MSS_INTERNAL_ACCESS_BIT		28
32 
33 #define MSS_AP_REGS_OFFSET		0x580000
34 #define MSS_CP_SRAM_OFFSET		0x220000
35 #define MSS_CP_REGS_OFFSET		0x280000
36 
37 struct addr_map_win ccu_mem_map[] = {
38 	{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
39 };
40 
41 /* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
42  * the access to cp0 and cp1 need to be provided. More precisely it is
43  * required to:
44  *  - get the information about device id which is stored in CP0 registers
45  *    (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
46  *  - get the access to cp which is needed for loading fw for cp0/cp1
47  *    coprocessors
48  * This function configures ccu windows accordingly.
49  *
50  * Note: there is no need to restore previous ccu configuration, since in next
51  * phase (BL31) the init_ccu will be called (via apn806_init/
52  * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
53  */
54 static int bl2_plat_mmap_init(void)
55 {
56 	int cfg_num, win_id, cfg_idx, cp;
57 
58 	cfg_num =  ARRAY_SIZE(ccu_mem_map);
59 
60 	/* CCU window-0 should not be counted - it's already used */
61 	if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
62 		ERROR("BL2: %s: trying to open too many windows\n", __func__);
63 		return -1;
64 	}
65 
66 	/* Enable required CCU windows
67 	 * Do not touch CCU window 0,
68 	 * it's used for the internal registers access
69 	 */
70 	for (cfg_idx = 0, win_id = 1;
71 	     (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
72 		/* Skip already enabled CCU windows */
73 		if (ccu_is_win_enabled(MVEBU_AP0, win_id))
74 			continue;
75 		/* Enable required CCU windows */
76 		ccu_win_check(&ccu_mem_map[cfg_idx]);
77 		ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
78 		cfg_idx++;
79 	}
80 
81 	/* Config address for each cp other than cp0 */
82 	for (cp = 1; cp < CP_COUNT; cp++)
83 		update_cp110_default_win(cp);
84 
85 	/* There is need to configure IO_WIN windows again to overwrite
86 	 * temporary configuration done during update_cp110_default_win
87 	 */
88 	init_io_win(MVEBU_AP0);
89 
90 	/* Open AMB bridge required for MG access */
91 	for (cp = 0; cp < CP_COUNT; cp++)
92 		cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
93 
94 	return 0;
95 }
96 
97 /*****************************************************************************
98  * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
99  * Return 0 on success, -1 otherwise.
100  *****************************************************************************
101  */
102 int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
103 {
104 	int ret;
105 
106 	INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
107 
108 	/* initialize time (for delay functionality) */
109 	plat_delay_timer_init();
110 
111 	ret = bl2_plat_mmap_init();
112 	if (ret != 0)
113 		return ret;
114 
115 	ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
116 		scp_bl2_image_info->image_size);
117 
118 	if (ret == 0)
119 		INFO("BL2: SCP_BL2 transferred to SCP\n");
120 	else
121 		ERROR("BL2: SCP_BL2 transfer failure\n");
122 
123 	return ret;
124 }
125 
126 uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
127 {
128 	return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
129 }
130 
131 uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
132 {
133 	if (is_secure()) {
134 		return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
135 	}
136 
137 	return 0; /* SRAM will not be used */
138 }
139 
140 uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
141 {
142 	return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
143 }
144 
145 uint32_t bl2_plat_get_cp_count(int ap_idx)
146 {
147 	uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
148 	/* A8040: two CPs.
149 	 * A7040: one CP.
150 	 */
151 	if (revision == MVEBU_80X0_DEV_ID ||
152 	    revision == MVEBU_80X0_CP115_DEV_ID)
153 		return 2;
154 	else if (revision == MVEBU_CN9130_DEV_ID)
155 		return CP_COUNT;
156 	else
157 		return 1;
158 }
159 
160 uint32_t bl2_plat_get_ap_count(void)
161 {
162 	/* A8040 and A7040 have only one AP */
163 	return 1;
164 }
165 
166 void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
167 {
168 	/* set AXI External and Internal Address Bus extension */
169 	mmio_write_32(MSS_AEBR(mss_regs),
170 		      ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
171 	mmio_write_32(MSS_AIBR(mss_regs),
172 		      ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
173 }
174