omap2+: Initialize omap_irq_base for entry-macro.S from platform code
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-omap2 / include / mach / entry-macro.S
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
42 /*
43  * We use __glue to avoid errors with multiple definitions of
44  * .globl omap_irq_base as it's included from entry-armv.S but not
45  * from entry-common.S.
46  */
47 #ifdef __glue
48                 .pushsection .data
49                 .globl  omap_irq_base
50 omap_irq_base:
51                 .word   0
52                 .popsection
53 #endif
54
55                 /*
56                  * Configure the interrupt base on the first interrupt.
57                  * See also omap_irq_base_init for setting omap_irq_base.
58                  */
59                 .macro  get_irqnr_preamble, base, tmp
60                 ldr     \base, =omap_irq_base   @ irq base address
61                 ldr     \base, [\base, #0]      @ irq base value
62                 .endm
63
64                 /* Check the pending interrupts. Note that base already set */
65                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
66                 tst     \base, #0x100           @ gic address?
67                 bne     4401f                   @ found gic
68
69                 /* Handle omap2 and omap3 */
70                 ldr     \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
71                 cmp     \irqnr, #0x0
72                 bne     9998f
73                 ldr     \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */
74                 cmp     \irqnr, #0x0
75                 bne     9998f
76                 ldr     \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
77                 cmp     \irqnr, #0x0
78 9998:
79                 ldrne   \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
80                 and     \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
81                 b       9999f
82
83                 /* Handle omap4 */
84 4401:           ldr     \irqstat, [\base, #GIC_CPU_INTACK]
85                 ldr     \tmp, =1021
86                 bic     \irqnr, \irqstat, #0x1c00
87                 cmp     \irqnr, #29
88                 cmpcc   \irqnr, \irqnr
89                 cmpne   \irqnr, \tmp
90                 cmpcs   \irqnr, \irqnr
91 9999:
92                 .endm
93
94
95 #else   /* MULTI_OMAP2 */
96
97
98 /*
99  * Optimized irq functions for omap2, 3 and 4
100  */
101
102 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
103                 .macro  get_irqnr_preamble, base, tmp
104 #ifdef CONFIG_ARCH_OMAP2
105                 ldr     \base, =OMAP2_IRQ_BASE
106 #else
107                 ldr     \base, =OMAP3_IRQ_BASE
108 #endif
109                 .endm
110
111                 /* Check the pending interrupts. Note that base already set */
112                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
113                 ldr     \irqnr, [\base, #0x98] /* IRQ pending reg 1 */
114                 cmp     \irqnr, #0x0
115                 bne     9999f
116                 ldr     \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */
117                 cmp     \irqnr, #0x0
118                 bne     9999f
119                 ldr     \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
120                 cmp     \irqnr, #0x0
121 9999:
122                 ldrne   \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
123                 and     \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
124
125                 .endm
126 #endif
127
128
129 #ifdef CONFIG_ARCH_OMAP4
130
131                 .macro  get_irqnr_preamble, base, tmp
132                 ldr     \base, =OMAP4_IRQ_BASE
133                 .endm
134
135                 /*
136                  * The interrupt numbering scheme is defined in the
137                  * interrupt controller spec.  To wit:
138                  *
139                  * Interrupts 0-15 are IPI
140                  * 16-28 are reserved
141                  * 29-31 are local.  We allow 30 to be used for the watchdog.
142                  * 32-1020 are global
143                  * 1021-1022 are reserved
144                  * 1023 is "spurious" (no interrupt)
145                  *
146                  * For now, we ignore all local interrupts so only return an
147                  * interrupt if it's between 30 and 1020.  The test_for_ipi
148                  * routine below will pick up on IPIs.
149                  * A simple read from the controller will tell us the number
150                  * of the highest priority enabled interrupt.
151                  * We then just need to check whether it is in the
152                  * valid range for an IRQ (30-1020 inclusive).
153                  */
154                 .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
155                 ldr     \irqstat, [\base, #GIC_CPU_INTACK]
156
157                 ldr     \tmp, =1021
158
159                 bic     \irqnr, \irqstat, #0x1c00
160
161                 cmp     \irqnr, #29
162                 cmpcc   \irqnr, \irqnr
163                 cmpne   \irqnr, \tmp
164                 cmpcs   \irqnr, \irqnr
165                 .endm
166 #endif
167 #endif  /* MULTI_OMAP2 */
168
169 #ifdef CONFIG_SMP
170                 /* We assume that irqstat (the raw value of the IRQ acknowledge
171                  * register) is preserved from the macro above.
172                  * If there is an IPI, we immediately signal end of interrupt
173                  * on the controller, since this requires the original irqstat
174                  * value which we won't easily be able to recreate later.
175                  */
176
177                 .macro test_for_ipi, irqnr, irqstat, base, tmp
178                 bic     \irqnr, \irqstat, #0x1c00
179                 cmp     \irqnr, #16
180                 it      cc
181                 strcc   \irqstat, [\base, #GIC_CPU_EOI]
182                 it      cs
183                 cmpcs   \irqnr, \irqnr
184                 .endm
185
186                 /* As above, this assumes that irqstat and base are preserved */
187
188                 .macro test_for_ltirq, irqnr, irqstat, base, tmp
189                 bic     \irqnr, \irqstat, #0x1c00
190                 mov     \tmp, #0
191                 cmp     \irqnr, #29
192                 itt     eq
193                 moveq   \tmp, #1
194                 streq   \irqstat, [\base, #GIC_CPU_EOI]
195                 cmp     \tmp, #0
196                 .endm
197 #endif  /* CONFIG_SMP */
198
199                 .macro  irq_prio_table
200                 .endm