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 int irq_is_busy(int irq) 68 { 69 return (irq >= 0 && irqs_desc[irq].handle_irq) ? -EBUSY : 0; 70 } 71 72 static int chip_irq_bad(struct irq_chip *chip) 73 { 74 if (!chip->name || 75 !chip->irq_init || 76 !chip->irq_enable || 77 !chip->irq_disable || 78 !chip->irq_set_type) 79 return -EINVAL; 80 81 return 0; 82 } 83 84 static int _do_arch_irq_init(void) 85 { 86 int irq, err = -EINVAL; 87 88 /* After relocation done, bss data initialized */ 89 if (!(gd->flags & GD_FLG_RELOC)) { 90 printf("WARN: interrupt should be init after reloc\n"); 91 return -EINVAL; 92 } 93 94 /* 95 * should set true before arch_gpio_irq_init(), otherwise 96 * can't request irqs for gpio banks. 97 */ 98 initialized = true; 99 100 for (irq = 0; irq < PLATFORM_MAX_IRQS_NR; irq++) { 101 irqs_desc[irq].handle_irq = NULL; 102 irqs_desc[irq].data = NULL; 103 } 104 105 gic_irq_chip = arch_gic_irq_init(); 106 if (chip_irq_bad(gic_irq_chip)) { 107 printf("ERROR: bad gic irq chip\n"); 108 goto out; 109 } 110 111 gpio_irq_chip = arch_gpio_irq_init(); 112 if (chip_irq_bad(gpio_irq_chip)) { 113 printf("ERROR: bad gpio irq chip\n"); 114 goto out; 115 } 116 117 err = gic_irq_chip->irq_init(); 118 if (err) { 119 printf("ERROR: gic interrupt init failed\n"); 120 goto out; 121 } 122 123 err = gpio_irq_chip->irq_init(); 124 if (err) { 125 printf("ERROR: gpio interrupt init failed\n"); 126 goto out; 127 } 128 129 return 0; 130 131 out: 132 initialized = false; 133 134 return err; 135 } 136 137 int irq_handler_enable(int irq) 138 { 139 if (irq_bad(irq)) 140 return -EINVAL; 141 142 if (irq < PLATFORM_GIC_IRQS_NR) 143 return gic_irq_chip->irq_enable(irq); 144 else 145 return gpio_irq_chip->irq_enable(irq); 146 } 147 148 int irq_handler_disable(int irq) 149 { 150 if (irq_bad(irq)) 151 return -EINVAL; 152 153 if (irq < PLATFORM_GIC_IRQS_NR) 154 return gic_irq_chip->irq_disable(irq); 155 else 156 return gpio_irq_chip->irq_disable(irq); 157 } 158 159 int irq_set_irq_type(int irq, unsigned int type) 160 { 161 if (irq_bad(irq)) 162 return -EINVAL; 163 164 if (irq < PLATFORM_GIC_IRQS_NR) 165 return gic_irq_chip->irq_set_type(irq, type); 166 else 167 return gpio_irq_chip->irq_set_type(irq, type); 168 } 169 170 int irq_revert_irq_type(int irq) 171 { 172 if (irq_bad(irq)) 173 return -EINVAL; 174 175 if (irq < PLATFORM_GIC_IRQS_NR) 176 return 0; 177 else 178 return gpio_irq_chip->irq_revert_type(irq); 179 } 180 181 int irq_get_gpio_level(int irq) 182 { 183 if (irq_bad(irq)) 184 return -EINVAL; 185 186 if (irq < PLATFORM_GIC_IRQS_NR) 187 return 0; 188 else 189 return gpio_irq_chip->irq_get_gpio_level(irq); 190 } 191 192 void irq_install_handler(int irq, interrupt_handler_t *handler, void *data) 193 { 194 if (irq_bad(irq)) 195 return; 196 197 irqs_desc[irq].handle_irq = handler; 198 irqs_desc[irq].data = data; 199 } 200 201 void irq_free_handler(int irq) 202 { 203 if (irq_handler_disable(irq)) 204 return; 205 206 irqs_desc[irq].handle_irq = NULL; 207 irqs_desc[irq].data = NULL; 208 } 209 210 int irqs_suspend(void) 211 { 212 int err; 213 214 err = gic_irq_chip->irq_suspend(); 215 if (err) { 216 printf("ERROR: irqs suspend failed\n"); 217 return err; 218 } 219 220 return 0; 221 } 222 223 int irqs_resume(void) 224 { 225 int err; 226 227 err = gic_irq_chip->irq_resume(); 228 if (err) { 229 printf("ERROR: irqs resume failed\n"); 230 return err; 231 } 232 233 return 0; 234 } 235 236 #ifdef CONFIG_ARM64 237 static void cpu_local_irq_enable(void) 238 { 239 asm volatile("msr daifclr, #0x02"); 240 } 241 242 static int cpu_local_irq_disable(void) 243 { 244 asm volatile("msr daifset, #0x02"); 245 246 return 0; 247 } 248 249 void do_irq(struct pt_regs *pt_regs, unsigned int esr) 250 { 251 #ifdef CONFIG_ROCKCHIP_DEBUGGER 252 printf("\n>>> Rockchip Debugger:\n"); 253 show_regs(pt_regs); 254 #endif 255 256 _do_generic_irq_handler(); 257 } 258 #else 259 static void cpu_local_irq_enable(void) 260 { 261 unsigned long cpsr; 262 263 __asm__ __volatile__("mrs %0, cpsr\n" 264 "bic %0, %0, #0x80\n" 265 "msr cpsr_c, %0" 266 : "=r" (cpsr) : : "memory"); 267 } 268 269 static int cpu_local_irq_disable(void) 270 { 271 unsigned long old_cpsr, new_cpsr; 272 273 __asm__ __volatile__("mrs %0, cpsr\n" 274 "orr %1, %0, #0xc0\n" 275 "msr cpsr_c, %1" 276 : "=r" (old_cpsr), "=r" (new_cpsr) 277 : 278 : "memory"); 279 280 return (old_cpsr & 0x80) == 0; 281 } 282 283 void do_irq(struct pt_regs *pt_regs) 284 { 285 #ifdef CONFIG_ROCKCHIP_DEBUGGER 286 printf("\n>>> Rockchp Debugger:\n"); 287 show_regs(pt_regs); 288 #endif 289 290 _do_generic_irq_handler(); 291 } 292 #endif 293 294 int arch_interrupt_init(void) 295 { 296 #ifndef CONFIG_ARM64 297 unsigned long cpsr __maybe_unused; 298 299 /* stack has been reserved in: arch_reserve_stacks() */ 300 IRQ_STACK_START = gd->irq_sp; 301 IRQ_STACK_START_IN = gd->irq_sp; 302 303 __asm__ __volatile__("mrs %0, cpsr\n" 304 : "=r" (cpsr) 305 : 306 : "memory"); 307 308 __asm__ __volatile__("msr cpsr_c, %0\n" 309 "mov sp, %1\n" 310 : 311 : "r" (IRQ_MODE | I_BIT | 312 F_BIT | (cpsr & ~FIQ_MODE)), 313 "r" (IRQ_STACK_START) 314 : "memory"); 315 316 __asm__ __volatile__("msr cpsr_c, %0" 317 : 318 : "r" (cpsr) 319 : "memory"); 320 #endif 321 return _do_arch_irq_init(); 322 } 323 324 int interrupt_init(void) 325 { 326 return arch_interrupt_init(); 327 } 328 329 void enable_interrupts(void) 330 { 331 cpu_local_irq_enable(); 332 } 333 334 int disable_interrupts(void) 335 { 336 return cpu_local_irq_disable(); 337 } 338