blob: 09b8446fa39c68d945146b5aad0cd0f5c70caa70 [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>
13#include <drivers/marvell/mochi/cp110_setup.h>
14#include <lib/mmio.h>
15
Konstantin Porotchkin91db2902018-07-29 13:30:51 +030016#include <armada_common.h>
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030017#include <marvell_plat_priv.h> /* timer functionality */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030018
19#include "mss_scp_bootloader.h"
20
21/* IO windows configuration */
22#define IOW_GCR_OFFSET (0x70)
23
24/* MSS windows configuration */
25#define MSS_AEBR(base) (base + 0x160)
26#define MSS_AIBR(base) (base + 0x164)
27#define MSS_AEBR_MASK 0xFFF
28#define MSS_AIBR_MASK 0xFFF
29
30#define MSS_EXTERNAL_SPACE 0x50000000
31#define MSS_EXTERNAL_ACCESS_BIT 28
32#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
33#define MSS_INTERNAL_ACCESS_BIT 28
34
35struct addr_map_win ccu_mem_map[] = {
36 {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
37};
38
39/* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
40 * the access to cp0 and cp1 need to be provided. More precisely it is
41 * required to:
42 * - get the information about device id which is stored in CP0 registers
43 * (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
44 * - get the access to cp which is needed for loading fw for cp0/cp1
45 * coprocessors
46 * This function configures ccu windows accordingly.
47 *
48 * Note: there is no need to restore previous ccu configuration, since in next
49 * phase (BL31) the init_ccu will be called (via apn806_init/
50 * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
51 */
52static int bl2_plat_mmap_init(void)
53{
54 int cfg_num, win_id, cfg_idx;
55
56 cfg_num = ARRAY_SIZE(ccu_mem_map);
57
58 /* CCU window-0 should not be counted - it's already used */
59 if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
60 ERROR("BL2: %s: trying to open too many windows\n", __func__);
61 return -1;
62 }
63
64 /* Enable required CCU windows
65 * Do not touch CCU window 0,
66 * it's used for the internal registers access
67 */
68 for (cfg_idx = 0, win_id = 1; cfg_idx < cfg_num; cfg_idx++, win_id++) {
69 /* Enable required CCU windows */
70 ccu_win_check(&ccu_mem_map[cfg_idx]);
71 ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
72 }
73
74 /* Set the default target id to PIDI */
75 mmio_write_32(MVEBU_IO_WIN_BASE(MVEBU_AP0) + IOW_GCR_OFFSET, PIDI_TID);
76
Grzegorz Jaszczyk17e43dd2017-08-18 16:42:12 +020077 /* Open AMB bridge required for MG access */
78 cp110_amb_init(MVEBU_CP_REGS_BASE(0));
79
80 if (CP_COUNT == 2)
81 cp110_amb_init(MVEBU_CP_REGS_BASE(1));
82
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030083 return 0;
84}
85
86/*****************************************************************************
87 * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
88 * Return 0 on success, -1 otherwise.
89 *****************************************************************************
90 */
91int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
92{
93 int ret;
94
95 INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030096
97 /* initialize time (for delay functionality) */
98 plat_delay_timer_init();
99
100 ret = bl2_plat_mmap_init();
101 if (ret != 0)
102 return ret;
103
104 ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
105 scp_bl2_image_info->image_size);
106
107 if (ret == 0)
108 INFO("BL2: SCP_BL2 transferred to SCP\n");
109 else
110 ERROR("BL2: SCP_BL2 transfer failure\n");
111
112 return ret;
113}
114
115uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
116{
117 return MVEBU_CP_REGS_BASE(cp_idx) + 0x280000;
118}
119
120uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
121{
122 return MVEBU_REGS_BASE + 0x580000;
123}
124
125uint32_t bl2_plat_get_cp_count(int ap_idx)
126{
127 uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
128 /* A8040: two CPs.
129 * A7040: one CP.
130 */
131 if (revision == MVEBU_80X0_DEV_ID ||
132 revision == MVEBU_80X0_CP115_DEV_ID)
133 return 2;
134 else
135 return 1;
136}
137
138uint32_t bl2_plat_get_ap_count(void)
139{
140 /* A8040 and A7040 have only one AP */
141 return 1;
142}
143
144void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
145{
146 /* set AXI External and Internal Address Bus extension */
147 mmio_write_32(MSS_AEBR(mss_regs),
148 ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
149 mmio_write_32(MSS_AIBR(mss_regs),
150 ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
151}