xref: /rk3399_ARM-atf/plat/mediatek/drivers/cirq/mt_cirq.c (revision 04f28f895f1dc8683838a1382c8f92881f4cf21d)
1*cc76896dSRex-BC Chen /*
2*cc76896dSRex-BC Chen  * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
3*cc76896dSRex-BC Chen  *
4*cc76896dSRex-BC Chen  * SPDX-License-Identifier: BSD-3-Clause
5*cc76896dSRex-BC Chen  */
6*cc76896dSRex-BC Chen 
7*cc76896dSRex-BC Chen #include <arch_helpers.h>
8*cc76896dSRex-BC Chen #include <common/debug.h>
9*cc76896dSRex-BC Chen #include <drivers/arm/gic_common.h>
10*cc76896dSRex-BC Chen #include <lib/mmio.h>
11*cc76896dSRex-BC Chen 
12*cc76896dSRex-BC Chen #include <mt_cirq.h>
13*cc76896dSRex-BC Chen #include <mt_gic_v3.h>
14*cc76896dSRex-BC Chen 
15*cc76896dSRex-BC Chen static struct cirq_events cirq_all_events = {
16*cc76896dSRex-BC Chen 	.spi_start = CIRQ_SPI_START,
17*cc76896dSRex-BC Chen };
18*cc76896dSRex-BC Chen static uint32_t already_cloned;
19*cc76896dSRex-BC Chen /*
20*cc76896dSRex-BC Chen  * mt_irq_mask_restore: restore all interrupts
21*cc76896dSRex-BC Chen  * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
22*cc76896dSRex-BC Chen  * Return 0 for success; return negative values for failure.
23*cc76896dSRex-BC Chen  * (This is ONLY used for the idle current measurement by the factory mode.)
24*cc76896dSRex-BC Chen  */
mt_irq_mask_restore(struct mtk_irq_mask * mask)25*cc76896dSRex-BC Chen int mt_irq_mask_restore(struct mtk_irq_mask *mask)
26*cc76896dSRex-BC Chen {
27*cc76896dSRex-BC Chen 	if (mask == NULL) {
28*cc76896dSRex-BC Chen 		return -1;
29*cc76896dSRex-BC Chen 	}
30*cc76896dSRex-BC Chen 	if (mask->header != IRQ_MASK_HEADER) {
31*cc76896dSRex-BC Chen 		return -1;
32*cc76896dSRex-BC Chen 	}
33*cc76896dSRex-BC Chen 	if (mask->footer != IRQ_MASK_FOOTER) {
34*cc76896dSRex-BC Chen 		return -1;
35*cc76896dSRex-BC Chen 	}
36*cc76896dSRex-BC Chen 
37*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
38*cc76896dSRex-BC Chen 		mask->mask1);
39*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
40*cc76896dSRex-BC Chen 		mask->mask2);
41*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
42*cc76896dSRex-BC Chen 		mask->mask3);
43*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
44*cc76896dSRex-BC Chen 		mask->mask4);
45*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
46*cc76896dSRex-BC Chen 		mask->mask5);
47*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
48*cc76896dSRex-BC Chen 		mask->mask6);
49*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
50*cc76896dSRex-BC Chen 		mask->mask7);
51*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
52*cc76896dSRex-BC Chen 		mask->mask8);
53*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
54*cc76896dSRex-BC Chen 		mask->mask9);
55*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
56*cc76896dSRex-BC Chen 		mask->mask10);
57*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
58*cc76896dSRex-BC Chen 		mask->mask11);
59*cc76896dSRex-BC Chen 	 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
60*cc76896dSRex-BC Chen 		mask->mask12);
61*cc76896dSRex-BC Chen 	/* make sure dist changes happen */
62*cc76896dSRex-BC Chen 	dsb();
63*cc76896dSRex-BC Chen 
64*cc76896dSRex-BC Chen 	return 0;
65*cc76896dSRex-BC Chen }
66*cc76896dSRex-BC Chen 
67*cc76896dSRex-BC Chen /*
68*cc76896dSRex-BC Chen  * mt_irq_mask_all: disable all interrupts
69*cc76896dSRex-BC Chen  * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
70*cc76896dSRex-BC Chen  * Return 0 for success; return negative values for failure.
71*cc76896dSRex-BC Chen  * (This is ONLY used for the idle current measurement by the factory mode.)
72*cc76896dSRex-BC Chen  */
mt_irq_mask_all(struct mtk_irq_mask * mask)73*cc76896dSRex-BC Chen int mt_irq_mask_all(struct mtk_irq_mask *mask)
74*cc76896dSRex-BC Chen {
75*cc76896dSRex-BC Chen 	if (mask != NULL) {
76*cc76896dSRex-BC Chen 		/* for SPI */
77*cc76896dSRex-BC Chen 		mask->mask1 = mmio_read_32((BASE_GICD_BASE +
78*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x4));
79*cc76896dSRex-BC Chen 		mask->mask2 = mmio_read_32((BASE_GICD_BASE +
80*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x8));
81*cc76896dSRex-BC Chen 		mask->mask3 = mmio_read_32((BASE_GICD_BASE +
82*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0xc));
83*cc76896dSRex-BC Chen 		mask->mask4 = mmio_read_32((BASE_GICD_BASE +
84*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x10));
85*cc76896dSRex-BC Chen 		mask->mask5 = mmio_read_32((BASE_GICD_BASE +
86*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x14));
87*cc76896dSRex-BC Chen 		mask->mask6 = mmio_read_32((BASE_GICD_BASE +
88*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x18));
89*cc76896dSRex-BC Chen 		mask->mask7 = mmio_read_32((BASE_GICD_BASE +
90*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x1c));
91*cc76896dSRex-BC Chen 		mask->mask8 = mmio_read_32((BASE_GICD_BASE +
92*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x20));
93*cc76896dSRex-BC Chen 		mask->mask9 = mmio_read_32((BASE_GICD_BASE +
94*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x24));
95*cc76896dSRex-BC Chen 		mask->mask10 = mmio_read_32((BASE_GICD_BASE +
96*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x28));
97*cc76896dSRex-BC Chen 		mask->mask11 = mmio_read_32((BASE_GICD_BASE +
98*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x2c));
99*cc76896dSRex-BC Chen 		mask->mask12 = mmio_read_32((BASE_GICD_BASE +
100*cc76896dSRex-BC Chen 			GICD_ISENABLER + 0x30));
101*cc76896dSRex-BC Chen 
102*cc76896dSRex-BC Chen 		/* for SPI */
103*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
104*cc76896dSRex-BC Chen 			0xFFFFFFFF);
105*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
106*cc76896dSRex-BC Chen 			0xFFFFFFFF);
107*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
108*cc76896dSRex-BC Chen 			0xFFFFFFFF);
109*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
110*cc76896dSRex-BC Chen 			0xFFFFFFFF);
111*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
112*cc76896dSRex-BC Chen 			0xFFFFFFFF);
113*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
114*cc76896dSRex-BC Chen 			0xFFFFFFFF);
115*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
116*cc76896dSRex-BC Chen 			0xFFFFFFFF);
117*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
118*cc76896dSRex-BC Chen 			0xFFFFFFFF);
119*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
120*cc76896dSRex-BC Chen 			0xFFFFFFFF);
121*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
122*cc76896dSRex-BC Chen 			0xFFFFFFFF);
123*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
124*cc76896dSRex-BC Chen 			0xFFFFFFFF);
125*cc76896dSRex-BC Chen 		mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
126*cc76896dSRex-BC Chen 			0xFFFFFFFF);
127*cc76896dSRex-BC Chen 		/* make sure distributor changes happen */
128*cc76896dSRex-BC Chen 		dsb();
129*cc76896dSRex-BC Chen 
130*cc76896dSRex-BC Chen 		mask->header = IRQ_MASK_HEADER;
131*cc76896dSRex-BC Chen 		mask->footer = IRQ_MASK_FOOTER;
132*cc76896dSRex-BC Chen 
133*cc76896dSRex-BC Chen 		return 0;
134*cc76896dSRex-BC Chen 	} else {
135*cc76896dSRex-BC Chen 		return -1;
136*cc76896dSRex-BC Chen 	}
137*cc76896dSRex-BC Chen }
138*cc76896dSRex-BC Chen 
mt_irq_get_pol(uint32_t irq)139*cc76896dSRex-BC Chen static uint32_t mt_irq_get_pol(uint32_t irq)
140*cc76896dSRex-BC Chen {
141*cc76896dSRex-BC Chen #ifdef CIRQ_WITH_POLARITY
142*cc76896dSRex-BC Chen 	uint32_t reg;
143*cc76896dSRex-BC Chen 	uint32_t base = INT_POL_CTL0;
144*cc76896dSRex-BC Chen 
145*cc76896dSRex-BC Chen 	if (irq < 32U) {
146*cc76896dSRex-BC Chen 		return 0;
147*cc76896dSRex-BC Chen 	}
148*cc76896dSRex-BC Chen 
149*cc76896dSRex-BC Chen 	reg = ((irq - 32U) / 32U);
150*cc76896dSRex-BC Chen 
151*cc76896dSRex-BC Chen 	return  mmio_read_32(base + reg * 4U);
152*cc76896dSRex-BC Chen #else
153*cc76896dSRex-BC Chen 	return 0;
154*cc76896dSRex-BC Chen #endif
155*cc76896dSRex-BC Chen }
156*cc76896dSRex-BC Chen 
mt_irq_get_sens(unsigned int irq)157*cc76896dSRex-BC Chen unsigned int mt_irq_get_sens(unsigned int irq)
158*cc76896dSRex-BC Chen {
159*cc76896dSRex-BC Chen 	unsigned int config;
160*cc76896dSRex-BC Chen 
161*cc76896dSRex-BC Chen 	/*
162*cc76896dSRex-BC Chen 	 * 2'b10 edge
163*cc76896dSRex-BC Chen 	 * 2'b01 level
164*cc76896dSRex-BC Chen 	 */
165*cc76896dSRex-BC Chen 	config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
166*cc76896dSRex-BC Chen 	config = (config >> (irq % 16U) * 2U) & 0x3;
167*cc76896dSRex-BC Chen 
168*cc76896dSRex-BC Chen 	return config;
169*cc76896dSRex-BC Chen }
170*cc76896dSRex-BC Chen 
collect_all_wakeup_events(void)171*cc76896dSRex-BC Chen static void collect_all_wakeup_events(void)
172*cc76896dSRex-BC Chen {
173*cc76896dSRex-BC Chen 	unsigned int i;
174*cc76896dSRex-BC Chen 	uint32_t gic_irq;
175*cc76896dSRex-BC Chen 	uint32_t cirq;
176*cc76896dSRex-BC Chen 	uint32_t cirq_reg;
177*cc76896dSRex-BC Chen 	uint32_t cirq_offset;
178*cc76896dSRex-BC Chen 	uint32_t mask;
179*cc76896dSRex-BC Chen 	uint32_t pol_mask;
180*cc76896dSRex-BC Chen 	uint32_t irq_offset;
181*cc76896dSRex-BC Chen 	uint32_t irq_mask;
182*cc76896dSRex-BC Chen 
183*cc76896dSRex-BC Chen 	if ((cirq_all_events.wakeup_events == NULL) ||
184*cc76896dSRex-BC Chen 			cirq_all_events.num_of_events == 0U) {
185*cc76896dSRex-BC Chen 		return;
186*cc76896dSRex-BC Chen 	}
187*cc76896dSRex-BC Chen 
188*cc76896dSRex-BC Chen 	for (i = 0U; i < cirq_all_events.num_of_events; i++) {
189*cc76896dSRex-BC Chen 		if (cirq_all_events.wakeup_events[i] > 0U) {
190*cc76896dSRex-BC Chen 			gic_irq = cirq_all_events.wakeup_events[i];
191*cc76896dSRex-BC Chen 			cirq = gic_irq - cirq_all_events.spi_start - 32U;
192*cc76896dSRex-BC Chen 			cirq_reg = cirq / 32U;
193*cc76896dSRex-BC Chen 			cirq_offset = cirq % 32U;
194*cc76896dSRex-BC Chen 			mask = 0x1 << cirq_offset;
195*cc76896dSRex-BC Chen 			irq_offset = gic_irq % 32U;
196*cc76896dSRex-BC Chen 			irq_mask = 0x1 << irq_offset;
197*cc76896dSRex-BC Chen 			/*
198*cc76896dSRex-BC Chen 			 * CIRQ default masks all
199*cc76896dSRex-BC Chen 			 */
200*cc76896dSRex-BC Chen 			cirq_all_events.table[cirq_reg].mask |= mask;
201*cc76896dSRex-BC Chen 			/*
202*cc76896dSRex-BC Chen 			 * CIRQ default pol is low
203*cc76896dSRex-BC Chen 			 */
204*cc76896dSRex-BC Chen 			pol_mask = mt_irq_get_pol(
205*cc76896dSRex-BC Chen 					cirq_all_events.wakeup_events[i])
206*cc76896dSRex-BC Chen 					& irq_mask;
207*cc76896dSRex-BC Chen 			/*
208*cc76896dSRex-BC Chen 			 * 0 means rising
209*cc76896dSRex-BC Chen 			 */
210*cc76896dSRex-BC Chen 			if (pol_mask == 0U) {
211*cc76896dSRex-BC Chen 				cirq_all_events.table[cirq_reg].pol |= mask;
212*cc76896dSRex-BC Chen 			}
213*cc76896dSRex-BC Chen 			/*
214*cc76896dSRex-BC Chen 			 * CIRQ could monitor edge/level trigger
215*cc76896dSRex-BC Chen 			 * cirq register (0: edge, 1: level)
216*cc76896dSRex-BC Chen 			 */
217*cc76896dSRex-BC Chen 			if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
218*cc76896dSRex-BC Chen 				== SENS_EDGE) {
219*cc76896dSRex-BC Chen 				cirq_all_events.table[cirq_reg].sen |= mask;
220*cc76896dSRex-BC Chen 			}
221*cc76896dSRex-BC Chen 
222*cc76896dSRex-BC Chen 			cirq_all_events.table[cirq_reg].used = 1U;
223*cc76896dSRex-BC Chen 			cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
224*cc76896dSRex-BC Chen 		}
225*cc76896dSRex-BC Chen 	}
226*cc76896dSRex-BC Chen }
227*cc76896dSRex-BC Chen 
228*cc76896dSRex-BC Chen /*
229*cc76896dSRex-BC Chen  * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
230*cc76896dSRex-BC Chen  * @cirq_num: the SYS_CIRQ number to set
231*cc76896dSRex-BC Chen  * @pol: polarity to set
232*cc76896dSRex-BC Chen  * @return:
233*cc76896dSRex-BC Chen  *    0: set pol success
234*cc76896dSRex-BC Chen  *   -1: cirq num is out of range
235*cc76896dSRex-BC Chen  */
236*cc76896dSRex-BC Chen #ifdef CIRQ_WITH_POLARITY
mt_cirq_set_pol(uint32_t cirq_num,uint32_t pol)237*cc76896dSRex-BC Chen static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
238*cc76896dSRex-BC Chen {
239*cc76896dSRex-BC Chen 	uint32_t base;
240*cc76896dSRex-BC Chen 	uint32_t bit = 1U << (cirq_num % 32U);
241*cc76896dSRex-BC Chen 
242*cc76896dSRex-BC Chen 	if (cirq_num >= CIRQ_IRQ_NUM) {
243*cc76896dSRex-BC Chen 		return -1;
244*cc76896dSRex-BC Chen 	}
245*cc76896dSRex-BC Chen 
246*cc76896dSRex-BC Chen 	if (pol == MT_CIRQ_POL_NEG) {
247*cc76896dSRex-BC Chen 		base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
248*cc76896dSRex-BC Chen 	} else if (pol == MT_CIRQ_POL_POS) {
249*cc76896dSRex-BC Chen 		base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
250*cc76896dSRex-BC Chen 	} else {
251*cc76896dSRex-BC Chen 		return -1;
252*cc76896dSRex-BC Chen 	}
253*cc76896dSRex-BC Chen 
254*cc76896dSRex-BC Chen 	mmio_write_32(base, bit);
255*cc76896dSRex-BC Chen 	return 0;
256*cc76896dSRex-BC Chen }
257*cc76896dSRex-BC Chen #endif
258*cc76896dSRex-BC Chen 
259*cc76896dSRex-BC Chen /*
260*cc76896dSRex-BC Chen  * mt_cirq_mask: Mask the specified SYS_CIRQ.
261*cc76896dSRex-BC Chen  * @cirq_num: the SYS_CIRQ number to mask
262*cc76896dSRex-BC Chen  * @return:
263*cc76896dSRex-BC Chen  *    0: mask success
264*cc76896dSRex-BC Chen  *   -1: cirq num is out of range
265*cc76896dSRex-BC Chen  */
mt_cirq_mask(uint32_t cirq_num)266*cc76896dSRex-BC Chen static int mt_cirq_mask(uint32_t cirq_num)
267*cc76896dSRex-BC Chen {
268*cc76896dSRex-BC Chen 	uint32_t bit = 1U << (cirq_num % 32U);
269*cc76896dSRex-BC Chen 
270*cc76896dSRex-BC Chen 	if (cirq_num >= CIRQ_IRQ_NUM) {
271*cc76896dSRex-BC Chen 		return -1;
272*cc76896dSRex-BC Chen 	}
273*cc76896dSRex-BC Chen 
274*cc76896dSRex-BC Chen 	mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
275*cc76896dSRex-BC Chen 
276*cc76896dSRex-BC Chen 	return 0;
277*cc76896dSRex-BC Chen }
278*cc76896dSRex-BC Chen 
279*cc76896dSRex-BC Chen /*
280*cc76896dSRex-BC Chen  * mt_cirq_unmask: Unmask the specified SYS_CIRQ.
281*cc76896dSRex-BC Chen  * @cirq_num: the SYS_CIRQ number to unmask
282*cc76896dSRex-BC Chen  * @return:
283*cc76896dSRex-BC Chen  *    0: umask success
284*cc76896dSRex-BC Chen  *   -1: cirq num is out of range
285*cc76896dSRex-BC Chen  */
mt_cirq_unmask(uint32_t cirq_num)286*cc76896dSRex-BC Chen static int mt_cirq_unmask(uint32_t cirq_num)
287*cc76896dSRex-BC Chen {
288*cc76896dSRex-BC Chen 	uint32_t bit = 1U << (cirq_num % 32U);
289*cc76896dSRex-BC Chen 
290*cc76896dSRex-BC Chen 	if (cirq_num >= CIRQ_IRQ_NUM) {
291*cc76896dSRex-BC Chen 		return -1;
292*cc76896dSRex-BC Chen 	}
293*cc76896dSRex-BC Chen 
294*cc76896dSRex-BC Chen 	mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
295*cc76896dSRex-BC Chen 
296*cc76896dSRex-BC Chen 	return 0;
297*cc76896dSRex-BC Chen }
298*cc76896dSRex-BC Chen 
mt_irq_get_en(uint32_t irq)299*cc76896dSRex-BC Chen uint32_t mt_irq_get_en(uint32_t irq)
300*cc76896dSRex-BC Chen {
301*cc76896dSRex-BC Chen 	uint32_t addr, st, val;
302*cc76896dSRex-BC Chen 
303*cc76896dSRex-BC Chen 	addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
304*cc76896dSRex-BC Chen 	st = mmio_read_32(addr);
305*cc76896dSRex-BC Chen 
306*cc76896dSRex-BC Chen 	val = (st >> (irq % 32U)) & 1U;
307*cc76896dSRex-BC Chen 
308*cc76896dSRex-BC Chen 	return val;
309*cc76896dSRex-BC Chen }
310*cc76896dSRex-BC Chen 
__cirq_fast_clone(void)311*cc76896dSRex-BC Chen static void __cirq_fast_clone(void)
312*cc76896dSRex-BC Chen {
313*cc76896dSRex-BC Chen 	struct cirq_reg *reg;
314*cc76896dSRex-BC Chen 	unsigned int i;
315*cc76896dSRex-BC Chen 
316*cc76896dSRex-BC Chen 	for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
317*cc76896dSRex-BC Chen 		uint32_t cirq_bit;
318*cc76896dSRex-BC Chen 
319*cc76896dSRex-BC Chen 		reg = &cirq_all_events.table[i];
320*cc76896dSRex-BC Chen 
321*cc76896dSRex-BC Chen 		if (reg->used == 0U) {
322*cc76896dSRex-BC Chen 			continue;
323*cc76896dSRex-BC Chen 		}
324*cc76896dSRex-BC Chen 
325*cc76896dSRex-BC Chen 		mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
326*cc76896dSRex-BC Chen 				    reg->sen);
327*cc76896dSRex-BC Chen 
328*cc76896dSRex-BC Chen 		for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
329*cc76896dSRex-BC Chen 			uint32_t val, cirq_id;
330*cc76896dSRex-BC Chen 			uint32_t gic_id;
331*cc76896dSRex-BC Chen #ifdef CIRQ_WITH_POLARITY
332*cc76896dSRex-BC Chen 			uint32_t gic_bit, pol;
333*cc76896dSRex-BC Chen #endif
334*cc76896dSRex-BC Chen 			uint32_t en;
335*cc76896dSRex-BC Chen 
336*cc76896dSRex-BC Chen 			val = ((1U << cirq_bit) & reg->mask);
337*cc76896dSRex-BC Chen 
338*cc76896dSRex-BC Chen 			if (val == 0U) {
339*cc76896dSRex-BC Chen 				continue;
340*cc76896dSRex-BC Chen 			}
341*cc76896dSRex-BC Chen 
342*cc76896dSRex-BC Chen 			cirq_id = (reg->reg_num << 5U) + cirq_bit;
343*cc76896dSRex-BC Chen 			gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
344*cc76896dSRex-BC Chen #ifdef CIRQ_WITH_POLARITY
345*cc76896dSRex-BC Chen 			gic_bit = (0x1U << ((gic_id - 32U) % 32U));
346*cc76896dSRex-BC Chen 			pol = mt_irq_get_pol(gic_id) & gic_bit;
347*cc76896dSRex-BC Chen 			if (pol != 0U) {
348*cc76896dSRex-BC Chen 				mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
349*cc76896dSRex-BC Chen 			} else {
350*cc76896dSRex-BC Chen 				mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
351*cc76896dSRex-BC Chen 			}
352*cc76896dSRex-BC Chen #endif
353*cc76896dSRex-BC Chen 			en = mt_irq_get_en(gic_id);
354*cc76896dSRex-BC Chen 			if (en == 1U) {
355*cc76896dSRex-BC Chen 				mt_cirq_unmask(cirq_id);
356*cc76896dSRex-BC Chen 			} else {
357*cc76896dSRex-BC Chen 				mt_cirq_mask(cirq_id);
358*cc76896dSRex-BC Chen 			}
359*cc76896dSRex-BC Chen 		}
360*cc76896dSRex-BC Chen 	}
361*cc76896dSRex-BC Chen }
362*cc76896dSRex-BC Chen 
cirq_fast_clone(void)363*cc76896dSRex-BC Chen static void cirq_fast_clone(void)
364*cc76896dSRex-BC Chen {
365*cc76896dSRex-BC Chen 	if (already_cloned == 0U) {
366*cc76896dSRex-BC Chen 		collect_all_wakeup_events();
367*cc76896dSRex-BC Chen 		already_cloned = 1U;
368*cc76896dSRex-BC Chen 	}
369*cc76896dSRex-BC Chen 	__cirq_fast_clone();
370*cc76896dSRex-BC Chen }
371*cc76896dSRex-BC Chen 
set_wakeup_sources(uint32_t * list,uint32_t num_of_events)372*cc76896dSRex-BC Chen void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
373*cc76896dSRex-BC Chen {
374*cc76896dSRex-BC Chen 	cirq_all_events.num_of_events = num_of_events;
375*cc76896dSRex-BC Chen 	cirq_all_events.wakeup_events = list;
376*cc76896dSRex-BC Chen }
377*cc76896dSRex-BC Chen /*
378*cc76896dSRex-BC Chen  * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
379*cc76896dSRex-BC Chen  */
mt_cirq_clone_gic(void)380*cc76896dSRex-BC Chen void mt_cirq_clone_gic(void)
381*cc76896dSRex-BC Chen {
382*cc76896dSRex-BC Chen 	cirq_fast_clone();
383*cc76896dSRex-BC Chen }
384*cc76896dSRex-BC Chen 
mt_irq_get_pending_vec(uint32_t start_irq)385*cc76896dSRex-BC Chen uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
386*cc76896dSRex-BC Chen {
387*cc76896dSRex-BC Chen 	uint32_t base = 0U;
388*cc76896dSRex-BC Chen 	uint32_t pending_vec = 0U;
389*cc76896dSRex-BC Chen 	uint32_t reg = start_irq / 32U;
390*cc76896dSRex-BC Chen 	uint32_t LSB_num, MSB_num;
391*cc76896dSRex-BC Chen 	uint32_t LSB_vec, MSB_vec;
392*cc76896dSRex-BC Chen 
393*cc76896dSRex-BC Chen 	base = BASE_GICD_BASE;
394*cc76896dSRex-BC Chen 
395*cc76896dSRex-BC Chen 	/* if start_irq is not aligned 32, do some assembling */
396*cc76896dSRex-BC Chen 	MSB_num = start_irq % 32U;
397*cc76896dSRex-BC Chen 	if (MSB_num != 0U) {
398*cc76896dSRex-BC Chen 		LSB_num = 32U - MSB_num;
399*cc76896dSRex-BC Chen 		LSB_vec = mmio_read_32(base + GICD_ISPENDR +
400*cc76896dSRex-BC Chen 			reg * 4U) >> MSB_num;
401*cc76896dSRex-BC Chen 		MSB_vec = mmio_read_32(base + GICD_ISPENDR +
402*cc76896dSRex-BC Chen 			(reg + 1U) * 4U) << LSB_num;
403*cc76896dSRex-BC Chen 		pending_vec = MSB_vec | LSB_vec;
404*cc76896dSRex-BC Chen 	} else {
405*cc76896dSRex-BC Chen 		pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
406*cc76896dSRex-BC Chen 	}
407*cc76896dSRex-BC Chen 
408*cc76896dSRex-BC Chen 	return pending_vec;
409*cc76896dSRex-BC Chen }
410*cc76896dSRex-BC Chen 
mt_cirq_get_mask_vec(unsigned int i)411*cc76896dSRex-BC Chen static int mt_cirq_get_mask_vec(unsigned int i)
412*cc76896dSRex-BC Chen {
413*cc76896dSRex-BC Chen 	return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
414*cc76896dSRex-BC Chen }
415*cc76896dSRex-BC Chen 
416*cc76896dSRex-BC Chen /*
417*cc76896dSRex-BC Chen  * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
418*cc76896dSRex-BC Chen  */
mt_cirq_ack_all(void)419*cc76896dSRex-BC Chen void mt_cirq_ack_all(void)
420*cc76896dSRex-BC Chen {
421*cc76896dSRex-BC Chen 	uint32_t ack_vec, pend_vec, mask_vec;
422*cc76896dSRex-BC Chen 	unsigned int i;
423*cc76896dSRex-BC Chen 
424*cc76896dSRex-BC Chen 	for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
425*cc76896dSRex-BC Chen 		/*
426*cc76896dSRex-BC Chen 		 * if a irq is pending & not masked, don't ack it
427*cc76896dSRex-BC Chen 		 * , since cirq start irq might not be 32 aligned with gic,
428*cc76896dSRex-BC Chen 		 * need an exotic API to get proper vector of pending irq
429*cc76896dSRex-BC Chen 		 */
430*cc76896dSRex-BC Chen 		pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
431*cc76896dSRex-BC Chen 			+ (i + 1U) * 32U);
432*cc76896dSRex-BC Chen 		mask_vec = mt_cirq_get_mask_vec(i);
433*cc76896dSRex-BC Chen 		/* those should be acked are: "not (pending & not masked)",
434*cc76896dSRex-BC Chen 		 */
435*cc76896dSRex-BC Chen 		ack_vec = (~pend_vec) | mask_vec;
436*cc76896dSRex-BC Chen 		mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
437*cc76896dSRex-BC Chen 	}
438*cc76896dSRex-BC Chen 
439*cc76896dSRex-BC Chen 	/*
440*cc76896dSRex-BC Chen 	 * make sure all cirq setting take effect
441*cc76896dSRex-BC Chen 	 * before doing other things
442*cc76896dSRex-BC Chen 	 */
443*cc76896dSRex-BC Chen 	dsb();
444*cc76896dSRex-BC Chen }
445*cc76896dSRex-BC Chen /*
446*cc76896dSRex-BC Chen  * mt_cirq_enable: Enable SYS_CIRQ
447*cc76896dSRex-BC Chen  */
mt_cirq_enable(void)448*cc76896dSRex-BC Chen void mt_cirq_enable(void)
449*cc76896dSRex-BC Chen {
450*cc76896dSRex-BC Chen 	uint32_t st;
451*cc76896dSRex-BC Chen 
452*cc76896dSRex-BC Chen 	/* level only */
453*cc76896dSRex-BC Chen 	mt_cirq_ack_all();
454*cc76896dSRex-BC Chen 
455*cc76896dSRex-BC Chen 	st = mmio_read_32(CIRQ_CON);
456*cc76896dSRex-BC Chen 	/*
457*cc76896dSRex-BC Chen 	 * CIRQ could monitor edge/level trigger
458*cc76896dSRex-BC Chen 	 */
459*cc76896dSRex-BC Chen 	st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
460*cc76896dSRex-BC Chen 
461*cc76896dSRex-BC Chen 	mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
462*cc76896dSRex-BC Chen }
463*cc76896dSRex-BC Chen 
464*cc76896dSRex-BC Chen /*
465*cc76896dSRex-BC Chen  * mt_cirq_disable: Disable SYS_CIRQ
466*cc76896dSRex-BC Chen  */
mt_cirq_disable(void)467*cc76896dSRex-BC Chen void mt_cirq_disable(void)
468*cc76896dSRex-BC Chen {
469*cc76896dSRex-BC Chen 	uint32_t st;
470*cc76896dSRex-BC Chen 
471*cc76896dSRex-BC Chen 	st = mmio_read_32(CIRQ_CON);
472*cc76896dSRex-BC Chen 	st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
473*cc76896dSRex-BC Chen 	mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
474*cc76896dSRex-BC Chen }
475*cc76896dSRex-BC Chen 
mt_irq_unmask_for_sleep_ex(uint32_t irq)476*cc76896dSRex-BC Chen void mt_irq_unmask_for_sleep_ex(uint32_t irq)
477*cc76896dSRex-BC Chen {
478*cc76896dSRex-BC Chen 	uint32_t mask;
479*cc76896dSRex-BC Chen 
480*cc76896dSRex-BC Chen 	mask = 1U << (irq % 32U);
481*cc76896dSRex-BC Chen 
482*cc76896dSRex-BC Chen 	mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
483*cc76896dSRex-BC Chen 		((irq / 32U) * 4U), mask);
484*cc76896dSRex-BC Chen }
485*cc76896dSRex-BC Chen 
mt_cirq_mask_all(void)486*cc76896dSRex-BC Chen void mt_cirq_mask_all(void)
487*cc76896dSRex-BC Chen {
488*cc76896dSRex-BC Chen 	unsigned int i;
489*cc76896dSRex-BC Chen 
490*cc76896dSRex-BC Chen 	for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
491*cc76896dSRex-BC Chen 		mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
492*cc76896dSRex-BC Chen 	}
493*cc76896dSRex-BC Chen 	dsb();
494*cc76896dSRex-BC Chen }
495*cc76896dSRex-BC Chen 
cirq_fast_sw_flush(void)496*cc76896dSRex-BC Chen static void cirq_fast_sw_flush(void)
497*cc76896dSRex-BC Chen {
498*cc76896dSRex-BC Chen 	struct cirq_reg *reg;
499*cc76896dSRex-BC Chen 	unsigned int i;
500*cc76896dSRex-BC Chen 
501*cc76896dSRex-BC Chen 	for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
502*cc76896dSRex-BC Chen 		uint32_t cirq_bit;
503*cc76896dSRex-BC Chen 
504*cc76896dSRex-BC Chen 		reg = &cirq_all_events.table[i];
505*cc76896dSRex-BC Chen 
506*cc76896dSRex-BC Chen 		if (reg->used == 0U) {
507*cc76896dSRex-BC Chen 			continue;
508*cc76896dSRex-BC Chen 		}
509*cc76896dSRex-BC Chen 
510*cc76896dSRex-BC Chen 		reg->pending = mmio_read_32(CIRQ_STA_BASE +
511*cc76896dSRex-BC Chen 			(reg->reg_num << 2U));
512*cc76896dSRex-BC Chen 		reg->pending &= reg->mask;
513*cc76896dSRex-BC Chen 
514*cc76896dSRex-BC Chen 		for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
515*cc76896dSRex-BC Chen 			uint32_t val, cirq_id;
516*cc76896dSRex-BC Chen 
517*cc76896dSRex-BC Chen 			val = (1U << cirq_bit) & reg->pending;
518*cc76896dSRex-BC Chen 			if (val == 0U) {
519*cc76896dSRex-BC Chen 				continue;
520*cc76896dSRex-BC Chen 			}
521*cc76896dSRex-BC Chen 
522*cc76896dSRex-BC Chen 			cirq_id = (reg->reg_num << 5U) + cirq_bit;
523*cc76896dSRex-BC Chen 			mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
524*cc76896dSRex-BC Chen 			if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
525*cc76896dSRex-BC Chen 				INFO("Set MD_WDT_IRQ pending in %s\n",
526*cc76896dSRex-BC Chen 					__func__);
527*cc76896dSRex-BC Chen 			}
528*cc76896dSRex-BC Chen 		}
529*cc76896dSRex-BC Chen 	}
530*cc76896dSRex-BC Chen }
531*cc76896dSRex-BC Chen 
532*cc76896dSRex-BC Chen /*
533*cc76896dSRex-BC Chen  * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
534*cc76896dSRex-BC Chen  */
mt_cirq_flush(void)535*cc76896dSRex-BC Chen void mt_cirq_flush(void)
536*cc76896dSRex-BC Chen {
537*cc76896dSRex-BC Chen 	cirq_fast_sw_flush();
538*cc76896dSRex-BC Chen 	mt_cirq_mask_all();
539*cc76896dSRex-BC Chen 	mt_cirq_ack_all();
540*cc76896dSRex-BC Chen }
541*cc76896dSRex-BC Chen 
mt_cirq_sw_reset(void)542*cc76896dSRex-BC Chen void mt_cirq_sw_reset(void)
543*cc76896dSRex-BC Chen {
544*cc76896dSRex-BC Chen 	uint32_t st;
545*cc76896dSRex-BC Chen 
546*cc76896dSRex-BC Chen 	st = mmio_read_32(CIRQ_CON);
547*cc76896dSRex-BC Chen 	st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
548*cc76896dSRex-BC Chen 	mmio_write_32(CIRQ_CON, st);
549*cc76896dSRex-BC Chen }
550