2021-01-28 07:05:24 +00:00
|
|
|
/* SPDX-License-Identifier: MIT */
|
|
|
|
|
|
|
|
#include "smp.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
#define CPU_START_BASE 0x23b754000L
|
|
|
|
#define RVBAR_BASE 0x210050000L
|
|
|
|
|
|
|
|
struct spin_table {
|
|
|
|
u64 flag;
|
|
|
|
u64 target;
|
|
|
|
};
|
|
|
|
|
|
|
|
void *_reset_stack;
|
|
|
|
|
|
|
|
u8 secondary_stacks[MAX_CPUS][0x8000] ALIGNED(64);
|
|
|
|
|
|
|
|
int target_cpu;
|
|
|
|
struct spin_table spin_table[MAX_CPUS];
|
|
|
|
|
|
|
|
extern u8 _vectors_start[0];
|
|
|
|
|
|
|
|
void smp_secondary_entry(void)
|
|
|
|
{
|
2021-01-28 12:59:55 +00:00
|
|
|
struct spin_table *me = &spin_table[target_cpu];
|
|
|
|
sysop("dmb sy");
|
|
|
|
me->flag = 1;
|
2021-01-28 07:05:24 +00:00
|
|
|
sysop("dmb sy");
|
|
|
|
u64 target;
|
|
|
|
while (1) {
|
2021-01-28 12:59:55 +00:00
|
|
|
while (!(target = me->target)) {
|
2021-01-28 07:05:24 +00:00
|
|
|
sysop("wfe");
|
|
|
|
}
|
|
|
|
sysop("dmb sy");
|
2021-01-28 12:59:55 +00:00
|
|
|
me->target = 0;
|
|
|
|
me->flag++;
|
2021-01-28 07:05:24 +00:00
|
|
|
sysop("dmb sy");
|
|
|
|
((void (*)(void))target)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void smp_start_cpu(int index, int cluster, int core)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int cpu_id = (cluster << 4) | core;
|
|
|
|
|
|
|
|
printf("Starting CPU %d (%d:%d)... ", index, cluster, core);
|
|
|
|
|
|
|
|
spin_table[index].flag = 0;
|
|
|
|
|
|
|
|
target_cpu = index;
|
|
|
|
_reset_stack = secondary_stacks[index];
|
|
|
|
|
|
|
|
sysop("dmb sy");
|
|
|
|
|
|
|
|
write64(RVBAR_BASE + (cpu_id << 20), (u64)_vectors_start);
|
|
|
|
|
|
|
|
if (cluster == 0) {
|
|
|
|
write32(CPU_START_BASE + 0x8, 1 << core);
|
|
|
|
} else {
|
|
|
|
write32(CPU_START_BASE + 0xc, 1 << core);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 500; i++) {
|
|
|
|
sysop("dmb ld");
|
|
|
|
if (spin_table[index].flag)
|
|
|
|
break;
|
|
|
|
udelay(1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= 500)
|
|
|
|
printf("Failed!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void smp_start_secondaries(void)
|
|
|
|
{
|
|
|
|
printf("Starting secondary CPUs...\n");
|
|
|
|
|
|
|
|
smp_start_cpu(1, 0, 1);
|
|
|
|
smp_start_cpu(2, 0, 2);
|
|
|
|
smp_start_cpu(3, 0, 3);
|
|
|
|
smp_start_cpu(4, 1, 0);
|
|
|
|
smp_start_cpu(5, 1, 1);
|
|
|
|
smp_start_cpu(6, 1, 2);
|
|
|
|
smp_start_cpu(7, 1, 3);
|
|
|
|
}
|