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 */ 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 */ 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 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 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 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 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 */ 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 */ 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 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 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 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 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 */ 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 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 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 */ 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 */ 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 */ 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 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 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 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 */ 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 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