blob: 45cf8cd1faf54d9c70d796bc092742b921c50ba6 [file] [log] [blame] [edit]
/*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
* Copyright: Linux Kernel team
* SPDX-License-Identifier: GPL-2.0-only
*
* The code in here is derived from the Linux kernel
*/
#include <autoconf.h>
#include <elfloader/gen_config.h>
#include <printf.h>
#include <armv/machine.h>
#include <scu.h>
#include <abort.h>
#if CONFIG_MAX_NUM_NODES > 1
VISIBLE volatile word_t smp_aps_index = 1;
/* System Reset Controller base address */
#define SRC_BASE 0x30390000
#define GPC_BASE 0x303a0000
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
#define BP_SRC_SCR_CORE1_RST 14
#define BP_SRC_SCR_CORE1_ENABLE 22
#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
#define GPC_PGC_C1 0x840
#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
#define SRC_A7RCR1 0x008
#define SRC_GPR1_V2 0x074
#define REG(base,offset) (*(volatile unsigned int*)(((void *)(base))+(offset)))
void imx_non_boot(void);
static void src_init(void)
{
unsigned int val;
val = REG(SRC_BASE, SRC_SCR);
val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
REG(SRC_BASE, SRC_SCR) = val;
}
static void gpc_core1_up(void)
{
unsigned int val = REG(GPC_BASE, GPC_CPU_PGC_SW_PUP_REQ);
REG(GPC_BASE, GPC_PGC_C1) = 1;
val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
REG(GPC_BASE, GPC_CPU_PGC_SW_PUP_REQ) = val;
while ((REG(GPC_BASE, GPC_CPU_PGC_SW_PUP_REQ) & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7) != 0);
REG(GPC_BASE, GPC_PGC_C1) = 0;
}
static void src_enable_cpu(int cpu)
{
unsigned int mask, val;
gpc_core1_up();
mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
val = REG(SRC_BASE, SRC_A7RCR1);
val |= mask;
REG(SRC_BASE, SRC_A7RCR1) = val;
}
static void src_set_cpu_jump(int cpu, unsigned int jump_addr)
{
REG(SRC_BASE, SRC_GPR1_V2 + cpu * 8) = (unsigned int)jump_addr;
dsb();
}
void init_cpus(void)
{
unsigned int i, num;
src_init();
/* get core count from L2CTLR */
asm volatile("mrc p15, 1, %0, c9, c0, 2": "=r"(num));
num = ((num >> 24) & 0x3) + 1;
if (num > CONFIG_MAX_NUM_NODES) {
num = CONFIG_MAX_NUM_NODES;
} else if (num < CONFIG_MAX_NUM_NODES) {
printf("Error: Unsupported number of CPUs! This platform has %u CPUs, while static configuration provided is %u CPUs\n",
num, CONFIG_MAX_NUM_NODES);
abort();
}
printf("Bringing up %d other cpus\n", num - 1);
for (i = 1; i < num; i++) {
src_set_cpu_jump(i, (unsigned int)imx_non_boot);
src_enable_cpu(i);
}
}
#endif /* CONFIG_MAX_NUM_NODES */