1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /* Use of "manager" may be out of sync with older versions of TRM */
9
10 #include "bootctl_reg.h"
11 #include "low_level_access.h"
12 #include "pik_system.h"
13 #include "synquacer_common.h"
14 #include "synquacer_config.h"
15 #include "synquacer_mmap.h"
16 #include "fwu_mdata.h"
17
18 #include <boot_ctl.h>
19 #include <sysdef_option.h>
20
21 #include <internal/crg11.h>
22 #include <internal/gpio.h>
23 #include <internal/nic400.h>
24 #include <internal/thermal_sensor.h>
25
26 #include <mod_f_i2c.h>
27 #include <mod_hsspi.h>
28 #include <mod_nor.h>
29 #include <mod_power_domain.h>
30 #include <mod_synquacer_system.h>
31
32 #include <fwk_assert.h>
33 #include <fwk_id.h>
34 #include <fwk_log.h>
35 #include <fwk_module_idx.h>
36 #include <fwk_status.h>
37
38 #include <fmw_cmsis.h>
39
40 #include <stdbool.h>
41 #include <stdint.h>
42 #include <string.h>
43
44 #define SEC_OVERRIDE_CONVERT_MASK UINT32_C(0x3)
45
46 #define SEC_OVERRIDE_CONVERT_TO_SEC UINT8_C(0)
47 #define SEC_OVERRIDE_CONVERT_TO_NONSEC UINT8_C(1)
48 #define SEC_OVERRIDE_CONVERT_TO_NO_CHANGE UINT8_C(2)
49
50 #define SEC_OVERRIDE_REG_PCIEIF0_MMU UINT8_C(0)
51 #define SEC_OVERRIDE_REG_PCIEIF1_MMU UINT8_C(2)
52 #define SEC_OVERRIDE_REG_EMMC_XDMAC_NETSEC_MMU UINT8_C(4)
53 #define SEC_OVERRIDE_REG_XDMAC_NIC UINT8_C(16)
54 #define SEC_OVERRIDE_REG_EMMC_NIC UINT8_C(18)
55 #define SEC_OVERRIDE_REG_NETSEC_NIC UINT8_C(20)
56
57 eeprom_config_t eeprom_config;
58
59 static fwk_id_t qspi_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_HSSPI, 0);
60 static fwk_id_t nor_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_NOR, 0);
61
62 void power_domain_coldboot(void);
63 int fw_ddr_spd_param_check(void);
64 void bus_sysoc_init(void);
65 void fw_fip_load_bl2(uint32_t boot_index);
66 void fw_fip_load_arm_tf(void);
67 void smmu_wrapper_initialize(void);
68 void pcie_wrapper_configure(void);
69
fw_prepare_debug_pik(void)70 static void fw_prepare_debug_pik(void)
71 {
72 /* DEBUG ack */
73 /*
74 * bit2 : CSYSPWRUPACK
75 * bit1 : CDBGPWRUPACK
76 * bit0 : CDBGPWRUPACK
77 */
78 writel(PIK_DEBUG_BASE, 0x00000007);
79 }
80
fw_ap_data_clk_preparation(void)81 void fw_ap_data_clk_preparation(void)
82 {
83 struct ap_data {
84 /* Use 8 bit temporarily until SCP and TF team get aligned*/
85 volatile uint64_t a72_cluster_mask : 8;
86 volatile uint32_t primary_cpu : 6;
87 volatile uint32_t unused : 18;
88 } *ap_data;
89
90 /* Initialise AP context area */
91 memset((void *)AP_CONTEXT_BASE, 0, AP_CONTEXT_SIZE);
92
93 /*
94 * Pass data to the AP using the MHU secure payload area for cluster 1.
95 * Avoid using cluster 0's payload area as this will be overwritten by the
96 * SCP Ready message before the AP is powered-up and has a chance to copy
97 * the data.
98 */
99 ap_data = ((struct ap_data *)MHU_PAYLOAD_S_CLUSTER_BASE(1));
100 ap_data->a72_cluster_mask = 0;
101 ap_data->primary_cpu = 0;
102 ap_data->unused = 0;
103 __DMB();
104
105 fw_prepare_debug_pik();
106 }
107
fw_get_config_table(void)108 eeprom_config_t *fw_get_config_table(void)
109 {
110 return &eeprom_config;
111 }
112
fw_set_sec_override(uint8_t value,uint8_t change_bit_offset)113 void fw_set_sec_override(uint8_t value, uint8_t change_bit_offset)
114 {
115 uint32_t temp, intsts;
116
117 if (value >= 0x3U)
118 return;
119
120 if (change_bit_offset > 20U)
121 return;
122
123 DI(intsts);
124
125 temp = readl(
126 CONFIG_SOC_REG_ADDR_SYS_OVER_REG_TOP +
127 CONFIG_SOC_SYS_OVER_OFFSET_SEC_OVERRIDE);
128
129 /* SEC_OVERRIDE_SCBM_MMU Set Convert to the Secure Transaction. */
130 temp &= (~(SEC_OVERRIDE_CONVERT_MASK << change_bit_offset));
131 temp |= (value << change_bit_offset);
132 writel(
133 CONFIG_SOC_REG_ADDR_SYS_OVER_REG_TOP +
134 CONFIG_SOC_SYS_OVER_OFFSET_SEC_OVERRIDE,
135 temp);
136
137 EI(intsts);
138 }
139
scb_am_block_init(void)140 static void scb_am_block_init(void)
141 {
142 uint32_t value;
143
144 /*
145 * set emmc/netsec1/xdmac to non-secure so that CA53 can use
146 * as a non-secure manager
147 */
148 fw_set_sec_override(
149 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_EMMC_XDMAC_NETSEC_MMU);
150 fw_set_sec_override(
151 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_XDMAC_NIC);
152 fw_set_sec_override(
153 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_EMMC_NIC);
154 fw_set_sec_override(
155 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_NETSEC_NIC);
156
157 #if defined(SET_PCIE_NON_SECURE)
158 /*
159 * This is only for DeveloperBox, set non-secure transaction
160 * for PCIe#0/#1.
161 */
162 fw_set_sec_override(
163 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_PCIEIF0_MMU);
164 fw_set_sec_override(
165 SEC_OVERRIDE_CONVERT_TO_NONSEC, SEC_OVERRIDE_REG_PCIEIF1_MMU);
166 #endif
167
168 /* set Re-tunuing mode 0*/
169 value = readl(CONFIG_SOC_SD_CTL_REG_BASE);
170
171 value &= ~(0x3U << 8);
172
173 writel(CONFIG_SOC_SD_CTL_REG_BASE, value);
174 }
175
fw_clear_clkforce(uint32_t value)176 void fw_clear_clkforce(uint32_t value)
177 {
178 /*
179 * Writing 1 to a bit enables dynamic hardware clock-gating.
180 * Writing 0 to a bit is ignored.
181 * bit8 : SYSPLLCLKDBGFORCE
182 * bit7 : DMCCLKFORCE
183 * bit6 : SYSPERCLKFORCE
184 * bit5 : PCLKSCPFORCE
185 * bit2 : CCNCLKFORCE
186 * bit0 : PPUCLKFORCE
187 */
188 PIK_SYSTEM->CLKFORCE_CLR = value;
189 }
190
191 static crg11_state_t crg11_state[CONFIG_SOC_CRG11_NUM] = {
192 {
193 /* ID0 PERI */
194 .ps_mode = 0,
195 .fb_mode = 10U,
196 .src_frequency = 25000000,
197 .lcrg_numerator = INVALID_LCRG,
198 .reg_addr = CONFIG_SOC_REG_ADDR_CRG_PERI_TOP,
199 .clock_domain_div_modifiable_mask = 0x1fffU,
200 .clock_domain_div = {
201 0x3,
202 0x3,
203 0x7,
204 0xf,
205 0x1,
206 0x7,
207 0xf,
208 0x3,
209 0xf9,
210 0x1,
211 0x1,
212 0x3,
213 0x7,
214 0,
215 0,
216 0,
217 },
218 .port_gate = { 0x1,
219 0xc1,
220 0x1,
221 0xf,
222 0x3,
223 0x1,
224 0x1,
225 0x1,
226 0x1,
227 0xff,
228 0x7d,
229 0x6,
230 0x3,
231 0x0,
232 0x0,
233 0x0 },
234 .gate_enable = { 0x1,
235 0xc1,
236 0x1,
237 0xf,
238 0x3,
239 0x1,
240 0x1,
241 0x1,
242 0x1,
243 0xff,
244 0x7d,
245 0x6,
246 0x3,
247 0x0,
248 0x0,
249 0x0 },
250 .ref_count = 1,
251 .ap_change_allowed_flag = false,
252 },
253 { /* ID1 EMMC */
254 .ps_mode = 0, .fb_mode = 26U, .src_frequency = 25000000,
255 .lcrg_numerator = INVALID_LCRG,
256 .reg_addr = CONFIG_SOC_REG_ADDR_CRG_EMMC_TOP,
257 .clock_domain_div_modifiable_mask = 0x1fU,
258 .clock_domain_div = {
259 0, 1, 1, 7, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
260 .port_gate = { 0 }, .gate_enable = { 0 }, .ref_count = 1,
261 .ap_change_allowed_flag = false,
262 }
263 };
264
synquacer_shutdown(void)265 int synquacer_shutdown(void)
266 {
267 volatile uint32_t *gpio = (uint32_t *)CONFIG_SOC_AP_GPIO_BASE;
268 int status;
269
270 /* set PD[9] high to turn off the ATX power supply */
271 gpio[5] |= 0x2; /* set GPIO direction to output */
272 __DSB();
273 status = synquacer_system_ctx.timer_api->delay(
274 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
275 10);
276 if (status != FWK_SUCCESS) {
277 FWK_LOG_ERR("[SYNQUACER SYSTEM] timer_api->delay error(%d).", status);
278 }
279 gpio[1] |= 0x2; /* set high */
280
281 for (;;) {
282 __WFI();
283 }
284 }
285
286
crg11_soft_reset(uint8_t crg11_id)287 void crg11_soft_reset(uint8_t crg11_id)
288 {
289 writel(CRG11_CRSWR(crg11_state[crg11_id].reg_addr), 1);
290 }
291
fw_system_reset(void)292 static void fw_system_reset(void)
293 {
294 crg11_soft_reset(CONFIG_SCB_CRG11_ID_PERI);
295
296 for (;;) {
297 __WFI();
298 }
299 }
300
synquacer_reboot_chip(void)301 int synquacer_reboot_chip(void)
302 {
303 struct bootctl_reg *bootctl =
304 (struct bootctl_reg *)CONFIG_SOC_REG_ADDR_BOOT_CTL_TOP;
305
306 FWK_LOG_INFO("[SYNQUACER SYSTEM] HSSPI initialize start.");
307 synquacer_system_ctx.qspi_api->init_csmode(qspi_id);
308 synquacer_system_ctx.nor_api->reset(nor_id, 0);
309
310 /* configure BOOT_CTL as initial state */
311 bootctl->BOOT_HSSPI |= (0x1U << 1);
312 bootctl->BOOT_HSSPI &= ~(0x1U << 0);
313 FWK_LOG_INFO("[SYNQUACER SYSTEM] HSSPI initialize end.");
314
315 __disable_fault_irq();
316
317 /* set default memory remap */
318 set_memory_remap(8U);
319
320 /* do chip reboot */
321 fw_system_reset();
322
323 /* Unreachable */
324
325 return FWK_SUCCESS;
326 }
327
ap_dev_init(void)328 static void ap_dev_init(void)
329 {
330 fw_ap_data_clk_preparation();
331 fw_gpio_init();
332 scb_am_block_init();
333 }
334
main_initialize(void)335 void main_initialize(void)
336 {
337 int status = FWK_SUCCESS;
338 (void)status;
339
340 sysdef_option_init_synquacer();
341
342 fw_clear_clkforce(sysdef_option_get_clear_clkforce());
343
344 FWK_LOG_INFO(
345 "[SYNQUACER SYSTEM] chip version %s.",
346 sysdef_option_get_chip_version());
347
348 power_domain_coldboot();
349 nic_secure_access_ctrl_init();
350 thermal_enable();
351
352 __enable_irq();
353 __enable_fault_irq();
354
355 synquacer_system_ctx.f_i2c_api->init();
356
357 status = fw_ddr_spd_param_check();
358 fwk_assert(status == FWK_SUCCESS);
359
360 /* read the eeprom configuration data */
361 synquacer_system_ctx.nor_api->read(
362 nor_id,
363 0,
364 MOD_NOR_READ_FAST_1_4_4_4BYTE,
365 CONFIG_SCP_CONFIG_TABLE_OFFSET + EEPROM_CONFIG_T_START_OFFSET,
366 &eeprom_config,
367 sizeof(eeprom_config));
368 bus_sysoc_init();
369
370 return;
371 }
372
373 /* FWU platform metadata for SynQuacer */
374 struct fwu_synquacer_metadata {
375 uint32_t boot_index;
376 uint32_t boot_count;
377 } __attribute__((__packed__));
378
update_platform_metadata(struct fwu_synquacer_metadata * platdata)379 static void update_platform_metadata(struct fwu_synquacer_metadata *platdata)
380 {
381 struct fwu_synquacer_metadata buf;
382
383 synquacer_system_ctx.nor_api->read(nor_id, 0,
384 MOD_NOR_READ_FAST_1_4_4_4BYTE,
385 CONFIG_SCB_PLAT_METADATA_OFFS,
386 &buf, sizeof(buf));
387
388 if (!memcmp(platdata, &buf, sizeof(buf))) {
389 return;
390 }
391
392 synquacer_system_ctx.nor_api->erase(nor_id, 0,
393 MOD_NOR_ERASE_BLOCK_4BYTE,
394 CONFIG_SCB_PLAT_METADATA_OFFS,
395 sizeof(*platdata));
396 synquacer_system_ctx.nor_api->program(nor_id, 0,
397 MOD_NOR_PROGRAM_4BYTE,
398 CONFIG_SCB_PLAT_METADATA_OFFS,
399 platdata, sizeof(*platdata));
400 /* Read to verify and set the "read" command-sequence */
401 synquacer_system_ctx.nor_api->read(nor_id, 0,
402 MOD_NOR_READ_FAST_1_4_4_4BYTE,
403 CONFIG_SCB_PLAT_METADATA_OFFS,
404 &buf, sizeof(buf));
405 if (memcmp(platdata, &buf, sizeof(buf))) {
406 FWK_LOG_ERR("[FWU] Failed to update boot-index!\n");
407 }
408 }
409
fwu_plat_get_boot_index(void)410 static uint32_t fwu_plat_get_boot_index(void)
411 {
412 struct fwu_synquacer_metadata platdata;
413 struct fwu_mdata metadata;
414
415 /* Read metadata */
416 synquacer_system_ctx.nor_api->read(nor_id, 0,
417 MOD_NOR_READ_FAST_1_4_4_4BYTE,
418 CONFIG_SCB_FWU_METADATA_OFFS,
419 &metadata, sizeof(metadata));
420
421 synquacer_system_ctx.nor_api->read(nor_id, 0,
422 MOD_NOR_READ_FAST_1_4_4_4BYTE,
423 CONFIG_SCB_PLAT_METADATA_OFFS,
424 &platdata, sizeof(platdata));
425
426 /* TODO: use CRC32 */
427 if (metadata.version != 1 ||
428 metadata.active_index > CONFIG_FWU_NUM_BANKS) {
429 platdata.boot_index = 0;
430 FWK_LOG_ERR("[FWU] FWU metadata is broken. Use default boot indx 0\n");
431 } else if (metadata.active_index != platdata.boot_index) {
432 /* Switch to new active bank as a trial. */
433 platdata.boot_index = metadata.active_index;
434 platdata.boot_count = 1;
435 FWK_LOG_INFO("[FWU] New firmware will boot. New index is %d\n",
436 (int)platdata.boot_index);
437 } else if (platdata.boot_count) {
438 /* BL33 will clear the boot_count when boot. */
439 if (platdata.boot_count < CONFIG_FWU_MAX_COUNT) {
440 platdata.boot_count++;
441 } else {
442 platdata.boot_index = metadata.previous_active_index;
443 platdata.boot_count = 0;
444 FWK_LOG_ERR("[FWU] New firmware boot trial failed. Rollback index is %d\n",
445 (int)platdata.boot_index);
446 }
447 }
448
449 update_platform_metadata(&platdata);
450
451 return platdata.boot_index;
452 }
453
fw_wakeup_ap(void)454 static void fw_wakeup_ap(void)
455 {
456 ap_dev_init();
457
458 /* Check DSW 3-4 */
459 if (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 0) & 0x8) {
460 FWK_LOG_INFO("[SYNQUACER SYSTEM] Arm tf BL2 load start.");
461 fw_fip_load_bl2(fwu_plat_get_boot_index());
462 FWK_LOG_INFO("[SYNQUACER SYSTEM] Arm tf BL2 load end.");
463 } else {
464 FWK_LOG_INFO("[SYNQUACER SYSTEM] Arm tf load start.");
465 fw_fip_load_arm_tf();
466 FWK_LOG_INFO("[SYNQUACER SYSTEM] Arm tf load end.");
467 }
468 synquacer_system_ctx.nor_api->configure_mmap_read(
469 nor_id, 0, MOD_NOR_READ_FAST_1_4_4_4BYTE, true);
470 }
471
synquacer_main(void)472 int synquacer_main(void)
473 {
474 int status;
475
476 smmu_wrapper_initialize();
477 pcie_wrapper_configure();
478 fw_wakeup_ap();
479
480 FWK_LOG_INFO("[SYNQUACER SYSTEM] powering up AP");
481 status = synquacer_system_ctx.mod_pd_restricted_api->set_state(
482 FWK_ID_ELEMENT(FWK_MODULE_IDX_POWER_DOMAIN, 0),
483 MOD_PD_SET_STATE_NO_RESP,
484 MOD_PD_COMPOSITE_STATE(
485 MOD_PD_LEVEL_2,
486 0,
487 MOD_PD_STATE_ON,
488 MOD_PD_STATE_ON,
489 MOD_PD_STATE_ON));
490
491 if (status == FWK_SUCCESS) {
492 FWK_LOG_INFO("[SYNQUACER SYSTEM] finished powering up AP");
493 } else {
494 FWK_LOG_ERR(
495 "[SYNQUACER SYSTEM] failed to power up AP. status=%d", status);
496 }
497
498 return status;
499 }
500