xref: /rk3399_ARM-atf/plat/mediatek/mt8183/drivers/mcsi/mcsi.c (revision 16b49f601df30378b78bb323a859109149f3ea00)
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