Commit 06491820 authored by Jeffrey Lee's avatar Jeffrey Lee

Merge SMP branch to trunk

Detail:
  hdr/StaticWS - Reserve workspace for QA7 peripheral address, HAL-wide spinlock, and doorbell device
  Makefile, s/DBell - Add doorbell device implementation
  hdr/BCM2835 - Clean up dead macros, add new macros for spinlock claim/release and basic CPU detection. Define new IRQ numbers for the "QA7" peripheral.
  hdr/CastleMacros, s/Top - Generate two HAL descriptors and entry point tables: One for single-core machines and one for multi-core machines. This avoids some MP-related overheads on ARM11 models of Pi. Implement SMP HAL entry points.
  s/Interrupts - Add support for the QA7 interrupts. Although some interrupts can be flexibly routed to different cores, we currently stick with a static scheme.
  s/Messaging - Use CPUDetect macro
Admin:
  Untested
  Requires Kernel-6_09


Version 0.76. Tagged as 'BCM2835-0_76'
parent 8c7c60d9
......@@ -17,7 +17,7 @@
COMPONENT = BCM2835 HAL
TARGET = BCM2835
OBJS = Top CLib CMOS Debug Interrupts SDIO Timers UART USB Video DMA Messaging GPIO VCHIQ IIC RTC SPI Touch KbdScan
OBJS = Top CLib CMOS Debug Interrupts SDIO Timers UART USB Video DMA Messaging GPIO VCHIQ IIC RTC SPI Touch KbdScan DBell
HDRS =
CMHGFILE =
......
/* (0.75)
/* (0.76)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.75
#define Module_MajorVersion_CMHG 0.76
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 21 Mar 2018
#define Module_Date_CMHG 07 Jul 2018
#define Module_MajorVersion "0.75"
#define Module_Version 75
#define Module_MajorVersion "0.76"
#define Module_Version 76
#define Module_MinorVersion ""
#define Module_Date "21 Mar 2018"
#define Module_Date "07 Jul 2018"
#define Module_ApplicationDate "21-Mar-18"
#define Module_ApplicationDate "07-Jul-18"
#define Module_ComponentName "BCM2835"
#define Module_ComponentPath "mixed/RiscOS/Sources/HAL/BCM2835"
#define Module_FullVersion "0.75"
#define Module_HelpVersion "0.75 (21 Mar 2018)"
#define Module_LibraryVersionInfo "0:75"
#define Module_FullVersion "0.76"
#define Module_HelpVersion "0.76 (07 Jul 2018)"
#define Module_LibraryVersionInfo "0:76"
......@@ -97,77 +97,48 @@ GPU_L2CnonAl * &40000000 ; GPU L2 cached non allocating coher
GPU_L1L2Cac * &00000000 ; both L1 and L2 cached GPU side
GPU_CacheMask * &c0000000
;
; Timer details
;
TIMER_RATE * 1000000 ; 1MHz
MACRO
$label ReadTMR0 $r,$cond
$label MRC$cond p6, 0, $r, c0, c1
MEND
; Exit CC if ARM11, CS if A7/A53
MACRO
$label ReadTMR1 $r,$cond
$label MRC$cond p6, 0, $r, c1, c1
MEND
MACRO
$label ReadTCR0 $r,$cond
$label MRC$cond p6, 0, $r, c2, c1
MEND
MACRO
$label ReadTCR1 $r,$cond
$label MRC$cond p6, 0, $r, c3, c1
MEND
MACRO
$label ReadTRR0 $r,$cond
$label MRC$cond p6, 0, $r, c4, c1
MEND
MACRO
$label ReadTRR1 $r,$cond
$label MRC$cond p6, 0, $r, c5, c1
MEND
MACRO
$label ReadTISR $r,$cond
$label MRC$cond p6, 0, $r, c6, c1
MEND
MACRO
$label ReadWDTCR $r,$cond
$label MRC$cond p6, 0, $r, c7, c1
$label CPUDetect $reg
$label MRC p15, 0, $reg, c0, c0, 0 ; read Main ID Register
AND $reg, $reg, #&FF00
CMP $reg, #&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7
MEND
; Acquire/release the HAL spinlock
; This is mainly for quad-core devices, but will work with ARMv6 too
MACRO
$label WriteTMR0 $r,$cond
$label MCR$cond p6, 0, $r, c0, c1
MEND
MACRO
$label WriteTMR1 $r,$cond
$label MCR$cond p6, 0, $r, c1, c1
MEND
MACRO
$label WriteTCR0 $r,$cond
$label MCR$cond p6, 0, $r, c2, c1
MEND
MACRO
$label WriteTCR1 $r,$cond
$label MCR$cond p6, 0, $r, c3, c1
MEND
MACRO
$label WriteTRR0 $r,$cond
$label MCR$cond p6, 0, $r, c4, c1
MEND
MACRO
$label WriteTRR1 $r,$cond
$label MCR$cond p6, 0, $r, c5, c1
MEND
MACRO
$label WriteTISR $r,$cond
$label MCR$cond p6, 0, $r, c6, c1
AcquireSpinlock ; Corrupts ip, NZ, stashes old PSR on stack
MRS ip, CPSR
Push "ip"
ADD sb, sb, #:INDEX:Spinlock
CPSID if
10
LDREX ip, [sb]
TEQ ip, #0
WFENE
STREXEQ ip, sb, [sb]
TEQEQ ip, #0
BNE %BT10
MCR p15, 0, ip, c7, c10, 5 ; a.k.a DoMemBarrier, but ip already 0
SUB sb, sb, #:INDEX:Spinlock
MEND
MACRO
$label WriteWDTCR $r,$cond
$label MCR$cond p6, 0, $r, c7, c1
ReleaseSpinlock ; Corrupts ip
MOV ip, #0
MCR p15, 0, ip, c7, c10, 5 ; a.k.a DoMemBarrier, but ip already 0
STR ip, Spinlock ; Clear spinlock before barrier
MCR p15, 0, ip, c7, c10, 4 ; a.k.a DataSyncBarrier, but ip already 0
SEV
Pull "ip"
MSR CPSR_c, ip
MEND
;
; Timer details
;
TIMER_RATE * 1000000 ; 1MHz
GBLA NumTimers
NumTimers SETA 0
......@@ -290,9 +261,7 @@ $label MRC p15, 1, $clidr, c0, c0, 1 ; read CLIDR
MACRO
$label FlushDataCache
$label MRC p15, 0, lr, c0, c0, 0 ; read Main ID Register
AND lr, lr, #&FF00
CMP lr, #&C000 ; xxxxB76x for ARM1176, xxxxC07x for Cortex-A7
$label CPUDetect lr
BCS %FA07
FlushDataCacheV6 lr
B %FT99
......@@ -622,7 +591,30 @@ iDev_ARM_SDIO * 64+18 ; copy of GPU IRQ 56
iDev_ARM_Uart * 64+19 ; copy of GPU IRQ 57
iDev_ARM_VCSDIO * 64+20 ; copy of GPU IRQ 62
iDev_Max * 64+21
iDev_ARM11_Max * 64+21
; Extra interrupt sources for QA7
; These are all core-specific interrupts
; Note that the original interrupts (0 - iDev_ARM11_Max) can only be routed to
; one core at a time (although IRQ and FIQ can be routed differently if we
; desire). If iDev_QA7_GPU is firing, it indicates that we are the owner of the
; GPU interrupts and should check its status registers to determine the source.
iDev_QA7_Base * iDev_ARM11_Max
^ iDev_QA7_Base
iDev_QA7_CNTPSIRQ # 4 ; Core-specific
iDev_QA7_CNTPNSIRQ # 4 ; Core-specific
iDev_QA7_CNTPHPIRQ # 4 ; Core-specific
iDev_QA7_CNTPVIRQ # 4 ; Core-specific
iDev_QA7_MBox0 # 4 ; Core-specific
iDev_QA7_MBox1 # 4 ; Core-specific
iDev_QA7_MBox2 # 4 ; Core-specific
iDev_QA7_MBox3 # 4 ; Core-specific
iDev_QA7_GPU # 4 ; Each of IRQ+FIQ can only be assigned to one core at a time
iDev_QA7_PMU # 4 ; Core-specific
iDev_QA7_AXI # 4 ; Can only be IRQ of core 0
iDev_QA7_LocalTimer # 4 ; Can only be assigned to one core (as either IRQ or FIQ)
iDev_QA7_Max # 0
;IIC0 (BSC0, i.e. Broadcom Serial Controller 0)
IIC_Base0 * &00205000 ; base of IIC0
......@@ -700,40 +692,7 @@ QA7_CORE3_MBOX0_RDCLR * &00F0
QA7_CORE3_MBOX1_RDCLR * &00F4
QA7_CORE3_MBOX2_RDCLR * &00F8
QA7_CORE3_MBOX3_RDCLR * &00FC
MACRO
$label ReadINTCTL $r,$cond
$label MRC$cond p6, 0, $r, c0, c0
MEND
MACRO
$label ReadINTSTR $r,$cond
$label MRC$cond p6, 0, $r, c4, c0
MEND
MACRO
$label ReadIINTSRC $r,$cond
$label MRC$cond p6, 0, $r, c8, c0
MEND
MACRO
$label ReadFINTSRC $r,$cond
$label MRC$cond p6, 0, $r, c9, c0
MEND
MACRO
$label WriteINTCTL $r,$cond
$label MCR$cond p6, 0, $r, c0, c0
MEND
MACRO
$label WriteINTSTR $r,$cond
$label MCR$cond p6, 0, $r, c4, c0
MEND
MACRO
$label WriteIINTSRC $r,$cond
$label MCR$cond p6, 0, $r, c8, c0
MEND
MACRO
$label WriteFINTSRC $r,$cond
$label MCR$cond p6, 0, $r, c9, c0
MEND
QA7_SIZE * &40000
]
END
......@@ -15,13 +15,23 @@
MACRO
HALEntry $name
ASSERT (. - HAL_EntryTable) / 4 = EntryNo_$name
DCD $name - HAL_EntryTable
ASSERT (. - $table) / 4 = EntryNo_$name
DCD $name - $table
MEND
MACRO
QA7Entry $name
ASSERT (. - $table) / 4 = EntryNo_$name
[ $table_idx == 0
DCD ARM11_$name - $table
|
DCD QA7_$name - $table
]
MEND
MACRO
NullEntry
DCD HAL_Null - HAL_EntryTable
DCD HAL_Null - $table
MEND
MACRO
......
......@@ -36,6 +36,7 @@
GET Hdr:DMADevice
GET Hdr:GPIODevice
GET Hdr:VideoDevice
GET Hdr:DBellDevice
GET hdr.BCM2835
; Per-timer workspace layout
......@@ -87,11 +88,13 @@ sb RN 9
PeriBase # 4
IRQ_Base_Address # 4
QA7_Base # 4
ARM_Counter_IO_Address # 4
ARM_Timer_IO_Address # 4
UARTOldModemStatus # 4
MMUOffBaseAddr # 4 ; original address kernel was loaded from
MachineID # 8 ; derived from MAC address if there
Spinlock # 4 ; Spinlock used for any atomic ops
IIC_Status # 4 ; Non-zero if an IIC transfer is going on
; NOTE - The following locations are for the base addresses of the
......@@ -162,6 +165,7 @@ SPI1Device # HALDeviceSize
SPI2Device # HALDeviceSize
TouchDevice # HALDeviceSize
MBoxDevice # HALDeviceSize
DBellDevice # HALDevice_DBell_Size
HAL_WsSize * :INDEX:@
sizeof_workspace * :INDEX:@
......
;
; Copyright (c) 2016, RISC OS Open Ltd
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of RISC OS Open Ltd nor the names of its contributors
; may be used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
IMPORT memcpy
GET Hdr:ListOpts
GET Hdr:CPU.Arch
GET Hdr:Macros
GET Hdr:Proc
GET hdr.BCM2835
GET hdr.StaticWS
sb RN 9
EXPORT DBell_InitDevices
AREA |Asm$$Code|, CODE, READONLY, PIC
DBell_InitDevices ROUT
CPUDetect a1
MOVCC pc, lr
Entry
ADRL a1, DBellDevice
ADR a2, DBellTemplate
MOV a3, #HALDevice_DBell_Size
BL memcpy
ADRL a2, DBellDevice
LDR a1, QA7_Base
ADD a1, a1, #QA7_CORE0_MBOX0_RDCLR
STR a1, [a2, #HALDevice_Address]
MOV a1, #0
MOV lr, pc
LDR pc, OSentries+4*OS_AddDevice
EXIT
MACRO
$class HALDeviceField $field, $value
LCLS myvalue
[ "$value" = ""
myvalue SETS "$field"
|
myvalue SETS "$value"
]
ASSERT . - %A0 = HALDevice_$class$field
[ ?HALDevice_$class$field = 2
DCW $myvalue
ELIF ?HALDevice_$class$field = 4
DCD $myvalue
|
% ?HALDevice_$class$field
]
MEND
DBellTemplate
0
HALDeviceField Type, HALDeviceType_Comms + HALDeviceComms_ARMDBell
HALDeviceField ID, HALDeviceID_ARMDBell_BCM2836
HALDeviceField Location, HALDeviceBus_Sys + HALDeviceSysBus_AHB ; Guess
HALDeviceField Version, 0
HALDeviceField Description, DBell_Description
HALDeviceField Address, 0
HALDeviceField Reserved1, 0
HALDeviceField Activate, DBell_Activate
HALDeviceField Deactivate, DBell_Deactivate
HALDeviceField Reset, DBell_Reset
HALDeviceField Sleep, DBell_Sleep
HALDeviceField Device, -1 ; IRQ numbers vary by core, use DBell_GetIRQ
HALDeviceField TestIRQ, DBell_TestIRQ
HALDeviceField ClearIRQ, DBell_ClearIRQ
HALDeviceField Reserved2, 0
ASSERT . - %A0 = HALDeviceSize
DBell HALDeviceField GetIRQ, DBell_GetIRQ
DBell HALDeviceField Ring, DBell_Ring
ASSERT . - %A0 = HALDevice_DBell_Size
DBell_Description
DCB "BCM2836/2837 QA7 mailbox 0 doorbell", 0
ALIGN
DBell_Activate
DBell_TestIRQ
MOV a1, #1
DBell_Deactivate
DBell_Reset
MOV pc, lr
DBell_Sleep
MOV a1, #0
MOV pc, lr
DBell_GetIRQ
; In: a2 = core number
ADD a1, a2, #iDev_QA7_MBox0
MOV pc, lr
DBell_ClearIRQ
LDR a1, [a1, #HALDevice_Address] ; -> QA7_CORE0_MBOX0_RDCLR
MRC p15, 0, a2, c0, c0, 5
MVN a3, #0
AND a2, a2, #3
ASSERT QA7_CORE1_MBOX0_RDCLR-QA7_CORE0_MBOX0_RDCLR = 16
STR a3, [a1, a2, LSL #4]
MOV pc, lr
DBell_Ring
; In: a2 = mask of CPU cores
LDR a1, [a1, #HALDevice_Address]
TST a2, #1
STRNE a1, [a1, #QA7_CORE0_MBOX0_SET-QA7_CORE0_MBOX0_RDCLR]
TST a2, #2
STRNE a1, [a1, #QA7_CORE1_MBOX0_SET-QA7_CORE0_MBOX0_RDCLR]
TST a2, #4
STRNE a1, [a1, #QA7_CORE2_MBOX0_SET-QA7_CORE0_MBOX0_RDCLR]
TST a2, #8
STRNE a1, [a1, #QA7_CORE3_MBOX0_SET-QA7_CORE0_MBOX0_RDCLR]
MOV pc, lr
END
......@@ -27,19 +27,34 @@
;
EXPORT Interrupt_Init
EXPORT HAL_IRQEnable
EXPORT HAL_IRQDisable
EXPORT HAL_IRQClear
EXPORT HAL_IRQSource
EXPORT HAL_IRQStatus
EXPORT HAL_FIQEnable
EXPORT HAL_FIQDisable
EXPORT HAL_FIQDisableAll
EXPORT HAL_FIQClear
EXPORT HAL_FIQSource
EXPORT HAL_FIQStatus
EXPORT HAL_IRQMax
EXPORT ARM11_HAL_IRQEnable
EXPORT ARM11_HAL_IRQDisable
EXPORT ARM11_HAL_IRQSource
EXPORT ARM11_HAL_IRQStatus
EXPORT ARM11_HAL_FIQEnable
EXPORT ARM11_HAL_FIQDisable
EXPORT ARM11_HAL_FIQDisableAll
EXPORT ARM11_HAL_FIQSource
EXPORT ARM11_HAL_FIQStatus
EXPORT ARM11_HAL_IRQMax
EXPORT ARM11_HAL_IRQProperties
EXPORT QA7_HAL_IRQEnable
EXPORT QA7_HAL_IRQDisable
EXPORT QA7_HAL_IRQSource
EXPORT QA7_HAL_IRQStatus
EXPORT QA7_HAL_FIQEnable
EXPORT QA7_HAL_FIQDisable
EXPORT QA7_HAL_FIQDisableAll
EXPORT QA7_HAL_FIQSource
EXPORT QA7_HAL_FIQStatus
EXPORT QA7_HAL_IRQMax
EXPORT QA7_HAL_IRQProperties
EXPORT QA7_HAL_IRQSetCores
EXPORT QA7_HAL_IRQGetCores
GET Hdr:ListOpts
GET Hdr:Macros
......@@ -61,10 +76,140 @@ Interrupt_Init
MOV pc, lr
HAL_IRQEnable
CMN a1,#1
MOVEQ pc,lr
QA7_HAL_IRQEnable ROUT
CMP a1, #iDev_QA7_Max
BHS ExitZero
SUBS a2, a1, #iDev_QA7_Base
BLT HAL_IRQEnable_GPU
MOV a4, #1 ; Signal this is an IRQ enable event
ToggleIRQ
AND a3, a2, #3 ; Extract core number
MOV a2, a2, LSR #2 ; Bit/device number
LDR a1, QA7_Base
AcquireSpinlock
ADD pc, pc, a2, LSL #2
NOP
B ToggleIRQ_CNTPSIRQ
B ToggleIRQ_CNTPNSIRQ
B ToggleIRQ_CNTPHPIRQ
B ToggleIRQ_CNTPVIRQ
B ToggleIRQ_MBox0
B ToggleIRQ_MBox1
B ToggleIRQ_MBox2
B ToggleIRQ_MBox3
B ToggleIRQ_GPU
B ToggleIRQ_PMU
B ToggleIRQ_AXI
B ToggleIRQ_LocalTimer
ToggleIRQ_MBox0
ToggleIRQ_MBox1
ToggleIRQ_MBox2
ToggleIRQ_MBox3
ADD a1, a1, #QA7_CORE0_MBOX_INT_CTRL-QA7_CORE0_TIMER_INT_CTRL
ToggleIRQ_CNTPSIRQ
ToggleIRQ_CNTPNSIRQ
ToggleIRQ_CNTPHPIRQ
ToggleIRQ_CNTPVIRQ ROUT
; Work out bit number
AND a2, a2, #3
TST a4, #2
MOVEQ ip, #1
MOVNE ip, #16
MOV ip, ip, LSL a2
; Work out the register number
ADD a1, a1, a3, LSL #2
; Grab the state
LDR a2, [a1, #QA7_CORE0_TIMER_INT_CTRL]
; Calc new state
; Note that this is a trivial implementation which doesn't attempt to do anything special to deal with the case that having FIQ enabled will mask the IRQ
TST a4, #1
BICEQ a4, a2, ip
ORRNE a4, a2, ip
STR a4, [a1, #QA7_CORE0_TIMER_INT_CTRL]
; Calc old state, ignoring that FIQs will mask IRQs
AND a1, a2, ip
ReleaseSpinlock
MOV pc, lr
ToggleIRQ_GPU ROUT
; Get old status
LDR a2, [a1, #QA7_GPU_INT_ROUTING]
; Calc new status (can only claim, not release)
TST a4, #1
BEQ %FT30
TST a4, #2
MOV ip, a2
BFIEQ ip, a3, #0, #2
BFINE ip, a3, #2, #2
STR ip, [a1, #QA7_GPU_INT_ROUTING]
30
ReleaseSpinlock
; Calc old state
TST a4, #2
MOVNE a2, a2, LSR #2
AND a2, a2, #3
CMP a2, a3
MOVEQ a1, #1
MOVNE a1, #0
MOV pc, lr
ToggleIRQ_PMU ROUT
; Grab the old state before we overwrite it
LDR a2, [a1, #QA7_PMU_INT_ROUT_CLR]
; Calculate the bit to toggle
; Note that this is a trivial implementation which doesn't attempt to do anything special to deal with the case that having FIQ enabled will mask the IRQ
TST a4, #2
MOVEQ ip, #1
MOVNE ip, #16
MOV ip, ip, LSL a3
; Calculate the register to write to
TST a4, #1 ; EQ: Disable, NE: Enable
ADDEQ a1, a1, #QA7_PMU_INT_ROUT_CLR
ADDNE a1, a1, #QA7_PMU_INT_ROUT_SET
STR ip, [a1]
; Calc old state, ignoring that FIQs will mask IRQs
AND a1, a2, ip
ReleaseSpinlock
MOV pc, lr
ToggleIRQ_AXI ROUT
; Only supported for core 0 IRQ
TEQ a3, #0
TSTEQ a4, #2
BNE ReleaseExitZero
LDR a2, [a1, #QA7_AXI_OUTSTANDING_IRQ]
MOV a3, a2
BFI a3, a4, #20, #1
STR a3, [a1, #QA7_AXI_OUTSTANDING_IRQ]
AND a1, a2, #1<<20
ReleaseSpinlock
MOV pc, lr
ToggleIRQ_LocalTimer ROUT
; Calculate required routing value
AND ip, a4, #2
ORR a3, a3, ip, LSL #1
; Get old status
LDR a2, [a1, #QA7_LOCAL_INT_ROUTING]
; Can only claim, not release
TST a4, #1
BEQ %FT40
MOV a4, a2
BFI a4, a3, #0, #3
STR a4, [a1, #QA7_LOCAL_INT_ROUTING]
40
ReleaseSpinlock
; Calc old state
AND a4, a4, #7
CMP a4, a3
MOVEQ a1, #1
MOVNE a1, #0
ARM11_HAL_IRQEnable ROUT
CMP a1, #iDev_ARM11_Max
BHS ExitZero
HAL_IRQEnable_GPU
DoMemBarrier ip
LDR ip, IRQ_Base_Address
ADD ip, ip, #IRQ_EN1
......@@ -78,10 +223,24 @@ HAL_IRQEnable
DoMemBarrier ip
MOV pc, lr
HAL_IRQDisable