mediatek: mt8183: add mcsi driver
authorkenny liang <kenny.liang@mediatek.com>
Thu, 2 May 2019 14:01:39 +0000 (22:01 +0800)
committerJohn Tsichritzis <john.tsichritzis@arm.com>
Thu, 6 Jun 2019 10:00:16 +0000 (11:00 +0100)
add mcsi driver to support cache coherence.

Change-Id: I94f5922783e5dbc6b7e92aa06464bc1f0177f00a
Signed-off-by: kenny liang <kenny.liang@mediatek.com>
plat/mediatek/mt8183/aarch64/platform_common.c
plat/mediatek/mt8183/bl31_plat_setup.c
plat/mediatek/mt8183/drivers/mcsi/mcsi.c [new file with mode: 0644]
plat/mediatek/mt8183/drivers/mcsi/mcsi.h [new file with mode: 0644]
plat/mediatek/mt8183/include/plat_private.h
plat/mediatek/mt8183/platform.mk

index ff0aaeb97c16a1ec4f52165d2d653af0c1d61faa..31d133908afb5971ee3b40d75b4c9fb77407679e 100644 (file)
@@ -7,10 +7,16 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <mcsi/mcsi.h>
 #include <platform_def.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables.h>
 
+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 @@ unsigned int plat_get_syscnt_freq2(void)
 {
        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();
+}
index 5a0cb87f1dbcd4aa913f2546003bff94cb6faa63..b451189d4bdf91b1155956db88a1bc5ddf4a7d47 100644 (file)
@@ -96,6 +96,9 @@ void bl31_platform_setup(void)
        /* 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_platform_setup(void)
  ******************************************************************************/
 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 (file)
index 0000000..cbe7f0a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <scu.h>
+#include <mcucfg.h>
+#include <drivers/delay_timer.h>
+#include <mcsi/mcsi.h>
+
+#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 (file)
index 0000000..c13e22a
--- /dev/null
@@ -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 <plat/common/common_def.h>
+#include <stdint.h>
+
+/* 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 */
index 599f14f3bb8155ba8347003bd69b34b4af852851..0853934b9f8a5d18e7cd0ba260f72ed303fce547 100644 (file)
@@ -17,10 +17,10 @@ void plat_configure_mmu_el3(uintptr_t total_base,
                            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);
index 607e7e3aafa9103bf46150bc853958cc6c7b9523..8c8e2fe9cc215745ccdba81fb28afcb1af3f9e28 100644 (file)
@@ -8,6 +8,7 @@ MTK_PLAT      := plat/mediatek
 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 @@ BL31_SOURCES    += drivers/arm/cci/cci.c                                 \
                    ${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                         \