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