blob: 9002b7ee1df410bc1cf9c820a2144c23969c71ed [file] [log] [blame]
developer28d70382019-12-19 15:58:20 +08001/*
2 * Copyright (c) 2020, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <common/debug.h>
9#include <drivers/arm/gic_common.h>
developer28d70382019-12-19 15:58:20 +080010#include <lib/mmio.h>
11
12#include <mt_gic_v3.h>
developer28d70382019-12-19 15:58:20 +080013#include <plat_mt_cirq.h>
14#include <platform_def.h>
15
16static struct cirq_events cirq_all_events = {
developerb63f6b22020-11-06 09:20:25 +080017 .spi_start = CIRQ_SPI_START,
developer28d70382019-12-19 15:58:20 +080018};
developerb63f6b22020-11-06 09:20:25 +080019static uint32_t already_cloned;
developer28d70382019-12-19 15:58:20 +080020/*
developerb63f6b22020-11-06 09:20:25 +080021 * mt_irq_mask_restore: restore all interrupts
22 * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
23 * Return 0 for success; return negative values for failure.
24 * (This is ONLY used for the idle current measurement by the factory mode.)
developer28d70382019-12-19 15:58:20 +080025 */
developerb63f6b22020-11-06 09:20:25 +080026int mt_irq_mask_restore(struct mtk_irq_mask *mask)
27{
28 if (mask == NULL) {
29 return -1;
30 }
31 if (mask->header != IRQ_MASK_HEADER) {
32 return -1;
33 }
34 if (mask->footer != IRQ_MASK_FOOTER) {
35 return -1;
36 }
developer28d70382019-12-19 15:58:20 +080037
developerb63f6b22020-11-06 09:20:25 +080038 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
39 mask->mask1);
40 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
41 mask->mask2);
42 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
43 mask->mask3);
44 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
45 mask->mask4);
46 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
47 mask->mask5);
48 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
49 mask->mask6);
50 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
51 mask->mask7);
52 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
53 mask->mask8);
54 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
55 mask->mask9);
56 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
57 mask->mask10);
58 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
59 mask->mask11);
60 mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
61 mask->mask12);
62 /* make sure dist changes happen */
63 dsb();
developer28d70382019-12-19 15:58:20 +080064
developerb63f6b22020-11-06 09:20:25 +080065 return 0;
66}
developer28d70382019-12-19 15:58:20 +080067
68/*
developerb63f6b22020-11-06 09:20:25 +080069 * mt_irq_mask_all: disable all interrupts
70 * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
71 * Return 0 for success; return negative values for failure.
72 * (This is ONLY used for the idle current measurement by the factory mode.)
developer28d70382019-12-19 15:58:20 +080073 */
developerb63f6b22020-11-06 09:20:25 +080074int mt_irq_mask_all(struct mtk_irq_mask *mask)
developer28d70382019-12-19 15:58:20 +080075{
developerb63f6b22020-11-06 09:20:25 +080076 if (mask != NULL) {
77 /* for SPI */
78 mask->mask1 = mmio_read_32((BASE_GICD_BASE +
79 GICD_ISENABLER + 0x4));
80 mask->mask2 = mmio_read_32((BASE_GICD_BASE +
81 GICD_ISENABLER + 0x8));
82 mask->mask3 = mmio_read_32((BASE_GICD_BASE +
83 GICD_ISENABLER + 0xc));
84 mask->mask4 = mmio_read_32((BASE_GICD_BASE +
85 GICD_ISENABLER + 0x10));
86 mask->mask5 = mmio_read_32((BASE_GICD_BASE +
87 GICD_ISENABLER + 0x14));
88 mask->mask6 = mmio_read_32((BASE_GICD_BASE +
89 GICD_ISENABLER + 0x18));
90 mask->mask7 = mmio_read_32((BASE_GICD_BASE +
91 GICD_ISENABLER + 0x1c));
92 mask->mask8 = mmio_read_32((BASE_GICD_BASE +
93 GICD_ISENABLER + 0x20));
94 mask->mask9 = mmio_read_32((BASE_GICD_BASE +
95 GICD_ISENABLER + 0x24));
96 mask->mask10 = mmio_read_32((BASE_GICD_BASE +
97 GICD_ISENABLER + 0x28));
98 mask->mask11 = mmio_read_32((BASE_GICD_BASE +
99 GICD_ISENABLER + 0x2c));
100 mask->mask12 = mmio_read_32((BASE_GICD_BASE +
101 GICD_ISENABLER + 0x30));
developer28d70382019-12-19 15:58:20 +0800102
developerb63f6b22020-11-06 09:20:25 +0800103 /* for SPI */
104 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
105 0xFFFFFFFF);
106 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
107 0xFFFFFFFF);
108 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
109 0xFFFFFFFF);
110 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
111 0xFFFFFFFF);
112 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
113 0xFFFFFFFF);
114 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
115 0xFFFFFFFF);
116 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
117 0xFFFFFFFF);
118 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
119 0xFFFFFFFF);
120 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
121 0xFFFFFFFF);
122 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
123 0xFFFFFFFF);
124 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
125 0xFFFFFFFF);
126 mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
127 0xFFFFFFFF);
128 /* make sure distributor changes happen */
129 dsb();
130
131 mask->header = IRQ_MASK_HEADER;
132 mask->footer = IRQ_MASK_FOOTER;
133
134 return 0;
135 } else {
136 return -1;
developer28d70382019-12-19 15:58:20 +0800137 }
developer28d70382019-12-19 15:58:20 +0800138}
139
developerb63f6b22020-11-06 09:20:25 +0800140static uint32_t mt_irq_get_pol(uint32_t irq)
developer28d70382019-12-19 15:58:20 +0800141{
developerb63f6b22020-11-06 09:20:25 +0800142#ifdef CIRQ_WITH_POLARITY
143 uint32_t reg;
144 uint32_t base = INT_POL_CTL0;
developer28d70382019-12-19 15:58:20 +0800145
developerb63f6b22020-11-06 09:20:25 +0800146 if (irq < 32U) {
147 return 0;
148 }
developer28d70382019-12-19 15:58:20 +0800149
developerb63f6b22020-11-06 09:20:25 +0800150 reg = ((irq - 32U) / 32U);
developer28d70382019-12-19 15:58:20 +0800151
developerb63f6b22020-11-06 09:20:25 +0800152 return mmio_read_32(base + reg * 4U);
153#else
154 return 0;
155#endif
developer28d70382019-12-19 15:58:20 +0800156}
157
developerb63f6b22020-11-06 09:20:25 +0800158unsigned int mt_irq_get_sens(unsigned int irq)
developer28d70382019-12-19 15:58:20 +0800159{
developerb63f6b22020-11-06 09:20:25 +0800160 unsigned int config;
developer28d70382019-12-19 15:58:20 +0800161
developerb63f6b22020-11-06 09:20:25 +0800162 /*
163 * 2'b10 edge
164 * 2'b01 level
165 */
166 config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
167 config = (config >> (irq % 16U) * 2U) & 0x3;
developer28d70382019-12-19 15:58:20 +0800168
developerb63f6b22020-11-06 09:20:25 +0800169 return config;
developer28d70382019-12-19 15:58:20 +0800170}
171
developerb63f6b22020-11-06 09:20:25 +0800172static void collect_all_wakeup_events(void)
developer28d70382019-12-19 15:58:20 +0800173{
developerb63f6b22020-11-06 09:20:25 +0800174 unsigned int i;
175 uint32_t gic_irq;
176 uint32_t cirq;
177 uint32_t cirq_reg;
178 uint32_t cirq_offset;
179 uint32_t mask;
180 uint32_t pol_mask;
181 uint32_t irq_offset;
182 uint32_t irq_mask;
developer28d70382019-12-19 15:58:20 +0800183
developerb63f6b22020-11-06 09:20:25 +0800184 if ((cirq_all_events.wakeup_events == NULL) ||
185 cirq_all_events.num_of_events == 0U) {
186 return;
developer28d70382019-12-19 15:58:20 +0800187 }
188
developerb63f6b22020-11-06 09:20:25 +0800189 for (i = 0U; i < cirq_all_events.num_of_events; i++) {
190 if (cirq_all_events.wakeup_events[i] > 0U) {
191 gic_irq = cirq_all_events.wakeup_events[i];
192 cirq = gic_irq - cirq_all_events.spi_start - 32U;
193 cirq_reg = cirq / 32U;
194 cirq_offset = cirq % 32U;
195 mask = 0x1 << cirq_offset;
196 irq_offset = gic_irq % 32U;
197 irq_mask = 0x1 << irq_offset;
198 /*
199 * CIRQ default masks all
200 */
201 cirq_all_events.table[cirq_reg].mask |= mask;
202 /*
203 * CIRQ default pol is low
204 */
205 pol_mask = mt_irq_get_pol(
206 cirq_all_events.wakeup_events[i])
207 & irq_mask;
208 /*
209 * 0 means rising
210 */
211 if (pol_mask == 0U) {
212 cirq_all_events.table[cirq_reg].pol |= mask;
213 }
214 /*
215 * CIRQ could monitor edge/level trigger
216 * cirq register (0: edge, 1: level)
217 */
218 if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
219 == SENS_EDGE) {
220 cirq_all_events.table[cirq_reg].sen |= mask;
221 }
developer28d70382019-12-19 15:58:20 +0800222
developerb63f6b22020-11-06 09:20:25 +0800223 cirq_all_events.table[cirq_reg].used = 1U;
224 cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
225 }
developer28d70382019-12-19 15:58:20 +0800226 }
developer28d70382019-12-19 15:58:20 +0800227}
228
229/*
developerb63f6b22020-11-06 09:20:25 +0800230 * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
231 * @cirq_num: the SYS_CIRQ number to set
232 * @pol: polarity to set
233 * @return:
234 * 0: set pol success
235 * -1: cirq num is out of range
developer28d70382019-12-19 15:58:20 +0800236 */
developerb63f6b22020-11-06 09:20:25 +0800237#ifdef CIRQ_WITH_POLARITY
238static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
developer28d70382019-12-19 15:58:20 +0800239{
developerb63f6b22020-11-06 09:20:25 +0800240 uint32_t base;
241 uint32_t bit = 1U << (cirq_num % 32U);
developer28d70382019-12-19 15:58:20 +0800242
developerb63f6b22020-11-06 09:20:25 +0800243 if (cirq_num >= CIRQ_IRQ_NUM) {
244 return -1;
245 }
246
247 if (pol == MT_CIRQ_POL_NEG) {
248 base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
249 } else if (pol == MT_CIRQ_POL_POS) {
250 base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
251 } else {
252 return -1;
developer28d70382019-12-19 15:58:20 +0800253 }
developerb63f6b22020-11-06 09:20:25 +0800254
255 mmio_write_32(base, bit);
256 return 0;
developer28d70382019-12-19 15:58:20 +0800257}
developerb63f6b22020-11-06 09:20:25 +0800258#endif
developer28d70382019-12-19 15:58:20 +0800259
260/*
261 * mt_cirq_mask: Mask the specified SYS_CIRQ.
262 * @cirq_num: the SYS_CIRQ number to mask
263 * @return:
264 * 0: mask success
265 * -1: cirq num is out of range
266 */
267static int mt_cirq_mask(uint32_t cirq_num)
268{
269 uint32_t bit = 1U << (cirq_num % 32U);
270
271 if (cirq_num >= CIRQ_IRQ_NUM) {
developer28d70382019-12-19 15:58:20 +0800272 return -1;
273 }
274
developerb63f6b22020-11-06 09:20:25 +0800275 mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
276
developer28d70382019-12-19 15:58:20 +0800277 return 0;
278}
279
280/*
281 * mt_cirq_unmask: Unmask the specified SYS_CIRQ.
282 * @cirq_num: the SYS_CIRQ number to unmask
283 * @return:
284 * 0: umask success
285 * -1: cirq num is out of range
286 */
287static int mt_cirq_unmask(uint32_t cirq_num)
288{
289 uint32_t bit = 1U << (cirq_num % 32U);
290
291 if (cirq_num >= CIRQ_IRQ_NUM) {
developer28d70382019-12-19 15:58:20 +0800292 return -1;
293 }
294
developerb63f6b22020-11-06 09:20:25 +0800295 mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
296
developer28d70382019-12-19 15:58:20 +0800297 return 0;
298}
299
developerb63f6b22020-11-06 09:20:25 +0800300uint32_t mt_irq_get_en(uint32_t irq)
developer28d70382019-12-19 15:58:20 +0800301{
developerb63f6b22020-11-06 09:20:25 +0800302 uint32_t addr, st, val;
developer28d70382019-12-19 15:58:20 +0800303
developerb63f6b22020-11-06 09:20:25 +0800304 addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
305 st = mmio_read_32(addr);
developer28d70382019-12-19 15:58:20 +0800306
developerb63f6b22020-11-06 09:20:25 +0800307 val = (st >> (irq % 32U)) & 1U;
developer28d70382019-12-19 15:58:20 +0800308
developerb63f6b22020-11-06 09:20:25 +0800309 return val;
developer28d70382019-12-19 15:58:20 +0800310}
311
developerb63f6b22020-11-06 09:20:25 +0800312static void __cirq_fast_clone(void)
developer28d70382019-12-19 15:58:20 +0800313{
developerb63f6b22020-11-06 09:20:25 +0800314 struct cirq_reg *reg;
315 unsigned int i;
developer28d70382019-12-19 15:58:20 +0800316
developerb63f6b22020-11-06 09:20:25 +0800317 for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
318 uint32_t cirq_bit;
developer28d70382019-12-19 15:58:20 +0800319
developerb63f6b22020-11-06 09:20:25 +0800320 reg = &cirq_all_events.table[i];
developer28d70382019-12-19 15:58:20 +0800321
developerb63f6b22020-11-06 09:20:25 +0800322 if (reg->used == 0U) {
323 continue;
324 }
developer28d70382019-12-19 15:58:20 +0800325
developerb63f6b22020-11-06 09:20:25 +0800326 mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
327 reg->sen);
developer28d70382019-12-19 15:58:20 +0800328
developerb63f6b22020-11-06 09:20:25 +0800329 for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
330 uint32_t val, cirq_id;
331 uint32_t gic_id;
332#ifdef CIRQ_WITH_POLARITY
333 uint32_t gic_bit, pol;
334#endif
335 uint32_t en;
developer28d70382019-12-19 15:58:20 +0800336
developerb63f6b22020-11-06 09:20:25 +0800337 val = ((1U << cirq_bit) & reg->mask);
developer28d70382019-12-19 15:58:20 +0800338
developerb63f6b22020-11-06 09:20:25 +0800339 if (val == 0U) {
340 continue;
341 }
developer28d70382019-12-19 15:58:20 +0800342
developerb63f6b22020-11-06 09:20:25 +0800343 cirq_id = (reg->reg_num << 5U) + cirq_bit;
344 gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
345#ifdef CIRQ_WITH_POLARITY
346 gic_bit = (0x1U << ((gic_id - 32U) % 32U));
347 pol = mt_irq_get_pol(gic_id) & gic_bit;
348 if (pol != 0U) {
349 mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
350 } else {
351 mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
352 }
353#endif
354 en = mt_irq_get_en(gic_id);
355 if (en == 1U) {
356 mt_cirq_unmask(cirq_id);
357 } else {
358 mt_cirq_mask(cirq_id);
359 }
360 }
developer28d70382019-12-19 15:58:20 +0800361 }
developerb63f6b22020-11-06 09:20:25 +0800362}
developer28d70382019-12-19 15:58:20 +0800363
developerb63f6b22020-11-06 09:20:25 +0800364static void cirq_fast_clone(void)
365{
366 if (already_cloned == 0U) {
367 collect_all_wakeup_events();
368 already_cloned = 1U;
369 }
370 __cirq_fast_clone();
developer28d70382019-12-19 15:58:20 +0800371}
372
developerb63f6b22020-11-06 09:20:25 +0800373void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
374{
375 cirq_all_events.num_of_events = num_of_events;
376 cirq_all_events.wakeup_events = list;
377}
developer28d70382019-12-19 15:58:20 +0800378/*
developerb63f6b22020-11-06 09:20:25 +0800379 * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
developer28d70382019-12-19 15:58:20 +0800380 */
developerb63f6b22020-11-06 09:20:25 +0800381void mt_cirq_clone_gic(void)
developer28d70382019-12-19 15:58:20 +0800382{
developerb63f6b22020-11-06 09:20:25 +0800383 cirq_fast_clone();
384}
developer28d70382019-12-19 15:58:20 +0800385
developerb63f6b22020-11-06 09:20:25 +0800386uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
387{
388 uint32_t base = 0U;
389 uint32_t pending_vec = 0U;
390 uint32_t reg = start_irq / 32U;
391 uint32_t LSB_num, MSB_num;
392 uint32_t LSB_vec, MSB_vec;
393
394 base = BASE_GICD_BASE;
395
396 /* if start_irq is not aligned 32, do some assembling */
397 MSB_num = start_irq % 32U;
398 if (MSB_num != 0U) {
399 LSB_num = 32U - MSB_num;
400 LSB_vec = mmio_read_32(base + GICD_ISPENDR +
401 reg * 4U) >> MSB_num;
402 MSB_vec = mmio_read_32(base + GICD_ISPENDR +
403 (reg + 1U) * 4U) << LSB_num;
404 pending_vec = MSB_vec | LSB_vec;
405 } else {
406 pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
developer28d70382019-12-19 15:58:20 +0800407 }
408
developerb63f6b22020-11-06 09:20:25 +0800409 return pending_vec;
developer28d70382019-12-19 15:58:20 +0800410}
411
developerb63f6b22020-11-06 09:20:25 +0800412static int mt_cirq_get_mask_vec(unsigned int i)
413{
414 return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
415}
416
developer28d70382019-12-19 15:58:20 +0800417/*
developerb63f6b22020-11-06 09:20:25 +0800418 * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
developer28d70382019-12-19 15:58:20 +0800419 */
developerb63f6b22020-11-06 09:20:25 +0800420void mt_cirq_ack_all(void)
developer28d70382019-12-19 15:58:20 +0800421{
developerb63f6b22020-11-06 09:20:25 +0800422 uint32_t ack_vec, pend_vec, mask_vec;
423 unsigned int i;
developer28d70382019-12-19 15:58:20 +0800424
developerb63f6b22020-11-06 09:20:25 +0800425 for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
426 /*
427 * if a irq is pending & not masked, don't ack it
428 * , since cirq start irq might not be 32 aligned with gic,
429 * need an exotic API to get proper vector of pending irq
430 */
431 pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
432 + (i + 1U) * 32U);
433 mask_vec = mt_cirq_get_mask_vec(i);
434 /* those should be acked are: "not (pending & not masked)",
435 */
436 ack_vec = (~pend_vec) | mask_vec;
437 mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
developer28d70382019-12-19 15:58:20 +0800438 }
developer28d70382019-12-19 15:58:20 +0800439
developerb63f6b22020-11-06 09:20:25 +0800440 /*
441 * make sure all cirq setting take effect
442 * before doing other things
443 */
444 dsb();
445}
developer28d70382019-12-19 15:58:20 +0800446/*
developerb63f6b22020-11-06 09:20:25 +0800447 * mt_cirq_enable: Enable SYS_CIRQ
developer28d70382019-12-19 15:58:20 +0800448 */
developerb63f6b22020-11-06 09:20:25 +0800449void mt_cirq_enable(void)
developer28d70382019-12-19 15:58:20 +0800450{
developerb63f6b22020-11-06 09:20:25 +0800451 uint32_t st;
developer28d70382019-12-19 15:58:20 +0800452
developerb63f6b22020-11-06 09:20:25 +0800453 /* level only */
454 mt_cirq_ack_all();
developer28d70382019-12-19 15:58:20 +0800455
developerb63f6b22020-11-06 09:20:25 +0800456 st = mmio_read_32(CIRQ_CON);
457 /*
458 * CIRQ could monitor edge/level trigger
459 */
460 st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
developer28d70382019-12-19 15:58:20 +0800461
developerb63f6b22020-11-06 09:20:25 +0800462 mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
developer28d70382019-12-19 15:58:20 +0800463}
464
465/*
developerb63f6b22020-11-06 09:20:25 +0800466 * mt_cirq_disable: Disable SYS_CIRQ
developer28d70382019-12-19 15:58:20 +0800467 */
developerb63f6b22020-11-06 09:20:25 +0800468void mt_cirq_disable(void)
developer28d70382019-12-19 15:58:20 +0800469{
developerb63f6b22020-11-06 09:20:25 +0800470 uint32_t st;
developer28d70382019-12-19 15:58:20 +0800471
developerb63f6b22020-11-06 09:20:25 +0800472 st = mmio_read_32(CIRQ_CON);
473 st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
474 mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
475}
developer28d70382019-12-19 15:58:20 +0800476
developerb63f6b22020-11-06 09:20:25 +0800477void mt_irq_unmask_for_sleep_ex(uint32_t irq)
478{
479 uint32_t mask;
developer28d70382019-12-19 15:58:20 +0800480
developerb63f6b22020-11-06 09:20:25 +0800481 mask = 1U << (irq % 32U);
developer28d70382019-12-19 15:58:20 +0800482
developerb63f6b22020-11-06 09:20:25 +0800483 mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
484 ((irq / 32U) * 4U), mask);
developer28d70382019-12-19 15:58:20 +0800485}
486
developerb63f6b22020-11-06 09:20:25 +0800487void mt_cirq_mask_all(void)
developer28d70382019-12-19 15:58:20 +0800488{
developerb63f6b22020-11-06 09:20:25 +0800489 unsigned int i;
490
491 for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
492 mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
493 }
494 dsb();
developer28d70382019-12-19 15:58:20 +0800495}
496
developerb63f6b22020-11-06 09:20:25 +0800497static void cirq_fast_sw_flush(void)
developer28d70382019-12-19 15:58:20 +0800498{
developerb63f6b22020-11-06 09:20:25 +0800499 struct cirq_reg *reg;
developer28d70382019-12-19 15:58:20 +0800500 unsigned int i;
developer28d70382019-12-19 15:58:20 +0800501
developerb63f6b22020-11-06 09:20:25 +0800502 for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
503 uint32_t cirq_bit;
developer28d70382019-12-19 15:58:20 +0800504
developerb63f6b22020-11-06 09:20:25 +0800505 reg = &cirq_all_events.table[i];
developer28d70382019-12-19 15:58:20 +0800506
developerb63f6b22020-11-06 09:20:25 +0800507 if (reg->used == 0U) {
508 continue;
developer28d70382019-12-19 15:58:20 +0800509 }
510
developerb63f6b22020-11-06 09:20:25 +0800511 reg->pending = mmio_read_32(CIRQ_STA_BASE +
512 (reg->reg_num << 2U));
513 reg->pending &= reg->mask;
514
515 for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
516 uint32_t val, cirq_id;
517
518 val = (1U << cirq_bit) & reg->pending;
519 if (val == 0U) {
developer28d70382019-12-19 15:58:20 +0800520 continue;
developer28d70382019-12-19 15:58:20 +0800521 }
developerb63f6b22020-11-06 09:20:25 +0800522
523 cirq_id = (reg->reg_num << 5U) + cirq_bit;
524 mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
525 if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
526 INFO("Set MD_WDT_IRQ pending in %s\n",
527 __func__);
developer28d70382019-12-19 15:58:20 +0800528 }
developer28d70382019-12-19 15:58:20 +0800529 }
530 }
developerb63f6b22020-11-06 09:20:25 +0800531}
developer28d70382019-12-19 15:58:20 +0800532
developerb63f6b22020-11-06 09:20:25 +0800533/*
534 * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
535 */
536void mt_cirq_flush(void)
537{
538 cirq_fast_sw_flush();
developer28d70382019-12-19 15:58:20 +0800539 mt_cirq_mask_all();
540 mt_cirq_ack_all();
541}
542
543void mt_cirq_sw_reset(void)
544{
developerb63f6b22020-11-06 09:20:25 +0800545#ifdef CIRQ_NEED_SW_RESET
developer28d70382019-12-19 15:58:20 +0800546 uint32_t st;
547
developerb63f6b22020-11-06 09:20:25 +0800548 st = mmio_read_32(CIRQ_CON);
developer28d70382019-12-19 15:58:20 +0800549 st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
developerb63f6b22020-11-06 09:20:25 +0800550 mmio_write_32(CIRQ_CON, st);
551#endif
developer28d70382019-12-19 15:58:20 +0800552}