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