1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <util.h> 8#include <stdint.h> 9#include <plat/machine.h> 10BOOT_CODE void initIRQController(void) 11{ 12 /* Disable all interrupts */ 13 intc_regs->bfDisableIRQs[0] = 0xffffffff; 14 intc_regs->bfDisableIRQs[1] = 0xffffffff; 15 intc_regs->bfDisableBasicIRQs = 0xffffffff; 16 /* Disable FIQ */ 17 intc_regs->FIQ_control &= ~FIQCTRL_FIQ_ENABLE; 18 /* Enable IRQ control for GPU */ 19 intc_regs->bfEnableBasicIRQs = BIT(INTERRUPT_BASIC_IRQ_PENDING_REGISTER1 - BASIC_IRQ_OFFSET); 20 intc_regs->bfEnableBasicIRQs = BIT(INTERRUPT_BASIC_IRQ_PENDING_REGISTER2 - BASIC_IRQ_OFFSET); 21 22 core_regs->coreTimerPrescaler = 0x80000000; 23} 24 25BOOT_CODE void cpu_initLocalIRQController(void) {} 26 27static inline irq_t getActiveIRQ(void) 28{ 29 uint32_t pending; 30 uint32_t irq; 31 /* Read core interrupt register */ 32 pending = core_regs->coreIRQSource[0]; 33 /* Mask out invalid bits */ 34 pending &= MASK(12); 35 /* If pending == 0 spurious interrupt */ 36 if (pending == 0) { 37 return irqInvalid; 38 } 39 40 /* Get IRQ number */ 41 irq = (wordBits - 1 - clzl(pending)); 42 if (irq != INTERRUPT_CORE_GPU) { 43 return irq; 44 } 45 46 /* GPU interrupt */ 47 pending = intc_regs->bfIRQBasicPending; 48 pending &= intc_regs->bfEnableBasicIRQs; 49 /* Mask out pending register 0 and 1 */ 50 pending &= ~BIT(INTERRUPT_BASIC_IRQ_PENDING_REGISTER1 - BASIC_IRQ_OFFSET); 51 pending &= ~BIT(INTERRUPT_BASIC_IRQ_PENDING_REGISTER2 - BASIC_IRQ_OFFSET); 52 if (pending) { 53 return (wordBits - 1 - clzl(pending)) + BASIC_IRQ_OFFSET; 54 } 55 56 pending = intc_regs->bfGPUIRQPending[1]; 57 pending &= intc_regs->bfEnableIRQs[1]; 58 if (pending) { 59 return (wordBits - 1 - clzl(pending)) + 32 + NORMAL_IRQ_OFFSET; 60 } 61 pending = intc_regs->bfGPUIRQPending[0]; 62 pending &= intc_regs->bfEnableIRQs[0]; 63 if (pending) { 64 return (wordBits - 1 - clzl(pending)) + 0 + NORMAL_IRQ_OFFSET; 65 } 66 67 return irqInvalid; 68} 69 70static inline void maskInterrupt(bool_t disable, irq_t irq) 71{ 72 switch (irq) { 73 case INTERRUPT_CORE_CNTPSIRQ : 74 case INTERRUPT_CORE_CNTPNSIRQ: 75 case INTERRUPT_CORE_CNTHPIRQ : 76 case INTERRUPT_CORE_CNTVIRQ : 77 if (disable) { 78 core_regs->coreTimersIrqCtrl[0] &= ~BIT(irq); 79 } else { 80 core_regs->coreTimersIrqCtrl[0] |= BIT(irq); 81 } 82 return; 83 case INTERRUPT_CORE_MAILBOX_0: 84 case INTERRUPT_CORE_MAILBOX_1: 85 case INTERRUPT_CORE_MAILBOX_2: 86 case INTERRUPT_CORE_MAILBOX_3: 87 if (disable) { 88 core_regs->coreMailboxesIrqCtrl[0] &= ~BIT(irq); 89 } else { 90 core_regs->coreMailboxesIrqCtrl[0] |= BIT(irq); 91 } 92 return; 93 case INTERRUPT_CORE_LOCAL_TIMER: 94 if (disable) { 95 core_regs->localTimerCtl &= ~BIT(LOCAL_TIMER_CTRL_IRQ_BIT); 96 } else { 97 core_regs->localTimerCtl |= BIT(LOCAL_TIMER_CTRL_IRQ_BIT); 98 } 99 return; 100 case INTERRUPT_CORE_GPU: 101 // Not maskable 102 case INTERRUPT_CORE_PMU: 103 // Not currently handled 104 case INTERRUPT_CORE_AXI: 105 // Not currently handled 106 return; 107 default: 108 break; 109 } 110 if (irq < BASIC_IRQ_OFFSET) { 111 // Other invalid irq 112 return; 113 } 114 115 if (irq < NORMAL_IRQ_OFFSET) { 116 if (disable) { 117 intc_regs->bfDisableBasicIRQs = BIT(irq - BASIC_IRQ_OFFSET); 118 } else { 119 intc_regs->bfEnableBasicIRQs = BIT(irq - BASIC_IRQ_OFFSET); 120 } 121 } else if (irq < maxIRQ) { 122 int normal_irq = irq - NORMAL_IRQ_OFFSET; 123 int index = normal_irq / 32; 124 if (disable) { 125 intc_regs->bfDisableIRQs[index] = BIT(normal_irq % 32); 126 } else { 127 intc_regs->bfEnableIRQs[index] = BIT(normal_irq % 32); 128 } 129 } 130} 131