u-boot/arch/arm/mach-uniphier/arm32/psci.c
Tom Rini 83d290c56f SPDX: Convert all of our single license tags to Linux Kernel style
When U-Boot started using SPDX tags we were among the early adopters and
there weren't a lot of other examples to borrow from.  So we picked the
area of the file that usually had a full license text and replaced it
with an appropriate SPDX-License-Identifier: entry.  Since then, the
Linux Kernel has adopted SPDX tags and they place it as the very first
line in a file (except where shebangs are used, then it's second line)
and with slightly different comment styles than us.

In part due to community overlap, in part due to better tag visibility
and in part for other minor reasons, switch over to that style.

This commit changes all instances where we have a single declared
license in the tag as both the before and after are identical in tag
contents.  There's also a few places where I found we did not have a tag
and have introduced one.

Signed-off-by: Tom Rini <trini@konsulko.com>
2018-05-07 09:34:12 -04:00

158 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Socionext Inc.
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
*/
#include <common.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/psci.h>
#include <linux/sizes.h>
#include <asm/processor.h>
#include <asm/psci.h>
#include <asm/secure.h>
#include "../debug.h"
#include "../soc-info.h"
#include "arm-mpcore.h"
#include "cache-uniphier.h"
#define UNIPHIER_SMPCTRL_ROM_RSV2 0x59801208
void uniphier_smp_trampoline(void);
void uniphier_smp_trampoline_end(void);
u32 uniphier_smp_booted[CONFIG_ARMV7_PSCI_NR_CPUS];
static int uniphier_get_nr_cpus(void)
{
switch (uniphier_get_soc_id()) {
case UNIPHIER_PRO4_ID:
case UNIPHIER_PRO5_ID:
return 2;
case UNIPHIER_PXS2_ID:
case UNIPHIER_LD6B_ID:
return 4;
default:
return 1;
}
}
static void uniphier_smp_kick_all_cpus(void)
{
const u32 target_ways = BIT(0);
size_t trmp_size;
u32 trmp_src = (unsigned long)uniphier_smp_trampoline;
u32 trmp_src_end = (unsigned long)uniphier_smp_trampoline_end;
u32 trmp_dest, trmp_dest_end;
int nr_cpus, i;
int timeout = 1000;
nr_cpus = uniphier_get_nr_cpus();
if (nr_cpus == 1)
return;
for (i = 0; i < nr_cpus; i++) /* lock ways for all CPUs */
uniphier_cache_set_active_ways(i, 0);
uniphier_cache_inv_way(target_ways);
uniphier_cache_enable();
/* copy trampoline code */
uniphier_cache_prefetch_range(trmp_src, trmp_src_end, target_ways);
trmp_size = trmp_src_end - trmp_src;
trmp_dest = trmp_src & (SZ_64K - 1);
trmp_dest += SZ_1M - SZ_64K * 2;
trmp_dest_end = trmp_dest + trmp_size;
uniphier_cache_touch_range(trmp_dest, trmp_dest_end, target_ways);
writel(trmp_dest, UNIPHIER_SMPCTRL_ROM_RSV2);
asm("dsb ishst\n" /* Ensure the write to ROM_RSV2 is visible */
"sev"); /* Bring up all secondary CPUs from Boot ROM into U-Boot */
while (--timeout) {
int all_booted = 1;
for (i = 1; i < nr_cpus; i++)
if (!uniphier_smp_booted[i])
all_booted = 0;
if (all_booted)
break;
udelay(1);
/* barrier here because uniphier_smp_booted[] may be updated */
cpu_relax();
}
if (!timeout)
pr_warn("warning: some of secondary CPUs may not boot\n");
uniphier_cache_disable();
}
void psci_board_init(void)
{
unsigned long scu_base;
u32 scu_ctrl, tmp;
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (scu_base));
scu_ctrl = readl(scu_base + 0x30);
if (!(scu_ctrl & 1))
writel(scu_ctrl | 0x1, scu_base + 0x30);
scu_ctrl = readl(scu_base + SCU_CTRL);
scu_ctrl |= SCU_ENABLE | SCU_STANDBY_ENABLE;
writel(scu_ctrl, scu_base + SCU_CTRL);
tmp = readl(scu_base + SCU_SNSAC);
tmp |= 0xfff;
writel(tmp, scu_base + SCU_SNSAC);
uniphier_smp_kick_all_cpus();
}
void psci_arch_init(void)
{
u32 actlr;
asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr));
actlr |= 0x41; /* set SMP and FW bits */
asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
}
u32 uniphier_psci_holding_pen_release __secure_data = 0xffffffff;
int __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point)
{
u32 cpu = cpuid & 0xff;
debug_puts("[U-Boot PSCI] psci_cpu_on: cpuid=");
debug_puth(cpuid);
debug_puts(", entry_point=");
debug_puth(entry_point);
debug_puts("\n");
psci_save_target_pc(cpu, entry_point);
/* We assume D-cache is off, so do not call flush_dcache() here */
uniphier_psci_holding_pen_release = cpu;
/* Send an event to wake up the secondary CPU. */
asm("dsb ishst\n"
"sev");
return PSCI_RET_SUCCESS;
}
void __secure psci_system_reset(u32 function_id)
{
reset_cpu(0);
}