blob: 71fa2b86872959c150c6992051f8c0d408a9b35d [file] [log] [blame]
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +03001/*
2 * Copyright (C) 2018 Marvell International Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
6 */
7
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#include <platform_def.h>
9
10#include <common/bl_common.h>
11#include <common/debug.h>
12#include <drivers/marvell/ccu.h>
Ben Peled79473592019-03-26 19:06:24 +020013#include <drivers/marvell/mochi/ap_setup.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014#include <drivers/marvell/mochi/cp110_setup.h>
15#include <lib/mmio.h>
16
Konstantin Porotchkin91db2902018-07-29 13:30:51 +030017#include <armada_common.h>
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030018#include <marvell_plat_priv.h> /* timer functionality */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030019
20#include "mss_scp_bootloader.h"
21
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030022/* 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
Konstantin Porotchkin276fd8e2020-01-29 16:02:46 +020033#define MSS_AP_REGS_OFFSET 0x580000
34#define MSS_CP_SRAM_OFFSET 0x220000
35#define MSS_CP_REGS_OFFSET 0x280000
36
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030037struct 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 */
54static int bl2_plat_mmap_init(void)
55{
Ben Peled79473592019-03-26 19:06:24 +020056 int cfg_num, win_id, cfg_idx, cp;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030057
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 */
Konstantin Porotchkinac2cf922019-03-31 17:22:53 +030070 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;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030075 /* 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);
Konstantin Porotchkinac2cf922019-03-31 17:22:53 +030078 cfg_idx++;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030079 }
80
Ben Peled79473592019-03-26 19:06:24 +020081 /* 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);
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030089
Grzegorz Jaszczyk17e43dd2017-08-18 16:42:12 +020090 /* Open AMB bridge required for MG access */
Grzegorz Jaszczyk95ad87c2019-04-12 12:56:07 +020091 for (cp = 0; cp < CP_COUNT; cp++)
92 cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
Grzegorz Jaszczyk17e43dd2017-08-18 16:42:12 +020093
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030094 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 */
102int 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");
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300107
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
126uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
127{
Konstantin Porotchkin276fd8e2020-01-29 16:02:46 +0200128 return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
129}
130
131uintptr_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 */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300138}
139
140uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
141{
Konstantin Porotchkin276fd8e2020-01-29 16:02:46 +0200142 return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300143}
144
145uint32_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;
Ben Peled34861362019-03-27 16:26:02 +0200154 else if (revision == MVEBU_CN9130_DEV_ID)
155 return CP_COUNT;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300156 else
157 return 1;
158}
159
160uint32_t bl2_plat_get_ap_count(void)
161{
162 /* A8040 and A7040 have only one AP */
163 return 1;
164}
165
166void 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}