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