1 /* 2 * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> 3 * Copyright (C) 2012-2013 Xilinx, Inc. 4 * Copyright (C) 2007-2009 PetaLogix 5 * Copyright (C) 2006 Atmark Techno, Inc. 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file "COPYING" in the main directory of this archive 9 * for more details. 10 */ 11 12 #include <linux/irqdomain.h> 13 #include <linux/irq.h> 14 #include <linux/irqchip.h> 15 #include <linux/irqchip/chained_irq.h> 16 #include <linux/of_address.h> 17 #include <linux/io.h> 18 #include <linux/jump_label.h> 19 #include <linux/bug.h> 20 #include <linux/of_irq.h> 21 22 /* No one else should require these constants, so define them locally here. */ 23 #define ISR 0x00 /* Interrupt Status Register */ 24 #define IPR 0x04 /* Interrupt Pending Register */ 25 #define IER 0x08 /* Interrupt Enable Register */ 26 #define IAR 0x0c /* Interrupt Acknowledge Register */ 27 #define SIE 0x10 /* Set Interrupt Enable bits */ 28 #define CIE 0x14 /* Clear Interrupt Enable bits */ 29 #define IVR 0x18 /* Interrupt Vector Register */ 30 #define MER 0x1c /* Master Enable Register */ 31 32 #define MER_ME (1<<0) 33 #define MER_HIE (1<<1) 34 35 static DEFINE_STATIC_KEY_FALSE(xintc_is_be); 36 37 struct xintc_irq_chip { 38 void __iomem *base; 39 struct irq_domain *root_domain; 40 u32 intr_mask; 41 }; 42 43 static struct xintc_irq_chip *xintc_irqc; 44 45 static void xintc_write(int reg, u32 data) 46 { 47 if (static_branch_unlikely(&xintc_is_be)) 48 iowrite32be(data, xintc_irqc->base + reg); 49 else 50 iowrite32(data, xintc_irqc->base + reg); 51 } 52 53 static unsigned int xintc_read(int reg) 54 { 55 if (static_branch_unlikely(&xintc_is_be)) 56 return ioread32be(xintc_irqc->base + reg); 57 else 58 return ioread32(xintc_irqc->base + reg); 59 } 60 61 static void intc_enable_or_unmask(struct irq_data *d) 62 { 63 unsigned long mask = 1 << d->hwirq; 64 65 pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq); 66 67 /* ack level irqs because they can't be acked during 68 * ack function since the handle_level_irq function 69 * acks the irq before calling the interrupt handler 70 */ 71 if (irqd_is_level_type(d)) 72 xintc_write(IAR, mask); 73 74 xintc_write(SIE, mask); 75 } 76 77 static void intc_disable_or_mask(struct irq_data *d) 78 { 79 pr_debug("irq-xilinx: disable: %ld\n", d->hwirq); 80 xintc_write(CIE, 1 << d->hwirq); 81 } 82 83 static void intc_ack(struct irq_data *d) 84 { 85 pr_debug("irq-xilinx: ack: %ld\n", d->hwirq); 86 xintc_write(IAR, 1 << d->hwirq); 87 } 88 89 static void intc_mask_ack(struct irq_data *d) 90 { 91 unsigned long mask = 1 << d->hwirq; 92 93 pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq); 94 xintc_write(CIE, mask); 95 xintc_write(IAR, mask); 96 } 97 98 static struct irq_chip intc_dev = { 99 .name = "Xilinx INTC", 100 .irq_unmask = intc_enable_or_unmask, 101 .irq_mask = intc_disable_or_mask, 102 .irq_ack = intc_ack, 103 .irq_mask_ack = intc_mask_ack, 104 }; 105 106 unsigned int xintc_get_irq(void) 107 { 108 unsigned int hwirq, irq = -1; 109 110 hwirq = xintc_read(IVR); 111 if (hwirq != -1U) 112 irq = irq_find_mapping(xintc_irqc->root_domain, hwirq); 113 114 pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq); 115 116 return irq; 117 } 118 119 static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) 120 { 121 if (xintc_irqc->intr_mask & (1 << hw)) { 122 irq_set_chip_and_handler_name(irq, &intc_dev, 123 handle_edge_irq, "edge"); 124 irq_clear_status_flags(irq, IRQ_LEVEL); 125 } else { 126 irq_set_chip_and_handler_name(irq, &intc_dev, 127 handle_level_irq, "level"); 128 irq_set_status_flags(irq, IRQ_LEVEL); 129 } 130 return 0; 131 } 132 133 static const struct irq_domain_ops xintc_irq_domain_ops = { 134 .xlate = irq_domain_xlate_onetwocell, 135 .map = xintc_map, 136 }; 137 138 static void xil_intc_irq_handler(struct irq_desc *desc) 139 { 140 struct irq_chip *chip = irq_desc_get_chip(desc); 141 u32 pending; 142 143 chained_irq_enter(chip, desc); 144 do { 145 pending = xintc_get_irq(); 146 if (pending == -1U) 147 break; 148 generic_handle_irq(pending); 149 } while (true); 150 chained_irq_exit(chip, desc); 151 } 152 153 static int __init xilinx_intc_of_init(struct device_node *intc, 154 struct device_node *parent) 155 { 156 u32 nr_irq; 157 int ret, irq; 158 struct xintc_irq_chip *irqc; 159 160 if (xintc_irqc) { 161 pr_err("irq-xilinx: Multiple instances aren't supported\n"); 162 return -EINVAL; 163 } 164 165 irqc = kzalloc(sizeof(*irqc), GFP_KERNEL); 166 if (!irqc) 167 return -ENOMEM; 168 169 xintc_irqc = irqc; 170 171 irqc->base = of_iomap(intc, 0); 172 BUG_ON(!irqc->base); 173 174 ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); 175 if (ret < 0) { 176 pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n"); 177 goto err_alloc; 178 } 179 180 ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask); 181 if (ret < 0) { 182 pr_warn("irq-xilinx: unable to read xlnx,kind-of-intr\n"); 183 irqc->intr_mask = 0; 184 } 185 186 if (irqc->intr_mask >> nr_irq) 187 pr_warn("irq-xilinx: mismatch in kind-of-intr param\n"); 188 189 pr_info("irq-xilinx: %s: num_irq=%d, edge=0x%x\n", 190 intc->full_name, nr_irq, irqc->intr_mask); 191 192 193 /* 194 * Disable all external interrupts until they are 195 * explicity requested. 196 */ 197 xintc_write(IER, 0); 198 199 /* Acknowledge any pending interrupts just in case. */ 200 xintc_write(IAR, 0xffffffff); 201 202 /* Turn on the Master Enable. */ 203 xintc_write(MER, MER_HIE | MER_ME); 204 if (!(xintc_read(MER) & (MER_HIE | MER_ME))) { 205 static_branch_enable(&xintc_is_be); 206 xintc_write(MER, MER_HIE | MER_ME); 207 } 208 209 irqc->root_domain = irq_domain_add_linear(intc, nr_irq, 210 &xintc_irq_domain_ops, irqc); 211 if (!irqc->root_domain) { 212 pr_err("irq-xilinx: Unable to create IRQ domain\n"); 213 goto err_alloc; 214 } 215 216 if (parent) { 217 irq = irq_of_parse_and_map(intc, 0); 218 if (irq) { 219 irq_set_chained_handler_and_data(irq, 220 xil_intc_irq_handler, 221 irqc); 222 } else { 223 pr_err("irq-xilinx: interrupts property not in DT\n"); 224 ret = -EINVAL; 225 goto err_alloc; 226 } 227 } else { 228 irq_set_default_host(irqc->root_domain); 229 } 230 231 return 0; 232 233 err_alloc: 234 xintc_irqc = NULL; 235 kfree(irqc); 236 return ret; 237 238 } 239 240 IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); 241 IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init); 242