From: Tang Yuantian <yuantian.t...@freescale.com> 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.z...@freescale.com> Signed-off-by: Tang Yuantian <yuantian.t...@feescale.com> --- arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/common.c | 3 + arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c | 95 ++++++++++++++++++++++++++++ arch/powerpc/platforms/85xx/smp.c | 86 +++++++++---------------- arch/powerpc/sysdev/fsl_rcpm.c | 2 - 5 files changed, 128 insertions(+), 59 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 1fe7fb9..7bc86da 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -2,6 +2,7 @@ # Makefile for the PowerPC 85xx linux kernel. # obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c index 7bfb9b1..91475f5 100644 --- a/arch/powerpc/platforms/85xx/common.c +++ b/arch/powerpc/platforms/85xx/common.c @@ -10,10 +10,13 @@ #include <linux/of_platform.h> #include <asm/qe.h> +#include <asm/fsl_pm.h> #include <sysdev/cpm2_pic.h> #include "mpc85xx.h" +const struct fsl_pm_ops *qoriq_pm_ops; + static const struct of_device_id mpc85xx_common_ids[] __initconst = { { .type = "soc", }, { .compatible = "soc", }, diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c new file mode 100644 index 0000000..e59714e --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c @@ -0,0 +1,95 @@ +/* + * MPC85xx PM operators + * + * Copyright 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 + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include <asm/io.h> +#include <asm/fsl_guts.h> +#include <asm/fsl_pm.h> + +static struct ccsr_guts __iomem *guts; + +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", }, + { .compatible = "fsl,bsc9132-guts", }, + {}, +}; + +static void mpc85xx_irq_mask(int cpu) +{ + +} + +static void mpc85xx_irq_unmask(int cpu) +{ + +} + +static void mpc85xx_cpu_die(int cpu) +{ + +} + +static void mpc85xx_cpu_up(int cpu) +{ + +} + +static void mpc85xx_freeze_time_base(bool 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 const struct fsl_pm_ops mpc85xx_pm_ops = { + .freeze_time_base = mpc85xx_freeze_time_base, + .irq_mask = mpc85xx_irq_mask, + .irq_unmask = mpc85xx_irq_unmask, + .cpu_die = mpc85xx_cpu_die, + .cpu_up = mpc85xx_cpu_up, +}; + +static int __init mpc85xx_setup_pmc(void) +{ + struct device_node *np; + + 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 -ENOMEM; + } + } + + qoriq_pm_ops = &mpc85xx_pm_ops; + + return 0; +} + +/* need to call this before SMP init */ +early_initcall(mpc85xx_setup_pmc) diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 1180f78..6811a5b 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -2,7 +2,7 @@ * Author: Andy Fleming <aflem...@freescale.com> * Kumar Gala <ga...@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> @@ -26,9 +25,9 @@ #include <asm/mpic.h> #include <asm/cacheflush.h> #include <asm/dbell.h> -#include <asm/fsl_guts.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 +42,10 @@ struct epapr_spin_table { u32 pir; }; -static struct ccsr_guts __iomem *guts; 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 +56,7 @@ static void mpc85xx_give_timebase(void) barrier(); tb_req = 0; - mpc85xx_timebase_freeze(1); + qoriq_pm_ops->freeze_time_base(1); #ifdef CONFIG_PPC64 /* * e5500/e6500 have a workaround for erratum A-006958 in place @@ -104,7 +89,7 @@ static void mpc85xx_give_timebase(void) while (tb_valid) barrier(); - mpc85xx_timebase_freeze(0); + qoriq_pm_ops->freeze_time_base(0); local_irq_restore(flags); } @@ -127,20 +112,10 @@ static void mpc85xx_take_timebase(void) } #ifdef CONFIG_HOTPLUG_CPU -static void smp_85xx_mach_cpu_die(void) +static void e500_cpu_idle(void) { - unsigned int cpu = smp_processor_id(); u32 tmp; - local_irq_disable(); - idle_task_exit(); - generic_set_cpu_dead(cpu); - mb(); - - mtspr(SPRN_TCR, 0); - - cur_cpu_spec->cpu_down_flush(); - tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP; mtspr(SPRN_HID0, tmp); isync(); @@ -151,6 +126,25 @@ static void smp_85xx_mach_cpu_die(void) mb(); mtmsr(tmp); isync(); +} + +static void qoriq_cpu_dying(void) +{ + unsigned int cpu = smp_processor_id(); + + hard_irq_disable(); + /* mask all irqs to prevent cpu wakeup */ + qoriq_pm_ops->irq_mask(cpu); + idle_task_exit(); + + mtspr(SPRN_TCR, 0); + mtspr(SPRN_TSR, mfspr(SPRN_TSR)); + + cur_cpu_spec->cpu_down_flush(); + + generic_set_cpu_dead(cpu); + + e500_cpu_idle(); while (1) ; @@ -332,9 +326,9 @@ struct smp_ops_t smp_85xx_ops = { .cpu_disable = generic_cpu_disable, .cpu_die = generic_cpu_die, #endif -#ifdef CONFIG_KEXEC - .give_timebase = smp_generic_give_timebase, - .take_timebase = smp_generic_take_timebase, +#if defined(CONFIG_KEXEC) || defined(CONFIG_HOTPLUG_CPU) + .give_timebase = mpc85xx_give_timebase, + .take_timebase = mpc85xx_take_timebase, #endif }; @@ -346,7 +340,7 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) local_irq_disable(); if (secondary) { - __flush_disable_L1(); + cur_cpu_spec->cpu_down_flush(); atomic_inc(&kexec_down_cpus); /* loop forever */ while (1); @@ -398,16 +392,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; @@ -431,21 +415,9 @@ 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; - } - 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; + ppc_md.cpu_die = qoriq_cpu_dying; #endif - } smp_ops = &smp_85xx_ops; diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c index acf3f94..e6ae678 100644 --- a/arch/powerpc/sysdev/fsl_rcpm.c +++ b/arch/powerpc/sysdev/fsl_rcpm.c @@ -20,8 +20,6 @@ #include <asm/cputhreads.h> #include <asm/fsl_pm.h> -const struct fsl_pm_ops *qoriq_pm_ops; - static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs; static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs; static unsigned int fsl_supported_pm_modes; -- 2.1.0.27.g96db324 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/