Created
August 18, 2019 15:19
-
-
Save tansly/50e1b74235cc9a40b281e5488bfa031e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-2.0-or-later | |
/* | |
* Actions Semi Leopard | |
* | |
* This file is based on arm realview smp platform. | |
* | |
* Copyright 2012 Actions Semi Inc. | |
* Author: Actions Semi, Inc. | |
* | |
* Copyright (c) 2017 Andreas Färber | |
*/ | |
#include <linux/delay.h> | |
#include <linux/io.h> | |
#include <linux/of.h> | |
#include <linux/of_address.h> | |
#include <linux/smp.h> | |
#include <linux/soc/actions/owl-sps.h> | |
#include <asm/cacheflush.h> | |
#include <asm/smp_plat.h> | |
#include <asm/smp_scu.h> | |
#define OWL_CPU1_ADDR 0x50 | |
#define OWL_CPU1_FLAG 0x5c | |
#define OWL_CPUx_FLAG_BOOT 0x55aa | |
#define OWL_SPS_PG_CTL_PWR_CPU2 BIT(5) | |
#define OWL_SPS_PG_CTL_PWR_CPU3 BIT(6) | |
#define OWL_SPS_PG_CTL_ACK_CPU2 BIT(21) | |
#define OWL_SPS_PG_CTL_ACK_CPU3 BIT(22) | |
static void __iomem *scu_base_addr; | |
static void __iomem *sps_base_addr; | |
static void __iomem *timer_base_addr; | |
static int ncores; | |
static int s500_wakeup_secondary(unsigned int cpu) | |
{ | |
int ret; | |
if (cpu > 3) | |
return -EINVAL; | |
/* The generic PM domain driver is not available this early. */ | |
switch (cpu) { | |
case 2: | |
ret = owl_sps_set_pg(sps_base_addr, | |
OWL_SPS_PG_CTL_PWR_CPU2, | |
OWL_SPS_PG_CTL_ACK_CPU2, true); | |
if (ret) | |
return ret; | |
break; | |
case 3: | |
ret = owl_sps_set_pg(sps_base_addr, | |
OWL_SPS_PG_CTL_PWR_CPU3, | |
OWL_SPS_PG_CTL_ACK_CPU3, true); | |
if (ret) | |
return ret; | |
break; | |
} | |
/* wait for CPUx to run to WFE instruction */ | |
udelay(200); | |
writel(__pa_symbol(secondary_startup), | |
timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4); | |
writel(OWL_CPUx_FLAG_BOOT, | |
timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4); | |
dsb_sev(); | |
mb(); | |
return 0; | |
} | |
static int s500_smp_boot_secondary(unsigned int cpu, struct task_struct *idle) | |
{ | |
int ret; | |
ret = s500_wakeup_secondary(cpu); | |
if (ret) | |
return ret; | |
udelay(10); | |
smp_send_reschedule(cpu); | |
writel(0, timer_base_addr + OWL_CPU1_ADDR + (cpu - 1) * 4); | |
writel(0, timer_base_addr + OWL_CPU1_FLAG + (cpu - 1) * 4); | |
return 0; | |
} | |
static void __init s500_smp_prepare_cpus(unsigned int max_cpus) | |
{ | |
struct device_node *node; | |
node = of_find_compatible_node(NULL, NULL, "actions,s500-timer"); | |
if (!node) { | |
pr_err("%s: missing timer\n", __func__); | |
return; | |
} | |
timer_base_addr = of_iomap(node, 0); | |
if (!timer_base_addr) { | |
pr_err("%s: could not map timer registers\n", __func__); | |
return; | |
} | |
node = of_find_compatible_node(NULL, NULL, "actions,s500-sps"); | |
if (!node) { | |
pr_err("%s: missing sps\n", __func__); | |
return; | |
} | |
sps_base_addr = of_iomap(node, 0); | |
if (!sps_base_addr) { | |
pr_err("%s: could not map sps registers\n", __func__); | |
return; | |
} | |
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { | |
node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); | |
if (!node) { | |
pr_err("%s: missing scu\n", __func__); | |
return; | |
} | |
scu_base_addr = of_iomap(node, 0); | |
if (!scu_base_addr) { | |
pr_err("%s: could not map scu registers\n", __func__); | |
return; | |
} | |
/* | |
* While the number of cpus is gathered from dt, also get the | |
* number of cores from the scu to verify this value when | |
* booting the cores. | |
*/ | |
ncores = scu_get_core_count(scu_base_addr); | |
pr_debug("%s: ncores %d\n", __func__, ncores); | |
scu_enable(scu_base_addr); | |
} | |
} | |
static const struct smp_operations s500_smp_ops __initconst = { | |
.smp_prepare_cpus = s500_smp_prepare_cpus, | |
.smp_boot_secondary = s500_smp_boot_secondary, | |
}; | |
CPU_METHOD_OF_DECLARE(s500_smp, "actions,s500-smp", &s500_smp_ops); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment