1 /* 2 * Broadcom BCM7120 style Level 2 interrupt controller driver 3 * 4 * Copyright (C) 2014 Broadcom Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/init.h> 14 #include <linux/slab.h> 15 #include <linux/module.h> 16 #include <linux/kconfig.h> 17 #include <linux/platform_device.h> 18 #include <linux/of.h> 19 #include <linux/of_irq.h> 20 #include <linux/of_address.h> 21 #include <linux/of_platform.h> 22 #include <linux/interrupt.h> 23 #include <linux/irq.h> 24 #include <linux/io.h> 25 #include <linux/irqdomain.h> 26 #include <linux/reboot.h> 27 #include <linux/bitops.h> 28 #include <linux/irqchip/chained_irq.h> 29 30 #include "irqchip.h" 31 32 /* Register offset in the L2 interrupt controller */ 33 #define IRQEN 0x00 34 #define IRQSTAT 0x04 35 36 #define MAX_WORDS 4 37 #define IRQS_PER_WORD 32 38 39 struct bcm7120_l2_intc_data { 40 unsigned int n_words; 41 void __iomem *base[MAX_WORDS]; 42 struct irq_domain *domain; 43 bool can_wake; 44 u32 irq_fwd_mask[MAX_WORDS]; 45 u32 irq_map_mask[MAX_WORDS]; 46 }; 47 48 static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) 49 { 50 struct bcm7120_l2_intc_data *b = irq_desc_get_handler_data(desc); 51 struct irq_chip *chip = irq_desc_get_chip(desc); 52 unsigned int idx; 53 54 chained_irq_enter(chip, desc); 55 56 for (idx = 0; idx < b->n_words; idx++) { 57 int base = idx * IRQS_PER_WORD; 58 struct irq_chip_generic *gc = 59 irq_get_domain_generic_chip(b->domain, base); 60 unsigned long pending; 61 int hwirq; 62 63 irq_gc_lock(gc); 64 pending = irq_reg_readl(gc, IRQSTAT) & gc->mask_cache; 65 irq_gc_unlock(gc); 66 67 for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { 68 generic_handle_irq(irq_find_mapping(b->domain, 69 base + hwirq)); 70 } 71 } 72 73 chained_irq_exit(chip, desc); 74 } 75 76 static void bcm7120_l2_intc_suspend(struct irq_data *d) 77 { 78 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 79 struct bcm7120_l2_intc_data *b = gc->private; 80 81 irq_gc_lock(gc); 82 if (b->can_wake) 83 irq_reg_writel(gc, gc->mask_cache | gc->wake_active, IRQEN); 84 irq_gc_unlock(gc); 85 } 86 87 static void bcm7120_l2_intc_resume(struct irq_data *d) 88 { 89 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 90 91 /* Restore the saved mask */ 92 irq_gc_lock(gc); 93 irq_reg_writel(gc, gc->mask_cache, IRQEN); 94 irq_gc_unlock(gc); 95 } 96 97 static int bcm7120_l2_intc_init_one(struct device_node *dn, 98 struct bcm7120_l2_intc_data *data, 99 int irq, const __be32 *map_mask) 100 { 101 int parent_irq; 102 unsigned int idx; 103 104 parent_irq = irq_of_parse_and_map(dn, irq); 105 if (!parent_irq) { 106 pr_err("failed to map interrupt %d\n", irq); 107 return -EINVAL; 108 } 109 110 /* For multiple parent IRQs with multiple words, this looks like: 111 * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...> 112 */ 113 for (idx = 0; idx < data->n_words; idx++) 114 data->irq_map_mask[idx] |= 115 be32_to_cpup(map_mask + irq * data->n_words + idx); 116 117 irq_set_handler_data(parent_irq, data); 118 irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle); 119 120 return 0; 121 } 122 123 int __init bcm7120_l2_intc_of_init(struct device_node *dn, 124 struct device_node *parent) 125 { 126 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 127 struct bcm7120_l2_intc_data *data; 128 struct irq_chip_generic *gc; 129 struct irq_chip_type *ct; 130 const __be32 *map_mask; 131 int num_parent_irqs; 132 int ret = 0, len; 133 unsigned int idx, irq, flags; 134 135 data = kzalloc(sizeof(*data), GFP_KERNEL); 136 if (!data) 137 return -ENOMEM; 138 139 for (idx = 0; idx < MAX_WORDS; idx++) { 140 data->base[idx] = of_iomap(dn, idx); 141 if (!data->base[idx]) 142 break; 143 data->n_words = idx + 1; 144 } 145 if (!data->n_words) { 146 pr_err("failed to remap intc L2 registers\n"); 147 ret = -ENOMEM; 148 goto out_unmap; 149 } 150 151 /* Enable all interrupts specified in the interrupt forward mask; 152 * disable all others. If the property doesn't exist (-EINVAL), 153 * assume all zeroes. 154 */ 155 ret = of_property_read_u32_array(dn, "brcm,int-fwd-mask", 156 data->irq_fwd_mask, data->n_words); 157 if (ret == 0 || ret == -EINVAL) { 158 for (idx = 0; idx < data->n_words; idx++) 159 __raw_writel(data->irq_fwd_mask[idx], 160 data->base[idx] + IRQEN); 161 } else { 162 /* property exists but has the wrong number of words */ 163 pr_err("invalid int-fwd-mask property\n"); 164 ret = -EINVAL; 165 goto out_unmap; 166 } 167 168 num_parent_irqs = of_irq_count(dn); 169 if (num_parent_irqs <= 0) { 170 pr_err("invalid number of parent interrupts\n"); 171 ret = -ENOMEM; 172 goto out_unmap; 173 } 174 175 map_mask = of_get_property(dn, "brcm,int-map-mask", &len); 176 if (!map_mask || 177 (len != (sizeof(*map_mask) * num_parent_irqs * data->n_words))) { 178 pr_err("invalid brcm,int-map-mask property\n"); 179 ret = -EINVAL; 180 goto out_unmap; 181 } 182 183 for (irq = 0; irq < num_parent_irqs; irq++) { 184 ret = bcm7120_l2_intc_init_one(dn, data, irq, map_mask); 185 if (ret) 186 goto out_unmap; 187 } 188 189 data->domain = irq_domain_add_linear(dn, IRQS_PER_WORD * data->n_words, 190 &irq_generic_chip_ops, NULL); 191 if (!data->domain) { 192 ret = -ENOMEM; 193 goto out_unmap; 194 } 195 196 /* MIPS chips strapped for BE will automagically configure the 197 * peripheral registers for CPU-native byte order. 198 */ 199 flags = IRQ_GC_INIT_MASK_CACHE; 200 if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) 201 flags |= IRQ_GC_BE_IO; 202 203 ret = irq_alloc_domain_generic_chips(data->domain, IRQS_PER_WORD, 1, 204 dn->full_name, handle_level_irq, clr, 0, flags); 205 if (ret) { 206 pr_err("failed to allocate generic irq chip\n"); 207 goto out_free_domain; 208 } 209 210 if (of_property_read_bool(dn, "brcm,irq-can-wake")) 211 data->can_wake = true; 212 213 for (idx = 0; idx < data->n_words; idx++) { 214 irq = idx * IRQS_PER_WORD; 215 gc = irq_get_domain_generic_chip(data->domain, irq); 216 217 gc->unused = 0xffffffff & ~data->irq_map_mask[idx]; 218 gc->reg_base = data->base[idx]; 219 gc->private = data; 220 ct = gc->chip_types; 221 222 ct->regs.mask = IRQEN; 223 ct->chip.irq_mask = irq_gc_mask_clr_bit; 224 ct->chip.irq_unmask = irq_gc_mask_set_bit; 225 ct->chip.irq_ack = irq_gc_noop; 226 ct->chip.irq_suspend = bcm7120_l2_intc_suspend; 227 ct->chip.irq_resume = bcm7120_l2_intc_resume; 228 229 if (data->can_wake) { 230 /* This IRQ chip can wake the system, set all 231 * relevant child interupts in wake_enabled mask 232 */ 233 gc->wake_enabled = 0xffffffff; 234 gc->wake_enabled &= ~gc->unused; 235 ct->chip.irq_set_wake = irq_gc_set_wake; 236 } 237 } 238 239 pr_info("registered BCM7120 L2 intc (mem: 0x%p, parent IRQ(s): %d)\n", 240 data->base[0], num_parent_irqs); 241 242 return 0; 243 244 out_free_domain: 245 irq_domain_remove(data->domain); 246 out_unmap: 247 for (idx = 0; idx < MAX_WORDS; idx++) { 248 if (data->base[idx]) 249 iounmap(data->base[idx]); 250 } 251 kfree(data); 252 return ret; 253 } 254 IRQCHIP_DECLARE(bcm7120_l2_intc, "brcm,bcm7120-l2-intc", 255 bcm7120_l2_intc_of_init); 256