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