xref: /arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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