1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <asm/io.h> 8 #include <asm/u-boot-arm.h> 9 #include <irq-generic.h> 10 #include "irq-gic.h" 11 #include "irq-gpio.h" 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 struct irq_desc { 16 interrupt_handler_t *handle_irq; 17 void *data; 18 }; 19 20 static struct irq_desc irqs_desc[PLATFORM_MAX_IRQS_NR]; 21 static struct irq_chip *gic_irq_chip, *gpio_irq_chip; 22 static bool initialized; 23 24 static int irq_bad(int irq) 25 { 26 if (irq >= PLATFORM_MAX_IRQS_NR) { 27 printf("WARN: IRQ %d is out of max supported IRQ %d\n", 28 irq, PLATFORM_MAX_IRQS_NR); 29 return -EINVAL; 30 } 31 32 if (!initialized) { 33 printf("WARN: Interrupt framework is not initialized\n"); 34 return -EINVAL; 35 } 36 37 return 0; 38 } 39 40 /* general interrupt handler for gpio chip */ 41 void _generic_gpio_handle_irq(int irq) 42 { 43 if (irq_bad(irq)) 44 return; 45 46 if (irq < PLATFORM_GIC_IRQS_NR) { 47 printf("WRAN: IRQ %d is not a GPIO irq\n", irq); 48 return; 49 } 50 51 if (irqs_desc[irq].handle_irq) 52 irqs_desc[irq].handle_irq(irq, irqs_desc[irq].data); 53 } 54 55 void _do_generic_irq_handler(void) 56 { 57 u32 irq = gic_irq_chip->irq_get(); 58 59 if (irq < PLATFORM_GIC_IRQS_NR) { 60 if (irqs_desc[irq].handle_irq) 61 irqs_desc[irq].handle_irq(irq, irqs_desc[irq].data); 62 } 63 64 gic_irq_chip->irq_eoi(irq); 65 } 66 67 static int chip_irq_bad(struct irq_chip *chip) 68 { 69 if (!chip->name || 70 !chip->irq_init || 71 !chip->irq_enable || 72 !chip->irq_disable || 73 !chip->irq_set_type) 74 return -EINVAL; 75 76 return 0; 77 } 78 79 static int _do_arch_irq_init(void) 80 { 81 int irq, err = -EINVAL; 82 83 /* After relocation done, bss data initialized */ 84 if (!(gd->flags & GD_FLG_RELOC)) { 85 printf("WARN: interrupt should be init after reloc\n"); 86 return -EINVAL; 87 } 88 89 /* 90 * should set true before arch_gpio_irq_init(), otherwise 91 * can't request irqs for gpio banks. 92 */ 93 initialized = true; 94 95 for (irq = 0; irq < PLATFORM_MAX_IRQS_NR; irq++) { 96 irqs_desc[irq].handle_irq = NULL; 97 irqs_desc[irq].data = NULL; 98 } 99 100 gic_irq_chip = arch_gic_irq_init(); 101 if (chip_irq_bad(gic_irq_chip)) { 102 printf("ERROR: bad gic irq chip\n"); 103 goto out; 104 } 105 106 gpio_irq_chip = arch_gpio_irq_init(); 107 if (chip_irq_bad(gpio_irq_chip)) { 108 printf("ERROR: bad gpio irq chip\n"); 109 goto out; 110 } 111 112 err = gic_irq_chip->irq_init(); 113 if (err) { 114 printf("ERROR: gic interrupt init failed\n"); 115 goto out; 116 } 117 118 err = gpio_irq_chip->irq_init(); 119 if (err) { 120 printf("ERROR: gpio interrupt init failed\n"); 121 goto out; 122 } 123 124 return 0; 125 126 out: 127 initialized = false; 128 129 return err; 130 } 131 132 int irq_handler_enable(int irq) 133 { 134 if (irq_bad(irq)) 135 return -EINVAL; 136 137 if (irq < PLATFORM_GIC_IRQS_NR) 138 return gic_irq_chip->irq_enable(irq); 139 else 140 return gpio_irq_chip->irq_enable(irq); 141 } 142 143 int irq_handler_disable(int irq) 144 { 145 if (irq_bad(irq)) 146 return -EINVAL; 147 148 if (irq < PLATFORM_GIC_IRQS_NR) 149 return gic_irq_chip->irq_disable(irq); 150 else 151 return gpio_irq_chip->irq_disable(irq); 152 } 153 154 int irq_set_irq_type(int irq, unsigned int type) 155 { 156 if (irq_bad(irq)) 157 return -EINVAL; 158 159 if (irq < PLATFORM_GIC_IRQS_NR) 160 return gic_irq_chip->irq_set_type(irq, type); 161 else 162 return gpio_irq_chip->irq_set_type(irq, type); 163 } 164 165 void irq_install_handler(int irq, interrupt_handler_t *handler, void *data) 166 { 167 if (irq_bad(irq)) 168 return; 169 170 irqs_desc[irq].handle_irq = handler; 171 irqs_desc[irq].data = data; 172 } 173 174 void irq_free_handler(int irq) 175 { 176 if (irq_bad(irq)) 177 return; 178 179 irqs_desc[irq].handle_irq = NULL; 180 irqs_desc[irq].data = NULL; 181 } 182 183 #ifdef CONFIG_ARM64 184 static void cpu_local_irq_enable(void) 185 { 186 asm volatile("msr daifclr, #0x02"); 187 } 188 189 static int cpu_local_irq_disable(void) 190 { 191 asm volatile("msr daifset, #0x02"); 192 193 return 0; 194 } 195 196 void do_irq(struct pt_regs *pt_regs, unsigned int esr) 197 { 198 _do_generic_irq_handler(); 199 } 200 #else 201 static void cpu_local_irq_enable(void) 202 { 203 unsigned long cpsr; 204 205 __asm__ __volatile__("mrs %0, cpsr\n" 206 "bic %0, %0, #0x80\n" 207 "msr cpsr_c, %0" 208 : "=r" (cpsr) : : "memory"); 209 } 210 211 static int cpu_local_irq_disable(void) 212 { 213 unsigned long old_cpsr, new_cpsr; 214 215 __asm__ __volatile__("mrs %0, cpsr\n" 216 "orr %1, %0, #0xc0\n" 217 "msr cpsr_c, %1" 218 : "=r" (old_cpsr), "=r" (new_cpsr) 219 : 220 : "memory"); 221 222 return (old_cpsr & 0x80) == 0; 223 } 224 225 void do_irq(struct pt_regs *pt_regs) 226 { 227 _do_generic_irq_handler(); 228 } 229 #endif 230 231 int arch_interrupt_init(void) 232 { 233 #ifndef CONFIG_ARM64 234 unsigned long cpsr __maybe_unused; 235 236 /* stack has been reserved in: arch_reserve_stacks() */ 237 IRQ_STACK_START = gd->irq_sp; 238 239 __asm__ __volatile__("mrs %0, cpsr\n" 240 : "=r" (cpsr) 241 : 242 : "memory"); 243 244 __asm__ __volatile__("msr cpsr_c, %0\n" 245 "mov sp, %1\n" 246 : 247 : "r" (IRQ_MODE | I_BIT | 248 F_BIT | (cpsr & ~FIQ_MODE)), 249 "r" (IRQ_STACK_START) 250 : "memory"); 251 252 __asm__ __volatile__("msr cpsr_c, %0" 253 : 254 : "r" (cpsr) 255 : "memory"); 256 #endif 257 return _do_arch_irq_init(); 258 } 259 260 int interrupt_init(void) 261 { 262 return arch_interrupt_init(); 263 } 264 265 void enable_interrupts(void) 266 { 267 cpu_local_irq_enable(); 268 } 269 270 int disable_interrupts(void) 271 { 272 return cpu_local_irq_disable(); 273 } 274