mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-24 15:43:11 +00:00
smp: Added A7-A11 start support
This includes: - EL3 handling - "Slow" IPI support - New start offsets Signed-off-by: Nick Chan <towinchenmi@gmail.com>
This commit is contained in:
parent
32ca84c769
commit
cb0ceb4ee8
5 changed files with 79 additions and 10 deletions
|
@ -201,6 +201,11 @@ void aic_set_sw(int irq, bool active)
|
|||
MASK_BIT(irq));
|
||||
}
|
||||
|
||||
void aic_write(u32 reg, u32 val)
|
||||
{
|
||||
write32(aic->base + reg, val);
|
||||
}
|
||||
|
||||
uint32_t aic_ack(void)
|
||||
{
|
||||
return read32(aic->base + aic->regs.event);
|
||||
|
|
|
@ -39,6 +39,7 @@ extern struct aic *aic;
|
|||
|
||||
void aic_init(void);
|
||||
void aic_set_sw(int irq, bool active);
|
||||
void aic_write(u32 reg, u32 val);
|
||||
uint32_t aic_ack(void);
|
||||
|
||||
#endif
|
||||
|
|
50
src/smp.c
50
src/smp.c
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "smp.h"
|
||||
#include "adt.h"
|
||||
#include "aic.h"
|
||||
#include "aic_regs.h"
|
||||
#include "cpu_regs.h"
|
||||
#include "malloc.h"
|
||||
#include "pmgr.h"
|
||||
|
@ -10,6 +12,8 @@
|
|||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define CPU_START_OFF_S5L8960X 0x30000
|
||||
#define CPU_START_OFF_S8000 0xd4000
|
||||
#define CPU_START_OFF_T8103 0x54000
|
||||
#define CPU_START_OFF_T8112 0x34000
|
||||
#define CPU_START_OFF_T6020 0x28000
|
||||
|
@ -28,11 +32,14 @@ struct spin_table {
|
|||
};
|
||||
|
||||
void *_reset_stack;
|
||||
void *_reset_stack_el1;
|
||||
|
||||
#define DUMMY_STACK_SIZE 0x1000
|
||||
u8 dummy_stack[DUMMY_STACK_SIZE];
|
||||
u8 dummy_stack[DUMMY_STACK_SIZE]; // Highest EL
|
||||
u8 dummy_stack_el1[DUMMY_STACK_SIZE]; // EL1 stack if EL3 exists
|
||||
|
||||
u8 *secondary_stacks[MAX_CPUS] = {dummy_stack};
|
||||
u8 *secondary_stacks_el3[MAX_EL3_CPUS];
|
||||
|
||||
static bool wfe_mode = false;
|
||||
|
||||
|
@ -63,14 +70,28 @@ void smp_secondary_entry(void)
|
|||
me->flag = 1;
|
||||
sysop("dmb sy");
|
||||
u64 target;
|
||||
if (!cpufeat_fast_ipi)
|
||||
aic_write(AIC_IPI_MASK_SET, AIC_IPI_SELF); // we only use the "other" IPI
|
||||
|
||||
while (1) {
|
||||
while (!(target = me->target)) {
|
||||
if (wfe_mode) {
|
||||
sysop("wfe");
|
||||
} else {
|
||||
if (!supports_arch_retention()) {
|
||||
// A7 - A11 does not support state retention across deep WFI
|
||||
// i.e. CPU always ends up at rvbar after deep WFI
|
||||
sysop("wfi");
|
||||
} else {
|
||||
deep_wfi();
|
||||
}
|
||||
if (cpufeat_fast_ipi) {
|
||||
msr(SYS_IMP_APL_IPI_SR_EL1, 1);
|
||||
} else {
|
||||
aic_ack(); // Actually read IPI reason
|
||||
aic_write(AIC_IPI_ACK, AIC_IPI_OTHER);
|
||||
aic_write(AIC_IPI_MASK_CLR, AIC_IPI_OTHER);
|
||||
}
|
||||
}
|
||||
sysop("isb");
|
||||
}
|
||||
|
@ -92,6 +113,9 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u
|
|||
if (index >= MAX_CPUS)
|
||||
return;
|
||||
|
||||
if (has_el3() && index >= MAX_EL3_CPUS)
|
||||
return;
|
||||
|
||||
if (spin_table[index].flag)
|
||||
return;
|
||||
|
||||
|
@ -101,6 +125,11 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u
|
|||
|
||||
target_cpu = index;
|
||||
secondary_stacks[index] = memalign(0x4000, SECONDARY_STACK_SIZE);
|
||||
if (has_el3()) {
|
||||
secondary_stacks_el3[index] = memalign(0x4000, SECONDARY_STACK_SIZE);
|
||||
_reset_stack = secondary_stacks_el3[index] + SECONDARY_STACK_SIZE; // EL3
|
||||
_reset_stack_el1 = secondary_stacks[index] + SECONDARY_STACK_SIZE; // EL1
|
||||
} else
|
||||
_reset_stack = secondary_stacks[index] + SECONDARY_STACK_SIZE;
|
||||
|
||||
sysop("dmb sy");
|
||||
|
@ -129,6 +158,7 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u
|
|||
printf(" Started.\n");
|
||||
|
||||
_reset_stack = dummy_stack + DUMMY_STACK_SIZE;
|
||||
_reset_stack_el1 = dummy_stack_el1 + DUMMY_STACK_SIZE;
|
||||
}
|
||||
|
||||
static void smp_stop_cpu(int index, int die, int cluster, int core, u64 impl, u64 cpu_start_base,
|
||||
|
@ -202,6 +232,20 @@ void smp_start_secondaries(void)
|
|||
memset(cpu_nodes, 0, sizeof(cpu_nodes));
|
||||
|
||||
switch (chip_id) {
|
||||
case S5L8960X:
|
||||
case T7000:
|
||||
case T7001:
|
||||
cpu_start_off = CPU_START_OFF_S5L8960X;
|
||||
break;
|
||||
case S8000:
|
||||
case S8001:
|
||||
case S8003:
|
||||
case T8010:
|
||||
case T8011:
|
||||
case T8012:
|
||||
case T8015:
|
||||
cpu_start_off = CPU_START_OFF_S8000;
|
||||
break;
|
||||
case T8103:
|
||||
case T6000:
|
||||
case T6001:
|
||||
|
@ -324,7 +368,11 @@ void smp_send_ipi(int cpu)
|
|||
return;
|
||||
|
||||
u64 mpidr = spin_table[cpu].mpidr;
|
||||
if (cpufeat_fast_ipi) {
|
||||
msr(SYS_IMP_APL_IPI_RR_GLOBAL_EL1, (mpidr & 0xff) | ((mpidr & 0xff00) << 8));
|
||||
} else {
|
||||
aic_write(AIC_IPI_SEND, AIC_IPI_SEND_CPU(cpu));
|
||||
}
|
||||
}
|
||||
|
||||
void smp_call4(int cpu, void *func, u64 arg0, u64 arg1, u64 arg2, u64 arg3)
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
#include "utils.h"
|
||||
|
||||
#define MAX_CPUS 24
|
||||
#define MAX_EL3_CPUS 4
|
||||
|
||||
#define SECONDARY_STACK_SIZE 0x10000
|
||||
extern u8 *secondary_stacks[MAX_CPUS];
|
||||
extern u8 *secondary_stacks_el3[MAX_EL3_CPUS];
|
||||
|
||||
void smp_secondary_entry(void);
|
||||
|
||||
|
|
13
src/start.S
13
src/start.S
|
@ -161,9 +161,22 @@ cpu_reset:
|
|||
bl debug_putc
|
||||
|
||||
mov x0, sp
|
||||
|
||||
mrs x8, CurrentEL
|
||||
cmp x8, #0xc
|
||||
beq cpu_reset_el3
|
||||
|
||||
bl _cpu_reset_c
|
||||
b .
|
||||
|
||||
cpu_reset_el3:
|
||||
bl _cpu_reset_c
|
||||
adrp x6, _reset_stack_el1
|
||||
add x6, x6, :lo12:_reset_stack_el1
|
||||
ldr x6, [x6]
|
||||
mov x0, x6
|
||||
adr x7, _cpu_reset_c
|
||||
|
||||
el3_eret_to_el1:
|
||||
adr x8, _vectors_start
|
||||
msr sctlr_el1, xzr
|
||||
|
|
Loading…
Reference in a new issue