1 /* 2 * Copyright (c) 2019-2020 Cobham Gaisler AB 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /* 8 * This is a driver for the GRLIB IRQMP interrupt controller common in LEON 9 * systems. 10 * 11 * Interrupt level 1..15 are SPARC interrupts. Interrupt level 16..31, if 12 * implemented in the interrupt controller, are IRQMP "extended interrupts". 13 * 14 * For more information about IRQMP, see the GRLIB IP Core User's Manual. 15 */ 16 17 #define DT_DRV_COMPAT gaisler_irqmp 18 19 #include <zephyr/kernel.h> 20 #include <zephyr/init.h> 21 22 /* 23 * Register description for IRQMP and IRQAMP interrupt controllers 24 * IRQMP - Multiprocessor Interrupt Controller 25 * IRQ(A)MP - Multiprocessor Interrupt Controller with extended ASMP support 26 */ 27 #define IRQMP_NCPU_MAX 16 28 struct irqmp_regs { 29 uint32_t ilevel; /* 0x00 */ 30 uint32_t ipend; /* 0x04 */ 31 uint32_t iforce0; /* 0x08 */ 32 uint32_t iclear; /* 0x0c */ 33 uint32_t mpstat; /* 0x10 */ 34 uint32_t brdlst; /* 0x14 */ 35 uint32_t errstat; /* 0x18 */ 36 uint32_t wdogctrl; /* 0x1c */ 37 uint32_t asmpctrl; /* 0x20 */ 38 uint32_t icselr[2]; /* 0x24 */ 39 uint32_t reserved2c; /* 0x2c */ 40 uint32_t reserved30; /* 0x30 */ 41 uint32_t reserved34; /* 0x34 */ 42 uint32_t reserved38; /* 0x38 */ 43 uint32_t reserved3c; /* 0x3c */ 44 uint32_t pimask[IRQMP_NCPU_MAX]; /* 0x40 */ 45 uint32_t piforce[IRQMP_NCPU_MAX]; /* 0x80 */ 46 uint32_t pextack[IRQMP_NCPU_MAX]; /* 0xc0 */ 47 }; 48 49 #define IRQMP_PEXTACK_EID (0x1f << 0) 50 get_irqmp_regs(void)51static volatile struct irqmp_regs *get_irqmp_regs(void) 52 { 53 return (struct irqmp_regs *) DT_INST_REG_ADDR(0); 54 } 55 get_irqmp_eirq(void)56static int get_irqmp_eirq(void) 57 { 58 return DT_INST_PROP(0, eirq); 59 } 60 arch_irq_enable(unsigned int source)61void arch_irq_enable(unsigned int source) 62 { 63 volatile struct irqmp_regs *regs = get_irqmp_regs(); 64 volatile uint32_t *pimask = ®s->pimask[0]; 65 const uint32_t setbit = (1U << source); 66 unsigned int key; 67 68 key = arch_irq_lock(); 69 *pimask |= setbit; 70 arch_irq_unlock(key); 71 } 72 arch_irq_disable(unsigned int source)73void arch_irq_disable(unsigned int source) 74 { 75 volatile struct irqmp_regs *regs = get_irqmp_regs(); 76 volatile uint32_t *pimask = ®s->pimask[0]; 77 const uint32_t keepbits = ~(1U << source); 78 unsigned int key; 79 80 key = arch_irq_lock(); 81 *pimask &= keepbits; 82 arch_irq_unlock(key); 83 } 84 arch_irq_is_enabled(unsigned int source)85int arch_irq_is_enabled(unsigned int source) 86 { 87 volatile struct irqmp_regs *regs = get_irqmp_regs(); 88 volatile uint32_t *pimask = ®s->pimask[0]; 89 90 return !!(*pimask & (1U << source)); 91 } 92 z_sparc_int_get_source(int irl)93int z_sparc_int_get_source(int irl) 94 { 95 volatile struct irqmp_regs *regs = get_irqmp_regs(); 96 const int eirq = get_irqmp_eirq(); 97 int source; 98 99 if ((eirq != 0) && (irl == eirq)) { 100 source = regs->pextack[0] & IRQMP_PEXTACK_EID; 101 if (source == 0) { 102 source = irl; 103 } 104 } else { 105 source = irl; 106 } 107 108 return source; 109 } 110 irqmp_init(void)111static int irqmp_init(void) 112 { 113 volatile struct irqmp_regs *regs = get_irqmp_regs(); 114 115 regs->ilevel = 0; 116 regs->ipend = 0; 117 regs->iforce0 = 0; 118 regs->pimask[0] = 0; 119 regs->piforce[0] = 0xfffe0000; 120 121 return 0; 122 } 123 124 SYS_INIT(irqmp_init, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY); 125