mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-28 09:20:17 +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));
|
MASK_BIT(irq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aic_write(u32 reg, u32 val)
|
||||||
|
{
|
||||||
|
write32(aic->base + reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t aic_ack(void)
|
uint32_t aic_ack(void)
|
||||||
{
|
{
|
||||||
return read32(aic->base + aic->regs.event);
|
return read32(aic->base + aic->regs.event);
|
||||||
|
|
|
@ -39,6 +39,7 @@ extern struct aic *aic;
|
||||||
|
|
||||||
void aic_init(void);
|
void aic_init(void);
|
||||||
void aic_set_sw(int irq, bool active);
|
void aic_set_sw(int irq, bool active);
|
||||||
|
void aic_write(u32 reg, u32 val);
|
||||||
uint32_t aic_ack(void);
|
uint32_t aic_ack(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
50
src/smp.c
50
src/smp.c
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
#include "adt.h"
|
#include "adt.h"
|
||||||
|
#include "aic.h"
|
||||||
|
#include "aic_regs.h"
|
||||||
#include "cpu_regs.h"
|
#include "cpu_regs.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "pmgr.h"
|
#include "pmgr.h"
|
||||||
|
@ -10,6 +12,8 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utils.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_T8103 0x54000
|
||||||
#define CPU_START_OFF_T8112 0x34000
|
#define CPU_START_OFF_T8112 0x34000
|
||||||
#define CPU_START_OFF_T6020 0x28000
|
#define CPU_START_OFF_T6020 0x28000
|
||||||
|
@ -28,11 +32,14 @@ struct spin_table {
|
||||||
};
|
};
|
||||||
|
|
||||||
void *_reset_stack;
|
void *_reset_stack;
|
||||||
|
void *_reset_stack_el1;
|
||||||
|
|
||||||
#define DUMMY_STACK_SIZE 0x1000
|
#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[MAX_CPUS] = {dummy_stack};
|
||||||
|
u8 *secondary_stacks_el3[MAX_EL3_CPUS];
|
||||||
|
|
||||||
static bool wfe_mode = false;
|
static bool wfe_mode = false;
|
||||||
|
|
||||||
|
@ -63,14 +70,28 @@ void smp_secondary_entry(void)
|
||||||
me->flag = 1;
|
me->flag = 1;
|
||||||
sysop("dmb sy");
|
sysop("dmb sy");
|
||||||
u64 target;
|
u64 target;
|
||||||
|
if (!cpufeat_fast_ipi)
|
||||||
|
aic_write(AIC_IPI_MASK_SET, AIC_IPI_SELF); // we only use the "other" IPI
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (!(target = me->target)) {
|
while (!(target = me->target)) {
|
||||||
if (wfe_mode) {
|
if (wfe_mode) {
|
||||||
sysop("wfe");
|
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 {
|
} else {
|
||||||
deep_wfi();
|
deep_wfi();
|
||||||
|
}
|
||||||
|
if (cpufeat_fast_ipi) {
|
||||||
msr(SYS_IMP_APL_IPI_SR_EL1, 1);
|
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");
|
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)
|
if (index >= MAX_CPUS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (has_el3() && index >= MAX_EL3_CPUS)
|
||||||
|
return;
|
||||||
|
|
||||||
if (spin_table[index].flag)
|
if (spin_table[index].flag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -101,6 +125,11 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u
|
||||||
|
|
||||||
target_cpu = index;
|
target_cpu = index;
|
||||||
secondary_stacks[index] = memalign(0x4000, SECONDARY_STACK_SIZE);
|
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;
|
_reset_stack = secondary_stacks[index] + SECONDARY_STACK_SIZE;
|
||||||
|
|
||||||
sysop("dmb sy");
|
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");
|
printf(" Started.\n");
|
||||||
|
|
||||||
_reset_stack = dummy_stack + DUMMY_STACK_SIZE;
|
_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,
|
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));
|
memset(cpu_nodes, 0, sizeof(cpu_nodes));
|
||||||
|
|
||||||
switch (chip_id) {
|
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 T8103:
|
||||||
case T6000:
|
case T6000:
|
||||||
case T6001:
|
case T6001:
|
||||||
|
@ -324,7 +368,11 @@ void smp_send_ipi(int cpu)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u64 mpidr = spin_table[cpu].mpidr;
|
u64 mpidr = spin_table[cpu].mpidr;
|
||||||
|
if (cpufeat_fast_ipi) {
|
||||||
msr(SYS_IMP_APL_IPI_RR_GLOBAL_EL1, (mpidr & 0xff) | ((mpidr & 0xff00) << 8));
|
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)
|
void smp_call4(int cpu, void *func, u64 arg0, u64 arg1, u64 arg2, u64 arg3)
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define MAX_CPUS 24
|
#define MAX_CPUS 24
|
||||||
|
#define MAX_EL3_CPUS 4
|
||||||
|
|
||||||
#define SECONDARY_STACK_SIZE 0x10000
|
#define SECONDARY_STACK_SIZE 0x10000
|
||||||
extern u8 *secondary_stacks[MAX_CPUS];
|
extern u8 *secondary_stacks[MAX_CPUS];
|
||||||
|
extern u8 *secondary_stacks_el3[MAX_EL3_CPUS];
|
||||||
|
|
||||||
void smp_secondary_entry(void);
|
void smp_secondary_entry(void);
|
||||||
|
|
||||||
|
|
13
src/start.S
13
src/start.S
|
@ -161,9 +161,22 @@ cpu_reset:
|
||||||
bl debug_putc
|
bl debug_putc
|
||||||
|
|
||||||
mov x0, sp
|
mov x0, sp
|
||||||
|
|
||||||
|
mrs x8, CurrentEL
|
||||||
|
cmp x8, #0xc
|
||||||
|
beq cpu_reset_el3
|
||||||
|
|
||||||
bl _cpu_reset_c
|
bl _cpu_reset_c
|
||||||
b .
|
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:
|
el3_eret_to_el1:
|
||||||
adr x8, _vectors_start
|
adr x8, _vectors_start
|
||||||
msr sctlr_el1, xzr
|
msr sctlr_el1, xzr
|
||||||
|
|
Loading…
Reference in a new issue