Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+ 2 : : /* 3 : : * Copyright 2010 Broadcom 4 : : * Copyright 2012 Simon Arlott, Chris Boot, Stephen Warren 5 : : * 6 : : * Quirk 1: Shortcut interrupts don't set the bank 1/2 register pending bits 7 : : * 8 : : * If an interrupt fires on bank 1 that isn't in the shortcuts list, bit 8 9 : : * on bank 0 is set to signify that an interrupt in bank 1 has fired, and 10 : : * to look in the bank 1 status register for more information. 11 : : * 12 : : * If an interrupt fires on bank 1 that _is_ in the shortcuts list, its 13 : : * shortcut bit in bank 0 is set as well as its interrupt bit in the bank 1 14 : : * status register, but bank 0 bit 8 is _not_ set. 15 : : * 16 : : * Quirk 2: You can't mask the register 1/2 pending interrupts 17 : : * 18 : : * In a proper cascaded interrupt controller, the interrupt lines with 19 : : * cascaded interrupt controllers on them are just normal interrupt lines. 20 : : * You can mask the interrupts and get on with things. With this controller 21 : : * you can't do that. 22 : : * 23 : : * Quirk 3: The shortcut interrupts can't be (un)masked in bank 0 24 : : * 25 : : * Those interrupts that have shortcuts can only be masked/unmasked in 26 : : * their respective banks' enable/disable registers. Doing so in the bank 0 27 : : * enable/disable registers has no effect. 28 : : * 29 : : * The FIQ control register: 30 : : * Bits 0-6: IRQ (index in order of interrupts from banks 1, 2, then 0) 31 : : * Bit 7: Enable FIQ generation 32 : : * Bits 8+: Unused 33 : : * 34 : : * An interrupt must be disabled before configuring it for FIQ generation 35 : : * otherwise both handlers will fire at the same time! 36 : : */ 37 : : 38 : : #include <linux/io.h> 39 : : #include <linux/slab.h> 40 : : #include <linux/of_address.h> 41 : : #include <linux/of_irq.h> 42 : : #include <linux/irqchip.h> 43 : : #include <linux/irqdomain.h> 44 : : 45 : : #include <asm/exception.h> 46 : : #ifndef CONFIG_ARM64 47 : : #include <asm/mach/irq.h> 48 : : #endif 49 : : 50 : : /* Put the bank and irq (32 bits) into the hwirq */ 51 : : #define MAKE_HWIRQ(b, n) (((b) << 5) | (n)) 52 : : #define HWIRQ_BANK(i) (i >> 5) 53 : : #define HWIRQ_BIT(i) BIT(i & 0x1f) 54 : : 55 : : #define NR_IRQS_BANK0 8 56 : : #define BANK0_HWIRQ_MASK 0xff 57 : : /* Shortcuts can't be disabled so any unknown new ones need to be masked */ 58 : : #define SHORTCUT1_MASK 0x00007c00 59 : : #define SHORTCUT2_MASK 0x001f8000 60 : : #define SHORTCUT_SHIFT 10 61 : : #define BANK1_HWIRQ BIT(8) 62 : : #define BANK2_HWIRQ BIT(9) 63 : : #define BANK0_VALID_MASK (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \ 64 : : | SHORTCUT1_MASK | SHORTCUT2_MASK) 65 : : 66 : : #undef ARM_LOCAL_GPU_INT_ROUTING 67 : : #define ARM_LOCAL_GPU_INT_ROUTING 0x0c 68 : : 69 : : #define REG_FIQ_CONTROL 0x0c 70 : : #define FIQ_CONTROL_ENABLE BIT(7) 71 : : 72 : : #define NR_BANKS 3 73 : : #define IRQS_PER_BANK 32 74 : : #define NUMBER_IRQS MAKE_HWIRQ(NR_BANKS, 0) 75 : : 76 : : static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 }; 77 : : static const int reg_enable[] __initconst = { 0x18, 0x10, 0x14 }; 78 : : static const int reg_disable[] __initconst = { 0x24, 0x1c, 0x20 }; 79 : : static const int bank_irqs[] __initconst = { 8, 32, 32 }; 80 : : 81 : : static const int shortcuts[] = { 82 : : 7, 9, 10, 18, 19, /* Bank 1 */ 83 : : 21, 22, 23, 24, 25, 30 /* Bank 2 */ 84 : : }; 85 : : 86 : : struct armctrl_ic { 87 : : void __iomem *base; 88 : : void __iomem *pending[NR_BANKS]; 89 : : void __iomem *enable[NR_BANKS]; 90 : : void __iomem *disable[NR_BANKS]; 91 : : struct irq_domain *domain; 92 : : void __iomem *local_base; 93 : : }; 94 : : 95 : : static struct armctrl_ic intc __read_mostly; 96 : : static void __exception_irq_entry bcm2835_handle_irq( 97 : : struct pt_regs *regs); 98 : : static void bcm2836_chained_handle_irq(struct irq_desc *desc); 99 : : 100 : : static inline unsigned int hwirq_to_fiq(unsigned long hwirq) 101 : : { 102 : 3 : hwirq -= NUMBER_IRQS; 103 : : /* 104 : : * The hwirq numbering used in this driver is: 105 : : * BASE (0-7) GPU1 (32-63) GPU2 (64-95). 106 : : * This differ from the one used in the FIQ register: 107 : : * GPU1 (0-31) GPU2 (32-63) BASE (64-71) 108 : : */ 109 : 3 : if (hwirq >= 32) 110 : 3 : return hwirq - 32; 111 : : 112 : 0 : return hwirq + 64; 113 : : } 114 : : 115 : 3 : static void armctrl_mask_irq(struct irq_data *d) 116 : : { 117 : 3 : if (d->hwirq >= NUMBER_IRQS) 118 : 0 : writel_relaxed(0, intc.base + REG_FIQ_CONTROL); 119 : : else 120 : 3 : writel_relaxed(HWIRQ_BIT(d->hwirq), 121 : : intc.disable[HWIRQ_BANK(d->hwirq)]); 122 : 3 : } 123 : : 124 : 3 : static void armctrl_unmask_irq(struct irq_data *d) 125 : : { 126 : 3 : if (d->hwirq >= NUMBER_IRQS) { 127 : 3 : if (num_online_cpus() > 1) { 128 : : unsigned int data; 129 : : 130 : 3 : if (!intc.local_base) { 131 : 0 : pr_err("FIQ is disabled due to missing arm_local_intc\n"); 132 : 3 : return; 133 : : } 134 : : 135 : 3 : data = readl_relaxed(intc.local_base + 136 : : ARM_LOCAL_GPU_INT_ROUTING); 137 : : 138 : 3 : data &= ~0xc; 139 : 3 : data |= (1 << 2); 140 : : writel_relaxed(data, 141 : : intc.local_base + 142 : : ARM_LOCAL_GPU_INT_ROUTING); 143 : : } 144 : : 145 : 3 : writel_relaxed(FIQ_CONTROL_ENABLE | hwirq_to_fiq(d->hwirq), 146 : : intc.base + REG_FIQ_CONTROL); 147 : : } else { 148 : 3 : writel_relaxed(HWIRQ_BIT(d->hwirq), 149 : : intc.enable[HWIRQ_BANK(d->hwirq)]); 150 : : } 151 : : } 152 : : 153 : : #ifdef CONFIG_ARM64 154 : : void bcm2836_arm_irqchip_spin_gpu_irq(void); 155 : : 156 : : static void armctrl_ack_irq(struct irq_data *d) 157 : : { 158 : : bcm2836_arm_irqchip_spin_gpu_irq(); 159 : : } 160 : : 161 : : #endif 162 : : 163 : : static struct irq_chip armctrl_chip = { 164 : : .name = "ARMCTRL-level", 165 : : .irq_mask = armctrl_mask_irq, 166 : : .irq_unmask = armctrl_unmask_irq, 167 : : #ifdef CONFIG_ARM64 168 : : .irq_ack = armctrl_ack_irq 169 : : #endif 170 : : }; 171 : : 172 : 3 : static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, 173 : : const u32 *intspec, unsigned int intsize, 174 : : unsigned long *out_hwirq, unsigned int *out_type) 175 : : { 176 : 3 : if (WARN_ON(intsize != 2)) 177 : : return -EINVAL; 178 : : 179 : 3 : if (WARN_ON(intspec[0] >= NR_BANKS)) 180 : : return -EINVAL; 181 : : 182 : 3 : if (WARN_ON(intspec[1] >= IRQS_PER_BANK)) 183 : : return -EINVAL; 184 : : 185 : 3 : if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0)) 186 : : return -EINVAL; 187 : : 188 : 3 : *out_hwirq = MAKE_HWIRQ(intspec[0], intspec[1]); 189 : 3 : *out_type = IRQ_TYPE_NONE; 190 : 3 : return 0; 191 : : } 192 : : 193 : : static const struct irq_domain_ops armctrl_ops = { 194 : : .xlate = armctrl_xlate 195 : : }; 196 : : 197 : 3 : static int __init armctrl_of_init(struct device_node *node, 198 : : struct device_node *parent, 199 : : bool is_2836) 200 : : { 201 : : void __iomem *base; 202 : : int irq = 0, last_irq, b, i; 203 : : u32 reg; 204 : : 205 : 3 : base = of_iomap(node, 0); 206 : 3 : if (!base) 207 : 0 : panic("%pOF: unable to map IC registers\n", node); 208 : : 209 : 3 : intc.base = base; 210 : 3 : intc.domain = irq_domain_add_linear(node, NUMBER_IRQS * 2, 211 : : &armctrl_ops, NULL); 212 : 3 : if (!intc.domain) 213 : 0 : panic("%pOF: unable to create IRQ domain\n", node); 214 : : 215 : 3 : for (b = 0; b < NR_BANKS; b++) { 216 : 3 : intc.pending[b] = base + reg_pending[b]; 217 : 3 : intc.enable[b] = base + reg_enable[b]; 218 : 3 : intc.disable[b] = base + reg_disable[b]; 219 : : 220 : 3 : for (i = 0; i < bank_irqs[b]; i++) { 221 : 3 : irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i)); 222 : 3 : BUG_ON(irq <= 0); 223 : : irq_set_chip_and_handler(irq, &armctrl_chip, 224 : : handle_level_irq); 225 : : irq_set_probe(irq); 226 : : } 227 : : 228 : 3 : reg = readl_relaxed(intc.enable[b]); 229 : 3 : if (reg) { 230 : 0 : writel_relaxed(reg, intc.disable[b]); 231 : 0 : pr_err(FW_BUG "Bootloader left irq enabled: " 232 : : "bank %d irq %*pbl\n", b, IRQS_PER_BANK, ®); 233 : : } 234 : : } 235 : : 236 : 3 : reg = readl_relaxed(base + REG_FIQ_CONTROL); 237 : 3 : if (reg & FIQ_CONTROL_ENABLE) { 238 : : writel_relaxed(0, base + REG_FIQ_CONTROL); 239 : 0 : pr_err(FW_BUG "Bootloader left fiq enabled\n"); 240 : : } 241 : : 242 : 3 : last_irq = irq; 243 : : 244 : 3 : if (is_2836) { 245 : 3 : int parent_irq = irq_of_parse_and_map(node, 0); 246 : : 247 : 3 : if (!parent_irq) { 248 : 0 : panic("%pOF: unable to get parent interrupt.\n", 249 : : node); 250 : : } 251 : : irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq); 252 : : } else { 253 : 0 : set_handle_irq(bcm2835_handle_irq); 254 : : } 255 : : 256 : 3 : if (is_2836) { 257 : : extern void __iomem * __attribute__((weak)) arm_local_intc; 258 : 3 : intc.local_base = arm_local_intc; 259 : 3 : if (!intc.local_base) 260 : 0 : pr_err("Failed to get local intc base. FIQ is disabled for cpus > 1\n"); 261 : : } 262 : : 263 : : /* Make a duplicate irq range which is used to enable FIQ */ 264 : 3 : for (b = 0; b < NR_BANKS; b++) { 265 : 3 : for (i = 0; i < bank_irqs[b]; i++) { 266 : 3 : irq = irq_create_mapping(intc.domain, 267 : 3 : MAKE_HWIRQ(b, i) + NUMBER_IRQS); 268 : 3 : BUG_ON(irq <= 0); 269 : 3 : irq_set_chip(irq, &armctrl_chip); 270 : : irq_set_probe(irq); 271 : : } 272 : : } 273 : : #ifndef CONFIG_ARM64 274 : 3 : init_FIQ(irq - last_irq); 275 : : #endif 276 : : 277 : 3 : return 0; 278 : : } 279 : : 280 : 0 : static int __init bcm2835_armctrl_of_init(struct device_node *node, 281 : : struct device_node *parent) 282 : : { 283 : 0 : return armctrl_of_init(node, parent, false); 284 : : } 285 : : 286 : 3 : static int __init bcm2836_armctrl_of_init(struct device_node *node, 287 : : struct device_node *parent) 288 : : { 289 : 3 : return armctrl_of_init(node, parent, true); 290 : : } 291 : : 292 : : 293 : : /* 294 : : * Handle each interrupt across the entire interrupt controller. This reads the 295 : : * status register before handling each interrupt, which is necessary given that 296 : : * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. 297 : : */ 298 : : 299 : : static u32 armctrl_translate_bank(int bank) 300 : : { 301 : 3 : u32 stat = readl_relaxed(intc.pending[bank]); 302 : : 303 : 3 : return MAKE_HWIRQ(bank, ffs(stat) - 1); 304 : : } 305 : : 306 : : static u32 armctrl_translate_shortcut(int bank, u32 stat) 307 : : { 308 : 3 : return MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]); 309 : : } 310 : : 311 : 3 : static u32 get_next_armctrl_hwirq(void) 312 : : { 313 : 3 : u32 stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK; 314 : : 315 : 3 : if (stat == 0) 316 : : return ~0; 317 : 3 : else if (stat & BANK0_HWIRQ_MASK) 318 : 3 : return MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1); 319 : 3 : else if (stat & SHORTCUT1_MASK) 320 : 3 : return armctrl_translate_shortcut(1, stat & SHORTCUT1_MASK); 321 : 3 : else if (stat & SHORTCUT2_MASK) 322 : 3 : return armctrl_translate_shortcut(2, stat & SHORTCUT2_MASK); 323 : 3 : else if (stat & BANK1_HWIRQ) 324 : 0 : return armctrl_translate_bank(1); 325 : 3 : else if (stat & BANK2_HWIRQ) 326 : 3 : return armctrl_translate_bank(2); 327 : : else 328 : 0 : BUG(); 329 : : } 330 : : 331 : 0 : static void __exception_irq_entry bcm2835_handle_irq( 332 : : struct pt_regs *regs) 333 : : { 334 : : u32 hwirq; 335 : : 336 : 0 : while ((hwirq = get_next_armctrl_hwirq()) != ~0) 337 : 0 : handle_domain_irq(intc.domain, hwirq, regs); 338 : 0 : } 339 : : 340 : 3 : static void bcm2836_chained_handle_irq(struct irq_desc *desc) 341 : : { 342 : : u32 hwirq; 343 : : 344 : 3 : while ((hwirq = get_next_armctrl_hwirq()) != ~0) 345 : 3 : generic_handle_irq(irq_linear_revmap(intc.domain, hwirq)); 346 : 3 : } 347 : : 348 : : IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", 349 : : bcm2835_armctrl_of_init); 350 : : IRQCHIP_DECLARE(bcm2836_armctrl_ic, "brcm,bcm2836-armctrl-ic", 351 : : bcm2836_armctrl_of_init);