aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2014-08-07 20:32:58 +0800
committerHaojian Zhuang <haojian.zhuang@linaro.org>2014-08-12 10:29:18 +0800
commite17111dba3e95c258b6c40e39d33e54484b6b457 (patch)
tree11fb5c57ebd23a833cd500d0801ecaa1d6095199
parent730ca5bddfcdb1018a18c287341a778a69bc8ac0 (diff)
ARM: hisi: fix hotplug issuetesting/hotplug-0812
1. fix hotplug issue. 2. move bootwrapper param into new node. Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
-rw-r--r--arch/arm/boot/dts/hip04.dtsi10
-rw-r--r--arch/arm/mach-hisi/platmcpm.c253
2 files changed, 164 insertions, 99 deletions
diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi
index e140c0ffd449..3887d9b6f916 100644
--- a/arch/arm/boot/dts/hip04.dtsi
+++ b/arch/arm/boot/dts/hip04.dtsi
@@ -20,6 +20,11 @@
serial0 = &uart0;
};
+ bootwrapper {
+ compatible = "hisilicon,hip04-bootwrapper";
+ boot-method = <0x10c00000 0x10000>, <0xe0000100 0x1000>;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -208,11 +213,6 @@
sysctrl: sysctrl {
compatible = "hisilicon,sysctrl";
reg = <0x3e00000 0x00100000>;
- relocation-entry = <0xe0000100>;
- relocation-size = <0x1000>;
- bootwrapper-phys = <0x10c00000>;
- bootwrapper-size = <0x10000>;
- bootwrapper-magic = <0xa5a5a5a5>;
};
fabric: fabric {
diff --git a/arch/arm/mach-hisi/platmcpm.c b/arch/arm/mach-hisi/platmcpm.c
index 2bda12b936f9..ceeb913f9581 100644
--- a/arch/arm/mach-hisi/platmcpm.c
+++ b/arch/arm/mach-hisi/platmcpm.c
@@ -8,6 +8,7 @@
*/
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/memblock.h>
#include <linux/of_address.h>
#include <asm/cputype.h>
@@ -52,22 +53,21 @@
#define HIP04_MAX_CPUS_PER_CLUSTER 4
#define POLL_MSEC 10
-#define TIMEOUT_MSEC 1000
-
-struct hip04_secondary_cpu_data {
- u32 bootwrapper_phys;
- u32 bootwrapper_size;
- u32 bootwrapper_magic;
- u32 relocation_entry;
- u32 relocation_size;
-};
+#define TIMEOUT_MSEC 100
-static void __iomem *relocation, *sysctrl, *fabric;
+static void __iomem *sysctrl, *fabric;
static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER];
static DEFINE_SPINLOCK(boot_lock);
-static struct hip04_secondary_cpu_data hip04_boot;
+static u32 fabric_phys_addr;
+/*
+ * [0]: bootwrapper physical address
+ * [1]: bootwrapper size
+ * [2]: relocation address
+ * [3]: relocation size
+ */
+static u32 hip04_boot_method[4];
-static bool hip04_cluster_down(unsigned int cluster)
+static bool hip04_cluster_is_down(unsigned int cluster)
{
int i;
@@ -93,46 +93,45 @@ static void hip04_set_snoop_filter(unsigned int cluster, unsigned int on)
if (data == readl_relaxed(fabric + FAB_SF_MODE))
break;
}
+ return;
}
static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
{
unsigned long data, mask;
+ void __iomem *sys_dreq, *sys_status;
- if (!relocation || !sysctrl)
+ if (!sysctrl)
return -ENODEV;
if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER)
return -EINVAL;
spin_lock_irq(&boot_lock);
- if (hip04_cpu_table[cluster][cpu]) {
- hip04_cpu_table[cluster][cpu]++;
- spin_unlock_irq(&boot_lock);
- return 0;
- }
+ if (hip04_cpu_table[cluster][cpu])
+ goto out;
- writel_relaxed(hip04_boot.bootwrapper_phys, relocation);
- writel_relaxed(hip04_boot.bootwrapper_magic, relocation + 4);
- writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
- writel_relaxed(0, relocation + 12);
-
- if (hip04_cluster_down(cluster)) {
+ sys_dreq = sysctrl + SC_CPU_RESET_DREQ(cluster);
+ sys_status = sysctrl + SC_CPU_RESET_STATUS(cluster);
+ if (hip04_cluster_is_down(cluster)) {
data = CLUSTER_DEBUG_RESET_BIT;
- writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+ writel_relaxed(data, sys_dreq);
do {
+ cpu_relax();
mask = CLUSTER_DEBUG_RESET_STATUS;
- data = readl_relaxed(sysctrl + \
- SC_CPU_RESET_STATUS(cluster));
+ data = readl_relaxed(sys_status);
} while (data & mask);
- hip04_set_snoop_filter(cluster, 1);
}
- hip04_cpu_table[cluster][cpu]++;
-
data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
CORE_DEBUG_RESET_BIT(cpu);
- writel_relaxed(data, sysctrl + SC_CPU_RESET_DREQ(cluster));
+ writel_relaxed(data, sys_dreq);
+ do {
+ cpu_relax();
+ } while (data == readl_relaxed(sys_status));
+ udelay(20);
+out:
+ hip04_cpu_table[cluster][cpu]++;
spin_unlock_irq(&boot_lock);
return 0;
@@ -140,8 +139,8 @@ static int hip04_mcpm_power_up(unsigned int cpu, unsigned int cluster)
static void hip04_mcpm_power_down(void)
{
- unsigned int mpidr, cpu, cluster, data = 0;
- bool skip_reset = false;
+ unsigned int mpidr, cpu, cluster;
+ bool skip_wfi = false, last_man = false;
mpidr = read_cpuid_mpidr();
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
@@ -149,59 +148,122 @@ static void hip04_mcpm_power_down(void)
__mcpm_cpu_going_down(cpu, cluster);
- spin_lock(&boot_lock);
+ spin_lock_irq(&boot_lock);
BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
hip04_cpu_table[cluster][cpu]--;
if (hip04_cpu_table[cluster][cpu] == 1) {
/* A power_up request went ahead of us. */
- skip_reset = true;
+ skip_wfi = true;
} else if (hip04_cpu_table[cluster][cpu] > 1) {
pr_err("Cluster %d CPU%d boots multiple times\n", cluster, cpu);
BUG();
}
- spin_unlock(&boot_lock);
- v7_exit_coherency_flush(louis);
+ last_man = hip04_cluster_is_down(cluster);
+ if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
+ spin_unlock(&boot_lock);
+ v7_exit_coherency_flush(all);
+ __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+ } else {
+ spin_unlock(&boot_lock);
+ v7_exit_coherency_flush(louis);
+ }
__mcpm_cpu_down(cpu, cluster);
- if (!skip_reset) {
- data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
- CORE_DEBUG_RESET_BIT(cpu);
- writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
- }
+ if (!skip_wfi)
+ wfi();
}
static int hip04_mcpm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
{
- unsigned int data, tries;
+ unsigned int data, tries, count;
BUG_ON(cluster >= HIP04_MAX_CLUSTERS ||
cpu >= HIP04_MAX_CPUS_PER_CLUSTER);
- for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; tries++) {
+ count = TIMEOUT_MSEC / POLL_MSEC;
+ spin_lock_irq(&boot_lock);
+ for (tries = 0; tries < count; tries++) {
+ cpu_relax();
+ udelay(50);
data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
- if (!(data & CORE_RESET_STATUS(cpu))) {
- msleep(POLL_MSEC);
- continue;
+ if (!hip04_cpu_table[cluster][cpu] || \
+ (data & CORE_WFI_STATUS(cpu))) {
+ break;
}
- return 0;
}
+ if (tries >= count)
+ goto err;
+ data = CORE_RESET_BIT(cpu) | NEON_RESET_BIT(cpu) | \
+ CORE_DEBUG_RESET_BIT(cpu);
+ writel_relaxed(data, sysctrl + SC_CPU_RESET_REQ(cluster));
+ for (tries = 0; tries < count; tries++) {
+ cpu_relax();
+ udelay(50);
+ data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster));
+ if (!hip04_cpu_table[cluster][cpu] || \
+ (data & CORE_RESET_STATUS(cpu))) {
+ break;
+ }
+ }
+ if (tries >= count)
+ goto err;
+ if (hip04_cluster_is_down(cluster))
+ hip04_set_snoop_filter(cluster, 0);
+ spin_unlock_irq(&boot_lock);
+ return 0;
+err:
+ spin_unlock_irq(&boot_lock);
return -ETIMEDOUT;
}
static void hip04_mcpm_powered_up(void)
{
- if (!relocation)
- return;
+ unsigned int mpidr, cpu, cluster;
+
+ mpidr = read_cpuid_mpidr();
+ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
spin_lock(&boot_lock);
- writel_relaxed(0, relocation);
- writel_relaxed(0, relocation + 4);
- writel_relaxed(0, relocation + 8);
- writel_relaxed(0, relocation + 12);
+ if (!hip04_cpu_table[cluster][cpu])
+ hip04_cpu_table[cluster][cpu] = 1;
spin_unlock(&boot_lock);
}
+static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level)
+{
+ asm volatile (" \n"
+" cmp r0, #0 \n"
+" bxeq lr \n"
+ /* calculate fabric phys address */
+" adr r2, 2f \n"
+" ldmia r2, {r1, r3} \n"
+" sub r0, r2, r1 \n"
+" ldr r2, [r0, r3] \n"
+ /* get cluster id from MPIDR */
+" mrc p15, 0, r0, c0, c0, 5 \n"
+" ubfx r1, r0, #8, #8 \n"
+ /* 1 << cluster id */
+" mov r0, #1 \n"
+" mov r3, r0, lsl r1 \n"
+" ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n"
+" tst r0, r3 \n"
+" bxne lr \n"
+" orr r1, r0, r3 \n"
+" str r1, [r2, #"__stringify(FAB_SF_MODE)"] \n"
+"1: ldr r0, [r2, #"__stringify(FAB_SF_MODE)"] \n"
+" tst r0, r3 \n"
+" beq 1b \n"
+" bx lr \n"
+
+" .align 2 \n"
+"2: .word . \n"
+" .word fabric_phys_addr \n"
+ );
+}
+
static const struct mcpm_platform_ops hip04_mcpm_ops = {
.power_up = hip04_mcpm_power_up,
.power_down = hip04_mcpm_power_down,
@@ -229,60 +291,48 @@ static bool __init hip04_cpu_table_init(void)
static int __init hip04_mcpm_init(void)
{
- struct device_node *np, *np_fab;
+ struct device_node *np, *np_sctl, *np_fab;
+ struct resource fab_res;
+ void __iomem *relocation;
int ret = -ENODEV;
- np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
+ np = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-bootwrapper");
if (!np)
goto err;
+ ret = of_property_read_u32_array(np, "boot-method",
+ &hip04_boot_method[0], 4);
+ if (ret)
+ goto err;
+ np_sctl = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
+ if (!np_sctl)
+ goto err;
np_fab = of_find_compatible_node(NULL, NULL, "hisilicon,hip04-fabric");
if (!np_fab)
goto err;
- if (of_property_read_u32(np, "bootwrapper-phys",
- &hip04_boot.bootwrapper_phys)) {
- pr_err("failed to get bootwrapper-phys\n");
- ret = -EINVAL;
+ ret = memblock_reserve(hip04_boot_method[0], hip04_boot_method[1]);
+ if (ret)
goto err;
- }
- if (of_property_read_u32(np, "bootwrapper-size",
- &hip04_boot.bootwrapper_size)) {
- pr_err("failed to get bootwrapper-size\n");
- ret = -EINVAL;
- goto err;
- }
- if (of_property_read_u32(np, "bootwrapper-magic",
- &hip04_boot.bootwrapper_magic)) {
- pr_err("failed to get bootwrapper-magic\n");
- ret = -EINVAL;
- goto err;
- }
- if (of_property_read_u32(np, "relocation-entry",
- &hip04_boot.relocation_entry)) {
- pr_err("failed to get relocation-entry\n");
- ret = -EINVAL;
- goto err;
- }
- if (of_property_read_u32(np, "relocation-size",
- &hip04_boot.relocation_size)) {
- pr_err("failed to get relocation-size\n");
- ret = -EINVAL;
- goto err;
- }
- relocation = ioremap(hip04_boot.relocation_entry,
- hip04_boot.relocation_size);
+ relocation = ioremap(hip04_boot_method[2], hip04_boot_method[3]);
if (!relocation) {
pr_err("failed to map relocation space\n");
ret = -ENOMEM;
- goto err;
+ goto err_reloc;
}
- sysctrl = of_iomap(np, 0);
+ sysctrl = of_iomap(np_sctl, 0);
if (!sysctrl) {
pr_err("failed to get sysctrl base\n");
ret = -ENOMEM;
goto err_sysctrl;
}
+ ret = of_address_to_resource(np_fab, 0, &fab_res);
+ if (ret) {
+ pr_err("failed to get fabric base phys\n");
+ goto err_fabric;
+ }
+ fabric_phys_addr = fab_res.start;
+ sync_cache_w(&fabric_phys_addr);
fabric = of_iomap(np_fab, 0);
if (!fabric) {
pr_err("failed to get fabric base\n");
@@ -290,19 +340,34 @@ static int __init hip04_mcpm_init(void)
goto err_fabric;
}
- if (!hip04_cpu_table_init())
- return -EINVAL;
+ if (!hip04_cpu_table_init()) {
+ ret = -EINVAL;
+ goto err_table;
+ }
ret = mcpm_platform_register(&hip04_mcpm_ops);
- if (!ret) {
- mcpm_sync_init(NULL);
- pr_info("HiP04 MCPM initialized\n");
+ if (ret) {
+ goto err_table;
}
+
+ /* Make secondary core out of reset. */
+ writel_relaxed(hip04_boot_method[0], relocation);
+ writel_relaxed(0xa5a5a5a5, relocation + 4); /* magic number */
+ writel_relaxed(virt_to_phys(mcpm_entry_point), relocation + 8);
+ writel_relaxed(0, relocation + 12);
+ iounmap(relocation);
+
+ mcpm_sync_init(hip04_mcpm_power_up_setup);
mcpm_smp_set_ops();
+ pr_info("HiP04 MCPM initialized\n");
return ret;
+err_table:
+ iounmap(fabric);
err_fabric:
iounmap(sysctrl);
err_sysctrl:
iounmap(relocation);
+err_reloc:
+ memblock_free(hip04_boot_method[0], hip04_boot_method[1]);
err:
return ret;
}