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_handler_disable(irq)) 177 return; 178 179 irqs_desc[irq].handle_irq = NULL; 180 irqs_desc[irq].data = NULL; 181 } 182 183 int irqs_suspend(void) 184 { 185 int err; 186 187 err = gic_irq_chip->irq_suspend(); 188 if (err) { 189 printf("ERROR: irqs suspend failed\n"); 190 return err; 191 } 192 193 return 0; 194 } 195 196 int irqs_resume(void) 197 { 198 int err; 199 200 err = gic_irq_chip->irq_resume(); 201 if (err) { 202 printf("ERROR: irqs resume failed\n"); 203 return err; 204 } 205 206 return 0; 207 } 208 209 #ifdef CONFIG_ARM64 210 static void cpu_local_irq_enable(void) 211 { 212 asm volatile("msr daifclr, #0x02"); 213 } 214 215 static int cpu_local_irq_disable(void) 216 { 217 asm volatile("msr daifset, #0x02"); 218 219 return 0; 220 } 221 222 void do_irq(struct pt_regs *pt_regs, unsigned int esr) 223 { 224 _do_generic_irq_handler(); 225 } 226 #else 227 static void cpu_local_irq_enable(void) 228 { 229 unsigned long cpsr; 230 231 __asm__ __volatile__("mrs %0, cpsr\n" 232 "bic %0, %0, #0x80\n" 233 "msr cpsr_c, %0" 234 : "=r" (cpsr) : : "memory"); 235 } 236 237 static int cpu_local_irq_disable(void) 238 { 239 unsigned long old_cpsr, new_cpsr; 240 241 __asm__ __volatile__("mrs %0, cpsr\n" 242 "orr %1, %0, #0xc0\n" 243 "msr cpsr_c, %1" 244 : "=r" (old_cpsr), "=r" (new_cpsr) 245 : 246 : "memory"); 247 248 return (old_cpsr & 0x80) == 0; 249 } 250 251 void do_irq(struct pt_regs *pt_regs) 252 { 253 _do_generic_irq_handler(); 254 } 255 #endif 256 257 int arch_interrupt_init(void) 258 { 259 #ifndef CONFIG_ARM64 260 unsigned long cpsr __maybe_unused; 261 262 /* stack has been reserved in: arch_reserve_stacks() */ 263 IRQ_STACK_START = gd->irq_sp; 264 265 __asm__ __volatile__("mrs %0, cpsr\n" 266 : "=r" (cpsr) 267 : 268 : "memory"); 269 270 __asm__ __volatile__("msr cpsr_c, %0\n" 271 "mov sp, %1\n" 272 : 273 : "r" (IRQ_MODE | I_BIT | 274 F_BIT | (cpsr & ~FIQ_MODE)), 275 "r" (IRQ_STACK_START) 276 : "memory"); 277 278 __asm__ __volatile__("msr cpsr_c, %0" 279 : 280 : "r" (cpsr) 281 : "memory"); 282 #endif 283 return _do_arch_irq_init(); 284 } 285 286 int interrupt_init(void) 287 { 288 return arch_interrupt_init(); 289 } 290 291 void enable_interrupts(void) 292 { 293 cpu_local_irq_enable(); 294 } 295 296 int disable_interrupts(void) 297 { 298 return cpu_local_irq_disable(); 299 } 300