1 /* 2 * This program is free software; you can redistribute it and/or modify it 3 * under the terms of the GNU General Public License version 2 as published 4 * by the Free Software Foundation. 5 * 6 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 7 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 8 */ 9 10 #include <linux/io.h> 11 #include <linux/bitops.h> 12 #include <linux/of_platform.h> 13 #include <linux/of_address.h> 14 #include <linux/of_irq.h> 15 #include <linux/irqdomain.h> 16 #include <linux/interrupt.h> 17 18 #include <asm/irq_cpu.h> 19 #include <asm/mipsregs.h> 20 21 #include "common.h" 22 23 /* INTC register offsets */ 24 #define INTC_REG_STATUS0 0x00 25 #define INTC_REG_STATUS1 0x04 26 #define INTC_REG_TYPE 0x20 27 #define INTC_REG_RAW_STATUS 0x30 28 #define INTC_REG_ENABLE 0x34 29 #define INTC_REG_DISABLE 0x38 30 31 #define INTC_INT_GLOBAL BIT(31) 32 33 #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) 34 #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5) 35 #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6) 36 #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) 37 38 /* we have a cascade of 8 irqs */ 39 #define RALINK_INTC_IRQ_BASE 8 40 41 /* we have 32 SoC irqs */ 42 #define RALINK_INTC_IRQ_COUNT 32 43 44 #define RALINK_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9) 45 46 static void __iomem *rt_intc_membase; 47 48 static inline void rt_intc_w32(u32 val, unsigned reg) 49 { 50 __raw_writel(val, rt_intc_membase + reg); 51 } 52 53 static inline u32 rt_intc_r32(unsigned reg) 54 { 55 return __raw_readl(rt_intc_membase + reg); 56 } 57 58 static void ralink_intc_irq_unmask(struct irq_data *d) 59 { 60 rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE); 61 } 62 63 static void ralink_intc_irq_mask(struct irq_data *d) 64 { 65 rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE); 66 } 67 68 static struct irq_chip ralink_intc_irq_chip = { 69 .name = "INTC", 70 .irq_unmask = ralink_intc_irq_unmask, 71 .irq_mask = ralink_intc_irq_mask, 72 .irq_mask_ack = ralink_intc_irq_mask, 73 }; 74 75 unsigned int __cpuinit get_c0_compare_int(void) 76 { 77 return CP0_LEGACY_COMPARE_IRQ; 78 } 79 80 static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc) 81 { 82 u32 pending = rt_intc_r32(INTC_REG_STATUS0); 83 84 if (pending) { 85 struct irq_domain *domain = irq_get_handler_data(irq); 86 generic_handle_irq(irq_find_mapping(domain, __ffs(pending))); 87 } else { 88 spurious_interrupt(); 89 } 90 } 91 92 asmlinkage void plat_irq_dispatch(void) 93 { 94 unsigned long pending; 95 96 pending = read_c0_status() & read_c0_cause() & ST0_IM; 97 98 if (pending & STATUSF_IP7) 99 do_IRQ(RALINK_CPU_IRQ_COUNTER); 100 101 else if (pending & STATUSF_IP5) 102 do_IRQ(RALINK_CPU_IRQ_FE); 103 104 else if (pending & STATUSF_IP6) 105 do_IRQ(RALINK_CPU_IRQ_WIFI); 106 107 else if (pending & STATUSF_IP2) 108 do_IRQ(RALINK_CPU_IRQ_INTC); 109 110 else 111 spurious_interrupt(); 112 } 113 114 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) 115 { 116 irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq); 117 118 return 0; 119 } 120 121 static const struct irq_domain_ops irq_domain_ops = { 122 .xlate = irq_domain_xlate_onecell, 123 .map = intc_map, 124 }; 125 126 static int __init intc_of_init(struct device_node *node, 127 struct device_node *parent) 128 { 129 struct resource res; 130 struct irq_domain *domain; 131 132 mips_cpu_irq_init(); 133 134 if (of_address_to_resource(node, 0, &res)) 135 panic("Failed to get intc memory range"); 136 137 if (request_mem_region(res.start, resource_size(&res), 138 res.name) < 0) 139 pr_err("Failed to request intc memory"); 140 141 rt_intc_membase = ioremap_nocache(res.start, 142 resource_size(&res)); 143 if (!rt_intc_membase) 144 panic("Failed to remap intc memory"); 145 146 /* disable all interrupts */ 147 rt_intc_w32(~0, INTC_REG_DISABLE); 148 149 /* route all INTC interrupts to MIPS HW0 interrupt */ 150 rt_intc_w32(0, INTC_REG_TYPE); 151 152 domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT, 153 RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL); 154 if (!domain) 155 panic("Failed to add irqdomain"); 156 157 rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE); 158 159 irq_set_chained_handler(RALINK_CPU_IRQ_INTC, ralink_intc_irq_handler); 160 irq_set_handler_data(RALINK_CPU_IRQ_INTC, domain); 161 162 cp0_perfcount_irq = irq_create_mapping(domain, 9); 163 164 return 0; 165 } 166 167 static struct of_device_id __initdata of_irq_ids[] = { 168 { .compatible = "ralink,rt2880-intc", .data = intc_of_init }, 169 {}, 170 }; 171 172 void __init arch_init_irq(void) 173 { 174 of_irq_init(of_irq_ids); 175 } 176 177