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