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