1/* 2 * arch/arm/plat-omap/include/mach/entry-macro.S 3 * 4 * Low-level IRQ helper macros for OMAP-based platforms 5 * 6 * Copyright (C) 2009 Texas Instruments 7 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 8 * 9 * This file is licensed under the terms of the GNU General Public 10 * License version 2. This program is licensed "as is" without any 11 * warranty of any kind, whether express or implied. 12 */ 13#include <mach/hardware.h> 14#include <mach/io.h> 15#include <mach/irqs.h> 16#include <asm/hardware/gic.h> 17 18#include <plat/omap24xx.h> 19#include <plat/omap34xx.h> 20#include <plat/omap44xx.h> 21 22#include <plat/multi.h> 23 24#define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) 25#define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) 26#define OMAP4_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE) 27#define INTCPS_SIR_IRQ_OFFSET 0x0040 /* omap2/3 active interrupt offset */ 28#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ 29 30 .macro disable_fiq 31 .endm 32 33 .macro arch_ret_to_user, tmp1, tmp2 34 .endm 35 36/* 37 * Unoptimized irq functions for multi-omap2, 3 and 4 38 */ 39 40#ifdef MULTI_OMAP2 41 .pushsection .data 42omap_irq_base: .word 0 43 .popsection 44 45 /* Configure the interrupt base on the first interrupt */ 46 .macro get_irqnr_preamble, base, tmp 479: 48 ldr \base, =omap_irq_base @ irq base address 49 ldr \base, [\base, #0] @ irq base value 50 cmp \base, #0 @ already configured? 51 bne 9997f @ nothing to do 52 53 mrc p15, 0, \tmp, c0, c0, 0 @ get processor revision 54 and \tmp, \tmp, #0x000f0000 @ only check architecture 55 cmp \tmp, #0x00070000 @ is v6? 56 beq 2400f @ found v6 so it's omap24xx 57 mrc p15, 0, \tmp, c0, c0, 0 @ get processor revision 58 and \tmp, \tmp, #0x000000f0 @ check cortex 8 or 9 59 cmp \tmp, #0x00000080 @ cortex A-8? 60 beq 3400f @ found A-8 so it's omap34xx 61 cmp \tmp, #0x00000090 @ cortex A-9? 62 beq 4400f @ found A-9 so it's omap44xx 632400: ldr \base, =OMAP2_IRQ_BASE 64 ldr \tmp, =omap_irq_base 65 str \base, [\tmp, #0] 66 b 9b 673400: ldr \base, =OMAP3_IRQ_BASE 68 ldr \tmp, =omap_irq_base 69 str \base, [\tmp, #0] 70 b 9b 714400: ldr \base, =OMAP4_IRQ_BASE 72 ldr \tmp, =omap_irq_base 73 str \base, [\tmp, #0] 74 b 9b 759997: 76 .endm 77 78 /* Check the pending interrupts. Note that base already set */ 79 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp 80 tst \base, #0x100 @ gic address? 81 bne 4401f @ found gic 82 83 /* Handle omap2 and omap3 */ 84 ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */ 85 cmp \irqnr, #0x0 86 bne 9998f 87 ldr \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */ 88 cmp \irqnr, #0x0 89 bne 9998f 90 ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ 91 cmp \irqnr, #0x0 929998: 93 ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] 94 and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ 95 b 9999f 96 97 /* Handle omap4 */ 984401: ldr \irqstat, [\base, #GIC_CPU_INTACK] 99 ldr \tmp, =1021 100 bic \irqnr, \irqstat, #0x1c00 101 cmp \irqnr, #29 102 cmpcc \irqnr, \irqnr 103 cmpne \irqnr, \tmp 104 cmpcs \irqnr, \irqnr 1059999: 106 .endm 107 108 109#else /* MULTI_OMAP2 */ 110 111 112/* 113 * Optimized irq functions for omap2, 3 and 4 114 */ 115 116#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 117 .macro get_irqnr_preamble, base, tmp 118#ifdef CONFIG_ARCH_OMAP2 119 ldr \base, =OMAP2_IRQ_BASE 120#else 121 ldr \base, =OMAP3_IRQ_BASE 122#endif 123 .endm 124 125 /* Check the pending interrupts. Note that base already set */ 126 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp 127 ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */ 128 cmp \irqnr, #0x0 129 bne 9999f 130 ldr \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */ 131 cmp \irqnr, #0x0 132 bne 9999f 133 ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ 134 cmp \irqnr, #0x0 1359999: 136 ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] 137 and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ 138 139 .endm 140#endif 141 142 143#ifdef CONFIG_ARCH_OMAP4 144 145 .macro get_irqnr_preamble, base, tmp 146 ldr \base, =OMAP4_IRQ_BASE 147 .endm 148 149 /* 150 * The interrupt numbering scheme is defined in the 151 * interrupt controller spec. To wit: 152 * 153 * Interrupts 0-15 are IPI 154 * 16-28 are reserved 155 * 29-31 are local. We allow 30 to be used for the watchdog. 156 * 32-1020 are global 157 * 1021-1022 are reserved 158 * 1023 is "spurious" (no interrupt) 159 * 160 * For now, we ignore all local interrupts so only return an 161 * interrupt if it's between 30 and 1020. The test_for_ipi 162 * routine below will pick up on IPIs. 163 * A simple read from the controller will tell us the number 164 * of the highest priority enabled interrupt. 165 * We then just need to check whether it is in the 166 * valid range for an IRQ (30-1020 inclusive). 167 */ 168 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp 169 ldr \irqstat, [\base, #GIC_CPU_INTACK] 170 171 ldr \tmp, =1021 172 173 bic \irqnr, \irqstat, #0x1c00 174 175 cmp \irqnr, #29 176 cmpcc \irqnr, \irqnr 177 cmpne \irqnr, \tmp 178 cmpcs \irqnr, \irqnr 179 .endm 180#endif 181#endif /* MULTI_OMAP2 */ 182 183#ifdef CONFIG_SMP 184 /* We assume that irqstat (the raw value of the IRQ acknowledge 185 * register) is preserved from the macro above. 186 * If there is an IPI, we immediately signal end of interrupt 187 * on the controller, since this requires the original irqstat 188 * value which we won't easily be able to recreate later. 189 */ 190 191 .macro test_for_ipi, irqnr, irqstat, base, tmp 192 bic \irqnr, \irqstat, #0x1c00 193 cmp \irqnr, #16 194 it cc 195 strcc \irqstat, [\base, #GIC_CPU_EOI] 196 it cs 197 cmpcs \irqnr, \irqnr 198 .endm 199 200 /* As above, this assumes that irqstat and base are preserved */ 201 202 .macro test_for_ltirq, irqnr, irqstat, base, tmp 203 bic \irqnr, \irqstat, #0x1c00 204 mov \tmp, #0 205 cmp \irqnr, #29 206 itt eq 207 moveq \tmp, #1 208 streq \irqstat, [\base, #GIC_CPU_EOI] 209 cmp \tmp, #0 210 .endm 211#endif /* CONFIG_SMP */ 212 213 .macro irq_prio_table 214 .endm 215