diff options
Diffstat (limited to 'plat')
114 files changed, 10553 insertions, 127 deletions
diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S new file mode 100644 index 000000000..6ee4597f2 --- /dev/null +++ b/plat/allwinner/common/include/plat_macros.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +#include <arm_macros.S> +#include <sunxi_mmap.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, SUNXI_GICC_BASE + mov_imm x16, SUNXI_GICD_BASE + arm_print_gic_regs + .endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h new file mode 100644 index 000000000..ca7db2f24 --- /dev/null +++ b/plat/allwinner/common/include/platform_def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include <common_def.h> +#include <sunxi_mmap.h> +#include <tbbr/tbbr_img_def.h> + +#define BL31_BASE SUNXI_SRAM_A2_BASE +#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE) + +/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */ +#define PLAT_SUNXI_NS_IMAGE_OFFSET (SUNXI_DRAM_BASE + (160U << 20)) + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define MAX_MMAP_REGIONS (4 + PLATFORM_MMAP_REGIONS) +#define MAX_XLAT_TABLES 2 + +#define PLAT_MAX_PWR_LVL_STATES 2 +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define PLAT_MAX_PWR_LVL 2 +#define PLAT_NUM_PWR_DOMAINS (1 + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) +#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 +#define PLATFORM_MMAP_REGIONS 4 +#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h new file mode 100644 index 000000000..e68fbe463 --- /dev/null +++ b/plat/allwinner/common/include/sunxi_def.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SUNXI_DEF_H__ +#define __SUNXI_DEF_H__ + +/* Clock configuration */ +#define SUNXI_OSC24M_CLK_IN_HZ 24000000 + +/* UART configuration */ +#define SUNXI_UART0_BAUDRATE 115200 +#define SUNXI_UART0_CLK_IN_HZ SUNXI_OSC24M_CLK_IN_HZ + +#endif /* __SUNXI_DEF_H__ */ diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S new file mode 100644 index 000000000..b00c7aefd --- /dev/null +++ b/plat/allwinner/common/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <sunxi_def.h> +#include <sunxi_mmap.h> + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_my_core_pos + .globl platform_mem_init + .globl plat_report_exception + +func plat_crash_console_init + mov_imm x0, SUNXI_UART0_BASE + mov_imm x1, SUNXI_UART0_CLK_IN_HZ + mov_imm x2, SUNXI_UART0_BAUDRATE + b console_16550_core_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm x1, SUNXI_UART0_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + ret +endfunc plat_crash_console_flush + +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CLUSTER_MASK + and x0, x0, #MPIDR_CPU_MASK + add x0, x0, x1, LSR #6 + ret +endfunc plat_my_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_report_exception + ret +endfunc plat_report_exception diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c new file mode 100644 index 000000000..d1f1aa153 --- /dev/null +++ b/plat/allwinner/common/sunxi_bl31_setup.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <assert.h> +#include <console.h> +#include <debug.h> +#include <generic_delay_timer.h> +#include <gicv2.h> +#include <platform.h> +#include <platform_def.h> +#include <sunxi_def.h> +#include <sunxi_mmap.h> +#include <uart_16550.h> + +#include "sunxi_private.h" + +static entry_point_info_t bl33_image_ep_info; + +static console_16550_t console; + +static const gicv2_driver_data_t sunxi_gic_data = { + .gicd_base = SUNXI_GICD_BASE, + .gicc_base = SUNXI_GICC_BASE, +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + /* Initialize the debug console as soon as possible */ + console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ, + SUNXI_UART0_BAUDRATE, &console); + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* Turn off all secondary CPUs */ + sunxi_disable_secondary_cpus(plat_my_core_pos()); +} + +void bl31_plat_arch_setup(void) +{ + sunxi_configure_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* Configure the interrupt controller */ + gicv2_driver_init(&sunxi_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + sunxi_security_setup(); + + INFO("BL31: Platform setup done\n"); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type) != 0); + assert(type == NON_SECURE); + + return &bl33_image_ep_info; +} diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c new file mode 100644 index 000000000..e36c8b071 --- /dev/null +++ b/plat/allwinner/common/sunxi_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform.h> +#include <platform_def.h> +#include <sunxi_def.h> +#include <xlat_tables_v2.h> + +static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = { + MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE, + MT_MEMORY | MT_RO | MT_SECURE), + MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE, + MT_MEMORY | MT_RW | MT_NS), + {}, +}; + +unsigned int plat_get_syscnt_freq2(void) +{ + return SUNXI_OSC24M_CLK_IN_HZ; +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_SUNXI_NS_IMAGE_OFFSET; +#endif +} + +void sunxi_configure_mmu_el3(int flags) +{ + mmap_add_region(BL31_BASE, BL31_BASE, + BL31_LIMIT - BL31_BASE, + MT_MEMORY | MT_RW | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); + mmap_add(sunxi_mmap); + init_xlat_tables(); + + enable_mmu_el3(0); +} diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c new file mode 100644 index 000000000..be72dee45 --- /dev/null +++ b/plat/allwinner/common/sunxi_cpu_ops.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <mmio.h> +#include <platform_def.h> +#include <sunxi_mmap.h> +#include <sunxi_cpucfg.h> +#include <utils_def.h> + +#include "sunxi_private.h" + +static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) +{ + if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) + return; + + INFO("PSCI: Disabling power to cluster %d core %d\n", cluster, core); + + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff); +} + +static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) +{ + if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0) + return; + + INFO("PSCI: Enabling power to cluster %d core %d\n", cluster, core); + + /* Power enable sequence from original Allwinner sources */ + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); + mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); +} + +void sunxi_cpu_off(unsigned int cluster, unsigned int core) +{ + INFO("PSCI: Powering off cluster %d core %d\n", cluster, core); + + /* Deassert DBGPWRDUP */ + mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); + /* Activate the core output clamps */ + mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Remove power from the CPU */ + sunxi_cpu_disable_power(cluster, core); +} + +void sunxi_cpu_on(unsigned int cluster, unsigned int core) +{ + INFO("PSCI: Powering on cluster %d core %d\n", cluster, core); + + /* Assert CPU core reset */ + mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert CPU power-on reset */ + mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Set CPU to start in AArch64 mode */ + mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core)); + /* Apply power to the CPU */ + sunxi_cpu_enable_power(cluster, core); + /* Release the core output clamps */ + mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); + /* Deassert CPU power-on reset */ + mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); + /* Deassert CPU core reset */ + mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); + /* Assert DBGPWRDUP */ + mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); +} + +void sunxi_disable_secondary_cpus(unsigned int primary_cpu) +{ + for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) { + if (cpu == primary_cpu) + continue; + sunxi_cpu_off(cpu / PLATFORM_MAX_CPUS_PER_CLUSTER, + cpu % PLATFORM_MAX_CPUS_PER_CLUSTER); + } +} diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c new file mode 100644 index 000000000..fcab130cd --- /dev/null +++ b/plat/allwinner/common/sunxi_pm.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <debug.h> +#include <delay_timer.h> +#include <gicv2.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <psci.h> +#include <sunxi_mmap.h> +#include <sunxi_cpucfg.h> + +#define SUNXI_WDOG0_CTRL_REG (SUNXI_WDOG_BASE + 0x0010) +#define SUNXI_WDOG0_CFG_REG (SUNXI_WDOG_BASE + 0x0014) +#define SUNXI_WDOG0_MODE_REG (SUNXI_WDOG_BASE + 0x0018) + +#include "sunxi_private.h" + +#define mpidr_is_valid(mpidr) ( \ + MPIDR_AFFLVL3_VAL(mpidr) == 0 && \ + MPIDR_AFFLVL2_VAL(mpidr) == 0 && \ + MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \ + MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER) + +static int sunxi_pwr_domain_on(u_register_t mpidr) +{ + if (mpidr_is_valid(mpidr) == 0) + return PSCI_E_INTERN_FAIL; + + sunxi_cpu_on(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr)); + + return PSCI_E_SUCCESS; +} + +static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) +{ + gicv2_cpuif_disable(); +} + +static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void __dead2 sunxi_system_off(void) +{ + /* Turn off all secondary CPUs */ + sunxi_disable_secondary_cpus(plat_my_core_pos()); + + ERROR("PSCI: Full shutdown not implemented, halting\n"); + wfi(); + panic(); +} + +static void __dead2 sunxi_system_reset(void) +{ + /* Reset the whole system when the watchdog times out */ + mmio_write_32(SUNXI_WDOG0_CFG_REG, 1); + /* Enable the watchdog with the shortest timeout (0.5 seconds) */ + mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1); + /* Wait for twice the watchdog timeout before panicking */ + mdelay(1000); + + ERROR("PSCI: System reset failed\n"); + wfi(); + panic(); +} + +static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + /* The non-secure entry point must be in DRAM */ + if (ns_entrypoint >= SUNXI_DRAM_BASE && + ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} + +static plat_psci_ops_t sunxi_psci_ops = { + .pwr_domain_on = sunxi_pwr_domain_on, + .pwr_domain_off = sunxi_pwr_domain_off, + .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, + .system_off = sunxi_system_off, + .system_reset = sunxi_system_reset, + .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + assert(psci_ops); + + for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) { + mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu), + sec_entrypoint & 0xffffffff); + mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu), + sec_entrypoint >> 32); + } + + *psci_ops = &sunxi_psci_ops; + + return 0; +} diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h new file mode 100644 index 000000000..b9f0fb41c --- /dev/null +++ b/plat/allwinner/common/sunxi_private.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SUNXI_PRIVATE_H__ +#define __SUNXI_PRIVATE_H__ + +void sunxi_configure_mmu_el3(int flags); +void sunxi_cpu_off(unsigned int cluster, unsigned int core); +void sunxi_cpu_on(unsigned int cluster, unsigned int core); +void sunxi_disable_secondary_cpus(unsigned int primary_cpu); + +void sunxi_security_setup(void); + +#endif /* __SUNXI_PRIVATE_H__ */ diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c new file mode 100644 index 000000000..e76007285 --- /dev/null +++ b/plat/allwinner/common/sunxi_security.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <mmio.h> +#include <sunxi_mmap.h> + +#ifdef SUNXI_SPC_BASE +#define SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4) +#define SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8) +#define SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc) +#endif + +#define R_PRCM_SEC_SWITCH_REG 0x1d0 +#define DMA_SEC_REG 0x20 + +/* + * Setup the peripherals to be accessible by non-secure world. + * This will not work for the Secure Peripherals Controller (SPC) unless + * a fuse it burnt (seems to be an erratum), but we do it nevertheless, + * to allow booting on boards using secure boot. + */ +void sunxi_security_setup(void) +{ + int i; + +#ifdef SUNXI_SPC_BASE + INFO("Configuring SPC Controller\n"); + /* SPC setup: set all devices to non-secure */ + for (i = 0; i < 6; i++) + mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff); +#endif + + /* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */ + mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7); + + /* set R_PRCM clocks to non-secure */ + mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7); + + /* Set all DMA channels (16 max.) to non-secure */ + mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff); +} diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c new file mode 100644 index 000000000..98cf63c8c --- /dev/null +++ b/plat/allwinner/common/sunxi_topology.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <platform.h> +#include <platform_def.h> + +static unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = { + /* One root node for the SoC */ + 1, + /* One node for each cluster */ + PLATFORM_CLUSTER_COUNT, + /* One set of CPUs per cluster */ + PLATFORM_MAX_CPUS_PER_CLUSTER, +}; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + if (MPIDR_AFFLVL3_VAL(mpidr) > 0 || + MPIDR_AFFLVL2_VAL(mpidr) > 0 || + cluster >= PLATFORM_CLUSTER_COUNT || + core >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core; +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h new file mode 100644 index 000000000..049c2ad23 --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SUNXI_CPUCFG_H__ +#define __SUNXI_CPUCFG_H__ + +#include <sunxi_mmap.h> + +/* c = cluster, n = core */ +#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16) +#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16) +#define SUNXI_CPUCFG_CACHE_CFG_REG0 (SUNXI_CPUCFG_BASE + 0x0008) +#define SUNXI_CPUCFG_CACHE_CFG_REG1 (SUNXI_CPUCFG_BASE + 0x000c) +#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x0020) +#define SUNXI_CPUCFG_GLB_CTRL_REG (SUNXI_CPUCFG_BASE + 0x0028) +#define SUNXI_CPUCFG_CPU_STS_REG(c) (SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4) +#define SUNXI_CPUCFG_L2_STS_REG (SUNXI_CPUCFG_BASE + 0x003c) +#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4) +#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8) +#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8) + +#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_PRCM_BASE + 0x0140 + \ + (c) * 16 + (n) * 4) +#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4) +#define SUNXI_R_CPUCFG_CPUS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0000) +#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4) +#define SUNXI_R_CPUCFG_SYS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0140) +#define SUNXI_R_CPUCFG_SS_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01a0) +#define SUNXI_R_CPUCFG_CPU_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a4) +#define SUNXI_R_CPUCFG_SS_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a8) +#define SUNXI_R_CPUCFG_HP_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01ac) + +#endif /* __SUNXI_CPUCFG_H__ */ diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h new file mode 100644 index 000000000..cb202a839 --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SUNXI_MMAP_H__ +#define __SUNXI_MMAP_H__ + +/* Memory regions */ +#define SUNXI_ROM_BASE 0x00000000 +#define SUNXI_ROM_SIZE 0x00010000 +#define SUNXI_SRAM_BASE 0x00010000 +#define SUNXI_SRAM_SIZE 0x00044000 +#define SUNXI_SRAM_A1_BASE 0x00010000 +#define SUNXI_SRAM_A1_SIZE 0x00008000 +#define SUNXI_SRAM_A2_BASE 0x00044000 +#define SUNXI_SRAM_A2_SIZE 0x00010000 +#define SUNXI_SRAM_C_BASE 0x00018000 +#define SUNXI_SRAM_C_SIZE 0x0001c000 +#define SUNXI_DEV_BASE 0x01000000 +#define SUNXI_DEV_SIZE 0x01000000 +#define SUNXI_DRAM_BASE 0x40000000 +#define SUNXI_DRAM_SIZE 0x80000000 + +/* Memory-mapped devices */ +#define SUNXI_CPU_MBIST_BASE 0x01502000 +#define SUNXI_CPUCFG_BASE 0x01700000 +#define SUNXI_SYSCON_BASE 0x01c00000 +#define SUNXI_SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24) +#define SUNXI_DMA_BASE 0x01c02000 +#define SUNXI_KEYMEM_BASE 0x01c0b000 +#define SUNXI_SMHC0_BASE 0x01c0f000 +#define SUNXI_SMHC1_BASE 0x01c10000 +#define SUNXI_SMHC2_BASE 0x01c11000 +#define SUNXI_SID_BASE 0x01c14000 +#define SUNXI_MSGBOX_BASE 0x01c17000 +#define SUNXI_SPINLOCK_BASE 0x01c18000 +#define SUNXI_CCU_BASE 0x01c20000 +#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x2f0) +#define SUNXI_PIO_BASE 0x01c20800 +#define SUNXI_TIMER_BASE 0x01c20c00 +#define SUNXI_WDOG_BASE 0x01c20ca0 +#define SUNXI_SPC_BASE 0x01c23400 +#define SUNXI_THS_BASE 0x01c25000 +#define SUNXI_UART0_BASE 0x01c28000 +#define SUNXI_UART1_BASE 0x01c28400 +#define SUNXI_UART2_BASE 0x01c28800 +#define SUNXI_UART3_BASE 0x01c28c00 +#define SUNXI_I2C0_BASE 0x01c2ac00 +#define SUNXI_I2C1_BASE 0x01c2b000 +#define SUNXI_I2C2_BASE 0x01c2b400 +#define SUNXI_DRAMCOM_BASE 0x01c62000 +#define SUNXI_DRAMCTL_BASE 0x01c63000 +#define SUNXI_DRAMPHY_BASE 0x01c65000 +#define SUNXI_SPI0_BASE 0x01c68000 +#define SUNXI_SPI1_BASE 0x01c69000 +#define SUNXI_SCU_BASE 0x01c80000 +#define SUNXI_GICD_BASE 0x01c81000 +#define SUNXI_GICC_BASE 0x01c82000 +#define SUNXI_RTC_BASE 0x01f00000 +#define SUNXI_R_TIMER_BASE 0x01f00800 +#define SUNXI_R_INTC_BASE 0x01f00c00 +#define SUNXI_R_WDOG_BASE 0x01f01000 +#define SUNXI_R_PRCM_BASE 0x01f01400 +#define SUNXI_R_TWD_BASE 0x01f01800 +#define SUNXI_R_CPUCFG_BASE 0x01f01c00 +#define SUNXI_R_CIR_BASE 0x01f02000 +#define SUNXI_R_I2C_BASE 0x01f02400 +#define SUNXI_R_UART_BASE 0x01f02800 +#define SUNXI_R_PIO_BASE 0x01f02c00 +#define SUNXI_R_RSB_BASE 0x01f03400 +#define SUNXI_R_PWM_BASE 0x01f03800 + +#endif /* __SUNXI_MMAP_H__ */ diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk new file mode 100644 index 000000000..236464fe8 --- /dev/null +++ b/plat/allwinner/sun50i_a64/platform.mk @@ -0,0 +1,59 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +AW_PLAT := plat/allwinner + +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -Iinclude/plat/arm/common/aarch64 \ + -I${AW_PLAT}/common/include \ + -I${AW_PLAT}/${PLAT}/include + +PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \ + drivers/ti/uart/${ARCH}/16550_console.S \ + ${XLAT_TABLES_LIB_SRCS} \ + ${AW_PLAT}/common/plat_helpers.S \ + ${AW_PLAT}/common/sunxi_common.c + +BL31_SOURCES += drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/${ARCH}/cortex_a53.S \ + plat/common/plat_gicv2.c \ + plat/common/plat_psci_common.c \ + ${AW_PLAT}/common/sunxi_bl31_setup.c \ + ${AW_PLAT}/common/sunxi_cpu_ops.c \ + ${AW_PLAT}/common/sunxi_pm.c \ + ${AW_PLAT}/common/sunxi_security.c \ + ${AW_PLAT}/common/sunxi_topology.c + +# The bootloader is guaranteed to only run on CPU 0 by the boot ROM. +COLD_BOOT_SINGLE_CPU := 1 + +# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4. +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Disable the PSCI platform compatibility layer. +ENABLE_PLAT_COMPAT := 0 + +MULTI_CONSOLE_API := 1 + +# Prohibit using deprecated interfaces. We rely on this for this platform. +ERROR_DEPRECATED := 1 + +# The reset vector can be changed for each CPU. +PROGRAMMABLE_RESET_ADDRESS := 1 + +# Allow mapping read-only data as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL +RESET_TO_BL31 := 1 diff --git a/plat/arm/board/fvp/aarch64/fvp_ras.c b/plat/arm/board/fvp/aarch64/fvp_ras.c new file mode 100644 index 000000000..fb80a8a0b --- /dev/null +++ b/plat/arm/board/fvp/aarch64/fvp_ras.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <ras.h> + +struct ras_interrupt fvp_ras_interrupts[] = { +}; + +struct err_record_info fvp_err_records[] = { +}; + +REGISTER_ERR_RECORD_INFO(fvp_err_records); +REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts); diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 3a2873339..ed41d4cb8 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -216,6 +216,10 @@ BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ lib/cpus/aarch64/cpuamu_helpers.S endif +ifeq (${RAS_EXTENSION},1) +BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c +endif + ifneq (${ENABLE_STACK_PROTECTOR},0) PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c endif diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S index 760a53af2..752929db5 100644 --- a/plat/arm/common/aarch64/arm_helpers.S +++ b/plat/arm/common/aarch64/arm_helpers.S @@ -8,9 +8,9 @@ .weak plat_arm_calc_core_pos .weak plat_my_core_pos - .globl plat_crash_console_init - .globl plat_crash_console_putc - .globl plat_crash_console_flush + .weak plat_crash_console_init + .weak plat_crash_console_putc + .weak plat_crash_console_flush .globl platform_mem_init @@ -50,7 +50,7 @@ func plat_crash_console_init mov_imm x0, PLAT_ARM_CRASH_UART_BASE mov_imm x1, PLAT_ARM_CRASH_UART_CLK_IN_HZ mov_imm x2, ARM_CONSOLE_BAUDRATE - b console_core_init + b console_pl011_core_init endfunc plat_crash_console_init /* --------------------------------------------- @@ -62,7 +62,7 @@ endfunc plat_crash_console_init */ func plat_crash_console_putc mov_imm x1, PLAT_ARM_CRASH_UART_BASE - b console_core_putc + b console_pl011_core_putc endfunc plat_crash_console_putc /* --------------------------------------------- @@ -75,7 +75,7 @@ endfunc plat_crash_console_putc */ func plat_crash_console_flush mov_imm x0, PLAT_ARM_CRASH_UART_BASE - b console_core_flush + b console_pl011_core_flush endfunc plat_crash_console_flush /* --------------------------------------------------------------------- diff --git a/plat/arm/common/aarch64/arm_ras.c b/plat/arm/common/aarch64/arm_ras.c deleted file mode 100644 index 80dfaf1b7..000000000 --- a/plat/arm/common/aarch64/arm_ras.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <ras.h> - -struct ras_interrupt arm_ras_interrupts[] = { -}; - -struct err_record_info arm_err_records[] = { -}; - -REGISTER_ERR_RECORD_INFO(arm_err_records); -REGISTER_RAS_INTERRUPTS(arm_ras_interrupts); diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 379e87df2..e5e730417 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -9,7 +9,6 @@ #include <arm_xlat_tables.h> #include <bl1.h> #include <bl_common.h> -#include <console.h> #include <plat_arm.h> #include <platform.h> #include <platform_def.h> @@ -45,8 +44,7 @@ void arm_bl1_early_platform_setup(void) #endif /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); /* Allow BL1 to see the whole Trusted RAM */ bl1_tzram_layout.total_base = ARM_BL_RAM_BASE; diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c index e70d115ee..e7247c63d 100644 --- a/plat/arm/common/arm_bl2_el3_setup.c +++ b/plat/arm/common/arm_bl2_el3_setup.c @@ -1,9 +1,8 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -#include <console.h> #include <generic_delay_timer.h> #include <plat_arm.h> #include <platform.h> @@ -21,8 +20,7 @@ static meminfo_t bl2_el3_tzram_layout; void arm_bl2_el3_early_platform_setup(void) { /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); /* * Allow BL2 to see the whole Trusted RAM. This is determined diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index 4ef3a9b0f..3aa99f805 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -8,7 +8,6 @@ #include <arm_def.h> #include <assert.h> #include <bl_common.h> -#include <console.h> #include <debug.h> #include <desc_image_load.h> #include <generic_delay_timer.h> @@ -176,8 +175,7 @@ struct entry_point_info *bl2_plat_get_bl31_ep_info(void) void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout) { /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); /* Setup the BL2 memory layout */ bl2_tzram_layout = *mem_layout; diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index 3b8e4aa46..cd691e5c3 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -7,7 +7,6 @@ #include <arch_helpers.h> #include <arm_def.h> #include <bl_common.h> -#include <console.h> #include <generic_delay_timer.h> #include <plat_arm.h> #include <platform_def.h> @@ -36,8 +35,8 @@ void bl2u_platform_setup(void) void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) { /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); + generic_delay_timer_init(); } diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 46f7ae0e5..6346f0fff 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -78,8 +78,7 @@ void arm_bl31_early_platform_setup(bl31_params_t *from_bl2, uintptr_t soc_fw_con #endif { /* Initialize the console to provide early debug support */ - console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_boot_init(); #if RESET_TO_BL31 /* There are no parameters from BL2 if BL31 is a reset vector */ @@ -249,12 +248,18 @@ void arm_bl31_platform_setup(void) /******************************************************************************* * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM * standard platforms + * Perform BL31 platform setup ******************************************************************************/ void arm_bl31_plat_runtime_setup(void) { +#if MULTI_CONSOLE_API + console_switch_state(CONSOLE_FLAG_RUNTIME); +#else + console_uninit(); +#endif + /* Initialize the runtime console */ - console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + arm_console_runtime_init(); } void bl31_platform_setup(void) diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 3f0ea01a1..32fd9ee68 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -81,14 +81,6 @@ void arm_setup_page_tables(uintptr_t total_base, MT_DEVICE | MT_RW | MT_SECURE); #endif -#if ENABLE_SPM && defined(IMAGE_BL31) - /* The address of the following region is calculated by the linker. */ - mmap_add_region(SP_IMAGE_XLAT_TABLES_START, - SP_IMAGE_XLAT_TABLES_START, - SP_IMAGE_XLAT_TABLES_SIZE, - MT_MEMORY | MT_RW | MT_SECURE); -#endif - /* Now (re-)map the platform-specific memory regions */ mmap_add(plat_arm_get_mmap()); @@ -168,6 +160,9 @@ void arm_configure_sys_timer(void) { unsigned int reg_val; + /* Read the frequency of the system counter */ + unsigned int freq_val = plat_get_syscnt_freq2(); + #if ARM_CONFIG_CNTACR reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); @@ -177,6 +172,23 @@ void arm_configure_sys_timer(void) reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID)); mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* + * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ + * system register initialized during psci_arch_setup() is different + * from this and has to be updated independently. + */ + mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val); + +#ifdef PLAT_juno + /* + * Initialize CNTFRQ register in Non-secure CNTBase frame. + * This is only required for Juno, because it doesn't follow ARM ARM + * in that the value updated in CNTFRQ is not reflected in CNTBASE_CNTFRQ. + * Hence update the value manually. + */ + mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASE_CNTFRQ, freq_val); +#endif } #endif /* ARM_SYS_TIMCTL_BASE */ diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 4b23ac675..533084708 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -125,6 +125,11 @@ SEPARATE_CODE_AND_RODATA := 1 # Enable new version of image loading on ARM platforms LOAD_IMAGE_V2 := 1 +# Use the multi console API, which is only available for AArch64 for now +ifeq (${ARCH}, aarch64) + MULTI_CONSOLE_API := 1 +endif + # Use generic OID definition (tbbr_oid.h) USE_TBBR_DEFS := 1 @@ -141,7 +146,8 @@ PLAT_INCLUDES += -Iinclude/plat/arm/common/aarch64 endif PLAT_BL_COMMON_SOURCES += plat/arm/common/${ARCH}/arm_helpers.S \ - plat/arm/common/arm_common.c + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ @@ -230,8 +236,7 @@ endif # RAS sources ifeq (${RAS_EXTENSION},1) BL31_SOURCES += lib/extensions/ras/std_err_record.c \ - lib/extensions/ras/ras_common.c \ - plat/arm/common/aarch64/arm_ras.c + lib/extensions/ras/ras_common.c endif ifneq (${TRUSTED_BOARD_BOOT},0) diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c new file mode 100644 index 000000000..6c8587fc4 --- /dev/null +++ b/plat/arm/common/arm_console.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <assert.h> +#include <console.h> +#include <debug.h> +#include <pl011.h> +#include <plat_arm.h> +#include <platform_def.h> + +/******************************************************************************* + * Functions that set up the console + ******************************************************************************/ +#if MULTI_CONSOLE_API +static console_pl011_t arm_boot_console; +static console_pl011_t arm_runtime_console; +#endif + +/* Initialize the console to provide early debug support */ +void arm_console_boot_init(void) +{ +#if MULTI_CONSOLE_API + int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE, + PLAT_ARM_BOOT_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_boot_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&arm_boot_console.console, CONSOLE_FLAG_BOOT); +#else + (void)console_init(PLAT_ARM_BOOT_UART_BASE, + PLAT_ARM_BOOT_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE); +#endif /* MULTI_CONSOLE_API */ +} + +void arm_console_boot_end(void) +{ + (void)console_flush(); + +#if MULTI_CONSOLE_API + (void)console_unregister(&arm_boot_console.console); +#else + console_uninit(); +#endif /* MULTI_CONSOLE_API */ +} + +/* Initialize the runtime console */ +void arm_console_runtime_init(void) +{ +#if MULTI_CONSOLE_API + int rc = console_pl011_register(PLAT_ARM_BL31_RUN_UART_BASE, + PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME); +#else + (void)console_init(PLAT_ARM_BL31_RUN_UART_BASE, + PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE); +#endif /* MULTI_CONSOLE_API */ +} + +void arm_console_runtime_end(void) +{ + (void)console_flush(); + +#if MULTI_CONSOLE_API + (void)console_unregister(&arm_runtime_console.console); +#else + console_uninit(); +#endif /* MULTI_CONSOLE_API */ +} diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index 32a515b56..118bd2628 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -61,8 +61,8 @@ void arm_load_tb_fw_config(void) err = arm_dyn_tb_fw_cfg_init((void *)config_base, &tb_fw_node); if (err < 0) { - WARN("Invalid TB_FW_CONFIG loaded\n"); - return; + ERROR("Invalid TB_FW_CONFIG loaded\n"); + panic(); } err = arm_dyn_get_disable_auth((void *)config_base, tb_fw_node, &disable_auth); diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index 44ac5b5d6..4632099e7 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,6 @@ #include <arm_def.h> #include <arm_gic.h> #include <assert.h> -#include <console.h> #include <errno.h> #include <plat_arm.h> #include <platform.h> @@ -160,6 +159,12 @@ void arm_system_pwr_domain_save(void) plat_arm_gic_save(); /* + * Unregister console now so that it is not registered for a second + * time during resume. + */ + arm_console_runtime_end(); + + /* * All the other peripheral which are configured by ARM TF are * re-initialized on resume from system suspend. Hence we * don't save their state here. @@ -174,8 +179,8 @@ void arm_system_pwr_domain_save(void) *****************************************************************************/ void arm_system_pwr_domain_resume(void) { - console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, - ARM_CONSOLE_BAUDRATE); + /* Initialize the console */ + arm_console_runtime_init(); /* Assert system power domain is available on the platform */ assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c index abeaea0bc..16125ad4f 100644 --- a/plat/arm/common/tsp/arm_tsp_setup.c +++ b/plat/arm/common/tsp/arm_tsp_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,8 @@ #include <arm_def.h> #include <bl_common.h> #include <console.h> +#include <debug.h> +#include <pl011.h> #include <plat_arm.h> #include <platform_def.h> #include <platform_tsp.h> @@ -22,14 +24,30 @@ /******************************************************************************* * Initialize the UART ******************************************************************************/ +#if MULTI_CONSOLE_API +static console_pl011_t arm_tsp_runtime_console; +#endif + void arm_tsp_early_platform_setup(void) { +#if MULTI_CONSOLE_API /* * Initialize a different console than already in use to display * messages from TSP */ + int rc = console_pl011_register(PLAT_ARM_TSP_UART_BASE, + PLAT_ARM_TSP_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE, + &arm_tsp_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&arm_tsp_runtime_console.console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME); +#else console_init(PLAT_ARM_TSP_UART_BASE, PLAT_ARM_TSP_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE); +#endif /* MULTI_CONSOLE_API */ } void tsp_early_platform_setup(void) diff --git a/plat/arm/css/sgi/fdts/sgi575.dts b/plat/arm/css/sgi/fdts/sgi575.dts new file mode 100644 index 000000000..be9920cbc --- /dev/null +++ b/plat/arm/css/sgi/fdts/sgi575.dts @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +/ { + /* compatible string */ + compatible = "arm,sgi575"; +}; diff --git a/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts new file mode 100644 index 000000000..0bb0a94e3 --- /dev/null +++ b/plat/arm/css/sgi/fdts/sgi575_tb_fw_config.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + /* Platform Config */ + compatible = "arm,tb_fw"; + hw_config_addr = <0x0 0xFEF00000>; + hw_config_max_size = <0x0100000>; +}; diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk index f6ef95a03..f4092f389 100644 --- a/plat/arm/css/sgi/sgi-common.mk +++ b/plat/arm/css/sgi/sgi-common.mk @@ -30,7 +30,8 @@ BL1_SOURCES += ${INTERCONNECT_SOURCES} \ ${CSS_ENT_BASE}/sgi_bl1_setup.c \ ${CSS_ENT_BASE}/sgi_plat_config.c -BL2_SOURCES += ${CSS_ENT_BASE}/sgi_security.c +BL2_SOURCES += ${CSS_ENT_BASE}/sgi_security.c \ + ${CSS_ENT_BASE}/sgi_image_load.c BL31_SOURCES += ${ENT_CPU_SOURCES} \ ${INTERCONNECT_SOURCES} \ @@ -39,6 +40,19 @@ BL31_SOURCES += ${ENT_CPU_SOURCES} \ ${CSS_ENT_BASE}/sgi_topology.c \ ${CSS_ENT_BASE}/sgi_plat_config.c +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${CSS_ENT_BASE}/fdts/${PLAT}_tb_fw_config.dts +TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config)) + +FDT_SOURCES += ${CSS_ENT_BASE}/fdts/${PLAT}.dts +HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb + +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config)) + $(eval $(call add_define,SGI_PLAT)) override CSS_LOAD_SCP_IMAGES := 0 diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c index 0928b83b7..20908463f 100644 --- a/plat/arm/css/sgi/sgi_bl31_setup.c +++ b/plat/arm/css/sgi/sgi_bl31_setup.c @@ -12,23 +12,8 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { - uint32_t plat_version; - bl_params_node_t *bl_params; - - bl_params = ((bl_params_t *)arg0)->head; - /* Initialize the platform configuration structure */ plat_config_init(); - while (bl_params) { - if (bl_params->image_id == BL33_IMAGE_ID) { - plat_version = mmio_read_32(SSC_VERSION); - bl_params->ep_info->args.arg2 = plat_version; - break; - } - - bl_params = bl_params->next_params_info; - } - arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); } diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c new file mode 100644 index 000000000..dda5e96c5 --- /dev/null +++ b/plat/arm/css/sgi/sgi_image_load.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <desc_image_load.h> +#include <libfdt.h> +#include <platform.h> + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * system-id { + * platform-id = <0>; + * } + ******************************************************************************/ +static int plat_sgi_append_config_node(void) +{ + bl_mem_params_node_t *mem_params; + void *fdt; + int nodeoffset, err; + unsigned int platid = 0; + char *platform_name; + + mem_params = get_bl_mem_params_node(HW_CONFIG_ID); + if (mem_params == NULL) { + ERROR("HW CONFIG base address is NULL"); + return -1; + } + + fdt = (void *)(mem_params->image_info.image_base); + + /* Check the validity of the fdt */ + if (fdt_check_header(fdt) != 0) { + ERROR("Invalid HW_CONFIG DTB passed\n"); + return -1; + } + + platform_name = (char *)fdt_getprop(fdt, 0, "compatible", NULL); + + if (strcmp(platform_name, "arm,sgi575") == 0) { + platid = mmio_read_32(SSC_VERSION); + } else { + WARN("Invalid platform \n"); + return -1; + } + + /* Increase DTB blob by 512 byte */ + err = fdt_open_into(fdt, fdt, mem_params->image_info.image_size + 512); + if (err < 0) { + ERROR("Failed to open HW_CONFIG DTB\n"); + return -1; + } + + /* Create "/system-id" node */ + nodeoffset = fdt_add_subnode(fdt, 0, "system-id"); + if (nodeoffset < 0) { + ERROR("Failed to add node system-id\n"); + return -1; + } + + err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid); + if (err < 0) { + ERROR("Failed to add node platform-id\n"); + return -1; + } + return 0; +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + int ret; + bl_params_t *next_bl_params; + + ret = plat_sgi_append_config_node(); + if (ret != 0) + panic(); + + next_bl_params = get_next_bl_params_from_mem_params_desc(); + populate_next_bl_params_config(next_bl_params); + + return next_bl_params; +} diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c index 94d713d99..7e1d4e207 100644 --- a/plat/arm/css/sgi/sgi_plat.c +++ b/plat/arm/css/sgi/sgi_plat.c @@ -72,50 +72,3 @@ const mmap_region_t plat_arm_mmap[] = { #endif ARM_CASSERT_MMAP - -/* - * Set up the page tables for the generic and platform-specific memory regions. - * The extents of the generic memory regions are specified by the function - * arguments and consist of: - * - Trusted SRAM seen by the BL image; - * - Code section; - * - Read-only data section; - * - Coherent memory region, if applicable. - */ - -#if IMAGE_BL1 -void bl1_plat_arch_setup(void) -{ - arm_setup_page_tables(ARM_BL_RAM_BASE, - ARM_BL_RAM_SIZE, - BL_CODE_BASE, - BL1_CODE_END, - BL1_RO_DATA_BASE, - BL1_RO_DATA_END -#if USE_COHERENT_MEM - , BL1_COHERENT_RAM_BASE, - BL1_COHERENT_RAM_LIMIT -#endif /* USE_COHERENT_MEM */ - ); - - enable_mmu_el3(0); -} -#endif /* IMAGE_BL1 */ - -#if IMAGE_BL2 -void bl2_plat_arch_setup(void) -{ - arm_setup_page_tables(BL2_BASE, - BL2_LIMIT-BL2_BASE, - BL_CODE_BASE, - BL_CODE_END, - BL_RO_DATA_BASE, - BL_RO_DATA_END -#if USE_COHERENT_MEM - , BL2_COHERENT_RAM_BASE, - BL2_COHERENT_RAM_LIMIT -#endif /* USE_COHERENT_MEM */ - ); - enable_mmu_el1(0); -} -#endif /* IMAGE_BL2 */ diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c index 4b1f23349..c5bbe7438 100644 --- a/plat/common/plat_bl1_common.c +++ b/plat/common/plat_bl1_common.c @@ -107,7 +107,8 @@ int bl1_plat_handle_post_image_load(unsigned int image_id) #if LOAD_IMAGE_V2 bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base; #else - bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base; + bl2_tzram_layout = (meminfo_t *) round_up(bl1_tzram_layout->free_base, + sizeof(uint64_t)); #endif /* LOAD_IMAGE_V2 */ #if !ERROR_DEPRECATED diff --git a/plat/imx/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S new file mode 100644 index 000000000..b89d346c6 --- /dev/null +++ b/plat/imx/common/imx8_helpers.S @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <platform_def.h> +#include <cortex_a35.h> + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_calc_core_pos + .globl plat_reset_handler + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl imx_mailbox_init + + /* -------------------------------------------------------------------- + * Helper macro that reads the part number of the current CPU and jumps + * to the given label if it matches the CPU MIDR provided. + * + * Clobbers x0. + * -------------------------------------------------------------------- + */ + .macro jump_if_cpu_midr _cpu_midr, _label + + mrs x0, midr_el1 + ubfx x0, x0, MIDR_PN_SHIFT, #12 + cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq \_label + + .endm + + /* ---------------------------------------------- + * The mailbox_base is used to distinguish warm/cold + * reset. The mailbox_base is in the data section, not + * in .bss, this allows function to start using this + * variable before the runtime memory is initialized. + * ---------------------------------------------- + */ + .section .data.mailbox_base + .align 3 + mailbox_base: .quad 0x0 + + /* ---------------------------------------------- + * unsigned int plat_is_my_cpu_primary(void); + * This function checks if this is the primary CPU + * ---------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ---------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This Function uses the plat_calc_core_pos() + * to get the index of the calling CPU. + * ---------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_my_core_pos + + /* + * unsigned int plat_calc_core_pos(uint64_t mpidr) + * helper function to calculate the core position. + * With this function. + */ +func plat_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_calc_core_pos + + /* --------------------------------------------- + * function to get the entrypoint. + * --------------------------------------------- + */ +func plat_get_my_entrypoint + adrp x1, mailbox_base + ldr x0, [x1, :lo12:mailbox_base] + ret +endfunc plat_get_my_entrypoint + +func imx_mailbox_init + adrp x1, mailbox_base + str x0, [x1, :lo12:mailbox_base] + ret +endfunc imx_mailbox_init + +func plat_secondary_cold_boot_setup + b . +endfunc plat_secondary_cold_boot_setup + +func plat_crash_console_init + ret +endfunc plat_crash_console_init + +func plat_crash_console_putc + ret +endfunc plat_crash_console_putc + +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/imx/common/imx8_topology.c b/plat/imx/common/imx8_topology.c new file mode 100644 index 000000000..bcb7d59f0 --- /dev/null +++ b/plat/imx/common/imx8_topology.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <platform.h> + +const unsigned char imx_power_domain_tree_desc[] = { + PWR_DOMAIN_AT_MAX_LVL, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return imx_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + if (cluster_id > PLATFORM_CLUSTER_COUNT || + cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER) + return -1; + + return (cpu_id + (cluster_id * 4)); +} diff --git a/plat/imx/common/include/imx8_iomux.h b/plat/imx/common/include/imx8_iomux.h new file mode 100644 index 000000000..7a7f5491c --- /dev/null +++ b/plat/imx/common/include/imx8_iomux.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IMX8_IOMUX_H__ +#define __IMX8_IOMUX_H__ + +#define PADRING_IFMUX_EN_SHIFT 31 +#define PADRING_IFMUX_EN_MASK (1 << PADRING_IFMUX_EN_SHIFT) +#define PADRING_GP_EN_SHIFT 30 +#define PADRING_GP_EN_MASK (1 << PADRING_GP_EN_SHIFT) +#define PADRING_IFMUX_SHIFT 27 +#define PADRING_IFMUX_MASK (0x7 << PADRING_IFMUX_SHIFT) +#define PADRING_CONFIG_SHIFT 25 +#define PADRING_CONFIG_MASK (0x3 << PADRING_CONFIG_SHIFT) +#define PADRING_LPCONFIG_SHIFT 23 +#define PADRING_LPCONFIG_MASK (0x3 << PADRING_LPCONFIG_SHIFT) +#define PADRING_PULL_SHIFT 5 +#define PADRING_PULL_MASK (0x3 << PADRING_PULL_SHIFT) +#define PADRING_DSE_SHIFT 0 +#define PADRING_DSE_MASK (0x7 << PADRING_DSE_SHIFT) + +#endif /* __IMX8_IOMUX_H__ */ diff --git a/plat/imx/common/include/imx8_lpuart.h b/plat/imx/common/include/imx8_lpuart.h new file mode 100644 index 000000000..4ff91bda7 --- /dev/null +++ b/plat/imx/common/include/imx8_lpuart.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __IMX_LPUART_H__ +#define __IMX_LPUART_H__ + +#include <console.h> + +#define VERID 0x0 +#define PARAM 0x4 +#define GLOBAL 0x8 +#define PINCFG 0xC +#define BAUD 0x10 +#define STAT 0x14 +#define CTRL 0x18 +#define DATA 0x1C +#define MATCH 0x20 +#define MODIR 0x24 +#define FIFO 0x28 +#define WATER 0x2c + +#define US1_TDRE (1 << 23) +#define US1_RDRF (1 << 21) + +#define CTRL_TE (1 << 19) +#define CTRL_RE (1 << 18) + +#define FIFO_TXFE 0x80 +#define FIFO_RXFE 0x40 + +#define WATER_TXWATER_OFF 1 +#define WATER_RXWATER_OFF 16 + +#define LPUART_CTRL_PT_MASK 0x1 +#define LPUART_CTRL_PE_MASK 0x2 +#define LPUART_CTRL_M_MASK 0x10 + +#define LPUART_BAUD_OSR_MASK (0x1F000000U) +#define LPUART_BAUD_OSR_SHIFT (24U) +#define LPUART_BAUD_OSR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_OSR_SHIFT)) & LPUART_BAUD_OSR_MASK) + +#define LPUART_BAUD_SBR_MASK (0x1FFFU) +#define LPUART_BAUD_SBR_SHIFT (0U) +#define LPUART_BAUD_SBR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_SBR_SHIFT)) & LPUART_BAUD_SBR_MASK) + +#define LPUART_BAUD_SBNS_MASK (0x2000U) +#define LPUART_BAUD_BOTHEDGE_MASK (0x20000U) +#define LPUART_BAUD_M10_MASK (0x20000000U) + +#ifndef __ASSEMBLY__ + +#include <types.h> + +typedef struct { + console_t console; + uintptr_t base; +} console_lpuart_t; + +int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_lpuart_t *console); +#endif /*__ASSEMBLY__*/ + +#endif /* __IMX_LPUART_H__*/ diff --git a/plat/imx/common/include/imx8qm_pads.h b/plat/imx/common/include/imx8qm_pads.h new file mode 100644 index 000000000..6107bd926 --- /dev/null +++ b/plat/imx/common/include/imx8qm_pads.h @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file used to configure SoC pad list. + */ + +#ifndef SC_PADS_H +#define SC_PADS_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Pad Definitions + */ +/*@{*/ +#define SC_P_SIM0_CLK 0 /* DMA.SIM0.CLK, LSIO.GPIO0.IO00 */ +#define SC_P_SIM0_RST 1 /* DMA.SIM0.RST, LSIO.GPIO0.IO01 */ +#define SC_P_SIM0_IO 2 /* DMA.SIM0.IO, LSIO.GPIO0.IO02 */ +#define SC_P_SIM0_PD 3 /* DMA.SIM0.PD, DMA.I2C3.SCL, LSIO.GPIO0.IO03 */ +#define SC_P_SIM0_POWER_EN 4 /* DMA.SIM0.POWER_EN, DMA.I2C3.SDA, LSIO.GPIO0.IO04 */ +#define SC_P_SIM0_GPIO0_00 5 /* DMA.SIM0.POWER_EN, LSIO.GPIO0.IO05 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SIM 6 /* */ +#define SC_P_M40_I2C0_SCL 7 /* M40.I2C0.SCL, M40.UART0.RX, M40.GPIO0.IO02, LSIO.GPIO0.IO06 */ +#define SC_P_M40_I2C0_SDA 8 /* M40.I2C0.SDA, M40.UART0.TX, M40.GPIO0.IO03, LSIO.GPIO0.IO07 */ +#define SC_P_M40_GPIO0_00 9 /* M40.GPIO0.IO00, M40.TPM0.CH0, DMA.UART4.RX, LSIO.GPIO0.IO08 */ +#define SC_P_M40_GPIO0_01 10 /* M40.GPIO0.IO01, M40.TPM0.CH1, DMA.UART4.TX, LSIO.GPIO0.IO09 */ +#define SC_P_M41_I2C0_SCL 11 /* M41.I2C0.SCL, M41.UART0.RX, M41.GPIO0.IO02, LSIO.GPIO0.IO10 */ +#define SC_P_M41_I2C0_SDA 12 /* M41.I2C0.SDA, M41.UART0.TX, M41.GPIO0.IO03, LSIO.GPIO0.IO11 */ +#define SC_P_M41_GPIO0_00 13 /* M41.GPIO0.IO00, M41.TPM0.CH0, DMA.UART3.RX, LSIO.GPIO0.IO12 */ +#define SC_P_M41_GPIO0_01 14 /* M41.GPIO0.IO01, M41.TPM0.CH1, DMA.UART3.TX, LSIO.GPIO0.IO13 */ +#define SC_P_GPT0_CLK 15 /* LSIO.GPT0.CLK, DMA.I2C1.SCL, LSIO.KPP0.COL4, LSIO.GPIO0.IO14 */ +#define SC_P_GPT0_CAPTURE 16 /* LSIO.GPT0.CAPTURE, DMA.I2C1.SDA, LSIO.KPP0.COL5, LSIO.GPIO0.IO15 */ +#define SC_P_GPT0_COMPARE 17 /* LSIO.GPT0.COMPARE, LSIO.PWM3.OUT, LSIO.KPP0.COL6, LSIO.GPIO0.IO16 */ +#define SC_P_GPT1_CLK 18 /* LSIO.GPT1.CLK, DMA.I2C2.SCL, LSIO.KPP0.COL7, LSIO.GPIO0.IO17 */ +#define SC_P_GPT1_CAPTURE 19 /* LSIO.GPT1.CAPTURE, DMA.I2C2.SDA, LSIO.KPP0.ROW4, LSIO.GPIO0.IO18 */ +#define SC_P_GPT1_COMPARE 20 /* LSIO.GPT1.COMPARE, LSIO.PWM2.OUT, LSIO.KPP0.ROW5, LSIO.GPIO0.IO19 */ +#define SC_P_UART0_RX 21 /* DMA.UART0.RX, SCU.UART0.RX, LSIO.GPIO0.IO20 */ +#define SC_P_UART0_TX 22 /* DMA.UART0.TX, SCU.UART0.TX, LSIO.GPIO0.IO21 */ +#define SC_P_UART0_RTS_B 23 /* DMA.UART0.RTS_B, LSIO.PWM0.OUT, DMA.UART2.RX, LSIO.GPIO0.IO22 */ +#define SC_P_UART0_CTS_B 24 /* DMA.UART0.CTS_B, LSIO.PWM1.OUT, DMA.UART2.TX, LSIO.GPIO0.IO23 */ +#define SC_P_UART1_TX 25 /* DMA.UART1.TX, DMA.SPI3.SCK, LSIO.GPIO0.IO24 */ +#define SC_P_UART1_RX 26 /* DMA.UART1.RX, DMA.SPI3.SDO, LSIO.GPIO0.IO25 */ +#define SC_P_UART1_RTS_B 27 /* DMA.UART1.RTS_B, DMA.SPI3.SDI, DMA.UART1.CTS_B, LSIO.GPIO0.IO26 */ +#define SC_P_UART1_CTS_B 28 /* DMA.UART1.CTS_B, DMA.SPI3.CS0, DMA.UART1.RTS_B, LSIO.GPIO0.IO27 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 29 /* */ +#define SC_P_SCU_PMIC_MEMC_ON 30 /* SCU.GPIO0.IOXX_PMIC_MEMC_ON */ +#define SC_P_SCU_WDOG_OUT 31 /* SCU.WDOG0.WDOG_OUT */ +#define SC_P_PMIC_I2C_SDA 32 /* SCU.PMIC_I2C.SDA */ +#define SC_P_PMIC_I2C_SCL 33 /* SCU.PMIC_I2C.SCL */ +#define SC_P_PMIC_EARLY_WARNING 34 /* SCU.PMIC_EARLY_WARNING */ +#define SC_P_PMIC_INT_B 35 /* SCU.DSC.PMIC_INT_B */ +#define SC_P_SCU_GPIO0_00 36 /* SCU.GPIO0.IO00, SCU.UART0.RX, LSIO.GPIO0.IO28 */ +#define SC_P_SCU_GPIO0_01 37 /* SCU.GPIO0.IO01, SCU.UART0.TX, LSIO.GPIO0.IO29 */ +#define SC_P_SCU_GPIO0_02 38 /* SCU.GPIO0.IO02, SCU.GPIO0.IOXX_PMIC_GPU0_ON, LSIO.GPIO0.IO30 */ +#define SC_P_SCU_GPIO0_03 39 /* SCU.GPIO0.IO03, SCU.GPIO0.IOXX_PMIC_GPU1_ON, LSIO.GPIO0.IO31 */ +#define SC_P_SCU_GPIO0_04 40 /* SCU.GPIO0.IO04, SCU.GPIO0.IOXX_PMIC_A72_ON, LSIO.GPIO1.IO00 */ +#define SC_P_SCU_GPIO0_05 41 /* SCU.GPIO0.IO05, SCU.GPIO0.IOXX_PMIC_A53_ON, LSIO.GPIO1.IO01 */ +#define SC_P_SCU_GPIO0_06 42 /* SCU.GPIO0.IO06, SCU.TPM0.CH0, LSIO.GPIO1.IO02 */ +#define SC_P_SCU_GPIO0_07 43 /* SCU.GPIO0.IO07, SCU.TPM0.CH1, SCU.DSC.RTC_CLOCK_OUTPUT_32K, LSIO.GPIO1.IO03 */ +#define SC_P_SCU_BOOT_MODE0 44 /* SCU.DSC.BOOT_MODE0 */ +#define SC_P_SCU_BOOT_MODE1 45 /* SCU.DSC.BOOT_MODE1 */ +#define SC_P_SCU_BOOT_MODE2 46 /* SCU.DSC.BOOT_MODE2 */ +#define SC_P_SCU_BOOT_MODE3 47 /* SCU.DSC.BOOT_MODE3 */ +#define SC_P_SCU_BOOT_MODE4 48 /* SCU.DSC.BOOT_MODE4, SCU.PMIC_I2C.SCL */ +#define SC_P_SCU_BOOT_MODE5 49 /* SCU.DSC.BOOT_MODE5, SCU.PMIC_I2C.SDA */ +#define SC_P_LVDS0_GPIO00 50 /* LVDS0.GPIO0.IO00, LVDS0.PWM0.OUT, LSIO.GPIO1.IO04 */ +#define SC_P_LVDS0_GPIO01 51 /* LVDS0.GPIO0.IO01, LSIO.GPIO1.IO05 */ +#define SC_P_LVDS0_I2C0_SCL 52 /* LVDS0.I2C0.SCL, LVDS0.GPIO0.IO02, LSIO.GPIO1.IO06 */ +#define SC_P_LVDS0_I2C0_SDA 53 /* LVDS0.I2C0.SDA, LVDS0.GPIO0.IO03, LSIO.GPIO1.IO07 */ +#define SC_P_LVDS0_I2C1_SCL 54 /* LVDS0.I2C1.SCL, DMA.UART2.TX, LSIO.GPIO1.IO08 */ +#define SC_P_LVDS0_I2C1_SDA 55 /* LVDS0.I2C1.SDA, DMA.UART2.RX, LSIO.GPIO1.IO09 */ +#define SC_P_LVDS1_GPIO00 56 /* LVDS1.GPIO0.IO00, LVDS1.PWM0.OUT, LSIO.GPIO1.IO10 */ +#define SC_P_LVDS1_GPIO01 57 /* LVDS1.GPIO0.IO01, LSIO.GPIO1.IO11 */ +#define SC_P_LVDS1_I2C0_SCL 58 /* LVDS1.I2C0.SCL, LVDS1.GPIO0.IO02, LSIO.GPIO1.IO12 */ +#define SC_P_LVDS1_I2C0_SDA 59 /* LVDS1.I2C0.SDA, LVDS1.GPIO0.IO03, LSIO.GPIO1.IO13 */ +#define SC_P_LVDS1_I2C1_SCL 60 /* LVDS1.I2C1.SCL, DMA.UART3.TX, LSIO.GPIO1.IO14 */ +#define SC_P_LVDS1_I2C1_SDA 61 /* LVDS1.I2C1.SDA, DMA.UART3.RX, LSIO.GPIO1.IO15 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_LVDSGPIO 62 /* */ +#define SC_P_MIPI_DSI0_I2C0_SCL 63 /* MIPI_DSI0.I2C0.SCL, LSIO.GPIO1.IO16 */ +#define SC_P_MIPI_DSI0_I2C0_SDA 64 /* MIPI_DSI0.I2C0.SDA, LSIO.GPIO1.IO17 */ +#define SC_P_MIPI_DSI0_GPIO0_00 65 /* MIPI_DSI0.GPIO0.IO00, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO18 */ +#define SC_P_MIPI_DSI0_GPIO0_01 66 /* MIPI_DSI0.GPIO0.IO01, LSIO.GPIO1.IO19 */ +#define SC_P_MIPI_DSI1_I2C0_SCL 67 /* MIPI_DSI1.I2C0.SCL, LSIO.GPIO1.IO20 */ +#define SC_P_MIPI_DSI1_I2C0_SDA 68 /* MIPI_DSI1.I2C0.SDA, LSIO.GPIO1.IO21 */ +#define SC_P_MIPI_DSI1_GPIO0_00 69 /* MIPI_DSI1.GPIO0.IO00, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO22 */ +#define SC_P_MIPI_DSI1_GPIO0_01 70 /* MIPI_DSI1.GPIO0.IO01, LSIO.GPIO1.IO23 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 71 /* */ +#define SC_P_MIPI_CSI0_MCLK_OUT 72 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO1.IO24 */ +#define SC_P_MIPI_CSI0_I2C0_SCL 73 /* MIPI_CSI0.I2C0.SCL, LSIO.GPIO1.IO25 */ +#define SC_P_MIPI_CSI0_I2C0_SDA 74 /* MIPI_CSI0.I2C0.SDA, LSIO.GPIO1.IO26 */ +#define SC_P_MIPI_CSI0_GPIO0_00 75 /* MIPI_CSI0.GPIO0.IO00, DMA.I2C0.SCL, MIPI_CSI1.I2C0.SCL, LSIO.GPIO1.IO27 */ +#define SC_P_MIPI_CSI0_GPIO0_01 76 /* MIPI_CSI0.GPIO0.IO01, DMA.I2C0.SDA, MIPI_CSI1.I2C0.SDA, LSIO.GPIO1.IO28 */ +#define SC_P_MIPI_CSI1_MCLK_OUT 77 /* MIPI_CSI1.ACM.MCLK_OUT, LSIO.GPIO1.IO29 */ +#define SC_P_MIPI_CSI1_GPIO0_00 78 /* MIPI_CSI1.GPIO0.IO00, DMA.UART4.RX, LSIO.GPIO1.IO30 */ +#define SC_P_MIPI_CSI1_GPIO0_01 79 /* MIPI_CSI1.GPIO0.IO01, DMA.UART4.TX, LSIO.GPIO1.IO31 */ +#define SC_P_MIPI_CSI1_I2C0_SCL 80 /* MIPI_CSI1.I2C0.SCL, LSIO.GPIO2.IO00 */ +#define SC_P_MIPI_CSI1_I2C0_SDA 81 /* MIPI_CSI1.I2C0.SDA, LSIO.GPIO2.IO01 */ +#define SC_P_HDMI_TX0_TS_SCL 82 /* HDMI_TX0.I2C0.SCL, DMA.I2C0.SCL, LSIO.GPIO2.IO02 */ +#define SC_P_HDMI_TX0_TS_SDA 83 /* HDMI_TX0.I2C0.SDA, DMA.I2C0.SDA, LSIO.GPIO2.IO03 */ +#define SC_P_COMP_CTL_GPIO_3V3_HDMIGPIO 84 /* */ +#define SC_P_ESAI1_FSR 85 /* AUD.ESAI1.FSR, LSIO.GPIO2.IO04 */ +#define SC_P_ESAI1_FST 86 /* AUD.ESAI1.FST, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO05 */ +#define SC_P_ESAI1_SCKR 87 /* AUD.ESAI1.SCKR, LSIO.GPIO2.IO06 */ +#define SC_P_ESAI1_SCKT 88 /* AUD.ESAI1.SCKT, AUD.SAI2.RXC, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO07 */ +#define SC_P_ESAI1_TX0 89 /* AUD.ESAI1.TX0, AUD.SAI2.RXD, AUD.SPDIF0.RX, LSIO.GPIO2.IO08 */ +#define SC_P_ESAI1_TX1 90 /* AUD.ESAI1.TX1, AUD.SAI2.RXFS, AUD.SPDIF0.TX, LSIO.GPIO2.IO09 */ +#define SC_P_ESAI1_TX2_RX3 91 /* AUD.ESAI1.TX2_RX3, AUD.SPDIF0.RX, LSIO.GPIO2.IO10 */ +#define SC_P_ESAI1_TX3_RX2 92 /* AUD.ESAI1.TX3_RX2, AUD.SPDIF0.TX, LSIO.GPIO2.IO11 */ +#define SC_P_ESAI1_TX4_RX1 93 /* AUD.ESAI1.TX4_RX1, LSIO.GPIO2.IO12 */ +#define SC_P_ESAI1_TX5_RX0 94 /* AUD.ESAI1.TX5_RX0, LSIO.GPIO2.IO13 */ +#define SC_P_SPDIF0_RX 95 /* AUD.SPDIF0.RX, AUD.MQS.R, AUD.ACM.MCLK_IN1, LSIO.GPIO2.IO14 */ +#define SC_P_SPDIF0_TX 96 /* AUD.SPDIF0.TX, AUD.MQS.L, AUD.ACM.MCLK_OUT1, LSIO.GPIO2.IO15 */ +#define SC_P_SPDIF0_EXT_CLK 97 /* AUD.SPDIF0.EXT_CLK, DMA.DMA0.REQ_IN0, LSIO.GPIO2.IO16 */ +#define SC_P_SPI3_SCK 98 /* DMA.SPI3.SCK, LSIO.GPIO2.IO17 */ +#define SC_P_SPI3_SDO 99 /* DMA.SPI3.SDO, DMA.FTM.CH0, LSIO.GPIO2.IO18 */ +#define SC_P_SPI3_SDI 100 /* DMA.SPI3.SDI, DMA.FTM.CH1, LSIO.GPIO2.IO19 */ +#define SC_P_SPI3_CS0 101 /* DMA.SPI3.CS0, DMA.FTM.CH2, LSIO.GPIO2.IO20 */ +#define SC_P_SPI3_CS1 102 /* DMA.SPI3.CS1, LSIO.GPIO2.IO21 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 103 /* */ +#define SC_P_ESAI0_FSR 104 /* AUD.ESAI0.FSR, LSIO.GPIO2.IO22 */ +#define SC_P_ESAI0_FST 105 /* AUD.ESAI0.FST, LSIO.GPIO2.IO23 */ +#define SC_P_ESAI0_SCKR 106 /* AUD.ESAI0.SCKR, LSIO.GPIO2.IO24 */ +#define SC_P_ESAI0_SCKT 107 /* AUD.ESAI0.SCKT, LSIO.GPIO2.IO25 */ +#define SC_P_ESAI0_TX0 108 /* AUD.ESAI0.TX0, LSIO.GPIO2.IO26 */ +#define SC_P_ESAI0_TX1 109 /* AUD.ESAI0.TX1, LSIO.GPIO2.IO27 */ +#define SC_P_ESAI0_TX2_RX3 110 /* AUD.ESAI0.TX2_RX3, LSIO.GPIO2.IO28 */ +#define SC_P_ESAI0_TX3_RX2 111 /* AUD.ESAI0.TX3_RX2, LSIO.GPIO2.IO29 */ +#define SC_P_ESAI0_TX4_RX1 112 /* AUD.ESAI0.TX4_RX1, LSIO.GPIO2.IO30 */ +#define SC_P_ESAI0_TX5_RX0 113 /* AUD.ESAI0.TX5_RX0, LSIO.GPIO2.IO31 */ +#define SC_P_MCLK_IN0 114 /* AUD.ACM.MCLK_IN0, AUD.ESAI0.RX_HF_CLK, AUD.ESAI1.RX_HF_CLK, LSIO.GPIO3.IO00 */ +#define SC_P_MCLK_OUT0 115 /* AUD.ACM.MCLK_OUT0, AUD.ESAI0.TX_HF_CLK, AUD.ESAI1.TX_HF_CLK, LSIO.GPIO3.IO01 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHC 116 /* */ +#define SC_P_SPI0_SCK 117 /* DMA.SPI0.SCK, AUD.SAI0.RXC, LSIO.GPIO3.IO02 */ +#define SC_P_SPI0_SDO 118 /* DMA.SPI0.SDO, AUD.SAI0.TXD, LSIO.GPIO3.IO03 */ +#define SC_P_SPI0_SDI 119 /* DMA.SPI0.SDI, AUD.SAI0.RXD, LSIO.GPIO3.IO04 */ +#define SC_P_SPI0_CS0 120 /* DMA.SPI0.CS0, AUD.SAI0.RXFS, LSIO.GPIO3.IO05 */ +#define SC_P_SPI0_CS1 121 /* DMA.SPI0.CS1, AUD.SAI0.TXC, LSIO.GPIO3.IO06 */ +#define SC_P_SPI2_SCK 122 /* DMA.SPI2.SCK, LSIO.GPIO3.IO07 */ +#define SC_P_SPI2_SDO 123 /* DMA.SPI2.SDO, LSIO.GPIO3.IO08 */ +#define SC_P_SPI2_SDI 124 /* DMA.SPI2.SDI, LSIO.GPIO3.IO09 */ +#define SC_P_SPI2_CS0 125 /* DMA.SPI2.CS0, LSIO.GPIO3.IO10 */ +#define SC_P_SPI2_CS1 126 /* DMA.SPI2.CS1, AUD.SAI0.TXFS, LSIO.GPIO3.IO11 */ +#define SC_P_SAI1_RXC 127 /* AUD.SAI1.RXC, AUD.SAI0.TXD, LSIO.GPIO3.IO12 */ +#define SC_P_SAI1_RXD 128 /* AUD.SAI1.RXD, AUD.SAI0.TXFS, LSIO.GPIO3.IO13 */ +#define SC_P_SAI1_RXFS 129 /* AUD.SAI1.RXFS, AUD.SAI0.RXD, LSIO.GPIO3.IO14 */ +#define SC_P_SAI1_TXC 130 /* AUD.SAI1.TXC, AUD.SAI0.TXC, LSIO.GPIO3.IO15 */ +#define SC_P_SAI1_TXD 131 /* AUD.SAI1.TXD, AUD.SAI1.RXC, LSIO.GPIO3.IO16 */ +#define SC_P_SAI1_TXFS 132 /* AUD.SAI1.TXFS, AUD.SAI1.RXFS, LSIO.GPIO3.IO17 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 133 /* */ +#define SC_P_ADC_IN7 134 /* DMA.ADC1.IN3, DMA.SPI1.CS1, LSIO.KPP0.ROW3, LSIO.GPIO3.IO25 */ +#define SC_P_ADC_IN6 135 /* DMA.ADC1.IN2, DMA.SPI1.CS0, LSIO.KPP0.ROW2, LSIO.GPIO3.IO24 */ +#define SC_P_ADC_IN5 136 /* DMA.ADC1.IN1, DMA.SPI1.SDI, LSIO.KPP0.ROW1, LSIO.GPIO3.IO23 */ +#define SC_P_ADC_IN4 137 /* DMA.ADC1.IN0, DMA.SPI1.SDO, LSIO.KPP0.ROW0, LSIO.GPIO3.IO22 */ +#define SC_P_ADC_IN3 138 /* DMA.ADC0.IN3, DMA.SPI1.SCK, LSIO.KPP0.COL3, LSIO.GPIO3.IO21 */ +#define SC_P_ADC_IN2 139 /* DMA.ADC0.IN2, LSIO.KPP0.COL2, LSIO.GPIO3.IO20 */ +#define SC_P_ADC_IN1 140 /* DMA.ADC0.IN1, LSIO.KPP0.COL1, LSIO.GPIO3.IO19 */ +#define SC_P_ADC_IN0 141 /* DMA.ADC0.IN0, LSIO.KPP0.COL0, LSIO.GPIO3.IO18 */ +#define SC_P_MLB_SIG 142 /* CONN.MLB.SIG, AUD.SAI3.RXC, LSIO.GPIO3.IO26 */ +#define SC_P_MLB_CLK 143 /* CONN.MLB.CLK, AUD.SAI3.RXFS, LSIO.GPIO3.IO27 */ +#define SC_P_MLB_DATA 144 /* CONN.MLB.DATA, AUD.SAI3.RXD, LSIO.GPIO3.IO28 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLHT 145 /* */ +#define SC_P_FLEXCAN0_RX 146 /* DMA.FLEXCAN0.RX, LSIO.GPIO3.IO29 */ +#define SC_P_FLEXCAN0_TX 147 /* DMA.FLEXCAN0.TX, LSIO.GPIO3.IO30 */ +#define SC_P_FLEXCAN1_RX 148 /* DMA.FLEXCAN1.RX, LSIO.GPIO3.IO31 */ +#define SC_P_FLEXCAN1_TX 149 /* DMA.FLEXCAN1.TX, LSIO.GPIO4.IO00 */ +#define SC_P_FLEXCAN2_RX 150 /* DMA.FLEXCAN2.RX, LSIO.GPIO4.IO01 */ +#define SC_P_FLEXCAN2_TX 151 /* DMA.FLEXCAN2.TX, LSIO.GPIO4.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOTHR 152 /* */ +#define SC_P_USB_SS3_TC0 153 /* DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO4.IO03 */ +#define SC_P_USB_SS3_TC1 154 /* DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */ +#define SC_P_USB_SS3_TC2 155 /* DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO05 */ +#define SC_P_USB_SS3_TC3 156 /* DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */ +#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 157 /* */ +#define SC_P_USDHC1_RESET_B 158 /* CONN.USDHC1.RESET_B, LSIO.GPIO4.IO07 */ +#define SC_P_USDHC1_VSELECT 159 /* CONN.USDHC1.VSELECT, LSIO.GPIO4.IO08 */ +#define SC_P_USDHC2_RESET_B 160 /* CONN.USDHC2.RESET_B, LSIO.GPIO4.IO09 */ +#define SC_P_USDHC2_VSELECT 161 /* CONN.USDHC2.VSELECT, LSIO.GPIO4.IO10 */ +#define SC_P_USDHC2_WP 162 /* CONN.USDHC2.WP, LSIO.GPIO4.IO11 */ +#define SC_P_USDHC2_CD_B 163 /* CONN.USDHC2.CD_B, LSIO.GPIO4.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 164 /* */ +#define SC_P_ENET0_MDIO 165 /* CONN.ENET0.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO13 */ +#define SC_P_ENET0_MDC 166 /* CONN.ENET0.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO14 */ +#define SC_P_ENET0_REFCLK_125M_25M 167 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, LSIO.GPIO4.IO15 */ +#define SC_P_ENET1_REFCLK_125M_25M 168 /* CONN.ENET1.REFCLK_125M_25M, CONN.ENET1.PPS, LSIO.GPIO4.IO16 */ +#define SC_P_ENET1_MDIO 169 /* CONN.ENET1.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO17 */ +#define SC_P_ENET1_MDC 170 /* CONN.ENET1.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO18 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 171 /* */ +#define SC_P_QSPI1A_SS0_B 172 /* LSIO.QSPI1A.SS0_B, LSIO.GPIO4.IO19 */ +#define SC_P_QSPI1A_SS1_B 173 /* LSIO.QSPI1A.SS1_B, LSIO.QSPI1A.SCLK2, LSIO.GPIO4.IO20 */ +#define SC_P_QSPI1A_SCLK 174 /* LSIO.QSPI1A.SCLK, LSIO.GPIO4.IO21 */ +#define SC_P_QSPI1A_DQS 175 /* LSIO.QSPI1A.DQS, LSIO.GPIO4.IO22 */ +#define SC_P_QSPI1A_DATA3 176 /* LSIO.QSPI1A.DATA3, DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO23 */ +#define SC_P_QSPI1A_DATA2 177 /* LSIO.QSPI1A.DATA2, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO24 */ +#define SC_P_QSPI1A_DATA1 178 /* LSIO.QSPI1A.DATA1, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO25 */ +#define SC_P_QSPI1A_DATA0 179 /* LSIO.QSPI1A.DATA0, LSIO.GPIO4.IO26 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI1 180 /* */ +#define SC_P_QSPI0A_DATA0 181 /* LSIO.QSPI0A.DATA0 */ +#define SC_P_QSPI0A_DATA1 182 /* LSIO.QSPI0A.DATA1 */ +#define SC_P_QSPI0A_DATA2 183 /* LSIO.QSPI0A.DATA2 */ +#define SC_P_QSPI0A_DATA3 184 /* LSIO.QSPI0A.DATA3 */ +#define SC_P_QSPI0A_DQS 185 /* LSIO.QSPI0A.DQS */ +#define SC_P_QSPI0A_SS0_B 186 /* LSIO.QSPI0A.SS0_B */ +#define SC_P_QSPI0A_SS1_B 187 /* LSIO.QSPI0A.SS1_B, LSIO.QSPI0A.SCLK2 */ +#define SC_P_QSPI0A_SCLK 188 /* LSIO.QSPI0A.SCLK */ +#define SC_P_QSPI0B_SCLK 189 /* LSIO.QSPI0B.SCLK */ +#define SC_P_QSPI0B_DATA0 190 /* LSIO.QSPI0B.DATA0 */ +#define SC_P_QSPI0B_DATA1 191 /* LSIO.QSPI0B.DATA1 */ +#define SC_P_QSPI0B_DATA2 192 /* LSIO.QSPI0B.DATA2 */ +#define SC_P_QSPI0B_DATA3 193 /* LSIO.QSPI0B.DATA3 */ +#define SC_P_QSPI0B_DQS 194 /* LSIO.QSPI0B.DQS */ +#define SC_P_QSPI0B_SS0_B 195 /* LSIO.QSPI0B.SS0_B */ +#define SC_P_QSPI0B_SS1_B 196 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI0B.SCLK2 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0 197 /* */ +#define SC_P_PCIE_CTRL0_CLKREQ_B 198 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO27 */ +#define SC_P_PCIE_CTRL0_WAKE_B 199 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO28 */ +#define SC_P_PCIE_CTRL0_PERST_B 200 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO29 */ +#define SC_P_PCIE_CTRL1_CLKREQ_B 201 /* HSIO.PCIE1.CLKREQ_B, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO30 */ +#define SC_P_PCIE_CTRL1_WAKE_B 202 /* HSIO.PCIE1.WAKE_B, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO31 */ +#define SC_P_PCIE_CTRL1_PERST_B 203 /* HSIO.PCIE1.PERST_B, DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO5.IO00 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 204 /* */ +#define SC_P_USB_HSIC0_DATA 205 /* CONN.USB_HSIC0.DATA, DMA.I2C1.SDA, LSIO.GPIO5.IO01 */ +#define SC_P_USB_HSIC0_STROBE 206 /* CONN.USB_HSIC0.STROBE, DMA.I2C1.SCL, LSIO.GPIO5.IO02 */ +#define SC_P_CALIBRATION_0_HSIC 207 /* */ +#define SC_P_CALIBRATION_1_HSIC 208 /* */ +#define SC_P_EMMC0_CLK 209 /* CONN.EMMC0.CLK, CONN.NAND.READY_B */ +#define SC_P_EMMC0_CMD 210 /* CONN.EMMC0.CMD, CONN.NAND.DQS, AUD.MQS.R, LSIO.GPIO5.IO03 */ +#define SC_P_EMMC0_DATA0 211 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO5.IO04 */ +#define SC_P_EMMC0_DATA1 212 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO5.IO05 */ +#define SC_P_EMMC0_DATA2 213 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO5.IO06 */ +#define SC_P_EMMC0_DATA3 214 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO5.IO07 */ +#define SC_P_EMMC0_DATA4 215 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, LSIO.GPIO5.IO08 */ +#define SC_P_EMMC0_DATA5 216 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, LSIO.GPIO5.IO09 */ +#define SC_P_EMMC0_DATA6 217 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, LSIO.GPIO5.IO10 */ +#define SC_P_EMMC0_DATA7 218 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, LSIO.GPIO5.IO11 */ +#define SC_P_EMMC0_STROBE 219 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, LSIO.GPIO5.IO12 */ +#define SC_P_EMMC0_RESET_B 220 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, CONN.USDHC1.VSELECT, LSIO.GPIO5.IO13 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX 221 /* */ +#define SC_P_USDHC1_CLK 222 /* CONN.USDHC1.CLK, AUD.MQS.R */ +#define SC_P_USDHC1_CMD 223 /* CONN.USDHC1.CMD, AUD.MQS.L, LSIO.GPIO5.IO14 */ +#define SC_P_USDHC1_DATA0 224 /* CONN.USDHC1.DATA0, CONN.NAND.RE_N, LSIO.GPIO5.IO15 */ +#define SC_P_USDHC1_DATA1 225 /* CONN.USDHC1.DATA1, CONN.NAND.RE_P, LSIO.GPIO5.IO16 */ +#define SC_P_CTL_NAND_RE_P_N 226 /* */ +#define SC_P_USDHC1_DATA2 227 /* CONN.USDHC1.DATA2, CONN.NAND.DQS_N, LSIO.GPIO5.IO17 */ +#define SC_P_USDHC1_DATA3 228 /* CONN.USDHC1.DATA3, CONN.NAND.DQS_P, LSIO.GPIO5.IO18 */ +#define SC_P_CTL_NAND_DQS_P_N 229 /* */ +#define SC_P_USDHC1_DATA4 230 /* CONN.USDHC1.DATA4, CONN.NAND.CE0_B, AUD.MQS.R, LSIO.GPIO5.IO19 */ +#define SC_P_USDHC1_DATA5 231 /* CONN.USDHC1.DATA5, CONN.NAND.RE_B, AUD.MQS.L, LSIO.GPIO5.IO20 */ +#define SC_P_USDHC1_DATA6 232 /* CONN.USDHC1.DATA6, CONN.NAND.WE_B, CONN.USDHC1.WP, LSIO.GPIO5.IO21 */ +#define SC_P_USDHC1_DATA7 233 /* CONN.USDHC1.DATA7, CONN.NAND.ALE, CONN.USDHC1.CD_B, LSIO.GPIO5.IO22 */ +#define SC_P_USDHC1_STROBE 234 /* CONN.USDHC1.STROBE, CONN.NAND.CE1_B, CONN.USDHC1.RESET_B, LSIO.GPIO5.IO23 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL2 235 /* */ +#define SC_P_USDHC2_CLK 236 /* CONN.USDHC2.CLK, AUD.MQS.R, LSIO.GPIO5.IO24 */ +#define SC_P_USDHC2_CMD 237 /* CONN.USDHC2.CMD, AUD.MQS.L, LSIO.GPIO5.IO25 */ +#define SC_P_USDHC2_DATA0 238 /* CONN.USDHC2.DATA0, DMA.UART4.RX, LSIO.GPIO5.IO26 */ +#define SC_P_USDHC2_DATA1 239 /* CONN.USDHC2.DATA1, DMA.UART4.TX, LSIO.GPIO5.IO27 */ +#define SC_P_USDHC2_DATA2 240 /* CONN.USDHC2.DATA2, DMA.UART4.CTS_B, LSIO.GPIO5.IO28 */ +#define SC_P_USDHC2_DATA3 241 /* CONN.USDHC2.DATA3, DMA.UART4.RTS_B, LSIO.GPIO5.IO29 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 242 /* */ +#define SC_P_ENET0_RGMII_TXC 243 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, LSIO.GPIO5.IO30 */ +#define SC_P_ENET0_RGMII_TX_CTL 244 /* CONN.ENET0.RGMII_TX_CTL, LSIO.GPIO5.IO31 */ +#define SC_P_ENET0_RGMII_TXD0 245 /* CONN.ENET0.RGMII_TXD0, LSIO.GPIO6.IO00 */ +#define SC_P_ENET0_RGMII_TXD1 246 /* CONN.ENET0.RGMII_TXD1, LSIO.GPIO6.IO01 */ +#define SC_P_ENET0_RGMII_TXD2 247 /* CONN.ENET0.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO02 */ +#define SC_P_ENET0_RGMII_TXD3 248 /* CONN.ENET0.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO03 */ +#define SC_P_ENET0_RGMII_RXC 249 /* CONN.ENET0.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO04 */ +#define SC_P_ENET0_RGMII_RX_CTL 250 /* CONN.ENET0.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO05 */ +#define SC_P_ENET0_RGMII_RXD0 251 /* CONN.ENET0.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO06 */ +#define SC_P_ENET0_RGMII_RXD1 252 /* CONN.ENET0.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO07 */ +#define SC_P_ENET0_RGMII_RXD2 253 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO08 */ +#define SC_P_ENET0_RGMII_RXD3 254 /* CONN.ENET0.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO09 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB 255 /* */ +#define SC_P_ENET1_RGMII_TXC 256 /* CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_OUT, CONN.ENET1.RCLK50M_IN, LSIO.GPIO6.IO10 */ +#define SC_P_ENET1_RGMII_TX_CTL 257 /* CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO6.IO11 */ +#define SC_P_ENET1_RGMII_TXD0 258 /* CONN.ENET1.RGMII_TXD0, LSIO.GPIO6.IO12 */ +#define SC_P_ENET1_RGMII_TXD1 259 /* CONN.ENET1.RGMII_TXD1, LSIO.GPIO6.IO13 */ +#define SC_P_ENET1_RGMII_TXD2 260 /* CONN.ENET1.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO14 */ +#define SC_P_ENET1_RGMII_TXD3 261 /* CONN.ENET1.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO15 */ +#define SC_P_ENET1_RGMII_RXC 262 /* CONN.ENET1.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO16 */ +#define SC_P_ENET1_RGMII_RX_CTL 263 /* CONN.ENET1.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO17 */ +#define SC_P_ENET1_RGMII_RXD0 264 /* CONN.ENET1.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO18 */ +#define SC_P_ENET1_RGMII_RXD1 265 /* CONN.ENET1.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO19 */ +#define SC_P_ENET1_RGMII_RXD2 266 /* CONN.ENET1.RGMII_RXD2, CONN.ENET1.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO20 */ +#define SC_P_ENET1_RGMII_RXD3 267 /* CONN.ENET1.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO21 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA 268 /* */ +/*@}*/ + +#endif /* SC_PADS_H */ diff --git a/plat/imx/common/include/imx8qx_pads.h b/plat/imx/common/include/imx8qx_pads.h new file mode 100644 index 000000000..0e153bb1e --- /dev/null +++ b/plat/imx/common/include/imx8qx_pads.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file used to configure SoC pad list. + */ + +#ifndef SC_PADS_H +#define SC_PADS_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Pad Definitions + */ +/*@{*/ +#define SC_P_PCIE_CTRL0_PERST_B 0 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO00 */ +#define SC_P_PCIE_CTRL0_CLKREQ_B 1 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO01 */ +#define SC_P_PCIE_CTRL0_WAKE_B 2 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 3 /* */ +#define SC_P_USB_SS3_TC0 4 /* ADMA.I2C1.SCL, CONN.USB_OTG1.PWR, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO03 */ +#define SC_P_USB_SS3_TC1 5 /* ADMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */ +#define SC_P_USB_SS3_TC2 6 /* ADMA.I2C1.SDA, CONN.USB_OTG1.OC, CONN.USB_OTG2.OC, LSIO.GPIO4.IO05 */ +#define SC_P_USB_SS3_TC3 7 /* ADMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */ +#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 8 /* */ +#define SC_P_EMMC0_CLK 9 /* CONN.EMMC0.CLK, CONN.NAND.READY_B, LSIO.GPIO4.IO07 */ +#define SC_P_EMMC0_CMD 10 /* CONN.EMMC0.CMD, CONN.NAND.DQS, LSIO.GPIO4.IO08 */ +#define SC_P_EMMC0_DATA0 11 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO4.IO09 */ +#define SC_P_EMMC0_DATA1 12 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO4.IO10 */ +#define SC_P_EMMC0_DATA2 13 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO4.IO11 */ +#define SC_P_EMMC0_DATA3 14 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO4.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX0 15 /* */ +#define SC_P_EMMC0_DATA4 16 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, CONN.EMMC0.WP, LSIO.GPIO4.IO13 */ +#define SC_P_EMMC0_DATA5 17 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, CONN.EMMC0.VSELECT, LSIO.GPIO4.IO14 */ +#define SC_P_EMMC0_DATA6 18 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, CONN.MLB.CLK, LSIO.GPIO4.IO15 */ +#define SC_P_EMMC0_DATA7 19 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, CONN.MLB.SIG, LSIO.GPIO4.IO16 */ +#define SC_P_EMMC0_STROBE 20 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, CONN.MLB.DATA, LSIO.GPIO4.IO17 */ +#define SC_P_EMMC0_RESET_B 21 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, LSIO.GPIO4.IO18 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX1 22 /* */ +#define SC_P_USDHC1_RESET_B 23 /* CONN.USDHC1.RESET_B, CONN.NAND.RE_N, ADMA.SPI2.SCK, LSIO.GPIO4.IO19 */ +#define SC_P_USDHC1_VSELECT 24 /* CONN.USDHC1.VSELECT, CONN.NAND.RE_P, ADMA.SPI2.SDO, CONN.NAND.RE_B, LSIO.GPIO4.IO20 */ +#define SC_P_CTL_NAND_RE_P_N 25 /* */ +#define SC_P_USDHC1_WP 26 /* CONN.USDHC1.WP, CONN.NAND.DQS_N, ADMA.SPI2.SDI, LSIO.GPIO4.IO21 */ +#define SC_P_USDHC1_CD_B 27 /* CONN.USDHC1.CD_B, CONN.NAND.DQS_P, ADMA.SPI2.CS0, CONN.NAND.DQS, LSIO.GPIO4.IO22 */ +#define SC_P_CTL_NAND_DQS_P_N 28 /* */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 29 /* */ +#define SC_P_USDHC1_CLK 30 /* CONN.USDHC1.CLK, ADMA.UART3.RX, LSIO.GPIO4.IO23 */ +#define SC_P_USDHC1_CMD 31 /* CONN.USDHC1.CMD, CONN.NAND.CE0_B, ADMA.MQS.R, LSIO.GPIO4.IO24 */ +#define SC_P_USDHC1_DATA0 32 /* CONN.USDHC1.DATA0, CONN.NAND.CE1_B, ADMA.MQS.L, LSIO.GPIO4.IO25 */ +#define SC_P_USDHC1_DATA1 33 /* CONN.USDHC1.DATA1, CONN.NAND.RE_B, ADMA.UART3.TX, LSIO.GPIO4.IO26 */ +#define SC_P_USDHC1_DATA2 34 /* CONN.USDHC1.DATA2, CONN.NAND.WE_B, ADMA.UART3.CTS_B, LSIO.GPIO4.IO27 */ +#define SC_P_USDHC1_DATA3 35 /* CONN.USDHC1.DATA3, CONN.NAND.ALE, ADMA.UART3.RTS_B, LSIO.GPIO4.IO28 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 36 /* */ +#define SC_P_ENET0_RGMII_TXC 37 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, CONN.NAND.CE1_B, LSIO.GPIO4.IO29 */ +#define SC_P_ENET0_RGMII_TX_CTL 38 /* CONN.ENET0.RGMII_TX_CTL, CONN.USDHC1.RESET_B, LSIO.GPIO4.IO30 */ +#define SC_P_ENET0_RGMII_TXD0 39 /* CONN.ENET0.RGMII_TXD0, CONN.USDHC1.VSELECT, LSIO.GPIO4.IO31 */ +#define SC_P_ENET0_RGMII_TXD1 40 /* CONN.ENET0.RGMII_TXD1, CONN.USDHC1.WP, LSIO.GPIO5.IO00 */ +#define SC_P_ENET0_RGMII_TXD2 41 /* CONN.ENET0.RGMII_TXD2, CONN.MLB.CLK, CONN.NAND.CE0_B, CONN.USDHC1.CD_B, LSIO.GPIO5.IO01 */ +#define SC_P_ENET0_RGMII_TXD3 42 /* CONN.ENET0.RGMII_TXD3, CONN.MLB.SIG, CONN.NAND.RE_B, LSIO.GPIO5.IO02 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0 43 /* */ +#define SC_P_ENET0_RGMII_RXC 44 /* CONN.ENET0.RGMII_RXC, CONN.MLB.DATA, CONN.NAND.WE_B, CONN.USDHC1.CLK, LSIO.GPIO5.IO03 */ +#define SC_P_ENET0_RGMII_RX_CTL 45 /* CONN.ENET0.RGMII_RX_CTL, CONN.USDHC1.CMD, LSIO.GPIO5.IO04 */ +#define SC_P_ENET0_RGMII_RXD0 46 /* CONN.ENET0.RGMII_RXD0, CONN.USDHC1.DATA0, LSIO.GPIO5.IO05 */ +#define SC_P_ENET0_RGMII_RXD1 47 /* CONN.ENET0.RGMII_RXD1, CONN.USDHC1.DATA1, LSIO.GPIO5.IO06 */ +#define SC_P_ENET0_RGMII_RXD2 48 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, CONN.USDHC1.DATA2, LSIO.GPIO5.IO07 */ +#define SC_P_ENET0_RGMII_RXD3 49 /* CONN.ENET0.RGMII_RXD3, CONN.NAND.ALE, CONN.USDHC1.DATA3, LSIO.GPIO5.IO08 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1 50 /* */ +#define SC_P_ENET0_REFCLK_125M_25M 51 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, CONN.ENET1.PPS, LSIO.GPIO5.IO09 */ +#define SC_P_ENET0_MDIO 52 /* CONN.ENET0.MDIO, ADMA.I2C3.SDA, CONN.ENET1.MDIO, LSIO.GPIO5.IO10 */ +#define SC_P_ENET0_MDC 53 /* CONN.ENET0.MDC, ADMA.I2C3.SCL, CONN.ENET1.MDC, LSIO.GPIO5.IO11 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 54 /* */ +#define SC_P_ESAI0_FSR 55 /* ADMA.ESAI0.FSR, CONN.ENET1.RCLK50M_OUT, ADMA.LCDIF.D00, CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_IN */ +#define SC_P_ESAI0_FST 56 /* ADMA.ESAI0.FST, CONN.MLB.CLK, ADMA.LCDIF.D01, CONN.ENET1.RGMII_TXD2, LSIO.GPIO0.IO01 */ +#define SC_P_ESAI0_SCKR 57 /* ADMA.ESAI0.SCKR, ADMA.LCDIF.D02, CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO0.IO02 */ +#define SC_P_ESAI0_SCKT 58 /* ADMA.ESAI0.SCKT, CONN.MLB.SIG, ADMA.LCDIF.D03, CONN.ENET1.RGMII_TXD3, LSIO.GPIO0.IO03 */ +#define SC_P_ESAI0_TX0 59 /* ADMA.ESAI0.TX0, CONN.MLB.DATA, ADMA.LCDIF.D04, CONN.ENET1.RGMII_RXC, LSIO.GPIO0.IO04 */ +#define SC_P_ESAI0_TX1 60 /* ADMA.ESAI0.TX1, ADMA.LCDIF.D05, CONN.ENET1.RGMII_RXD3, LSIO.GPIO0.IO05 */ +#define SC_P_ESAI0_TX2_RX3 61 /* ADMA.ESAI0.TX2_RX3, CONN.ENET1.RMII_RX_ER, ADMA.LCDIF.D06, CONN.ENET1.RGMII_RXD2, LSIO.GPIO0.IO06 */ +#define SC_P_ESAI0_TX3_RX2 62 /* ADMA.ESAI0.TX3_RX2, ADMA.LCDIF.D07, CONN.ENET1.RGMII_RXD1, LSIO.GPIO0.IO07 */ +#define SC_P_ESAI0_TX4_RX1 63 /* ADMA.ESAI0.TX4_RX1, ADMA.LCDIF.D08, CONN.ENET1.RGMII_TXD0, LSIO.GPIO0.IO08 */ +#define SC_P_ESAI0_TX5_RX0 64 /* ADMA.ESAI0.TX5_RX0, ADMA.LCDIF.D09, CONN.ENET1.RGMII_TXD1, LSIO.GPIO0.IO09 */ +#define SC_P_SPDIF0_RX 65 /* ADMA.SPDIF0.RX, ADMA.MQS.R, ADMA.LCDIF.D10, CONN.ENET1.RGMII_RXD0, LSIO.GPIO0.IO10 */ +#define SC_P_SPDIF0_TX 66 /* ADMA.SPDIF0.TX, ADMA.MQS.L, ADMA.LCDIF.D11, CONN.ENET1.RGMII_RX_CTL, LSIO.GPIO0.IO11 */ +#define SC_P_SPDIF0_EXT_CLK 67 /* ADMA.SPDIF0.EXT_CLK, ADMA.LCDIF.D12, CONN.ENET1.REFCLK_125M_25M, LSIO.GPIO0.IO12 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 68 /* */ +#define SC_P_SPI3_SCK 69 /* ADMA.SPI3.SCK, ADMA.LCDIF.D13, LSIO.GPIO0.IO13 */ +#define SC_P_SPI3_SDO 70 /* ADMA.SPI3.SDO, ADMA.LCDIF.D14, LSIO.GPIO0.IO14 */ +#define SC_P_SPI3_SDI 71 /* ADMA.SPI3.SDI, ADMA.LCDIF.D15, LSIO.GPIO0.IO15 */ +#define SC_P_SPI3_CS0 72 /* ADMA.SPI3.CS0, ADMA.ACM.MCLK_OUT1, ADMA.LCDIF.HSYNC, LSIO.GPIO0.IO16 */ +#define SC_P_SPI3_CS1 73 /* ADMA.SPI3.CS1, ADMA.I2C3.SCL, ADMA.LCDIF.RESET, ADMA.SPI2.CS0, ADMA.LCDIF.D16 */ +#define SC_P_MCLK_IN1 74 /* ADMA.ACM.MCLK_IN1, ADMA.I2C3.SDA, ADMA.LCDIF.EN, ADMA.SPI2.SCK, ADMA.LCDIF.D17 */ +#define SC_P_MCLK_IN0 75 /* ADMA.ACM.MCLK_IN0, ADMA.ESAI0.RX_HF_CLK, ADMA.LCDIF.VSYNC, ADMA.SPI2.SDI, LSIO.GPIO0.IO19 */ +#define SC_P_MCLK_OUT0 76 /* ADMA.ACM.MCLK_OUT0, ADMA.ESAI0.TX_HF_CLK, ADMA.LCDIF.CLK, ADMA.SPI2.SDO, LSIO.GPIO0.IO20 */ +#define SC_P_UART1_TX 77 /* ADMA.UART1.TX, LSIO.PWM0.OUT, LSIO.GPT0.CAPTURE, LSIO.GPIO0.IO21 */ +#define SC_P_UART1_RX 78 /* ADMA.UART1.RX, LSIO.PWM1.OUT, LSIO.GPT0.COMPARE, LSIO.GPT1.CLK, LSIO.GPIO0.IO22 */ +#define SC_P_UART1_RTS_B 79 /* ADMA.UART1.RTS_B, LSIO.PWM2.OUT, ADMA.LCDIF.D16, LSIO.GPT1.CAPTURE, LSIO.GPT0.CLK */ +#define SC_P_UART1_CTS_B 80 /* ADMA.UART1.CTS_B, LSIO.PWM3.OUT, ADMA.LCDIF.D17, LSIO.GPT1.COMPARE, LSIO.GPIO0.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHK 81 /* */ +#define SC_P_SAI0_TXD 82 /* ADMA.SAI0.TXD, ADMA.SAI1.RXC, ADMA.SPI1.SDO, ADMA.LCDIF.D18, LSIO.GPIO0.IO25 */ +#define SC_P_SAI0_TXC 83 /* ADMA.SAI0.TXC, ADMA.SAI1.TXD, ADMA.SPI1.SDI, ADMA.LCDIF.D19, LSIO.GPIO0.IO26 */ +#define SC_P_SAI0_RXD 84 /* ADMA.SAI0.RXD, ADMA.SAI1.RXFS, ADMA.SPI1.CS0, ADMA.LCDIF.D20, LSIO.GPIO0.IO27 */ +#define SC_P_SAI0_TXFS 85 /* ADMA.SAI0.TXFS, ADMA.SPI2.CS1, ADMA.SPI1.SCK, LSIO.GPIO0.IO28 */ +#define SC_P_SAI1_RXD 86 /* ADMA.SAI1.RXD, ADMA.SAI0.RXFS, ADMA.SPI1.CS1, ADMA.LCDIF.D21, LSIO.GPIO0.IO29 */ +#define SC_P_SAI1_RXC 87 /* ADMA.SAI1.RXC, ADMA.SAI1.TXC, ADMA.LCDIF.D22, LSIO.GPIO0.IO30 */ +#define SC_P_SAI1_RXFS 88 /* ADMA.SAI1.RXFS, ADMA.SAI1.TXFS, ADMA.LCDIF.D23, LSIO.GPIO0.IO31 */ +#define SC_P_SPI2_CS0 89 /* ADMA.SPI2.CS0, LSIO.GPIO1.IO00 */ +#define SC_P_SPI2_SDO 90 /* ADMA.SPI2.SDO, LSIO.GPIO1.IO01 */ +#define SC_P_SPI2_SDI 91 /* ADMA.SPI2.SDI, LSIO.GPIO1.IO02 */ +#define SC_P_SPI2_SCK 92 /* ADMA.SPI2.SCK, LSIO.GPIO1.IO03 */ +#define SC_P_SPI0_SCK 93 /* ADMA.SPI0.SCK, ADMA.SAI0.TXC, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO04 */ +#define SC_P_SPI0_SDI 94 /* ADMA.SPI0.SDI, ADMA.SAI0.TXD, M40.TPM0.CH0, M40.GPIO0.IO02, LSIO.GPIO1.IO05 */ +#define SC_P_SPI0_SDO 95 /* ADMA.SPI0.SDO, ADMA.SAI0.TXFS, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO06 */ +#define SC_P_SPI0_CS1 96 /* ADMA.SPI0.CS1, ADMA.SAI0.RXC, ADMA.SAI1.TXD, ADMA.LCD_PWM0.OUT, LSIO.GPIO1.IO07 */ +#define SC_P_SPI0_CS0 97 /* ADMA.SPI0.CS0, ADMA.SAI0.RXD, M40.TPM0.CH1, M40.GPIO0.IO03, LSIO.GPIO1.IO08 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 98 /* */ +#define SC_P_ADC_IN1 99 /* ADMA.ADC.IN1, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO09 */ +#define SC_P_ADC_IN0 100 /* ADMA.ADC.IN0, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO10 */ +#define SC_P_ADC_IN3 101 /* ADMA.ADC.IN3, M40.UART0.TX, M40.GPIO0.IO03, ADMA.ACM.MCLK_OUT0, LSIO.GPIO1.IO11 */ +#define SC_P_ADC_IN2 102 /* ADMA.ADC.IN2, M40.UART0.RX, M40.GPIO0.IO02, ADMA.ACM.MCLK_IN0, LSIO.GPIO1.IO12 */ +#define SC_P_ADC_IN5 103 /* ADMA.ADC.IN5, M40.TPM0.CH1, M40.GPIO0.IO05, LSIO.GPIO1.IO13 */ +#define SC_P_ADC_IN4 104 /* ADMA.ADC.IN4, M40.TPM0.CH0, M40.GPIO0.IO04, LSIO.GPIO1.IO14 */ +#define SC_P_FLEXCAN0_RX 105 /* ADMA.FLEXCAN0.RX, ADMA.SAI2.RXC, ADMA.UART0.RTS_B, ADMA.SAI1.TXC, LSIO.GPIO1.IO15 */ +#define SC_P_FLEXCAN0_TX 106 /* ADMA.FLEXCAN0.TX, ADMA.SAI2.RXD, ADMA.UART0.CTS_B, ADMA.SAI1.TXFS, LSIO.GPIO1.IO16 */ +#define SC_P_FLEXCAN1_RX 107 /* ADMA.FLEXCAN1.RX, ADMA.SAI2.RXFS, ADMA.FTM.CH2, ADMA.SAI1.TXD, LSIO.GPIO1.IO17 */ +#define SC_P_FLEXCAN1_TX 108 /* ADMA.FLEXCAN1.TX, ADMA.SAI3.RXC, ADMA.DMA0.REQ_IN0, ADMA.SAI1.RXD, LSIO.GPIO1.IO18 */ +#define SC_P_FLEXCAN2_RX 109 /* ADMA.FLEXCAN2.RX, ADMA.SAI3.RXD, ADMA.UART3.RX, ADMA.SAI1.RXFS, LSIO.GPIO1.IO19 */ +#define SC_P_FLEXCAN2_TX 110 /* ADMA.FLEXCAN2.TX, ADMA.SAI3.RXFS, ADMA.UART3.TX, ADMA.SAI1.RXC, LSIO.GPIO1.IO20 */ +#define SC_P_UART0_RX 111 /* ADMA.UART0.RX, ADMA.MQS.R, ADMA.FLEXCAN0.RX, SCU.UART0.RX, LSIO.GPIO1.IO21 */ +#define SC_P_UART0_TX 112 /* ADMA.UART0.TX, ADMA.MQS.L, ADMA.FLEXCAN0.TX, SCU.UART0.TX, LSIO.GPIO1.IO22 */ +#define SC_P_UART2_TX 113 /* ADMA.UART2.TX, ADMA.FTM.CH1, ADMA.FLEXCAN1.TX, LSIO.GPIO1.IO23 */ +#define SC_P_UART2_RX 114 /* ADMA.UART2.RX, ADMA.FTM.CH0, ADMA.FLEXCAN1.RX, LSIO.GPIO1.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 115 /* */ +#define SC_P_MIPI_DSI0_I2C0_SCL 116 /* MIPI_DSI0.I2C0.SCL, MIPI_DSI1.GPIO0.IO02, LSIO.GPIO1.IO25 */ +#define SC_P_MIPI_DSI0_I2C0_SDA 117 /* MIPI_DSI0.I2C0.SDA, MIPI_DSI1.GPIO0.IO03, LSIO.GPIO1.IO26 */ +#define SC_P_MIPI_DSI0_GPIO0_00 118 /* MIPI_DSI0.GPIO0.IO00, ADMA.I2C1.SCL, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO27 */ +#define SC_P_MIPI_DSI0_GPIO0_01 119 /* MIPI_DSI0.GPIO0.IO01, ADMA.I2C1.SDA, LSIO.GPIO1.IO28 */ +#define SC_P_MIPI_DSI1_I2C0_SCL 120 /* MIPI_DSI1.I2C0.SCL, MIPI_DSI0.GPIO0.IO02, LSIO.GPIO1.IO29 */ +#define SC_P_MIPI_DSI1_I2C0_SDA 121 /* MIPI_DSI1.I2C0.SDA, MIPI_DSI0.GPIO0.IO03, LSIO.GPIO1.IO30 */ +#define SC_P_MIPI_DSI1_GPIO0_00 122 /* MIPI_DSI1.GPIO0.IO00, ADMA.I2C2.SCL, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO31 */ +#define SC_P_MIPI_DSI1_GPIO0_01 123 /* MIPI_DSI1.GPIO0.IO01, ADMA.I2C2.SDA, LSIO.GPIO2.IO00 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 124 /* */ +#define SC_P_JTAG_TRST_B 125 /* SCU.JTAG.TRST_B, SCU.WDOG0.WDOG_OUT */ +#define SC_P_PMIC_I2C_SCL 126 /* SCU.PMIC_I2C.SCL, SCU.GPIO0.IOXX_PMIC_A35_ON, LSIO.GPIO2.IO01 */ +#define SC_P_PMIC_I2C_SDA 127 /* SCU.PMIC_I2C.SDA, SCU.GPIO0.IOXX_PMIC_GPU_ON, LSIO.GPIO2.IO02 */ +#define SC_P_PMIC_INT_B 128 /* SCU.DSC.PMIC_INT_B */ +#define SC_P_SCU_GPIO0_00 129 /* SCU.GPIO0.IO00, SCU.UART0.RX, M40.UART0.RX, ADMA.UART3.RX, LSIO.GPIO2.IO03 */ +#define SC_P_SCU_GPIO0_01 130 /* SCU.GPIO0.IO01, SCU.UART0.TX, M40.UART0.TX, ADMA.UART3.TX, SCU.WDOG0.WDOG_OUT */ +#define SC_P_SCU_PMIC_STANDBY 131 /* SCU.DSC.PMIC_STANDBY */ +#define SC_P_SCU_BOOT_MODE0 132 /* SCU.DSC.BOOT_MODE0 */ +#define SC_P_SCU_BOOT_MODE1 133 /* SCU.DSC.BOOT_MODE1 */ +#define SC_P_SCU_BOOT_MODE2 134 /* SCU.DSC.BOOT_MODE2, SCU.PMIC_I2C.SDA */ +#define SC_P_SCU_BOOT_MODE3 135 /* SCU.DSC.BOOT_MODE3, SCU.PMIC_I2C.SCL, SCU.DSC.RTC_CLOCK_OUTPUT_32K */ +#define SC_P_CSI_D00 136 /* CI_PI.D02, ADMA.SAI0.RXC */ +#define SC_P_CSI_D01 137 /* CI_PI.D03, ADMA.SAI0.RXD */ +#define SC_P_CSI_D02 138 /* CI_PI.D04, ADMA.SAI0.RXFS */ +#define SC_P_CSI_D03 139 /* CI_PI.D05, ADMA.SAI2.RXC */ +#define SC_P_CSI_D04 140 /* CI_PI.D06, ADMA.SAI2.RXD */ +#define SC_P_CSI_D05 141 /* CI_PI.D07, ADMA.SAI2.RXFS */ +#define SC_P_CSI_D06 142 /* CI_PI.D08, ADMA.SAI3.RXC */ +#define SC_P_CSI_D07 143 /* CI_PI.D09, ADMA.SAI3.RXD */ +#define SC_P_CSI_HSYNC 144 /* CI_PI.HSYNC, CI_PI.D00, ADMA.SAI3.RXFS */ +#define SC_P_CSI_VSYNC 145 /* CI_PI.VSYNC, CI_PI.D01 */ +#define SC_P_CSI_PCLK 146 /* CI_PI.PCLK, MIPI_CSI0.I2C0.SCL, ADMA.SPI1.SCK, LSIO.GPIO3.IO00 */ +#define SC_P_CSI_MCLK 147 /* CI_PI.MCLK, MIPI_CSI0.I2C0.SDA, ADMA.SPI1.SDO, LSIO.GPIO3.IO01 */ +#define SC_P_CSI_EN 148 /* CI_PI.EN, CI_PI.I2C.SCL, ADMA.I2C3.SCL, ADMA.SPI1.SDI, LSIO.GPIO3.IO02 */ +#define SC_P_CSI_RESET 149 /* CI_PI.RESET, CI_PI.I2C.SDA, ADMA.I2C3.SDA, ADMA.SPI1.CS0, LSIO.GPIO3.IO03 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHD 150 /* */ +#define SC_P_MIPI_CSI0_MCLK_OUT 151 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO3.IO04 */ +#define SC_P_MIPI_CSI0_I2C0_SCL 152 /* MIPI_CSI0.I2C0.SCL, MIPI_CSI0.GPIO0.IO02, LSIO.GPIO3.IO05 */ +#define SC_P_MIPI_CSI0_I2C0_SDA 153 /* MIPI_CSI0.I2C0.SDA, MIPI_CSI0.GPIO0.IO03, LSIO.GPIO3.IO06 */ +#define SC_P_MIPI_CSI0_GPIO0_01 154 /* MIPI_CSI0.GPIO0.IO01, ADMA.I2C0.SDA, LSIO.GPIO3.IO07 */ +#define SC_P_MIPI_CSI0_GPIO0_00 155 /* MIPI_CSI0.GPIO0.IO00, ADMA.I2C0.SCL, LSIO.GPIO3.IO08 */ +#define SC_P_QSPI0A_DATA0 156 /* LSIO.QSPI0A.DATA0, LSIO.GPIO3.IO09 */ +#define SC_P_QSPI0A_DATA1 157 /* LSIO.QSPI0A.DATA1, LSIO.GPIO3.IO10 */ +#define SC_P_QSPI0A_DATA2 158 /* LSIO.QSPI0A.DATA2, LSIO.GPIO3.IO11 */ +#define SC_P_QSPI0A_DATA3 159 /* LSIO.QSPI0A.DATA3, LSIO.GPIO3.IO12 */ +#define SC_P_QSPI0A_DQS 160 /* LSIO.QSPI0A.DQS, LSIO.GPIO3.IO13 */ +#define SC_P_QSPI0A_SS0_B 161 /* LSIO.QSPI0A.SS0_B, LSIO.GPIO3.IO14 */ +#define SC_P_QSPI0A_SS1_B 162 /* LSIO.QSPI0A.SS1_B, LSIO.GPIO3.IO15 */ +#define SC_P_QSPI0A_SCLK 163 /* LSIO.QSPI0A.SCLK, LSIO.GPIO3.IO16 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0A 164 /* */ +#define SC_P_QSPI0B_SCLK 165 /* LSIO.QSPI0B.SCLK, LSIO.QSPI1A.SCLK, LSIO.KPP0.COL0, LSIO.GPIO3.IO17 */ +#define SC_P_QSPI0B_DATA0 166 /* LSIO.QSPI0B.DATA0, LSIO.QSPI1A.DATA0, LSIO.KPP0.COL1, LSIO.GPIO3.IO18 */ +#define SC_P_QSPI0B_DATA1 167 /* LSIO.QSPI0B.DATA1, LSIO.QSPI1A.DATA1, LSIO.KPP0.COL2, LSIO.GPIO3.IO19 */ +#define SC_P_QSPI0B_DATA2 168 /* LSIO.QSPI0B.DATA2, LSIO.QSPI1A.DATA2, LSIO.KPP0.COL3, LSIO.GPIO3.IO20 */ +#define SC_P_QSPI0B_DATA3 169 /* LSIO.QSPI0B.DATA3, LSIO.QSPI1A.DATA3, LSIO.KPP0.ROW0, LSIO.GPIO3.IO21 */ +#define SC_P_QSPI0B_DQS 170 /* LSIO.QSPI0B.DQS, LSIO.QSPI1A.DQS, LSIO.KPP0.ROW1, LSIO.GPIO3.IO22 */ +#define SC_P_QSPI0B_SS0_B 171 /* LSIO.QSPI0B.SS0_B, LSIO.QSPI1A.SS0_B, LSIO.KPP0.ROW2, LSIO.GPIO3.IO23 */ +#define SC_P_QSPI0B_SS1_B 172 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI1A.SS1_B, LSIO.KPP0.ROW3, LSIO.GPIO3.IO24 */ +#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0B 173 /* */ +/*@}*/ + +#endif /* SC_PADS_H */ diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h new file mode 100644 index 000000000..27d4c376e --- /dev/null +++ b/plat/imx/common/include/plat_imx8.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_IMX8_H__ +#define __PLAT_IMX8_H__ + +#include <gicv3.h> + +unsigned int plat_calc_core_pos(uint64_t mpidr); +void imx_mailbox_init(uintptr_t base_addr); +void plat_gic_driver_init(void); +void plat_gic_init(void); +void plat_gic_cpuif_enable(void); +void plat_gic_cpuif_disable(void); +void plat_gic_pcpu_init(void); + +#endif /*__PLAT_IMX8_H__ */ diff --git a/plat/imx/common/include/plat_macros.S b/plat/imx/common/include/plat_macros.S new file mode 100644 index 000000000..30cce0a47 --- /dev/null +++ b/plat/imx/common/include/plat_macros.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * the below macros print out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1 + */ +.macro plat_print_gic_regs + /* TODO */ +.endm + +/* + * the below macros print out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1 + */ +.macro plat_print_interconnect_regs + /* TODO */ +.endm + +/* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + /* TODO */ +.endm diff --git a/plat/imx/common/include/sci/sci.h b/plat/imx/common/include/sci/sci.h new file mode 100644 index 000000000..3dd17ce1f --- /dev/null +++ b/plat/imx/common/include/sci/sci.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SC_SCI_H +#define _SC_SCI_H + +/* Defines */ + +/* Includes */ + +#include <sci/sci_ipc.h> +#include <sci/svc/pad/sci_pad_api.h> +#include <sci/svc/pm/sci_pm_api.h> +#include <sci/svc/rm/sci_rm_api.h> + +#endif /* _SC_SCI_H */ diff --git a/plat/imx/common/include/sci/sci_ipc.h b/plat/imx/common/include/sci/sci_ipc.h new file mode 100644 index 000000000..c169a7911 --- /dev/null +++ b/plat/imx/common/include/sci/sci_ipc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the IPC implementation. + */ + +#ifndef SC_IPC_H +#define SC_IPC_H + +/* Includes */ + +#include <sci/sci_types.h> + +/* Defines */ + +/* Types */ + +/* Functions */ + +/*! + * This function opens an IPC channel. + * + * @param[out] ipc return pointer for ipc handle + * @param[in] id id of channel to open + * + * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_IPC + * otherwise). + * + * The \a id parameter is implementation specific. Could be an MU + * address, pointer to a driver path, channel index, etc. + */ +sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id); + +/*! + * This function closes an IPC channel. + * + * @param[in] ipc id of channel to close + */ +void sc_ipc_close(sc_ipc_t ipc); + +/*! + * This function reads a message from an IPC channel. + * + * @param[in] ipc id of channel read from + * @param[out] data pointer to message buffer to read + * + * This function will block if no message is available to be read. + */ +void sc_ipc_read(sc_ipc_t ipc, void *data); + +/*! + * This function writes a message to an IPC channel. + * + * @param[in] ipc id of channel to write to + * @param[in] data pointer to message buffer to write + * + * This function will block if the outgoing buffer is full. + */ +void sc_ipc_write(sc_ipc_t ipc, void *data); + +sc_ipc_t ipc_handle; + +#endif /* SC_IPC_H */ diff --git a/plat/imx/common/include/sci/sci_rpc.h b/plat/imx/common/include/sci/sci_rpc.h new file mode 100644 index 000000000..052f3615c --- /dev/null +++ b/plat/imx/common/include/sci/sci_rpc.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the RPC implementation. + */ + +#ifndef SC_RPC_H +#define SC_RPC_H + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/sci_ipc.h> +#include <stdbool.h> + +/* Defines */ + +#define SC_RPC_VERSION 1U + +#define SC_RPC_MAX_MSG 8U + +#define RPC_VER(MSG) ((MSG)->version) +#define RPC_SIZE(MSG) ((MSG)->size) +#define RPC_SVC(MSG) ((MSG)->svc) +#define RPC_FUNC(MSG) ((MSG)->func) +#define RPC_R8(MSG) ((MSG)->func) +#define RPC_I32(MSG, IDX) ((MSG)->DATA.i32[(IDX) / 4U]) +#define RPC_I16(MSG, IDX) ((MSG)->DATA.i16[(IDX) / 2U]) +#define RPC_I8(MSG, IDX) ((MSG)->DATA.i8[(IDX)]) +#define RPC_U32(MSG, IDX) ((MSG)->DATA.u32[(IDX) / 4U]) +#define RPC_U16(MSG, IDX) ((MSG)->DATA.u16[(IDX) / 2U]) +#define RPC_U8(MSG, IDX) ((MSG)->DATA.u8[(IDX)]) + +#define SC_RPC_SVC_UNKNOWN 0U +#define SC_RPC_SVC_RETURN 1U +#define SC_RPC_SVC_PM 2U +#define SC_RPC_SVC_RM 3U +#define SC_RPC_SVC_TIMER 5U +#define SC_RPC_SVC_PAD 6U +#define SC_RPC_SVC_MISC 7U +#define SC_RPC_SVC_IRQ 8U +#define SC_RPC_SVC_ABORT 9U + +#define SC_RPC_ASYNC_STATE_RD_START 0U +#define SC_RPC_ASYNC_STATE_RD_ACTIVE 1U +#define SC_RPC_ASYNC_STATE_RD_DONE 2U +#define SC_RPC_ASYNC_STATE_WR_START 3U +#define SC_RPC_ASYNC_STATE_WR_ACTIVE 4U +#define SC_RPC_ASYNC_STATE_WR_DONE 5U + +#define SC_RPC_MU_GIR_SVC 0x1U +#define SC_RPC_MU_GIR_DBG 0x8U + +/* Types */ + +typedef uint8_t sc_rpc_svc_t; + +typedef struct sc_rpc_msg_s { + uint8_t version; + uint8_t size; + uint8_t svc; + uint8_t func; + union { + int32_t i32[(SC_RPC_MAX_MSG - 1U)]; + int16_t i16[(SC_RPC_MAX_MSG - 1U) * 2U]; + int8_t i8[(SC_RPC_MAX_MSG - 1U) * 4U]; + uint32_t u32[(SC_RPC_MAX_MSG - 1U)]; + uint16_t u16[(SC_RPC_MAX_MSG - 1U) * 2U]; + uint8_t u8[(SC_RPC_MAX_MSG - 1U) * 4U]; + } DATA; +} sc_rpc_msg_t; + +typedef uint8_t sc_rpc_async_state_t; + +typedef struct sc_rpc_async_msg_s { + sc_rpc_async_state_t state; + uint8_t wordIdx; + sc_rpc_msg_t msg; + uint32_t timeStamp; +} sc_rpc_async_msg_t; + +/* Functions */ + +/*! + * This is an internal function to send an RPC message over an IPC + * channel. It is called by client-side SCFW API function shims. + * + * @param[in] ipc IPC handle + * @param[in,out] msg handle to a message + * @param[in] no_resp response flag + * + * If \a no_resp is SC_FALSE then this function waits for a response + * and returns the result in \a msg. + */ +void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp); + +/*! + * This is an internal function to dispath an RPC call that has + * arrived via IPC over an MU. It is called by server-side SCFW. + * + * @param[in] mu MU message arrived on + * @param[in,out] msg handle to a message + * + * The function result is returned in \a msg. + */ +void sc_rpc_dispatch(sc_rsrc_t mu, sc_rpc_msg_t *msg); + +/*! + * This function translates an RPC message and forwards on to the + * normal RPC API. It is used only by hypervisors. + * + * @param[in] ipc IPC handle + * @param[in,out] msg handle to a message + * + * This function decodes a message, calls macros to translate the + * resources, pads, addresses, partitions, memory regions, etc. and + * then forwards on to the hypervisors SCFW API.Return results are + * translated back abd placed back into the message to be returned + * to the original API. + */ +void sc_rpc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_RPC_H */ diff --git a/plat/imx/common/include/sci/sci_scfw.h b/plat/imx/common/include/sci/sci_scfw.h new file mode 100644 index 000000000..9d08dad4b --- /dev/null +++ b/plat/imx/common/include/sci/sci_scfw.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SC_SCFW_H +#define _SC_SCFW_H + +/* Includes */ + +#include <types.h> + +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*! + * This type is used to declare a handle for an IPC communication + * channel. Its meaning is specific to the IPC implementation. + */ +typedef uint64_t sc_ipc_t; + +/*! + * This type is used to declare an ID for an IPC communication + * channel. For the reference IPC implementation, this ID + * selects the base address of the MU used for IPC. + */ +typedef uint64_t sc_ipc_id_t; + + +#endif /* _SC_SCFW_H */ + diff --git a/plat/imx/common/include/sci/sci_types.h b/plat/imx/common/include/sci/sci_types.h new file mode 100644 index 000000000..3ee527676 --- /dev/null +++ b/plat/imx/common/include/sci/sci_types.h @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing types used across multiple service APIs. + */ + +#ifndef SC_TYPES_H +#define SC_TYPES_H + +/* Includes */ + +#include <sci/sci_scfw.h> + +/* Defines */ + +/*! + * @name Defines for common frequencies + */ +/*@{*/ +#define SC_32KHZ 32768U /* 32KHz */ +#define SC_10MHZ 10000000U /* 10MHz */ +#define SC_20MHZ 20000000U /* 20MHz */ +#define SC_25MHZ 25000000U /* 25MHz */ +#define SC_27MHZ 27000000U /* 27MHz */ +#define SC_40MHZ 40000000U /* 40MHz */ +#define SC_45MHZ 45000000U /* 45MHz */ +#define SC_50MHZ 50000000U /* 50MHz */ +#define SC_60MHZ 60000000U /* 60MHz */ +#define SC_66MHZ 66666666U /* 66MHz */ +#define SC_74MHZ 74250000U /* 74.25MHz */ +#define SC_80MHZ 80000000U /* 80MHz */ +#define SC_83MHZ 83333333U /* 83MHz */ +#define SC_84MHZ 84375000U /* 84.37MHz */ +#define SC_100MHZ 100000000U /* 100MHz */ +#define SC_125MHZ 125000000U /* 125MHz */ +#define SC_133MHZ 133333333U /* 133MHz */ +#define SC_135MHZ 135000000U /* 135MHz */ +#define SC_150MHZ 150000000U /* 150MHz */ +#define SC_160MHZ 160000000U /* 160MHz */ +#define SC_166MHZ 166666666U /* 166MHz */ +#define SC_175MHZ 175000000U /* 175MHz */ +#define SC_180MHZ 180000000U /* 180MHz */ +#define SC_200MHZ 200000000U /* 200MHz */ +#define SC_250MHZ 250000000U /* 250MHz */ +#define SC_266MHZ 266666666U /* 266MHz */ +#define SC_300MHZ 300000000U /* 300MHz */ +#define SC_312MHZ 312500000U /* 312.5MHZ */ +#define SC_320MHZ 320000000U /* 320MHz */ +#define SC_325MHZ 325000000U /* 325MHz */ +#define SC_333MHZ 333333333U /* 333MHz */ +#define SC_350MHZ 350000000U /* 350MHz */ +#define SC_372MHZ 372000000U /* 372MHz */ +#define SC_375MHZ 375000000U /* 375MHz */ +#define SC_400MHZ 400000000U /* 400MHz */ +#define SC_500MHZ 500000000U /* 500MHz */ +#define SC_594MHZ 594000000U /* 594MHz */ +#define SC_625MHZ 625000000U /* 625MHz */ +#define SC_640MHZ 640000000U /* 640MHz */ +#define SC_650MHZ 650000000U /* 650MHz */ +#define SC_667MHZ 666666667U /* 667MHz */ +#define SC_675MHZ 675000000U /* 675MHz */ +#define SC_700MHZ 700000000U /* 700MHz */ +#define SC_720MHZ 720000000U /* 720MHz */ +#define SC_750MHZ 750000000U /* 750MHz */ +#define SC_800MHZ 800000000U /* 800MHz */ +#define SC_850MHZ 850000000U /* 850MHz */ +#define SC_900MHZ 900000000U /* 900MHz */ +#define SC_1000MHZ 1000000000U /* 1GHz */ +#define SC_1056MHZ 1056000000U /* 1.056GHz */ +#define SC_1188MHZ 1188000000U /* 1.188GHz */ +#define SC_1260MHZ 1260000000U /* 1.26GHz */ +#define SC_1280MHZ 1280000000U /* 1.28GHz */ +#define SC_1300MHZ 1300000000U /* 1.3GHz */ +#define SC_1400MHZ 1400000000U /* 1.4GHz */ +#define SC_1500MHZ 1500000000U /* 1.5GHz */ +#define SC_1600MHZ 1600000000U /* 1.6GHz */ +#define SC_1800MHZ 1800000000U /* 1.8GHz */ +#define SC_2000MHZ 2000000000U /* 2.0GHz */ +#define SC_2112MHZ 2112000000U /* 2.12GHz */ +/*@}*/ + +/*! + * @name Defines for 24M related frequencies + */ +/*@{*/ +#define SC_8MHZ 8000000U /* 8MHz */ +#define SC_12MHZ 12000000U /* 12MHz */ +#define SC_19MHZ 19800000U /* 19.8MHz */ +#define SC_24MHZ 24000000U /* 24MHz */ +#define SC_48MHZ 48000000U /* 48MHz */ +#define SC_120MHZ 120000000U /* 120MHz */ +#define SC_132MHZ 132000000U /* 132MHz */ +#define SC_144MHZ 144000000U /* 144MHz */ +#define SC_192MHZ 192000000U /* 192MHz */ +#define SC_211MHZ 211200000U /* 211.2MHz */ +#define SC_240MHZ 240000000U /* 240MHz */ +#define SC_264MHZ 264000000U /* 264MHz */ +#define SC_352MHZ 352000000U /* 352MHz */ +#define SC_360MHZ 360000000U /* 360MHz */ +#define SC_384MHZ 384000000U /* 384MHz */ +#define SC_396MHZ 396000000U /* 396MHz */ +#define SC_432MHZ 432000000U /* 432MHz */ +#define SC_480MHZ 480000000U /* 480MHz */ +#define SC_600MHZ 600000000U /* 600MHz */ +#define SC_744MHZ 744000000U /* 744MHz */ +#define SC_792MHZ 792000000U /* 792MHz */ +#define SC_864MHZ 864000000U /* 864MHz */ +#define SC_960MHZ 960000000U /* 960MHz */ +#define SC_1056MHZ 1056000000U /* 1056MHz */ +#define SC_1200MHZ 1200000000U /* 1.2GHz */ +#define SC_1464MHZ 1464000000U /* 1.464GHz */ +#define SC_2400MHZ 2400000000U /* 2.4GHz */ +/*@}*/ + +/*! + * @name Defines for A/V related frequencies + */ +/*@{*/ +#define SC_62MHZ 62937500U /* 62.9375MHz */ +#define SC_755MHZ 755250000U /* 755.25MHz */ +/*@}*/ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_FADDR_W 36U /* Width of sc_faddr_t */ +#define SC_BOOL_W 1U /* Width of sc_bool_t */ +#define SC_ERR_W 4U /* Width of sc_err_t */ +#define SC_RSRC_W 10U /* Width of sc_rsrc_t */ +#define SC_CTRL_W 6U /* Width of sc_ctrl_t */ +/*@}*/ + +/*! + * @name Defines for sc_bool_t + */ +/*@{*/ +#define SC_FALSE ((sc_bool_t) 0U) /* True */ +#define SC_TRUE ((sc_bool_t) 1U) /* False */ +/*@}*/ + +/*! + * @name Defines for sc_err_t. + */ +/*@{*/ +#define SC_ERR_NONE 0U /* Success */ +#define SC_ERR_VERSION 1U /* Incompatible API version */ +#define SC_ERR_CONFIG 2U /* Configuration error */ +#define SC_ERR_PARM 3U /* Bad parameter */ +#define SC_ERR_NOACCESS 4U /* Permission error (no access) */ +#define SC_ERR_LOCKED 5U /* Permission error (locked) */ +#define SC_ERR_UNAVAILABLE 6U /* Unavailable (out of resources) */ +#define SC_ERR_NOTFOUND 7U /* Not found */ +#define SC_ERR_NOPOWER 8U /* No power */ +#define SC_ERR_IPC 9U /* Generic IPC error */ +#define SC_ERR_BUSY 10U /* Resource is currently busy/active */ +#define SC_ERR_FAIL 11U /* General I/O failure */ +#define SC_ERR_LAST 12U +/*@}*/ + +/*! + * @name Defines for sc_rsrc_t. + */ +/*@{*/ +#define SC_R_A53 0U +#define SC_R_A53_0 1U +#define SC_R_A53_1 2U +#define SC_R_A53_2 3U +#define SC_R_A53_3 4U +#define SC_R_A72 5U +#define SC_R_A72_0 6U +#define SC_R_A72_1 7U +#define SC_R_A72_2 8U +#define SC_R_A72_3 9U +#define SC_R_CCI 10U +#define SC_R_DB 11U +#define SC_R_DRC_0 12U +#define SC_R_DRC_1 13U +#define SC_R_GIC_SMMU 14U +#define SC_R_IRQSTR_M4_0 15U +#define SC_R_IRQSTR_M4_1 16U +#define SC_R_SMMU 17U +#define SC_R_GIC 18U +#define SC_R_DC_0_BLIT0 19U +#define SC_R_DC_0_BLIT1 20U +#define SC_R_DC_0_BLIT2 21U +#define SC_R_DC_0_BLIT_OUT 22U +#define SC_R_DC_0_CAPTURE0 23U +#define SC_R_DC_0_CAPTURE1 24U +#define SC_R_DC_0_WARP 25U +#define SC_R_DC_0_INTEGRAL0 26U +#define SC_R_DC_0_INTEGRAL1 27U +#define SC_R_DC_0_VIDEO0 28U +#define SC_R_DC_0_VIDEO1 29U +#define SC_R_DC_0_FRAC0 30U +#define SC_R_DC_0_FRAC1 31U +#define SC_R_DC_0 32U +#define SC_R_GPU_2_PID0 33U +#define SC_R_DC_0_PLL_0 34U +#define SC_R_DC_0_PLL_1 35U +#define SC_R_DC_1_BLIT0 36U +#define SC_R_DC_1_BLIT1 37U +#define SC_R_DC_1_BLIT2 38U +#define SC_R_DC_1_BLIT_OUT 39U +#define SC_R_DC_1_CAPTURE0 40U +#define SC_R_DC_1_CAPTURE1 41U +#define SC_R_DC_1_WARP 42U +#define SC_R_DC_1_INTEGRAL0 43U +#define SC_R_DC_1_INTEGRAL1 44U +#define SC_R_DC_1_VIDEO0 45U +#define SC_R_DC_1_VIDEO1 46U +#define SC_R_DC_1_FRAC0 47U +#define SC_R_DC_1_FRAC1 48U +#define SC_R_DC_1 49U +#define SC_R_GPU_3_PID0 50U +#define SC_R_DC_1_PLL_0 51U +#define SC_R_DC_1_PLL_1 52U +#define SC_R_SPI_0 53U +#define SC_R_SPI_1 54U +#define SC_R_SPI_2 55U +#define SC_R_SPI_3 56U +#define SC_R_UART_0 57U +#define SC_R_UART_1 58U +#define SC_R_UART_2 59U +#define SC_R_UART_3 60U +#define SC_R_UART_4 61U +#define SC_R_EMVSIM_0 62U +#define SC_R_EMVSIM_1 63U +#define SC_R_DMA_0_CH0 64U +#define SC_R_DMA_0_CH1 65U +#define SC_R_DMA_0_CH2 66U +#define SC_R_DMA_0_CH3 67U +#define SC_R_DMA_0_CH4 68U +#define SC_R_DMA_0_CH5 69U +#define SC_R_DMA_0_CH6 70U +#define SC_R_DMA_0_CH7 71U +#define SC_R_DMA_0_CH8 72U +#define SC_R_DMA_0_CH9 73U +#define SC_R_DMA_0_CH10 74U +#define SC_R_DMA_0_CH11 75U +#define SC_R_DMA_0_CH12 76U +#define SC_R_DMA_0_CH13 77U +#define SC_R_DMA_0_CH14 78U +#define SC_R_DMA_0_CH15 79U +#define SC_R_DMA_0_CH16 80U +#define SC_R_DMA_0_CH17 81U +#define SC_R_DMA_0_CH18 82U +#define SC_R_DMA_0_CH19 83U +#define SC_R_DMA_0_CH20 84U +#define SC_R_DMA_0_CH21 85U +#define SC_R_DMA_0_CH22 86U +#define SC_R_DMA_0_CH23 87U +#define SC_R_DMA_0_CH24 88U +#define SC_R_DMA_0_CH25 89U +#define SC_R_DMA_0_CH26 90U +#define SC_R_DMA_0_CH27 91U +#define SC_R_DMA_0_CH28 92U +#define SC_R_DMA_0_CH29 93U +#define SC_R_DMA_0_CH30 94U +#define SC_R_DMA_0_CH31 95U +#define SC_R_I2C_0 96U +#define SC_R_I2C_1 97U +#define SC_R_I2C_2 98U +#define SC_R_I2C_3 99U +#define SC_R_I2C_4 100U +#define SC_R_ADC_0 101U +#define SC_R_ADC_1 102U +#define SC_R_FTM_0 103U +#define SC_R_FTM_1 104U +#define SC_R_CAN_0 105U +#define SC_R_CAN_1 106U +#define SC_R_CAN_2 107U +#define SC_R_DMA_1_CH0 108U +#define SC_R_DMA_1_CH1 109U +#define SC_R_DMA_1_CH2 110U +#define SC_R_DMA_1_CH3 111U +#define SC_R_DMA_1_CH4 112U +#define SC_R_DMA_1_CH5 113U +#define SC_R_DMA_1_CH6 114U +#define SC_R_DMA_1_CH7 115U +#define SC_R_DMA_1_CH8 116U +#define SC_R_DMA_1_CH9 117U +#define SC_R_DMA_1_CH10 118U +#define SC_R_DMA_1_CH11 119U +#define SC_R_DMA_1_CH12 120U +#define SC_R_DMA_1_CH13 121U +#define SC_R_DMA_1_CH14 122U +#define SC_R_DMA_1_CH15 123U +#define SC_R_DMA_1_CH16 124U +#define SC_R_DMA_1_CH17 125U +#define SC_R_DMA_1_CH18 126U +#define SC_R_DMA_1_CH19 127U +#define SC_R_DMA_1_CH20 128U +#define SC_R_DMA_1_CH21 129U +#define SC_R_DMA_1_CH22 130U +#define SC_R_DMA_1_CH23 131U +#define SC_R_DMA_1_CH24 132U +#define SC_R_DMA_1_CH25 133U +#define SC_R_DMA_1_CH26 134U +#define SC_R_DMA_1_CH27 135U +#define SC_R_DMA_1_CH28 136U +#define SC_R_DMA_1_CH29 137U +#define SC_R_DMA_1_CH30 138U +#define SC_R_DMA_1_CH31 139U +#define SC_R_UNUSED1 140U +#define SC_R_UNUSED2 141U +#define SC_R_UNUSED3 142U +#define SC_R_UNUSED4 143U +#define SC_R_GPU_0_PID0 144U +#define SC_R_GPU_0_PID1 145U +#define SC_R_GPU_0_PID2 146U +#define SC_R_GPU_0_PID3 147U +#define SC_R_GPU_1_PID0 148U +#define SC_R_GPU_1_PID1 149U +#define SC_R_GPU_1_PID2 150U +#define SC_R_GPU_1_PID3 151U +#define SC_R_PCIE_A 152U +#define SC_R_SERDES_0 153U +#define SC_R_MATCH_0 154U +#define SC_R_MATCH_1 155U +#define SC_R_MATCH_2 156U +#define SC_R_MATCH_3 157U +#define SC_R_MATCH_4 158U +#define SC_R_MATCH_5 159U +#define SC_R_MATCH_6 160U +#define SC_R_MATCH_7 161U +#define SC_R_MATCH_8 162U +#define SC_R_MATCH_9 163U +#define SC_R_MATCH_10 164U +#define SC_R_MATCH_11 165U +#define SC_R_MATCH_12 166U +#define SC_R_MATCH_13 167U +#define SC_R_MATCH_14 168U +#define SC_R_PCIE_B 169U +#define SC_R_SATA_0 170U +#define SC_R_SERDES_1 171U +#define SC_R_HSIO_GPIO 172U +#define SC_R_MATCH_15 173U +#define SC_R_MATCH_16 174U +#define SC_R_MATCH_17 175U +#define SC_R_MATCH_18 176U +#define SC_R_MATCH_19 177U +#define SC_R_MATCH_20 178U +#define SC_R_MATCH_21 179U +#define SC_R_MATCH_22 180U +#define SC_R_MATCH_23 181U +#define SC_R_MATCH_24 182U +#define SC_R_MATCH_25 183U +#define SC_R_MATCH_26 184U +#define SC_R_MATCH_27 185U +#define SC_R_MATCH_28 186U +#define SC_R_LCD_0 187U +#define SC_R_LCD_0_PWM_0 188U +#define SC_R_LCD_0_I2C_0 189U +#define SC_R_LCD_0_I2C_1 190U +#define SC_R_PWM_0 191U +#define SC_R_PWM_1 192U +#define SC_R_PWM_2 193U +#define SC_R_PWM_3 194U +#define SC_R_PWM_4 195U +#define SC_R_PWM_5 196U +#define SC_R_PWM_6 197U +#define SC_R_PWM_7 198U +#define SC_R_GPIO_0 199U +#define SC_R_GPIO_1 200U +#define SC_R_GPIO_2 201U +#define SC_R_GPIO_3 202U +#define SC_R_GPIO_4 203U +#define SC_R_GPIO_5 204U +#define SC_R_GPIO_6 205U +#define SC_R_GPIO_7 206U +#define SC_R_GPT_0 207U +#define SC_R_GPT_1 208U +#define SC_R_GPT_2 209U +#define SC_R_GPT_3 210U +#define SC_R_GPT_4 211U +#define SC_R_KPP 212U +#define SC_R_MU_0A 213U +#define SC_R_MU_1A 214U +#define SC_R_MU_2A 215U +#define SC_R_MU_3A 216U +#define SC_R_MU_4A 217U +#define SC_R_MU_5A 218U +#define SC_R_MU_6A 219U +#define SC_R_MU_7A 220U +#define SC_R_MU_8A 221U +#define SC_R_MU_9A 222U +#define SC_R_MU_10A 223U +#define SC_R_MU_11A 224U +#define SC_R_MU_12A 225U +#define SC_R_MU_13A 226U +#define SC_R_MU_5B 227U +#define SC_R_MU_6B 228U +#define SC_R_MU_7B 229U +#define SC_R_MU_8B 230U +#define SC_R_MU_9B 231U +#define SC_R_MU_10B 232U +#define SC_R_MU_11B 233U +#define SC_R_MU_12B 234U +#define SC_R_MU_13B 235U +#define SC_R_ROM_0 236U +#define SC_R_FSPI_0 237U +#define SC_R_FSPI_1 238U +#define SC_R_IEE 239U +#define SC_R_IEE_R0 240U +#define SC_R_IEE_R1 241U +#define SC_R_IEE_R2 242U +#define SC_R_IEE_R3 243U +#define SC_R_IEE_R4 244U +#define SC_R_IEE_R5 245U +#define SC_R_IEE_R6 246U +#define SC_R_IEE_R7 247U +#define SC_R_SDHC_0 248U +#define SC_R_SDHC_1 249U +#define SC_R_SDHC_2 250U +#define SC_R_ENET_0 251U +#define SC_R_ENET_1 252U +#define SC_R_MLB_0 253U +#define SC_R_DMA_2_CH0 254U +#define SC_R_DMA_2_CH1 255U +#define SC_R_DMA_2_CH2 256U +#define SC_R_DMA_2_CH3 257U +#define SC_R_DMA_2_CH4 258U +#define SC_R_USB_0 259U +#define SC_R_USB_1 260U +#define SC_R_USB_0_PHY 261U +#define SC_R_USB_2 262U +#define SC_R_USB_2_PHY 263U +#define SC_R_DTCP 264U +#define SC_R_NAND 265U +#define SC_R_LVDS_0 266U +#define SC_R_LVDS_0_PWM_0 267U +#define SC_R_LVDS_0_I2C_0 268U +#define SC_R_LVDS_0_I2C_1 269U +#define SC_R_LVDS_1 270U +#define SC_R_LVDS_1_PWM_0 271U +#define SC_R_LVDS_1_I2C_0 272U +#define SC_R_LVDS_1_I2C_1 273U +#define SC_R_LVDS_2 274U +#define SC_R_LVDS_2_PWM_0 275U +#define SC_R_LVDS_2_I2C_0 276U +#define SC_R_LVDS_2_I2C_1 277U +#define SC_R_M4_0_PID0 278U +#define SC_R_M4_0_PID1 279U +#define SC_R_M4_0_PID2 280U +#define SC_R_M4_0_PID3 281U +#define SC_R_M4_0_PID4 282U +#define SC_R_M4_0_RGPIO 283U +#define SC_R_M4_0_SEMA42 284U +#define SC_R_M4_0_TPM 285U +#define SC_R_M4_0_PIT 286U +#define SC_R_M4_0_UART 287U +#define SC_R_M4_0_I2C 288U +#define SC_R_M4_0_INTMUX 289U +#define SC_R_M4_0_SIM 290U +#define SC_R_M4_0_WDOG 291U +#define SC_R_M4_0_MU_0B 292U +#define SC_R_M4_0_MU_0A0 293U +#define SC_R_M4_0_MU_0A1 294U +#define SC_R_M4_0_MU_0A2 295U +#define SC_R_M4_0_MU_0A3 296U +#define SC_R_M4_0_MU_1A 297U +#define SC_R_M4_1_PID0 298U +#define SC_R_M4_1_PID1 299U +#define SC_R_M4_1_PID2 300U +#define SC_R_M4_1_PID3 301U +#define SC_R_M4_1_PID4 302U +#define SC_R_M4_1_RGPIO 303U +#define SC_R_M4_1_SEMA42 304U +#define SC_R_M4_1_TPM 305U +#define SC_R_M4_1_PIT 306U +#define SC_R_M4_1_UART 307U +#define SC_R_M4_1_I2C 308U +#define SC_R_M4_1_INTMUX 309U +#define SC_R_M4_1_SIM 310U +#define SC_R_M4_1_WDOG 311U +#define SC_R_M4_1_MU_0B 312U +#define SC_R_M4_1_MU_0A0 313U +#define SC_R_M4_1_MU_0A1 314U +#define SC_R_M4_1_MU_0A2 315U +#define SC_R_M4_1_MU_0A3 316U +#define SC_R_M4_1_MU_1A 317U +#define SC_R_SAI_0 318U +#define SC_R_SAI_1 319U +#define SC_R_SAI_2 320U +#define SC_R_IRQSTR_SCU2 321U +#define SC_R_IRQSTR_DSP 322U +#define SC_R_UNUSED5 323U +#define SC_R_OCRAM 324U +#define SC_R_AUDIO_PLL_0 325U +#define SC_R_PI_0 326U +#define SC_R_PI_0_PWM_0 327U +#define SC_R_PI_0_PWM_1 328U +#define SC_R_PI_0_I2C_0 329U +#define SC_R_PI_0_PLL 330U +#define SC_R_PI_1 331U +#define SC_R_PI_1_PWM_0 332U +#define SC_R_PI_1_PWM_1 333U +#define SC_R_PI_1_I2C_0 334U +#define SC_R_PI_1_PLL 335U +#define SC_R_SC_PID0 336U +#define SC_R_SC_PID1 337U +#define SC_R_SC_PID2 338U +#define SC_R_SC_PID3 339U +#define SC_R_SC_PID4 340U +#define SC_R_SC_SEMA42 341U +#define SC_R_SC_TPM 342U +#define SC_R_SC_PIT 343U +#define SC_R_SC_UART 344U +#define SC_R_SC_I2C 345U +#define SC_R_SC_MU_0B 346U +#define SC_R_SC_MU_0A0 347U +#define SC_R_SC_MU_0A1 348U +#define SC_R_SC_MU_0A2 349U +#define SC_R_SC_MU_0A3 350U +#define SC_R_SC_MU_1A 351U +#define SC_R_SYSCNT_RD 352U +#define SC_R_SYSCNT_CMP 353U +#define SC_R_DEBUG 354U +#define SC_R_SYSTEM 355U +#define SC_R_SNVS 356U +#define SC_R_OTP 357U +#define SC_R_VPU_PID0 358U +#define SC_R_VPU_PID1 359U +#define SC_R_VPU_PID2 360U +#define SC_R_VPU_PID3 361U +#define SC_R_VPU_PID4 362U +#define SC_R_VPU_PID5 363U +#define SC_R_VPU_PID6 364U +#define SC_R_VPU_PID7 365U +#define SC_R_VPU_UART 366U +#define SC_R_VPUCORE 367U +#define SC_R_VPUCORE_0 368U +#define SC_R_VPUCORE_1 369U +#define SC_R_VPUCORE_2 370U +#define SC_R_VPUCORE_3 371U +#define SC_R_DMA_4_CH0 372U +#define SC_R_DMA_4_CH1 373U +#define SC_R_DMA_4_CH2 374U +#define SC_R_DMA_4_CH3 375U +#define SC_R_DMA_4_CH4 376U +#define SC_R_ISI_CH0 377U +#define SC_R_ISI_CH1 378U +#define SC_R_ISI_CH2 379U +#define SC_R_ISI_CH3 380U +#define SC_R_ISI_CH4 381U +#define SC_R_ISI_CH5 382U +#define SC_R_ISI_CH6 383U +#define SC_R_ISI_CH7 384U +#define SC_R_MJPEG_DEC_S0 385U +#define SC_R_MJPEG_DEC_S1 386U +#define SC_R_MJPEG_DEC_S2 387U +#define SC_R_MJPEG_DEC_S3 388U +#define SC_R_MJPEG_ENC_S0 389U +#define SC_R_MJPEG_ENC_S1 390U +#define SC_R_MJPEG_ENC_S2 391U +#define SC_R_MJPEG_ENC_S3 392U +#define SC_R_MIPI_0 393U +#define SC_R_MIPI_0_PWM_0 394U +#define SC_R_MIPI_0_I2C_0 395U +#define SC_R_MIPI_0_I2C_1 396U +#define SC_R_MIPI_1 397U +#define SC_R_MIPI_1_PWM_0 398U +#define SC_R_MIPI_1_I2C_0 399U +#define SC_R_MIPI_1_I2C_1 400U +#define SC_R_CSI_0 401U +#define SC_R_CSI_0_PWM_0 402U +#define SC_R_CSI_0_I2C_0 403U +#define SC_R_CSI_1 404U +#define SC_R_CSI_1_PWM_0 405U +#define SC_R_CSI_1_I2C_0 406U +#define SC_R_HDMI 407U +#define SC_R_HDMI_I2S 408U +#define SC_R_HDMI_I2C_0 409U +#define SC_R_HDMI_PLL_0 410U +#define SC_R_HDMI_RX 411U +#define SC_R_HDMI_RX_BYPASS 412U +#define SC_R_HDMI_RX_I2C_0 413U +#define SC_R_ASRC_0 414U +#define SC_R_ESAI_0 415U +#define SC_R_SPDIF_0 416U +#define SC_R_SPDIF_1 417U +#define SC_R_SAI_3 418U +#define SC_R_SAI_4 419U +#define SC_R_SAI_5 420U +#define SC_R_GPT_5 421U +#define SC_R_GPT_6 422U +#define SC_R_GPT_7 423U +#define SC_R_GPT_8 424U +#define SC_R_GPT_9 425U +#define SC_R_GPT_10 426U +#define SC_R_DMA_2_CH5 427U +#define SC_R_DMA_2_CH6 428U +#define SC_R_DMA_2_CH7 429U +#define SC_R_DMA_2_CH8 430U +#define SC_R_DMA_2_CH9 431U +#define SC_R_DMA_2_CH10 432U +#define SC_R_DMA_2_CH11 433U +#define SC_R_DMA_2_CH12 434U +#define SC_R_DMA_2_CH13 435U +#define SC_R_DMA_2_CH14 436U +#define SC_R_DMA_2_CH15 437U +#define SC_R_DMA_2_CH16 438U +#define SC_R_DMA_2_CH17 439U +#define SC_R_DMA_2_CH18 440U +#define SC_R_DMA_2_CH19 441U +#define SC_R_DMA_2_CH20 442U +#define SC_R_DMA_2_CH21 443U +#define SC_R_DMA_2_CH22 444U +#define SC_R_DMA_2_CH23 445U +#define SC_R_DMA_2_CH24 446U +#define SC_R_DMA_2_CH25 447U +#define SC_R_DMA_2_CH26 448U +#define SC_R_DMA_2_CH27 449U +#define SC_R_DMA_2_CH28 450U +#define SC_R_DMA_2_CH29 451U +#define SC_R_DMA_2_CH30 452U +#define SC_R_DMA_2_CH31 453U +#define SC_R_ASRC_1 454U +#define SC_R_ESAI_1 455U +#define SC_R_SAI_6 456U +#define SC_R_SAI_7 457U +#define SC_R_AMIX 458U +#define SC_R_MQS_0 459U +#define SC_R_DMA_3_CH0 460U +#define SC_R_DMA_3_CH1 461U +#define SC_R_DMA_3_CH2 462U +#define SC_R_DMA_3_CH3 463U +#define SC_R_DMA_3_CH4 464U +#define SC_R_DMA_3_CH5 465U +#define SC_R_DMA_3_CH6 466U +#define SC_R_DMA_3_CH7 467U +#define SC_R_DMA_3_CH8 468U +#define SC_R_DMA_3_CH9 469U +#define SC_R_DMA_3_CH10 470U +#define SC_R_DMA_3_CH11 471U +#define SC_R_DMA_3_CH12 472U +#define SC_R_DMA_3_CH13 473U +#define SC_R_DMA_3_CH14 474U +#define SC_R_DMA_3_CH15 475U +#define SC_R_DMA_3_CH16 476U +#define SC_R_DMA_3_CH17 477U +#define SC_R_DMA_3_CH18 478U +#define SC_R_DMA_3_CH19 479U +#define SC_R_DMA_3_CH20 480U +#define SC_R_DMA_3_CH21 481U +#define SC_R_DMA_3_CH22 482U +#define SC_R_DMA_3_CH23 483U +#define SC_R_DMA_3_CH24 484U +#define SC_R_DMA_3_CH25 485U +#define SC_R_DMA_3_CH26 486U +#define SC_R_DMA_3_CH27 487U +#define SC_R_DMA_3_CH28 488U +#define SC_R_DMA_3_CH29 489U +#define SC_R_DMA_3_CH30 490U +#define SC_R_DMA_3_CH31 491U +#define SC_R_AUDIO_PLL_1 492U +#define SC_R_AUDIO_CLK_0 493U +#define SC_R_AUDIO_CLK_1 494U +#define SC_R_MCLK_OUT_0 495U +#define SC_R_MCLK_OUT_1 496U +#define SC_R_PMIC_0 497U +#define SC_R_PMIC_1 498U +#define SC_R_SECO 499U +#define SC_R_CAAM_JR1 500U +#define SC_R_CAAM_JR2 501U +#define SC_R_CAAM_JR3 502U +#define SC_R_SECO_MU_2 503U +#define SC_R_SECO_MU_3 504U +#define SC_R_SECO_MU_4 505U +#define SC_R_HDMI_RX_PWM_0 506U +#define SC_R_A35 507U +#define SC_R_A35_0 508U +#define SC_R_A35_1 509U +#define SC_R_A35_2 510U +#define SC_R_A35_3 511U +#define SC_R_DSP 512U +#define SC_R_DSP_RAM 513U +#define SC_R_CAAM_JR1_OUT 514U +#define SC_R_CAAM_JR2_OUT 515U +#define SC_R_CAAM_JR3_OUT 516U +#define SC_R_VPU_DEC_0 517U +#define SC_R_VPU_ENC_0 518U +#define SC_R_CAAM_JR0 519U +#define SC_R_CAAM_JR0_OUT 520U +#define SC_R_PMIC_2 521U +#define SC_R_DBLOGIC 522U +#define SC_R_HDMI_PLL_1 523U +#define SC_R_BOARD_R0 524U +#define SC_R_BOARD_R1 525U +#define SC_R_BOARD_R2 526U +#define SC_R_BOARD_R3 527U +#define SC_R_BOARD_R4 528U +#define SC_R_BOARD_R5 529U +#define SC_R_BOARD_R6 530U +#define SC_R_BOARD_R7 531U +#define SC_R_MJPEG_DEC_MP 532U +#define SC_R_MJPEG_ENC_MP 533U +#define SC_R_VPU_TS_0 534U +#define SC_R_VPU_MU_0 535U +#define SC_R_VPU_MU_1 536U +#define SC_R_VPU_MU_2 537U +#define SC_R_VPU_MU_3 538U +#define SC_R_VPU_ENC_1 539U +#define SC_R_VPU 540U +#define SC_R_LAST 541U +#define SC_R_ALL ((sc_rsrc_t) UINT16_MAX) /* All resources */ +/*@}*/ + +/* NOTE - please add by replacing some of the UNUSED from above! */ + +/*! + * Defnes for sc_ctrl_t. + */ +#define SC_C_TEMP 0U +#define SC_C_TEMP_HI 1U +#define SC_C_TEMP_LOW 2U +#define SC_C_PXL_LINK_MST1_ADDR 3U +#define SC_C_PXL_LINK_MST2_ADDR 4U +#define SC_C_PXL_LINK_MST_ENB 5U +#define SC_C_PXL_LINK_MST1_ENB 6U +#define SC_C_PXL_LINK_MST2_ENB 7U +#define SC_C_PXL_LINK_SLV1_ADDR 8U +#define SC_C_PXL_LINK_SLV2_ADDR 9U +#define SC_C_PXL_LINK_MST_VLD 10U +#define SC_C_PXL_LINK_MST1_VLD 11U +#define SC_C_PXL_LINK_MST2_VLD 12U +#define SC_C_SINGLE_MODE 13U +#define SC_C_ID 14U +#define SC_C_PXL_CLK_POLARITY 15U +#define SC_C_LINESTATE 16U +#define SC_C_PCIE_G_RST 17U +#define SC_C_PCIE_BUTTON_RST 18U +#define SC_C_PCIE_PERST 19U +#define SC_C_PHY_RESET 20U +#define SC_C_PXL_LINK_RATE_CORRECTION 21U +#define SC_C_PANIC 22U +#define SC_C_PRIORITY_GROUP 23U +#define SC_C_TXCLK 24U +#define SC_C_CLKDIV 25U +#define SC_C_DISABLE_50 26U +#define SC_C_DISABLE_125 27U +#define SC_C_SEL_125 28U +#define SC_C_MODE 29U +#define SC_C_SYNC_CTRL0 30U +#define SC_C_KACHUNK_CNT 31U +#define SC_C_KACHUNK_SEL 32U +#define SC_C_SYNC_CTRL1 33U +#define SC_C_DPI_RESET 34U +#define SC_C_MIPI_RESET 35U +#define SC_C_DUAL_MODE 36U +#define SC_C_VOLTAGE 37U +#define SC_C_PXL_LINK_SEL 38U +#define SC_C_OFS_SEL 39U +#define SC_C_OFS_AUDIO 40U +#define SC_C_OFS_PERIPH 41U +#define SC_C_OFS_IRQ 42U +#define SC_C_RST0 43U +#define SC_C_RST1 44U +#define SC_C_SEL0 45U +#define SC_C_LAST 46U + +#define SC_P_ALL ((sc_pad_t) UINT16_MAX) /* All pads */ + +/* Types */ + +/*! + * This type is used to store a boolean + */ +typedef uint8_t sc_bool_t; + +/*! + * This type is used to store a system (full-size) address. + */ +typedef uint64_t sc_faddr_t; + +/*! + * This type is used to indicate error response for most functions. + */ +typedef uint8_t sc_err_t; + +/*! + * This type is used to indicate a resource. Resources include peripherals + * and bus masters (but not memory regions). Note items from list should + * never be changed or removed (only added to at the end of the list). + */ +typedef uint16_t sc_rsrc_t; + +/*! + * This type is used to indicate a control. + */ +typedef uint8_t sc_ctrl_t; + +/*! + * This type is used to indicate a pad. Valid values are SoC specific. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +typedef uint16_t sc_pad_t; + +/* Extra documentation of standard types */ + +#ifdef DOXYGEN + /*! + * Type used to declare an 8-bit integer. + */ +typedef __INT8_TYPE__ int8_t; + + /*! + * Type used to declare a 16-bit integer. + */ +typedef __INT16_TYPE__ int16_t; + + /*! + * Type used to declare a 32-bit integer. + */ +typedef __INT32_TYPE__ int32_t; + + /*! + * Type used to declare a 64-bit integer. + */ +typedef __INT64_TYPE__ int64_t; + + /*! + * Type used to declare an 8-bit unsigned integer. + */ +typedef __UINT8_TYPE__ uint8_t; + + /*! + * Type used to declare a 16-bit unsigned integer. + */ +typedef __UINT16_TYPE__ uint16_t; + + /*! + * Type used to declare a 32-bit unsigned integer. + */ +typedef __UINT32_TYPE__ uint32_t; + + /*! + * Type used to declare a 64-bit unsigned integer. + */ +typedef __UINT64_TYPE__ uint64_t; +#endif + +#endif /* SC_TYPES_H */ diff --git a/plat/imx/common/include/sci/svc/pad/sci_pad_api.h b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h new file mode 100644 index 000000000..0955678ba --- /dev/null +++ b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Pad Control (PAD) function. + * + * @addtogroup PAD_SVC (SVC) Pad Service + * + * Module for the Pad Control (PAD) service. + * + * @details + * + * Pad configuration is managed by SC firmware. The pad configuration + * features supported by the SC firmware include: + * + * - Configuring the mux, input/output connection, and low-power isolation + mode. + * - Configuring the technology-specific pad setting such as drive strength, + * pullup/pulldown, etc. + * - Configuring compensation for pad groups with dual voltage capability. + * + * Pad functions fall into one of three categories. Generic functions are + * common to all SoCs and all process technologies. SoC functions are raw + * low-level functions. Technology-specific functions are specific to the + * process technology. + * + * The list of pads is SoC specific. Refer to the SoC [Pad List](@ref PADS) + * for valid pad values. Note that all pads exist on a die but may or + * may not be brought out by the specific package. Mapping of pads to + * package pins/balls is documented in the associated Data Sheet. Some pads + * may not be brought out because the part (die+package) is defeatured and + * some pads may connect to the substrate in the package. + * + * Some pads (SC_P_COMP_*) that can be specified are not individual pads + * but are in fact pad groups. These groups have additional configuration + * that can be done using the sc_pad_set_gp_28fdsoi_comp() function. More + * info on these can be found in the associated Reference Manual. + * + * Pads are managed as a resource by the Resource Manager (RM). They have + * assigned owners and only the owners can configure the pads. Some of the + * pads are reserved for use by the SCFW itself and this can be overriden + * with the implementation of board_config_sc(). Additionally, pads may + * be assigned to various other partitions via the implementation of + * board_system_config(). + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * @{ + */ + +#ifndef SC_PAD_API_H +#define SC_PAD_API_H + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/svc/rm/sci_rm_api.h> + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_PAD_MUX_W 3 /* Width of mux parameter */ +/*@}*/ + +/*! + * @name Defines for sc_pad_config_t + */ +/*@{*/ +#define SC_PAD_CONFIG_NORMAL 0U /* Normal */ +#define SC_PAD_CONFIG_OD 1U /* Open Drain */ +#define SC_PAD_CONFIG_OD_IN 2U /* Open Drain and input */ +#define SC_PAD_CONFIG_OUT_IN 3U /* Output and input */ +/*@}*/ + +/*! + * @name Defines for sc_pad_iso_t + */ +/*@{*/ +#define SC_PAD_ISO_OFF 0U /* ISO latch is transparent */ +#define SC_PAD_ISO_EARLY 1U /* Follow EARLY_ISO */ +#define SC_PAD_ISO_LATE 2U /* Follow LATE_ISO */ +#define SC_PAD_ISO_ON 3U /* ISO latched data is held */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_dse_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_DSE_18V_1MA 0U /* Drive strength of 1mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_2MA 1U /* Drive strength of 2mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_4MA 2U /* Drive strength of 4mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_6MA 3U /* Drive strength of 6mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_8MA 4U /* Drive strength of 8mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_10MA 5U /* Drive strength of 10mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_12MA 6U /* Drive strength of 12mA for 1.8v */ +#define SC_PAD_28FDSOI_DSE_18V_HS 7U /* High-speed drive strength for 1.8v */ +#define SC_PAD_28FDSOI_DSE_33V_2MA 0U /* Drive strength of 2mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_4MA 1U /* Drive strength of 4mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_8MA 2U /* Drive strength of 8mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_33V_12MA 3U /* Drive strength of 12mA for 3.3v */ +#define SC_PAD_28FDSOI_DSE_DV_HIGH 0U /* High drive strength for dual volt */ +#define SC_PAD_28FDSOI_DSE_DV_LOW 1U /* Low drive strength for dual volt */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_ps_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_PS_KEEPER 0U /* Bus-keeper (only valid for 1.8v) */ +#define SC_PAD_28FDSOI_PS_PU 1U /* Pull-up */ +#define SC_PAD_28FDSOI_PS_PD 2U /* Pull-down */ +#define SC_PAD_28FDSOI_PS_NONE 3U /* No pull (disabled) */ +/*@}*/ + +/*! + * @name Defines for sc_pad_28fdsoi_pus_t + */ +/*@{*/ +#define SC_PAD_28FDSOI_PUS_30K_PD 0U /* 30K pull-down */ +#define SC_PAD_28FDSOI_PUS_100K_PU 1U /* 100K pull-up */ +#define SC_PAD_28FDSOI_PUS_3K_PU 2U /* 3K pull-up */ +#define SC_PAD_28FDSOI_PUS_30K_PU 3U /* 30K pull-up */ +/*@}*/ + +/*! + * @name Defines for sc_pad_wakeup_t + */ +/*@{*/ +#define SC_PAD_WAKEUP_OFF 0U /* Off */ +#define SC_PAD_WAKEUP_CLEAR 1U /* Clears pending flag */ +#define SC_PAD_WAKEUP_LOW_LVL 4U /* Low level */ +#define SC_PAD_WAKEUP_FALL_EDGE 5U /* Falling edge */ +#define SC_PAD_WAKEUP_RISE_EDGE 6U /* Rising edge */ +#define SC_PAD_WAKEUP_HIGH_LVL 7U /* High-level */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a pad config. It determines how the + * output data is driven, pull-up is controlled, and input signal is + * connected. Normal and OD are typical and only connect the input + * when the output is not driven. The IN options are less common and + * force an input connection even when driving the output. + */ +typedef uint8_t sc_pad_config_t; + +/*! + * This type is used to declare a pad low-power isolation config. + * ISO_LATE is the most common setting. ISO_EARLY is only used when + * an output pad is directly determined by another input pad. The + * other two are only used when SW wants to directly contol isolation. + */ +typedef uint8_t sc_pad_iso_t; + +/*! + * This type is used to declare a drive strength. Note it is specific + * to 28FDSOI. Also note that valid values depend on the pad type. + */ +typedef uint8_t sc_pad_28fdsoi_dse_t; + +/*! + * This type is used to declare a pull select. Note it is specific + * to 28FDSOI. + */ +typedef uint8_t sc_pad_28fdsoi_ps_t; + +/*! + * This type is used to declare a pull-up select. Note it is specific + * to 28FDSOI HSIC pads. + */ +typedef uint8_t sc_pad_28fdsoi_pus_t; + +/*! + * This type is used to declare a wakeup mode of a pad. + */ +typedef uint8_t sc_pad_wakeup_t; + +/* Functions */ + +/*! + * @name Generic Functions + * @{ + */ + +/*! + * This function configures the mux settings for a pad. This includes + * the signal mux, pad config, and low-power isolation mode. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] mux mux setting + * @param[in] config pad config + * @param[in] iso low-power isolation mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso); + +/*! + * This function gets the mux settings for a pad. This includes + * the signal mux, pad config, and low-power isolation mode. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] mux pointer to return mux setting + * @param[out] config pointer to return pad config + * @param[out] iso pointer to return low-power isolation mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *mux, sc_pad_config_t *config, + sc_pad_iso_t *iso); + +/*! + * This function configures the general purpose pad control. This + * is technology dependent and includes things like drive strength, + * slew rate, pull up/down, etc. Refer to the SoC Reference Manual + * for bit field details. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] ctrl control value to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl); + +/*! + * This function gets the general purpose pad control. This + * is technology dependent and includes things like drive strength, + * slew rate, pull up/down, etc. Refer to the SoC Reference Manual + * for bit field details. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] ctrl pointer to return control value + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl); + +/*! + * This function configures the wakeup mode of the pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] wakeup wakeup to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup); + +/*! + * This function gets the wakeup mode of a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] wakeup pointer to return wakeup + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup); + +/*! + * This function configures a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] mux mux setting + * @param[in] config pad config + * @param[in] iso low-power isolation mode + * @param[in] ctrl control value + * @param[in] wakeup wakeup to set + * + * @see sc_pad_set_mux(). + * @see sc_pad_set_gp(). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Note muxing two input pads to the same IP functional signal will + * result in undefined behavior. + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux, + sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl, + sc_pad_wakeup_t wakeup); + +/*! + * This function gets a pad's config. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] mux pointer to return mux setting + * @param[out] config pointer to return pad config + * @param[out] iso pointer to return low-power isolation mode + * @param[out] ctrl pointer to return control value + * @param[out] wakeup pointer to return wakeup to set + * + * @see sc_pad_set_mux(). + * @see sc_pad_set_gp(). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux, + sc_pad_config_t *config, sc_pad_iso_t *iso, + uint32_t *ctrl, sc_pad_wakeup_t *wakeup); + +/* @} */ + +/*! + * @name SoC Specific Functions + * @{ + */ + +/*! + * This function configures the settings for a pad. This setting is SoC + * specific. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] val value to set + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val); + +/*! + * This function gets the settings for a pad. This setting is SoC + * specific. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] val pointer to return setting + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val); + +/* @} */ + +/*! + * @name Technology Specific Functions + * @{ + */ + +/*! + * This function configures the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] dse drive strength + * @param[in] ps pull select + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, + sc_pad_28fdsoi_ps_t ps); + +/*! + * This function gets the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] dse pointer to return drive strength + * @param[out] ps pointer to return pull select + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, + sc_pad_28fdsoi_ps_t *ps); + +/*! + * This function configures the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] dse drive strength + * @param[in] hys hysteresis + * @param[in] pus pull-up select + * @param[in] pke pull keeper enable + * @param[in] pue pull-up enable + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_bool_t hys, + sc_pad_28fdsoi_pus_t pus, sc_bool_t pke, + sc_bool_t pue); + +/*! + * This function gets the pad control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] dse pointer to return drive strength + * @param[out] hys pointer to return hysteresis + * @param[out] pus pointer to return pull-up select + * @param[out] pke pointer to return pull keeper enable + * @param[out] pue pointer to return pull-up enable + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys, + sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke, + sc_bool_t *pue); + +/*! + * This function configures the compensation control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to configure + * @param[in] compen compensation/freeze mode + * @param[in] fastfrz fast freeze + * @param[in] rasrcp compensation code for PMOS + * @param[in] rasrcn compensation code for NMOS + * @param[in] nasrc_sel NASRC read select + * @param[in] psw_ovr 2.5v override + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + * + * Note \a psw_ovr is only applicable to pads supporting 2.5 volt + * operation (e.g. some Ethernet pads). + */ +sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t compen, sc_bool_t fastfrz, + uint8_t rasrcp, uint8_t rasrcn, + sc_bool_t nasrc_sel, sc_bool_t psw_ovr); + +/*! + * This function gets the compensation control specific to 28FDSOI. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to query + * @param[out] compen pointer to return compensation/freeze mode + * @param[out] fastfrz pointer to return fast freeze + * @param[out] rasrcp pointer to return compensation code for PMOS + * @param[out] rasrcn pointer to return compensation code for NMOS + * @param[out] nasrc_sel pointer to return NASRC read select + * @param[out] compok pointer to return compensation status + * @param[out] nasrc pointer to return NASRCP/NASRCN + * @param[out] psw_ovr pointer to return the 2.5v override + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner, + * - SC_ERR_UNAVAILABLE if process not applicable + * + * Refer to the SoC [Pad List](@ref PADS) for valid pad values. + */ +sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *compen, sc_bool_t *fastfrz, + uint8_t *rasrcp, uint8_t *rasrcn, + sc_bool_t *nasrc_sel, sc_bool_t *compok, + uint8_t *nasrc, sc_bool_t *psw_ovr); + +/* @} */ + +#endif /* SC_PAD_API_H */ + +/**@}*/ diff --git a/plat/imx/common/include/sci/svc/pm/sci_pm_api.h b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h new file mode 100644 index 000000000..5c3c3821d --- /dev/null +++ b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Power Management (PM) function. This includes functions for power state + * control, clock control, reset control, and wake-up event control. + * + * @addtogroup PM_SVC (SVC) Power Management Service + * + * Module for the Power Management (PM) service. + * + * @{ + */ + +#ifndef SC_PM_API_H +#define SC_PM_API_H + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/svc/rm/sci_rm_api.h> + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_PM_POWER_MODE_W 2 /* Width of sc_pm_power_mode_t */ +#define SC_PM_CLOCK_MODE_W 3 /* Width of sc_pm_clock_mode_t */ +#define SC_PM_RESET_TYPE_W 2 /* Width of sc_pm_reset_type_t */ +#define SC_PM_RESET_REASON_W 3 /* Width of sc_pm_reset_reason_t */ +/*@}*/ + +/*! + * @name Defines for clock indexes (sc_pm_clk_t) + */ +/*@{*/ +/*@}*/ + +/*! + * @name Defines for ALL parameters + */ +/*@{*/ +#define SC_PM_CLK_ALL UINT8_MAX /* All clocks */ +/*@}*/ + +/*! + * @name Defines for sc_pm_power_mode_t + */ +/*@{*/ +#define SC_PM_PW_MODE_OFF 0U /* Power off */ +#define SC_PM_PW_MODE_STBY 1U /* Power in standby */ +#define SC_PM_PW_MODE_LP 2U /* Power in low-power */ +#define SC_PM_PW_MODE_ON 3U /* Power on */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_t + */ +/*@{*/ +#define SC_PM_CLK_SLV_BUS 0U /* Slave bus clock */ +#define SC_PM_CLK_MST_BUS 1U /* Master bus clock */ +#define SC_PM_CLK_PER 2U /* Peripheral clock */ +#define SC_PM_CLK_PHY 3U /* Phy clock */ +#define SC_PM_CLK_MISC 4U /* Misc clock */ +#define SC_PM_CLK_MISC0 0U /* Misc 0 clock */ +#define SC_PM_CLK_MISC1 1U /* Misc 1 clock */ +#define SC_PM_CLK_MISC2 2U /* Misc 2 clock */ +#define SC_PM_CLK_MISC3 3U /* Misc 3 clock */ +#define SC_PM_CLK_MISC4 4U /* Misc 4 clock */ +#define SC_PM_CLK_CPU 2U /* CPU clock */ +#define SC_PM_CLK_PLL 4U /* PLL */ +#define SC_PM_CLK_BYPASS 4U /* Bypass clock */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_mode_t + */ +/*@{*/ +#define SC_PM_CLK_MODE_ROM_INIT 0U /* Clock is initialized by ROM. */ +#define SC_PM_CLK_MODE_OFF 1U /* Clock is disabled */ +#define SC_PM_CLK_MODE_ON 2U /* Clock is enabled. */ +#define SC_PM_CLK_MODE_AUTOGATE_SW 3U /* Clock is in SW autogate mode */ +#define SC_PM_CLK_MODE_AUTOGATE_HW 4U /* Clock is in HW autogate mode */ +#define SC_PM_CLK_MODE_AUTOGATE_SW_HW 5U /* Clock is in SW-HW autogate mode */ +/*@}*/ + +/*! + * @name Defines for sc_pm_clk_parent_t + */ +/*@{*/ +#define SC_PM_PARENT_XTAL 0U /* Parent is XTAL. */ +#define SC_PM_PARENT_PLL0 1U /* Parent is PLL0 */ +#define SC_PM_PARENT_PLL1 2U /* Parent is PLL1 or PLL0/2 */ +#define SC_PM_PARENT_PLL2 3U /* Parent in PLL2 or PLL0/4 */ +#define SC_PM_PARENT_BYPS 4U /* Parent is a bypass clock. */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_type_t + */ +/*@{*/ +#define SC_PM_RESET_TYPE_COLD 0U /* Cold reset */ +#define SC_PM_RESET_TYPE_WARM 1U /* Warm reset */ +#define SC_PM_RESET_TYPE_BOARD 2U /* Board reset */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_cause_t + */ +/*@{*/ +#define SC_PM_RESET_CAUSE_TEMP 0U /* Reset due to temp panic alarm */ +#define SC_PM_RESET_CAUSE_FAULT 1U /* Reset due to fault exception */ +#define SC_PM_RESET_CAUSE_IRQ 2U /* Reset due to SCU reset IRQ */ +#define SC_PM_RESET_CAUSE_WDOG 3U /* Reset due to SW WDOG */ +#define SC_PM_RESET_CAUSE_API 4U /* Reset due to pm_reset() or monitor */ +/*@}*/ + +/*! + * @name Defines for sc_pm_reset_reason_t + */ +/*@{*/ +#define SC_PM_RESET_REASON_POR 0U /* Power on reset */ +#define SC_PM_RESET_REASON_WARM 1U /* Warm reset */ +#define SC_PM_RESET_REASON_SW 2U /* Software reset */ +#define SC_PM_RESET_REASON_WDOG 3U /* Watchdog reset */ +#define SC_PM_RESET_REASON_LOCKUP 4U /* Lockup reset */ +#define SC_PM_RESET_REASON_TAMPER 5U /* Tamper reset */ +#define SC_PM_RESET_REASON_TEMP 6U /* Temp reset */ +#define SC_PM_RESET_REASON_LOW_VOLT 7U /* Low voltage reset */ +/*@}*/ + +/*! + * @name Defines for sc_pm_sys_if_t + */ +/*@{*/ +#define SC_PM_SYS_IF_INTERCONNECT 0U /* System interconnect */ +#define SC_PM_SYS_IF_MU 1U /* AP -> SCU message units */ +#define SC_PM_SYS_IF_OCMEM 2U /* On-chip memory (ROM/OCRAM) */ +#define SC_PM_SYS_IF_DDR 3U /* DDR memory */ +/*@}*/ + +/*! + * @name Defines for sc_pm_wake_src_t + */ +/*@{*/ +#define SC_PM_WAKE_SRC_NONE 0U /* No wake source, used for self-kill */ +#define SC_PM_WAKE_SRC_SCU 1U /* Wakeup from SCU to resume CPU (IRQSTEER & GIC powered down) */ +#define SC_PM_WAKE_SRC_IRQSTEER 2U /* Wakeup from IRQSTEER to resume CPU (GIC powered down) */ +#define SC_PM_WAKE_SRC_IRQSTEER_GIC 3U /* Wakeup from IRQSTEER+GIC to wake CPU (GIC clock gated) */ +#define SC_PM_WAKE_SRC_GIC 4U /* Wakeup from GIC to wake CPU */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a power mode. Note resources only use + * SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON. The other modes are used only + * as system power modes. + */ +typedef uint8_t sc_pm_power_mode_t; + +/*! + * This type is used to declare a clock. + */ +typedef uint8_t sc_pm_clk_t; + +/*! + * This type is used to declare a clock mode. + */ +typedef uint8_t sc_pm_clk_mode_t; + +/*! + * This type is used to declare the clock parent. + */ +typedef uint8_t sc_pm_clk_parent_t; + +/*! + * This type is used to declare clock rates. + */ +typedef uint32_t sc_pm_clock_rate_t; + +/*! + * This type is used to declare a desired reset type. + */ +typedef uint8_t sc_pm_reset_type_t; + +/*! + * This type is used to declare a desired reset type. + */ +typedef uint8_t sc_pm_reset_cause; + +/*! + * This type is used to declare a reason for a reset. + */ +typedef uint8_t sc_pm_reset_reason_t; + +/*! + * This type is used to specify a system-level interface to be power managed. + */ +typedef uint8_t sc_pm_sys_if_t; + +/*! + * This type is used to specify a wake source for CPU resources. + */ +typedef uint8_t sc_pm_wake_src_t; + +/* Functions */ + +/*! + * @name Power Functions + * @{ + */ + +/*! + * This function sets the system power mode. Only the owner of the + * SC_R_SYSTEM resource can do this. + * + * @param[in] ipc IPC handle + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid mode, + * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM + * + * @see sc_pm_set_sys_power_mode(). + */ +sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode); + +/*! + * This function sets the power mode of a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition or mode, + * - SC_ERR_NOACCESS if caller's partition is not the owner or + * parent of \a pt + * + * The power mode of the partitions is a max power any resource will + * be set to. Calling this will result in all resources owned + * by \a pt to have their power changed to the lower of \a mode or the + * individual resource mode set using sc_pm_set_resource_power_mode(). + */ +sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t mode); + +/*! + * This function gets the power mode of a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition + * @param[out] mode pointer to return power mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition + */ +sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t *mode); + +/*! + * This function sets the power mode of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or mode, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner + * + * This function will record the individual resource power mode + * and change it if the requested mode is lower than or equal to the + * partition power mode set with sc_pm_set_partition_power_mode(). + * In other words, the power mode of the resource will be the minimum + * of the resource power mode and the partition power mode. + * + * Note some resources are still not accessible even when powered up if bus + * transactions go through a fabric not powered up. Examples of this are + * resources in display and capture subsystems which require the display + * controller or the imaging subsytem to be powered up first. + * + * Not that resources are grouped into power domains by the underlying + * hardware. If any resource in the domain is on, the entire power domain + * will be on. Other power domains required to access the resource will + * also be turned on. Clocks required to access the peripheral will be + * turned on. Refer to the SoC RM for more info on power domains and access + * infrastructure (bus fabrics, clock domains, etc.). + */ +sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode); + +/*! + * This function gets the power mode of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[out] mode pointer to return power mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Note only SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON are valid. The value + * returned does not reflect the power mode of the partition.. + */ +sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode); + +/*! + * This function requests the low power mode some of the resources + * can enter based on their state. This API is only valid for the + * following resources : SC_R_A53, SC_R_A53_0, SC_R_A53_1, SC_A53_2, + * SC_A53_3, SC_R_A72, SC_R_A72_0, SC_R_A72_1, SC_R_CC1, SC_R_A35, + * SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3. + * For all other resources it will return SC_ERR_PARAM. + * This function will set the low power mode the cores, cluster + * and cluster associated resources will enter when all the cores + * in a given cluster execute WFI + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode); + +/*! + * This function requests low-power mode entry for CPU/cluster + * resources. This API is only valid for the following resources: + * SC_R_A53, SC_R_A53_x, SC_R_A72, SC_R_A72_x, SC_R_A35, SC_R_A35_x, + * SC_R_CCI. For all other resources it will return SC_ERR_PARAM. + * For individual core resources, the specified power mode + * and wake source will be applied after the core has entered + * WFI. For cluster resources, the specified power mode is + * applied after all cores in the cluster have entered low-power mode. + * For multicluster resources, the specified power mode is applied + * after all clusters have reached low-power mode. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] mode power mode to apply + * @param[in] wake_src wake source for low-power exit + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode, + sc_pm_wake_src_t wake_src); + +/*! + * This function is used to set the resume address of a CPU. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] address 64-bit resume address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource, + sc_faddr_t address); + +/*! + * This function is used to set parameters for CPU resume from + * low-power mode. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] isPrimary set SC_TRUE if primary wake CPU + * @param[in] address 64-bit resume address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t isPrimary, sc_faddr_t address); + +/*! + * This function requests the power mode configuration for system-level + * interfaces including messaging units, interconnect, and memories. This API + * is only valid for the following resources : SC_R_A53, SC_R_A72, and + * SC_R_M4_x_PID_y. For all other resources, it will return SC_ERR_PARAM. + * The requested power mode will be captured and applied to system-level + * resources as system conditions allow. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] sys_if system-level interface to be configured + * @param[in] hpm high-power mode for the system interface + * @param[in] lpm low-power mode for the system interface + * + * @return Returns an error code (SC_ERR_NONE = success). + * + */ +sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_sys_if_t sys_if, + sc_pm_power_mode_t hpm, + sc_pm_power_mode_t lpm); + +/* @} */ + +/*! + * @name Clock/PLL Functions + * @{ + */ + +/*! + * This function sets the rate of a resource's clock/PLL. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock/PLL to affect + * @param[in,out] rate pointer to rate to set, + * return actual rate + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock/PLL, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource, + * - SC_ERR_LOCKED if rate locked (usually because shared clock/PLL) + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values. + */ +sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate); + +/*! + * This function gets the rate of a resource's clock/PLL. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock/PLL to affect + * @param[out] rate pointer to return rate + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock/PLL, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values. + */ +sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate); + +/*! + * This function enables/disables a resource's clock. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[in] enable enable if SC_TRUE; otherwise disabled + * @param[in] autog HW auto clock gating + * + * If \a resource is SC_R_ALL then all resources owned will be affected. + * No error will be returned. + * + * If \a clk is SC_PM_CLK_ALL, then an error will be returned if any + * of the available clocks returns an error. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog); + +/*! + * This function sets the parent of a resource's clock. + * This function should only be called when the clock is disabled. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[in] parent New parent of the clock. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * - SC_ERR_BUSY if clock is currently enabled. + * - SC_ERR_NOPOWER if resource not powered + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t parent); + +/*! + * This function gets the parent of a resource's clock. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the resource + * @param[in] clk clock to affect + * @param[out] parent pointer to return parent of clock. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or clock, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner + * or parent of the owner, + * - SC_ERR_UNAVAILABLE if clock not applicable to this resource + * + * Refer to the [Clock List](@ref CLOCKS) for valid clock values. + */ +sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t *parent); + +/* @} */ + +/*! + * @name Reset Functions + * @{ + */ + +/*! + * This function is used to reset the system. Only the owner of the + * SC_R_SYSTEM resource can do this. + * + * @param[in] ipc IPC handle + * @param[in] type reset type + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid type, + * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM + * + * If this function returns, then the reset did not occur due to an + * invalid parameter. + */ +sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type); + +/*! + * This function gets a caller's reset reason. + * + * @param[in] ipc IPC handle + * @param[out] reason pointer to return reset reason + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason); + +/*! + * This function is used to boot a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to boot + * @param[in] resource_cpu ID of the CPU resource to start + * @param[in] boot_addr 64-bit boot address + * @param[in] resource_mu ID of the MU that must be powered + * @param[in] resource_dev ID of the boot device that must be powered + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition, resource, or addr, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * partition to boot + */ +sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_rsrc_t resource_cpu, sc_faddr_t boot_addr, + sc_rsrc_t resource_mu, sc_rsrc_t resource_dev); + +/*! + * This function is used to reboot the caller's partition. + * + * @param[in] ipc IPC handle + * @param[in] type reset type + * + * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by + * the calling partition will be reset if possible. SC state (partitions, + * power, clocks, etc.) is reset. The boot SW of the booting CPU must be + * able to handle peripherals that that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset. + * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW + * of the booting CPU must be able to handle peripherals and SC state that + * that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action. + * + * If this function returns, then the reset did not occur due to an + * invalid parameter. + */ +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type); + +/*! + * This function is used to reboot a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to reboot + * @param[in] type reset type + * + * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by + * the calling partition will be reset if possible. SC state (partitions, + * power, clocks, etc.) is reset. The boot SW of the booting CPU must be + * able to handle peripherals that that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset. + * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW + * of the booting CPU must be able to handle peripherals and SC state that + * that are not reset. + * + * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action. + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid partition or type + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * + * Most peripherals owned by the partition will be reset if + * possible. SC state (partitions, power, clocks, etc.) is reset. The + * boot SW of the booting CPU must be able to handle peripherals that + * that are not reset. + */ +sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_reset_type_t type); + +/*! + * This function is used to start/stop a CPU. + * + * @param[in] ipc IPC handle + * @param[in] resource ID of the CPU resource + * @param[in] enable start if SC_TRUE; otherwise stop + * @param[in] address 64-bit boot address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if invalid resource or address, + * - SC_ERR_NOACCESS if caller's partition is not the parent of the + * resource (CPU) owner + */ +sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address); + +/* @} */ + +#endif /* SC_PM_API_H */ + +/**@}*/ diff --git a/plat/imx/common/include/sci/svc/rm/sci_rm_api.h b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h new file mode 100644 index 000000000..012d919fd --- /dev/null +++ b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file containing the public API for the System Controller (SC) + * Resource Management (RM) function. This includes functions for + * partitioning resources, pads, and memory regions. + * + * @addtogroup RM_SVC (SVC) Resource Management Service + * + * Module for the Resource Management (RM) service. + * + * @includedoc rm/details.dox + * + * @{ + */ + +#ifndef SC_RM_API_H +#define SC_RM_API_H + +/* Includes */ + +#include <sci/sci_types.h> + +/* Defines */ + +/*! + * @name Defines for type widths + */ +/*@{*/ +#define SC_RM_PARTITION_W 5 /* Width of sc_rm_pt_t */ +#define SC_RM_MEMREG_W 6 /* Width of sc_rm_mr_t */ +#define SC_RM_DID_W 4 /* Width of sc_rm_did_t */ +#define SC_RM_SID_W 6 /* Width of sc_rm_sid_t */ +#define SC_RM_SPA_W 2 /* Width of sc_rm_spa_t */ +#define SC_RM_PERM_W 3 /* Width of sc_rm_perm_t */ +/*@}*/ + +/*! + * @name Defines for ALL parameters + */ +/*@{*/ +#define SC_RM_PT_ALL ((sc_rm_pt_t) UINT8_MAX) /* All partitions */ +#define SC_RM_MR_ALL ((sc_rm_mr_t) UINT8_MAX) /* All memory regions */ +/*@}*/ + +/*! + * @name Defines for sc_rm_spa_t + */ +/*@{*/ +#define SC_RM_SPA_PASSTHRU 0U /* Pass through (attribute driven by master) */ +#define SC_RM_SPA_PASSSID 1U /* Pass through and output on SID */ +#define SC_RM_SPA_ASSERT 2U /* Assert (force to be secure/privileged) */ +#define SC_RM_SPA_NEGATE 3U /* Negate (force to be non-secure/user) */ +/*@}*/ + +/*! + * @name Defines for sc_rm_perm_t + */ +/*@{*/ +#define SC_RM_PERM_NONE 0U /* No access */ +#define SC_RM_PERM_SEC_R 1U /* Secure RO */ +#define SC_RM_PERM_SECPRIV_RW 2U /* Secure privilege R/W */ +#define SC_RM_PERM_SEC_RW 3U /* Secure R/W */ +#define SC_RM_PERM_NSPRIV_R 4U /* Secure R/W, non-secure privilege RO */ +#define SC_RM_PERM_NS_R 5U /* Secure R/W, non-secure RO */ +#define SC_RM_PERM_NSPRIV_RW 6U /* Secure R/W, non-secure privilege R/W */ +#define SC_RM_PERM_FULL 7U /* Full access */ +/*@}*/ + +/* Types */ + +/*! + * This type is used to declare a resource partition. + */ +typedef uint8_t sc_rm_pt_t; + +/*! + * This type is used to declare a memory region. + */ +typedef uint8_t sc_rm_mr_t; + +/*! + * This type is used to declare a resource domain ID used by the + * isolation HW. + */ +typedef uint8_t sc_rm_did_t; + +/*! + * This type is used to declare an SMMU StreamID. + */ +typedef uint16_t sc_rm_sid_t; + +/*! + * This type is a used to declare master transaction attributes. + */ +typedef uint8_t sc_rm_spa_t; + +/*! + * This type is used to declare a resource/memory region access permission. + * Refer to the XRDC2 Block Guide for more information. + */ +typedef uint8_t sc_rm_perm_t; + +/* Functions */ + +/*! + * @name Partition Functions + * @{ + */ + +/*! + * This function requests that the SC create a new resource partition. + * + * @param[in] ipc IPC handle + * @param[out] pt return handle for partition; used for subsequent function + * calls associated with this partition + * @param[in] secure boolean indicating if this partition should be secure; only + * valid if caller is secure + * @param[in] isolated boolean indicating if this partition should be HW isolated + * via XRDC; set SC_TRUE if new DID is desired + * @param[in] restricted boolean indicating if this partition should be restricted; set + * SC_TRUE if masters in this partition cannot create new partitions + * @param[in] grant boolean indicating if this partition should always grant + * access and control to the parent + * @param[in] coherent boolean indicating if this partition is coherent; + * set SC_TRUE if only this partition will contain both AP clusters + * and they will be coherent via the CCI + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_ERR_PARM if caller's partition is not secure but a new secure partition is requested, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_UNAVAILABLE if partition table is full (no more allocation space) + * + * Marking as non-secure prevents subsequent functions from configuring masters in this + * partition to assert the secure signal. If restricted then the new partition is limited + * in what functions it can call, especially those associated with managing partitions. + * + * The grant option is usually used to isolate a bus master's traffic to specific + * memory without isolating the peripheral interface of the master or the API + * controls of that master. + */ +sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure, + sc_bool_t isolated, sc_bool_t restricted, + sc_bool_t grant, sc_bool_t coherent); + +/*! + * This function makes a partition confidential. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition that is granting + * @param[in] retro retroactive + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a pt out of range, + * - SC_ERR_NOACCESS if caller's not allowed to change \a pt + * - SC_ERR_LOCKED if partition \a pt is locked + * + * Call to make a partition confidential. Confidential means only this + * partition should be able to grant access permissions to this partition. + * + * If retroactive, then all resources owned by other partitions will have + * access rights for this partition removed, even if locked. + */ +sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro); + +/*! + * This function frees a partition and assigns all resources to the caller. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to free + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if \a pt out of range or invalid, + * - SC_ERR_NOACCESS if \a pt is the SC partition, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if \a pt or caller's partition is locked + * + * All resources, memory regions, and pads are assigned to the caller/parent. + * The partition watchdog is disabled (even if locked). DID is freed. + */ +sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt); + +/*! + * This function returns the DID of a partition. + * + * @param[in] ipc IPC handle + * + * @return Returns the domain ID (DID) of the caller's partition. + * + * The DID is a SoC-specific internal ID used by the HW resource + * protection mechanism. It is only required by clients when using the + * SEMA42 module as the DID is sometimes connected to the master ID. + */ +sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc); + +/*! + * This function forces a partition to use a specific static DID. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to assign \a did + * @param[in] did static DID to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if \a pt or \a did out of range, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if \a pt is locked + * + * Assumes no assigned resources or memory regions yet! The number of static + * DID is fixed by the SC at boot. + */ +sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did); + +/*! + * This function locks a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to lock + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a pt out of range, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt + * + * If a partition is locked it cannot be freed, have resources/pads assigned + * to/from it, memory regions created/assigned, DID changed, or parent changed. + */ +sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt); + +/*! + * This function gets the partition handle of the caller. + * + * @param[in] ipc IPC handle + * @param[out] pt return handle for caller's partition + * + * @return Returns an error code (SC_ERR_NONE = success). + */ +sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt); + +/*! + * This function sets a new parent for a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition for which parent is to be + * changed + * @param[in] pt_parent handle of partition to set as parent + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt, + * - SC_ERR_LOCKED if either partition is locked + */ +sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent); + +/*! + * This function moves all movable resources/pads owned by a source partition + * to a destination partition. It can be used to more quickly set up a new + * partition if a majority of the caller's resources are to be moved to a + * new partition. + * + * @param[in] ipc IPC handle + * @param[in] pt_src handle of partition from which resources should + * be moved from + * @param[in] pt_dst handle of partition to which resources should be + * moved to + * @param[in] move_rsrc boolean to indicate if resources should be moved + * @param[in] move_pads boolean to indicate if pads should be moved + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * By default, all resources are movable. This can be changed using the + * sc_rm_set_resource_movable() function. Note all masters defaulted to SMMU + * bypass. + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not \a pt_src or the + * parent of \a pt_src, + * - SC_ERR_LOCKED if either partition is locked + */ +sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst, + sc_bool_t move_rsrc, sc_bool_t move_pads); + +/* @} */ + +/*! + * @name Resource Functions + * @{ + */ + +/*! + * This function assigns ownership of a resource to a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which resource should be + * assigned + * @param[in] resource resource to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * This action resets the resource's master and peripheral attributes. + * Privilege attribute will be PASSTHRU, security attribute will be + * ASSERT if the partition si secure and NEGATE if it is not, and + * masters will defaulted to SMMU bypass. Access permissions will reset + * to SEC_RW for the owning partition only for secure partitions, FULL for + * non-secure. DEfault is no access by other partitions. + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource); + +/*! + * This function flags resources as movable or not. + * + * @param[in] ipc IPC handle + * @param[in] resource_fst first resource for which flag should be set + * @param[in] resource_lst last resource for which flag should be set + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if resources are out of range, + * - SC_ERR_NOACCESS if caller's partition is not a parent of a resource owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function is used to determine the set of resources that will be + * moved using the sc_rm_move_all() function. All resources are movable + * by default so this function is normally used to prevent a set of + * resources from moving. + */ +sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst, + sc_rsrc_t resource_lst, sc_bool_t movable); + +/*! + * This function flags all of a subsystem's resources as movable + * or not. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to use to identify subsystem + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if a function argument is out of range + * + * Note \a resource is used to find the associated subsystem. Only + * resources owned by the caller are set. + */ +sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t movable); + +/*! + * This function sets attributes for a resource which is a bus master (i.e. + * capable of DMA). + * + * @param[in] ipc IPC handle + * @param[in] resource master resource for which attributes should apply + * @param[in] sa security attribute + * @param[in] pa privilege attribute + * @param[in] smmu_bypass SMMU bypass mode + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not a parent of the resource owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function configures how the HW isolation will see bus transactions + * from the specified master. Note the security attribute will only be + * changed if the caller's partition is secure. + */ +sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_spa_t sa, sc_rm_spa_t pa, + sc_bool_t smmu_bypass); + +/*! + * This function sets the StreamID for a resource which is a bus master (i.e. + * capable of DMA). + * + * @param[in] ipc IPC handle + * @param[in] resource master resource for which attributes should apply + * @param[in] sid StreamID + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function configures the SID attribute associated with all bus transactions + * from this master. Note 0 is not a valid SID as it is reserved to indicate + * bypass. + */ +sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t sid); + +/*! + * This function sets access permissions for a peripheral resource. + * + * @param[in] ipc IPC handle + * @param[in] resource peripheral resource for which permissions should apply + * @param[in] pt handle of partition \a perm should by applied for + * @param[in] perm permissions to apply to \a resource for \a pt + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt + * + * This function configures how the HW isolation will restrict access to a + * peripheral based on the attributes of a transaction from bus master. + */ +sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_pt_t pt, sc_rm_perm_t perm); + +/*! + * This function gets ownership status of a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the resource). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to test if a resource is a bus master. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if the resource is a bus master). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to test if a resource is a peripheral. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to check + * + * @return Returns a boolean (SC_TRUE if the resource is a peripheral). + * + * If \a resource is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource); + +/*! + * This function is used to obtain info about a resource. + * + * @param[in] ipc IPC handle + * @param[in] resource resource to inquire about + * @param[out] sid pointer to return StreamID + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a resource is out of range + */ +sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t *sid); + +/* @} */ + +/*! + * @name Memory Region Functions + * @{ + */ + +/*! + * This function requests that the SC create a new memory region. + * + * @param[in] ipc IPC handle + * @param[out] mr return handle for region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region (physical) + * @param[in] addr_end end address of region (physical) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if the new memory region is misaligned, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_PARM if the new memory region spans multiple existing regions, + * - SC_ERR_NOACCESS if caller's partition does not own the memory containing + * the new region, + * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation + * space) + * + * The area covered by the memory region must currently be owned by the caller. + * By default, the new region will have access permission set to allow the + * caller to access. + */ +sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end); + +/*! + * This function requests that the SC split a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to split + * @param[out] mr_ret return handle for new region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region (physical) + * @param[in] addr_end end address of region (physical) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_PARM if the new memory region is not start/end part of mr, + * - SC_ERR_LOCKED if caller's partition is locked, + * - SC_ERR_PARM if the new memory region spans multiple existing regions, + * - SC_ERR_NOACCESS if caller's partition does not own the memory containing + * the new region, + * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation + * space) + * + * Note the new region must start or end on the split region. + */ +sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_mr_t *mr_ret, sc_faddr_t addr_start, + sc_faddr_t addr_end); + +/*! + * This function frees a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to free + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a mr out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not a parent of \a mr, + * - SC_ERR_LOCKED if the owning partition of \a mr is locked + */ +sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr); + +/*! + * Internal SC function to find a memory region. + * + * @see sc_rm_find_memreg(). + */ +/*! + * This function finds a memory region. + * + * @param[in] ipc IPC handle + * @param[out] mr return handle for region; used for + * subsequent function calls + * associated with this region + * @param[in] addr_start start address of region to search for + * @param[in] addr_end end address of region to search for + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOTFOUND if region not found, + * + * Searches only for regions owned by the caller. Finds first + * region containing the range specified. + */ +sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end); + +/*! + * This function assigns ownership of a memory region. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which memory region + * should be assigned + * @param[in] mr handle of memory region to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the \a mr owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr); + +/*! + * This function sets access permissions for a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region for which permissions + * should apply + * @param[in] pt handle of partition \a perm should by + * applied for + * @param[in] perm permissions to apply to \a mr for \a pt + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the region owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition is locked + * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt + * + * This function configures how the HW isolation will restrict access to a + * memory region based on the attributes of a transaction from bus master. + */ +sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_pt_t pt, sc_rm_perm_t perm); + +/*! + * This function gets ownership status of a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the + * memory region). + * + * If \a mr is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr); + +/*! + * This function is used to obtain info about a memory region. + * + * @param[in] ipc IPC handle + * @param[in] mr handle of memory region to inquire about + * @param[out] addr_start pointer to return start address + * @param[out] addr_end pointer to return end address + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if \a mr is out of range + */ +sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_faddr_t *addr_start, sc_faddr_t *addr_end); + +/* @} */ + +/*! + * @name Pad Functions + * @{ + */ + +/*! + * This function assigns ownership of a pad to a partition. + * + * @param[in] ipc IPC handle + * @param[in] pt handle of partition to which pad should + * be assigned + * @param[in] pad pad to assign + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_ERR_NOACCESS if caller's partition is restricted, + * - SC_PARM if arguments out of range or invalid, + * - SC_ERR_NOACCESS if caller's partition is not the pad owner or parent + * of the owner, + * - SC_ERR_LOCKED if the owning partition or \a pt is locked + */ +sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad); + +/*! + * This function flags pads as movable or not. + * + * @param[in] ipc IPC handle + * @param[in] pad_fst first pad for which flag should be set + * @param[in] pad_lst last pad for which flag should be set + * @param[in] movable movable flag (SC_TRUE is movable) + * + * @return Returns an error code (SC_ERR_NONE = success). + * + * Return errors: + * - SC_PARM if pads are out of range, + * - SC_ERR_NOACCESS if caller's partition is not a parent of a pad owner, + * - SC_ERR_LOCKED if the owning partition is locked + * + * This function is used to determine the set of pads that will be + * moved using the sc_rm_move_all() function. All pads are movable + * by default so this function is normally used to prevent a set of + * pads from moving. + */ +sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst, + sc_pad_t pad_lst, sc_bool_t movable); + +/*! + * This function gets ownership status of a pad. + * + * @param[in] ipc IPC handle + * @param[in] pad pad to check + * + * @return Returns a boolean (SC_TRUE if caller's partition owns the pad). + * + * If \a pad is out of range then SC_FALSE is returned. + */ +sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad); + +/* @} */ + +/*! + * @name Debug Functions + * @{ + */ + +/*! + * This function dumps the RM state for debug. + * + * @param[in] ipc IPC handle + */ +void sc_rm_dump(sc_ipc_t ipc); + +/* @} */ + +#endif /* SC_RM_API_H */ + +/**@}*/ diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S new file mode 100644 index 000000000..ad71b89f2 --- /dev/null +++ b/plat/imx/common/lpuart_console.S @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <console_macros.S> +#include <assert_macros.S> +#include "imx8_lpuart.h" + + .globl console_lpuart_register + .globl console_lpuart_init + .globl console_lpuart_putc + .globl console_lpuart_getc + +func console_lpuart_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_DRVDATA] + + bl console_lpuart_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register lpuart + +register_fail: + ret x7 +endfunc console_lpuart_register + +func console_lpuart_init + mov w0, #1 + ret +endfunc console_lpuart_init + +func console_lpuart_putc + ldr x1, [x1, #CONSOLE_T_DRVDATA] + cbz x1, putc_error + /* Prepare '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #STAT] + tbz w2, #23, 1b + mov w2, #0xD + str w2, [x1, #DATA] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #STAT] + tbz w2, #23, 2b + str w0, [x1, #DATA] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_lpuart_putc + +func console_lpuart_getc + ldr x0, [x0, #CONSOLE_T_DRVDATA] + cbz x0, getc_error + /* Check if the receive FIFO state */ + ret +getc_error: + mov w0, #-1 + ret +endfunc console_lpuart_getc diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c new file mode 100644 index 000000000..242e31b4b --- /dev/null +++ b/plat/imx/common/plat_imx8_gic.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <gicv3.h> +#include <plat_imx8.h> +#include <platform.h> +#include <platform_def.h> +#include <utils.h> + +/* the GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +/* array of Group1 secure interrupts to be configured by the gic driver */ +const unsigned int g1s_interrupt_array[] = { 6 }; + +/* array of Group0 interrupts to be configured by the gic driver */ +const unsigned int g0_interrupt_array[] = { 7 }; + +static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +const gicv3_driver_data_t arm_gic_data = { + .gicd_base = PLAT_GICD_BASE, + .gicr_base = PLAT_GICR_BASE, + .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array), + .g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array), + .g0_interrupt_array = g0_interrupt_array, + .g1s_interrupt_array = g1s_interrupt_array, + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = plat_imx_mpidr_to_core_pos, +}; + +void plat_gic_driver_init(void) +{ + /* + * the GICv3 driver is initialized in EL3 and does not need + * to be initialized again in S-EL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&arm_gic_data); +#endif +} + +void plat_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void plat_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/plat/imx/common/sci/imx8_mu.c b/plat/imx/common/sci/imx8_mu.c new file mode 100644 index 000000000..8028c76d6 --- /dev/null +++ b/plat/imx/common/sci/imx8_mu.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <mmio.h> +#include "imx8_mu.h" + +void MU_EnableRxFullInt(uint32_t base, uint32_t index) +{ + uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1); + + reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1); + reg |= MU_CR_RIE0_MASK1 >> index; + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} + +void MU_EnableGeneralInt(uint32_t base, uint32_t index) +{ + uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1); + + reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1); + reg |= MU_CR_GIE0_MASK1 >> index; + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} + +void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg) +{ + uint32_t mask = MU_SR_TE0_MASK1 >> regIndex; + + /* Wait TX register to be empty. */ + while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask)) + ; + mmio_write_32(base + MU_ATR0_OFFSET1 + (regIndex * 4), msg); +} + +void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg) +{ + uint32_t mask = MU_SR_RF0_MASK1 >> regIndex; + + /* Wait RX register to be full. */ + while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask)) + ; + *msg = mmio_read_32(base + MU_ARR0_OFFSET1 + (regIndex * 4)); +} + +void MU_Init(uint32_t base) +{ + uint32_t reg; + + reg = mmio_read_32(base + MU_ACR_OFFSET1); + /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */ + reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1 + | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1); + mmio_write_32(base + MU_ACR_OFFSET1, reg); +} diff --git a/plat/imx/common/sci/imx8_mu.h b/plat/imx/common/sci/imx8_mu.h new file mode 100644 index 000000000..8834a976c --- /dev/null +++ b/plat/imx/common/sci/imx8_mu.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <types.h> + +#define MU_ATR0_OFFSET1 0x0 +#define MU_ARR0_OFFSET1 0x10 +#define MU_ASR_OFFSET1 0x20 +#define MU_ACR_OFFSET1 0x24 +#define MU_TR_COUNT1 4 +#define MU_RR_COUNT1 4 + +#define MU_CR_GIEn_MASK1 (0xF << 28) +#define MU_CR_RIEn_MASK1 (0xF << 24) +#define MU_CR_TIEn_MASK1 (0xF << 20) +#define MU_CR_GIRn_MASK1 (0xF << 16) +#define MU_CR_NMI_MASK1 (1 << 3) +#define MU_CR_Fn_MASK1 0x7 + +#define MU_SR_TE0_MASK1 (1 << 23) +#define MU_SR_RF0_MASK1 (1 << 27) +#define MU_CR_RIE0_MASK1 (1 << 27) +#define MU_CR_GIE0_MASK1 (1 << 31) + +#define MU_TR_COUNT 4 +#define MU_RR_COUNT 4 + +void MU_Init(uint32_t base); +void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg); +void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg); +void MU_EnableGeneralInt(uint32_t base, uint32_t index); +void MU_EnableRxFullInt(uint32_t base, uint32_t index); diff --git a/plat/imx/common/sci/ipc.c b/plat/imx/common/sci/ipc.c new file mode 100644 index 000000000..2af256782 --- /dev/null +++ b/plat/imx/common/sci/ipc.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bakery_lock.h> +#include <sci/sci_scfw.h> +#include <sci/sci_ipc.h> +#include <sci/sci_rpc.h> +#include <stdlib.h> +#include "imx8_mu.h" + +DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock); +#define sc_ipc_lock_init() bakery_lock_init(&sc_ipc_bakery_lock) +#define sc_ipc_lock() bakery_lock_get(&sc_ipc_bakery_lock) +#define sc_ipc_unlock() bakery_lock_release(&sc_ipc_bakery_lock) + +void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp) +{ + sc_ipc_lock(); + + sc_ipc_write(ipc, msg); + if (!no_resp) + sc_ipc_read(ipc, msg); + + sc_ipc_unlock(); +} + +sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id) +{ + uint32_t base = id; + uint32_t i; + + /* Get MU base associated with IPC channel */ + if ((ipc == NULL) || (base == 0)) + return SC_ERR_IPC; + + sc_ipc_lock_init(); + + /* Init MU */ + MU_Init(base); + + /* Enable all RX interrupts */ + for (i = 0; i < MU_RR_COUNT; i++) { + MU_EnableRxFullInt(base, i); + } + + /* Return MU address as handle */ + *ipc = (sc_ipc_t) id; + + return SC_ERR_NONE; +} + +void sc_ipc_close(sc_ipc_t ipc) +{ + uint32_t base = ipc; + + if (base != 0) + MU_Init(base); +} + +void sc_ipc_read(sc_ipc_t ipc, void *data) +{ + uint32_t base = ipc; + sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; + uint8_t count = 0; + + /* Check parms */ + if ((base == 0) || (msg == NULL)) + return; + + /* Read first word */ + MU_ReceiveMsg(base, 0, (uint32_t *) msg); + count++; + + /* Check size */ + if (msg->size > SC_RPC_MAX_MSG) { + *((uint32_t *) msg) = 0; + return; + } + + /* Read remaining words */ + while (count < msg->size) { + MU_ReceiveMsg(base, count % MU_RR_COUNT, + &(msg->DATA.u32[count - 1])); + count++; + } +} + +void sc_ipc_write(sc_ipc_t ipc, void *data) +{ + sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; + uint32_t base = ipc; + uint8_t count = 0; + + /* Check parms */ + if ((base == 0) || (msg == NULL)) + return; + + /* Check size */ + if (msg->size > SC_RPC_MAX_MSG) + return; + + /* Write first word */ + MU_SendMessage(base, 0, *((uint32_t *) msg)); + count++; + + /* Write remaining words */ + while (count < msg->size) { + MU_SendMessage(base, count % MU_TR_COUNT, + msg->DATA.u32[count - 1]); + count++; + } +} + diff --git a/plat/imx/common/sci/sci_api.mk b/plat/imx/common/sci/sci_api.mk new file mode 100644 index 000000000..b277877ec --- /dev/null +++ b/plat/imx/common/sci/sci_api.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL31_SOURCES += plat/imx/common/sci/ipc.c \ + plat/imx/common/sci/imx8_mu.c \ + plat/imx/common/sci/svc/pad/pad_rpc_clnt.c \ + plat/imx/common/sci/svc/pm/pm_rpc_clnt.c \ + plat/imx/common/sci/svc/rm/rm_rpc_clnt.c diff --git a/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c new file mode 100644 index 000000000..555e7047a --- /dev/null +++ b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the PAD service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup PAD_SVC + * @{ + */ + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/svc/rm/sci_rm_api.h> +#include <sci/svc/pad/sci_pad_api.h> +#include <sci/sci_rpc.h> +#include <stdlib.h> +#include "sci_pad_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_MUX; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)mux; + RPC_U8(&msg, 3U) = (uint8_t)config; + RPC_U8(&msg, 4U) = (uint8_t)iso; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *mux, sc_pad_config_t *config, + sc_pad_iso_t *iso) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_MUX; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mux != NULL) { + *mux = RPC_U8(&msg, 0U); + } + + if (config != NULL) { + *config = RPC_U8(&msg, 1U); + } + + if (iso != NULL) { + *iso = RPC_U8(&msg, 2U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (ctrl != NULL) { + *ctrl = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_WAKEUP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)wakeup; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_WAKEUP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (wakeup != NULL) { + *wakeup = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux, + sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl, + sc_pad_wakeup_t wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_ALL; + RPC_U32(&msg, 0U) = (uint32_t)ctrl; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_U8(&msg, 6U) = (uint8_t)mux; + RPC_U8(&msg, 7U) = (uint8_t)config; + RPC_U8(&msg, 8U) = (uint8_t)iso; + RPC_U8(&msg, 9U) = (uint8_t)wakeup; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux, + sc_pad_config_t *config, sc_pad_iso_t *iso, + uint32_t *ctrl, sc_pad_wakeup_t *wakeup) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_ALL; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (ctrl != NULL) { + *ctrl = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + if (mux != NULL) { + *mux = RPC_U8(&msg, 4U); + } + + if (config != NULL) { + *config = RPC_U8(&msg, 5U); + } + + if (iso != NULL) { + *iso = RPC_U8(&msg, 6U); + } + + if (wakeup != NULL) { + *wakeup = RPC_U8(&msg, 7U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET; + RPC_U32(&msg, 0U) = (uint32_t)val; + RPC_U16(&msg, 4U) = (uint16_t)pad; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (val != NULL) { + *val = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_pad_28fdsoi_ps_t ps) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)dse; + RPC_U8(&msg, 3U) = (uint8_t)ps; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, + sc_pad_28fdsoi_ps_t *ps) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (dse != NULL) { + *dse = RPC_U8(&msg, 0U); + } + + if (ps != NULL) { + *ps = RPC_U8(&msg, 1U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t dse, sc_bool_t hys, + sc_pad_28fdsoi_pus_t pus, sc_bool_t pke, + sc_bool_t pue) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_HSIC; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)dse; + RPC_U8(&msg, 3U) = (uint8_t)pus; + RPC_U8(&msg, 4U) = (uint8_t)hys; + RPC_U8(&msg, 5U) = (uint8_t)pke; + RPC_U8(&msg, 6U) = (uint8_t)pue; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad, + sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys, + sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke, + sc_bool_t *pue) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_HSIC; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (dse != NULL) { + *dse = RPC_U8(&msg, 0U); + } + + if (pus != NULL) { + *pus = RPC_U8(&msg, 1U); + } + + if (hys != NULL) { + *hys = RPC_U8(&msg, 2U); + } + + if (pke != NULL) { + *pke = RPC_U8(&msg, 3U); + } + + if (pue != NULL) { + *pue = RPC_U8(&msg, 4U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t compen, sc_bool_t fastfrz, + uint8_t rasrcp, uint8_t rasrcn, + sc_bool_t nasrc_sel, sc_bool_t psw_ovr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_COMP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)compen; + RPC_U8(&msg, 3U) = (uint8_t)rasrcp; + RPC_U8(&msg, 4U) = (uint8_t)rasrcn; + RPC_U8(&msg, 5U) = (uint8_t)fastfrz; + RPC_U8(&msg, 6U) = (uint8_t)nasrc_sel; + RPC_U8(&msg, 7U) = (uint8_t)psw_ovr; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad, + uint8_t *compen, sc_bool_t *fastfrz, + uint8_t *rasrcp, uint8_t *rasrcn, + sc_bool_t *nasrc_sel, sc_bool_t *compok, + uint8_t *nasrc, sc_bool_t *psw_ovr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD; + RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_COMP; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (compen != NULL) { + *compen = RPC_U8(&msg, 0U); + } + + if (rasrcp != NULL) { + *rasrcp = RPC_U8(&msg, 1U); + } + + if (rasrcn != NULL) { + *rasrcn = RPC_U8(&msg, 2U); + } + + if (nasrc != NULL) { + *nasrc = RPC_U8(&msg, 3U); + } + + if (fastfrz != NULL) { + *fastfrz = RPC_U8(&msg, 4U); + } + + if (nasrc_sel != NULL) { + *nasrc_sel = RPC_U8(&msg, 5U); + } + + if (compok != NULL) { + *compok = RPC_U8(&msg, 6U); + } + + if (psw_ovr != NULL) { + *psw_ovr = RPC_U8(&msg, 7U); + } + + return (sc_err_t)result; +} + +/**@}*/ diff --git a/plat/imx/common/sci/svc/pad/sci_pad_rpc.h b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h new file mode 100644 index 000000000..686e6e997 --- /dev/null +++ b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the PAD RPC implementation. + * + * @addtogroup PAD_SVC + * @{ + */ + +#ifndef SC_PAD_RPC_H +#define SC_PAD_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC PAD function calls + */ +/*@{*/ +#define PAD_FUNC_UNKNOWN 0 /* Unknown function */ +#define PAD_FUNC_SET_MUX 1U /* Index for pad_set_mux() RPC call */ +#define PAD_FUNC_GET_MUX 6U /* Index for pad_get_mux() RPC call */ +#define PAD_FUNC_SET_GP 2U /* Index for pad_set_gp() RPC call */ +#define PAD_FUNC_GET_GP 7U /* Index for pad_get_gp() RPC call */ +#define PAD_FUNC_SET_WAKEUP 4U /* Index for pad_set_wakeup() RPC call */ +#define PAD_FUNC_GET_WAKEUP 9U /* Index for pad_get_wakeup() RPC call */ +#define PAD_FUNC_SET_ALL 5U /* Index for pad_set_all() RPC call */ +#define PAD_FUNC_GET_ALL 10U /* Index for pad_get_all() RPC call */ +#define PAD_FUNC_SET 15U /* Index for pad_set() RPC call */ +#define PAD_FUNC_GET 16U /* Index for pad_get() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI 11U /* Index for pad_set_gp_28fdsoi() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI 12U /* Index for pad_get_gp_28fdsoi() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI_HSIC 3U /* Index for pad_set_gp_28fdsoi_hsic() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI_HSIC 8U /* Index for pad_get_gp_28fdsoi_hsic() RPC call */ +#define PAD_FUNC_SET_GP_28FDSOI_COMP 13U /* Index for pad_set_gp_28fdsoi_comp() RPC call */ +#define PAD_FUNC_GET_GP_28FDSOI_COMP 14U /* Index for pad_get_gp_28fdsoi_comp() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming PAD RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void pad_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an PAD RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void pad_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_PAD_RPC_H */ + +/**@}*/ diff --git a/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c new file mode 100644 index 000000000..b108c499b --- /dev/null +++ b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the PM service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup PM_SVC + * @{ + */ + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/svc/rm/sci_rm_api.h> +#include <sci/svc/pm/sci_pm_api.h> +#include <sci/sci_rpc.h> +#include <stdlib.h> +#include "sci_pm_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_SYS_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_PARTITION_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_power_mode_t *mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_SYS_POWER_MODE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mode != NULL) { + *mode = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_RESOURCE_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t *mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_RESOURCE_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mode != NULL) { + *mode = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_LOW_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_power_mode_t mode, + sc_pm_wake_src_t wake_src) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_CPU_LOW_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)mode; + RPC_U8(&msg, 3U) = (uint8_t)wake_src; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource, + sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME_ADDR; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t isPrimary, sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_U8(&msg, 10U) = (uint8_t)isPrimary; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_sys_if_t sys_if, + sc_pm_power_mode_t hpm, + sc_pm_power_mode_t lpm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_SYS_IF_POWER_MODE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)sys_if; + RPC_U8(&msg, 3U) = (uint8_t)hpm; + RPC_U8(&msg, 4U) = (uint8_t)lpm; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_RATE; + RPC_U32(&msg, 0U) = *(uint32_t *)rate; + RPC_U16(&msg, 4U) = (uint16_t)resource; + RPC_U8(&msg, 6U) = (uint8_t)clk; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + *rate = RPC_U32(&msg, 0U); + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clock_rate_t *rate) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_RATE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (rate != NULL) { + *rate = RPC_U32(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CLOCK_ENABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_U8(&msg, 3U) = (uint8_t)enable; + RPC_U8(&msg, 4U) = (uint8_t)autog; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_PARENT; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_U8(&msg, 3U) = (uint8_t)parent; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource, + sc_pm_clk_t clk, sc_pm_clk_parent_t *parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_PARENT; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)clk; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (parent != NULL) { + *parent = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET; + RPC_U8(&msg, 0U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET_REASON; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (reason != NULL) { + *reason = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_rsrc_t resource_cpu, sc_faddr_t boot_addr, + sc_rsrc_t resource_mu, sc_rsrc_t resource_dev) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_BOOT; + RPC_U32(&msg, 0U) = (uint32_t)(boot_addr >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)boot_addr; + RPC_U16(&msg, 8U) = (uint16_t)resource_cpu; + RPC_U16(&msg, 10U) = (uint16_t)resource_mu; + RPC_U16(&msg, 12U) = (uint16_t)resource_dev; + RPC_U8(&msg, 14U) = (uint8_t)pt; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT; + RPC_U8(&msg, 0U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_TRUE); + + return; +} + +sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt, + sc_pm_reset_type_t type) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT_PARTITION; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)type; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, + sc_faddr_t address) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM; + RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CPU_START; + RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)address; + RPC_U16(&msg, 8U) = (uint16_t)resource; + RPC_U8(&msg, 10U) = (uint8_t)enable; + RPC_SIZE(&msg) = 4U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +/**@}*/ diff --git a/plat/imx/common/sci/svc/pm/sci_pm_rpc.h b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h new file mode 100644 index 000000000..19ab6e441 --- /dev/null +++ b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the PM RPC implementation. + * + * @addtogroup PM_SVC + * @{ + */ + +#ifndef SC_PM_RPC_H +#define SC_PM_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC PM function calls + */ +/*@{*/ +#define PM_FUNC_UNKNOWN 0 /* Unknown function */ +#define PM_FUNC_SET_SYS_POWER_MODE 19U /* Index for pm_set_sys_power_mode() RPC call */ +#define PM_FUNC_SET_PARTITION_POWER_MODE 1U /* Index for pm_set_partition_power_mode() RPC call */ +#define PM_FUNC_GET_SYS_POWER_MODE 2U /* Index for pm_get_sys_power_mode() RPC call */ +#define PM_FUNC_SET_RESOURCE_POWER_MODE 3U /* Index for pm_set_resource_power_mode() RPC call */ +#define PM_FUNC_GET_RESOURCE_POWER_MODE 4U /* Index for pm_get_resource_power_mode() RPC call */ +#define PM_FUNC_REQ_LOW_POWER_MODE 16U /* Index for pm_req_low_power_mode() RPC call */ +#define PM_FUNC_REQ_CPU_LOW_POWER_MODE 20U /* Index for pm_req_cpu_low_power_mode() RPC call */ +#define PM_FUNC_SET_CPU_RESUME_ADDR 17U /* Index for pm_set_cpu_resume_addr() RPC call */ +#define PM_FUNC_SET_CPU_RESUME 21U /* Index for pm_set_cpu_resume() RPC call */ +#define PM_FUNC_REQ_SYS_IF_POWER_MODE 18U /* Index for pm_req_sys_if_power_mode() RPC call */ +#define PM_FUNC_SET_CLOCK_RATE 5U /* Index for pm_set_clock_rate() RPC call */ +#define PM_FUNC_GET_CLOCK_RATE 6U /* Index for pm_get_clock_rate() RPC call */ +#define PM_FUNC_CLOCK_ENABLE 7U /* Index for pm_clock_enable() RPC call */ +#define PM_FUNC_SET_CLOCK_PARENT 14U /* Index for pm_set_clock_parent() RPC call */ +#define PM_FUNC_GET_CLOCK_PARENT 15U /* Index for pm_get_clock_parent() RPC call */ +#define PM_FUNC_RESET 13U /* Index for pm_reset() RPC call */ +#define PM_FUNC_RESET_REASON 10U /* Index for pm_reset_reason() RPC call */ +#define PM_FUNC_BOOT 8U /* Index for pm_boot() RPC call */ +#define PM_FUNC_REBOOT 9U /* Index for pm_reboot() RPC call */ +#define PM_FUNC_REBOOT_PARTITION 12U /* Index for pm_reboot_partition() RPC call */ +#define PM_FUNC_CPU_START 11U /* Index for pm_cpu_start() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming PM RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void pm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an PM RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void pm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_PM_RPC_H */ + +/**@}*/ diff --git a/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c new file mode 100644 index 000000000..230956c7c --- /dev/null +++ b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * File containing client-side RPC functions for the RM service. These + * functions are ported to clients that communicate to the SC. + * + * @addtogroup RM_SVC + * @{ + */ + +/* Includes */ + +#include <sci/sci_types.h> +#include <sci/svc/rm/sci_rm_api.h> +#include <sci/sci_rpc.h> +#include <stdlib.h> +#include "sci_rm_rpc.h" + +/* Local Defines */ + +/* Local Types */ + +/* Local Functions */ + +sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure, + sc_bool_t isolated, sc_bool_t restricted, + sc_bool_t grant, sc_bool_t coherent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_ALLOC; + RPC_U8(&msg, 0U) = (uint8_t)secure; + RPC_U8(&msg, 1U) = (uint8_t)isolated; + RPC_U8(&msg, 2U) = (uint8_t)restricted; + RPC_U8(&msg, 3U) = (uint8_t)grant; + RPC_U8(&msg, 4U) = (uint8_t)coherent; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (pt != NULL) { + *pt = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_CONFIDENTIAL; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)retro; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_FREE; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_DID; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_rm_did_t) result; +} + +sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_STATIC; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)did; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_LOCK; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_PARTITION; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (pt != NULL) { + *pt = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PARENT; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)pt_parent; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst, + sc_bool_t move_rsrc, sc_bool_t move_pads) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MOVE_ALL; + RPC_U8(&msg, 0U) = (uint8_t)pt_src; + RPC_U8(&msg, 1U) = (uint8_t)pt_dst; + RPC_U8(&msg, 2U) = (uint8_t)move_rsrc; + RPC_U8(&msg, 3U) = (uint8_t)move_pads; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_RESOURCE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst, + sc_rsrc_t resource_lst, sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_RESOURCE_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource_fst; + RPC_U16(&msg, 2U) = (uint16_t)resource_lst; + RPC_U8(&msg, 4U) = (uint8_t)movable; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource, + sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_SUBSYS_RSRC_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)movable; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_spa_t sa, sc_rm_spa_t pa, + sc_bool_t smmu_bypass) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_ATTRIBUTES; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)sa; + RPC_U8(&msg, 3U) = (uint8_t)pa; + RPC_U8(&msg, 4U) = (uint8_t)smmu_bypass; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_SID; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U16(&msg, 2U) = (uint16_t)sid; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_pt_t pt, sc_rm_perm_t perm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PERIPHERAL_PERMISSIONS; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_U8(&msg, 3U) = (uint8_t)perm; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_OWNED; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_MASTER; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_PERIPHERAL; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource, + sc_rm_sid_t *sid) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_RESOURCE_INFO; + RPC_U16(&msg, 0U) = (uint16_t)resource; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (sid != NULL) { + *sid = RPC_U16(&msg, 0U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_ALLOC; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr != NULL) { + *mr = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_mr_t *mr_ret, sc_faddr_t addr_start, + sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_SPLIT; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_U8(&msg, 16U) = (uint8_t)mr; + RPC_SIZE(&msg) = 6U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr_ret != NULL) { + *mr_ret = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_FREE; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr, + sc_faddr_t addr_start, sc_faddr_t addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_FIND_MEMREG; + RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U); + RPC_U32(&msg, 4U) = (uint32_t)addr_start; + RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U); + RPC_U32(&msg, 12U) = (uint32_t)addr_end; + RPC_SIZE(&msg) = 5U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + if (mr != NULL) { + *mr = RPC_U8(&msg, 0U); + } + + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_MEMREG; + RPC_U8(&msg, 0U) = (uint8_t)pt; + RPC_U8(&msg, 1U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_rm_pt_t pt, sc_rm_perm_t perm) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MEMREG_PERMISSIONS; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_U8(&msg, 1U) = (uint8_t)pt; + RPC_U8(&msg, 2U) = (uint8_t)perm; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_MEMREG_OWNED; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr, + sc_faddr_t *addr_start, sc_faddr_t *addr_end) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_MEMREG_INFO; + RPC_U8(&msg, 0U) = (uint8_t)mr; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + if (addr_start != NULL) { + *addr_start = + ((uint64_t) RPC_U32(&msg, 0U) << 32U) | RPC_U32(&msg, 4U); + } + + if (addr_end != NULL) { + *addr_end = + ((uint64_t) RPC_U32(&msg, 8U) << 32U) | RPC_U32(&msg, 12U); + } + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_PAD; + RPC_U16(&msg, 0U) = (uint16_t)pad; + RPC_U8(&msg, 2U) = (uint8_t)pt; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst, + sc_pad_t pad_lst, sc_bool_t movable) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PAD_MOVABLE; + RPC_U16(&msg, 0U) = (uint16_t)pad_fst; + RPC_U16(&msg, 2U) = (uint16_t)pad_lst; + RPC_U8(&msg, 4U) = (uint8_t)movable; + RPC_SIZE(&msg) = 3U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_err_t)result; +} + +sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad) +{ + sc_rpc_msg_t msg; + uint8_t result; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_PAD_OWNED; + RPC_U8(&msg, 0U) = (uint8_t)pad; + RPC_SIZE(&msg) = 2U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + result = RPC_R8(&msg); + return (sc_bool_t)result; +} + +void sc_rm_dump(sc_ipc_t ipc) +{ + sc_rpc_msg_t msg; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM; + RPC_FUNC(&msg) = (uint8_t)RM_FUNC_DUMP; + RPC_SIZE(&msg) = 1U; + + sc_call_rpc(ipc, &msg, SC_FALSE); + + return; +} + +/**@}*/ diff --git a/plat/imx/common/sci/svc/rm/sci_rm_rpc.h b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h new file mode 100644 index 000000000..e3de4505e --- /dev/null +++ b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! + * Header file for the RM RPC implementation. + * + * @addtogroup RM_SVC + * @{ + */ + +#ifndef SC_RM_RPC_H +#define SC_RM_RPC_H + +/* Includes */ + +/* Defines */ + +/*! + * @name Defines for RPC RM function calls + */ +/*@{*/ +#define RM_FUNC_UNKNOWN 0 /* Unknown function */ +#define RM_FUNC_PARTITION_ALLOC 1U /* Index for rm_partition_alloc() RPC call */ +#define RM_FUNC_SET_CONFIDENTIAL 31U /* Index for rm_set_confidential() RPC call */ +#define RM_FUNC_PARTITION_FREE 2U /* Index for rm_partition_free() RPC call */ +#define RM_FUNC_GET_DID 26U /* Index for rm_get_did() RPC call */ +#define RM_FUNC_PARTITION_STATIC 3U /* Index for rm_partition_static() RPC call */ +#define RM_FUNC_PARTITION_LOCK 4U /* Index for rm_partition_lock() RPC call */ +#define RM_FUNC_GET_PARTITION 5U /* Index for rm_get_partition() RPC call */ +#define RM_FUNC_SET_PARENT 6U /* Index for rm_set_parent() RPC call */ +#define RM_FUNC_MOVE_ALL 7U /* Index for rm_move_all() RPC call */ +#define RM_FUNC_ASSIGN_RESOURCE 8U /* Index for rm_assign_resource() RPC call */ +#define RM_FUNC_SET_RESOURCE_MOVABLE 9U /* Index for rm_set_resource_movable() RPC call */ +#define RM_FUNC_SET_SUBSYS_RSRC_MOVABLE 28U /* Index for rm_set_subsys_rsrc_movable() RPC call */ +#define RM_FUNC_SET_MASTER_ATTRIBUTES 10U /* Index for rm_set_master_attributes() RPC call */ +#define RM_FUNC_SET_MASTER_SID 11U /* Index for rm_set_master_sid() RPC call */ +#define RM_FUNC_SET_PERIPHERAL_PERMISSIONS 12U /* Index for rm_set_peripheral_permissions() RPC call */ +#define RM_FUNC_IS_RESOURCE_OWNED 13U /* Index for rm_is_resource_owned() RPC call */ +#define RM_FUNC_IS_RESOURCE_MASTER 14U /* Index for rm_is_resource_master() RPC call */ +#define RM_FUNC_IS_RESOURCE_PERIPHERAL 15U /* Index for rm_is_resource_peripheral() RPC call */ +#define RM_FUNC_GET_RESOURCE_INFO 16U /* Index for rm_get_resource_info() RPC call */ +#define RM_FUNC_MEMREG_ALLOC 17U /* Index for rm_memreg_alloc() RPC call */ +#define RM_FUNC_MEMREG_SPLIT 29U /* Index for rm_memreg_split() RPC call */ +#define RM_FUNC_MEMREG_FREE 18U /* Index for rm_memreg_free() RPC call */ +#define RM_FUNC_FIND_MEMREG 30U /* Index for rm_find_memreg() RPC call */ +#define RM_FUNC_ASSIGN_MEMREG 19U /* Index for rm_assign_memreg() RPC call */ +#define RM_FUNC_SET_MEMREG_PERMISSIONS 20U /* Index for rm_set_memreg_permissions() RPC call */ +#define RM_FUNC_IS_MEMREG_OWNED 21U /* Index for rm_is_memreg_owned() RPC call */ +#define RM_FUNC_GET_MEMREG_INFO 22U /* Index for rm_get_memreg_info() RPC call */ +#define RM_FUNC_ASSIGN_PAD 23U /* Index for rm_assign_pad() RPC call */ +#define RM_FUNC_SET_PAD_MOVABLE 24U /* Index for rm_set_pad_movable() RPC call */ +#define RM_FUNC_IS_PAD_OWNED 25U /* Index for rm_is_pad_owned() RPC call */ +#define RM_FUNC_DUMP 27U /* Index for rm_dump() RPC call */ +/*@}*/ + +/* Types */ + +/* Functions */ + +/*! + * This function dispatches an incoming RM RPC request. + * + * @param[in] caller_pt caller partition + * @param[in] msg pointer to RPC message + */ +void rm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg); + +/*! + * This function translates and dispatches an RM RPC request. + * + * @param[in] ipc IPC handle + * @param[in] msg pointer to RPC message + */ +void rm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg); + +#endif /* SC_RM_RPC_H */ + +/**@}*/ diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c new file mode 100644 index 000000000..6cfdaf8ee --- /dev/null +++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <cci.h> +#include <console.h> +#include <context.h> +#include <context_mgmt.h> +#include <debug.h> +#include <imx8qm_pads.h> +#include <imx8_iomux.h> +#include <imx8_lpuart.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <plat_imx8.h> +#include <sci/sci.h> +#include <sec_rsrc.h> +#include <stdbool.h> +#include <xlat_tables.h> + +IMPORT_SYM(unsigned long, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START); +IMPORT_SYM(unsigned long, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END); +IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_START); +IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_END); +IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START); +IMPORT_SYM(unsigned long, __RW_END__, BL31_RW_END); + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \ + (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \ + (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT)) + +const static int imx8qm_cci_map[] = { + CLUSTER0_CCI_SLVAE_IFACE, + CLUSTER1_CCI_SLVAE_IFACE +}; + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(PLAT_CCI_BASE, PLAT_CCI_SIZE, MT_DEVICE | MT_RW), + {0} +}; + +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + + return spsr; +} + +#if DEBUG_CONSOLE_A53 +static void lpuart32_serial_setbrg(unsigned int base, int baudrate) +{ + unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr; + unsigned int diff1, diff2, tmp, rate; + + if (baudrate == 0) + panic(); + + sc_pm_get_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate); + + baud_diff = baudrate; + osr = 0; + sbr = 0; + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { + tmp_sbr = (rate / (baudrate * tmp_osr)); + if (tmp_sbr == 0) + tmp_sbr = 1; + + /* calculate difference in actual baud w/ current values */ + diff1 = rate / (tmp_osr * tmp_sbr) - baudrate; + diff2 = rate / (tmp_osr * (tmp_sbr + 1)); + + /* select best values between sbr and sbr+1 */ + if (diff1 > (baudrate - diff2)) { + diff1 = baudrate - diff2; + tmp_sbr++; + } + + if (diff1 <= baud_diff) { + baud_diff = diff1; + osr = tmp_osr; + sbr = tmp_sbr; + } + } + + tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD); + + if ((osr > 3) && (osr < 8)) + tmp |= LPUART_BAUD_BOTHEDGE_MASK; + + tmp &= ~LPUART_BAUD_OSR_MASK; + tmp |= LPUART_BAUD_OSR(osr - 1); + tmp &= ~LPUART_BAUD_SBR_MASK; + tmp |= LPUART_BAUD_SBR(sbr); + + /* explicitly disable 10 bit mode & set 1 stop bit */ + tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); + + mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp); +} + +static int lpuart32_serial_init(unsigned int base) +{ + unsigned int tmp; + + /* disable TX & RX before enabling clocks */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(CTRL_TE | CTRL_RE); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0); + mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE)); + + mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0); + + /* provide data bits, parity, stop bit, etc */ + lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE); + + /* eight data bits no parity bit */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE); + + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A); + + return 0; +} +#endif + +void mx8_partition_resources(void) +{ + sc_rm_pt_t secure_part, os_part; + sc_rm_mr_t mr, mr_record = 64; + sc_faddr_t start, end; + bool owned, owned2; + sc_err_t err; + int i; + + err = sc_rm_get_partition(ipc_handle, &secure_part); + + err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false, + false, false, false); + + err = sc_rm_set_parent(ipc_handle, os_part, secure_part); + + /* set secure resources to NOT-movable */ + for (i = 0; i < ARRAY_SIZE(secure_rsrcs); i++) { + err = sc_rm_set_resource_movable(ipc_handle, secure_rsrcs[i], + secure_rsrcs[i], false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + secure_rsrcs[i], err); + } + + owned = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_0_PID0); + if (owned) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0, + SC_R_M4_0_PID0, false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + } + + owned2 = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_1_PID0); + if (owned2) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0, + SC_R_M4_1_PID0, false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + } + /* move all movable resources and pins to non-secure partition */ + err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true); + if (err) + ERROR("sc_rm_move_all: %u\n", err); + + /* iterate through peripherals to give NS OS part access */ + for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) { + err = sc_rm_set_peripheral_permissions(ipc_handle, ns_access_allowed[i], + os_part, SC_RM_PERM_FULL); + if (err) + ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \ + ret %u\n", ns_access_allowed[i], err); + } + + if (owned) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0, + SC_R_M4_0_PID0, true); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_0_PID0); + if (err) + ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n", + SC_R_M4_0_PID0, err); + } + if (owned2) { + err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0, + SC_R_M4_1_PID0, true); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_1_PID0); + if (err) + ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n", + SC_R_M4_1_PID0, err); + } + + /* + * sc_rm_set_peripheral_permissions + * sc_rm_set_memreg_permissions + * sc_rm_set_pin_movable + */ + + for (mr = 0; mr < 64; mr++) { + owned = sc_rm_is_memreg_owned(ipc_handle, mr); + if (owned) { + err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr); + NOTICE("Memreg %u 0x%llx -- 0x%llx\n", mr, start, end); + if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) { + mr_record = mr; /* Record the mr for ATF running */ + } else { + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx, \ + err %d\n", start, end, err); + } + } + } + + if (mr_record != 64) { + err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr_record); + if ((BL31_LIMIT - 1) < end) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n", + (sc_faddr_t)BL31_LIMIT, end); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n", + (sc_faddr_t)BL31_LIMIT, end); + } + + if (start < (BL31_BASE - 1)) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n", + start, (sc_faddr_t)BL31_BASE - 1); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n", + start, (sc_faddr_t)BL31_BASE - 1); + } + } + + if (err) + NOTICE("Partitioning Failed\n"); + else + NOTICE("Non-secure Partitioning Succeeded\n"); + +} + +void bl31_early_platform_setup(bl31_params_t *from_bl2, + void *plat_params_from_bl2) +{ +#if DEBUG_CONSOLE + static console_lpuart_t console; +#endif + if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE) + panic(); + +#if DEBUG_CONSOLE_A53 + sc_pm_set_resource_power_mode(ipc_handle, SC_R_UART_0, SC_PM_PW_MODE_ON); + sc_pm_clock_rate_t rate = 80000000; + sc_pm_set_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate); + sc_pm_clock_enable(ipc_handle, SC_R_UART_0, 2, true, false); + + /* configure UART pads */ + sc_pad_set(ipc_handle, SC_P_UART0_RX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, SC_P_UART0_TX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, SC_P_UART0_RTS_B, UART_PAD_CTRL); + sc_pad_set(ipc_handle, SC_P_UART0_CTS_B, UART_PAD_CTRL); + lpuart32_serial_init(IMX_BOOT_UART_BASE); +#endif + +#if DEBUG_CONSOLE + console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); +#endif + + /* turn on MU1 for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON); + + /* + * create new partition for non-secure OS/Hypervisor + * uses global structs defined in sec_rsrc.h + */ + mx8_partition_resources(); + + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* init the first cluster's cci slave interface */ + cci_init(PLAT_CCI_BASE, imx8qm_cci_map, PLATFORM_CLUSTER_COUNT); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +void bl31_plat_arch_setup(void) +{ + unsigned long ro_start = BL31_RO_START; + unsigned long ro_size = BL31_RO_END - BL31_RO_START; + unsigned long rw_start = BL31_RW_START; + unsigned long rw_size = BL31_RW_END - BL31_RW_START; +#if USE_COHERENT_MEM + unsigned long coh_start = BL31_COHERENT_RAM_START; + unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START; +#endif + + mmap_add_region(ro_start, ro_start, ro_size, + MT_RO | MT_MEMORY | MT_SECURE); + mmap_add_region(rw_start, rw_start, rw_size, + MT_RW | MT_MEMORY | MT_SECURE); + mmap_add(imx_mmap); + +#if USE_COHERENT_MEM + mmap_add_region(coh_start, coh_start, coh_size, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + /* setup xlat table */ + init_xlat_tables(); + /* enable the MMU */ + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + plat_gic_driver_init(); + plat_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl31_plat_runtime_setup(void) +{ + return; +} diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c new file mode 100644 index 000000000..b9b794bec --- /dev/null +++ b/plat/imx/imx8qm/imx8qm_psci.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <cci.h> +#include <debug.h> +#include <gicv3.h> +#include <mmio.h> +#include <plat_imx8.h> +#include <psci.h> +#include <sci/sci.h> +#include <stdbool.h> + +const static int ap_core_index[PLATFORM_CORE_COUNT] = { + SC_R_A53_0, SC_R_A53_1, SC_R_A53_2, + SC_R_A53_3, SC_R_A72_0, SC_R_A72_1, +}; + +/* need to enable USE_COHERENT_MEM to avoid coherence issue */ +#if USE_COHERENT_MEM +static unsigned int a53_cpu_on_number __section("tzfw_coherent_mem"); +static unsigned int a72_cpu_on_number __section("tzfw_coherent_mem"); +#endif + +int imx_pwr_domain_on(u_register_t mpidr) +{ + int ret = PSCI_E_SUCCESS; + unsigned int cluster_id, cpu_id; + + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id); + + if (cluster_id == 0) { + if (a53_cpu_on_number == 0) + sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON); + + if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_ON) != SC_ERR_NONE) { + ERROR("cluster0 core %d power on failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id], + true, BL31_BASE) != SC_ERR_NONE) { + ERROR("boot cluster0 core %d failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + } else { + if (a72_cpu_on_number == 0) + sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); + + if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4], + SC_PM_PW_MODE_ON) != SC_ERR_NONE) { + ERROR(" cluster1 core %d power on failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4], + true, BL31_BASE) != SC_ERR_NONE) { + ERROR("boot cluster1 core %d failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + } + + return ret; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + + if (cluster_id == 0 && a53_cpu_on_number++ == 0) + cci_enable_snoop_dvm_reqs(0); + if (cluster_id == 1 && a72_cpu_on_number++ == 0) + cci_enable_snoop_dvm_reqs(1); + + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +} + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uint64_t mpidr = read_mpidr_el1(); + unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + + imx_mailbox_init(sec_entrypoint); + *psci_ops = &imx_plat_psci_ops; + + if (cluster_id == 0) + a53_cpu_on_number++; + else + a72_cpu_on_number++; + + return 0; +} diff --git a/plat/imx/imx8qm/include/platform_def.h b/plat/imx/imx8qm/include/platform_def.h new file mode 100644 index 000000000..51c2e1e18 --- /dev/null +++ b/plat/imx/imx8qm/include/platform_def.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0X400 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU 0x0 +#define PLATFORM_MAX_CPU_PER_CLUSTER 4 +#define PLATFORM_CLUSTER_COUNT 2 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 +#define PLATFORM_CLUSTER1_CORE_COUNT 2 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT) + +#define IMX_PWR_LVL0 MPIDR_AFFLVL0 +#define IMX_PWR_LVL1 MPIDR_AFFLVL1 +#define IMX_PWR_LVL2 MPIDR_AFFLVL2 + +#define PWR_DOMAIN_AT_MAX_LVL 1 +#define PLAT_MAX_PWR_LVL 2 +#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_RET_STATE 1 + +#define BL31_BASE 0x80000000 +#define BL31_LIMIT 0x80020000 + +#define PLAT_GICD_BASE 0x51a00000 +#define PLAT_GICD_SIZE 0x10000 +#define PLAT_GICR_BASE 0x51b00000 +#define PLAT_GICR_SIZE 0xc0000 +#define PLAT_CCI_BASE 0x52090000 +#define PLAT_CCI_SIZE 0x10000 +#define CLUSTER0_CCI_SLVAE_IFACE 3 +#define CLUSTER1_CCI_SLVAE_IFACE 4 +#define IMX_BOOT_UART_BASE 0x5a060000 +#define IMX_BOOT_UART_SIZE 0x1000 +#define IMX_BOOT_UART_BAUDRATE 115200 +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT__CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 +#define SC_IPC_BASE 0x5d1b0000 +#define SC_IPC_SIZE 0x10000 + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET 0x80020000 + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 12 + +#define DEBUG_CONSOLE 0 +#define DEBUG_CONSOLE_A53 0 +#define PLAT_IMX8QM 1 diff --git a/plat/imx/imx8qm/include/sec_rsrc.h b/plat/imx/imx8qm/include/sec_rsrc.h new file mode 100644 index 000000000..a623cd3f1 --- /dev/null +++ b/plat/imx/imx8qm/include/sec_rsrc.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* resources that are going to stay in secure partition */ +sc_rsrc_t secure_rsrcs[] = { + SC_R_MU_0A, + SC_R_A53, + SC_R_A53_0, + SC_R_A53_1, + SC_R_A53_2, + SC_R_A53_3, + SC_R_A72, + SC_R_A72_0, + SC_R_A72_1, + SC_R_GIC, + SC_R_GIC_SMMU, + SC_R_CCI, + SC_R_SYSTEM, + SC_R_IRQSTR_SCU2 +}; + +/* resources that have register access for non-secure domain */ +sc_rsrc_t ns_access_allowed[] = { + SC_R_GIC, + SC_R_GIC_SMMU, + SC_R_CCI +}; diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk new file mode 100644 index 000000000..c295e14bf --- /dev/null +++ b/plat/imx/imx8qm/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/imx8qm/include \ + -Iplat/imx/common/include \ + +IMX_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/arm_gicv3_common.c \ + drivers/arm/gic/v3/gic500.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/common/gic_common.c \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/lpuart_console.S \ + plat/imx/common/imx8_helpers.S \ + plat/imx/imx8qm/imx8qm_bl31_setup.c \ + plat/imx/imx8qm/imx8qm_psci.c \ + plat/imx/common/imx8_topology.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + drivers/console/aarch64/console.S \ + drivers/arm/cci/cci.c \ + ${IMX_GIC_SOURCES} \ + +include plat/imx/common/sci/sci_api.mk + +ENABLE_PLAT_COMPAT := 0 +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +ARM_GIC_ARCH := 3 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +MULTI_CONSOLE_API := 1 +ERRATA_A72_859971 := 1 diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c new file mode 100644 index 000000000..8dac9439d --- /dev/null +++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <cci.h> +#include <console.h> +#include <context.h> +#include <context_mgmt.h> +#include <debug.h> +#include <imx8qx_pads.h> +#include <imx8_iomux.h> +#include <imx8_lpuart.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <plat_imx8.h> +#include <sci/sci.h> +#include <sec_rsrc.h> +#include <stdbool.h> +#include <xlat_tables.h> + +IMPORT_SYM(unsigned long, __COHERENT_RAM_START__, BL31_COHERENT_RAM_START); +IMPORT_SYM(unsigned long, __COHERENT_RAM_END__, BL31_COHERENT_RAM_END); +IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_START); +IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_END); +IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START); +IMPORT_SYM(unsigned long, __RW_END__, BL31_RW_END); + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \ + (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \ + (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \ + (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \ + (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT)) + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_BOOT_UART_BASE, IMX_BOOT_UART_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(SC_IPC_BASE, SC_IPC_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(PLAT_GICD_BASE, PLAT_GICD_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(PLAT_GICR_BASE, PLAT_GICR_SIZE, MT_DEVICE | MT_RW), + {0} +}; + +static uint32_t get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned long mode; + uint32_t spsr; + + /* figure out what mode we enter the non-secure world */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +#if DEBUG_CONSOLE_A35 +static void lpuart32_serial_setbrg(unsigned int base, int baudrate) +{ + unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr; + unsigned int diff1, diff2, tmp, rate; + + if (baudrate == 0) + panic(); + + sc_pm_get_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate); + + baud_diff = baudrate; + osr = 0; + sbr = 0; + for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { + tmp_sbr = (rate / (baudrate * tmp_osr)); + if (tmp_sbr == 0) + tmp_sbr = 1; + + /* calculate difference in actual baud w/ current values */ + diff1 = rate / (tmp_osr * tmp_sbr) - baudrate; + diff2 = rate / (tmp_osr * (tmp_sbr + 1)); + + /* select best values between sbr and sbr+1 */ + if (diff1 > (baudrate - diff2)) { + diff1 = baudrate - diff2; + tmp_sbr++; + } + + if (diff1 <= baud_diff) { + baud_diff = diff1; + osr = tmp_osr; + sbr = tmp_sbr; + } + } + + tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD); + + if ((osr > 3) && (osr < 8)) + tmp |= LPUART_BAUD_BOTHEDGE_MASK; + + tmp &= ~LPUART_BAUD_OSR_MASK; + tmp |= LPUART_BAUD_OSR(osr - 1); + tmp &= ~LPUART_BAUD_SBR_MASK; + tmp |= LPUART_BAUD_SBR(sbr); + + /* explicitly disable 10 bit mode & set 1 stop bit */ + tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); + + mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp); +} + +static int lpuart32_serial_init(unsigned int base) +{ + unsigned int tmp; + + /* disable TX & RX before enabling clocks */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(CTRL_TE | CTRL_RE); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0); + mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE)); + + mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0); + + /* provide data bits, parity, stop bit, etc */ + lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE); + + /* eight data bits no parity bit */ + tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL); + tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK); + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp); + + mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE); + + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55); + mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A); + + return 0; +} +#endif + +void imx8_partition_resources(void) +{ + sc_rm_pt_t secure_part, os_part; + sc_rm_mr_t mr, mr_record = 64; + sc_faddr_t start, end; + sc_err_t err; + bool owned; + int i; + + err = sc_rm_get_partition(ipc_handle, &secure_part); + if (err) + ERROR("sc_rm_get_partition failed: %u\n", err); + + err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false, + false, false, false); + if (err) + ERROR("sc_rm_partition_alloc failed: %u\n", err); + + err = sc_rm_set_parent(ipc_handle, os_part, secure_part); + if (err) + ERROR("sc_rm_set_parent: %u\n", err); + + /* set secure resources to NOT-movable */ + for (i = 0; i < (ARRAY_SIZE(secure_rsrcs)); i++) { + err = sc_rm_set_resource_movable(ipc_handle, + secure_rsrcs[i], secure_rsrcs[i], false); + if (err) + ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n", + secure_rsrcs[i], err); + } + + /* move all movable resources and pins to non-secure partition */ + err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true); + if (err) + ERROR("sc_rm_move_all: %u\n", err); + + /* iterate through peripherals to give NS OS part access */ + for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) { + err = sc_rm_set_peripheral_permissions(ipc_handle, + ns_access_allowed[i], os_part, SC_RM_PERM_FULL); + if (err) + ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \ + ret %u\n", ns_access_allowed[i], err); + } + + /* + * sc_rm_set_peripheral_permissions + * sc_rm_set_memreg_permissions + * sc_rm_set_pin_movable + */ + for (mr = 0; mr < 64; mr++) { + owned = sc_rm_is_memreg_owned(ipc_handle, mr); + if (owned) { + err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr); + + NOTICE("Memreg %u 0x%llx -- 0x%llx\n", mr, start, end); + if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) { + mr_record = mr; /* Record the mr for ATF running */ + } else { + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx, \ + err %d\n", start, end, err); + } + } + } + + if (mr_record != 64) { + err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end); + if (err) + ERROR("Memreg get info failed, %u\n", mr_record); + if ((BL31_LIMIT - 1) < end) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n", + (sc_faddr_t)BL31_LIMIT, end); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n", + (sc_faddr_t)BL31_LIMIT, end); + } + + if (start < (BL31_BASE - 1)) { + err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1); + if (err) + ERROR("sc_rm_memreg_alloc failed, 0x%llx -- 0x%llx\n", + start, (sc_faddr_t)BL31_BASE - 1); + err = sc_rm_assign_memreg(ipc_handle, os_part, mr); + if (err) + ERROR("Memreg assign failed, 0x%llx -- 0x%llx\n", + start, (sc_faddr_t)BL31_BASE - 1); + } + } + + if (err) + NOTICE("Partitioning Failed\n"); + else + NOTICE("Non-secure Partitioning Succeeded\n"); +} + +void bl31_early_platform_setup(bl31_params_t *from_bl2, + void *plat_params_from_bl2) +{ +#if DEBUG_CONSOLE + static console_lpuart_t console; +#endif + if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE) + panic(); + +#if DEBUG_CONSOLE_A35 + sc_pm_set_resource_power_mode(ipc_handle, SC_R_UART_0, SC_PM_PW_MODE_ON); + sc_pm_clock_rate_t rate = 80000000; + sc_pm_set_clock_rate(ipc_handle, SC_R_UART_0, 2, &rate); + sc_pm_clock_enable(ipc_handle, SC_R_UART_0, 2, true, false); + + /* Configure UART pads */ + sc_pad_set(ipc_handle, SC_P_UART0_RX, UART_PAD_CTRL); + sc_pad_set(ipc_handle, SC_P_UART0_TX, UART_PAD_CTRL); + lpuart32_serial_init(IMX_BOOT_UART_BASE); +#endif + +#if DEBUG_CONSOLE + console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); +#endif + /* Turn on MU1 for non-secure OS/Hypervisor */ + sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON); + + /* + * create new partition for non-secure OS/Hypervisor + * uses global structs defined in sec_rsrc.h + */ + imx8_partition_resources(); + + bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET; + bl33_image_ep_info.spsr = get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +void bl31_plat_arch_setup(void) +{ + unsigned long ro_start = BL31_RO_START; + unsigned long ro_size = BL31_RO_END - BL31_RO_START; + unsigned long rw_start = BL31_RW_START; + unsigned long rw_size = BL31_RW_END - BL31_RW_START; +#if USE_COHERENT_MEM + unsigned long coh_start = BL31_COHERENT_RAM_START; + unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START; +#endif + + mmap_add_region(ro_start, ro_start, ro_size, + MT_RO | MT_MEMORY | MT_SECURE); + mmap_add_region(rw_start, rw_start, rw_size, + MT_RW | MT_MEMORY | MT_SECURE); + mmap_add(imx_mmap); + +#if USE_COHERENT_MEM + mmap_add_region(coh_start, coh_start, coh_size, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + init_xlat_tables(); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + plat_gic_driver_init(); + plat_gic_init(); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + if (type == NON_SECURE) + return &bl33_image_ep_info; + if (type == SECURE) + return &bl32_image_ep_info; + + return NULL; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return COUNTER_FREQUENCY; +} + +void bl31_plat_runtime_setup(void) +{ + return; +} diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c new file mode 100644 index 000000000..47233dc8d --- /dev/null +++ b/plat/imx/imx8qx/imx8qx_psci.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <debug.h> +#include <gicv3.h> +#include <mmio.h> +#include <plat_imx8.h> +#include <psci.h> +#include <sci/sci.h> +#include <stdbool.h> + +const static int ap_core_index[PLATFORM_CORE_COUNT] = { + SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3 +}; + +plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *target_state, + unsigned int ncpu) +{ + return 0; +} + +int imx_pwr_domain_on(u_register_t mpidr) +{ + int ret = PSCI_E_SUCCESS; + unsigned int cpu_id; + + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + tf_printf("imx_pwr_domain_on cpu_id %d\n", cpu_id); + + if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id], + SC_PM_PW_MODE_ON) != SC_ERR_NONE) { + ERROR("core %d power on failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id], + true, BL31_BASE) != SC_ERR_NONE) { + ERROR("boot core %d failed!\n", cpu_id); + ret = PSCI_E_INTERN_FAIL; + } + + return ret; +} + +void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +} + +int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) +{ + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t imx_plat_psci_ops = { + .pwr_domain_on = imx_pwr_domain_on, + .pwr_domain_on_finish = imx_pwr_domain_on_finish, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + imx_mailbox_init(sec_entrypoint); + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h new file mode 100644 index 000000000..2cd140097 --- /dev/null +++ b/plat/imx/imx8qx/include/platform_def.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE 0x400 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU 0x0 +#define PLATFORM_MAX_CPU_PER_CLUSTER 4 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CORE_COUNT 4 + +#define PWR_DOMAIN_AT_MAX_LVL 1 +#define PLAT_MAX_PWR_LVL 2 +#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_RET_STATE 1 + +#define BL31_BASE 0x80000000 +#define BL31_LIMIT 0x80020000 + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) + +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 8 + +#define PLAT_GICD_BASE 0x51a00000 +#define PLAT_GICD_SIZE 0x10000 +#define PLAT_GICR_BASE 0x51b00000 +#define PLAT_GICR_SIZE 0xc0000 +#define IMX_BOOT_UART_BASE 0x5a060000 +#define IMX_BOOT_UART_SIZE 0x1000 +#define IMX_BOOT_UART_BAUDRATE 115200 +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT__CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 +#define SC_IPC_BASE 0x5d1b0000 +#define SC_IPC_SIZE 0x10000 + +#define COUNTER_FREQUENCY 8000000 + +/* non-secure u-boot base */ +#define PLAT_NS_IMAGE_OFFSET 0x80020000 + +#define DEBUG_CONSOLE 0 +#define DEBUG_CONSOLE_A35 0 +#define PLAT_IMX8QX 1 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/imx/imx8qx/include/sec_rsrc.h b/plat/imx/imx8qx/include/sec_rsrc.h new file mode 100644 index 000000000..37c9f6637 --- /dev/null +++ b/plat/imx/imx8qx/include/sec_rsrc.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* resources that are going to stay in secure partition */ +sc_rsrc_t secure_rsrcs[] = { + SC_R_MU_0A, + SC_R_A35, + SC_R_A35_0, + SC_R_A35_1, + SC_R_A35_2, + SC_R_A35_3, + SC_R_GIC, + SC_R_SYSTEM, + SC_R_IRQSTR_SCU2 +}; + +/* resources that have register access for non-secure domain */ +sc_rsrc_t ns_access_allowed[] = { + SC_R_GIC, +}; diff --git a/plat/imx/imx8qx/platform.mk b/plat/imx/imx8qx/platform.mk new file mode 100644 index 000000000..c16ce6e60 --- /dev/null +++ b/plat/imx/imx8qx/platform.mk @@ -0,0 +1,35 @@ +# +# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/imx8qx/include \ + -Iplat/imx/common/include \ + +IMX_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/arm_gicv3_common.c \ + drivers/arm/gic/v3/gic500.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/common/gic_common.c \ + plat/common/plat_gicv3.c \ + plat/imx/common/plat_imx8_gic.c + +BL31_SOURCES += plat/imx/common/lpuart_console.S \ + plat/imx/common/imx8_helpers.S \ + plat/imx/imx8qx/imx8qx_bl31_setup.c \ + plat/imx/imx8qx/imx8qx_psci.c \ + plat/imx/common/imx8_topology.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/cpus/aarch64/cortex_a35.S \ + drivers/console/aarch64/console.S \ + ${IMX_GIC_SOURCES} \ + +include plat/imx/common/sci/sci_api.mk + +ENABLE_PLAT_COMPAT := 0 +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +ARM_GIC_ARCH := 3 +MULTI_CONSOLE_API := 1 diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h index 679216c84..e847b2e0e 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.h +++ b/plat/rockchip/rk3399/drivers/dram/dfs.h @@ -7,6 +7,8 @@ #ifndef __SOC_ROCKCHIP_RK3399_DFS_H__ #define __SOC_ROCKCHIP_RK3399_DFS_H__ +#include <stdint.h> + struct rk3399_sdram_default_config { unsigned char bl; /* 1:auto precharge, 0:never auto precharge */ diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index ae74c9c40..3f0f619f2 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -11,7 +11,6 @@ #include <plat_sip_calls.h> #include <rockchip_sip_svc.h> #include <runtime_svc.h> -#include <stdint.h> #define RK_SIP_DDR_CFG 0x82000008 #define DRAM_INIT 0x00 diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c index e3acfe9f6..6a3c1d604 100644 --- a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c +++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c @@ -99,6 +99,10 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), +#ifdef SPD_opteed + .image_info.image_base = RPI3_OPTEE_PAGEABLE_LOAD_BASE, + .image_info.image_max_size = RPI3_OPTEE_PAGEABLE_LOAD_SIZE, +#endif .next_handoff_image_id = INVALID_IMAGE_ID, }, # endif /* BL32_BASE */ diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h index 5e2f1da50..ebd77cd17 100644 --- a/plat/rpi3/include/platform_def.h +++ b/plat/rpi3/include/platform_def.h @@ -181,6 +181,13 @@ #define BL32_DRAM_BASE SEC_DRAM0_BASE #define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE) +#ifdef SPD_opteed +/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */ +#define RPI3_OPTEE_PAGEABLE_LOAD_SIZE 0x080000 /* 512KB */ +#define RPI3_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - \ + RPI3_OPTEE_PAGEABLE_LOAD_SIZE) +#endif + #define SEC_SRAM_ID 0 #define SEC_DRAM_ID 1 diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk index 2cb7a1520..2aaf4064e 100644 --- a/plat/rpi3/platform.mk +++ b/plat/rpi3/platform.mk @@ -120,3 +120,17 @@ endif ifeq (${ARCH},aarch32) $(error Error: AArch32 not supported on rpi3) endif + +ifeq (${SPD},opteed) +BL2_SOURCES += \ + lib/optee/optee_utils.c +endif + +# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images +# in the FIP if the platform requires. +ifneq ($(BL32_EXTRA1),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c index f286caf03..13e8c0155 100644 --- a/plat/rpi3/rpi3_bl2_setup.c +++ b/plat/rpi3/rpi3_bl2_setup.c @@ -9,6 +9,7 @@ #include <bl_common.h> #include <debug.h> #include <desc_image_load.h> +#include <optee_utils.h> #include <platform_def.h> #include <xlat_mmu_helpers.h> #include <xlat_tables_defs.h> @@ -67,11 +68,28 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) { int err = 0; bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); +#ifdef SPD_opteed + bl_mem_params_node_t *pager_mem_params = NULL; + bl_mem_params_node_t *paged_mem_params = NULL; +#endif assert(bl_mem_params != NULL); switch (image_id) { case BL32_IMAGE_ID: +#ifdef SPD_opteed + pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); + assert(pager_mem_params); + + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert(paged_mem_params); + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err != 0) + WARN("OPTEE header parse error.\n"); +#endif bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); break; diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c index 03914a6d7..65f5e7ad0 100644 --- a/plat/rpi3/rpi3_common.c +++ b/plat/rpi3/rpi3_common.c @@ -34,6 +34,13 @@ #define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ MT_MEMORY | MT_RW | MT_SECURE) +#ifdef SPD_opteed +#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \ + RPI3_OPTEE_PAGEABLE_LOAD_BASE, \ + RPI3_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + /* * Table of regions for various BL stages to map using the MMU. */ @@ -42,6 +49,9 @@ static const mmap_region_t plat_rpi3_mmap[] = { MAP_SHARED_RAM, MAP_DEVICE0, MAP_FIP, +#ifdef SPD_opteed + MAP_OPTEE_PAGEABLE, +#endif {0} }; #endif @@ -190,3 +200,13 @@ uint32_t plat_ic_get_pending_interrupt_type(void) { return INTR_TYPE_INVAL; } + +uint32_t plat_interrupt_type_to_line(uint32_t type, + uint32_t security_state) +{ + /* It is not expected to receive an interrupt route to EL3. + * Hence panic() to flag error. + */ + ERROR("Interrupt not expected to be routed to EL3"); + panic(); +} diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c index 7ac45ef63..e090b2b3e 100644 --- a/plat/rpi3/rpi3_io_storage.c +++ b/plat/rpi3/rpi3_io_storage.c @@ -54,6 +54,14 @@ static const io_uuid_spec_t bl32_uuid_spec = { .uuid = UUID_SECURE_PAYLOAD_BL32, }; +static const io_uuid_spec_t bl32_extra1_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, +}; + +static const io_uuid_spec_t bl32_extra2_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, +}; + static const io_uuid_spec_t bl33_uuid_spec = { .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, }; @@ -123,6 +131,21 @@ static const struct plat_io_policy policies[] = { (uintptr_t)&bl32_uuid_spec, open_fip }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL32_EXTRA1_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra1_uuid_spec, + open_fip + }, + [BL32_EXTRA2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_extra2_uuid_spec, + open_fip + }, [BL33_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl33_uuid_spec, diff --git a/plat/socionext/synquacer/drivers/mhu/sq_mhu.c b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c new file mode 100644 index 000000000..5c2a635bb --- /dev/null +++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bakery_lock.h> +#include <mmio.h> +#include <platform_def.h> +#include <sq_common.h> +#include "sq_mhu.h" + +/* SCP MHU secure channel registers */ +#define SCP_INTR_S_STAT 0x200 +#define SCP_INTR_S_SET 0x208 +#define SCP_INTR_S_CLEAR 0x210 + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x300 +#define CPU_INTR_S_SET 0x308 +#define CPU_INTR_S_CLEAR 0x310 + +DEFINE_BAKERY_LOCK(sq_lock); + +/* + * Slot 31 is reserved because the MHU hardware uses this register bit to + * indicate a non-secure access attempt. The total number of available slots is + * therefore 31 [30:0]. + */ +#define MHU_MAX_SLOT_ID 30 + +void mhu_secure_message_start(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + bakery_lock_get(&sq_lock); + + /* Make sure any previous command has finished */ + while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id)) + ; +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))); + + /* Send command to SCP */ + mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); +} + +uint32_t mhu_secure_message_wait(void) +{ + uint32_t response; + + /* Wait for response from SCP */ + while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT))) + ; + + return response; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + /* + * Clear any response we got by writing one in the relevant slot bit to + * the CLEAR register + */ + mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); + + bakery_lock_release(&sq_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&sq_lock); + + /* + * The STAT register resets to zero. Ensure it is in the expected state, + * as a stale or garbage value would make us think it's a message we've + * already sent. + */ + assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0); +} + +void plat_sq_pwrc_setup(void) +{ + mhu_secure_init(); +} diff --git a/plat/socionext/synquacer/drivers/mhu/sq_mhu.h b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h new file mode 100644 index 000000000..bef117d7f --- /dev/null +++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SQ_MHU_H__ +#define __SQ_MHU_H__ + +#include <stdint.h> + +void mhu_secure_message_start(unsigned int slot_id); +void mhu_secure_message_send(unsigned int slot_id); +uint32_t mhu_secure_message_wait(void); +void mhu_secure_message_end(unsigned int slot_id); + +void mhu_secure_init(void); + +#endif /* __SQ_MHU_H__ */ diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.c b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c new file mode 100644 index 000000000..170b7e184 --- /dev/null +++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <platform_def.h> +#include <sq_common.h> +#include <debug.h> +#include <string.h> +#include "sq_mhu.h" +#include "sq_scpi.h" + +#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_SQ_SCP_COM_SHARED_MEM_BASE +#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SQ_SCP_COM_SHARED_MEM_BASE \ + + 0x100) + +#define SCPI_CMD_HEADER_AP_TO_SCP \ + ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP) +#define SCPI_CMD_PAYLOAD_AP_TO_SCP \ + ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t))) + +/* ID of the MHU slot used for the SCPI protocol */ +#define SCPI_MHU_SLOT_ID 0 + +static void scpi_secure_message_start(void) +{ + mhu_secure_message_start(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_send(size_t payload_size) +{ + /* + * Ensure that any write to the SCPI payload area is seen by SCP before + * we write to the MHU register. If these 2 writes were reordered by + * the CPU then SCP would read stale payload data + */ + dmbst(); + + mhu_secure_message_send(SCPI_MHU_SLOT_ID); +} + +static void scpi_secure_message_receive(scpi_cmd_t *cmd) +{ + uint32_t mhu_status; + + assert(cmd != NULL); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd)); +} + +static void scpi_secure_message_end(void) +{ + mhu_secure_message_end(SCPI_MHU_SLOT_ID); +} + +int scpi_wait_ready(void) +{ + scpi_cmd_t scpi_cmd; + scpi_status_t status = SCP_OK; + + VERBOSE("Waiting for SCP_READY command...\n"); + + /* Get a message from the SCP */ + scpi_secure_message_start(); + scpi_secure_message_receive(&scpi_cmd); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + if (scpi_cmd.id != SCPI_CMD_SCP_READY) { + ERROR("Unexpected SCP command: expected command #%u," + "got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id); + status = SCP_E_SUPPORT; + } else if (scpi_cmd.size != 0) { + ERROR("SCP_READY command has incorrect size: expected 0," + "got %u\n", scpi_cmd.size); + status = SCP_E_SIZE; + } + + VERBOSE("Sending response for SCP_READY command\n"); + + /* + * Send our response back to SCP. + * We are using the same SCPI header, just update the status field. + */ + scpi_cmd.status = status; + scpi_secure_message_start(); + memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd)); + scpi_secure_message_send(0); + scpi_secure_message_end(); + + return status == SCP_OK ? 0 : -1; +} + +void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, scpi_power_state_t sq_state) +{ + scpi_cmd_t *cmd; + uint32_t state = 0; + uint32_t *payload_addr; + + state |= mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= sq_state << 16; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SET_POWER_STATE; + cmd->set = SCPI_SET_NORMAL; + cmd->sender = 0; + cmd->size = sizeof(state); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = state; + scpi_secure_message_send(sizeof(state)); + + /* + * SCP does not reply to this command in order to avoid MHU interrupts + * from the sender, which could interfere with its power state request. + */ + scpi_secure_message_end(); +} + +uint32_t scpi_sys_power_state(scpi_system_state_t system_state) +{ + scpi_cmd_t *cmd; + uint8_t *payload_addr; + scpi_cmd_t response; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SYS_POWER_STATE; + cmd->set = 0; + cmd->sender = 0; + cmd->size = sizeof(*payload_addr); + /* Populate the command payload */ + payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP; + *payload_addr = system_state & 0xff; + scpi_secure_message_send(sizeof(*payload_addr)); + + scpi_secure_message_receive(&response); + + scpi_secure_message_end(); + + return response.status; +} + +uint32_t scpi_get_draminfo(struct draminfo *info) +{ + scpi_cmd_t *cmd; + struct { + scpi_cmd_t cmd; + struct draminfo info; + } response; + uint32_t mhu_status; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_GET_DRAMINFO; + cmd->set = SCPI_SET_EXTENDED; + cmd->sender = 0; + cmd->size = 0; + + scpi_secure_message_send(0); + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCPI message, reject any other protocol */ + if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* + * Ensure that any read to the SCPI payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); + + memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response)); + + scpi_secure_message_end(); + + if (response.cmd.status == SCP_OK) + *info = response.info; + + return response.cmd.status; +} diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h new file mode 100644 index 000000000..30fa5c72d --- /dev/null +++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SQ_SCPI_H__ +#define __SQ_SCPI_H__ + +#include <stddef.h> +#include <stdint.h> + +/* + * An SCPI command consists of a header and a payload. + * The following structure describes the header. It is 64-bit long. + */ +typedef struct { + /* Command ID */ + uint32_t id : 7; + /* Set ID. Identifies whether this is a standard or extended command. */ + uint32_t set : 1; + /* Sender ID to match a reply. The value is sender specific. */ + uint32_t sender : 8; + /* Size of the payload in bytes (0 - 511) */ + uint32_t size : 9; + uint32_t reserved : 7; + /* + * Status indicating the success of a command. + * See the enum below. + */ + uint32_t status; +} scpi_cmd_t; + +typedef enum { + SCPI_SET_NORMAL = 0, /* Normal SCPI commands */ + SCPI_SET_EXTENDED /* Extended SCPI commands */ +} scpi_set_t; + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ + SCPI_E_DEVICE, /* Device error */ + SCPI_E_BUSY, /* Device is busy */ +}; + +typedef uint32_t scpi_status_t; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_POWER_STATE = 0x03, + SCPI_CMD_SYS_POWER_STATE = 0x05 +} scpi_command_t; + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state_t; + +typedef enum { + scpi_system_shutdown = 0, + scpi_system_reboot = 1, + scpi_system_reset = 2 +} scpi_system_state_t; + +extern int scpi_wait_ready(void); +extern void scpi_set_sq_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, + scpi_power_state_t css_state); +uint32_t scpi_sys_power_state(scpi_system_state_t system_state); + +#endif /* __SQ_SCPI_H__ */ diff --git a/plat/socionext/synquacer/include/plat_macros.S b/plat/socionext/synquacer/include/plat_macros.S new file mode 100644 index 000000000..3dc06aa98 --- /dev/null +++ b/plat/socionext/synquacer/include/plat_macros.S @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +/* + * Print CCN registers + */ + .macro plat_crash_print_regs + .endm +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h new file mode 100644 index 000000000..3e1664223 --- /dev/null +++ b/plat/socionext/synquacer/include/platform_def.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include <common_def.h> + +/* CPU topology */ +#define PLAT_MAX_CORES_PER_CLUSTER 2 +#define PLAT_CLUSTER_COUNT 12 +#define PLATFORM_CORE_COUNT (PLAT_CLUSTER_COUNT * \ + PLAT_MAX_CORES_PER_CLUSTER) + +#define PLAT_MAX_PWR_LVL 1 +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define SQ_LOCAL_STATE_RUN 0 +#define SQ_LOCAL_STATE_RET 1 +#define SQ_LOCAL_STATE_OFF 2 + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 4 +#define MAX_MMAP_REGIONS 6 + +#define PLATFORM_STACK_SIZE 0x400 + +#define BL31_BASE 0x04000000 +#define BL31_SIZE 0x00080000 +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +#define PLAT_SQ_CCN_BASE 0x32000000 +#define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP \ + 0, /* Cluster 0 */ \ + 18, /* Cluster 1 */ \ + 11, /* Cluster 2 */ \ + 29, /* Cluster 3 */ \ + 35, /* Cluster 4 */ \ + 17, /* Cluster 5 */ \ + 12, /* Cluster 6 */ \ + 30, /* Cluster 7 */ \ + 14, /* Cluster 8 */ \ + 32, /* Cluster 9 */ \ + 15, /* Cluster 10 */ \ + 33 /* Cluster 11 */ + +/* UART related constants */ +#define PLAT_SQ_BOOT_UART_BASE 0x2A400000 +#define PLAT_SQ_BOOT_UART_CLK_IN_HZ 62500000 +#define SQ_CONSOLE_BAUDRATE 115200 + +#define SQ_SYS_CNTCTL_BASE 0x2a430000 + +#define SQ_SYS_TIMCTL_BASE 0x2a810000 +#define PLAT_SQ_NSTIMER_FRAME_ID 0 + +#define DRAMINFO_BASE 0x2E00FFC0 + +#define PLAT_SQ_MHU_BASE 0x45000000 + +#define PLAT_SQ_SCP_COM_SHARED_MEM_BASE 0x45400000 +#define SCPI_CMD_GET_DRAMINFO 0x1 + +#define SQ_BOOT_CFG_ADDR 0x45410000 +#define PLAT_SQ_PRIMARY_CPU_SHIFT 8 +#define PLAT_SQ_PRIMARY_CPU_BIT_WIDTH 6 + +#define PLAT_SQ_GICD_BASE 0x30000000 +#define PLAT_SQ_GICR_BASE 0x30400000 + +#define PLAT_SQ_GPIO_BASE 0x51000000 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h new file mode 100644 index 000000000..58b1e24ec --- /dev/null +++ b/plat/socionext/synquacer/include/sq_common.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SQ_COMMON_H__ +#define __SQ_COMMON_H__ + +#include <sys/types.h> +#include <xlat_tables_v2.h> + +struct draminfo { + uint32_t num_regions; + uint32_t reserved; + uint64_t base1; + uint64_t size1; + uint64_t base2; + uint64_t size2; + uint64_t base3; + uint64_t size3; +}; + +uint32_t scpi_get_draminfo(struct draminfo *info); + +void plat_sq_pwrc_setup(void); + +void plat_sq_interconnect_init(void); +void plat_sq_interconnect_enter_coherency(void); +void plat_sq_interconnect_exit_coherency(void); + +unsigned int sq_calc_core_pos(u_register_t mpidr); + +void sq_gic_driver_init(void); +void sq_gic_init(void); +void sq_gic_cpuif_enable(void); +void sq_gic_cpuif_disable(void); +void sq_gic_pcpu_init(void); + +void sq_mmap_setup(uintptr_t total_base, size_t total_size, + const struct mmap_region *mmap); + +#endif /* __SQ_COMMON_H__ */ diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk new file mode 100644 index 000000000..546f84aa1 --- /dev/null +++ b/plat/socionext/synquacer/platform.mk @@ -0,0 +1,46 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +override RESET_TO_BL31 := 1 +override ENABLE_PLAT_COMPAT := 0 +override MULTI_CONSOLE_API := 1 +override PROGRAMMABLE_RESET_ADDRESS := 1 +override USE_COHERENT_MEM := 1 +override SEPARATE_CODE_AND_RODATA := 1 +override ENABLE_SVE_FOR_NS := 0 + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_855873 := 1 + +# Libraries +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_PATH := plat/socionext/synquacer +PLAT_INCLUDES := -I$(PLAT_PATH)/include \ + -I$(PLAT_PATH)/drivers/scpi \ + -I$(PLAT_PATH)/drivers/mhu + +PLAT_BL_COMMON_SOURCES += $(PLAT_PATH)/sq_helpers.S \ + drivers/arm/pl011/pl011_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL31_SOURCES += drivers/arm/ccn/ccn.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/gicv3_main.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + $(PLAT_PATH)/sq_bl31_setup.c \ + $(PLAT_PATH)/sq_ccn.c \ + $(PLAT_PATH)/sq_topology.c \ + $(PLAT_PATH)/sq_psci.c \ + $(PLAT_PATH)/sq_gicv3.c \ + $(PLAT_PATH)/sq_xlat_setup.c \ + $(PLAT_PATH)/drivers/scpi/sq_scpi.c \ + $(PLAT_PATH)/drivers/mhu/sq_mhu.c diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c new file mode 100644 index 000000000..461c8dece --- /dev/null +++ b/plat/socionext/synquacer/sq_bl31_setup.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <platform_def.h> +#include <assert.h> +#include <bl_common.h> +#include <pl011.h> +#include <debug.h> +#include <mmio.h> +#include <sq_common.h> + +static console_pl011_t console; +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info; +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t sq_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t sq_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +void bl31_early_platform_setup(bl31_params_t *from_bl2, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + (void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE, + PLAT_SQ_BOOT_UART_CLK_IN_HZ, + SQ_CONSOLE_BAUDRATE, &console); + + console_set_scope(&console.console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); + + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = sq_get_spsr_for_bl32_entry(); +#endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; + bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} + +static void sq_configure_sys_timer(void) +{ + unsigned int reg_val; + + reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); + reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); + reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); + mmio_write_32(SQ_SYS_TIMCTL_BASE + + CNTACR_BASE(PLAT_SQ_NSTIMER_FRAME_ID), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID)); + mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val); +} + +void bl31_platform_setup(void) +{ + /* Initialize the CCN interconnect */ + plat_sq_interconnect_init(); + plat_sq_interconnect_enter_coherency(); + + /* Initialize the GIC driver, cpu and distributor interfaces */ + sq_gic_driver_init(); + sq_gic_init(); + + /* Enable and initialize the System level generic timer */ + mmio_write_32(SQ_SYS_CNTCTL_BASE + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_EN); + + /* Allow access to the System counter timer module */ + sq_configure_sys_timer(); + + /* Initialize power controller before setting up topology */ + plat_sq_pwrc_setup(); +} + +void bl31_plat_runtime_setup(void) +{ + struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE; + + scpi_get_draminfo(di); +} + +void bl31_plat_arch_setup(void) +{ + sq_mmap_setup(BL31_BASE, BL31_SIZE, NULL); + enable_mmu_el3(XLAT_TABLE_NC); +} + +void bl31_plat_enable_mmu(uint32_t flags) +{ + enable_mmu_el3(flags | XLAT_TABLE_NC); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int counter_base_frequency; + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0) + panic(); + + return counter_base_frequency; +} diff --git a/plat/socionext/synquacer/sq_ccn.c b/plat/socionext/synquacer/sq_ccn.c new file mode 100644 index 000000000..bb70d5d80 --- /dev/null +++ b/plat/socionext/synquacer/sq_ccn.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <ccn.h> +#include <platform_def.h> + +static const unsigned char master_to_rn_id_map[] = { + PLAT_SQ_CLUSTER_TO_CCN_ID_MAP +}; + +static const ccn_desc_t sq_ccn_desc = { + .periphbase = PLAT_SQ_CCN_BASE, + .num_masters = ARRAY_SIZE(master_to_rn_id_map), + .master_to_rn_id_map = master_to_rn_id_map +}; + +/****************************************************************************** + * Helper function to initialize SQ CCN driver. + *****************************************************************************/ +void plat_sq_interconnect_init(void) +{ + ccn_init(&sq_ccn_desc); +} + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_sq_interconnect_enter_coherency(void) +{ + ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_sq_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/plat/socionext/synquacer/sq_gicv3.c b/plat/socionext/synquacer/sq_gicv3.c new file mode 100644 index 000000000..94e5a66b6 --- /dev/null +++ b/plat/socionext/synquacer/sq_gicv3.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <gicv3.h> +#include <interrupt_props.h> +#include <platform.h> +#include <platform_def.h> + +#include "sq_common.h" + +static uintptr_t sq_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t sq_interrupt_props[] = { + /* G0 interrupts */ + + /* SGI0 */ + INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + /* SGI6 */ + INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0, + GIC_INTR_CFG_EDGE), + + /* G1S interrupts */ + + /* Timer */ + INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_LEVEL), + /* SGI1 */ + INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI2 */ + INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI3 */ + INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI4 */ + INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI5 */ + INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE), + /* SGI7 */ + INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S, + GIC_INTR_CFG_EDGE) +}; + +static unsigned int sq_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_core_pos_by_mpidr(mpidr); +} + +static const struct gicv3_driver_data sq_gic_driver_data = { + .gicd_base = PLAT_SQ_GICD_BASE, + .gicr_base = PLAT_SQ_GICR_BASE, + .interrupt_props = sq_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(sq_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = sq_rdistif_base_addrs, + .mpidr_to_core_pos = sq_mpidr_to_core_pos, +}; + +void sq_gic_driver_init(void) +{ + gicv3_driver_init(&sq_gic_driver_data); +} + +void sq_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void sq_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void sq_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void sq_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/plat/socionext/synquacer/sq_helpers.S b/plat/socionext/synquacer/sq_helpers.S new file mode 100644 index 000000000..558aa15f6 --- /dev/null +++ b/plat/socionext/synquacer/sq_helpers.S @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <platform_def.h> + + .global sq_calc_core_pos + .global plat_my_core_pos + .global platform_mem_init + .global plat_is_my_cpu_primary + .global plat_secondary_cold_boot_setup + .global plat_crash_console_init + .global plat_crash_console_putc + .global plat_crash_console_flush + +/* + * unsigned int sq_calc_core_pos(u_register_t mpidr) + * core_pos = (cluster_id * max_cpus_per_cluster) + core_id + */ +func sq_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, lsr #7 + ret +endfunc sq_calc_core_pos + +func plat_my_core_pos + mrs x0, mpidr_el1 + b sq_calc_core_pos +endfunc plat_my_core_pos + +func platform_mem_init + ret +endfunc platform_mem_init + +/* + * Secondary CPUs are placed in a holding pen, waiting for their mailbox + * to be populated. Note that all CPUs share the same mailbox ; therefore, + * populating it will release all CPUs from their holding pen. If + * finer-grained control is needed then this should be handled in the + * code that secondary CPUs jump to. + */ +func plat_secondary_cold_boot_setup + ldr x0, sq_sec_entrypoint + + /* Wait until the mailbox gets populated */ +poll_mailbox: + cbz x0, 1f + br x0 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + +/* + * Find out whether the current cpu is the primary + * cpu (applicable only after a cold boot) + */ +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + ldr x1, =SQ_BOOT_CFG_ADDR + ldr x1, [x1] + ubfx x1, x1, #PLAT_SQ_PRIMARY_CPU_SHIFT, \ + #PLAT_SQ_PRIMARY_CPU_BIT_WIDTH + cmp x0, x1 + cset w0, eq + ret x9 +endfunc plat_is_my_cpu_primary + +/* + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + */ +func plat_crash_console_init + mov_imm x0, PLAT_SQ_BOOT_UART_BASE + mov_imm x1, PLAT_SQ_BOOT_UART_CLK_IN_HZ + mov_imm x2, SQ_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + +/* + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + */ +func plat_crash_console_putc + mov_imm x1, PLAT_SQ_BOOT_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + +/* + * int plat_crash_console_flush(int c) + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + */ +func plat_crash_console_flush + mov_imm x0, PLAT_SQ_BOOT_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c new file mode 100644 index 000000000..c327f1d48 --- /dev/null +++ b/plat/socionext/synquacer/sq_psci.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <cassert.h> +#include <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <generic_delay_timer.h> +#include <platform_def.h> +#include <sq_common.h> +#include "sq_scpi.h" +#include <psci.h> + +/* Macros to read the SQ power domain state */ +#define SQ_PWR_LVL0 MPIDR_AFFLVL0 +#define SQ_PWR_LVL1 MPIDR_AFFLVL1 +#define SQ_PWR_LVL2 MPIDR_AFFLVL2 + +#define SQ_CORE_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL0] +#define SQ_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL1] +#define SQ_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\ + (state)->pwr_domain_state[SQ_PWR_LVL2] : 0) + +uintptr_t sq_sec_entrypoint; + +int sq_pwr_domain_on(u_register_t mpidr) +{ + /* + * SCP takes care of powering up parent power domains so we + * only need to care about level 0 + */ + scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +static void sq_pwr_domain_on_finisher_common( + const psci_power_state_t *target_state) +{ + assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF); + + /* + * Perform the common cluster specific operations i.e enable coherency + * if this cluster was off. + */ + if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) + plat_sq_interconnect_enter_coherency(); +} + +void sq_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Assert that the system power domain need not be initialized */ + assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN); + + sq_pwr_domain_on_finisher_common(target_state); + + /* Program the gic per-cpu distributor or re-distributor interface */ + sq_gic_pcpu_init(); + + /* Enable the gic cpu interface */ + sq_gic_cpuif_enable(); +} + +static void sq_power_down_common(const psci_power_state_t *target_state) +{ + uint32_t cluster_state = scpi_power_on; + uint32_t system_state = scpi_power_on; + + /* Prevent interrupts from spuriously waking up this cpu */ + sq_gic_cpuif_disable(); + + /* Check if power down at system power domain level is requested */ + if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Cluster is to be turned off, so disable coherency */ + if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) { + plat_sq_interconnect_exit_coherency(); + cluster_state = scpi_power_off; + } + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_sq_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + system_state); +} + +void sq_pwr_domain_off(const psci_power_state_t *target_state) +{ + sq_power_down_common(target_state); +} + +void __dead2 sq_system_off(void) +{ + volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE; + + /* set PD[9] high to power off the system */ + gpio[5] |= 0x2; /* set output */ + gpio[1] |= 0x2; /* set high */ + dmbst(); + + generic_delay_timer_init(); + + mdelay(1); + + while (1) { + gpio[1] &= ~0x2; /* set low */ + dmbst(); + + mdelay(1); + + gpio[1] |= 0x2; /* set high */ + dmbst(); + + mdelay(100); + } + + wfi(); + ERROR("SQ System Off: operation not handled.\n"); + panic(); +} + +void __dead2 sq_system_reset(void) +{ + uint32_t response; + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("SQ System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("SQ System Reset: operation not handled.\n"); + panic(); +} + +void sq_cpu_standby(plat_local_state_t cpu_state) +{ + unsigned int scr; + + assert(cpu_state == SQ_LOCAL_STATE_RET); + + scr = read_scr_el3(); + /* Enable PhysicalIRQ bit for NS world to wake the CPU */ + write_scr_el3(scr | SCR_IRQ_BIT); + isb(); + dsb(); + wfi(); + + /* + * Restore SCR to the original value, synchronisation of scr_el3 is + * done by eret while el3_exit to save some execution cycles. + */ + write_scr_el3(scr); +} + +const plat_psci_ops_t sq_psci_ops = { + .pwr_domain_on = sq_pwr_domain_on, + .pwr_domain_off = sq_pwr_domain_off, + .pwr_domain_on_finish = sq_pwr_domain_on_finish, + .cpu_standby = sq_cpu_standby, + .system_off = sq_system_off, + .system_reset = sq_system_reset, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + sq_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&sq_sec_entrypoint, + sizeof(sq_sec_entrypoint)); + + *psci_ops = &sq_psci_ops; + + return 0; +} diff --git a/plat/socionext/synquacer/sq_topology.c b/plat/socionext/synquacer/sq_topology.c new file mode 100644 index 000000000..aa2035599 --- /dev/null +++ b/plat/socionext/synquacer/sq_topology.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <sq_common.h> +#include <platform_def.h> + +unsigned char sq_pd_tree_desc[PLAT_CLUSTER_COUNT + 1]; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + if (cluster_id >= PLAT_CLUSTER_COUNT) + return -1; + + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + if (cpu_id >= PLAT_MAX_CORES_PER_CLUSTER) + return -1; + + return sq_calc_core_pos(mpidr); +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + + sq_pd_tree_desc[0] = PLAT_CLUSTER_COUNT; + + for (i = 0; i < PLAT_CLUSTER_COUNT; i++) + sq_pd_tree_desc[i + 1] = PLAT_MAX_CORES_PER_CLUSTER; + + return sq_pd_tree_desc; +} diff --git a/plat/socionext/synquacer/sq_xlat_setup.c b/plat/socionext/synquacer/sq_xlat_setup.c new file mode 100644 index 000000000..ae147003a --- /dev/null +++ b/plat/socionext/synquacer/sq_xlat_setup.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <debug.h> +#include <platform_def.h> +#include <xlat_tables_v2.h> + +#define SQ_REG_REGION_BASE 0x20000000ULL +#define SQ_REG_REGION_SIZE 0x60000000ULL + +void sq_mmap_setup(uintptr_t total_base, size_t total_size, + const struct mmap_region *mmap) +{ + VERBOSE("Trusted RAM seen by this BL image: %p - %p\n", + (void *)total_base, (void *)(total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_NON_CACHEABLE | MT_RW | MT_SECURE); + + /* remap the code section */ + VERBOSE("Code region: %p - %p\n", + (void *)BL_CODE_BASE, (void *)BL_CODE_END); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE, + MT_NON_CACHEABLE | MT_RO | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *)BL_RO_DATA_BASE, (void *)BL_RO_DATA_END); + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + round_up(BL_RO_DATA_END, PAGE_SIZE) - BL_RO_DATA_BASE, + (MT_NON_CACHEABLE | MT_RO | MT_EXECUTE_NEVER | + MT_SECURE)); + + /* remap the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); + + /* register region */ + mmap_add_region(SQ_REG_REGION_BASE, SQ_REG_REGION_BASE, + SQ_REG_REGION_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + + /* additional regions if needed */ + if (mmap) + mmap_add(mmap); + + init_xlat_tables(); +} diff --git a/plat/socionext/uniphier/uniphier_cci.c b/plat/socionext/uniphier/uniphier_cci.c index 30f4b4761..9e00c56e3 100644 --- a/plat/socionext/uniphier/uniphier_cci.c +++ b/plat/socionext/uniphier/uniphier_cci.c @@ -13,7 +13,7 @@ #define UNIPHIER_CCI500_BASE 0x5FD00000 -static const int uniphier_cci_map[] = {0, 1}; +static const int uniphier_cci_map[] = {1, 0}; static void __uniphier_cci_init(void) { diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk new file mode 100644 index 000000000..a34221454 --- /dev/null +++ b/plat/ti/k3/board/generic/board.mk @@ -0,0 +1,17 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_BASE ?= 0x9e800000 +$(eval $(call add_define,BL32_BASE)) + +PRELOADED_BL33_BASE ?= 0x80080000 +$(eval $(call add_define,PRELOADED_BL33_BASE)) + +K3_HW_CONFIG_BASE ?= 0x82000000 +$(eval $(call add_define,K3_HW_CONFIG_BASE)) + +PLAT_INCLUDES += \ + -Iplat/ti/k3/board/generic/include \ diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h new file mode 100644 index 000000000..4c59c758c --- /dev/null +++ b/plat/ti/k3/board/generic/include/board_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __BOARD_DEF_H__ +#define __BOARD_DEF_H__ + +/* The ports must be in order and contiguous */ +#define K3_CLUSTER0_CORE_COUNT 2 +#define K3_CLUSTER0_MSMC_PORT 0 + +#define K3_CLUSTER1_CORE_COUNT 2 +#define K3_CLUSTER1_MSMC_PORT 1 + +#define K3_CLUSTER2_CORE_COUNT 2 +#define K3_CLUSTER2_MSMC_PORT 2 + +#define K3_CLUSTER3_CORE_COUNT 2 +#define K3_CLUSTER3_MSMC_PORT 3 + +/* + * This RAM will be used for the bootloader including code, bss, and stacks. + * It may need to be increased if BL31 grows in size. + */ +#define SEC_SRAM_BASE 0x70000000 /* Base of MSMC SRAM */ +#define SEC_SRAM_SIZE 0x00020000 /* 128k */ + +#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_RET_STATE 1 + +#endif /* __BOARD_DEF_H__ */ diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c new file mode 100644 index 000000000..ca7d214a1 --- /dev/null +++ b/plat/ti/k3/common/k3_bl31_setup.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <debug.h> +#include <k3_console.h> +#include <plat_arm.h> +#include <platform_def.h> +#include <k3_gicv3.h> +#include <string.h> + +/* Table of regions to map using the MMU */ +const mmap_region_t plat_arm_mmap[] = { + MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + { /* sentinel */ } +}; + +/* + * Placeholder variables for maintaining information about the next image(s) + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +static uint32_t k3_get_spsr_for_bl33_entry(void) +{ + unsigned long el_status; + unsigned int mode; + uint32_t spsr; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + mode = (el_status) ? MODE_EL2 : MODE_EL1; + + spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + return spsr; +} + +/******************************************************************************* + * Perform any BL3-1 early platform setup, such as console init and deciding on + * memory layout. + ******************************************************************************/ +void bl31_early_platform_setup(bl31_params_t *from_bl2, + void *plat_params_from_bl2) +{ + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + + bl31_console_setup(); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); +#endif + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + bl33_image_ep_info.pc = PRELOADED_BL33_BASE; + bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#ifdef K3_HW_CONFIG_BASE + /* + * According to the file ``Documentation/arm64/booting.txt`` of the + * Linux kernel tree, Linux expects the physical address of the device + * tree blob (DTB) in x0, while x1-x3 are reserved for future use and + * must be 0. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +#endif +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + bl31_early_platform_setup((void *)arg0, (void *)arg1); +} + +void bl31_plat_arch_setup(void) +{ + arm_setup_page_tables(BL31_BASE, + BL31_END - BL31_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE); + k3_gic_init(); +} + +void platform_mem_init(void) +{ + /* Do nothing for now... */ +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +/* + * Empty function to prevent the console from being uninitialized after BL33 is + * started and allow us to see messages from BL31. + */ +void bl31_plat_runtime_setup(void) +{ +} + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image + * for the security state specified. BL3-3 corresponds to the non-secure + * image type while BL3-2 corresponds to the secure image type. A NULL + * pointer is returned if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info : + &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + + NOTICE("Requested nonexistent image\n"); + return NULL; +} diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c new file mode 100644 index 000000000..ff3ca61ce --- /dev/null +++ b/plat/ti/k3/common/k3_console.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <console.h> +#include <k3_console.h> +#include <platform_def.h> +#include <uart_16550.h> + +void bl31_console_setup(void) +{ + static console_16550_t console; + + /* Initialize the console to provide early debug support */ + console_16550_register(K3_USART_BASE_ADDRESS, K3_USART_CLK_SPEED, + K3_USART_BAUD, &console); +} diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c new file mode 100644 index 000000000..3253130f6 --- /dev/null +++ b/plat/ti/k3/common/k3_gicv3.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <gicv3.h> +#include <interrupt_props.h> +#include <k3_gicv3.h> +#include <platform.h> +#include <platform_def.h> +#include <utils.h> + +/* The GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t k3_interrupt_props[] = { + PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0) +}; + +static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +gicv3_driver_data_t k3_gic_data = { + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .interrupt_props = k3_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(k3_interrupt_props), + .mpidr_to_core_pos = k3_mpidr_to_core_pos, +}; + +void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ + k3_gic_data.gicd_base = gicd_base; + k3_gic_data.gicr_base = gicr_base; + gicv3_driver_init(&k3_gic_data); +} + +void k3_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void k3_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void k3_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void k3_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S new file mode 100644 index 000000000..c95e9c367 --- /dev/null +++ b/plat/ti/k3/common/k3_helpers.S @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + +#define K3_BOOT_REASON_COLD_RESET 0x1 + + /* ------------------------------------------------------------------ + * uintptr_t plat_get_my_entrypoint(void) + * ------------------------------------------------------------------ + * + * This function is called with the called with the MMU and caches + * disabled (SCTLR_EL3.M = 0 and SCTLR_EL3.C = 0). The function is + * responsible for distinguishing between a warm and cold reset for the + * current CPU using platform-specific means. If it's a warm reset, + * then it returns the warm reset entrypoint point provided to + * plat_setup_psci_ops() during BL31 initialization. If it's a cold + * reset then this function must return zero. + * + * This function does not follow the Procedure Call Standard used by + * the Application Binary Interface for the ARM 64-bit architecture. + * The caller should not assume that callee saved registers are + * preserved across a call to this function. + */ + .globl plat_get_my_entrypoint +func plat_get_my_entrypoint + ldr x0, k3_boot_reason_data_store + cmp x0, #K3_BOOT_REASON_COLD_RESET + + /* We ONLY support cold boot at this point */ + bne plat_unsupported_boot + mov x0, #0 + ret + + /* + * We self manage our boot reason. + * At load time, we have just a default reason - which is cold reset + */ +k3_boot_reason_data_store: + .word K3_BOOT_REASON_COLD_RESET + +plat_unsupported_boot: + b plat_unsupported_boot + +endfunc plat_get_my_entrypoint + + /* ------------------------------------------------------------------ + * unsigned int plat_my_core_pos(void) + * ------------------------------------------------------------------ + * + * This function returns the index of the calling CPU which is used as a + * CPU-specific linear index into blocks of memory (for example while + * allocating per-CPU stacks). This function will be invoked very early + * in the initialization sequence which mandates that this function + * should be implemented in assembly and should not rely on the + * avalability of a C runtime environment. This function can clobber x0 + * - x8 and must preserve x9 - x29. + * + * This function plays a crucial role in the power domain topology + * framework in PSCI and details of this can be found in Power Domain + * Topology Design. + */ + .globl plat_my_core_pos +func plat_my_core_pos + mrs x0, MPIDR_EL1 + + and x1, x0, #MPIDR_CLUSTER_MASK + lsr x1, x1, #MPIDR_AFF1_SHIFT + and x0, x0, #MPIDR_CPU_MASK + +#if K3_CLUSTER1_MSMC_PORT != UNUSED + cmp x1, #K3_CLUSTER0_MSMC_PORT + b.eq out + add x0, x0, #K3_CLUSTER0_CORE_COUNT +#if K3_CLUSTER2_MSMC_PORT != UNUSED + cmp x1, #K3_CLUSTER1_MSMC_PORT + b.eq out + add x0, x0, #K3_CLUSTER1_CORE_COUNT +#if K3_CLUSTER3_MSMC_PORT != UNUSED + cmp x1, #K3_CLUSTER2_MSMC_PORT + b.eq out + add x0, x0, #K3_CLUSTER2_CORE_COUNT +#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */ +#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */ +#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */ + +out: + ret +endfunc plat_my_core_pos + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x4 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, CRASH_CONSOLE_BASE + mov_imm x1, CRASH_CONSOLE_CLK + mov_imm x2, CRASH_CONSOLE_BAUD_RATE + mov w3, #0x0 + b console_core_init + +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(void) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, CRASH_CONSOLE_BASE + b console_core_putc +endfunc plat_crash_console_putc diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c new file mode 100644 index 000000000..91602c8c1 --- /dev/null +++ b/plat/ti/k3/common/k3_psci.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <debug.h> +#include <k3_gicv3.h> +#include <psci.h> +#include <stdbool.h> + +#define STUB() ERROR("stub %s called\n", __func__) + +uintptr_t k3_sec_entrypoint; + +static void k3_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +static int k3_pwr_domain_on(u_register_t mpidr) +{ + sev(); + + /* TODO: Indicate to System firmware about powering up */ + + return PSCI_E_SUCCESS; +} + +void k3_pwr_domain_off(const psci_power_state_t *target_state) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + k3_gic_cpuif_disable(); + + /* TODO: Indicate to System firmware about powering down */ +} + +void k3_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* TODO: Indicate to System firmware about completion */ + + k3_gic_pcpu_init(); + k3_gic_cpuif_enable(); +} + +static void __dead2 k3_system_reset(void) +{ + /* TODO: Indicate to System firmware about system reset */ + STUB(); + + while (true) + wfi(); +} + +static int k3_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + /* TODO: perform the proper validation */ + + return PSCI_E_SUCCESS; +} + +static int k3_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* TODO: perform the proper validation */ + + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t k3_plat_psci_ops = { + .cpu_standby = k3_cpu_standby, + .pwr_domain_on = k3_pwr_domain_on, + .pwr_domain_off = k3_pwr_domain_off, + .pwr_domain_on_finish = k3_pwr_domain_on_finish, + .system_reset = k3_system_reset, + .validate_power_state = k3_validate_power_state, + .validate_ns_entrypoint = k3_validate_ns_entrypoint +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + k3_sec_entrypoint = sec_entrypoint; + + *psci_ops = &k3_plat_psci_ops; + + return 0; +} diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c new file mode 100644 index 000000000..a77c8f34c --- /dev/null +++ b/plat/ti/k3/common/k3_topology.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> +#include <psci.h> + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + K3_CLUSTER0_CORE_COUNT, +#if K3_CLUSTER1_MSMC_PORT != UNUSED + K3_CLUSTER1_CORE_COUNT, +#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */ +#if K3_CLUSTER2_MSMC_PORT != UNUSED + K3_CLUSTER2_CORE_COUNT, +#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */ +#if K3_CLUSTER3_MSMC_PORT != UNUSED + K3_CLUSTER3_CORE_COUNT, +#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */ +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) + return -1; + + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + + switch (MPIDR_AFFLVL1_VAL(mpidr)) { + case K3_CLUSTER0_MSMC_PORT: + if (cpu_id < K3_CLUSTER0_CORE_COUNT) + return cpu_id; + return -1; +#if K3_CLUSTER1_MSMC_PORT != UNUSED + case K3_CLUSTER1_MSMC_PORT: + if (cpu_id < K3_CLUSTER1_CORE_COUNT) + return K3_CLUSTER0_CORE_COUNT + cpu_id; + return -1; +#endif /* K3_CLUSTER1_MSMC_PORT != UNUSED */ +#if K3_CLUSTER2_MSMC_PORT != UNUSED + case K3_CLUSTER2_MSMC_PORT: + if (cpu_id < K3_CLUSTER2_CORE_COUNT) + return K3_CLUSTER0_CORE_COUNT + + K3_CLUSTER1_CORE_COUNT + cpu_id; + return -1; +#endif /* K3_CLUSTER2_MSMC_PORT != UNUSED */ +#if K3_CLUSTER3_MSMC_PORT != UNUSED + case K3_CLUSTER3_MSMC_PORT: + if (cpu_id < K3_CLUSTER3_CORE_COUNT) + return K3_CLUSTER0_CORE_COUNT + + K3_CLUSTER1_CORE_COUNT + + K3_CLUSTER2_CORE_COUNT + cpu_id; + return -1; +#endif /* K3_CLUSTER3_MSMC_PORT != UNUSED */ + default: + return -1; + } +} diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk new file mode 100644 index 000000000..bf2a73fbb --- /dev/null +++ b/plat/ti/k3/common/plat_common.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# We don't use BL1 or BL2, so BL31 is the first image to execute +RESET_TO_BL31 := 1 +# Only one core starts up at first +COLD_BOOT_SINGLE_CPU := 1 +# We can choose where a core starts executing +PROGRAMMABLE_RESET_ADDRESS:= 1 + +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 + +ERROR_DEPRECATED := 1 +ENABLE_PLAT_COMPAT := 0 + +# A53 erratum for SoC. (enable them all) +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +MULTI_CONSOLE_API := 1 +TI_16550_MDR_QUIRK := 1 +$(eval $(call add_define,TI_16550_MDR_QUIRK)) + +# Libraries +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_INCLUDES += \ + -I${PLAT_PATH}/include \ + -Iinclude/plat/arm/common/ \ + -Iinclude/plat/arm/common/aarch64/ \ + +K3_CONSOLE_SOURCES += \ + drivers/console/aarch64/console.S \ + drivers/ti/uart/aarch64/16550_console.S \ + ${PLAT_PATH}/common/k3_console.c \ + +K3_GIC_SOURCES += \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + plat/common/plat_gicv3.c \ + ${PLAT_PATH}/common/k3_gicv3.c \ + +K3_PSCI_SOURCES += \ + plat/common/plat_psci_common.c \ + ${PLAT_PATH}/common/k3_psci.c \ + +PLAT_BL_COMMON_SOURCES += \ + plat/arm/common/arm_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + ${XLAT_TABLES_LIB_SRCS} \ + ${K3_CONSOLE_SOURCES} \ + +BL31_SOURCES += \ + ${PLAT_PATH}/common/k3_bl31_setup.c \ + ${PLAT_PATH}/common/k3_helpers.S \ + ${PLAT_PATH}/common/k3_topology.c \ + ${K3_GIC_SOURCES} \ + ${K3_PSCI_SOURCES} \ diff --git a/plat/ti/k3/include/k3_console.h b/plat/ti/k3/include/k3_console.h new file mode 100644 index 000000000..5b01a31f2 --- /dev/null +++ b/plat/ti/k3/include/k3_console.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __K3_CONSOLE_H__ +#define __K3_CONSOLE_H__ + +void bl31_console_setup(void); + +#endif /* __K3_CONSOLE_H__ */ diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h new file mode 100644 index 000000000..bbf5bf9fe --- /dev/null +++ b/plat/ti/k3/include/k3_gicv3.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __K3_GICV3_H__ +#define __K3_GICV3_H__ + +void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base); +void k3_gic_init(void); +void k3_gic_cpuif_enable(void); +void k3_gic_cpuif_disable(void); +void k3_gic_pcpu_init(void); + +#endif /* __K3_GICV3_H__ */ diff --git a/plat/ti/k3/include/plat_macros.S b/plat/ti/k3/include/plat_macros.S new file mode 100644 index 000000000..96d1cd20d --- /dev/null +++ b/plat/ti/k3/include/plat_macros.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* STUB */ + .endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h new file mode 100644 index 000000000..8856af2ca --- /dev/null +++ b/plat/ti/k3/include/platform_def.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include <arch.h> +#include <board_def.h> +#include <common_def.h> + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stack */ +#if IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#else +#define PLATFORM_STACK_SIZE 0x1000 +#endif + +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CORE_COUNT (K3_CLUSTER0_CORE_COUNT + \ + K3_CLUSTER1_CORE_COUNT + \ + K3_CLUSTER2_CORE_COUNT + \ + K3_CLUSTER3_CORE_COUNT) + +#define PLATFORM_CLUSTER_COUNT ((K3_CLUSTER0_MSMC_PORT != UNUSED) + \ + (K3_CLUSTER1_MSMC_PORT != UNUSED) + \ + (K3_CLUSTER2_MSMC_PORT != UNUSED) + \ + (K3_CLUSTER3_MSMC_PORT != UNUSED)) + +#define UNUSED -1 + +#if !defined(K3_CLUSTER1_CORE_COUNT) || !defined(K3_CLUSTER1_MSMC_PORT) +#define K3_CLUSTER1_CORE_COUNT 0 +#define K3_CLUSTER1_MSMC_PORT UNUSED +#endif + +#if !defined(K3_CLUSTER2_CORE_COUNT) || !defined(K3_CLUSTER2_MSMC_PORT) +#define K3_CLUSTER2_CORE_COUNT 0 +#define K3_CLUSTER2_MSMC_PORT UNUSED +#endif + +#if !defined(K3_CLUSTER3_CORE_COUNT) || !defined(K3_CLUSTER3_MSMC_PORT) +#define K3_CLUSTER3_CORE_COUNT 0 +#define K3_CLUSTER3_MSMC_PORT UNUSED +#endif + +#if K3_CLUSTER0_MSMC_PORT == UNUSED +#error "ARM cluster 0 must be used" +#endif + +#if ((K3_CLUSTER1_MSMC_PORT == UNUSED) && (K3_CLUSTER1_CORE_COUNT != 0)) || \ + ((K3_CLUSTER2_MSMC_PORT == UNUSED) && (K3_CLUSTER2_CORE_COUNT != 0)) || \ + ((K3_CLUSTER3_MSMC_PORT == UNUSED) && (K3_CLUSTER3_CORE_COUNT != 0)) +#error "Unused ports must have 0 ARM cores" +#endif + +#define PLATFORM_CLUSTER_OFFSET K3_CLUSTER0_MSMC_PORT + +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 + +/******************************************************************************* + * Memory layout constants + ******************************************************************************/ + +/* + * ARM-TF lives in SRAM, partition it here + */ + +#define SHARED_RAM_BASE BL31_LIMIT +#define SHARED_RAM_SIZE 0x00001000 + +/* + * BL3-1 specific defines. + * + * Put BL3-1 at the base of the Trusted SRAM, before SHARED_RAM. + */ +#define BL31_BASE SEC_SRAM_BASE +#define BL31_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL31_LIMIT + +/* + * Defines the maximum number of translation tables that are allocated by the + * translation table library code. To minimize the amount of runtime memory + * used, choose the smallest value needed to map the required virtual addresses + * for each BL stage. + */ +#define MAX_XLAT_TABLES 8 + +/* + * Defines the maximum number of regions that are allocated by the translation + * table library code. A region consists of physical base address, virtual base + * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as + * defined in the `mmap_region_t` structure. The platform defines the regions + * that should be mapped. Then, the translation table library will create the + * corresponding tables and descriptors at runtime. To minimize the amount of + * runtime memory used, choose the smallest value needed to register the + * required regions for each BL stage. + */ +#define MAX_MMAP_REGIONS 8 + +/* + * Defines the total size of the address space in bytes. For example, for a 32 + * bit address space, this value should be `(1ull << 32)`. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* Platform default console definitions */ +#ifndef K3_USART_BASE_ADDRESS +#define K3_USART_BASE_ADDRESS 0x02800000 +#endif + +/* USART has a default size for address space */ +#define K3_USART_SIZE 0x1000 + +#ifndef K3_USART_CLK_SPEED +#define K3_USART_CLK_SPEED 48000000 +#endif + +#ifndef K3_USART_BAUD +#define K3_USART_BAUD 115200 +#endif + +/* Crash console defaults */ +#define CRASH_CONSOLE_BASE K3_USART_BASE_ADDRESS +#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED +#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD + +/* Timer frequency */ +#ifndef SYS_COUNTER_FREQ_IN_TICKS +#define SYS_COUNTER_FREQ_IN_TICKS 200000000 +#endif + +/* Interrupt numbers */ +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE) + +#define K3_GICD_BASE 0x01800000 +#define K3_GICD_SIZE 0x10000 +#define K3_GICR_BASE 0x01880000 +#define K3_GICR_SIZE 0x100000 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk new file mode 100644 index 000000000..65d5cc2a4 --- /dev/null +++ b/plat/ti/k3/platform.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_PATH := plat/ti/k3 +TARGET_BOARD ?= generic + +include ${PLAT_PATH}/common/plat_common.mk +include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk + +# modify BUILD_PLAT to point to board specific build directory +BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE} diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index b144c84bd..c3612706a 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -205,12 +205,21 @@ static char *zynqmp_get_silicon_idcode_name(void) { uint32_t id, ver, chipid[2]; size_t i, j, len; - enum pm_ret_status ret; const char *name = "EG/EV"; - ret = pm_get_chipid(chipid); - if (ret) +#ifdef IMAGE_BL32 + /* + * For BL32, get the chip id info directly by reading corresponding + * registers instead of making pm call. This has limitation + * that these registers should be configured to have access + * from APU which is default case. + */ + chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET); +#else + if (pm_get_chipid(chipid) != PM_RET_SUCCESS) return "UNKN"; +#endif id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK); diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h index ebbc8c2cd..49766cc92 100644 --- a/plat/xilinx/zynqmp/include/platform_def.h +++ b/plat/xilinx/zynqmp/include/platform_def.h @@ -34,7 +34,7 @@ * little space for growth. */ #ifndef ZYNQMP_ATF_MEM_BASE -#if !DEBUG +#if !DEBUG && defined(SPD_none) # define BL31_BASE 0xfffea000 # define BL31_LIMIT 0xffffffff #else |