1 /* 2 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB 3 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/module.h> 8 #include <linux/errno.h> 9 #include <linux/mutex.h> 10 #include <linux/slab.h> 11 #include <linux/of.h> 12 #include <linux/of_platform.h> 13 #include <linux/interrupt.h> 14 #include <linux/of_device.h> 15 #include <asm/oplib.h> 16 #include <asm/timer.h> 17 #include <asm/prom.h> 18 #include <asm/leon.h> 19 #include <asm/leon_amba.h> 20 21 #include "prom.h" 22 #include "irq.h" 23 24 struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ 25 struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ 26 struct amba_apb_device leon_percpu_timer_dev[16]; 27 28 int leondebug_irq_disable; 29 int leon_debug_irqout; 30 static int dummy_master_l10_counter; 31 32 unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ 33 unsigned int sparc_leon_eirq; 34 #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) 35 36 /* Return the IRQ of the pending IRQ on the extended IRQ controller */ 37 int sparc_leon_eirq_get(int eirq, int cpu) 38 { 39 return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f; 40 } 41 42 irqreturn_t sparc_leon_eirq_isr(int dummy, void *dev_id) 43 { 44 printk(KERN_ERR "sparc_leon_eirq_isr: ERROR EXTENDED IRQ\n"); 45 return IRQ_HANDLED; 46 } 47 48 /* The extended IRQ controller has been found, this function registers it */ 49 void sparc_leon_eirq_register(int eirq) 50 { 51 int irq; 52 53 /* Register a "BAD" handler for this interrupt, it should never happen */ 54 irq = request_irq(eirq, sparc_leon_eirq_isr, 55 (IRQF_DISABLED | SA_STATIC_ALLOC), "extirq", NULL); 56 57 if (irq) { 58 printk(KERN_ERR 59 "sparc_leon_eirq_register: unable to attach IRQ%d\n", 60 eirq); 61 } else { 62 sparc_leon_eirq = eirq; 63 } 64 65 } 66 67 static inline unsigned long get_irqmask(unsigned int irq) 68 { 69 unsigned long mask; 70 71 if (!irq || ((irq > 0xf) && !sparc_leon_eirq) 72 || ((irq > 0x1f) && sparc_leon_eirq)) { 73 printk(KERN_ERR 74 "leon_get_irqmask: false irq number: %d\n", irq); 75 mask = 0; 76 } else { 77 mask = LEON_HARD_INT(irq); 78 } 79 return mask; 80 } 81 82 static void leon_enable_irq(unsigned int irq_nr) 83 { 84 unsigned long mask, flags; 85 mask = get_irqmask(irq_nr); 86 local_irq_save(flags); 87 LEON3_BYPASS_STORE_PA(LEON_IMASK, 88 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); 89 local_irq_restore(flags); 90 } 91 92 static void leon_disable_irq(unsigned int irq_nr) 93 { 94 unsigned long mask, flags; 95 mask = get_irqmask(irq_nr); 96 local_irq_save(flags); 97 LEON3_BYPASS_STORE_PA(LEON_IMASK, 98 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); 99 local_irq_restore(flags); 100 101 } 102 103 void __init leon_init_timers(irq_handler_t counter_fn) 104 { 105 int irq; 106 107 leondebug_irq_disable = 0; 108 leon_debug_irqout = 0; 109 master_l10_counter = (unsigned int *)&dummy_master_l10_counter; 110 dummy_master_l10_counter = 0; 111 112 if (leon3_gptimer_regs && leon3_irqctrl_regs) { 113 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); 114 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, 115 (((1000000 / 100) - 1))); 116 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); 117 118 } else { 119 printk(KERN_ERR "No Timer/irqctrl found\n"); 120 BUG(); 121 } 122 123 irq = request_irq(leon3_gptimer_irq, 124 counter_fn, 125 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 126 127 if (irq) { 128 printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", 129 LEON_INTERRUPT_TIMER1); 130 prom_halt(); 131 } 132 133 if (leon3_gptimer_regs) { 134 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 135 LEON3_GPTIMER_EN | 136 LEON3_GPTIMER_RL | 137 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); 138 } 139 } 140 141 void leon_clear_clock_irq(void) 142 { 143 } 144 145 void leon_load_profile_irq(int cpu, unsigned int limit) 146 { 147 BUG(); 148 } 149 150 151 152 153 void __init leon_trans_init(struct device_node *dp) 154 { 155 if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) { 156 struct property *p; 157 p = of_find_property(dp, "mid", (void *)0); 158 if (p) { 159 int mid; 160 dp->name = prom_early_alloc(5 + 1); 161 memcpy(&mid, p->value, p->length); 162 sprintf((char *)dp->name, "cpu%.2d", mid); 163 } 164 } 165 } 166 167 void __initdata (*prom_amba_init)(struct device_node *dp, struct device_node ***nextp) = 0; 168 169 void __init leon_node_init(struct device_node *dp, struct device_node ***nextp) 170 { 171 if (prom_amba_init && 172 strcmp(dp->type, "ambapp") == 0 && 173 strcmp(dp->name, "ambapp0") == 0) { 174 prom_amba_init(dp, nextp); 175 } 176 } 177 178 void __init leon_init_IRQ(void) 179 { 180 sparc_init_timers = leon_init_timers; 181 182 BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM); 183 BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM); 184 BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM); 185 BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM); 186 187 BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, 188 BTFIXUPCALL_NORM); 189 BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq, 190 BTFIXUPCALL_NOP); 191 192 #ifdef CONFIG_SMP 193 BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM); 194 BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM); 195 BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM); 196 #endif 197 198 } 199 200 void __init leon_init(void) 201 { 202 prom_build_more = &leon_node_init; 203 } 204