summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/85xx/smp.c
diff options
context:
space:
mode:
authorchenhui zhao <chenhui.zhao@freescale.com>2015-11-20 17:14:00 +0800
committerScott Wood <oss@buserror.net>2016-03-04 23:53:11 -0600
commit56f1ba280719469bffc870b6b2d935f3a3019ea4 (patch)
tree92562692750c084169659406f6efed81647c2b81 /arch/powerpc/platforms/85xx/smp.c
parentd17799f9c10e283cccd4d598d3416e6fac336ab9 (diff)
powerpc/mpc85xx: refactor the PM operations
Freescale CoreNet-based and Non-CoreNet-based platforms require different PM operations. This patch extracted existing PM operations on Non-CoreNet-based platforms to a new file which can accommodate both platforms. In this way, PM operation codes are clearer structurally. Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com> Signed-off-by: Tang Yuantian <Yuantian.Tang@feescale.com> Signed-off-by: Scott Wood <oss@buserror.net>
Diffstat (limited to 'arch/powerpc/platforms/85xx/smp.c')
-rw-r--r--arch/powerpc/platforms/85xx/smp.c73
1 files changed, 19 insertions, 54 deletions
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 4a7841616c7f..ab0459d904ff 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -2,7 +2,7 @@
* Author: Andy Fleming <afleming@freescale.com>
* Kumar Gala <galak@kernel.crashing.org>
*
- * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012, 2015 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/of.h>
-#include <linux/of_address.h>
#include <linux/kexec.h>
#include <linux/highmem.h>
#include <linux/cpu.h>
@@ -29,6 +28,7 @@
#include <asm/dbell.h>
#include <asm/code-patching.h>
#include <asm/cputhreads.h>
+#include <asm/fsl_pm.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
@@ -43,24 +43,11 @@ struct epapr_spin_table {
u32 pir;
};
-static struct ccsr_guts __iomem *guts;
+#ifdef CONFIG_HOTPLUG_CPU
static u64 timebase;
static int tb_req;
static int tb_valid;
-static void mpc85xx_timebase_freeze(int freeze)
-{
- uint32_t mask;
-
- mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
- if (freeze)
- setbits32(&guts->devdisr, mask);
- else
- clrbits32(&guts->devdisr, mask);
-
- in_be32(&guts->devdisr);
-}
-
static void mpc85xx_give_timebase(void)
{
unsigned long flags;
@@ -71,7 +58,7 @@ static void mpc85xx_give_timebase(void)
barrier();
tb_req = 0;
- mpc85xx_timebase_freeze(1);
+ qoriq_pm_ops->freeze_time_base(true);
#ifdef CONFIG_PPC64
/*
* e5500/e6500 have a workaround for erratum A-006958 in place
@@ -104,7 +91,7 @@ static void mpc85xx_give_timebase(void)
while (tb_valid)
barrier();
- mpc85xx_timebase_freeze(0);
+ qoriq_pm_ops->freeze_time_base(false);
local_irq_restore(flags);
}
@@ -126,31 +113,25 @@ static void mpc85xx_take_timebase(void)
local_irq_restore(flags);
}
-#ifdef CONFIG_HOTPLUG_CPU
static void smp_85xx_mach_cpu_die(void)
{
unsigned int cpu = smp_processor_id();
- u32 tmp;
local_irq_disable();
+ hard_irq_disable();
+ /* mask all irqs to prevent cpu wakeup */
+ qoriq_pm_ops->irq_mask(cpu);
+
idle_task_exit();
- generic_set_cpu_dead(cpu);
- mb();
mtspr(SPRN_TCR, 0);
+ mtspr(SPRN_TSR, mfspr(SPRN_TSR));
- cur_cpu_spec->cpu_down_flush();
+ generic_set_cpu_dead(cpu);
- tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
- mtspr(SPRN_HID0, tmp);
- isync();
+ cur_cpu_spec->cpu_down_flush();
- /* Enter NAP mode. */
- tmp = mfmsr();
- tmp |= MSR_WE;
- mb();
- mtmsr(tmp);
- isync();
+ qoriq_pm_ops->cpu_die(cpu);
while (1)
;
@@ -468,16 +449,6 @@ static void smp_85xx_setup_cpu(int cpu_nr)
smp_85xx_basic_setup(cpu_nr);
}
-static const struct of_device_id mpc85xx_smp_guts_ids[] = {
- { .compatible = "fsl,mpc8572-guts", },
- { .compatible = "fsl,p1020-guts", },
- { .compatible = "fsl,p1021-guts", },
- { .compatible = "fsl,p1022-guts", },
- { .compatible = "fsl,p1023-guts", },
- { .compatible = "fsl,p2020-guts", },
- {},
-};
-
void __init mpc85xx_smp_init(void)
{
struct device_node *np;
@@ -501,22 +472,16 @@ void __init mpc85xx_smp_init(void)
smp_85xx_ops.probe = NULL;
}
- np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
- if (np) {
- guts = of_iomap(np, 0);
- of_node_put(np);
- if (!guts) {
- pr_err("%s: Could not map guts node address\n",
- __func__);
- return;
- }
+#ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_FSL_PMC
+ mpc85xx_setup_pmc();
+#endif
+ if (qoriq_pm_ops) {
smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
-#ifdef CONFIG_HOTPLUG_CPU
ppc_md.cpu_die = smp_85xx_mach_cpu_die;
-#endif
}
-
+#endif
smp_ops = &smp_85xx_ops;
#ifdef CONFIG_KEXEC