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