; Copyright 2009 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
        GET     Hdr:ListOpts
        GET     Hdr:Macros
        GET     Hdr:System
        GET     Hdr:Machine.<Machine>
        GET     Hdr:ImageSize.<ImageSize>

        GET     Hdr:MEMM.ARM600

        GET     Hdr:Proc
        GET     Hdr:OSEntries
        GET     Hdr:HALEntries

        GET     hdr.omap3530
        GET     hdr.StaticWS
        GET     hdr.SDRC
        GET     hdr.Interrupts
        GET     hdr.Timers
        GET     hdr.GPIO
        GET     hdr.Copro15ops
        GET     hdr.UART

; This version assumes a RISC OS image starting 64K after us.

; FIQ-based debugger - prints out the PC when the beagleboard USER button is pressed
; Currently the code installs itself on the FIQ interrupt during HAL_InitDevices - but something during bootup appears to overwrite the code, so to get it working you may have to re-call it via OS_Hardware (with r8=0,r9=100)
                GBLL FIQDebug
FIQDebug        SETL {FALSE}

        AREA    |Asm$$Code|, CODE, READONLY, PIC

        EXPORT  rom_checkedout_ok

        IMPORT  HAL_Base
        IMPORT  DebugHALPrint
        IMPORT  DebugHALPrintReg
;        IMPORT  generate_POR_flags
        IMPORT  RTC_Init

; v8 is used as pointer to RISC OS entry table throughout pre-MMU stage.
        MACRO
        CallOSM $entry, $reg
        LDR     ip, [v8, #$entry*4]
        MOV     lr, pc
        ADD     pc, v8, ip
        MEND

        MACRO
        CallOS  $entry, $tailcall
        ASSERT  $entry <= HighestOSEntry
 [ "$tailcall"=""
        MOV     lr, pc
 |
   [ "$tailcall"<>"tailcall"
        ! 0, "Unrecognised parameter to CallOS"
   ]
 ]
        LDR     pc, OSentries + 4*$entry
        MEND

rom_checkedout_ok
        ; Register the attached RAM
        LDR     v1, =SDRC_Regs
        MOV     a1, #0
        MOV     sp, #0
        ; Check CS0
        LDR     a3, [v1, #SDRC_MCFG_0]
        LDR     a2, =&3FF00<<13
        ANDS    a3, a2, a3, LSL #13 ; Get CS0 RAM size
        BEQ     no_cs0
        LDR     a2, =CS0_SDRAM
        ADD     a3, a3, a2
        LDR     a4, =&FFFFFFFF
        ADD     sp, a2, #4096 ; HAL spec says that (for software reset compliance only?) stack should be 4K into first block
        STR     a1, [sp, #-4]!
        MOV     a1, #0
        CallOSM OS_AddRAM
no_cs0
        ; Check CS1
        LDR     a3, [v1, #SDRC_MCFG_1]
        LDR     a2, =&3FF00<<13
        ANDS    a3, a2, a3, LSL #13
        BEQ     no_cs1
        LDR     a2, =CS0_SDRAM
        LDR     a4, [v1, #SDRC_CS_CFG]
        AND     v2, a4, #7 ; Offset in 128MB units
        ADD     a2, a2, v2, LSL #20+7
        AND     v2, a4, #&300 ; Offset in 32MB units
        ADD     a2, a2, v2, LSL #20+5-8
        ADD     a3, a3, a2
        LDR     a4, =&FFFFFFFF
        CMP     sp, #0
        ADDEQ   sp, a2, #4096 ; If no CS0 set up stack in CS1
        STR     a1, [sp, #-4]!
        MOV     a1, #0
        CallOSM OS_AddRAM
no_cs1
        DebugChar v1,v2,71
        MOV     a4, a1
        MOV     a1, #OSStartFlag_RAMCleared
        ADRL    a2, HAL_Base + 64*1024          ; a2 -> RISC OS image
        ADR     a3, HALdescriptor
        CallOSM OS_Start


HALdescriptor   DATA
        DCD     HALFlag_NCNBWorkspace
        DCD     HAL_Base - HALdescriptor
        DCD     64*1024
        DCD     HAL_EntryTable - HALdescriptor
        DCD     HAL_Entries
        DCD     HAL_WsSize


        MACRO
        HALEntry $name
        ASSERT  (. - HAL_EntryTable) / 4 = EntryNo_$name
        DCD     $name - HAL_EntryTable
        MEND

        MACRO
        NullEntry
        DCD     HAL_Null - HAL_EntryTable
        MEND

        IMPORT   Video_init
        IMPORT   Interrupt_Init
        IMPORT   Timer_Init
        IMPORT   PRCM_SetClocks
        IMPORT   USB_Init
        IMPORT   I2C_Init

        IMPORT   HAL_IRQEnable
        IMPORT   HAL_IRQDisable
        IMPORT   HAL_IRQClear
        IMPORT   HAL_IRQSource
        IMPORT   HAL_IRQStatus
        IMPORT   HAL_FIQEnable
        IMPORT   HAL_FIQDisable
        IMPORT   HAL_FIQDisableAll
        IMPORT   HAL_FIQClear
        IMPORT   HAL_FIQSource
        IMPORT   HAL_FIQStatus

        IMPORT   HAL_Timers
        IMPORT   HAL_TimerDevice
        IMPORT   HAL_TimerGranularity
        IMPORT   HAL_TimerMaxPeriod
        IMPORT   HAL_TimerSetPeriod
        IMPORT   HAL_TimerPeriod
        IMPORT   HAL_TimerReadCountdown

        IMPORT   HAL_CounterRate
        IMPORT   HAL_CounterPeriod
        IMPORT   HAL_CounterRead
        IMPORT   HAL_CounterDelay

        IMPORT   HAL_IICBuses
        IMPORT   HAL_IICType
        IMPORT   HAL_IICDevice
        IMPORT   HAL_IICTransfer
        IMPORT   HAL_IICMonitorTransfer

        IMPORT   HAL_NVMemoryType

        IMPORT   HAL_VideoFlybackDevice
        IMPORT   HAL_Video_SetMode
        IMPORT   HAL_Video_WritePaletteEntry
        IMPORT   HAL_Video_WritePaletteEntries
        IMPORT   HAL_Video_ReadPaletteEntry
        IMPORT   HAL_Video_SetInterlace
        IMPORT   HAL_Video_SetBlank
        IMPORT   HAL_Video_SetPowerSave
        IMPORT   HAL_Video_UpdatePointer
        IMPORT   HAL_Video_SetDAG
        IMPORT   HAL_Video_VetMode
        IMPORT   HAL_Video_PixelFormats
        IMPORT   HAL_Video_Features
        IMPORT   HAL_Video_BufferAlignment
        IMPORT   HAL_Video_OutputFormat
        IMPORT   HAL_Video_IICOp ; Implemented in s.I2C

        IMPORT   HAL_UARTPorts
        IMPORT   HAL_UARTStartUp
        IMPORT   HAL_UARTShutdown
        IMPORT   HAL_UARTFeatures
        IMPORT   HAL_UARTReceiveByte
        IMPORT   HAL_UARTTransmitByte
        IMPORT   HAL_UARTLineStatus
        IMPORT   HAL_UARTInterruptEnable
        IMPORT   HAL_UARTRate
        IMPORT   HAL_UARTFormat
        IMPORT   HAL_UARTFIFOSize
        IMPORT   HAL_UARTFIFOClear
        IMPORT   HAL_UARTFIFOEnable
        IMPORT   HAL_UARTFIFOThreshold
        IMPORT   HAL_UARTInterruptID
        IMPORT   HAL_UARTBreak
        IMPORT   HAL_UARTModemControl
        IMPORT   HAL_UARTModemStatus
        IMPORT   HAL_UARTDevice

        IMPORT   HAL_DebugRX
        IMPORT   HAL_DebugTX

        IMPORT   HAL_ATAControllerInfo

        IMPORT   HAL_KbdScanSetup
        IMPORT   HAL_KbdScan
        IMPORT   HAL_KbdScanFinish
        IMPORT   HAL_KbdScanInterrupt

        IMPORT   HAL_Reset

        IMPORT   HAL_USBControllerInfo
        IMPORT   HAL_USBPortPower
        IMPORT   HAL_USBPortStatus
        IMPORT   HAL_USBPortIRQ

HAL_EntryTable  DATA
        HALEntry HAL_Init

        HALEntry HAL_IRQEnable
        HALEntry HAL_IRQDisable
        HALEntry HAL_IRQClear
        HALEntry HAL_IRQSource
        HALEntry HAL_IRQStatus
        HALEntry HAL_FIQEnable
        HALEntry HAL_FIQDisable
        HALEntry HAL_FIQDisableAll
        HALEntry HAL_FIQClear
        HALEntry HAL_FIQSource
        HALEntry HAL_FIQStatus

        HALEntry HAL_Timers
        HALEntry HAL_TimerDevice
        HALEntry HAL_TimerGranularity
        HALEntry HAL_TimerMaxPeriod
        HALEntry HAL_TimerSetPeriod
        HALEntry HAL_TimerPeriod
        HALEntry HAL_TimerReadCountdown

        HALEntry HAL_CounterRate
        HALEntry HAL_CounterPeriod
        HALEntry HAL_CounterRead
        HALEntry HAL_CounterDelay

        HALEntry HAL_NVMemoryType
        NullEntry ; HAL_NVMemorySize
        NullEntry ; HAL_NVMemoryPageSize
        NullEntry ; HAL_NVMemoryProtectedSize
        NullEntry ; HAL_NVMemoryProtection
        NullEntry ; HAL_NVMemoryIICAddress
        NullEntry ; HAL_NVMemoryRead
        NullEntry ; HAL_NVMemoryWrite

        HALEntry HAL_IICBuses
        HALEntry HAL_IICType
        NullEntry ; HAL_IICSetLines
        NullEntry ; HAL_IICReadLines
        HALEntry HAL_IICDevice
        HALEntry HAL_IICTransfer
        HALEntry HAL_IICMonitorTransfer

        HALEntry HAL_VideoFlybackDevice
        HALEntry HAL_Video_SetMode
        HALEntry HAL_Video_WritePaletteEntry
        HALEntry HAL_Video_WritePaletteEntries
        HALEntry HAL_Video_ReadPaletteEntry
        HALEntry HAL_Video_SetInterlace
        HALEntry HAL_Video_SetBlank
        HALEntry HAL_Video_SetPowerSave
        HALEntry HAL_Video_UpdatePointer
        HALEntry HAL_Video_SetDAG
        HALEntry HAL_Video_VetMode
        HALEntry HAL_Video_PixelFormats
        HALEntry HAL_Video_Features
        HALEntry HAL_Video_BufferAlignment
        HALEntry HAL_Video_OutputFormat

        NullEntry ; HALEntry HAL_MatrixColumns
        NullEntry ; HALEntry HAL_MatrixScan

        NullEntry ; HALEntry HAL_TouchscreenType
        NullEntry ; HALEntry HAL_TouchscreenRead
        NullEntry ; HALEntry HAL_TouchscreenMode
        NullEntry ; HALEntry HAL_TouchscreenMeasure

        HALEntry HAL_MachineID

        HALEntry HAL_ControllerAddress
        HALEntry HAL_HardwareInfo
        HALEntry HAL_SuperIOInfo
        HALEntry HAL_PlatformInfo
        NullEntry ; HALEntry HAL_CleanerSpace

        HALEntry HAL_UARTPorts
        HALEntry HAL_UARTStartUp
        HALEntry HAL_UARTShutdown
        HALEntry HAL_UARTFeatures
        HALEntry HAL_UARTReceiveByte
        HALEntry HAL_UARTTransmitByte
        HALEntry HAL_UARTLineStatus
        HALEntry HAL_UARTInterruptEnable
        HALEntry HAL_UARTRate
        HALEntry HAL_UARTFormat
        HALEntry HAL_UARTFIFOSize
        HALEntry HAL_UARTFIFOClear
        HALEntry HAL_UARTFIFOEnable
        HALEntry HAL_UARTFIFOThreshold
        HALEntry HAL_UARTInterruptID
        HALEntry HAL_UARTBreak
        HALEntry HAL_UARTModemControl
        HALEntry HAL_UARTModemStatus
        HALEntry HAL_UARTDevice

        HALEntry HAL_Reset

        HALEntry HAL_DebugRX
        HALEntry HAL_DebugTX

        NullEntry ; HAL_PCIFeatures
        NullEntry ; HAL_PCIReadConfigByte
        NullEntry ; HAL_PCIReadConfigHalfword
        NullEntry ; HAL_PCIReadConfigWord
        NullEntry ; HAL_PCIWriteConfigByte
        NullEntry ; HAL_PCIWriteConfigHalfword
        NullEntry ; HAL_PCIWriteConfigWord
        NullEntry ; HAL_PCISpecialCycle
        NullEntry ; HAL_PCISlotTable
        NullEntry ; HAL_PCIAddresses

        HALEntry HAL_ATAControllerInfo
        NullEntry ; HAL_ATASetModes
        NullEntry ; HAL_ATACableID

        HALEntry HAL_InitDevices

        HALEntry HAL_KbdScanSetup
        HALEntry HAL_KbdScan
        HALEntry HAL_KbdScanFinish
        HALEntry HAL_KbdScanInterrupt

        HALEntry HAL_PhysInfo

        HALEntry HAL_USBControllerInfo

        NullEntry ;HALEntry HAL_MonitorLeadID

        NullEntry ;HALEntry HAL_Video_Render

        HALEntry HAL_USBPortPower
        HALEntry HAL_USBPortStatus
        HALEntry HAL_USBPortIRQ

        HALEntry HAL_Video_IICOp

HAL_Entries     * (.-HAL_EntryTable)/4


;--------------------------------------------------------------------------------------


HAL_Init
        Entry

        STR     a2, NCNBWorkspace
        STR     a2, NCNBAllocNext

        BL      SetUpOSEntries

        ; Map in the main IO ranges (L3, L4) and then store the offsets to the components we're interested in
        MOV     a1, #0
        LDR     a2, =L3_Control
        MOV     a3, #L3_Size
        CallOS  OS_MapInIO
        STR     a1, L3_Log

        MOV     a1, #0
        LDR     a2, =L4_Core
        MOV     a3, #L4_Core_Size
        CallOS  OS_MapInIO
        STR     a1, L4_Core_Log
        ADD     a2, a1, #L4_Wakeup-L4_Core
        STR     a2, L4_Wakeup_Log

        ; L4_PowerMan, L4_32KTIMER, L4_GPIO1
        ADD     a3, a2, #L4_PowerMan-L4_Wakeup
        STR     a3, L4_PowerMan_Log
        ADD     a3, a2, #L4_32KTIMER-L4_Wakeup
        STR     a3, L4_32KTIMER_Log
        ADD     a3, a2, #L4_GPIO1-L4_Wakeup
        STR     a3, L4_GPIO1_Log

        ; Interrupt controller
        ADD     a3, a1, #MPU_INTC-L4_Core
        STR     a3, MPU_INTC_Log

        ; Clockman
        ADD     a3, a1, #L4_ClockMan-L4_Core
        STR     a3, L4_ClockMan_Log

        ; Display
        ADD     a3, a1, #L4_Display-L4_Core
        STR     a3, L4_Display_Log

        ; USB
        ADD     a3, a1, #L4_USBTLL-L4_Core
        STR     a3, L4_USBTLL_Log
        ADD     a3, a1, #L4_USB_Host-L4_Core
        STR     a3, L4_USB_Host_Log
        ADD     a3, a1, #L4_USB_OTG-L4_Core
        STR     a3, L4_USB_OTG_Log

        ; I2C
        ADD     a3, a1, #L4_I2C1-L4_Core
        STR     a3, I2C1Block+I2C_HW
        ADD     a3, a1, #L4_I2C2-L4_Core
        STR     a3, I2C2Block+I2C_HW
        ADD     a3, a1, #L4_I2C3-L4_Core
        STR     a3, I2C3Block+I2C_HW

        MOV     a1, #0
        LDR     a2, =L4_Per
        MOV     a3, #L4_Per_Size
        CallOS  OS_MapInIO
        STR     a1, L4_Per_Log

        ; Timers
        ADD     a2, a1, #TIMER_BASE-L4_Per
        STR     a2, Timers_Log

        ; UART
        ADD     a2, a1, #L4_UART3-L4_Per
        STR     a2, L4_UART3_Log

        ; GPIO2-6
        ADD     a2, a1, #L4_GPIO2-L4_Per
        STR     a2, L4_GPIO2_Log
        ADD     a2, a1, #L4_GPIO3-L4_Per
        STR     a2, L4_GPIO3_Log
        ADD     a2, a1, #L4_GPIO4-L4_Per
        STR     a2, L4_GPIO4_Log
        ADD     a2, a1, #L4_GPIO5-L4_Per
        STR     a2, L4_GPIO5_Log
        ADD     a2, a1, #L4_GPIO6-L4_Per
        STR     a2, L4_GPIO6_Log

;        DebugChar a1,a2, 72

        BL      PRCM_SetClocks ; Calls Timer_init & starts GPTIMER2

;        DebugChar a1,a2, 73

        BL      Video_init ; Uses GPTIMER2

        BL      USB_Init ; Uses GPTIMER2

        BL      I2C_Init ; Uses GPTIMER2

;        DebugChar a1,a2, 74

        BL      Timer_Init ; Re-inits timers

;        DebugChar a1,a2, 75

        BL      Interrupt_Init

;        DebugChar a1,a2, 76

        MOV     a1,#0
        BL      HAL_UARTStartUp

;        DebugChar a1,a2, 77
;        MOV     a1,#1
;        BL      HAL_UARTStartUp
;        MOV     a1,#2
;        BL      HAL_UARTStartUp

        EXIT

; Initialise and relocate the entry table.
SetUpOSEntries  ROUT
        STR     a1, OSheader
        LDR     a2, [a1, #OSHdr_NumEntries]
        CMP     a2, #HighestOSEntry+1
        MOVHI   a2, #HighestOSEntry+1

        ADR     a3, OSentries
        LDR     a4, [a1, #OSHdr_Entries]
        ADD     a4, a4, a1

05      SUBS    a2, a2, #1
        LDR     ip, [a4, a2, LSL #2]
        ADD     ip, ip, a4
        STR     ip, [a3, a2, LSL #2]
        BNE     %BT05
        ; Fall through

HAL_Null
        MOV     pc, lr

HAL_InitDevices
        Entry
        BL      RTC_Init
        ; todo - move the FIQDebug code someplace safer!
 [ FIQDebug
        ; HAL_InitDevices gets called after the processor vectors are set up... so it's the perfect time for us to hijack the FIQ vector!
        ; First we set up the vector
        LDR     a1, =&E51FF004
        ADR     a2, FIQRoutine
        MOV     a4, #&1C
        STMIA   a4,{a1-a2,sb}
        ; Sync cache
        MOV     a1, #0
        MCR     p15, 0, a1, c7, c11, 1 ; Clean DCache by VA to PoU
        MCR     p15, 0, a1, c7, c5, 1 ; invalidate ICache entry (to PoC)
        MCR     p15, 0, a1, c7, c10, 4 ; Drain write buffer
        ; Now reconfigure the USER button (GPIO 7) to fire an FIQ
        LDR     a1, L4_GPIO1_Log
        LDR     a2, [a1, #GPIO_OE]
        ORR     a2, a2, #1:SHL:7 ; Configure as input
        STR     a2, [a1, #GPIO_OE]
        MOV     a2, #0
        STR     a2, [a1, #GPIO_LEVELDETECT0]
        STR     a2, [a1, #GPIO_LEVELDETECT1]
        STR     a2, [a1, #GPIO_FALLINGDETECT]
        MOV     a2, #1:SHL:7
        STR     a2, [a1, #GPIO_RISINGDETECT] ; Enable IRQ on rising edge
        STR     a2, [a1, #GPIO_IRQENABLE1] ; Set MPU as interrupt target
        MOV     a1, #29 ; GPIO1 IRQ
        BL      HAL_FIQEnable
        ; Done!
 ]
        EXIT

HAL_ControllerAddress
        MOV     a1, #0
        MOV     pc, lr

HAL_HardwareInfo
        LDR     ip, =&FFFFFF00
        STR     ip, [a1]
        MOV     ip, #0
        STR     ip, [a2]
        LDR     ip, =&00FFFF00
        STR     ip, [a3]
        MOV     pc, lr

HAL_PlatformInfo
        MOV     ip, #2_10000                    ; no podules,no PCI cards,no multi CPU,no soft off (for now!),and soft ROM
        STR     ip, [a2]
        MOV     ip, #2_11111                    ; mask of valid bits
        STR     ip, [a3]
        MOV     pc, lr

HAL_SuperIOInfo
        MOV     ip, #0
        STR     ip, [a1]
        STR     ip, [a2]
        MOV     pc, lr

HAL_MachineID
        LDR     a3, L4_Wakeup_Log
        ADD     a3, a3, #(L4_DIE_ID-L4_Wakeup) :AND: &FF00
        ADD     a3, a3, #(L4_DIE_ID-L4_Wakeup) :AND: &00FF
        LDMIA   a3, {a1-a2} ; Return the lower 8 bytes of the ID. According to the HAL spec there should also be a CRC, as calculated in kernel.s.PMF.osinit
        MOV     pc, lr

; Shifts to determine number of bytes/words to allocate in table.
NibbleShift     *       PAGE_SIZE_POW2
ByteShift       *       NibbleShift + 1
WordShift       *       ByteShift + 2

; Bit patterns for different types of memory.
NotPresent      *       &00000000
DRAM_Pattern    *       &11111111
VRAM_Pattern    *       &22222222
ROM_Pattern     *       &33333333
IO_Pattern      *       &44444444
NotAvailable    *       &88888888

        IMPORT  memset

HAL_PhysInfo
        TEQ     a1, #0
        MOVEQ   a1, #1:SHL:(32-ByteShift)
        MOVEQ   pc, lr

        Push    "a2,v1,v2,lr"
        MOV     v1, a1
        ADR     v2, HAL_PhysTable
10      LDMIA   v2, {a1, a2, lr}
        SUB     a3, lr, a1
        ADD     a1, v1, a1, LSR #ByteShift
        MOV     a3, a3, LSR #ByteShift
        BL      memset
        LDR     a1, [v2, #8]!
        TEQ     a1, #0
        BNE     %BT10
        MOV     a1, #&70000000 ; Physical RAM from &70000000 and up?
        LDR     lr, =&FFFFE000-1
        Pull    "a2"
        STR     lr, [a2]
        Pull    "v1,v2,pc"

; HAL_PhysInfo uses memset to fill the table, so all regions
; must be byte-aligned (ie double-page-aligned addresses).
HAL_PhysTable
        DCD     &00000000, NotPresent  :OR: NotAvailable ; GPMC
        DCD     &40000000, IO_Pattern  :OR: NotAvailable ; All I/O registers
        DCD     &70000000, NotPresent  :OR: NotAvailable ; SDRC-SMS/SDRAM
        DCD     &FFFFE000, NotPresent  :OR: NotAvailable ; SDRC-SMS/SDRAM
        DCD     0

        LTORG

        EXPORT  vtophys
vtophys
        CallOS  OS_LogToPhys, tailcall

        EXPORT  mapinio
mapinio
        CallOS  OS_MapInIO, tailcall

 [ FIQDebug
FIQRoutine
        ; Dump PC value to the serial port
        MOV     r8, #&24
        LDR     sb, [r8]
        LDR     r8, L4_UART3_Log
        ADR     r9, hextab
        MOV     r10, #8
        MOV     r11, lr ; Preserve return address
10
        LDRB    r12, [r8, #UART_LSR]
        TST     r12, #THRE
        BEQ     %BT10
        LDRB    r12, [r9, r11, LSR #28]
        STRB    r12, [r8, #UART_THR]
        MOV     r11, r11, LSL #4
        SUBS    r10, r10, #1
        BNE     %BT10
10
        LDRB    r12, [r8, #UART_LSR]
        TST     r12, #THRE
        BEQ     %BT10
        MOV     r12, #13
        STRB    r12, [r8, #UART_THR]
10
        LDRB    r12, [r8, #UART_LSR]
        TST     r12, #THRE
        BEQ     %BT10
        MOV     r12, #10
        STRB    r12, [r8, #UART_THR]
        ; Clear interrupt
        MOV     r8, #&24
        LDR     sb, [r8]
        LDR     r8, L4_GPIO1_Log
        LDR     r10, [r8, #GPIO_IRQSTATUS1]
        STR     r10, [r8, #GPIO_IRQSTATUS1]
        LDR     r8, MPU_INTC_Log
        MOV     r10, #2
        STR     r10, [r8, #INTCPS_CONTROL]
        ; Data synchronisation barrier to make sure INTC gets the message
        MOV     r8, #0
        MCR     ARM_config_cp, 0, r8, C7, C10, 4
        ; Now return
        SUBS    pc, lr, #4

hextab  DCB "0123456789abcdef"
 ]
        END