diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst index ab33a8a..a69f022 100644 --- a/docs/plat/imx8m.rst +++ b/docs/plat/imx8m.rst @@ -31,6 +31,7 @@ CROSS_COMPILE=aarch64-linux-gnu- make PLAT= bl31 Target_SoC should be "imx8mq" for i.MX8MQ SoC. + Target_SoC should be "imx8mm" for i.MX8MM SoC. Deploy TF-A Images ----------------- diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c new file mode 100644 index 0000000..ab59292 --- /dev/null +++ b/plat/imx/imx8m/imx8mm/gpc.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +void imx_gpc_init(void) +{ + unsigned int val; + int i; + + /* mask all the wakeup irq by default */ + for (i = 0; i < 4; i++) { + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0); + mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0); + } + + val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC); + /* use GIC wake_request to wakeup C0~C3 from LPM */ + val |= 0x30c00000; + /* clear the MASTER0 LPM handshake */ + val &= ~(1 << 6); + mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val); + + /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */ + mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING | + MASTER2_MAPPING)); + + /* set all mix/PU in A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff); + + /* + * Set the CORE & SCU power up timing: + * SW = 0x1, SW2ISO = 0x1; + * the CPU CORE and SCU power up timming counter + * is drived by 32K OSC, each domain's power up + * latency is (SW + SW2ISO) / 32768 + */ + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x81); + mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING, + (0x59 << 10) | 0x5B | (0x2 << 20)); + + /* set DUMMY PDN/PUP ACK by default for A53 domain */ + mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, + A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK); + + /* clear DSM by default */ + val = mmio_read_32(IMX_GPC_BASE + SLPCR); + val &= ~SLPCR_EN_DSM; + /* enable the fast wakeup wait mode */ + val |= SLPCR_A53_FASTWUP_WAIT_MODE; + /* clear the RBC */ + val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT); + /* set the STBY_COUNT to 0x5, (128 * 30)us */ + val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT); + val |= (0x5 << SLPCR_STBY_COUNT_SHFT); + mmio_write_32(IMX_GPC_BASE + SLPCR, val); + + /* + * USB PHY power up needs to make sure RESET bit in SRC is clear, + * otherwise, the PU power up bit in GPC will NOT self-cleared. + * only need to do it once. + */ + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1); + mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1); + + /* enable all the power domain by default */ + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf); +} diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c new file mode 100644 index 0000000..a541ed3 --- /dev/null +++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const mmap_region_t imx_mmap[] = { + MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), + MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */ + {0}, +}; + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* get SPSR for BL33 entry */ +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; +} + +void bl31_tzc380_setup(void) +{ + unsigned int val; + + val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28); + if ((val & GPR_TZASC_EN) != GPR_TZASC_EN) + return; + + tzc380_init(IMX_TZASC_BASE); + + /* + * Need to substact offset 0x40000000 from CPU address when + * programming tzasc region for i.mx8mm. + */ + + /* Enable 1G-5G S/NS RW */ + tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_uart_t console; + int i; + + /* Enable CSU NS access permission */ + for (i = 0; i < 64; i++) { + mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff); + } + + + console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ, + IMX_CONSOLE_BAUDRATE, &console); + /* This console is only used for boot stage */ + console_set_scope(&console.console, CONSOLE_FLAG_BOOT); + + /* + * tell BL3-1 where the non-secure software image is located + * and the entry state information. + */ + 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); + + bl31_tzc380_setup(); +} + +void bl31_plat_arch_setup(void) +{ + 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_MEMORY | MT_RO | MT_SECURE); +#if USE_COHERENT_MEM + 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); +#endif + mmap_add(imx_mmap); + + init_xlat_tables(); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + generic_delay_timer_init(); + + /* select the CKIL source to 32K OSC */ + mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1); + + plat_gic_driver_init(); + plat_gic_init(); + + imx_gpc_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; +} diff --git a/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/plat/imx/imx8m/imx8mm/imx8mm_psci.c new file mode 100644 index 0000000..e558724 --- /dev/null +++ b/plat/imx/imx8m/imx8mm/imx8mm_psci.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +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, + .pwr_domain_off = imx_pwr_domain_off, + .validate_ns_entrypoint = imx_validate_ns_entrypoint, + .validate_power_state = imx_validate_power_state, + .cpu_standby = imx_cpu_standby, + .pwr_domain_suspend = imx_domain_suspend, + .pwr_domain_suspend_finish = imx_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, + .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, + .system_reset = imx_system_reset, + .system_off = imx_system_off, +}; + +/* export the platform specific psci ops */ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* sec_entrypoint is used for warm reset */ + imx_mailbox_init(sec_entrypoint); + + *psci_ops = &imx_plat_psci_ops; + + return 0; +} diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h new file mode 100644 index 0000000..a95ab83 --- /dev/null +++ b/plat/imx/imx8m/imx8mm/include/platform_def.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019, 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 0xB00 +#define CACHE_WRITEBACK_GRANULE 64 + +#define PLAT_PRIMARY_CPU 0x0 +#define PLATFORM_MAX_CPU_PER_CLUSTER 4 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 +#define PLATFORM_CLUSTER1_CORE_COUNT 0 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_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 U(1) +#define PLAT_MAX_PWR_LVL U(2) +#define PLAT_MAX_OFF_STATE U(4) +#define PLAT_MAX_RET_STATE U(2) + +#define PLAT_WAIT_RET_STATE U(1) +#define PLAT_STOP_OFF_STATE U(3) + +#define BL31_BASE U(0x920000) +#define BL31_LIMIT U(0x940000) +#define BL32_BASE U(0xbe000000) + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) + +/* GICv3 base address */ +#define PLAT_GICD_BASE U(0x38800000) +#define PLAT_GICR_BASE U(0x38880000) + +#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 16 + +#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */ + +#define IMX_BOOT_UART_BASE U(0x30890000) +#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */ + +#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE +#define PLAT_CRASH_UART_CLK_IN_HZ 24000000 +#define IMX_CONSOLE_BAUDRATE 115200 + +#define IMX_AIPSTZ1 U(0x301f0000) +#define IMX_AIPSTZ2 U(0x305f0000) +#define IMX_AIPSTZ3 U(0x309f0000) +#define IMX_AIPSTZ4 U(0x32df0000) + +#define IMX_AIPS_BASE U(0x30000000) +#define IMX_AIPS_SIZE U(0xC00000) +#define IMX_GPV_BASE U(0x32000000) +#define IMX_GPV_SIZE U(0x800000) +#define IMX_AIPS1_BASE U(0x30200000) +#define IMX_AIPS4_BASE U(0x32c00000) +#define IMX_ANAMIX_BASE U(0x30360000) +#define IMX_CCM_BASE U(0x30380000) +#define IMX_SRC_BASE U(0x30390000) +#define IMX_GPC_BASE U(0x303a0000) +#define IMX_RDC_BASE U(0x303d0000) +#define IMX_CSU_BASE U(0x303e0000) +#define IMX_WDOG_BASE U(0x30280000) +#define IMX_SNVS_BASE U(0x30370000) +#define IMX_NOC_BASE U(0x32700000) +#define IMX_TZASC_BASE U(0x32F80000) +#define IMX_IOMUX_GPR_BASE U(0x30340000) +#define IMX_DDRC_BASE U(0x3d400000) +#define IMX_DDRPHY_BASE U(0x3c000000) +#define IMX_DDR_IPS_BASE U(0x3d000000) +#define IMX_ROM_BASE U(0x0) + +#define GPV_BASE U(0x32000000) +#define GPV_SIZE U(0x800000) +#define IMX_GIC_BASE PLAT_GICD_BASE +#define IMX_GIC_SIZE U(0x200000) + +#define WDOG_WSR U(0x2) +#define WDOG_WCR_WDZST BIT(0) +#define WDOG_WCR_WDBG BIT(1) +#define WDOG_WCR_WDE BIT(2) +#define WDOG_WCR_WDT BIT(3) +#define WDOG_WCR_SRS BIT(4) +#define WDOG_WCR_WDA BIT(5) +#define WDOG_WCR_SRE BIT(6) +#define WDOG_WCR_WDW BIT(7) + +#define SRC_A53RCR0 U(0x4) +#define SRC_A53RCR1 U(0x8) +#define SRC_OTG1PHY_SCR U(0x20) +#define SRC_OTG2PHY_SCR U(0x24) +#define SRC_GPR1_OFFSET U(0x74) + +#define SNVS_LPCR U(0x38) +#define SNVS_LPCR_SRTC_ENV BIT(0) +#define SNVS_LPCR_DP_EN BIT(5) +#define SNVS_LPCR_TOP BIT(6) + +#define IOMUXC_GPR10 U(0x28) +#define GPR_TZASC_EN BIT(0) +#define GPR_TZASC_EN_LOCK BIT(16) + +#define ANAMIX_MISC_CTL U(0x124) + +#define MAX_CSU_NUM U(64) + +#define OCRAM_S_BASE U(0x00180000) +#define OCRAM_S_SIZE U(0x8000) +#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE) + +#define COUNTER_FREQUENCY 8000000 /* 8MHz */ + +#define IMX_WDOG_B_RESET diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk new file mode 100644 index 0000000..d50af20 --- /dev/null +++ b/plat/imx/imx8m/imx8mm/platform.mk @@ -0,0 +1,44 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iplat/imx/common/include \ + -Iplat/imx/imx8m/include \ + -Iplat/imx/imx8m/imx8mm/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/imx8_helpers.S \ + plat/imx/imx8m/gpc_common.c \ + plat/imx/imx8m/imx8m_psci_common.c \ + plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c \ + plat/imx/imx8m/imx8mm/imx8mm_psci.c \ + plat/imx/imx8m/imx8mm/gpc.c \ + plat/imx/common/imx8_topology.c \ + plat/imx/common/imx_uart_console.S \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + drivers/console/aarch64/console.S \ + drivers/arm/tzc/tzc380.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${IMX_GIC_SOURCES} + +USE_COHERENT_MEM := 1 +RESET_TO_BL31 := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +MULTI_CONSOLE_API := 1 + +ERRATA_A53_835769 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h index ce2665d..139132c 100644 --- a/plat/imx/imx8m/include/gpc.h +++ b/plat/imx/imx8m/include/gpc.h @@ -68,6 +68,9 @@ #define SLT_PLAT_PDN BIT(8) #define SLT_PLAT_PUP BIT(9) +#define MASTER1_MAPPING BIT(1) +#define MASTER2_MAPPING BIT(2) + /* helper macro */ #define A53_LPM_MASK U(0xF) #define A53_LPM_WAIT U(0x5)