diff --git a/plat/mediatek/mt8183/aarch64/platform_common.c b/plat/mediatek/mt8183/aarch64/platform_common.c index ff0aaeb..31d1339 100644 --- a/plat/mediatek/mt8183/aarch64/platform_common.c +++ b/plat/mediatek/mt8183/aarch64/platform_common.c @@ -7,10 +7,16 @@ #include #include #include +#include #include #include #include +static const int cci_map[] = { + PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX +}; + /* Table of regions to map using the MMU. */ const mmap_region_t plat_mmap[] = { /* for TF text, RO, RW */ @@ -51,3 +57,28 @@ { return SYS_COUNTER_FREQ_IN_TICKS; } + +void plat_mtk_cci_init(void) +{ + /* Initialize CCI driver */ + mcsi_init(PLAT_MT_CCI_BASE, ARRAY_SIZE(cci_map)); +} + +void plat_mtk_cci_enable(void) +{ + /* Enable CCI coherency for this cluster. + * No need for locks as no other cpu is active at the moment. + */ + cci_enable_cluster_coherency(read_mpidr()); +} + +void plat_mtk_cci_disable(void) +{ + cci_disable_cluster_coherency(read_mpidr()); +} + +void plat_mtk_cci_init_sf(void) +{ + /* Init mcsi snoop filter. */ + cci_init_sf(); +} diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c index 5a0cb87..b451189 100644 --- a/plat/mediatek/mt8183/bl31_plat_setup.c +++ b/plat/mediatek/mt8183/bl31_plat_setup.c @@ -96,6 +96,9 @@ /* Initialize the GIC driver, CPU and distributor interfaces */ mt_gic_driver_init(); mt_gic_init(); + + /* Init mcsi SF */ + plat_mtk_cci_init_sf(); } /******************************************************************************* @@ -104,6 +107,9 @@ ******************************************************************************/ void bl31_plat_arch_setup(void) { + plat_mtk_cci_init(); + plat_mtk_cci_enable(); + enable_scu(read_mpidr()); plat_configure_mmu_el3(BL_CODE_BASE, diff --git a/plat/mediatek/mt8183/drivers/mcsi/mcsi.c b/plat/mediatek/mt8183/drivers/mcsi/mcsi.c new file mode 100644 index 0000000..cbe7f0a --- /dev/null +++ b/plat/mediatek/mt8183/drivers/mcsi/mcsi.c @@ -0,0 +1,211 @@ +/* + * 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 + +#define MAX_CLUSTERS 5 + +static unsigned long cci_base_addr; +static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS]; + +void mcsi_init(unsigned long cci_base, + unsigned int num_cci_masters) +{ + int i; + + assert(cci_base); + assert(num_cci_masters < MAX_CLUSTERS); + + cci_base_addr = cci_base; + + for (i = 0; i < num_cci_masters; i++) + cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i); +} + +void mcsi_cache_flush(void) +{ + /* timeout is 10ms */ + int timeout = 10000; + + /* to make flush by SF safe, need to disable BIU DCM */ + mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8); + mmio_write_32(cci_base_addr + FLUSH_SF, 0x1); + + for (; timeout; timeout--, udelay(1)) { + if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0) + break; + } + + if (!timeout) { + INFO("SF lush timeout\n"); + return; + } + + /* enable BIU DCM as it was */ + mmio_setbits_32(CCI_CLK_CTRL, 1 << 8); +} + +static inline unsigned long get_slave_iface_base(unsigned long mpidr) +{ + /* + * We assume the TF topology code allocates affinity instances + * consecutively from zero. + * It is a programming error if this is called without initializing + * the slave interface to use for this cluster. + */ + unsigned int cluster_id = + (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + + assert(cluster_id < MAX_CLUSTERS); + assert(cci_cluster_ix_to_iface[cluster_id] != 0); + + return cci_base_addr + cci_cluster_ix_to_iface[cluster_id]; +} + +void cci_enable_cluster_coherency(unsigned long mpidr) +{ + unsigned long slave_base; + unsigned int support_ability; + unsigned int config = 0; + unsigned int pending = 0; + + assert(cci_base_addr); + slave_base = get_slave_iface_base(mpidr); + support_ability = mmio_read_32(slave_base); + + pending = (mmio_read_32( + cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; + while (pending) { + pending = (mmio_read_32( + cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; + } + + if (support_ability & SNP_SUPPORT) + config |= SNOOP_EN_BIT; + if (support_ability & DVM_SUPPORT) + config |= DVM_EN_BIT; + + mmio_write_32(slave_base, support_ability | config); + + /* Wait for the dust to settle down */ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; +} + +#if ERRATA_MCSIB_SW +#pragma weak mcsib_sw_workaround_main +#endif + +void cci_disable_cluster_coherency(unsigned long mpidr) +{ + unsigned long slave_base; + unsigned int config = 0; + + assert(cci_base_addr); + slave_base = get_slave_iface_base(mpidr); + + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; + + config = mmio_read_32(slave_base); + config &= ~(DVM_EN_BIT | SNOOP_EN_BIT); + + /* Disable Snoops and DVM messages */ + mmio_write_32(slave_base, config); + +#if ERRATA_MCSIB_SW + mcsib_sw_workaround_main(); +#endif + + /* Wait for the dust to settle down */ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; +} + +void cci_secure_switch(unsigned int status) +{ + unsigned int config; + + config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); + if (status == NS_ACC) + config |= SECURE_ACC_EN; + else + config &= ~SECURE_ACC_EN; + mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); +} + +void cci_pmu_secure_switch(unsigned int status) +{ + unsigned int config; + + config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); + if (status == NS_ACC) + config |= PMU_SECURE_ACC_EN; + else + config &= ~PMU_SECURE_ACC_EN; + mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); +} + +void cci_init_sf(void) +{ + while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) + ; + /* init sf1 */ + mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT); + while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT) + ; + while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE)) + ; + /* init sf2 */ + mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT); + while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT) + ; + while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE)) + ; +} + +void cci_interrupt_en(void) +{ + mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN); +} + +unsigned long cci_reg_access(unsigned int op, unsigned long offset, + unsigned long val) +{ + unsigned long ret = 0; + + if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ)) + panic(); + + switch (op) { + case MCSI_REG_ACCESS_READ: + ret = mmio_read_32(cci_base_addr + offset); + break; + case MCSI_REG_ACCESS_WRITE: + mmio_write_32(cci_base_addr + offset, val); + dsb(); + break; + case MCSI_REG_ACCESS_SET_BITMASK: + mmio_setbits_32(cci_base_addr + offset, val); + dsb(); + break; + case MCSI_REG_ACCESS_CLEAR_BITMASK: + mmio_clrbits_32(cci_base_addr + offset, val); + dsb(); + break; + default: + break; + } + return ret; +} diff --git a/plat/mediatek/mt8183/drivers/mcsi/mcsi.h b/plat/mediatek/mt8183/drivers/mcsi/mcsi.h new file mode 100644 index 0000000..c13e22a --- /dev/null +++ b/plat/mediatek/mt8183/drivers/mcsi/mcsi.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCSI_H +#define MCSI_H + +#define SLAVE_IFACE7_OFFSET 0x1700 +#define SLAVE_IFACE6_OFFSET 0x1600 +#define SLAVE_IFACE5_OFFSET 0x1500 +#define SLAVE_IFACE4_OFFSET 0x1400 +#define SLAVE_IFACE3_OFFSET 0x1300 +#define SLAVE_IFACE2_OFFSET 0x1200 +#define SLAVE_IFACE1_OFFSET 0x1100 +#define SLAVE_IFACE0_OFFSET 0x1000 +#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \ + (0x100 * (index))) +/* Control and ID register offsets */ +#define CENTRAL_CTRL_REG 0x0 +#define ERR_FLAG_REG 0x4 +#define SF_INIT_REG 0x10 +#define SF_CTRL_REG 0x14 +#define DCM_CTRL_REG 0x18 +#define ERR_FLAG2_REG 0x20 +#define SNP_PENDING_REG 0x28 +#define ACP_PENDING_REG 0x2c +#define FLUSH_SF 0x500 +#define SYS_CCE_CTRL 0x2000 +#define MST1_CTRL 0x2100 +#define MTS2_CTRL 0x2200 +#define XBAR_ARAW_ARB 0x3000 +#define XBAR_R_ARB 0x3004 + +/* Slave interface register offsets */ +#define SNOOP_CTRL_REG 0x0 +#define QOS_CTRL_REG 0x4 +#define QOS_OVERRIDE_REG 0x8 +#define QOS_TARGET_REG 0xc +#define BD_CTRL_REG 0x40 + +/* Snoop Control register bit definitions */ +#define DVM_SUPPORT (1 << 31) +#define SNP_SUPPORT (1 << 30) +#define SHAREABLE_OVWRT (1 << 2) +#define DVM_EN_BIT (1 << 1) +#define SNOOP_EN_BIT (1 << 0) +#define SF2_INIT_DONE (1 << 17) +#define SF1_INIT_DONE (1 << 16) +#define TRIG_SF2_INIT (1 << 1) +#define TRIG_SF1_INIT (1 << 0) + +/* Status register bit definitions */ +#define SNP_PENDING 31 + +/* Status bit */ +#define NS_ACC 1 +#define S_ACC 0 + +/* Central control register bit definitions */ +#define PMU_SECURE_ACC_EN (1 << 4) +#define INT_EN (1 << 3) +#define SECURE_ACC_EN (1 << 2) +#define DVM_DIS (1 << 1) +#define SNOOP_DIS (1 << 0) + +#define MSCI_MEMORY_SZ (0x10000) + +#define MCSI_REG_ACCESS_READ (0x0) +#define MCSI_REG_ACCESS_WRITE (0x1) +#define MCSI_REG_ACCESS_SET_BITMASK (0x2) +#define MCSI_REG_ACCESS_CLEAR_BITMASK (0x3) + +#define NR_MAX_SLV (7) + +/* ICCS */ +#define CACHE_INSTR_EN (1 << 2) +#define IDLE_CACHE (1 << 3) +#define USE_SHARED_CACHE (1 << 4) +#define CACHE_SHARED_PRE_EN (1 << 5) +#define CACHE_SHARED_POST_EN (1 << 6) + +#define ACP_PENDING_MASK (0x1007f) + +#define CCI_CLK_CTRL (MCUCFG_BASE + 0x660) + +#ifndef __ASSEMBLY__ + +#include +#include + +/* Function declarations */ + +/* + * The MCSI driver must be initialized with the base address of the + * MCSI device in the platform memory map, and the cluster indices for + * the MCSI slave interfaces 3 and 4 respectively. These are the fully + * coherent ACE slave interfaces of MCSI. + * The cluster indices must either be 0 or 1, corresponding to the level 1 + * affinity instance of the mpidr representing the cluster. A negative cluster + * index indicates that no cluster is present on that slave interface. + */ +void mcsi_init(unsigned long cci_base, + unsigned int num_cci_masters); +void mcsi_cache_flush(void); + +void cci_enable_cluster_coherency(unsigned long mpidr); +void cci_disable_cluster_coherency(unsigned long mpidr); + +void cci_secure_switch(unsigned int ns); +void cci_init_sf(void); +unsigned long cci_reg_access(unsigned int op, unsigned long offset, unsigned long val); + +#endif /* __ASSEMBLY__ */ +#endif /* MCSI_H */ diff --git a/plat/mediatek/mt8183/include/plat_private.h b/plat/mediatek/mt8183/include/plat_private.h index 599f14f..0853934 100644 --- a/plat/mediatek/mt8183/include/plat_private.h +++ b/plat/mediatek/mt8183/include/plat_private.h @@ -17,10 +17,10 @@ uintptr_t coh_start, uintptr_t coh_limit); -void plat_cci_init(void); -void plat_cci_enable(void); -void plat_cci_disable(void); -void plat_cci_init_sf(void); +void plat_mtk_cci_init(void); +void plat_mtk_cci_enable(void); +void plat_mtk_cci_disable(void); +void plat_mtk_cci_init_sf(void); /* Declarations for plat_topology.c */ int mt_setup_topology(void); diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk index 607e7e3..8c8e2fe 100644 --- a/plat/mediatek/mt8183/platform.mk +++ b/plat/mediatek/mt8183/platform.mk @@ -8,6 +8,7 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT_SOC}/drivers/ \ -I${MTK_PLAT_SOC}/include/ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ @@ -32,6 +33,7 @@ ${MTK_PLAT}/common/mtk_plat_common.c \ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \ ${MTK_PLAT_SOC}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_topology.c \ ${MTK_PLAT_SOC}/plat_mt_gic.c \