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