1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * linux/arch/arm/mach-omap1/ams-delta-fiq-handler.S |
4 | * |
5 | * Based on linux/arch/arm/lib/floppydma.S |
6 | * Renamed and modified to work with 2.6 kernel by Matt Callow |
7 | * Copyright (C) 1995, 1996 Russell King |
8 | * Copyright (C) 2004 Pete Trapps |
9 | * Copyright (C) 2006 Matt Callow |
10 | * Copyright (C) 2010 Janusz Krzysztofik |
11 | */ |
12 | |
13 | #include <linux/linkage.h> |
14 | #include <linux/platform_data/ams-delta-fiq.h> |
15 | #include <linux/platform_data/gpio-omap.h> |
16 | #include <linux/soc/ti/omap1-io.h> |
17 | |
18 | #include <asm/assembler.h> |
19 | #include <asm/irq.h> |
20 | |
21 | #include "hardware.h" |
22 | #include "ams-delta-fiq.h" |
23 | #include "board-ams-delta.h" |
24 | #include "iomap.h" |
25 | |
26 | /* |
27 | * OMAP1510 GPIO related symbol copied from arch/arm/mach-omap1/gpio15xx.c. |
28 | * Unfortunately, it was not placed in a separate header file. |
29 | */ |
30 | #define OMAP1510_GPIO_BASE 0xFFFCE000 |
31 | |
32 | /* GPIO register bitmasks */ |
33 | #define KEYBRD_DATA_MASK (0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_DATA) |
34 | #define KEYBRD_CLK_MASK (0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_CLK) |
35 | #define MODEM_IRQ_MASK (0x1 << AMS_DELTA_GPIO_PIN_MODEM_IRQ) |
36 | #define HOOK_SWITCH_MASK (0x1 << AMS_DELTA_GPIO_PIN_HOOK_SWITCH) |
37 | #define OTHERS_MASK (MODEM_IRQ_MASK | HOOK_SWITCH_MASK) |
38 | |
39 | /* IRQ handler register bitmasks */ |
40 | #define DEFERRED_FIQ_MASK OMAP_IRQ_BIT(INT_DEFERRED_FIQ) |
41 | #define GPIO_BANK1_MASK OMAP_IRQ_BIT(INT_GPIO_BANK1) |
42 | |
43 | /* Driver buffer byte offsets */ |
44 | #define BUF_MASK (FIQ_MASK * 4) |
45 | #define BUF_STATE (FIQ_STATE * 4) |
46 | #define BUF_KEYS_CNT (FIQ_KEYS_CNT * 4) |
47 | #define BUF_TAIL_OFFSET (FIQ_TAIL_OFFSET * 4) |
48 | #define BUF_HEAD_OFFSET (FIQ_HEAD_OFFSET * 4) |
49 | #define BUF_BUF_LEN (FIQ_BUF_LEN * 4) |
50 | #define BUF_KEY (FIQ_KEY * 4) |
51 | #define BUF_MISSED_KEYS (FIQ_MISSED_KEYS * 4) |
52 | #define BUF_BUFFER_START (FIQ_BUFFER_START * 4) |
53 | #define BUF_GPIO_INT_MASK (FIQ_GPIO_INT_MASK * 4) |
54 | #define BUF_KEYS_HICNT (FIQ_KEYS_HICNT * 4) |
55 | #define BUF_IRQ_PEND (FIQ_IRQ_PEND * 4) |
56 | #define BUF_SIR_CODE_L1 (FIQ_SIR_CODE_L1 * 4) |
57 | #define BUF_SIR_CODE_L2 (IRQ_SIR_CODE_L2 * 4) |
58 | #define BUF_CNT_INT_00 (FIQ_CNT_INT_00 * 4) |
59 | #define BUF_CNT_INT_KEY (FIQ_CNT_INT_KEY * 4) |
60 | #define BUF_CNT_INT_MDM (FIQ_CNT_INT_MDM * 4) |
61 | #define BUF_CNT_INT_03 (FIQ_CNT_INT_03 * 4) |
62 | #define BUF_CNT_INT_HSW (FIQ_CNT_INT_HSW * 4) |
63 | #define BUF_CNT_INT_05 (FIQ_CNT_INT_05 * 4) |
64 | #define BUF_CNT_INT_06 (FIQ_CNT_INT_06 * 4) |
65 | #define BUF_CNT_INT_07 (FIQ_CNT_INT_07 * 4) |
66 | #define BUF_CNT_INT_08 (FIQ_CNT_INT_08 * 4) |
67 | #define BUF_CNT_INT_09 (FIQ_CNT_INT_09 * 4) |
68 | #define BUF_CNT_INT_10 (FIQ_CNT_INT_10 * 4) |
69 | #define BUF_CNT_INT_11 (FIQ_CNT_INT_11 * 4) |
70 | #define BUF_CNT_INT_12 (FIQ_CNT_INT_12 * 4) |
71 | #define BUF_CNT_INT_13 (FIQ_CNT_INT_13 * 4) |
72 | #define BUF_CNT_INT_14 (FIQ_CNT_INT_14 * 4) |
73 | #define BUF_CNT_INT_15 (FIQ_CNT_INT_15 * 4) |
74 | #define BUF_CIRC_BUFF (FIQ_CIRC_BUFF * 4) |
75 | |
76 | |
77 | /* |
78 | * Register usage |
79 | * r8 - temporary |
80 | * r9 - the driver buffer |
81 | * r10 - temporary |
82 | * r11 - interrupts mask |
83 | * r12 - base pointers |
84 | * r13 - interrupts status |
85 | */ |
86 | |
87 | .text |
88 | |
89 | .global qwerty_fiqin_end |
90 | |
91 | ENTRY(qwerty_fiqin_start) |
92 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
93 | @ FIQ intrrupt handler |
94 | ldr r12, omap_ih1_base @ set pointer to level1 handler |
95 | |
96 | ldr r11, [r12, #IRQ_MIR_REG_OFFSET] @ fetch interrupts mask |
97 | |
98 | ldr r13, [r12, #IRQ_ITR_REG_OFFSET] @ fetch interrupts status |
99 | bics r13, r13, r11 @ clear masked - any left? |
100 | beq exit @ none - spurious FIQ? exit |
101 | |
102 | ldr r10, [r12, #IRQ_SIR_FIQ_REG_OFFSET] @ get requested interrupt number |
103 | |
104 | mov r8, #2 @ reset FIQ agreement |
105 | str r8, [r12, #IRQ_CONTROL_REG_OFFSET] |
106 | |
107 | cmp r10, #(INT_GPIO_BANK1 - NR_IRQS_LEGACY) @ is it GPIO interrupt? |
108 | beq gpio @ yes - process it |
109 | |
110 | mov r8, #1 |
111 | orr r8, r11, r8, lsl r10 @ mask spurious interrupt |
112 | str r8, [r12, #IRQ_MIR_REG_OFFSET] |
113 | exit: |
114 | subs pc, lr, #4 @ return from FIQ |
115 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
116 | |
117 | |
118 | @@@@@@@@@@@@@@@@@@@@@@@@@@@ |
119 | gpio: @ GPIO bank interrupt handler |
120 | ldr r12, omap1510_gpio_base @ set base pointer to GPIO bank |
121 | |
122 | ldr r11, [r12, #OMAP1510_GPIO_INT_MASK] @ fetch GPIO interrupts mask |
123 | restart: |
124 | ldr r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ fetch status bits |
125 | bics r13, r13, r11 @ clear masked - any left? |
126 | beq exit @ no - spurious interrupt? exit |
127 | |
128 | orr r11, r11, r13 @ mask all requested interrupts |
129 | str r11, [r12, #OMAP1510_GPIO_INT_MASK] |
130 | |
131 | str r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack all requested interrupts |
132 | |
133 | ands r10, r13, #KEYBRD_CLK_MASK @ extract keyboard status - set? |
134 | beq hksw @ no - try next source |
135 | |
136 | |
137 | @@@@@@@@@@@@@@@@@@@@@@ |
138 | @ Keyboard clock FIQ mode interrupt handler |
139 | @ r10 now contains KEYBRD_CLK_MASK, use it |
140 | bic r11, r11, r10 @ unmask it |
141 | str r11, [r12, #OMAP1510_GPIO_INT_MASK] |
142 | |
143 | @ Process keyboard data |
144 | ldr r8, [r12, #OMAP1510_GPIO_DATA_INPUT] @ fetch GPIO input |
145 | |
146 | ldr r10, [r9, #BUF_STATE] @ fetch kbd interface state |
147 | cmp r10, #0 @ are we expecting start bit? |
148 | bne data @ no - go to data processing |
149 | |
150 | ands r8, r8, #KEYBRD_DATA_MASK @ check start bit - detected? |
151 | beq hksw @ no - try next source |
152 | |
153 | @ r8 contains KEYBRD_DATA_MASK, use it |
154 | str r8, [r9, #BUF_STATE] @ enter data processing state |
155 | @ r10 already contains 0, reuse it |
156 | str r10, [r9, #BUF_KEY] @ clear keycode |
157 | mov r10, #2 @ reset input bit mask |
158 | str r10, [r9, #BUF_MASK] |
159 | |
160 | @ Mask other GPIO line interrupts till key done |
161 | str r11, [r9, #BUF_GPIO_INT_MASK] @ save mask for later restore |
162 | mvn r11, #KEYBRD_CLK_MASK @ prepare all except kbd mask |
163 | str r11, [r12, #OMAP1510_GPIO_INT_MASK] @ store into the mask register |
164 | |
165 | b restart @ restart |
166 | |
167 | data: ldr r10, [r9, #BUF_MASK] @ fetch current input bit mask |
168 | |
169 | @ r8 still contains GPIO input bits |
170 | ands r8, r8, #KEYBRD_DATA_MASK @ is keyboard data line low? |
171 | ldreq r8, [r9, #BUF_KEY] @ yes - fetch collected so far, |
172 | orreq r8, r8, r10 @ set 1 at current mask position |
173 | streq r8, [r9, #BUF_KEY] @ and save back |
174 | |
175 | mov r10, r10, lsl #1 @ shift mask left |
176 | bics r10, r10, #0x800 @ have we got all the bits? |
177 | strne r10, [r9, #BUF_MASK] @ not yet - store the mask |
178 | bne restart @ and restart |
179 | |
180 | @ r10 already contains 0, reuse it |
181 | str r10, [r9, #BUF_STATE] @ reset state to start |
182 | |
183 | @ Key done - restore interrupt mask |
184 | ldr r10, [r9, #BUF_GPIO_INT_MASK] @ fetch saved mask |
185 | and r11, r11, r10 @ unmask all saved as unmasked |
186 | str r11, [r12, #OMAP1510_GPIO_INT_MASK] @ restore into the mask register |
187 | |
188 | @ Try appending the keycode to the circular buffer |
189 | ldr r10, [r9, #BUF_KEYS_CNT] @ get saved keystrokes count |
190 | ldr r8, [r9, #BUF_BUF_LEN] @ get buffer size |
191 | cmp r10, r8 @ is buffer full? |
192 | beq hksw @ yes - key lost, next source |
193 | |
194 | add r10, r10, #1 @ incremet keystrokes counter |
195 | str r10, [r9, #BUF_KEYS_CNT] |
196 | |
197 | ldr r10, [r9, #BUF_TAIL_OFFSET] @ get buffer tail offset |
198 | @ r8 already contains buffer size |
199 | cmp r10, r8 @ end of buffer? |
200 | moveq r10, #0 @ yes - rewind to buffer start |
201 | |
202 | ldr r12, [r9, #BUF_BUFFER_START] @ get buffer start address |
203 | add r12, r12, r10, LSL #2 @ calculate buffer tail address |
204 | ldr r8, [r9, #BUF_KEY] @ get last keycode |
205 | str r8, [r12] @ append it to the buffer tail |
206 | |
207 | add r10, r10, #1 @ increment buffer tail offset |
208 | str r10, [r9, #BUF_TAIL_OFFSET] |
209 | |
210 | ldr r10, [r9, #BUF_CNT_INT_KEY] @ increment interrupts counter |
211 | add r10, r10, #1 |
212 | str r10, [r9, #BUF_CNT_INT_KEY] |
213 | @@@@@@@@@@@@@@@@@@@@@@@@ |
214 | |
215 | |
216 | hksw: @Is hook switch interrupt requested? |
217 | tst r13, #HOOK_SWITCH_MASK @ is hook switch status bit set? |
218 | beq mdm @ no - try next source |
219 | |
220 | |
221 | @@@@@@@@@@@@@@@@@@@@@@@@ |
222 | @ Hook switch interrupt FIQ mode simple handler |
223 | |
224 | @ Don't toggle active edge, the switch always bounces |
225 | |
226 | @ Increment hook switch interrupt counter |
227 | ldr r10, [r9, #BUF_CNT_INT_HSW] |
228 | add r10, r10, #1 |
229 | str r10, [r9, #BUF_CNT_INT_HSW] |
230 | @@@@@@@@@@@@@@@@@@@@@@@@ |
231 | |
232 | |
233 | mdm: @Is it a modem interrupt? |
234 | tst r13, #MODEM_IRQ_MASK @ is modem status bit set? |
235 | beq irq @ no - check for next interrupt |
236 | |
237 | |
238 | @@@@@@@@@@@@@@@@@@@@@@@@ |
239 | @ Modem FIQ mode interrupt handler stub |
240 | |
241 | @ Increment modem interrupt counter |
242 | ldr r10, [r9, #BUF_CNT_INT_MDM] |
243 | add r10, r10, #1 |
244 | str r10, [r9, #BUF_CNT_INT_MDM] |
245 | @@@@@@@@@@@@@@@@@@@@@@@@ |
246 | |
247 | |
248 | irq: @ Place deferred_fiq interrupt request |
249 | ldr r12, deferred_fiq_ih_base @ set pointer to IRQ handler |
250 | mov r10, #DEFERRED_FIQ_MASK @ set deferred_fiq bit |
251 | str r10, [r12, #IRQ_ISR_REG_OFFSET] @ place it in the ISR register |
252 | |
253 | ldr r12, omap1510_gpio_base @ set pointer back to GPIO bank |
254 | b restart @ check for next GPIO interrupt |
255 | @@@@@@@@@@@@@@@@@@@@@@@@@@@ |
256 | |
257 | |
258 | /* |
259 | * Virtual addresses for IO |
260 | */ |
261 | omap_ih1_base: |
262 | .word OMAP1_IO_ADDRESS(OMAP_IH1_BASE) |
263 | deferred_fiq_ih_base: |
264 | .word OMAP1_IO_ADDRESS(DEFERRED_FIQ_IH_BASE) |
265 | omap1510_gpio_base: |
266 | .word OMAP1_IO_ADDRESS(OMAP1510_GPIO_BASE) |
267 | qwerty_fiqin_end: |
268 | |
269 | /* |
270 | * Check the size of the FIQ, |
271 | * it cannot go beyond 0xffff0200, and is copied to 0xffff001c |
272 | */ |
273 | .if (qwerty_fiqin_end - qwerty_fiqin_start) > (0x200 - 0x1c) |
274 | .err |
275 | .endif |
276 | |