Commit c71645ad2bd5179ad21e2501c26f574e9688f02a

Authored by David Feng
Committed by Albert ARIBAUD
1 parent 91290cf728

arm64 patch: gicv3 support

This patch add gicv3 support to uboot armv8 platform.

Changes for v2:
  - rename arm/cpu/armv8/gic.S with arm/lib/gic_64.S
  - move smp_kick_all_cpus() from gic.S to start.S, it would be
    implementation dependent.
  - Each core initialize it's own ReDistributor instead of master
    initializeing all ReDistributors. This is advised by arnab.basu
    <arnab.basu@freescale.com>.

Signed-off-by: David Feng <fenghua@phytium.com.cn>

Showing 7 changed files with 297 additions and 114 deletions Side-by-side Diff

arch/arm/cpu/armv8/Makefile
... ... @@ -13,6 +13,5 @@
13 13 obj-y += exceptions.o
14 14 obj-y += cache.o
15 15 obj-y += tlb.o
16   -obj-y += gic.o
17 16 obj-y += transition.o
arch/arm/cpu/armv8/gic.S
1   -/*
2   - * GIC Initialization Routines.
3   - *
4   - * (C) Copyright 2013
5   - * David Feng <fenghua@phytium.com.cn>
6   - *
7   - * SPDX-License-Identifier: GPL-2.0+
8   - */
9   -
10   -#include <asm-offsets.h>
11   -#include <config.h>
12   -#include <linux/linkage.h>
13   -#include <asm/macro.h>
14   -#include <asm/gic.h>
15   -
16   -
17   -/*************************************************************************
18   - *
19   - * void gic_init(void) __attribute__((weak));
20   - *
21   - * Currently, this routine only initialize secure copy of GIC
22   - * with Security Extensions at EL3.
23   - *
24   - *************************************************************************/
25   -WEAK(gic_init)
26   - branch_if_slave x0, 2f
27   -
28   - /* Initialize Distributor and SPIs */
29   - ldr x1, =GICD_BASE
30   - mov w0, #0x3 /* EnableGrp0 | EnableGrp1 */
31   - str w0, [x1, GICD_CTLR] /* Secure GICD_CTLR */
32   - ldr w0, [x1, GICD_TYPER]
33   - and w2, w0, #0x1f /* ITLinesNumber */
34   - cbz w2, 2f /* No SPIs */
35   - add x1, x1, (GICD_IGROUPRn + 4)
36   - mov w0, #~0 /* Config SPIs as Grp1 */
37   -1: str w0, [x1], #0x4
38   - sub w2, w2, #0x1
39   - cbnz w2, 1b
40   -
41   - /* Initialize SGIs and PPIs */
42   -2: ldr x1, =GICD_BASE
43   - mov w0, #~0 /* Config SGIs and PPIs as Grp1 */
44   - str w0, [x1, GICD_IGROUPRn] /* GICD_IGROUPR0 */
45   - mov w0, #0x1 /* Enable SGI 0 */
46   - str w0, [x1, GICD_ISENABLERn]
47   -
48   - /* Initialize Cpu Interface */
49   - ldr x1, =GICC_BASE
50   - mov w0, #0x1e7 /* Disable IRQ/FIQ Bypass & */
51   - /* Enable Ack Group1 Interrupt & */
52   - /* EnableGrp0 & EnableGrp1 */
53   - str w0, [x1, GICC_CTLR] /* Secure GICC_CTLR */
54   -
55   - mov w0, #0x1 << 7 /* Non-Secure access to GICC_PMR */
56   - str w0, [x1, GICC_PMR]
57   -
58   - ret
59   -ENDPROC(gic_init)
60   -
61   -
62   -/*************************************************************************
63   - *
64   - * void gic_send_sgi(u64 sgi) __attribute__((weak));
65   - *
66   - *************************************************************************/
67   -WEAK(gic_send_sgi)
68   - ldr x1, =GICD_BASE
69   - mov w2, #0x8000
70   - movk w2, #0x100, lsl #16
71   - orr w2, w2, w0
72   - str w2, [x1, GICD_SGIR]
73   - ret
74   -ENDPROC(gic_send_sgi)
75   -
76   -
77   -/*************************************************************************
78   - *
79   - * void wait_for_wakeup(void) __attribute__((weak));
80   - *
81   - * Wait for SGI 0 from master.
82   - *
83   - *************************************************************************/
84   -WEAK(wait_for_wakeup)
85   - ldr x1, =GICC_BASE
86   -0: wfi
87   - ldr w0, [x1, GICC_AIAR]
88   - str w0, [x1, GICC_AEOIR]
89   - cbnz w0, 0b
90   - ret
91   -ENDPROC(wait_for_wakeup)
92   -
93   -
94   -/*************************************************************************
95   - *
96   - * void smp_kick_all_cpus(void) __attribute__((weak));
97   - *
98   - *************************************************************************/
99   -WEAK(smp_kick_all_cpus)
100   - /* Kick secondary cpus up by SGI 0 interrupt */
101   - mov x0, xzr /* SGI 0 */
102   - mov x29, lr /* Save LR */
103   - bl gic_send_sgi
104   - mov lr, x29 /* Restore LR */
105   - ret
106   -ENDPROC(smp_kick_all_cpus)
arch/arm/cpu/armv8/start.S
... ... @@ -50,7 +50,10 @@
50 50 */
51 51 adr x0, vectors
52 52 switch_el x1, 3f, 2f, 1f
53   -3: msr vbar_el3, x0
  53 +3: mrs x0, scr_el3
  54 + orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */
  55 + msr scr_el3, x0
  56 + msr vbar_el3, x0
54 57 msr cptr_el3, xzr /* Enable FP/SIMD */
55 58 ldr x0, =COUNTER_FREQUENCY
56 59 msr cntfrq_el0, x0 /* Initialize CNTFRQ */
57 60  
58 61  
59 62  
60 63  
61 64  
62 65  
63 66  
... ... @@ -95,31 +98,60 @@
95 98 /*-----------------------------------------------------------------------*/
96 99  
97 100 WEAK(lowlevel_init)
98   - /* Initialize GIC Secure Bank Status */
99 101 mov x29, lr /* Save LR */
100   - bl gic_init
101 102  
102   - branch_if_master x0, x1, 1f
  103 +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
  104 + branch_if_slave x0, 1f
  105 + ldr x0, =GICD_BASE
  106 + bl gic_init_secure
  107 +1:
  108 +#if defined(CONFIG_GICV3)
  109 + ldr x0, =GICR_BASE
  110 + bl gic_init_secure_percpu
  111 +#elif defined(CONFIG_GICV2)
  112 + ldr x0, =GICD_BASE
  113 + ldr x1, =GICC_BASE
  114 + bl gic_init_secure_percpu
  115 +#endif
  116 +#endif
103 117  
  118 + branch_if_master x0, x1, 2f
  119 +
104 120 /*
105 121 * Slave should wait for master clearing spin table.
106 122 * This sync prevent salves observing incorrect
107 123 * value of spin table and jumping to wrong place.
108 124 */
109   - bl wait_for_wakeup
  125 +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
  126 +#ifdef CONFIG_GICV2
  127 + ldr x0, =GICC_BASE
  128 +#endif
  129 + bl gic_wait_for_interrupt
  130 +#endif
110 131  
111 132 /*
112   - * All processors will enter EL2 and optionally EL1.
  133 + * All slaves will enter EL2 and optionally EL1.
113 134 */
114 135 bl armv8_switch_to_el2
115 136 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
116 137 bl armv8_switch_to_el1
117 138 #endif
118 139  
119   -1:
  140 +2:
120 141 mov lr, x29 /* Restore LR */
121 142 ret
122 143 ENDPROC(lowlevel_init)
  144 +
  145 +WEAK(smp_kick_all_cpus)
  146 + /* Kick secondary cpus up by SGI 0 interrupt */
  147 + mov x29, lr /* Save LR */
  148 +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
  149 + ldr x0, =GICD_BASE
  150 + bl gic_kick_secondary_cpus
  151 +#endif
  152 + mov lr, x29 /* Restore LR */
  153 + ret
  154 +ENDPROC(smp_kick_all_cpus)
123 155  
124 156 /*-----------------------------------------------------------------------*/
125 157  
arch/arm/include/asm/gic.h
... ... @@ -51,5 +51,61 @@
51 51 #define GICC_IIDR 0x00fc
52 52 #define GICC_DIR 0x1000
53 53  
  54 +/* ReDistributor Registers for Control and Physical LPIs */
  55 +#define GICR_CTLR 0x0000
  56 +#define GICR_IIDR 0x0004
  57 +#define GICR_TYPER 0x0008
  58 +#define GICR_STATUSR 0x0010
  59 +#define GICR_WAKER 0x0014
  60 +#define GICR_SETLPIR 0x0040
  61 +#define GICR_CLRLPIR 0x0048
  62 +#define GICR_SEIR 0x0068
  63 +#define GICR_PROPBASER 0x0070
  64 +#define GICR_PENDBASER 0x0078
  65 +#define GICR_INVLPIR 0x00a0
  66 +#define GICR_INVALLR 0x00b0
  67 +#define GICR_SYNCR 0x00c0
  68 +#define GICR_MOVLPIR 0x0100
  69 +#define GICR_MOVALLR 0x0110
  70 +
  71 +/* ReDistributor Registers for SGIs and PPIs */
  72 +#define GICR_IGROUPRn 0x0080
  73 +#define GICR_ISENABLERn 0x0100
  74 +#define GICR_ICENABLERn 0x0180
  75 +#define GICR_ISPENDRn 0x0200
  76 +#define GICR_ICPENDRn 0x0280
  77 +#define GICR_ISACTIVERn 0x0300
  78 +#define GICR_ICACTIVERn 0x0380
  79 +#define GICR_IPRIORITYRn 0x0400
  80 +#define GICR_ICFGR0 0x0c00
  81 +#define GICR_ICFGR1 0x0c04
  82 +#define GICR_IGROUPMODRn 0x0d00
  83 +#define GICR_NSACRn 0x0e00
  84 +
  85 +/* Cpu Interface System Registers */
  86 +#define ICC_IAR0_EL1 S3_0_C12_C8_0
  87 +#define ICC_IAR1_EL1 S3_0_C12_C12_0
  88 +#define ICC_EOIR0_EL1 S3_0_C12_C8_1
  89 +#define ICC_EOIR1_EL1 S3_0_C12_C12_1
  90 +#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
  91 +#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
  92 +#define ICC_BPR0_EL1 S3_0_C12_C8_3
  93 +#define ICC_BPR1_EL1 S3_0_C12_C12_3
  94 +#define ICC_DIR_EL1 S3_0_C12_C11_1
  95 +#define ICC_PMR_EL1 S3_0_C4_C6_0
  96 +#define ICC_RPR_EL1 S3_0_C12_C11_3
  97 +#define ICC_CTLR_EL1 S3_0_C12_C12_4
  98 +#define ICC_CTLR_EL3 S3_6_C12_C12_4
  99 +#define ICC_SRE_EL1 S3_0_C12_C12_5
  100 +#define ICC_SRE_EL2 S3_4_C12_C9_5
  101 +#define ICC_SRE_EL3 S3_6_C12_C12_5
  102 +#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
  103 +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
  104 +#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
  105 +#define ICC_SEIEN_EL1 S3_0_C12_C13_0
  106 +#define ICC_SGI0R_EL1 S3_0_C12_C11_7
  107 +#define ICC_SGI1R_EL1 S3_0_C12_C11_5
  108 +#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
  109 +
54 110 #endif /* __GIC_H__ */
arch/arm/lib/Makefile
... ... @@ -35,6 +35,7 @@
35 35  
36 36 obj-y += sections.o
37 37 ifdef CONFIG_ARM64
  38 +obj-y += gic_64.o
38 39 obj-y += interrupts_64.o
39 40 else
40 41 obj-y += interrupts.o
arch/arm/lib/gic_64.S
  1 +/*
  2 + * GIC Initialization Routines.
  3 + *
  4 + * (C) Copyright 2013
  5 + * David Feng <fenghua@phytium.com.cn>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#include <asm-offsets.h>
  11 +#include <config.h>
  12 +#include <linux/linkage.h>
  13 +#include <asm/macro.h>
  14 +#include <asm/gic.h>
  15 +
  16 +
  17 +/*************************************************************************
  18 + *
  19 + * void gic_init_secure(DistributorBase);
  20 + *
  21 + * Initialize secure copy of GIC at EL3.
  22 + *
  23 + *************************************************************************/
  24 +ENTRY(gic_init_secure)
  25 + /*
  26 + * Initialize Distributor
  27 + * x0: Distributor Base
  28 + */
  29 +#if defined(CONFIG_GICV3)
  30 + mov w9, #0x37 /* EnableGrp0 | EnableGrp1NS */
  31 + /* EnableGrp1S | ARE_S | ARE_NS */
  32 + str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */
  33 + ldr w9, [x0, GICD_TYPER]
  34 + and w10, w9, #0x1f /* ITLinesNumber */
  35 + cbz w10, 1f /* No SPIs */
  36 + add x11, x0, (GICD_IGROUPRn + 4)
  37 + add x12, x0, (GICD_IGROUPMODRn + 4)
  38 + mov w9, #~0
  39 +0: str w9, [x11], #0x4
  40 + str wzr, [x12], #0x4 /* Config SPIs as Group1NS */
  41 + sub w10, w10, #0x1
  42 + cbnz w10, 0b
  43 +#elif defined(CONFIG_GICV2)
  44 + mov w9, #0x3 /* EnableGrp0 | EnableGrp1 */
  45 + str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */
  46 + ldr w9, [x0, GICD_TYPER]
  47 + and w10, w9, #0x1f /* ITLinesNumber */
  48 + cbz w10, 1f /* No SPIs */
  49 + add x11, x0, (GICD_IGROUPRn + 4)
  50 + mov w9, #~0 /* Config SPIs as Grp1 */
  51 +0: str w9, [x11], #0x4
  52 + sub w10, w10, #0x1
  53 + cbnz w10, 0b
  54 +#endif
  55 +1:
  56 + ret
  57 +ENDPROC(gic_init_secure)
  58 +
  59 +
  60 +/*************************************************************************
  61 + * For Gicv2:
  62 + * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase);
  63 + * For Gicv3:
  64 + * void gic_init_secure_percpu(ReDistributorBase);
  65 + *
  66 + * Initialize secure copy of GIC at EL3.
  67 + *
  68 + *************************************************************************/
  69 +ENTRY(gic_init_secure_percpu)
  70 +#if defined(CONFIG_GICV3)
  71 + /*
  72 + * Initialize ReDistributor
  73 + * x0: ReDistributor Base
  74 + */
  75 + mrs x10, mpidr_el1
  76 + lsr x9, x10, #32
  77 + bfi x10, x9, #24, #8 /* w10 is aff3:aff2:aff1:aff0 */
  78 + mov x9, x0
  79 +1: ldr x11, [x9, GICR_TYPER]
  80 + lsr x11, x11, #32 /* w11 is aff3:aff2:aff1:aff0 */
  81 + cmp w10, w11
  82 + b.eq 2f
  83 + add x9, x9, #(2 << 16)
  84 + b 1b
  85 +
  86 + /* x9: ReDistributor Base Address of Current CPU */
  87 +2: mov w10, #~0x2
  88 + ldr w11, [x9, GICR_WAKER]
  89 + and w11, w11, w10 /* Clear ProcessorSleep */
  90 + str w11, [x9, GICR_WAKER]
  91 + dsb st
  92 + isb
  93 +3: ldr w10, [x9, GICR_WAKER]
  94 + tbnz w10, #2, 3b /* Wait Children be Alive */
  95 +
  96 + add x10, x9, #(1 << 16) /* SGI_Base */
  97 + mov w11, #~0
  98 + str w11, [x10, GICR_IGROUPRn]
  99 + str wzr, [x10, GICR_IGROUPMODRn] /* SGIs|PPIs Group1NS */
  100 + mov w11, #0x1 /* Enable SGI 0 */
  101 + str w11, [x10, GICR_ISENABLERn]
  102 +
  103 + /* Initialize Cpu Interface */
  104 + mrs x10, ICC_SRE_EL3
  105 + orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */
  106 + /* Allow EL2 access to ICC_SRE_EL2 */
  107 + msr ICC_SRE_EL3, x10
  108 + isb
  109 +
  110 + mrs x10, ICC_SRE_EL2
  111 + orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */
  112 + /* Allow EL1 access to ICC_SRE_EL1 */
  113 + msr ICC_SRE_EL2, x10
  114 + isb
  115 +
  116 + mov x10, #0x3 /* EnableGrp1NS | EnableGrp1S */
  117 + msr ICC_IGRPEN1_EL3, x10
  118 + isb
  119 +
  120 + msr ICC_CTLR_EL3, xzr
  121 + isb
  122 +
  123 + msr ICC_CTLR_EL1, xzr /* NonSecure ICC_CTLR_EL1 */
  124 + isb
  125 +
  126 + mov x10, #0x1 << 7 /* Non-Secure access to ICC_PMR_EL1 */
  127 + msr ICC_PMR_EL1, x10
  128 + isb
  129 +#elif defined(CONFIG_GICV2)
  130 + /*
  131 + * Initialize SGIs and PPIs
  132 + * x0: Distributor Base
  133 + * x1: Cpu Interface Base
  134 + */
  135 + mov w9, #~0 /* Config SGIs and PPIs as Grp1 */
  136 + str w9, [x0, GICD_IGROUPRn] /* GICD_IGROUPR0 */
  137 + mov w9, #0x1 /* Enable SGI 0 */
  138 + str w9, [x0, GICD_ISENABLERn]
  139 +
  140 + /* Initialize Cpu Interface */
  141 + mov w9, #0x1e7 /* Disable IRQ/FIQ Bypass & */
  142 + /* Enable Ack Group1 Interrupt & */
  143 + /* EnableGrp0 & EnableGrp1 */
  144 + str w9, [x1, GICC_CTLR] /* Secure GICC_CTLR */
  145 +
  146 + mov w9, #0x1 << 7 /* Non-Secure access to GICC_PMR */
  147 + str w9, [x1, GICC_PMR]
  148 +#endif
  149 + ret
  150 +ENDPROC(gic_init_secure_percpu)
  151 +
  152 +
  153 +/*************************************************************************
  154 + * For Gicv2:
  155 + * void gic_kick_secondary_cpus(DistributorBase);
  156 + * For Gicv3:
  157 + * void gic_kick_secondary_cpus(void);
  158 + *
  159 + *************************************************************************/
  160 +ENTRY(gic_kick_secondary_cpus)
  161 +#if defined(CONFIG_GICV3)
  162 + mov x9, #(1 << 40)
  163 + msr ICC_ASGI1R_EL1, x9
  164 + isb
  165 +#elif defined(CONFIG_GICV2)
  166 + mov w9, #0x8000
  167 + movk w9, #0x100, lsl #16
  168 + str w9, [x0, GICD_SGIR]
  169 +#endif
  170 + ret
  171 +ENDPROC(gic_kick_secondary_cpus)
  172 +
  173 +
  174 +/*************************************************************************
  175 + * For Gicv2:
  176 + * void gic_wait_for_interrupt(CpuInterfaceBase);
  177 + * For Gicv3:
  178 + * void gic_wait_for_interrupt(void);
  179 + *
  180 + * Wait for SGI 0 from master.
  181 + *
  182 + *************************************************************************/
  183 +ENTRY(gic_wait_for_interrupt)
  184 +0: wfi
  185 +#if defined(CONFIG_GICV3)
  186 + mrs x9, ICC_IAR1_EL1
  187 + msr ICC_EOIR1_EL1, x9
  188 +#elif defined(CONFIG_GICV2)
  189 + ldr w9, [x0, GICC_AIAR]
  190 + str w9, [x0, GICC_AEOIR]
  191 +#endif
  192 + cbnz w9, 0b
  193 + ret
  194 +ENDPROC(gic_wait_for_interrupt)
include/configs/vexpress_aemv8a.h
... ... @@ -12,6 +12,8 @@
12 12  
13 13 #define CONFIG_REMAKE_ELF
14 14  
  15 +#define CONFIG_GICV3
  16 +
15 17 /*#define CONFIG_ARMV8_SWITCH_TO_EL1*/
16 18  
17 19 /*#define CONFIG_SYS_GENERIC_BOARD*/
18 20  
... ... @@ -93,8 +95,13 @@
93 95 #define COUNTER_FREQUENCY (0x1800000) /* 24MHz */
94 96  
95 97 /* Generic Interrupt Controller Definitions */
  98 +#ifdef CONFIG_GICV3
  99 +#define GICD_BASE (0x2f000000)
  100 +#define GICR_BASE (0x2f100000)
  101 +#else
96 102 #define GICD_BASE (0x2C001000)
97 103 #define GICC_BASE (0x2C002000)
  104 +#endif
98 105  
99 106 #define CONFIG_SYS_MEMTEST_START V2M_BASE
100 107 #define CONFIG_SYS_MEMTEST_END (V2M_BASE + 0x80000000)