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