Browse Source

Added Generic Timer support for the Veyron.

This change enables the ARM Generic Timer on the RK3288 Veyron SoC platform.
This includes three main additions: adding the GTDT ACPI table; setting the
ARM Generic Timer's frequency (CNTFRQ) to the fixed 24 MHz on each core;
jumping to monitor mode in order to set the ARM Generic Timer's virtual
offset (CNTVOFF) to zero on each core.
Chris Stevens 8 years ago
parent
commit
0320c85442

+ 17 - 1
include/minoca/kernel/arm.h

@@ -161,6 +161,7 @@ Author:
 #define ARM_MODE_FIQ    0x00000011
 #define ARM_MODE_IRQ    0x00000012
 #define ARM_MODE_SVC    0x00000013
+#define ARM_MODE_MON    0x00000016
 #define ARM_MODE_ABORT  0x00000017
 #define ARM_MODE_HYP    0x0000001A
 #define ARM_MODE_UNDEF  0x0000001B
@@ -327,7 +328,7 @@ Author:
 
 #define MMU_ENABLED                     0x00000001
 #define MMU_ALIGNMENT_FAULT_ENABLED     0x00000002
-#define MMU_DCACHE_UNIFIED_ENABLED      0x00000004
+#define MMU_DCACHE_ENABLED              0x00000004
 #define MMU_WRITE_BUFFER_ENABLED        0x00000008
 #define MMU_ENDIANNESS                  0x00000080
 #define MMU_SYSTEM_PROTECTION           0x00000100
@@ -553,6 +554,21 @@ Author:
 
 #define ARM_PROCESSOR_ID_MASK 0x00FFFFFF
 
+//
+// Define the Secure Configuration Register values.
+//
+
+#define SCR_NON_SECURE                            0x00000001
+#define SCR_MONITOR_MODE_IRQ                      0x00000002
+#define SCR_MONITOR_MODE_FIQ                      0x00000004
+#define SCR_MONITOR_MODE_EXTERNAL_ABORT           0x00000008
+#define SCR_CPSR_FIQ_WRITABLE                     0x00000010
+#define SCR_CPSR_ASYNC_ABORT_WRITABLE             0x00000020
+#define SCR_EARLY_TERMINATION_DISABLED            0x00000040
+#define SCR_NON_SECURE_SMC_DISABLED               0x00000080
+#define SCR_NON_SECURE_HVC_ENABLED                0x00000100
+#define SCR_NON_SECURE_INSTRUCTION_FETCH_DISABLED 0x00000200
+
 //
 // ------------------------------------------------------ Data Type Definitions
 //

+ 16 - 0
include/minoca/kernel/arm.inc

@@ -62,6 +62,7 @@ Environment:
 #define ARM_MODE_FIQ    0x00000011
 #define ARM_MODE_IRQ    0x00000012
 #define ARM_MODE_SVC    0x00000013
+#define ARM_MODE_MON    0x00000016
 #define ARM_MODE_ABORT  0x00000017
 #define ARM_MODE_HYP    0x0000001A
 #define ARM_MODE_UNDEF  0x0000001B
@@ -136,6 +137,21 @@ Environment:
 
 #define MMU_TLB_LOCKING_ENABLE          0x00020000
 
+##
+## Secure Configuration Register bits (SCR).
+##
+
+#define SCR_NON_SECURE                            0x00000001
+#define SCR_MONITOR_MODE_IRQ                      0x00000002
+#define SCR_MONITOR_MODE_FIQ                      0x00000004
+#define SCR_MONITOR_MODE_EXTERNAL_ABORT           0x00000008
+#define SCR_CPSR_FIQ_WRITABLE                     0x00000010
+#define SCR_CPSR_ASYNC_ABORT_WRITABLE             0x00000020
+#define SCR_EARLY_TERMINATION_DISABLED            0x00000040
+#define SCR_NON_SECURE_SMC_DISABLED               0x00000080
+#define SCR_NON_SECURE_HVC_ENABLED                0x00000100
+#define SCR_NON_SECURE_INSTRUCTION_FETCH_DISABLED 0x00000200
+
 ##
 ## Definition for the structure on the exception stacks.
 ##

+ 3 - 2
uefi/plat/veyron/Makefile

@@ -51,8 +51,9 @@ OBJS += debug.o                 \
         veyronfwv.o             \
         video.o                 \
 
-ARMV7_OBJS = armv7/entry.o  \
-             armv7/smpa.o   \
+ARMV7_OBJS = armv7/entry.o   \
+             armv7/minttbl.o \
+             armv7/smpa.o    \
 
 TEXT_ADDRESS = 0x020000A4
 

+ 1 - 0
uefi/plat/veyron/acpi/Makefile

@@ -35,6 +35,7 @@ OBJS += apic.aml     \
         dsdt.aml     \
         facp.aml     \
         facs.aml     \
+        gtdt.aml     \
         rk32.aml     \
 
 include $(SRCROOT)/os/minoca.mk

+ 1 - 0
uefi/plat/veyron/acpi/build.ck

@@ -27,6 +27,7 @@ function build() {
         "dsdt.asl",
         "facp.asl",
         "facs.asl",
+        "gtdt.asl",
         "rk32.asl"
     ];
 

+ 61 - 0
uefi/plat/veyron/acpi/gtdt.asl

@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 2016 Minoca Corp. All Rights Reserved
+
+Module Name:
+
+    gtdt.asl
+
+Abstract:
+
+    This module implements the Generic Timer Descriptor Table for the RK3288
+    Veyron.
+
+Author:
+
+    Chris Stevens 23-May-2016
+
+Environment:
+
+    Firmware
+
+--*/
+
+//
+// ---------------------------------------------------------------- Definitions
+//
+
+[0004]                          Signature : "GTDT"    [Generic Timer Description Table]
+[0004]                       Table Length : 00000050
+[0001]                           Revision : 01
+[0001]                           Checksum : F1
+[0006]                             Oem ID : "MINOCA"
+[0008]                       Oem Table ID : "MINOCA  "
+[0004]                       Oem Revision : 00000001
+[0004]                    Asl Compiler ID : "INTL"
+[0004]              Asl Compiler Revision : 20110623
+
+[0008]                      Timer Address : 0000000000000000
+[0004]              Flags (decoded below) : 00000000
+                           Memory Present : 0
+
+[0004]               Secure PL1 Interrupt : 0000001D
+[0004]         SPL1 Flags (decoded below) : 00000000
+                             Trigger Mode : 0
+                                 Polarity : 0
+
+[0004]           Non-Secure PL1 Interrupt : 0000001E
+[0004]        NSPL1 Flags (decoded below) : 00000000
+                             Trigger Mode : 0
+                                 Polarity : 0
+
+[0004]            Virtual Timer Interrupt : 0000001B
+[0004]           VT Flags (decoded below) : 00000000
+                             Trigger Mode : 0
+                                 Polarity : 0
+
+[0004]           Non-Secure PL2 Interrupt : 0000001A
+[0004]        NSPL2 Flags (decoded below) : 00000000
+                             Trigger Mode : 0
+                                 Polarity : 0
+

+ 3 - 7
uefi/plat/veyron/armv7/entry.S

@@ -26,6 +26,7 @@ Environment:
 ##
 
 #include <minoca/kernel/arm.inc>
+#include "smp.inc"
 
 ##
 ## ---------------------------------------------------------------- Definitions
@@ -81,14 +82,10 @@ _start:
     mcr     p15, 0, %r0, %cr1, %cr0, 0
 
     ##
-    ## Set the SMP bit in the auxiliary control register.
+    ## Perform initialization steps that must be taken on each core.
     ##
 
-    mrc     p15, 0, %r0, %cr1, %cr0, 1
-    ldr     %r1, =InitialAuxOrMask
-    ldr     %r1, [%r1]
-    orr     %r0, %r0, %r1
-    mcr     p15, 0, %r0, %cr1, %cr0, 1
+    RK32_SMP_INIT
 
     ##
     ## Zero out the BSS section.
@@ -123,5 +120,4 @@ LoopForever:
 
 InitialMmuAndMask: .word ~(MMU_ALIGNMENT_FAULT_ENABLED)
 InitialMmuOrMask: .word MMU_UNALIGNED_ACCESS_ENABLED
-InitialAuxOrMask: .word CORTEX_A17_AUX_SMP_ENABLE
 

+ 132 - 0
uefi/plat/veyron/armv7/minttbl.S

@@ -0,0 +1,132 @@
+/*++
+
+Copyright (c) 2016 Minoca Corp. All Rights Reserved
+
+Module Name:
+
+    minttbl.S
+
+Abstract:
+
+    This module implements the monitor mode interrupt jump vector table for the
+    RK3288 Veyron SoC.
+
+Author:
+
+    Chris Stevens 8-Jun-2016
+
+Environment:
+
+    Firmware
+
+--*/
+
+##
+## ------------------------------------------------------------------ Includes
+##
+
+#include <minoca/kernel/arm.inc>
+
+##
+## --------------------------------------------------------------- Definitions
+##
+
+##
+## ---------------------------------------------------------------------- Code
+##
+
+ASSEMBLY_FILE_HEADER
+.arch_extension virt
+
+##
+## .globl allows these labels to be visible to the linker.
+##
+
+.globl EfipRk32MonitorInterruptTable
+
+##
+## This address must be aligned to a 32 byte address so that it can be set in
+## the MVBAR register.
+##
+
+.balign 32
+
+EfipRk32MonitorInterruptTable:
+.word 0
+.word 0
+    ldr     %pc, EfipRk32SecureMonitorCallVector
+    ldr     %pc, EfipRk32PrefetchAbortVector
+    ldr     %pc, EfipRk32DataAbortVector
+.word 0
+    ldr     %pc, EfipRk32IrqInterruptVector
+    ldr     %pc, EfipRk32FiqInterruptVector
+
+EfipRk32SecureMonitorCallVector:
+    .word EfipRk32SecureMonitorCallEntry
+
+EfipRk32PrefetchAbortVector:
+    .word 0
+
+EfipRk32DataAbortVector:
+    .word 0
+
+EfipRk32IrqInterruptVector:
+    .word 0
+
+EfipRk32FiqInterruptVector:
+    .word 0
+
+##
+## --------------------------------------------------------- Internal Functions
+##
+
+##
+## VOID
+## EfipRk32SecureMonitorCallEntry (
+##     VOID
+##     )
+##
+
+/*++
+
+Routine Description:
+
+    This routine directly handles an exception generated by a secure monitor
+    call.
+
+Arguments:
+
+    None.
+
+Return Value:
+
+    None.
+
+--*/
+
+FUNCTION EfipRk32SecureMonitorCallEntry
+
+    ##
+    ## The ARM Generic Timer's virtual offset can bet set in HYP mode and in
+    ## Monitor Mode when the SCR.NS bit is set to 1. Set the NS bit and zero
+    ## the offset.
+    ##
+
+    mrc     p15, 0, %r0, %c1, %c1, 0          @ Get the SCR
+    orr     %r0, %r0, #SCR_NON_SECURE
+    mcr     p15, 0, %r0, %c1, %c1, 0          @ Set the SCR
+    mov     %r2, #0
+    mov     %r3, #0
+    mcrr    p15, 4, %r2, %r3, %c14
+
+    ##
+    ## Clear the NS bit before returing from the exception to remain in secure
+    ## mode.
+    ##
+
+    bic     %r0, %r0, #SCR_NON_SECURE
+    mcr     p15, 0, %r0, %c1, %c1, 0          @ Set the SCR
+    eret
+
+END_FUNCTION EfipRk32SecureMonitorCallEntry
+

+ 83 - 0
uefi/plat/veyron/armv7/smp.inc

@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 2016 Minoca Corp. All Rights Reserved
+
+Module Name:
+
+    smp.inc
+
+Abstract:
+
+    This module contains definitions for SMP assembly on the RK3288 Veyron SoC.
+
+Author:
+
+    Chris Stevens 9-Jun-2016
+
+Environment:
+
+    Firmware
+
+--*/
+
+##
+## --------------------------------------------------------------- Definitions
+##
+
+#define RK32_TIMER_FREQUENCY 0x016E3600
+
+##
+## -------------------------------------------------------------------- Macros
+##
+
+##
+## This macro can be run immediately after an exception or interrupt. It
+## switches back to SVC mode and creates a trap frame. This uses several
+## instructions from ARMv6T2, including srs, cpsid #mode, and clrex.
+##
+
+.macro RK32_SMP_INIT
+
+    ##
+    ## Set the SMP bit in the auxiliary control register on this core.
+    ##
+
+    mrc     p15, 0, %r0, %cr1, %cr0, 1
+    orr     %r0, %r0, #CORTEX_A17_AUX_SMP_ENABLE
+    mcr     p15, 0, %r0, %cr1, %cr0, 1
+    DSB
+    ISB
+
+    ##
+    ## Set the ARM Generic Timer frequency. This must be done in secure mode
+    ## on each core.
+    ##
+
+    ldr     %r0, =RK32_TIMER_FREQUENCY
+    mcr     p15, 0, %r0, %c14, %c0, 0           @ Set the CNTFRQ
+
+    ##
+    ## Set the Monitor Mode Interrupt Vector Base Address register in
+    ## preparation for the SMC instruction below.
+    ##
+
+    ldr     %r0, =EfipRk32MonitorInterruptTable
+    mcr     p15, 0, %r0, %c12, %c0, 1
+
+    ##
+    ## The SMC exception must be taken in Thumb mode.
+    ##
+
+    mrc     p15, 0, %r0, %cr1, %cr0, 0          @ Get the SCTLR.
+    orr     %r0, %r0, #MMU_THUMB_EXCEPTIONS
+    mcr     p15, 0, %r0, %cr1, %cr0, 0          @ Set the SCTLR.
+
+    ##
+    ## Make the jump to Monitor Mode in order to zero the virtual count offset
+    ## of the ARM Generic Timer.
+    ##
+
+    smc     #0
+
+.endm
+

+ 3 - 7
uefi/plat/veyron/armv7/smpa.S

@@ -26,6 +26,7 @@ Environment:
 ##
 
 #include <minoca/kernel/arm.inc>
+#include "smp.inc"
 
 ##
 ## --------------------------------------------------------------- Definitions
@@ -107,15 +108,10 @@ Return Value:
 EfipRk32ProcessorStartup:
 
     ##
-    ## Set the SMP bit in the auxiliary control register on this core.
+    ## Perform initialization steps that must be taken on each core.
     ##
 
-    mrc     p15, 0, %r0, %cr1, %cr0, 1
-    ldr     %r1, =CORTEX_A17_AUX_SMP_ENABLE
-    orr     %r0, %r0, %r1
-    mcr     p15, 0, %r0, %cr1, %cr0, 1
-    DSB
-    ISB
+    RK32_SMP_INIT
 
     ##
     ## Initialize the local GIC CPU interface by setting the lowest priority

+ 1 - 0
uefi/plat/veyron/build.ck

@@ -26,6 +26,7 @@ function build() {
     text_address = "0x020000A4";
     sources = [
         "armv7/entry.S",
+        "armv7/minttbl.S",
         "armv7/smpa.S",
         "debug.c",
         "fwvol.c",