1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "juno_ppu_idx.h"
9 #include "juno_utils.h"
10 #include "juno_wdog_rom.h"
11 #include "scp_config.h"
12
13 #include <mod_juno_ppu.h>
14 #include <mod_power_domain.h>
15
16 #include <fwk_assert.h>
17 #include <fwk_id.h>
18 #include <fwk_interrupt.h>
19 #include <fwk_module_idx.h>
20 #include <fwk_status.h>
21
22 #include <fmw_cmsis.h>
23
24 #include <stdbool.h>
25 #include <stdint.h>
26
27 /* Platform default dividers for debug clocks */
28 #define JUNO_DEBUG_ROM_DIVIDER_ATCLK 16
29 #define JUNO_DEBUG_ROM_DIVIDER_TRACECLK 16
30 #define JUNO_DEBUG_ROM_DIVIDER_PCLK 16
31
32 const struct mod_juno_ppu_rom_api *ppu_api;
33
34 static const fwk_id_t dbgsys_ppu_id =
35 FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PPU, JUNO_PPU_DEV_IDX_DBGSYS);
36
37 static const fwk_id_t big_sstop_ppu_id =
38 FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PPU, JUNO_PPU_DEV_IDX_BIG_SSTOP);
39
40 static const fwk_id_t little_sstop_ppu_id =
41 FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_JUNO_PPU, JUNO_PPU_DEV_IDX_LITTLE_SSTOP);
42
43 static const uint32_t debug_clk_mask = (SCP_CONFIG_CLOCK_ENABLE_PCLKDBGEN |
44 SCP_CONFIG_CLOCK_ENABLE_TRACECLKINEN |
45 SCP_CONFIG_CLOCK_ENABLE_ATCLKEN);
46
47 /*
48 * Static helpers
49 */
50
juno_debug_rom_set_clocks(void)51 static void juno_debug_rom_set_clocks(void)
52 {
53 /*
54 * Setup ATCLK
55 */
56 juno_utils_atclk_clock_div_set(JUNO_DEBUG_ROM_DIVIDER_ATCLK);
57 while (
58 !juno_utils_atclk_clock_div_set_check(JUNO_DEBUG_ROM_DIVIDER_ATCLK)) {
59 continue;
60 }
61
62 juno_utils_atclk_clock_sel_set(SCP_CONFIG_STDCLK_CONTROL_CLKSEL_SYSINCLK);
63 while (!juno_utils_atclk_clock_sel_set_check(
64 SCP_CONFIG_STDCLK_CONTROL_CLKSEL_SYSINCLK)) {
65 continue;
66 }
67
68 /*
69 * Setup TRACECLKIN
70 */
71 juno_utils_traceclk_clock_div_set(JUNO_DEBUG_ROM_DIVIDER_TRACECLK);
72 while (!juno_utils_traceclk_clock_div_set_check(
73 JUNO_DEBUG_ROM_DIVIDER_TRACECLK)) {
74 continue;
75 }
76
77 juno_utils_traceclk_clock_sel_set(
78 SCP_CONFIG_STDCLK_CONTROL_CLKSEL_SYSINCLK);
79 while (!juno_utils_traceclk_clock_sel_set_check(
80 SCP_CONFIG_STDCLK_CONTROL_CLKSEL_SYSINCLK)) {
81 continue;
82 }
83
84 /*
85 * Setup PCLKDBG
86 */
87 juno_utils_pclkdbg_clock_div_set(JUNO_DEBUG_ROM_DIVIDER_PCLK);
88 while (
89 !juno_utils_pclkdbg_clock_div_set_check(JUNO_DEBUG_ROM_DIVIDER_PCLK)) {
90 continue;
91 }
92 }
93
94 /*
95 * Interrupt service routines
96 */
97
juno_debug_cdbg_pwr_up_req_isr(void)98 static void juno_debug_cdbg_pwr_up_req_isr(void)
99 {
100 int status;
101
102 #ifndef BUILD_MODE_DEBUG
103 juno_wdog_rom_reload();
104 #endif
105
106 if (SCP_CONFIG->DEBUG_STATUS & SCP_CONFIG_DEBUG_STATUS_CDBGPWRUPREQ) {
107 #ifndef BUILD_MODE_DEBUG
108 juno_wdog_rom_halt_on_debug_enable(true);
109 #endif
110
111 juno_utils_system_clock_enable(debug_clk_mask);
112
113 /* Turn on DBGSYS */
114 status = ppu_api->set_state_and_wait(dbgsys_ppu_id, MOD_PD_STATE_ON);
115 fwk_assert(status == FWK_SUCCESS);
116
117 status = ppu_api->set_state_and_wait(big_sstop_ppu_id, MOD_PD_STATE_ON);
118 fwk_assert(status == FWK_SUCCESS);
119
120 status =
121 ppu_api->set_state_and_wait(little_sstop_ppu_id, MOD_PD_STATE_ON);
122 fwk_assert(status == FWK_SUCCESS);
123
124 juno_debug_rom_set_clocks();
125
126 SCP_CONFIG->SYS_MANUAL_RESET.SET =
127 SCP_CONFIG_SYS_MANUAL_RESET_DBGSYSRESET;
128 SCP_CONFIG->SYS_MANUAL_RESET.CLEAR =
129 SCP_CONFIG_SYS_MANUAL_RESET_DBGSYSRESET;
130
131 /* Acknowledge end of debug power up */
132 SCP_CONFIG->DEBUG_CONTROL |= SCP_CONFIG_DEBUG_CONTROL_CDBGPWRUPACK;
133
134 } else {
135 status = ppu_api->set_state_and_wait(dbgsys_ppu_id, MOD_PD_STATE_OFF);
136 fwk_assert(status == FWK_SUCCESS);
137
138 SCP_CONFIG->DEBUG_CONTROL &= ~SCP_CONFIG_DEBUG_CONTROL_CDBGPWRUPACK;
139
140 #ifndef BUILD_MODE_DEBUG
141 juno_wdog_rom_halt_on_debug_enable(false);
142 #endif
143 }
144 }
145
juno_debug_csys_pwr_up_req_isr(void)146 static void juno_debug_csys_pwr_up_req_isr(void)
147 {
148 int status;
149
150 #ifndef BUILD_MODE_DEBUG
151 juno_wdog_rom_reload();
152 #endif
153
154 if (SCP_CONFIG->DEBUG_STATUS & SCP_CONFIG_DEBUG_STATUS_CSYSPWRUPREQ) {
155 juno_utils_system_clock_enable(debug_clk_mask);
156
157 status = ppu_api->set_state_and_wait(dbgsys_ppu_id, MOD_PD_STATE_ON);
158 fwk_assert(status == FWK_SUCCESS);
159
160 juno_debug_rom_set_clocks();
161
162 SCP_CONFIG->DEBUG_CONTROL |= SCP_CONFIG_DEBUG_CONTROL_CSYSPWRUPACK;
163 } else {
164 status = ppu_api->set_state_and_wait(dbgsys_ppu_id, MOD_PD_STATE_OFF);
165 fwk_assert(status == FWK_SUCCESS);
166
167 SCP_CONFIG->DEBUG_CONTROL &= ~SCP_CONFIG_DEBUG_CONTROL_CSYSPWRUPACK;
168 }
169 }
170
juno_debug_cdbg_rst_req_isr(void)171 static void juno_debug_cdbg_rst_req_isr(void)
172 {
173 #ifndef BUILD_MODE_DEBUG
174 juno_wdog_rom_reload();
175 #endif
176
177 /* Reset debug system */
178 SCP_CONFIG->SYS_MANUAL_RESET.SET = SCP_CONFIG_SYS_MANUAL_RESET_DBGSYSRESET;
179
180 /* Acknowledge request */
181 SCP_CONFIG->DEBUG_CONTROL |= SCP_CONFIG_DEBUG_CONTROL_CDBGRSTACK;
182
183 /* Wait for CoreSight to de-assert request */
184 while ((SCP_CONFIG->DEBUG_STATUS & SCP_CONFIG_DEBUG_STATUS_CDBGRSTREQ) ==
185 SCP_CONFIG_DEBUG_STATUS_CDBGRSTREQ) {
186 continue;
187 }
188
189 /* De-assert reset */
190 SCP_CONFIG->SYS_MANUAL_RESET.SET = SCP_CONFIG_SYS_MANUAL_RESET_DBGSYSRESET;
191
192 /* De-assert ACK */
193 SCP_CONFIG->DEBUG_CONTROL &= ~SCP_CONFIG_DEBUG_CONTROL_CDBGRSTACK;
194 }
195
196 /*
197 * Public interface
198 */
199
juno_debug_rom_init(const struct mod_juno_ppu_rom_api * rom_ppu_api)200 int juno_debug_rom_init(const struct mod_juno_ppu_rom_api *rom_ppu_api)
201 {
202 int status;
203 ppu_api = rom_ppu_api;
204
205 /*
206 * IRQs are not yet enabled but there may be a pending debug power-up
207 * request that was raised before SCP was released from reset
208 */
209 if (SCP_CONFIG->DEBUG_STATUS & SCP_CONFIG_DEBUG_STATUS_CDBGPWRUPREQ) {
210 juno_debug_cdbg_pwr_up_req_isr();
211
212 fwk_assert((SCP_CONFIG->DEBUG_CONTROL &
213 SCP_CONFIG_DEBUG_CONTROL_CDBGPWRUPACK) != 0);
214 }
215
216 status = fwk_interrupt_clear_pending((unsigned int)CDBG_PWR_UP_REQ_IRQ);
217 if (status != FWK_SUCCESS) {
218 return status;
219 }
220
221 status = fwk_interrupt_clear_pending((unsigned int)CDBG_RST_REQ_IRQ);
222 if (status != FWK_SUCCESS) {
223 return status;
224 }
225
226 status = fwk_interrupt_clear_pending((unsigned int)CSYS_PWR_UP_REQ_IRQ);
227 if (status != FWK_SUCCESS) {
228 return status;
229 }
230
231 status = fwk_interrupt_set_isr(
232 (unsigned int)CDBG_PWR_UP_REQ_IRQ, juno_debug_cdbg_pwr_up_req_isr);
233 if (status != FWK_SUCCESS) {
234 return status;
235 }
236
237 status = fwk_interrupt_set_isr(
238 (unsigned int)CSYS_PWR_UP_REQ_IRQ, juno_debug_csys_pwr_up_req_isr);
239 if (status != FWK_SUCCESS) {
240 return status;
241 }
242
243 status = fwk_interrupt_set_isr(
244 (unsigned int)CDBG_RST_REQ_IRQ, juno_debug_cdbg_rst_req_isr);
245 if (status != FWK_SUCCESS) {
246 return status;
247 }
248
249 status = fwk_interrupt_enable((unsigned int)CDBG_PWR_UP_REQ_IRQ);
250 if (status != FWK_SUCCESS) {
251 return status;
252 }
253
254 status = fwk_interrupt_enable((unsigned int)CDBG_RST_REQ_IRQ);
255 if (status != FWK_SUCCESS) {
256 return status;
257 }
258
259 status = fwk_interrupt_enable((unsigned int)CSYS_PWR_UP_REQ_IRQ);
260 if (status != FWK_SUCCESS) {
261 return status;
262 }
263
264 return FWK_SUCCESS;
265 }
266