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