diff options
author | chenhui zhao <chenhui.zhao@freescale.com> | 2015-11-20 17:14:00 +0800 |
---|---|---|
committer | Scott Wood <oss@buserror.net> | 2016-03-04 23:53:11 -0600 |
commit | 56f1ba280719469bffc870b6b2d935f3a3019ea4 (patch) | |
tree | 92562692750c084169659406f6efed81647c2b81 /arch/powerpc/platforms/85xx/smp.c | |
parent | d17799f9c10e283cccd4d598d3416e6fac336ab9 (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.c | 73 |
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 |