1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <arch.h> 8*91f16700Schasinglulu #include <arch_helpers.h> 9*91f16700Schasinglulu #include <assert.h> 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <lib/mmio.h> 12*91f16700Schasinglulu #include <scu.h> 13*91f16700Schasinglulu #include <mcucfg.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <mcsi/mcsi.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #define MAX_CLUSTERS 5 18*91f16700Schasinglulu 19*91f16700Schasinglulu static unsigned long cci_base_addr; 20*91f16700Schasinglulu static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS]; 21*91f16700Schasinglulu 22*91f16700Schasinglulu void mcsi_init(unsigned long cci_base, 23*91f16700Schasinglulu unsigned int num_cci_masters) 24*91f16700Schasinglulu { 25*91f16700Schasinglulu int i; 26*91f16700Schasinglulu 27*91f16700Schasinglulu assert(cci_base); 28*91f16700Schasinglulu assert(num_cci_masters < MAX_CLUSTERS); 29*91f16700Schasinglulu 30*91f16700Schasinglulu cci_base_addr = cci_base; 31*91f16700Schasinglulu 32*91f16700Schasinglulu for (i = 0; i < num_cci_masters; i++) 33*91f16700Schasinglulu cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i); 34*91f16700Schasinglulu } 35*91f16700Schasinglulu 36*91f16700Schasinglulu void mcsi_cache_flush(void) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu /* timeout is 10ms */ 39*91f16700Schasinglulu int timeout = 10000; 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* to make flush by SF safe, need to disable BIU DCM */ 42*91f16700Schasinglulu mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8); 43*91f16700Schasinglulu mmio_write_32(cci_base_addr + FLUSH_SF, 0x1); 44*91f16700Schasinglulu 45*91f16700Schasinglulu for (; timeout; timeout--, udelay(1)) { 46*91f16700Schasinglulu if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0) 47*91f16700Schasinglulu break; 48*91f16700Schasinglulu } 49*91f16700Schasinglulu 50*91f16700Schasinglulu if (!timeout) { 51*91f16700Schasinglulu INFO("SF lush timeout\n"); 52*91f16700Schasinglulu return; 53*91f16700Schasinglulu } 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* enable BIU DCM as it was */ 56*91f16700Schasinglulu mmio_setbits_32(CCI_CLK_CTRL, 1 << 8); 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu static inline unsigned long get_slave_iface_base(unsigned long mpidr) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu /* 62*91f16700Schasinglulu * We assume the TF topology code allocates affinity instances 63*91f16700Schasinglulu * consecutively from zero. 64*91f16700Schasinglulu * It is a programming error if this is called without initializing 65*91f16700Schasinglulu * the slave interface to use for this cluster. 66*91f16700Schasinglulu */ 67*91f16700Schasinglulu unsigned int cluster_id = 68*91f16700Schasinglulu (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; 69*91f16700Schasinglulu 70*91f16700Schasinglulu assert(cluster_id < MAX_CLUSTERS); 71*91f16700Schasinglulu assert(cci_cluster_ix_to_iface[cluster_id] != 0); 72*91f16700Schasinglulu 73*91f16700Schasinglulu return cci_base_addr + cci_cluster_ix_to_iface[cluster_id]; 74*91f16700Schasinglulu } 75*91f16700Schasinglulu 76*91f16700Schasinglulu void cci_enable_cluster_coherency(unsigned long mpidr) 77*91f16700Schasinglulu { 78*91f16700Schasinglulu unsigned long slave_base; 79*91f16700Schasinglulu unsigned int support_ability; 80*91f16700Schasinglulu unsigned int config = 0; 81*91f16700Schasinglulu unsigned int pending = 0; 82*91f16700Schasinglulu 83*91f16700Schasinglulu assert(cci_base_addr); 84*91f16700Schasinglulu slave_base = get_slave_iface_base(mpidr); 85*91f16700Schasinglulu support_ability = mmio_read_32(slave_base); 86*91f16700Schasinglulu 87*91f16700Schasinglulu pending = (mmio_read_32( 88*91f16700Schasinglulu cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; 89*91f16700Schasinglulu while (pending) { 90*91f16700Schasinglulu pending = (mmio_read_32( 91*91f16700Schasinglulu cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING; 92*91f16700Schasinglulu } 93*91f16700Schasinglulu 94*91f16700Schasinglulu if (support_ability & SNP_SUPPORT) 95*91f16700Schasinglulu config |= SNOOP_EN_BIT; 96*91f16700Schasinglulu if (support_ability & DVM_SUPPORT) 97*91f16700Schasinglulu config |= DVM_EN_BIT; 98*91f16700Schasinglulu 99*91f16700Schasinglulu mmio_write_32(slave_base, support_ability | config); 100*91f16700Schasinglulu 101*91f16700Schasinglulu /* Wait for the dust to settle down */ 102*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) 103*91f16700Schasinglulu ; 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu #if ERRATA_MCSIB_SW 107*91f16700Schasinglulu #pragma weak mcsib_sw_workaround_main 108*91f16700Schasinglulu #endif 109*91f16700Schasinglulu 110*91f16700Schasinglulu void cci_disable_cluster_coherency(unsigned long mpidr) 111*91f16700Schasinglulu { 112*91f16700Schasinglulu unsigned long slave_base; 113*91f16700Schasinglulu unsigned int config = 0; 114*91f16700Schasinglulu 115*91f16700Schasinglulu assert(cci_base_addr); 116*91f16700Schasinglulu slave_base = get_slave_iface_base(mpidr); 117*91f16700Schasinglulu 118*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) 119*91f16700Schasinglulu ; 120*91f16700Schasinglulu 121*91f16700Schasinglulu config = mmio_read_32(slave_base); 122*91f16700Schasinglulu config &= ~(DVM_EN_BIT | SNOOP_EN_BIT); 123*91f16700Schasinglulu 124*91f16700Schasinglulu /* Disable Snoops and DVM messages */ 125*91f16700Schasinglulu mmio_write_32(slave_base, config); 126*91f16700Schasinglulu 127*91f16700Schasinglulu #if ERRATA_MCSIB_SW 128*91f16700Schasinglulu mcsib_sw_workaround_main(); 129*91f16700Schasinglulu #endif 130*91f16700Schasinglulu 131*91f16700Schasinglulu /* Wait for the dust to settle down */ 132*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) 133*91f16700Schasinglulu ; 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu void cci_secure_switch(unsigned int status) 137*91f16700Schasinglulu { 138*91f16700Schasinglulu unsigned int config; 139*91f16700Schasinglulu 140*91f16700Schasinglulu config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); 141*91f16700Schasinglulu if (status == NS_ACC) 142*91f16700Schasinglulu config |= SECURE_ACC_EN; 143*91f16700Schasinglulu else 144*91f16700Schasinglulu config &= ~SECURE_ACC_EN; 145*91f16700Schasinglulu mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); 146*91f16700Schasinglulu } 147*91f16700Schasinglulu 148*91f16700Schasinglulu void cci_pmu_secure_switch(unsigned int status) 149*91f16700Schasinglulu { 150*91f16700Schasinglulu unsigned int config; 151*91f16700Schasinglulu 152*91f16700Schasinglulu config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG); 153*91f16700Schasinglulu if (status == NS_ACC) 154*91f16700Schasinglulu config |= PMU_SECURE_ACC_EN; 155*91f16700Schasinglulu else 156*91f16700Schasinglulu config &= ~PMU_SECURE_ACC_EN; 157*91f16700Schasinglulu mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config); 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu void cci_init_sf(void) 161*91f16700Schasinglulu { 162*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING) 163*91f16700Schasinglulu ; 164*91f16700Schasinglulu /* init sf1 */ 165*91f16700Schasinglulu mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT); 166*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT) 167*91f16700Schasinglulu ; 168*91f16700Schasinglulu while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE)) 169*91f16700Schasinglulu ; 170*91f16700Schasinglulu /* init sf2 */ 171*91f16700Schasinglulu mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT); 172*91f16700Schasinglulu while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT) 173*91f16700Schasinglulu ; 174*91f16700Schasinglulu while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE)) 175*91f16700Schasinglulu ; 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu void cci_interrupt_en(void) 179*91f16700Schasinglulu { 180*91f16700Schasinglulu mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN); 181*91f16700Schasinglulu } 182*91f16700Schasinglulu 183*91f16700Schasinglulu unsigned long cci_reg_access(unsigned int op, unsigned long offset, 184*91f16700Schasinglulu unsigned long val) 185*91f16700Schasinglulu { 186*91f16700Schasinglulu unsigned long ret = 0; 187*91f16700Schasinglulu 188*91f16700Schasinglulu if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ)) 189*91f16700Schasinglulu panic(); 190*91f16700Schasinglulu 191*91f16700Schasinglulu switch (op) { 192*91f16700Schasinglulu case MCSI_REG_ACCESS_READ: 193*91f16700Schasinglulu ret = mmio_read_32(cci_base_addr + offset); 194*91f16700Schasinglulu break; 195*91f16700Schasinglulu case MCSI_REG_ACCESS_WRITE: 196*91f16700Schasinglulu mmio_write_32(cci_base_addr + offset, val); 197*91f16700Schasinglulu dsb(); 198*91f16700Schasinglulu break; 199*91f16700Schasinglulu case MCSI_REG_ACCESS_SET_BITMASK: 200*91f16700Schasinglulu mmio_setbits_32(cci_base_addr + offset, val); 201*91f16700Schasinglulu dsb(); 202*91f16700Schasinglulu break; 203*91f16700Schasinglulu case MCSI_REG_ACCESS_CLEAR_BITMASK: 204*91f16700Schasinglulu mmio_clrbits_32(cci_base_addr + offset, val); 205*91f16700Schasinglulu dsb(); 206*91f16700Schasinglulu break; 207*91f16700Schasinglulu default: 208*91f16700Schasinglulu break; 209*91f16700Schasinglulu } 210*91f16700Schasinglulu return ret; 211*91f16700Schasinglulu } 212