ipq40x: Added multicore support

-Device IO commands are not supported
-CPU down is supported by waiting in loop
-Need reboot to execute bootipq command

Change-Id: Id10eef0c8e5feb636716461c58ba1640dfe46658
Signed-off-by: Santan Kumar <santank@codeaurora.org>
This commit is contained in:
Santan Kumar 2018-04-27 12:00:30 +05:30 committed by Gerrit - the friendly Code Review server
parent 8d9a453c47
commit b7af9b06d2
4 changed files with 181 additions and 2 deletions

View file

@ -13,9 +13,61 @@
#include <asm/system.h>
#include <linux/linkage.h>
ENTRY(ak_secondary_cpu_reinit)
ENTRY(dk_secondary_cpu_reinit)
mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */
and r1, r0, #0xf /* return CPU ID in cluster */
sub r0, r1, #1
/* Now r1 has the cpu number,
* this will serve as index to "struct cpu_entry_arg"
* struct cpu_entry_arg {
* void *stack_ptr; +0 1c 38 54
* volatile void *gd_ptr; +4 20 3c
* void *arg_ptr; +8 24 40
* int cpu_up; +0xc 28 44
* int cmd_complete; +0x10 2c 48
* int cmd_result; +0x14 30 4c
* void *stack_top_ptr; +0x18 34 50
* +0x1c (next entry in core[])
* };
*/
ldr r4, =globl_core_array
mov r3, #0x1c
mul r2, r0, r3
ldr r0, [r4]
add r0, r0, r2
/* For us r0 has the arg structure pointer
struct cpu_entry_arg {
void *stack_ptr;
void *gd_ptr;
void *arg_ptr;
int cpu_up;
int cmd_complete;
int cmd_result;
};
*/
ldr sp, [r0] /* stack_ptr */
bic sp, sp, #7 /* 8-byte alignment required for stack */
/* gd address is always in r9, but if u-boot changes Tomorrow,
* we have to change here. Note :- --> ARM: use r9 for gd
*/
ldr r9, [r0, #0x4]
/* store success in cpu_up */
mov r3, #1
str r3, [r0, #0xc]
add r1, r0, #0x10
add r2, r0, #0x14
ldr r0, [r0, #0x8]
bl secondary_core_entry
self_reloop:
b self_reloop
ENDPROC(ak_secondary_cpu_reinit)
ENDPROC(dk_secondary_cpu_reinit)
ENTRY(dk_secondary_cpu_init)
ENTRY(ak_secondary_cpu_init)
mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */
and r1, r0, #0xf /* return CPU ID in cluster */
and r1, r0, #0xf /* return CPU ID in cluster */
sub r0, r1, #1
/* Now r1 has the cpu number,
* this will serve as index to "struct cpu_entry_arg"
@ -93,6 +145,7 @@ self_loop:
b self_loop
ENDPROC(secondary_cpu_init)
ENDPROC(ak_secondary_cpu_init)
ENDPROC(dk_secondary_cpu_init)
ENTRY(send_event)
dsb
@ -107,6 +160,12 @@ ENTRY(wait_event)
bx r0
ENDPROC(wait_event)
ENTRY(get_cpu_id)
mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */
and r0, r0, #0xf /* return CPU ID in cluster */
bx lr
ENDPROC(get_cpu_id)
.globl globl_core_array
globl_core_array:
.word 0

View file

@ -39,6 +39,12 @@
#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E70
DECLARE_GLOBAL_DATA_PTR;
#define CPU0_APCS_SAW2_VCTL 0x0b089014
#define CPU0_APCS_CPU_PWR_CTL 0x0b088004
#define CPU_APCS_SAW2_VCTL(cpuid) (CPU0_APCS_SAW2_VCTL + (cpuid * 0x10000))
#define CPU_APCS_CPU_PWR_CTL(cpuid) (CPU0_APCS_CPU_PWR_CTL + (cpuid * 0x10000))
#ifndef CONFIG_SDHCI_SUPPORT
qca_mmc mmc_host;
#else
@ -508,5 +514,112 @@ unsigned int get_dts_machid(unsigned int machid)
*/
int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
{
return 0;
}
extern void dk_secondary_cpu_init(void);
extern void dk_secondary_cpu_reinit(void);
/*
* Set the cold/warm boot address for one of the CPU cores.
*/
int scm_set_boot_addr(bool enable_sec_core)
{
int ret;
struct {
unsigned int flags;
unsigned long addr;
} cmd;
if (!enable_sec_core)
return -1;
cmd.addr = (unsigned long)dk_secondary_cpu_init;
cmd.flags = 0xff;
ret = scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
&cmd, sizeof(cmd), NULL, 0);
if (ret) {
printf("--- %s: scm_call failed ret = %d\n", __func__, ret);
}
return ret;
}
int is_secondary_core_off(unsigned int cpuid)
{
return 1;
}
static int secondary_core_already_reset[NR_CPUS];
static int scm_boot_addr_already_set;
extern int get_cpu_id(void);
static volatile int core_var;
volatile void bring_secondary_core_down(unsigned int state)
{
int current_cpu_id;
current_cpu_id = (1 << get_cpu_id());
core_var &= (~current_cpu_id);
while (!(core_var & current_cpu_id)) {
cp_delay();
}
dk_secondary_cpu_reinit();
}
static int kpssv1_release_secondary(unsigned int cpuid)
{
dcache_enable();
writel(0xa4, CPU_APCS_SAW2_VCTL(cpuid));
barrier();
udelay(512);
writel(0x109, CPU_APCS_CPU_PWR_CTL(cpuid));
writel(0x101, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(1);
writel(0x121, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(2);
writel(0x120, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(2);
writel(0x100, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(100);
writel(0x180, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
dcache_disable();
return 0;
}
int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg)
{
int err = 0;
if (!secondary_core_already_reset[cpuid]) {
if (!scm_boot_addr_already_set) {
err = scm_set_boot_addr(true);
core_var = 0;
if (!err) {
scm_boot_addr_already_set = 1;
kpssv1_release_secondary(cpuid);
secondary_core_already_reset[cpuid] = 1;
} else
return err;
} else {
kpssv1_release_secondary(cpuid);
secondary_core_already_reset[cpuid] = 1;
}
} else {
core_var |= (1 << cpuid);
}
return 0;
}

View file

@ -924,6 +924,7 @@ int ipq_get_tz_version(char *version_name, int buf_size)
void forever(void) { while (1); }
extern void ak_secondary_cpu_init(void);
extern void ak_secondary_cpu_reinit(void);
extern void send_event(void);
/*
* Set the cold/warm boot address for one of the CPU cores.
@ -1001,7 +1002,7 @@ extern void wait_event(void (*)(void));
void bring_secondary_core_down(unsigned int state)
{
wait_event(ak_secondary_cpu_init);
wait_event(ak_secondary_cpu_reinit);
}
static int krait_release_secondary(void)

View file

@ -277,6 +277,12 @@ typedef struct {
#define CONFIG_LIB_UUID
#define CONFIG_SMP_CMD_SUPPORT
#ifdef CONFIG_SMP_CMD_SUPPORT
#define NR_CPUS 4
#endif
/*
* CRASH DUMP ENABLE
*/