[PATCH] cpuidle: remove cpu_pm calls when entering a idle state
The functions, cpu_pm_enter and cpu_pm_exit, assume that CPU would be reset when entering and exiting a idle state. If that is not the case, they would cause issue. Signed-off-by: Chenhui Zhao --- include/linux/cpuidle.h | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index bb31373..063af89 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -261,12 +261,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) return idx; \ } \ \ - __ret = cpu_pm_enter(); \ - if (!__ret) { \ - __ret = low_level_idle_enter(idx); \ - cpu_pm_exit(); \ - } \ - \ + __ret = low_level_idle_enter(idx); \ __ret ? -1 : idx; \ }) -- 1.9.1
Re: [PATCH 2/2] soc: nxp: Add a RCPM driver
On Mon, Aug 1, 2016 at 8:25 PM, Arnd Bergmann wrote: > On Monday, August 1, 2016 5:49:03 PM CEST Chenhui Zhao wrote: >> The NXP's QorIQ Processors based on ARM Core have a RCPM module >> (Run Control and Power Management), which performs all device-level >> tasks associated with power management. >> >> This patch mainly implements the wakeup sources configuration before >> entering LPM20, a low power state of device-level. The devices can be >> waked up by specified sources, such as Flextimer, GPIO and so on. >> >> Signed-off-by: Chenhui Zhao > > Adding irqchip maintainers to cc, as this wakeup handling is normally > part of the irq controller. > >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* So far there are not more than two registers */ >> +#define RCPM_IPPDEXPCR0 0x140 >> +#define RCPM_IPPDEXPCR1 0x144 >> +#define RCPM_IPPDEXPCR(x)(RCPM_IPPDEXPCR0 + 4 * x) >> +#define RCPM_WAKEUP_CELL_MAX_SIZE2 >> + >> +/* it reprents the number of the registers RCPM_IPPDEXPCR */ >> +static unsigned int rcpm_wakeup_cells; >> +static void __iomem *rcpm_reg_base; >> +static u32 ippdexpcr[RCPM_WAKEUP_CELL_MAX_SIZE]; > > Can you make these local to the context of whoever > calls into the driver? > > >> +static void rcpm_wakeup_fixup(struct device *dev, void *data) >> +{ >> + struct device_node *node = dev ? dev->of_node : NULL; >> + u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1]; >> + int ret; >> + int i; >> + >> + if (!dev || !node || !device_may_wakeup(dev)) >> + return; >> + >> + /* >> + * Get the values in the "rcpm-wakeup" property. >> + * Refer to Documentation/devicetree/bindings/soc/fsl/rcpm.txt >> + */ >> + ret = of_property_read_u32_array(node, "rcpm-wakeup",c >> + value, rcpm_wakeup_cells + 1); > > My first impression is that you are trying to do something > in a platform specific way that should be handled by common > code here. > > You are parsing rcpm_wakeup_cells once for the global node, > but you don't check whether the device that has the rcpm-wakeup > node actually refers to this instance, and that would require > an incompatible change if we ever get an implementation that > has multiple such nodes. > > Arnd The code is specific to the QorIQ platform. For a given QorIQ SoC, the value of the "fsl,#rcpm-wakeup-cells" property would not change. Anyway, your suggestion is better getting the rcpm node from the "rcpm-wakeup" property. Thanks, Chenhui
Re: [PATCH 2/2] soc: nxp: Add a RCPM driver
On Mon, Aug 1, 2016 at 9:22 PM, Marc Zyngier wrote: > > On 01/08/16 10:49, Chenhui Zhao wrote: > > The NXP's QorIQ Processors based on ARM Core have a RCPM module > > (Run Control and Power Management), which performs all device-level > > tasks associated with power management. > > > > This patch mainly implements the wakeup sources configuration before > > entering LPM20, a low power state of device-level. The devices can be > > waked up by specified sources, such as Flextimer, GPIO and so on. > > > > Signed-off-by: Chenhui Zhao > > --- > > drivers/soc/fsl/Makefile | 1 + > > drivers/soc/fsl/pm/Makefile | 1 + > > drivers/soc/fsl/pm/ls-rcpm.c | 144 > > +++ > > 3 files changed, 146 insertions(+) > > create mode 100644 drivers/soc/fsl/pm/Makefile > > create mode 100644 drivers/soc/fsl/pm/ls-rcpm.c > > > > diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile > > index 203307f..b5adbaf 100644 > > --- a/drivers/soc/fsl/Makefile > > +++ b/drivers/soc/fsl/Makefile > > @@ -4,3 +4,4 @@ > > > > obj-$(CONFIG_QUICC_ENGINE) += qe/ > > obj-$(CONFIG_CPM)+= qe/ > > +obj-$(CONFIG_SUSPEND)+= pm/ > > diff --git a/drivers/soc/fsl/pm/Makefile b/drivers/soc/fsl/pm/Makefile > > new file mode 100644 > > index 000..e275d63 > > --- /dev/null > > +++ b/drivers/soc/fsl/pm/Makefile > > @@ -0,0 +1 @@ > > +obj-$(CONFIG_ARCH_LAYERSCAPE) += ls-rcpm.o > > diff --git a/drivers/soc/fsl/pm/ls-rcpm.c b/drivers/soc/fsl/pm/ls-rcpm.c > > new file mode 100644 > > index 000..c5f2b97 > > --- /dev/null > > +++ b/drivers/soc/fsl/pm/ls-rcpm.c > > @@ -0,0 +1,144 @@ > > +/* > > + * Run Control and Power Management (RCPM) driver > > + * > > + * Copyright 2016 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. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + */ > > +#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +/* So far there are not more than two registers */ > > +#define RCPM_IPPDEXPCR0 0x140 > > +#define RCPM_IPPDEXPCR1 0x144 > > +#define RCPM_IPPDEXPCR(x)(RCPM_IPPDEXPCR0 + 4 * x) > > +#define RCPM_WAKEUP_CELL_MAX_SIZE2 > > + > > +/* it reprents the number of the registers RCPM_IPPDEXPCR */ > > +static unsigned int rcpm_wakeup_cells; > > +static void __iomem *rcpm_reg_base; > > +static u32 ippdexpcr[RCPM_WAKEUP_CELL_MAX_SIZE]; > > + > > +static inline void rcpm_reg_write(u32 offset, u32 value) > > +{ > > + iowrite32be(value, rcpm_reg_base + offset); > > +} > > + > > +static inline u32 rcpm_reg_read(u32 offset) > > +{ > > + return ioread32be(rcpm_reg_base + offset); > > +} > > + > > +static void rcpm_wakeup_fixup(struct device *dev, void *data) > > +{ > > + struct device_node *node = dev ? dev->of_node : NULL; > > + u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1]; > > + int ret; > > + int i; > > + > > + if (!dev || !node || !device_may_wakeup(dev)) > > + return; > > + > > + /* > > + * Get the values in the "rcpm-wakeup" property. > > + * Refer to Documentation/devicetree/bindings/soc/fsl/rcpm.txt > > + */ > > + ret = of_property_read_u32_array(node, "rcpm-wakeup", > > + value, rcpm_wakeup_cells + 1); > > + if (ret) > > + return; > > + > > + pr_debug("wakeup source: the device %s\n", node->full_name); > > This looks absolutely dreadful. You are parsing every node for each > device, and apply a set-in-stone configuration. > > The normal way to handle this is by making this device an interrupt > controller, and honour the irq_set_wake API. This has already been done > on other FSL/NXP hardware (see the iMX GPC stuff). > > Thanks, > > M. The RCPM IP block is really not an interrupt controller, instead it is related to power management. The code in this patch is to set the bits in the IPPDEXPCR register. Setting these bits can make the corresponding IP block alive during the period of sleep, so that the IP blocks working as wakeup sources can wake the device. The "rcpm-wakeup" property records the bit mask which should be set when the IP block is working as wakeup source. The bit definition may be different for each QorIQ SoC. The operation is specific to QorIQ platform, so put the code in drivers/soc/fsl/pm/. Thanks, Chenhui
[PATCH v3 0/5] powerpc/pm: QorIQ deep sleep
Changes for v3: * add mcke-gpios in dts to specify the GPIO pin which works as MCKE signal Changes for v2: * Ioremap every dts node used in the patches. * Check the board compatible string to see if the board supports deep sleep. * Can not reserve the first page of DDR memory, because PPC64 doesn't support changing the kernel base address. So still save and restore the first 128 bytes of DDR memory. * Still save and restoer CCSR registers in kernel, because bootloader doesn't know what register values to restore * Changed copyright and email address from freescale to NXP Please refer to the version 1: [1/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM http://patchwork.ozlabs.org/patch/502549/ [2/4] powerpc: get the physical base address of DCSR http://patchwork.ozlabs.org/patch/502551/ It is removed. [3/4] powerpc: pm: add EPU FSM configuration for deep sleep http://patchwork.ozlabs.org/patch/502548/ [4/4] powerpc: pm: support deep sleep feature on T104x http://patchwork.ozlabs.org/patch/502550/ Chenhui Zhao (5): powerpc/dts: add mcke-gpios for PM feature powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM powerpc: pm: add EPU FSM configuration for deep sleep powerpc/pm: support deep sleep feature on T104x powerpc/pm: save and restore registers during deep sleep Documentation/devicetree/bindings/soc/fsl/rcpm.txt | 13 + arch/powerpc/Kconfig | 3 +- arch/powerpc/boot/dts/fsl/t1040si-post.dtsi| 3 + arch/powerpc/include/asm/fsl_pm.h | 28 +- arch/powerpc/kernel/asm-offsets.c | 12 + arch/powerpc/kernel/fsl_booke_entry_mapping.S | 10 + arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/platforms/85xx/Kconfig| 5 + arch/powerpc/platforms/85xx/Makefile | 2 + arch/powerpc/platforms/85xx/deepsleep.c| 384 +++ arch/powerpc/platforms/85xx/qoriq_pm.c | 84 arch/powerpc/platforms/85xx/sleep_fsm.c| 267 +++ arch/powerpc/platforms/85xx/sleep_fsm.h| 92 arch/powerpc/platforms/85xx/t104x_deepsleep.S | 531 + arch/powerpc/platforms/86xx/Kconfig| 1 + arch/powerpc/sysdev/fsl_rcpm.c | 28 +- 16 files changed, 1446 insertions(+), 19 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.c create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.h create mode 100644 arch/powerpc/platforms/85xx/t104x_deepsleep.S -- 1.9.1
[PATCH v3 1/5] powerpc/dts: add mcke-gpios for PM feature
Signed-off-by: Chenhui Zhao --- Documentation/devicetree/bindings/soc/fsl/rcpm.txt | 13 + arch/powerpc/boot/dts/fsl/t1040si-post.dtsi| 3 +++ 2 files changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt index e284e4e..1d44a80 100644 --- a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt @@ -21,6 +21,10 @@ Required properites: * "fsl,qoriq-rcpm-2.0": for chassis 2.0 rcpm * "fsl,qoriq-rcpm-2.1": for chassis 2.1 rcpm +Optional properites: + - mcke-gpios : The GPIO pin is used for keeping the MCKE signal of DDR modules +low in the LPM35 state on some platforms, such as T1040. + All references to "1.0" and "2.0" refer to the QorIQ chassis version to which the chip complies. Chassis VersionExample Chips @@ -37,6 +41,15 @@ The RCPM node for T4240: fsl,#rcpm-wakeup-cells = <2>; }; +The RCPM node for T1040 (which supports LPM35 state): + rcpm: global-utilities@e2000 { + compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1"; + reg = <0xe2000 0x1000>; + fsl,#rcpm-wakeup-cells = <1>; + mcke-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH> + }; + + * Freescale RCPM Wakeup Source Device Tree Bindings --- Required fsl,rcpm-wakeup property should be added to a device node if the device diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index 507649e..f66e7dd 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi @@ -33,6 +33,7 @@ */ #include +#include &bman_fbpr { compatible = "fsl,bman-fbpr"; @@ -474,6 +475,8 @@ rcpm: global-utilities@e2000 { compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1"; reg = <0xe2000 0x1000>; + fsl,#rcpm-wakeup-cells = <1>; + mcke-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; }; sfp: sfp@e8000 { -- 1.9.1
[PATCH v3 3/5] powerpc: pm: add EPU FSM configuration for deep sleep
In the last stage of deep sleep, software will trigger a Finite State Machine (FSM) to control the hardware precedure, such as board isolation, killing PLLs, removing power, and so on. When the system is waked up by an interrupt, the FSM controls the hardware to complete the early resume precedure. This patch configure the EPU FSM preparing for deep sleep. Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/Makefile| 2 +- arch/powerpc/platforms/85xx/sleep_fsm.c | 267 arch/powerpc/platforms/85xx/sleep_fsm.h | 92 +++ 3 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.c create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.h diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index fdae28b..87fb847 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o -obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o +obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o sleep_fsm.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/sleep_fsm.c b/arch/powerpc/platforms/85xx/sleep_fsm.c new file mode 100644 index 000..2b0c16b --- /dev/null +++ b/arch/powerpc/platforms/85xx/sleep_fsm.c @@ -0,0 +1,267 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2016 Freescale Semiconductor Inc. + * + * Author: Hongbo Zhang + * Chenhui Zhao + * + * 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 +#include +#include + +#include "sleep_fsm.h" + +struct fsm_reg_vals { + u32 offset; + u32 value; +}; + +/* + * These values are from chip's reference manual. For example, + * the values for T1040 can be found in "8.4.3.8 Programming + * supporting deep sleep mode" of Chapter 8 "Run Control and + * Power Management (RCPM)". + * The default value is applied to T1040, T1042, T1024. + */ +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x8084}, + {EPECR0 + EPECR_STRIDE * 4, 0x2084}, + {EPECR0 + EPECR_STRIDE * 5, 0x0804}, + {EPECR0 + EPECR_STRIDE * 6, 0x8084}, + {EPECR0 + EPECR_STRIDE * 7, 0x8084}, + {EPECR0 + EPECR_STRIDE * 8, 0x6084}, + {EPECR0 + EPECR_STRIDE * 9, 0x0884}, + {EPECR0 + EPECR_STRIDE * 10, 0x4284}, + {EPECR0 + EPECR_STRIDE * 11, 0x9084}, + {EPECR0 + EPECR_STRIDE * 12, 0x8084}, + {EPECR0 + EPECR_STRIDE * 13, 0x0884}, + {EPECR0 + EPECR_STRIDE * 14, 0x0284}, + {EPECR0 + EPECR_STRIDE * 15, 0x0004}, + /* +* EPEVTCR (Event Processor EVT Pin Control Registers) +* SCU8 triger EVT2, and SCU11 triger EVT9 +*/ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x8001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB001}, + /* EPCMPR (Event Processor Counter Compare Registers) */ + {EPCMPR0 + EPCMPR_STRIDE * 0, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 1, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 2, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 3, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 4, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 5, 0x0020}, + {EPCMPR0 + EPCMPR_STRIDE * 6, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 7, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 8, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 9, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 10, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 11, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 12, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 13, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 14, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 15, 0x00FF}, + /* EPCCR (Event Processor Counter Control Registers) */ + {EPCCR0 + EPCCR_STRIDE * 0, 0}, + {EPCCR0 + EPCCR_STRIDE * 1, 0}, + {EPCCR0 + EPCCR_STRIDE * 2, 0x9284}, + {EPCCR0 + EPCCR_STRIDE * 3, 0}, + {EPCCR0 + EPCCR_STRIDE * 4, 0x9284}, + {EP
[PATCH v3 2/5] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
In sleep mode, the clocks of e500 cores and unused IP blocks is turned off. The IP blocks which are allowed to wake up the processor are still running. The sleep mode is equal to the Standby state in Linux. Use the command to enter sleep mode: echo standby > /sys/power/state Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig | 3 +- arch/powerpc/include/asm/fsl_pm.h | 2 +- arch/powerpc/platforms/85xx/Kconfig| 5 +++ arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/qoriq_pm.c | 59 ++ arch/powerpc/platforms/86xx/Kconfig| 1 + arch/powerpc/sysdev/fsl_rcpm.c | 20 7 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 0a9d439..078d08c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -242,7 +242,7 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ - (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ + FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \ || 44x || 40x config PPC_DCR_NATIVE @@ -778,7 +778,6 @@ config FSL_PCI config FSL_PMC bool - default y depends on SUSPEND && (PPC_85xx || PPC_86xx) help Freescale MPC85xx/MPC86xx power management controller support diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h index 47df55e..e05049b 100644 --- a/arch/powerpc/include/asm/fsl_pm.h +++ b/arch/powerpc/include/asm/fsl_pm.h @@ -34,7 +34,7 @@ struct fsl_pm_ops { void (*cpu_exit_state)(int cpu, int state); void (*cpu_up_prepare)(int cpu); void (*cpu_die)(int cpu); - int (*plat_enter_sleep)(void); + int (*plat_enter_sleep)(int state); void (*freeze_time_base)(bool freeze); /* keep the power of IP blocks during sleep/deep sleep */ diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index e626461..dff2ea6 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -9,6 +9,8 @@ menuconfig FSL_SOC_BOOKE select SERIAL_8250_EXTENDED if SERIAL_8250 select SERIAL_8250_SHARE_IRQ if SERIAL_8250 select FSL_CORENET_RCPM if PPC_E500MC + select FSL_QORIQ_PM if SUSPEND && PPC_E500MC + select FSL_PMC if SUSPEND && !PPC_E500MC default y if FSL_SOC_BOOKE @@ -289,3 +291,6 @@ endif # FSL_SOC_BOOKE config TQM85xx bool + +config FSL_QORIQ_PM + bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 7bc86da..fdae28b 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o +obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c b/arch/powerpc/platforms/85xx/qoriq_pm.c new file mode 100644 index 000..c97ef8f --- /dev/null +++ b/arch/powerpc/platforms/85xx/qoriq_pm.c @@ -0,0 +1,59 @@ +/* + * Support Power Management feature + * + * Copyright 2016 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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 +#include +#include + +#include + +static unsigned int pm_modes; + +static int qoriq_suspend_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + ret = qoriq_pm_ops->plat_enter_sleep(FSL_PM_SLEEP); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int qoriq_suspend_valid(suspend_state_t state) +{ + + if (state == PM_SUSPEND_STANDBY && (pm_modes & FSL_PM_SLEEP)) + return 1; + + return 0; +} + +static const struct platform_suspend_ops qoriq_suspend_ops = { + .valid = qoriq_suspend_valid, + .enter = qoriq_suspend_enter, +}; + +static int __init qoriq_suspend_init(void) +{ + /* support sleep by default */ + pm_modes |= FSL_PM_SLEEP; + + suspend_set_ops(&qoriq_suspend_ops); + return 0; +} +arch_initcall(qoriq_suspend_init); diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 1afd1e4..09638e0 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -5,6 +5,7 @@ menuconfig PPC_86xx select FSL_SOC se
[PATCH v3 5/5] powerpc/pm: save and restore registers during deep sleep
Some CCSR registers will lost during deep sleep. Therefore, should save them before entering deep sleep, and restore them when resuming from deep sleep. Signed-off-by: Tang Yuantian Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/fsl_pm.h | 2 + arch/powerpc/platforms/85xx/deepsleep.c | 108 +++- 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h index 48c2631..95601fb 100644 --- a/arch/powerpc/include/asm/fsl_pm.h +++ b/arch/powerpc/include/asm/fsl_pm.h @@ -61,7 +61,9 @@ extern void fsl_dp_enter_low(void *priv); extern void fsl_booke_deep_sleep_resume(void); struct fsl_iomap { + void *ccsr_lcc_base; void *ccsr_scfg_base; + void *ccsr_dcfg_base; void *ccsr_rcpm_base; void *ccsr_ddr_base; void *ccsr_gpio1_base; diff --git a/arch/powerpc/platforms/85xx/deepsleep.c b/arch/powerpc/platforms/85xx/deepsleep.c index 9521d99..71987fd 100644 --- a/arch/powerpc/platforms/85xx/deepsleep.c +++ b/arch/powerpc/platforms/85xx/deepsleep.c @@ -23,6 +23,8 @@ #include "sleep_fsm.h" +#define CCSR_LAW_OFFSET0xC00 + #define CPC_CPCHDBCR0 0x0f00 #define CPC_CPCHDBCR0_SPEC_DIS 0x0800 @@ -41,6 +43,17 @@ #define QORIQ_CPLD_MISCCSR 0x17 #define QORIQ_CPLD_MISCCSR_SLEEPEN 0x40 +#define CCSR_LCC_BSTRH 0x20 +#define CCSR_LCC_BSTRL 0x24 +#define CCSR_LCC_BSTAR 0x28 + +#define CCSR_DCFG_BRR 0xE4 + +#define CCSR_RCPM_PCTBENR 0x1A0 + +/* the target id for the memory complex 1 (MC1) */ +#define MC1_TRGT_ID0x10 + /* 128 bytes buffer for restoring data broke by DDR training initialization */ #define DDR_BUF_SIZE 128 static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64); @@ -50,6 +63,23 @@ static void fsl_dp_iounmap(void); static struct fsl_iomap fsl_dp_priv; +struct fsl_ccsr_law { + u32 lawbarh;/* LAWn base address high */ + u32 lawbarl;/* LAWn base address low */ + u32 lawar; /* LAWn attributes */ + u32 reserved; +}; + +static struct fsl_regs_buffer { + u32 bstrh; + u32 bstrl; + u32 bstar; + u32 brr; + u32 pctbenr; + u32 law_count; + void *law_regs; +} fsl_dp_buffer; + static const struct of_device_id fsl_dp_cpld_ids[] __initconst = { { .compatible = "fsl,t1024-cpld", }, { .compatible = "fsl,t1040rdb-cpld", }, @@ -65,6 +95,60 @@ static const struct of_device_id fsl_dp_fpga_ids[] __initconst = { {} }; +static void fsl_regs_save(struct fsl_iomap *base, + struct fsl_regs_buffer *buffer) +{ + int i; + struct fsl_ccsr_law *src = base->ccsr_lcc_base + CCSR_LAW_OFFSET; + struct fsl_ccsr_law *dst = buffer->law_regs; + + buffer->bstrh = in_be32(base->ccsr_lcc_base + CCSR_LCC_BSTRH); + buffer->bstrl = in_be32(base->ccsr_lcc_base + CCSR_LCC_BSTRL); + buffer->bstar = in_be32(base->ccsr_lcc_base + CCSR_LCC_BSTAR); + buffer->brr = in_be32(base->ccsr_dcfg_base + CCSR_DCFG_BRR); + buffer->pctbenr = in_be32(base->ccsr_rcpm_base + CCSR_RCPM_PCTBENR); + + for (i = 0; i < buffer->law_count; i++) { + dst->lawbarh = in_be32(&src->lawbarh); + dst->lawbarl = in_be32(&src->lawbarl); + dst->lawar = in_be32(&src->lawar); + dst++; + src++; + } +} + +static void fsl_regs_restore(struct fsl_iomap *base, +struct fsl_regs_buffer *buffer) +{ + int i; + u32 attr; + struct fsl_ccsr_law *src = buffer->law_regs; + struct fsl_ccsr_law *dst = base->ccsr_lcc_base + CCSR_LAW_OFFSET; + + out_be32(base->ccsr_lcc_base + CCSR_LCC_BSTRH, buffer->bstrh); + out_be32(base->ccsr_lcc_base + CCSR_LCC_BSTRL, buffer->bstrl); + out_be32(base->ccsr_lcc_base + CCSR_LCC_BSTAR, buffer->bstar); + out_be32(base->ccsr_dcfg_base + CCSR_DCFG_BRR, buffer->brr); + out_be32(base->ccsr_rcpm_base + CCSR_RCPM_PCTBENR, buffer->pctbenr); + + for (i = 0; i < buffer->law_count; i++) { + /* +* If the LAW with the target id of MC1 has been set, +* skip. Because changing it here causes memory +* access error. +*/ + attr = in_be32(&dst->lawar); + if (((attr >> 20) & 0xff) == MC1_TRGT_ID) + continue; + out_be32(&dst->lawar, 0); + out_be32(&dst->lawbarl, src->lawbarl); + out_be32(&dst->lawbarh, src->lawbarh); + out_be32(&dst->lawar, src->lawar); + src++; + dst++; + } +} +
[PATCH v3 1/5] powerpc/dts: add mcke-gpios for PM feature
Signed-off-by: Chenhui Zhao --- Documentation/devicetree/bindings/soc/fsl/rcpm.txt | 13 + arch/powerpc/boot/dts/fsl/t1040si-post.dtsi| 3 +++ 2 files changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt index e284e4e..1d44a80 100644 --- a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt @@ -21,6 +21,10 @@ Required properites: * "fsl,qoriq-rcpm-2.0": for chassis 2.0 rcpm * "fsl,qoriq-rcpm-2.1": for chassis 2.1 rcpm +Optional properites: + - mcke-gpios : The GPIO pin is used for keeping the MCKE signal of DDR modules +low in the LPM35 state on some platforms, such as T1040. + All references to "1.0" and "2.0" refer to the QorIQ chassis version to which the chip complies. Chassis VersionExample Chips @@ -37,6 +41,15 @@ The RCPM node for T4240: fsl,#rcpm-wakeup-cells = <2>; }; +The RCPM node for T1040 (which supports LPM35 state): + rcpm: global-utilities@e2000 { + compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1"; + reg = <0xe2000 0x1000>; + fsl,#rcpm-wakeup-cells = <1>; + mcke-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH> + }; + + * Freescale RCPM Wakeup Source Device Tree Bindings --- Required fsl,rcpm-wakeup property should be added to a device node if the device diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index 507649e..f66e7dd 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi @@ -33,6 +33,7 @@ */ #include +#include &bman_fbpr { compatible = "fsl,bman-fbpr"; @@ -474,6 +475,8 @@ rcpm: global-utilities@e2000 { compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1"; reg = <0xe2000 0x1000>; + fsl,#rcpm-wakeup-cells = <1>; + mcke-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; }; sfp: sfp@e8000 { -- 1.9.1
[PATCH v3 4/5] powerpc/pm: support deep sleep feature on T104x
T104x has deep sleep feature, which can switch off most parts of the SoC when it is in deep sleep mode. This way, it becomes more energy-efficient. The DDR controller will also be powered off in deep sleep. Therefore, the last stage (the latter part of fsl_dp_enter_low) will run without DDR access. This piece of code and related TLBs are prefetched in advance. Due to the different initialization code between 32-bit and 64-bit, they have separate resume entry and precedure. The feature supports 32-bit and 64-bit kernel mode. Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/fsl_pm.h | 24 ++ arch/powerpc/kernel/asm-offsets.c | 12 + arch/powerpc/kernel/fsl_booke_entry_mapping.S | 10 + arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/deepsleep.c | 278 ++ arch/powerpc/platforms/85xx/qoriq_pm.c| 25 ++ arch/powerpc/platforms/85xx/t104x_deepsleep.S | 531 ++ arch/powerpc/sysdev/fsl_rcpm.c| 8 +- 9 files changed, 889 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c create mode 100644 arch/powerpc/platforms/85xx/t104x_deepsleep.S diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h index e05049b..48c2631 100644 --- a/arch/powerpc/include/asm/fsl_pm.h +++ b/arch/powerpc/include/asm/fsl_pm.h @@ -20,6 +20,7 @@ #define PLAT_PM_SLEEP 20 #define PLAT_PM_LPM20 30 +#define PLAT_PM_LPM35 40 #define FSL_PM_SLEEP (1 << 0) #define FSL_PM_DEEP_SLEEP (1 << 1) @@ -48,4 +49,27 @@ extern const struct fsl_pm_ops *qoriq_pm_ops; int __init fsl_rcpm_init(void); +#ifdef CONFIG_FSL_QORIQ_PM +int fsl_enter_deepsleep(void); +int fsl_deepsleep_init(void); +#else +static inline int fsl_enter_deepsleep(void) { return -1; } +static inline int fsl_deepsleep_init(void) { return -1; } +#endif + +extern void fsl_dp_enter_low(void *priv); +extern void fsl_booke_deep_sleep_resume(void); + +struct fsl_iomap { + void *ccsr_scfg_base; + void *ccsr_rcpm_base; + void *ccsr_ddr_base; + void *ccsr_gpio1_base; + void *ccsr_cpc_base; + void *dcsr_epu_base; + void *dcsr_npc_base; + void *dcsr_rcpm_base; + void *cpld_base; + void *fpga_base; +}; #endif /* __PPC_FSL_PM_H */ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 9ea0955..cc488f9 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -68,6 +68,10 @@ #include "../mm/mmu_decl.h" #endif +#ifdef CONFIG_FSL_QORIQ_PM +#include +#endif + int main(void) { DEFINE(THREAD, offsetof(struct task_struct, thread)); @@ -783,5 +787,13 @@ int main(void) DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER); +#ifdef CONFIG_FSL_QORIQ_PM + DEFINE(CCSR_CPC_BASE, offsetof(struct fsl_iomap, ccsr_cpc_base)); + DEFINE(CCSR_GPIO1_BASE, offsetof(struct fsl_iomap, ccsr_gpio1_base)); + DEFINE(CCSR_RCPM_BASE, offsetof(struct fsl_iomap, ccsr_rcpm_base)); + DEFINE(CCSR_DDR_BASE, offsetof(struct fsl_iomap, ccsr_ddr_base)); + DEFINE(CCSR_SCFG_BASE, offsetof(struct fsl_iomap, ccsr_scfg_base)); + DEFINE(DCSR_EPU_BASE, offsetof(struct fsl_iomap, dcsr_epu_base)); +#endif return 0; } diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S index 83dd0f6..659b059 100644 --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S @@ -173,6 +173,10 @@ skpinv:addir6,r6,1 /* Increment */ lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@h ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_NEEDED)@l mtspr SPRN_MAS2,r6 +#ifdef ENTRY_DEEPSLEEP_SETUP + LOAD_REG_IMMEDIATE(r8, MEMORY_START) + ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR) +#endif mtspr SPRN_MAS3,r8 tlbwe @@ -215,12 +219,18 @@ next_tlb_setup: #error You need to specify the mapping or not use this at all. #endif +#ifdef ENTRY_DEEPSLEEP_SETUP + LOAD_REG_ADDR(r6, 2f) + mfmsr r7 + rlwinm r7,r7,0,~(MSR_IS|MSR_DS) +#else lis r7,MSR_KERNEL@h ori r7,r7,MSR_KERNEL@l bl 1f /* Find our address */ 1: mflrr9 rlwimi r6,r9,0,20,31 addir6,r6,(2f - 1b) +#endif mtspr SPRN_SRR0,r6 mtspr SPRN_SRR1,r7 rfi /* start execution out of TLB1[0] entry */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 2d14774..21fa124 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -829,7 +829,7 @@ _GLOBAL(start_secondary_resume) /* * This subroutine clobbers r11 and r12
[PATCH 2/2] soc: nxp: Add a RCPM driver
The NXP's QorIQ Processors based on ARM Core have a RCPM module (Run Control and Power Management), which performs all device-level tasks associated with power management. This patch mainly implements the wakeup sources configuration before entering LPM20, a low power state of device-level. The devices can be waked up by specified sources, such as Flextimer, GPIO and so on. Signed-off-by: Chenhui Zhao --- drivers/soc/fsl/Makefile | 1 + drivers/soc/fsl/pm/Makefile | 1 + drivers/soc/fsl/pm/ls-rcpm.c | 144 +++ 3 files changed, 146 insertions(+) create mode 100644 drivers/soc/fsl/pm/Makefile create mode 100644 drivers/soc/fsl/pm/ls-rcpm.c diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile index 203307f..b5adbaf 100644 --- a/drivers/soc/fsl/Makefile +++ b/drivers/soc/fsl/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_QUICC_ENGINE) += qe/ obj-$(CONFIG_CPM) += qe/ +obj-$(CONFIG_SUSPEND) += pm/ diff --git a/drivers/soc/fsl/pm/Makefile b/drivers/soc/fsl/pm/Makefile new file mode 100644 index 000..e275d63 --- /dev/null +++ b/drivers/soc/fsl/pm/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_LAYERSCAPE) += ls-rcpm.o diff --git a/drivers/soc/fsl/pm/ls-rcpm.c b/drivers/soc/fsl/pm/ls-rcpm.c new file mode 100644 index 000..c5f2b97 --- /dev/null +++ b/drivers/soc/fsl/pm/ls-rcpm.c @@ -0,0 +1,144 @@ +/* + * Run Control and Power Management (RCPM) driver + * + * Copyright 2016 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__ + +#include +#include +#include +#include +#include + +/* So far there are not more than two registers */ +#define RCPM_IPPDEXPCR00x140 +#define RCPM_IPPDEXPCR10x144 +#define RCPM_IPPDEXPCR(x) (RCPM_IPPDEXPCR0 + 4 * x) +#define RCPM_WAKEUP_CELL_MAX_SIZE 2 + +/* it reprents the number of the registers RCPM_IPPDEXPCR */ +static unsigned int rcpm_wakeup_cells; +static void __iomem *rcpm_reg_base; +static u32 ippdexpcr[RCPM_WAKEUP_CELL_MAX_SIZE]; + +static inline void rcpm_reg_write(u32 offset, u32 value) +{ + iowrite32be(value, rcpm_reg_base + offset); +} + +static inline u32 rcpm_reg_read(u32 offset) +{ + return ioread32be(rcpm_reg_base + offset); +} + +static void rcpm_wakeup_fixup(struct device *dev, void *data) +{ + struct device_node *node = dev ? dev->of_node : NULL; + u32 value[RCPM_WAKEUP_CELL_MAX_SIZE + 1]; + int ret; + int i; + + if (!dev || !node || !device_may_wakeup(dev)) + return; + + /* +* Get the values in the "rcpm-wakeup" property. +* Refer to Documentation/devicetree/bindings/soc/fsl/rcpm.txt +*/ + ret = of_property_read_u32_array(node, "rcpm-wakeup", +value, rcpm_wakeup_cells + 1); + if (ret) + return; + + pr_debug("wakeup source: the device %s\n", node->full_name); + + for (i = 0; i < rcpm_wakeup_cells; i++) + ippdexpcr[i] |= value[i + 1]; +} + +static int rcpm_suspend_prepare(void) +{ + int i; + + for (i = 0; i < rcpm_wakeup_cells; i++) + ippdexpcr[i] = 0; + + dpm_for_each_dev(NULL, rcpm_wakeup_fixup); + + for (i = 0; i < rcpm_wakeup_cells; i++) { + rcpm_reg_write(RCPM_IPPDEXPCR(i), ippdexpcr[i]); + pr_debug("ippdexpcr%d = 0x%x\n", i, ippdexpcr[i]); + } + + return 0; +} + +static int rcpm_suspend_notifier_call(struct notifier_block *bl, + unsigned long state, + void *unused) +{ + switch (state) { + case PM_SUSPEND_PREPARE: + rcpm_suspend_prepare(); + break; + } + + return NOTIFY_DONE; +} + +static const struct of_device_id rcpm_matches[] = { + { + .compatible = "fsl,qoriq-rcpm-2.1", + }, + {} +}; + +static struct notifier_block rcpm_suspend_notifier = { + .notifier_call = rcpm_suspend_notifier_call, +}; + +static int __init layerscape_rcpm_init(void) +{ + struct device_node *np; + int ret; + + np = of_find_matching_node_and_match(NULL, rcpm_matches, NULL); + if (!np) + return -ENODEV; + + ret = of_property_read_u32_index(np, "fsl,#rcpm-wakeu
[PATCH 1/2] ARM: dts: ls1043a: add a rcpm node
LS1043A have a RCPM module (Run Control and Power Management), which performs all device-level tasks associated with power management. Signed-off-by: Chenhui Zhao --- arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index de0323b..43944b7 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -196,6 +196,12 @@ bus-width = <4>; }; + rcpm: rcpm@1ee2000 { + compatible = "fsl,ls1043a-rcpm", "fsl,qoriq-rcpm-2.1"; + reg = <0x0 0x1ee2000 0x0 0x1000>; + fsl,#rcpm-wakeup-cells = <1>; + }; + dspi0: dspi@210 { compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; #address-cells = <1>; -- 1.9.1
[PATCH] powerpc/dts: fix rcpm compatible string
For T1040, T1042, T1023, and T1024, they should use the compatible string "fsl,qoriq-rcpm-2.1". Signed-off-by: Chenhui Zhao --- arch/powerpc/boot/dts/fsl/t1023si-post.dtsi | 2 +- arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi index 99e421d..6e0b489 100644 --- a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi @@ -263,7 +263,7 @@ }; rcpm: global-utilities@e2000 { - compatible = "fsl,t1023-rcpm", "fsl,qoriq-rcpm-2.0"; + compatible = "fsl,t1023-rcpm", "fsl,qoriq-rcpm-2.1"; reg = <0xe2000 0x1000>; }; diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi index e0f4da5..507649e 100644 --- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi @@ -472,7 +472,7 @@ }; rcpm: global-utilities@e2000 { - compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.0"; + compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1"; reg = <0xe2000 0x1000>; }; -- 1.9.1
[PATCH v4 1/6] powerpc/mm: any thread in one core can be the first to setup TLB1
On e6500, in the case of cpu hotplug, either thread in one core may be the first thread initilzing the TLB1. The subsequent threads must not setup it again. The code is derived from the comment of Scott Wood. Signed-off-by: Chenhui Zhao --- Changes for v4: * added CONFIG_BOOKE arch/powerpc/include/asm/cputhreads.h | 8 arch/powerpc/mm/tlb_nohash.c | 4 +--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index ba42e46..ea96231 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h @@ -94,6 +94,14 @@ static inline int cpu_last_thread_sibling(int cpu) return cpu | (threads_per_core - 1); } +static inline u32 get_tensr(void) +{ +#ifdef CONFIG_BOOKE + if (cpu_has_feature(CPU_FTR_SMT)) + return mfspr(SPRN_TENSR); +#endif + return 1; +} #endif /* _ASM_POWERPC_CPUTHREADS_H */ diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index bb04e4d..f466848 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -640,9 +640,7 @@ static void early_init_this_mmu(void) * transient mapping would cause problems. */ #ifdef CONFIG_SMP - if (cpu != boot_cpuid && - (cpu != cpu_first_thread_sibling(cpu) || -cpu == cpu_first_thread_sibling(boot_cpuid))) + if (hweight32(get_tensr()) > 1) map = false; #endif -- 1.9.1 -- 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/
Re: [PATCH v2,5/5] PowerPC/mpc85xx: Add CPU hotplug support for E6500
On Thu, Aug 27, 2015 at 6:42 AM, Scott Wood wrote: On Wed, Aug 26, 2015 at 08:09:48PM +0800, Chenhui Zhao wrote: + .globl booting_thread_hwid +booting_thread_hwid: + .long INVALID_THREAD_HWID + .align 3 The commit message goes into no detail about the changes you're making to thread handling, nor are there relevant comments. OK. Will add some comments. +/* + * r3 = the thread physical id + */ +_GLOBAL(book3e_stop_thread) + li r4, 1 + sld r4, r4, r3 + mtspr SPRN_TENC, r4 + isync + blr Why did the C code not have an isync, if it's required here? Just make sure "mtspr" has completed before the routine returns. _GLOBAL(fsl_secondary_thread_init) /* Enable branch prediction */ lis r3,BUCSR_INIT@h @@ -197,8 +236,10 @@ _GLOBAL(fsl_secondary_thread_init) * but the low bit right by two bits so that the cpu numbering is * continuous. */ - mfspr r3, SPRN_PIR - rlwimi r3, r3, 30, 2, 30 + bl 10f +10: mflrr5 + addir5,r5,(booting_thread_hwid - 10b) + lwz r3,0(r5) mtspr SPRN_PIR, r3 #endif I assume the reason for this is that, unlike the kexec case, the cpu has been reset so PIR has been reset? Don't make me guess -- document. We can not rely on the value saved in SPRN_PIR. Every time running fsl_secondary_thread_init, SPRN_PIR may not always has a reset value. Using booting_thread_hwid to ensure SPRN_PIR has a correct value. @@ -245,6 +286,30 @@ _GLOBAL(generic_secondary_smp_init) mr r3,r24 mr r4,r25 bl book3e_secondary_core_init + +/* + * If we want to boot Thread1, start Thread1 and stop Thread0. + * Note that only Thread0 will run the piece of code. + */ What ensures that only thread 0 runs this? Especially if we're entering via kdump on thread 1? This piece of code will be executed only when core resets (Thead0 will start first). Thead1 will run fsl_secondary_thread_init() to start. How can kdump run this on Thread1? I know little about kexec. s/the piece/this piece/ + LOAD_REG_ADDR(r3, booting_thread_hwid) + lwz r4, 0(r3) + cmpwi r4, INVALID_THREAD_HWID + beq 20f + cmpwr4, r24 + beq 20f Do all cores get released from the spin table before the first thread gets kicked? Yes. + + /* start Thread1 */ + LOAD_REG_ADDR(r5, fsl_secondary_thread_init) + ld r4, 0(r5) + li r3, 1 + bl book3e_start_thread + + /* stop Thread0 */ + li r3, 0 + bl book3e_stop_thread +10: + b 10b +20: #endif generic_secondary_common_init: diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 73eb994..61f68ad 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -181,17 +181,11 @@ static inline u32 read_spin_table_addr_l(void *spin_table) static void wake_hw_thread(void *info) { void fsl_secondary_thread_init(void); - unsigned long imsr1, inia1; - int nr = *(const int *)info; + unsigned long inia; + int hw_cpu = get_hard_smp_processor_id(*(const int *)info); - imsr1 = MSR_KERNEL; - inia1 = *(unsigned long *)fsl_secondary_thread_init; - - mttmr(TMRN_IMSR1, imsr1); - mttmr(TMRN_INIA1, inia1); - mtspr(SPRN_TENS, TEN_THREAD(1)); - - smp_generic_kick_cpu(nr); + inia = *(unsigned long *)fsl_secondary_thread_init; + book3e_start_thread(cpu_thread_in_core(hw_cpu), inia); } #endif @@ -279,7 +273,6 @@ static int smp_85xx_kick_cpu(int nr) int ret = 0; #ifdef CONFIG_PPC64 int primary = nr; - int primary_hw = get_hard_smp_processor_id(primary); #endif WARN_ON(nr < 0 || nr >= num_possible_cpus()); @@ -287,33 +280,43 @@ static int smp_85xx_kick_cpu(int nr) pr_debug("kick CPU #%d\n", nr); #ifdef CONFIG_PPC64 + booting_thread_hwid = INVALID_THREAD_HWID; /* Threads don't use the spin table */ - if (cpu_thread_in_core(nr) != 0) { - int primary = cpu_first_thread_sibling(nr); + if (threads_per_core == 2) { + booting_thread_hwid = get_hard_smp_processor_id(nr); What does setting booting_thread_hwid to INVALID_THREAD_HWID here accomplish? If threads_per_core != 2 it would never have been set to anything else, and if threads_per_core == 2 you immediately overwrite it. booting_thread_hwid is valid only for the case that one core has two threads (e6500). For e5500 and e500mc, one core one thread, "booting_thread_hwid" is invalid. "booting_thread_hwid" will determine starting which thread in generic_secondary_smp_init(). + primary = cpu_first_thread_sibl
Re: [PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores
On Thu, Aug 27, 2015 at 4:55 AM, Scott Wood wrote: On Wed, Aug 26, 2015 at 08:09:47PM +0800, Chenhui Zhao wrote: +int check_cpu_dead(unsigned int cpu) +{ + return per_cpu(cpu_state, cpu) == CPU_DEAD; +} I'm not sure this needs to be a function versus open-coded, but if you do want to make it a function, make it more obvious from the caller side by changing it to: bool is_cpu_dead(unsigned int cpu); Otherwise if I see "if (check_cpu_dead(cpu))" I don't know if the if-block is executed if the CPU is dead or if it isn't. OK. diff --git a/arch/powerpc/platforms/85xx/smp.h b/arch/powerpc/platforms/85xx/smp.h index 0b20ae3..8ee19a3 100644 --- a/arch/powerpc/platforms/85xx/smp.h +++ b/arch/powerpc/platforms/85xx/smp.h @@ -6,6 +6,7 @@ #ifdef CONFIG_SMP void __init mpc85xx_smp_init(void); int __init mpc85xx_setup_pmc(void); +int __init fsl_rcpm_init(void); #else Why wasn't this added in the patch that added fsl_rcpm_init()? -Scott Will move it to there. Thanks, -Chenhui -- 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/
[PATCH v2,3/5] 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 Signed-off-by: Tang Yuantian --- major changes for v2: * moved mpc85xx_cpu_die() * added qoriq_pm_ops->cpu_die() in smp_85xx_mach_cpu_die(). it puts the dying cpu in a low power mode arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c | 106 +++ arch/powerpc/platforms/85xx/smp.c| 74 +-- arch/powerpc/platforms/85xx/smp.h| 1 + 4 files changed, 127 insertions(+), 55 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/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c new file mode 100644 index 000..ed356dd --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include + +#include +#include +#include + +static struct ccsr_guts __iomem *guts; + +static void mpc85xx_irq_mask(int cpu) +{ + +} + +static void mpc85xx_irq_unmask(int cpu) +{ + +} + +static void mpc85xx_cpu_die(int cpu) +{ + u32 tmp; + + tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP; + mtspr(SPRN_HID0, tmp); + + /* Enter NAP mode. */ + tmp = mfmsr(); + tmp |= MSR_WE; + asm volatile( + "msync\n" + "mtmsr %0\n" + "isync\n" + : + : "r" (tmp)); +} + +static void mpc85xx_cpu_up_prepare(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 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 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_prepare = mpc85xx_cpu_up_prepare, +}; + +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("Could not map guts node address\n"); + return -ENOMEM; + } + } + + qoriq_pm_ops = &mpc85xx_pm_ops; + + return 0; +} diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 0b75e8e..f9552b8 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -2,7 +2,7 @@ * Author: Andy Fleming *Kumar Gala * - * 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 #include #include -#include #include #include #include @@ -26,9 +25,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -43,24 +42,11 @@ struct epapr_spin_table { u32 pir; }; -static
[PATCH v2,2/5] powerpc/rcpm: add RCPM driver
There is a RCPM (Run Control/Power Management) in Freescale QorIQ series processors. The device performs tasks associated with device run control and power management. The driver implements some features: mask/unmask irq, enter/exit low power states, freeze time base, etc. Signed-off-by: Chenhui Zhao Signed-off-by: Tang Yuantian --- major changes for v2: * rcpm_v1_cpu_die() and rcpm_v2_cpu_die() will be executed by the dying cpu. this way, more stable Documentation/devicetree/bindings/soc/fsl/rcpm.txt | 44 +++ arch/powerpc/include/asm/fsl_guts.h| 105 ++ arch/powerpc/include/asm/fsl_pm.h | 50 +++ arch/powerpc/platforms/85xx/Kconfig| 1 + arch/powerpc/platforms/85xx/common.c | 3 + arch/powerpc/sysdev/Kconfig| 5 + arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/fsl_rcpm.c | 390 + 8 files changed, 599 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/fsl/rcpm.txt create mode 100644 arch/powerpc/include/asm/fsl_pm.h create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt new file mode 100644 index 000..dc52f70 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt @@ -0,0 +1,44 @@ +* Run Control and Power Management + +The RCPM performs all device-level tasks associated with device run control +and power management. + +Required properites: + - reg : Offset and length of the register set of RCPM block. + - compatible : Sould contain a chip-specific RCPM block compatible string + and (if applicable) may contain a chassis-version RCPM compatible string. + Chip-specific strings are of the form "fsl,-rcpm", such as: + * "fsl,p2041-rcpm" + * "fsl,p3041-rcpm" + * "fsl,p4080-rcpm" + * "fsl,p5020-rcpm" + * "fsl,p5040-rcpm" + * "fsl,t4240-rcpm" + * "fsl,b4420-rcpm" + * "fsl,b4860-rcpm" + + Chassis-version RCPM strings include: + * "fsl,qoriq-rcpm-1.0": for chassis 1.0 rcpm + * "fsl,qoriq-rcpm-2.0": for chassis 2.0 rcpm + * "fsl,qoriq-rcpm-2.1": for chassis 2.1 rcpm + +All references to "1.0" and "2.0" refer to the QorIQ chassis version to +which the chip complies. +Chassis VersionExample Chips +------ +1.0p4080, p5020, p5040, p2041, p3041 +2.0t4240, b4860, b4420 +2.1t1040 + +Example: +The RCPM node for T4240: + rcpm: global-utilities@e2000 { + compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2.0"; + reg = <0xe2000 0x1000>; + }; + +The RCPM node for P4080: + rcpm: global-utilities@e2000 { + compatible = "fsl,qoriq-rcpm-1.0"; + reg = <0xe2000 0x1000>; + }; diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h index 43b6bb1..a67413c 100644 --- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -188,5 +188,110 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, #endif +struct ccsr_rcpm_v1 { + u8 res[4]; + __be32 cdozsr; /* 0x0004 Core Doze Status Register */ + u8 res0008[4]; + __be32 cdozcr; /* 0x000c Core Doze Control Register */ + u8 res0010[4]; + __be32 cnapsr; /* 0x0014 Core Nap Status Register */ + u8 res0018[4]; + __be32 cnapcr; /* 0x001c Core Nap Control Register */ + u8 res0020[4]; + __be32 cdozpsr;/* 0x0024 Core Doze Previous Status Register */ + u8 res0028[4]; + __be32 cnappsr;/* 0x002c Core Nap Previous Status Register */ + u8 res0030[4]; + __be32 cwaitsr;/* 0x0034 Core Wait Status Register */ + u8 res0038[4]; + __be32 cwdtdsr;/* 0x003c Core Watchdog Detect Status Register */ + __be32 powmgtcsr; /* 0x0040 PM Control&Status Register */ +#define RCPM_POWMGTCSR_SLP 0x0002 + u8 res0044[12]; + __be32 ippdexpcr; /* 0x0050 IP Powerdown Exception Control Register */ + u8 res0054[16]; + __be32 cpmimr; /* 0x0064 Core PM IRQ Mask Register */ + u8 res0068[4]; + __be32 cpmcimr;/* 0x006c Core PM Critical IRQ Mask Register */ + u8 res0070[4]; + __be32 cpmmcmr;/* 0x0074 Core PM Machine Check Mask Register */ + u8 res0078[4]; + __be32 cpmnmimr; /* 0x007c Core PM NMI Mask Register */
[PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores
Freescale E500MC and E5500 core-based platforms, like P4080, T1040, support disabling/enabling CPU dynamically. This patch adds this feature on those platforms. Signed-off-by: Chenhui Zhao Signed-off-by: Tang Yuantian --- major changes for v2: * factor out smp_85xx_start_cpu() * move fsl_rcpm_init() into mpc85xx_smp_init() due to the init sequence * add hard_irq_disable() after local_irq_save(). for platforms that implement lazy enabling/disabling of interrupts, call hard_irq_disable() to ensure interrupts are disabled physically. arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/smp.h| 3 + arch/powerpc/kernel/smp.c | 7 +- arch/powerpc/platforms/85xx/smp.c | 193 ++ arch/powerpc/platforms/85xx/smp.h | 1 + 5 files changed, 122 insertions(+), 84 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5ef2711..dd9e252 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -386,7 +386,7 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ - PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) + PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE) ---help--- Say Y here to be able to disable and re-enable individual CPUs at runtime on SMP machines. diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 825663c..4ff5b71 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -67,6 +67,9 @@ void generic_cpu_die(unsigned int cpu); void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_up(unsigned int cpu); int generic_check_cpu_restart(unsigned int cpu); +int check_cpu_dead(unsigned int cpu); +#else +#define generic_set_cpu_up(i) do { } while (0) #endif #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ec9ec20..95111f2 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -427,7 +427,7 @@ void generic_cpu_die(unsigned int cpu) for (i = 0; i < 100; i++) { smp_rmb(); - if (per_cpu(cpu_state, cpu) == CPU_DEAD) + if (check_cpu_dead(cpu)) return; msleep(100); } @@ -454,6 +454,11 @@ int generic_check_cpu_restart(unsigned int cpu) return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; } +int check_cpu_dead(unsigned int cpu) +{ + return per_cpu(cpu_state, cpu) == CPU_DEAD; +} + static bool secondaries_inhibited(void) { return kvm_hv_mode_active(); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index f9552b8..73eb994 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -10,6 +10,8 @@ * option) any later version. */ +#define pr_fmt(fmt) "smp: %s: " fmt, __func__ + #include #include #include @@ -52,6 +54,7 @@ static void mpc85xx_give_timebase(void) unsigned long flags; local_irq_save(flags); + hard_irq_disable(); while (!tb_req) barrier(); @@ -100,6 +103,7 @@ static void mpc85xx_take_timebase(void) unsigned long flags; local_irq_save(flags); + hard_irq_disable(); tb_req = 1; while (!tb_valid) @@ -135,8 +139,31 @@ static void smp_85xx_mach_cpu_die(void) while (1) ; } + +static void qoriq_cpu_kill(unsigned int cpu) +{ + int i; + + for (i = 0; i < 500; i++) { + if (check_cpu_dead(cpu)) { +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif + return; + } + msleep(20); + } + pr_err("CPU%d didn't die...\n", cpu); +} #endif +/* + * To keep it compatible with old boot program which uses + * cache-inhibit spin table, we need to flush the cache + * before accessing spin table to invalidate any staled data. + * We also need to flush the cache after writing to spin + * table to push data out. + */ static inline void flush_spin_table(void *spin_table) { flush_dcache_range((ulong)spin_table, @@ -168,51 +195,20 @@ static void wake_hw_thread(void *info) } #endif -static int smp_85xx_kick_cpu(int nr) +static int smp_85xx_start_cpu(int cpu) { - unsigned long flags; - const u64 *cpu_rel_addr; - __iomem struct epapr_spin_table *spin_table; + int ret = 0; struct device_node *np; - int hw_cpu = get_hard_smp_processor_id(nr); + const u64 *cpu_rel_addr; + unsigned long flags; int ioremappable; - int ret = 0; - - WARN_ON(nr < 0 || nr >= NR_CPUS); - WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS); - - pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); - -#ifdef CONFIG_PPC64 -
[PATCH v2,5/5] PowerPC/mpc85xx: Add CPU hotplug support for E6500
Support Freescale E6500 core-based platforms, like t4240. Support disabling/enabling individual CPU thread dynamically. Signed-off-by: Chenhui Zhao --- major changes for v2: * start Thread1 by Thread0 when we want to boot Thread1 only replacing the method of changing cpu physical id arch/powerpc/include/asm/cputhreads.h | 9 + arch/powerpc/include/asm/smp.h| 1 + arch/powerpc/kernel/head_64.S | 69 ++- arch/powerpc/platforms/85xx/smp.c | 53 ++- arch/powerpc/sysdev/fsl_rcpm.c| 2 +- 5 files changed, 106 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index ba42e46..9920f61 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h @@ -1,6 +1,7 @@ #ifndef _ASM_POWERPC_CPUTHREADS_H #define _ASM_POWERPC_CPUTHREADS_H +#ifndef __ASSEMBLY__ #include /* @@ -95,6 +96,14 @@ static inline int cpu_last_thread_sibling(int cpu) } +#ifdef CONFIG_PPC_BOOK3E +void book3e_start_thread(int thread, unsigned long addr); +void book3e_stop_thread(int thread); +#endif + +#endif /* __ASSEMBLY__ */ + +#define INVALID_THREAD_HWID0x0fff #endif /* _ASM_POWERPC_CPUTHREADS_H */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 4ff5b71..a1faa4c 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -200,6 +200,7 @@ extern void generic_secondary_thread_init(void); extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; extern char __secondary_hold; +extern unsigned int booting_thread_hwid; extern void __early_start(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index d48125d..6df2aa4 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -40,6 +40,7 @@ #include #include #include +#include /* The physical memory is laid out such that the secondary processor * spin code sits at 0x...0x00ff. On server, the vectors follow @@ -181,6 +182,44 @@ exception_marker: #endif #ifdef CONFIG_PPC_BOOK3E + .globl booting_thread_hwid +booting_thread_hwid: + .long INVALID_THREAD_HWID + .align 3 +/* + * start threads in the same cpu + * input parameters: + * r3 = the thread physical id + * r4 = the entry point where thread starts + */ +_GLOBAL(book3e_start_thread) + LOAD_REG_IMMEDIATE(r5, MSR_KERNEL) + cmpi0, r3, 0 + bne 10f + mttmr TMRN_IMSR0, r5 + mttmr TMRN_INIA0, r4 + b 11f +10: + mttmr TMRN_IMSR1, r5 + mttmr TMRN_INIA1, r4 +11: + isync + li r6, 1 + sld r6, r6, r3 + mtspr SPRN_TENS, r6 + isync + blr + +/* + * r3 = the thread physical id + */ +_GLOBAL(book3e_stop_thread) + li r4, 1 + sld r4, r4, r3 + mtspr SPRN_TENC, r4 + isync + blr + _GLOBAL(fsl_secondary_thread_init) /* Enable branch prediction */ lis r3,BUCSR_INIT@h @@ -197,8 +236,10 @@ _GLOBAL(fsl_secondary_thread_init) * but the low bit right by two bits so that the cpu numbering is * continuous. */ - mfspr r3, SPRN_PIR - rlwimi r3, r3, 30, 2, 30 + bl 10f +10:mflrr5 + addir5,r5,(booting_thread_hwid - 10b) + lwz r3,0(r5) mtspr SPRN_PIR, r3 #endif @@ -245,6 +286,30 @@ _GLOBAL(generic_secondary_smp_init) mr r3,r24 mr r4,r25 bl book3e_secondary_core_init + +/* + * If we want to boot Thread1, start Thread1 and stop Thread0. + * Note that only Thread0 will run the piece of code. + */ + LOAD_REG_ADDR(r3, booting_thread_hwid) + lwz r4, 0(r3) + cmpwi r4, INVALID_THREAD_HWID + beq 20f + cmpwr4, r24 + beq 20f + + /* start Thread1 */ + LOAD_REG_ADDR(r5, fsl_secondary_thread_init) + ld r4, 0(r5) + li r3, 1 + bl book3e_start_thread + + /* stop Thread0 */ + li r3, 0 + bl book3e_stop_thread +10: + b 10b +20: #endif generic_secondary_common_init: diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 73eb994..61f68ad 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -181,17 +181,11 @@ static inline u32 read_spin_table_addr_l(void *spin_table) static void wake_hw_thread(void *info) { void fsl_secondary_thread_init(void); - unsigned long imsr1, inia1; - int nr = *(const int *)info; + unsigned long inia; + int hw_cpu = get_hard_smp_processor_id(*(const int *)info); - imsr1 = MSR_KERNEL; - inia1 = *(unsigned long *)fsl_secondary_thread_init; - - mttmr(TMRN_IMSR1, imsr1
[PATCH v2,1/5] powerpc/cache: add cache flush operation for various e500
Various e500 core have different cache architecture, so they need different cache flush operations. Therefore, add a callback function cpu_flush_caches to the struct cpu_spec. The cache flush operation for the specific kind of e500 is selected at init time. The callback function will flush all caches inside the current cpu. Signed-off-by: Chenhui Zhao Signed-off-by: Tang Yuantian --- arch/powerpc/include/asm/cacheflush.h | 2 - arch/powerpc/include/asm/cputable.h | 11 +++ arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/cpu_setup_fsl_booke.S | 112 ++ arch/powerpc/kernel/cputable.c| 4 ++ arch/powerpc/kernel/head_fsl_booke.S | 74 arch/powerpc/platforms/85xx/smp.c | 5 +- 7 files changed, 133 insertions(+), 78 deletions(-) diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index 30b35ff..729fde4 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping)do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -extern void __flush_disable_L1(void); - extern void flush_icache_range(unsigned long, unsigned long); extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index b118072..d89b04a 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -43,6 +43,13 @@ extern int machine_check_e500(struct pt_regs *regs); extern int machine_check_e200(struct pt_regs *regs); extern int machine_check_47x(struct pt_regs *regs); +#if defined(CONFIG_E500) +extern void cpu_down_flush_e500v2(void); +extern void cpu_down_flush_e500mc(void); +extern void cpu_down_flush_e5500(void); +extern void cpu_down_flush_e6500(void); +#endif + /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ struct cpu_spec { /* CPU is matched via (PVR & pvr_mask) == pvr_value */ @@ -59,6 +66,10 @@ struct cpu_spec { unsigned inticache_bsize; unsigned intdcache_bsize; +#if defined(CONFIG_E500) + /* flush caches inside the current cpu */ + void (*cpu_down_flush)(void); +#endif /* number of performance monitor counters */ unsigned intnum_pmcs; enum powerpc_pmc_type pmc_type; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 9823057..17b672d 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -373,6 +373,9 @@ int main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); +#if defined(CONFIG_E500) + DEFINE(CPU_DOWN_FLUSH, offsetof(struct cpu_spec, cpu_down_flush)); +#endif DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index dddba3e..462aed9 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -13,11 +13,13 @@ * */ +#include #include #include #include #include #include +#include _GLOBAL(__e500_icache_setup) mfspr r0, SPRN_L1CSR1 @@ -233,3 +235,113 @@ _GLOBAL(__setup_cpu_e5500) mtlrr5 blr #endif + +/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */ +_GLOBAL(flush_dcache_L1) + mfmsr r10 + wrteei 0 + + mfspr r3,SPRN_L1CFG0 + rlwinm r5,r3,9,3 /* Extract cache block size */ + twlgti r5,1/* Only 32 and 64 byte cache blocks +* are currently defined. +*/ + li r4,32 + subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) - +* log2(number of ways) +*/ + slw r5,r4,r5/* r5 = cache block size */ + + rlwinm r7,r3,0,0xff/* Extract number of KiB in the cache */ + mulli r7,r7,13/* An 8-way cache will require 13 +* loads per set. +*/ + slw r7,r7,r6 + + /* save off HID0 and set DCFA */ + mfspr r8,SPRN_HID0 + ori r9,r8,HID0_DCFA@l + mtspr SPRN_HID0,r9 + isync + + LOAD_REG_IMMEDIATE(r6, KERNELBASE) + mr r4, r6 + mtctr r7 + +1: lwz r3,0(r4)/* Load... */ + add r4,r
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Fri, Aug 7, 2015 at 2:02 AM, Scott Wood wrote: On Thu, 2015-08-06 at 13:54 +0800, Chenhui Zhao wrote: On Thu, Aug 6, 2015 at 1:46 PM, Scott Wood wrote: > On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote: > > On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood > > > > wrote: > > > On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: > > > > On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood > > > > > > wrote: > > > > > On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: > > > > > > > > > > > > > > > > > > On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > Could you explain irq_mask()? Why would there still be > > IRQs > > > > > > destined > > > > > > > for > > > > > > > this CPU at this point? > > > > > > > > > > > > This function just masks irq by setting the registers in > > RCPM > > > > (for > > > > > > example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to > > > > this CPU > > > > > > have been migrated to other CPUs. > > > > > > > > > > So why do we need to set those bits in RCPM? Is it just > > caution? > > > > > > > > Setting these bits can mask interrupts signalled to RCPM from > > MPIC > > > > as a > > > > means of > > > > waking up from a lower power state. So, cores will not be > > waked up > > > > unexpectedly. > > > > > > Why would the MPIC be signalling those interrupts if they've been > > > masked at > > > the MPIC? > > > > > > -Scott > > > > > > > The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and > > Critical interrupts. Some of them didn't be masked in MPIC. > > What interrupt could actually happen to a sleeping cpu that this > protects > against? > > -Scott Not sure. Maybe spurious interrupts or hardware exceptions. Spurious interrupts happen due to race conditions. They don't happen because the MPIC is bored and decides to ring a CPU's doorbell and hide in the bushes. If by "hardware exceptions" you mean machine checks, how would such a machine check be generated by a core that is off? However, setting them make sure dead cpus can not be waked up unexpectedly. I'm not seeing enough value here to warrant resurrecting the old sleep node stuff. -Scott My guess maybe not accurate. My point is that electronic parts don't always work as expected. Taking preventative measures can make the system more robust. In addition, this step is required in deep sleep procedure. -Chenhui -- 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/
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Thu, Aug 6, 2015 at 1:46 PM, Scott Wood wrote: On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote: On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood wrote: > On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: > > On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood > > wrote: > > > On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: > > > > > > > > > > > > On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood > > > > > > wrote: > > > > > > > > > > > > > Could you explain irq_mask()? Why would there still be IRQs > > > > destined > > > > > for > > > > > this CPU at this point? > > > > > > > > This function just masks irq by setting the registers in RCPM > > (for > > > > example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to > > this CPU > > > > have been migrated to other CPUs. > > > > > > So why do we need to set those bits in RCPM? Is it just caution? > > > > Setting these bits can mask interrupts signalled to RCPM from MPIC > > as a > > means of > > waking up from a lower power state. So, cores will not be waked up > > unexpectedly. > > Why would the MPIC be signalling those interrupts if they've been > masked at > the MPIC? > > -Scott > The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and Critical interrupts. Some of them didn't be masked in MPIC. What interrupt could actually happen to a sleeping cpu that this protects against? -Scott Not sure. Maybe spurious interrupts or hardware exceptions. However, setting them make sure dead cpus can not be waked up unexpectedly. -Chenhui -- 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/
Re: [PATCH 3/3] PowerPC/mpc85xx: Add hotplug support on E6500 cores
On Thu, Aug 6, 2015 at 11:16 AM, Scott Wood wrote: On Wed, 2015-08-05 at 19:08 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood wrote: > On Fri, 2015-07-31 at 17:20 +0800, b29983@freescale.comwrote: > > + /* > > + * If both threads are offline, reset core to start. > > + * When core is up, Thread 0 always gets up first, > > + * so bind the current logical cpu with Thread 0. > > + */ > > + if (hw_cpu != cpu_first_thread_sibling(hw_cpu)) { > > + int hw_cpu1, hw_cpu2; > > + > > + hw_cpu1 = get_hard_smp_processor_id(primary); > > + hw_cpu2 = get_hard_smp_processor_id(primary + > > 1); > > + set_hard_smp_processor_id(primary, hw_cpu2); > > + set_hard_smp_processor_id(primary + 1, > > hw_cpu1); > > + /* get new physical cpu id */ > > + hw_cpu = get_hard_smp_processor_id(nr); > > NACK as discussed in http://patchwork.ozlabs.org/patch/454944/ > > -Scott You said, There's no need for this. I have booting from a thread1, and having it kick its thread0, working locally without messing with the hwid/cpu mapping. I still have questions here. After a core reset, how can you boot Thread1 of the core first. As I know, Thread0 boots up first by default. So the issue isn't that thread1 comes up first, but that you *want* thread1 to come up first and it won't. I don't think this remapping is an acceptable answer, though. Instead, if you need only thread1 to come up, start the core, have thread0 start thread1, and then send thread0 into whatever waiting state it would be in if thread1 had never been offlined. -Scott Remapping is a concise solution. what's the harm of it? Keeping things simple is good in my opinion. -Chenhui -- 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/
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood wrote: On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote: On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood wrote: > On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: > > > > > > On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood > > wrote: > > > > > > > Could you explain irq_mask()? Why would there still be IRQs > > destined > > > for > > > this CPU at this point? > > > > This function just masks irq by setting the registers in RCPM (for > > example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU > > have been migrated to other CPUs. > > So why do we need to set those bits in RCPM? Is it just caution? Setting these bits can mask interrupts signalled to RCPM from MPIC as a means of waking up from a lower power state. So, cores will not be waked up unexpectedly. Why would the MPIC be signalling those interrupts if they've been masked at the MPIC? -Scott The interrupts to RCPM from MPIC are IRQ, Machine Check, NMI and Critical interrupts. Some of them didn't be masked in MPIC. -Chenhui -- 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/
Re: [PATCH 3/3] PowerPC/mpc85xx: Add hotplug support on E6500 cores
On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood wrote: On Fri, 2015-07-31 at 17:20 +0800, b29...@freescale.com wrote: diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 7f0dadb..8652a49 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -189,15 +189,22 @@ static inline u32 read_spin_table_addr_l(void *spin_table) static void wake_hw_thread(void *info) { void fsl_secondary_thread_init(void); - unsigned long imsr1, inia1; + unsigned long imsr, inia; int nr = *(const int *)info; - - imsr1 = MSR_KERNEL; - inia1 = *(unsigned long *)fsl_secondary_thread_init; - - mttmr(TMRN_IMSR1, imsr1); - mttmr(TMRN_INIA1, inia1); - mtspr(SPRN_TENS, TEN_THREAD(1)); + int hw_cpu = get_hard_smp_processor_id(nr); + int thread_idx = cpu_thread_in_core(hw_cpu); + + booting_cpu_hwid = (u32)hw_cpu; Unnecessary cast. Please explain why you need booting_cpu_hwid. + imsr = MSR_KERNEL; + inia = *(unsigned long *)fsl_secondary_thread_init; + if (thread_idx == 0) { + mttmr(TMRN_IMSR0, imsr); + mttmr(TMRN_INIA0, inia); + } else { + mttmr(TMRN_IMSR1, imsr); + mttmr(TMRN_INIA1, inia); + } + mtspr(SPRN_TENS, TEN_THREAD(thread_idx)); Please rebase this on top of http://patchwork.ozlabs.org/patch/496952/ OK. + /* + * If both threads are offline, reset core to start. + * When core is up, Thread 0 always gets up first, + * so bind the current logical cpu with Thread 0. + */ + if (hw_cpu != cpu_first_thread_sibling(hw_cpu)) { + int hw_cpu1, hw_cpu2; + + hw_cpu1 = get_hard_smp_processor_id(primary); + hw_cpu2 = get_hard_smp_processor_id(primary + 1); + set_hard_smp_processor_id(primary, hw_cpu2); + set_hard_smp_processor_id(primary + 1, hw_cpu1); + /* get new physical cpu id */ + hw_cpu = get_hard_smp_processor_id(nr); NACK as discussed in http://patchwork.ozlabs.org/patch/454944/ -Scott You said, There's no need for this. I have booting from a thread1, and having it kick its thread0, working locally without messing with the hwid/cpu mapping. I still have questions here. After a core reset, how can you boot Thread1 of the core first. As I know, Thread0 boots up first by default. -Chenhui -- 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/
Re: [PATCH 2/3] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores
On Tue, Aug 4, 2015 at 5:18 AM, Scott Wood wrote: [Added linuxppc-...@lists.ozlabs.org. Besides that list being required for review of PPC patches, it feeds the patchwork that I use to track and apply patches.] On Mon, 2015-08-03 at 19:52 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:14 AM, Scott Wood wrote: > On Fri, 2015-07-31 at 17:20 +0800, b29983@freescale.comwrote: > > From: Tang Yuantian > > > > Freescale E500MC and E5500 core-based platforms, like P4080, T1040, > > support disabling/enabling CPU dynamically. > > This patch adds this feature on those platforms. > > > > Signed-off-by: Chenhui Zhao > > Signed-off-by: Tang Yuantian +{ > > + int i; > > + > > + for (i = 0; i < 5; i++) { > > + if (generic_check_cpu_dead(cpu)) { > > + qoriq_pm_ops->cpu_die(cpu); > > +#ifdef CONFIG_PPC64 > > + paca[cpu].cpu_start = 0; > > +#endif > > + return; > > + } > > + udelay(10); > > + } > > + pr_err("%s: CPU%d didn't die...\n", __func__, cpu); > > +} > > Only 500ms timeout, versus 10sec in generic_cpu_die()? The process is fast. Maybe 10 second is too large. Is it fast 100% of the time? What if the CPU you intend to die is in a long critical section? What harm is there to having a longer timeout, similar to what other platforms use? Will change the max timeout to 10 seconds. > > > #endif > > > > static inline void flush_spin_table(void *spin_table) > > @@ -246,11 +267,7 @@ static int smp_85xx_kick_cpu(int nr) > >spin_table = phys_to_virt(*cpu_rel_addr); > > > >local_irq_save(flags); > > -#ifdef CONFIG_PPC32 > > #ifdef CONFIG_HOTPLUG_CPU > > - /* Corresponding to generic_set_cpu_dead() */ > > - generic_set_cpu_up(nr); > > - > >if (system_state == SYSTEM_RUNNING) { > >/* > > * To keep it compatible with old boot program which > > uses > > @@ -263,6 +280,7 @@ static int smp_85xx_kick_cpu(int nr) > >out_be32(&spin_table->addr_l, 0); > >flush_spin_table(spin_table); > > > > + qoriq_pm_ops->cpu_up(nr); > > Again, is it possible to get here without a valid qoriq_pm_ops (i.e. > is there > anything stopping the user from trying to initiate CPU hotplug)? > > -Scott For every platform running this code, should has a valid qoriq_pm_ops. If not valid, it's a bug. How do you prevent this code from running when there is no valid qoriq_pm_ops? -Scott Will check if qoriq_pm_ops is valid. -Chenhui -- 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/
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood wrote: On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote: > On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood wrote: > > Could you explain irq_mask()? Why would there still be IRQs destined > for > this CPU at this point? This function just masks irq by setting the registers in RCPM (for example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU have been migrated to other CPUs. So why do we need to set those bits in RCPM? Is it just caution? Setting these bits can mask interrupts signalled to RCPM from MPIC as a means of waking up from a lower power state. So, cores will not be waked up unexpectedly. > @@ -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 > > Shouldn't you make sure there's a valid qoriq_pm_ops before setting > cpu_die()? Or make sure that qoriq_cpu_dying() works regardless. > > -Scott This patch is just for e500v2. The following patches will handle the case of e500mc, e5500 and e6500. What stops a user from trying to use cpu hotplug on unsupported cpus, or in a virtualized environment, and crashing here? -Scott Will set these callback functions only if qoriq_pm_ops is valid. -Chenhui -- 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/
Re: [PATCH v5] powerpc/rcpm: add RCPM driver
On Tue, Aug 4, 2015 at 4:23 AM, Scott Wood wrote: On Mon, 2015-08-03 at 19:14 +0800, Chenhui Zhao wrote: On Sat, Aug 1, 2015 at 8:45 AM, Scott Wood wrote: > On Fri, 2015-06-26 at 15:44 +0800, Yuantian.Tang@freescale.comwrote: > > +static void rcpm_v1_set_ip_power(bool enable, u32 *mask) > > +{ > > + if (enable) > > + setbits32(&rcpm_v1_regs->ippdexpcr, *mask); > > + else > > + clrbits32(&rcpm_v1_regs->ippdexpcr, *mask); > > +} > > + > > +static void rcpm_v2_set_ip_power(bool enable, u32 *mask) > > +{ > > + if (enable) > > + setbits32(&rcpm_v2_regs->ippdexpcr[0], *mask); > > + else > > + clrbits32(&rcpm_v2_regs->ippdexpcr[0], *mask); > > +} > > Why do these take "u32 *mask" instead of "u32 mask"? > > -Scott I think it can be used in the case where there are several mask values. When would that be? -Scott So far, only use one register, even though the register name is "IPPDEXPCRn" (has "n" suffix) in T4 RM. OK. Just change the parameter to "u32 mask". -Chenhui -- 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/
Re: [PATCH 3/4] powerpc: pm: add EPU FSM configuration for deep sleep
On Sat, Aug 1, 2015 at 8:41 AM, Scott Wood wrote: On Fri, 2015-07-31 at 20:53 +0800, Chenhui Zhao wrote: In the last stage of deep sleep, software will trigger a Finite State Machine (FSM) to control the hardware precedure, such as board isolation, killing PLLs, removing power, and so on. When the system is waked up by an interrupt, the FSM controls the hardware to complete the early resume precedure. This patch configure the EPU FSM preparing for deep sleep. Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/Makefile| 2 +- arch/powerpc/platforms/85xx/sleep_fsm.c | 256 arch/powerpc/platforms/85xx/sleep_fsm.h | 104 + 3 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.c create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.h When I asked why this was in drivers/platform[1], you said it was to share with LS1, and that the values used were the same -- so why did you move it to arch/powerpc? There are some changes. LS1 will use PSCI (Power State Coordination Interface) to implement deep sleep. So these code just used by PowerPC. [1] Note that other proposed patches create a drivers/soc/fsl instead of drivers/platform/fsl... We need one of them, not both. +void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val) +{ + struct fsm_reg_vals *data = val; + + BUG_ON(!base || !data); This BUG_ON is useless. If one of those is NULL you'll get an oops anyway. diff --git a/arch/powerpc/platforms/85xx/sleep_fsm.h b/arch/powerpc/platforms/85xx/sleep_fsm.h new file mode 100644 index 000..2c60b40 --- /dev/null +++ b/arch/powerpc/platforms/85xx/sleep_fsm.h @@ -0,0 +1,104 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * 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. + */ +#ifndef _FSL_SLEEP_FSM_H +#define _FSL_SLEEP_FSM_H + +#define FSL_STRIDE_4B4 +#define FSL_STRIDE_8B8 Why not just use 4/8 directly? +/* Block offsets */ +#define RCPM_BLOCK_OFFSET0x00022000 +#define EPU_BLOCK_OFFSET 0x +#define NPC_BLOCK_OFFSET 0x1000 I thought you said OK to not putting these offsets in the kernel source... -Scott OK. Will change them. -Chenhui -- 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/
Re: [PATCH 2/3] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores
On Sat, Aug 1, 2015 at 8:14 AM, Scott Wood wrote: On Fri, 2015-07-31 at 17:20 +0800, b29...@freescale.com wrote: From: Tang Yuantian Freescale E500MC and E5500 core-based platforms, like P4080, T1040, support disabling/enabling CPU dynamically. This patch adds this feature on those platforms. Signed-off-by: Chenhui Zhao Signed-off-by: Tang Yuantian --- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/smp.h| 1 + arch/powerpc/kernel/smp.c | 5 + arch/powerpc/platforms/85xx/smp.c | 39 --- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5ef2711..dd9e252 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -386,7 +386,7 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ - PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) + PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE) ---help--- Say Y here to be able to disable and re-enable individual CPUs at runtime on SMP machines. diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 825663c..bf37d17 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -67,6 +67,7 @@ void generic_cpu_die(unsigned int cpu); void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_up(unsigned int cpu); int generic_check_cpu_restart(unsigned int cpu); +int generic_check_cpu_dead(unsigned int cpu); #endif #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ec9ec20..2cca27a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -454,6 +454,11 @@ int generic_check_cpu_restart(unsigned int cpu) return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; } +int generic_check_cpu_dead(unsigned int cpu) +{ + return per_cpu(cpu_state, cpu) == CPU_DEAD; +} Is there a non-generic check_cpu_dead()? NO, just follow the name "generic_check_cpu_restart()". It gets open-coded in generic_cpu_die()... Either open-code it elsewhere, or call it check_cpu_dead() and use it everywhere there's a CPU_DEAD check. + static bool secondaries_inhibited(void) { return kvm_hv_mode_active(); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 6811a5b..7f0dadb 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -42,6 +42,7 @@ struct epapr_spin_table { u32 pir; }; +#ifdef CONFIG_HOTPLUG_CPU static u64 timebase; static int tb_req; static int tb_valid; @@ -111,7 +112,7 @@ static void mpc85xx_take_timebase(void) local_irq_restore(flags); } -#ifdef CONFIG_HOTPLUG_CPU +#ifndef CONFIG_PPC_E500MC static void e500_cpu_idle(void) What happens if we bisect to patch 1/3 and run this on e500mc? Please move the ifdef to that patch. OK. { u32 tmp; @@ -127,6 +128,7 @@ static void e500_cpu_idle(void) mtmsr(tmp); isync(); } +#endif static void qoriq_cpu_dying(void) { @@ -144,11 +146,30 @@ static void qoriq_cpu_dying(void) generic_set_cpu_dead(cpu); +#ifndef CONFIG_PPC_E500MC e500_cpu_idle(); +#endif while (1) ; } + +static void qoriq_real_cpu_die(unsigned int cpu) Real as opposed to...? It's hard to find a good name. :) +{ + int i; + + for (i = 0; i < 5; i++) { + if (generic_check_cpu_dead(cpu)) { + qoriq_pm_ops->cpu_die(cpu); +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif + return; + } + udelay(10); + } + pr_err("%s: CPU%d didn't die...\n", __func__, cpu); +} Only 500ms timeout, versus 10sec in generic_cpu_die()? The process is fast. Maybe 10 second is too large. #endif static inline void flush_spin_table(void *spin_table) @@ -246,11 +267,7 @@ static int smp_85xx_kick_cpu(int nr) spin_table = phys_to_virt(*cpu_rel_addr); local_irq_save(flags); -#ifdef CONFIG_PPC32 #ifdef CONFIG_HOTPLUG_CPU - /* Corresponding to generic_set_cpu_dead() */ - generic_set_cpu_up(nr); - if (system_state == SYSTEM_RUNNING) { /* * To keep it compatible with old boot program which uses @@ -263,6 +280,7 @@ static int smp_85xx_kick_cpu(int nr) out_be32(&spin_table->addr_l, 0); flush_spin_table(spin_table); + qoriq_pm_ops->cpu_up(nr); Again, is it possible to get here without a valid qoriq_pm_ops (i.e. is there anything stopping the user from trying to initiate CPU hotplug)? -Scott For every platform running this code,
Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations
On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood wrote: On Fri, 2015-07-31 at 17:20 +0800, b29...@freescale.com wrote: @@ -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); freeze_time_base() takes a bool. Use true/false. OK. #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) This is not the function that gets called during normal cpu idle, and it shouldn't be named to look like it is. Sorry, it's a typo. It shoule be "e500_cpu_die". { - 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(); Why is something that claims to be applicable to all qoriq directly calling an e500v2-specific function? Added "#ifndef CONFIG_PPC_E500MC" in the following patch. Could you explain irq_mask()? Why would there still be IRQs destined for this CPU at this point? This function just masks irq by setting the registers in RCPM (for example, RCPM_CPMIMR, RCPM_CPMCIMR). Actually, all irqs to this CPU have been migrated to other CPUs. @@ -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 Shouldn't you make sure there's a valid qoriq_pm_ops before setting cpu_die()? Or make sure that qoriq_cpu_dying() works regardless. -Scott This patch is just for e500v2. The following patches will handle the case of e500mc, e5500 and e6500. -Chenhui -- 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/
Re: [PATCH v5] powerpc/rcpm: add RCPM driver
On Sat, Aug 1, 2015 at 8:45 AM, Scott Wood wrote: On Fri, 2015-06-26 at 15:44 +0800, yuantian.t...@freescale.com wrote: +static void rcpm_v1_set_ip_power(bool enable, u32 *mask) +{ + if (enable) + setbits32(&rcpm_v1_regs->ippdexpcr, *mask); + else + clrbits32(&rcpm_v1_regs->ippdexpcr, *mask); +} + +static void rcpm_v2_set_ip_power(bool enable, u32 *mask) +{ + if (enable) + setbits32(&rcpm_v2_regs->ippdexpcr[0], *mask); + else + clrbits32(&rcpm_v2_regs->ippdexpcr[0], *mask); +} Why do these take "u32 *mask" instead of "u32 mask"? -Scott I think it can be used in the case where there are several mask values. -Chenhui -- 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/
Re: [PATCH] powerpc/85xx: add sleep and deep sleep support
On Sat, Aug 1, 2015 at 10:57 AM, Scott Wood wrote: On Fri, 2015-07-24 at 20:46 +0800, Chenhui Zhao wrote: +static void mpc85xx_pmc_set_wake(struct device *dev, void *enable) { int ret; + u32 value[2]; + + if (!device_may_wakeup(dev)) + return; + + if (!pmc_regs) { + dev_err(dev, "%s: PMC is unavailable\n", __func__); + return; + } + + ret = of_property_read_u32_array(dev->of_node, "sleep", value, 2); This will crash on any device without an of_node. Add this before this line: if (!dev->of_node) return; + if (ret) { + dev_dbg(dev, "%s: Can not find the \"sleep\" property.\n", + __func__); + return; + } + + if (*(int *)enable) + pmc_pmcdr_mask &= ~value[1]; + else + pmc_pmcdr_mask |= value[1]; + + if ((value[1] & 0xe0) && (pmc_flag & PMC_LOSSLESS)) + pmc_powmgtcsr = POWMGTCSR_LOSSLESS; +} What is 0xe0? -Scott This is a mask value for the register PMCDR, which includes all bits corresponding to eTSEC. Will use a macro instead. -Chenhui -- 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/
[PATCH 2/4] powerpc: get the physical base address of DCSR
Add get_dcsrbase() to get the physical base address of DCSR. Signed-off-by: Chenhui Zhao --- arch/powerpc/sysdev/fsl_soc.c | 31 +++ arch/powerpc/sysdev/fsl_soc.h | 1 + 2 files changed, 32 insertions(+) diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 99269c0..ffb7c1c 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -45,6 +45,37 @@ extern void init_fcc_ioports(struct fs_platform_info*); extern void init_fec_ioports(struct fs_platform_info*); extern void init_smc_ioports(struct fs_uart_platform_info*); static phys_addr_t immrbase = -1; +static phys_addr_t dcsrbase = -1; + +phys_addr_t get_dcsrbase(void) +{ + struct device_node *np; + const __be32 *prop; + int size; + u32 naddr; + + if (dcsrbase != -1) + return dcsrbase; + + np = of_find_compatible_node(NULL, NULL, "fsl,dcsr"); + if (!np) + return -1; + + prop = of_get_property(np, "#address-cells", &size); + if (prop && size == 4) + naddr = be32_to_cpup(prop); + else + naddr = 2; + + prop = of_get_property(np, "ranges", NULL); + if (prop) + dcsrbase = of_translate_address(np, prop + naddr); + + of_node_put(np); + + return dcsrbase; +} +EXPORT_SYMBOL(get_dcsrbase); phys_addr_t get_immrbase(void) { diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 4c5a19e..5fdd3a5 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -6,6 +6,7 @@ struct spi_device; +extern phys_addr_t get_dcsrbase(void); extern phys_addr_t get_immrbase(void); #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx) extern u32 get_brgfreq(void); -- 1.9.1 -- 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/
[PATCH 3/4] powerpc: pm: add EPU FSM configuration for deep sleep
In the last stage of deep sleep, software will trigger a Finite State Machine (FSM) to control the hardware precedure, such as board isolation, killing PLLs, removing power, and so on. When the system is waked up by an interrupt, the FSM controls the hardware to complete the early resume precedure. This patch configure the EPU FSM preparing for deep sleep. Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/Makefile| 2 +- arch/powerpc/platforms/85xx/sleep_fsm.c | 256 arch/powerpc/platforms/85xx/sleep_fsm.h | 104 + 3 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.c create mode 100644 arch/powerpc/platforms/85xx/sleep_fsm.h diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index fdae28b..87fb847 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o -obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o +obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o sleep_fsm.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/sleep_fsm.c b/arch/powerpc/platforms/85xx/sleep_fsm.c new file mode 100644 index 000..2e81d37 --- /dev/null +++ b/arch/powerpc/platforms/85xx/sleep_fsm.c @@ -0,0 +1,256 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2015 Freescale Semiconductor Inc. + * + * Author: Hongbo Zhang + * Chenhui Zhao + * + * 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 +#include +#include + +#include "sleep_fsm.h" +/* + * These values are from chip's reference manual. For example, + * the values for T1040 can be found in "8.4.3.8 Programming + * supporting deep sleep mode" of Chapter 8 "Run Control and + * Power Management (RCPM)". + * The default value can be applied to T104x, LS1021. + */ +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x8084}, + {EPECR0 + EPECR_STRIDE * 4, 0x2084}, + {EPECR0 + EPECR_STRIDE * 5, 0x0804}, + {EPECR0 + EPECR_STRIDE * 6, 0x8084}, + {EPECR0 + EPECR_STRIDE * 7, 0x8084}, + {EPECR0 + EPECR_STRIDE * 8, 0x6084}, + {EPECR0 + EPECR_STRIDE * 9, 0x0884}, + {EPECR0 + EPECR_STRIDE * 10, 0x4284}, + {EPECR0 + EPECR_STRIDE * 11, 0x9084}, + {EPECR0 + EPECR_STRIDE * 12, 0x8084}, + {EPECR0 + EPECR_STRIDE * 13, 0x0884}, + {EPECR0 + EPECR_STRIDE * 14, 0x0284}, + {EPECR0 + EPECR_STRIDE * 15, 0x0004}, + /* +* EPEVTCR (Event Processor EVT Pin Control Registers) +* SCU8 triger EVT2, and SCU11 triger EVT9 +*/ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x8001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB001}, + /* EPCMPR (Event Processor Counter Compare Registers) */ + {EPCMPR0 + EPCMPR_STRIDE * 0, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 1, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 2, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 3, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 4, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 5, 0x0020}, + {EPCMPR0 + EPCMPR_STRIDE * 6, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 7, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 8, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 9, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 10, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 11, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 12, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 13, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 14, 0x00FF}, + {EPCMPR0 + EPCMPR_STRIDE * 15, 0x00FF}, + /* EPCCR (Event Processor Counter Control Registers) */ + {EPCCR0 + EPCCR_STRIDE * 0, 0}, + {EPCCR0 + EPCCR_STRIDE * 1, 0}, + {EPCCR0 + EPCCR_STRIDE * 2, 0x9284}, + {EPCCR0 + EPCCR_STRIDE * 3, 0}, + {EPCCR0 + EPCCR_STRIDE * 4, 0x9284}, + {EPCCR0 + EPCCR_STRIDE * 5, 0x9284}, + {EPCCR0 + EPCCR_STRIDE * 6, 0},
[PATCH 4/4] powerpc: pm: support deep sleep feature on T104x
T104x has deep sleep feature, which can switch off most parts of the SoC when it is in deep sleep mode. This way, it becomes more energy-efficient. The DDR controller will also be powered off in deep sleep. Therefore, the last stage (the latter part of fsl_dp_enter_low) will run without DDR access. This piece of code and related TLBs are prefetched in advance. Due to the different initialization code between 32-bit and 64-bit, they have separate resume entry and precedure. The feature supports 32-bit and 64-bit kernel mode. Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/fsl_pm.h | 14 + arch/powerpc/kernel/fsl_booke_entry_mapping.S | 10 + arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/deepsleep.c | 322 +++ arch/powerpc/platforms/85xx/qoriq_pm.c| 81 +++- arch/powerpc/platforms/85xx/t104x_deepsleep.S | 570 ++ 7 files changed, 997 insertions(+), 3 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c create mode 100644 arch/powerpc/platforms/85xx/t104x_deepsleep.S diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h index 4b09f09..b44f484 100644 --- a/arch/powerpc/include/asm/fsl_pm.h +++ b/arch/powerpc/include/asm/fsl_pm.h @@ -12,6 +12,7 @@ #define __PPC_FSL_PM_H #ifdef __KERNEL__ +#ifndef __ASSEMBLY__ #define E500_PM_PH10 1 #define E500_PM_PH15 2 #define E500_PM_PH20 3 @@ -44,5 +45,18 @@ struct fsl_pm_ops { }; extern const struct fsl_pm_ops *qoriq_pm_ops; + +extern int fsl_dp_iomap(void); +extern void fsl_dp_iounmap(void); + +extern int fsl_enter_epu_deepsleep(void); +extern void fsl_dp_enter_low(void __iomem *ccsr_base, void __iomem *dcsr_base, +void __iomem *pld_base, int pld_flag); +extern void fsl_booke_deep_sleep_resume(void); +#endif /* __ASSEMBLY__ */ + +#define T1040QDS_TETRA_FLAG1 +#define T104xRDB_CPLD_FLAG 2 + #endif /* __KERNEL__ */ #endif /* __PPC_FSL_PM_H */ diff --git a/arch/powerpc/kernel/fsl_booke_entry_mapping.S b/arch/powerpc/kernel/fsl_booke_entry_mapping.S index f22e7e4..32ec426f 100644 --- a/arch/powerpc/kernel/fsl_booke_entry_mapping.S +++ b/arch/powerpc/kernel/fsl_booke_entry_mapping.S @@ -170,6 +170,10 @@ skpinv:addir6,r6,1 /* Increment */ lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l mtspr SPRN_MAS2,r6 +#ifdef ENTRY_DEEPSLEEP_SETUP + LOAD_REG_IMMEDIATE(r8, MEMORY_START) + ori r8,r8,(MAS3_SX|MAS3_SW|MAS3_SR) +#endif mtspr SPRN_MAS3,r8 tlbwe @@ -212,12 +216,18 @@ next_tlb_setup: #error You need to specify the mapping or not use this at all. #endif +#ifdef ENTRY_DEEPSLEEP_SETUP + LOAD_REG_ADDR(r6, 2f) + mfmsr r7 + rlwinm r7,r7,0,~(MSR_IS|MSR_DS) +#else lis r7,MSR_KERNEL@h ori r7,r7,MSR_KERNEL@l bl 1f /* Find our address */ 1: mflrr9 rlwimi r6,r9,0,20,31 addir6,r6,(2f - 1b) +#endif mtspr SPRN_SRR0,r6 mtspr SPRN_SRR1,r7 rfi /* start execution out of TLB1[0] entry */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index d48125d..b9eb02a 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -696,7 +696,7 @@ _GLOBAL(start_secondary_resume) /* * This subroutine clobbers r11 and r12 */ -enable_64b_mode: +_GLOBAL(enable_64b_mode) mfmsr r11 /* grab the current MSR */ #ifdef CONFIG_PPC_BOOK3E orisr11,r11,0x8000 /* CM bit set, we'll set ICM later */ diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 87fb847..a73d563 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o sleep_fsm.o +obj-$(CONFIG_FSL_QORIQ_PM) += deepsleep.o t104x_deepsleep.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/deepsleep.c b/arch/powerpc/platforms/85xx/deepsleep.c new file mode 100644 index 000..5de904d --- /dev/null +++ b/arch/powerpc/platforms/85xx/deepsleep.c @@ -0,0 +1,322 @@ +/* + * Support deep sleep feature for T104x + * + * Copyright 2015 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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 +#include +#include +#include +#in
[PATCH 1/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
In sleep mode, the clocks of e500 cores and unused IP blocks is turned off. The IP blocks which are allowed to wake up the processor are still running. The sleep mode is equal to the Standby state in Linux. Use the command to enter sleep mode: echo standby > /sys/power/state Signed-off-by: Chenhui Zhao --- Note: This patch set is based on CPU hotplug patches. arch/powerpc/Kconfig | 3 +- arch/powerpc/platforms/85xx/Kconfig| 5 +++ arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/qoriq_pm.c | 59 ++ arch/powerpc/platforms/86xx/Kconfig| 1 + 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index dd9e252..57bbbfb 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -233,7 +233,7 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ - (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ + FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \ || 44x || 40x config PPC_DCR_NATIVE @@ -753,7 +753,6 @@ config FSL_PCI config FSL_PMC bool - default y depends on SUSPEND && (PPC_85xx || PPC_86xx) help Freescale MPC85xx/MPC86xx power management controller support diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index e626461..dff2ea6 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -9,6 +9,8 @@ menuconfig FSL_SOC_BOOKE select SERIAL_8250_EXTENDED if SERIAL_8250 select SERIAL_8250_SHARE_IRQ if SERIAL_8250 select FSL_CORENET_RCPM if PPC_E500MC + select FSL_QORIQ_PM if SUSPEND && PPC_E500MC + select FSL_PMC if SUSPEND && !PPC_E500MC default y if FSL_SOC_BOOKE @@ -289,3 +291,6 @@ endif # FSL_SOC_BOOKE config TQM85xx bool + +config FSL_QORIQ_PM + bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 7bc86da..fdae28b 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o +obj-$(CONFIG_FSL_QORIQ_PM) += qoriq_pm.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c b/arch/powerpc/platforms/85xx/qoriq_pm.c new file mode 100644 index 000..27ec337 --- /dev/null +++ b/arch/powerpc/platforms/85xx/qoriq_pm.c @@ -0,0 +1,59 @@ +/* + * Support Power Management feature + * + * Copyright 2014-2015 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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 +#include +#include + +#include + +static int qoriq_suspend_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + cur_cpu_spec->cpu_down_flush(); + ret = qoriq_pm_ops->plat_enter_sleep(); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int qoriq_suspend_valid(suspend_state_t state) +{ + unsigned int pm_modes; + + pm_modes = qoriq_pm_ops->get_pm_modes(); + + if ((state == PM_SUSPEND_STANDBY) && (pm_modes & FSL_PM_SLEEP)) + return 1; + + return 0; +} + +static const struct platform_suspend_ops qoriq_suspend_ops = { + .valid = qoriq_suspend_valid, + .enter = qoriq_suspend_enter, +}; + +static int __init qoriq_suspend_init(void) +{ + suspend_set_ops(&qoriq_suspend_ops); + + return 0; +} +arch_initcall(qoriq_suspend_init); diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 1afd1e4..09638e0 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -5,6 +5,7 @@ menuconfig PPC_86xx select FSL_SOC select ALTIVEC select ARCH_WANT_OPTIONAL_GPIOLIB + select FSL_PMC if SUSPEND help The Freescale E600 SoCs have 74xx cores. -- 1.9.1 -- 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/
[PATCH] powerpc/85xx: add sleep and deep sleep support
In sleep PM mode, the clocks of e500 core and unused IP blocks is turned off. IP blocks which are allowed to wake up the processor are still running. Some Freescale chips like MPC8536 and P1022 has deep sleep PM mode in addtion to the sleep PM mode. While in deep sleep PM mode, additionally, the power supply is removed from e500 core and most IP blocks. Only the blocks needed to wake up the chip out of deep sleep are ON. This patch supports 32-bit and 36-bit address space. The sleep mode is equal to the Standby state in Linux. The deep sleep mode is equal to the Suspend-to-RAM state of Linux Power Management. Command to enter sleep mode. echo standby > /sys/power/state Command to enter deep sleep mode. echo mem > /sys/power/state Signed-off-by: Li Yang Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/cacheflush.h | 5 + arch/powerpc/platforms/85xx/Makefile| 3 + arch/powerpc/platforms/85xx/pmc_deepsleep.S | 645 arch/powerpc/sysdev/fsl_pmc.c | 146 ++- arch/powerpc/sysdev/fsl_soc.h | 5 + 5 files changed, 785 insertions(+), 19 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/pmc_deepsleep.S diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index 30b35ff..9ec4c31 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -31,6 +31,11 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_unlock(mapping) do { } while (0) extern void __flush_disable_L1(void); +#ifdef CONFIG_FSL_BOOKE +extern void flush_dcache_L1(void); +#else +#define flush_dcache_L1() do { } while (0) +#endif extern void flush_icache_range(unsigned long, unsigned long); extern void flush_icache_user_range(struct vm_area_struct *vma, diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 1fe7fb9..d187253 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -2,6 +2,9 @@ # Makefile for the PowerPC 85xx linux kernel. # obj-$(CONFIG_SMP) += smp.o +ifneq ($(CONFIG_PPC_E500MC),y) +obj-$(CONFIG_SUSPEND) += pmc_deepsleep.o +endif obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/pmc_deepsleep.S b/arch/powerpc/platforms/85xx/pmc_deepsleep.S new file mode 100644 index 000..57fd4f4 --- /dev/null +++ b/arch/powerpc/platforms/85xx/pmc_deepsleep.S @@ -0,0 +1,645 @@ +/* + * Enter and leave deep sleep/sleep state on MPC85xx + * + * Author: Scott Wood + * + * Copyright 2006-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 +#include +#include +#include + +#define SS_TB 0x00 +#define SS_HID 0x08 /* 2 HIDs */ +#define SS_IAC 0x10 /* 2 IACs */ +#define SS_DAC 0x18 /* 2 DACs */ +#define SS_DBCR0x20 /* 3 DBCRs */ +#define SS_PID 0x2c /* 3 PIDs */ +#define SS_SPRG0x38 /* 8 SPRGs */ +#define SS_IVOR0x58 /* 20 interrupt vectors */ +#define SS_TCR 0xa8 +#define SS_BUCSR 0xac +#define SS_L1CSR 0xb0 /* 2 L1CSRs */ +#define SS_MSR 0xb8 +#define SS_USPRG 0xbc +#define SS_GPREG 0xc0 /* r12-r31 */ +#define SS_LR 0x110 +#define SS_CR 0x114 +#define SS_SP 0x118 +#define SS_CURRENT 0x11c +#define SS_IVPR0x120 +#define SS_BPTR0x124 + + +#define STATE_SAVE_SIZE 0x128 + + .section .data + .align 5 +mpc85xx_sleep_save_area: + .space STATE_SAVE_SIZE +ccsrbase_low: + .long 0 +ccsrbase_high: + .long 0 +powmgtreq: + .long 0 + + .section .text + + /* r3 = virtual address of L2 controller, WIMG = 01xx */ +flush_disable_L2: + /* It's a write-through cache, so only invalidation is needed. */ + mbar + isync + lwz r4, 0(r3) + li r5, 1 + rlwimi r4, r5, 30, 0xc000 + stw r4, 0(r3) + + /* Wait for the invalidate to finish */ +1: lwz r4, 0(r3) + andis. r4, r4, 0x4000 + bne 1b + mbar + + blr + + /* r3 = virtual address of L2 controller, WIMG = 01xx */ +invalidate_enable_L2: + mbar + isync + lwz r4, 0(r3) + li r5, 3 + rlwimi r4, r5, 30, 0xc000 + stw r4, 0(r3) + + /* Wait for the invalidate to finish */ +1: lwz r4, 0(r3) + andis. r4, r4, 0x4000 + bne 1b + mbar + + blr + + /* +* r3 = high word of physical address of CCSR +* r4 = low word of physical address of CCSR +* r5 = JOG or deep sl
[PATCH] powerpc/corenet: use the mixed mode of MPIC when enabling CPU hotplug
Core reset may cause issue if using the proxy mode of MPIC. Use the mixed mode of MPIC if enabling CPU hotplug. Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/corenet_generic.c | 8 1 file changed, 8 insertions(+) diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index bd839dc..0119224 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c @@ -212,7 +212,15 @@ define_machine(corenet_generic) { .pcibios_fixup_bus = fsl_pcibios_fixup_bus, .pcibios_fixup_phb = fsl_pcibios_fixup_phb, #endif +/* + * Core reset may cause issue if using the proxy mode of MPIC. + * So, use the mixed mode of MPIC if enabling CPU hotplug. + */ +#ifdef CONFIG_HOTPLUG_CPU + .get_irq= mpic_get_irq, +#else .get_irq= mpic_get_coreint_irq, +#endif .restart= fsl_rstcr_restart, .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, -- 1.9.1 -- 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/
[PATCH 2/4] powerpc/rcpm: add RCPM driver
There is a RCPM (Run Control/Power Management) in Freescale QorIQ series processors. The device performs tasks associated with device run control and power management. The driver implements some features: mask/unmask irq, enter/exit low power states, freeze time base, etc. Signed-off-by: Chenhui Zhao --- Documentation/devicetree/bindings/soc/fsl/rcpm.txt | 23 ++ arch/powerpc/include/asm/fsl_guts.h| 105 ++ arch/powerpc/include/asm/fsl_pm.h | 49 +++ arch/powerpc/platforms/85xx/Kconfig| 1 + arch/powerpc/sysdev/Kconfig| 5 + arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/fsl_rcpm.c | 353 + 7 files changed, 537 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/fsl/rcpm.txt create mode 100644 arch/powerpc/include/asm/fsl_pm.h create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt new file mode 100644 index 000..8c21b6c --- /dev/null +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt @@ -0,0 +1,23 @@ +* Run Control and Power Management + +The RCPM performs all device-level tasks associated with device run control +and power management. + +Required properites: + - reg : Offset and length of the register set of RCPM block. + - compatible : Specifies the compatibility list for the RCPM. The type +should be string, such as "fsl,qoriq-rcpm-1.0", "fsl,qoriq-rcpm-2.0". + +Example: +The RCPM node for T4240: + rcpm: global-utilities@e2000 { + compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2.0"; + reg = <0xe2000 0x1000>; + }; + +The RCPM node for P4080: + rcpm: global-utilities@e2000 { + compatible = "fsl,qoriq-rcpm-1.0"; + reg = <0xe2000 0x1000>; + #sleep-cells = <1>; + }; diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h index 43b6bb1..96018ee 100644 --- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -188,5 +188,110 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, #endif +struct ccsr_rcpm_v1 { + u8 res[4]; + __be32 cdozsr; /* 0x0004 Core Doze Status Register */ + u8 res0008[4]; + __be32 cdozcr; /* 0x000c Core Doze Control Register */ + u8 res0010[4]; + __be32 cnapsr; /* 0x0014 Core Nap Status Register */ + u8 res0018[4]; + __be32 cnapcr; /* 0x001c Core Nap Control Register */ + u8 res0020[4]; + __be32 cdozpsr;/* 0x0024 Core Doze Previous Status Register */ + u8 res0028[4]; + __be32 cnappsr;/* 0x002c Core Nap Previous Status Register */ + u8 res0030[4]; + __be32 cwaitsr;/* 0x0034 Core Wait Status Register */ + u8 res0038[4]; + __be32 cwdtdsr;/* 0x003c Core Watchdog Detect Status Register */ + __be32 powmgtcsr; /* 0x0040 Power Management Control&Status Register */ +#define RCPM_POWMGTCSR_SLP 0x0002 + u8 res0044[12]; + __be32 ippdexpcr; /* 0x0050 IP Powerdown Exception Control Register */ + u8 res0054[16]; + __be32 cpmimr; /* 0x0064 Core PM IRQ Mask Register */ + u8 res0068[4]; + __be32 cpmcimr;/* 0x006c Core PM Critical IRQ Mask Register */ + u8 res0070[4]; + __be32 cpmmcmr;/* 0x0074 Core PM Machine Check Mask Register */ + u8 res0078[4]; + __be32 cpmnmimr; /* 0x007c Core PM NMI Mask Register */ + u8 res0080[4]; + __be32 ctbenr; /* 0x0084 Core Time Base Enable Register */ + u8 res0088[4]; + __be32 ctbckselr; /* 0x008c Core Time Base Clock Select Register */ + u8 res0090[4]; + __be32 ctbhltcr; /* 0x0094 Core Time Base Halt Control Register */ + u8 res0098[4]; + __be32 cmcpmaskcr; /* 0x00a4 Core Machine Check Mask Register */ +}; + +struct ccsr_rcpm_v2 { + u8 res_00[12]; + __be32 tph10sr0; /* Thread PH10 Status Register */ + u8 res_10[12]; + __be32 tph10setr0; /* Thread PH10 Set Control Register */ + u8 res_20[12]; + __be32 tph10clrr0; /* Thread PH10 Clear Control Register */ + u8 res_30[12]; + __be32 tph10psr0; /* Thread PH10 Previous Status Register */ + u8 res_40[12]; + __be32 twaitsr0; /* Thread Wait Status Register */ + u8 res_50[96]; + __be32 pcph15sr; /* Physical Core PH15 Status Register */ + __be32 pcph15setr; /* Physical Core PH15 Set Control Register */ + __be32 pcph15clrr; /* Physical Core PH15 Clear C
[PATCH 3/4] powerpc: support CPU hotplug for e500mc, e5500 and e6500
Implemented CPU hotplug on e500mc, e5500 and e6500, and support multiple threads mode and 64-bits mode. For e6500 with two threads, if one thread is online, it can enable/disable the other thread in the same core. If two threads of one core are offline, the core will enter the PH20 state (a low power state). When the core is up again, Thread0 is up first, and it will be bound with the present booting cpu. This way, all CPUs can hotplug separately. Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/fsl_pm.h | 4 + arch/powerpc/include/asm/smp.h| 2 + arch/powerpc/kernel/head_64.S | 20 +++-- arch/powerpc/kernel/smp.c | 5 ++ arch/powerpc/platforms/85xx/smp.c | 182 +- arch/powerpc/sysdev/fsl_rcpm.c| 56 7 files changed, 220 insertions(+), 51 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 22b0940..9846c83 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -380,7 +380,7 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ - PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) + PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE) ---help--- Say Y here to be able to disable and re-enable individual CPUs at runtime on SMP machines. diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h index bbe6089..579f495 100644 --- a/arch/powerpc/include/asm/fsl_pm.h +++ b/arch/powerpc/include/asm/fsl_pm.h @@ -34,6 +34,10 @@ struct fsl_pm_ops { void (*cpu_enter_state)(int cpu, int state); /* exit the CPU from the specified state */ void (*cpu_exit_state)(int cpu, int state); + /* cpu up */ + void (*cpu_up)(int cpu); + /* cpu die */ + void (*cpu_die)(int cpu); /* place the platform in the sleep state */ int (*plat_enter_sleep)(void); /* freeze the time base */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index d607df5..1e500ed 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -67,6 +67,7 @@ void generic_cpu_die(unsigned int cpu); void generic_set_cpu_dead(unsigned int cpu); void generic_set_cpu_up(unsigned int cpu); int generic_check_cpu_restart(unsigned int cpu); +int generic_check_cpu_dead(unsigned int cpu); #endif #ifdef CONFIG_PPC64 @@ -198,6 +199,7 @@ extern void generic_secondary_thread_init(void); extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; extern char __secondary_hold; +extern unsigned int __cur_boot_cpu; extern void __early_start(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index d48125d..ac89050 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -181,6 +181,10 @@ exception_marker: #endif #ifdef CONFIG_PPC_BOOK3E + .globl __cur_boot_cpu +__cur_boot_cpu: + .long 0x0 + .align 3 _GLOBAL(fsl_secondary_thread_init) /* Enable branch prediction */ lis r3,BUCSR_INIT@h @@ -189,16 +193,14 @@ _GLOBAL(fsl_secondary_thread_init) isync /* -* Fix PIR to match the linear numbering in the device tree. -* -* On e6500, the reset value of PIR uses the low three bits for -* the thread within a core, and the upper bits for the core -* number. There are two threads per core, so shift everything -* but the low bit right by two bits so that the cpu numbering is -* continuous. +* The current thread has been in 64-bit mode, +* see the value of TMRN_IMSR. +* compute the address of __cur_boot_cpu */ - mfspr r3, SPRN_PIR - rlwimi r3, r3, 30, 2, 30 + bl 10f +10:mflrr22 + addir22,r22,(__cur_boot_cpu - 10b) + lwz r3,0(r22) mtspr SPRN_PIR, r3 #endif diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ec9ec20..2cca27a 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -454,6 +454,11 @@ int generic_check_cpu_restart(unsigned int cpu) return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; } +int generic_check_cpu_dead(unsigned int cpu) +{ + return per_cpu(cpu_state, cpu) == CPU_DEAD; +} + static bool secondaries_inhibited(void) { return kvm_hv_mode_active(); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index fba474f..f51441b 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -2,7 +2,7 @@ * Author: Andy Fleming *Kumar Gala * - * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc. + * Copyright 2006-2008, 2011-2012, 2015 Freescale Semiconductor
[PATCH 1/4] powerpc/cache: add cache flush operation for various e500
Various e500 core have different cache architecture, so they need different cache flush operations. Therefore, add a callback function cpu_flush_caches to the struct cpu_spec. The cache flush operation for the specific kind of e500 is selected at init time. The callback function will flush all caches inside the current cpu. Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/cacheflush.h | 2 - arch/powerpc/include/asm/cputable.h | 11 +++ arch/powerpc/kernel/asm-offsets.c | 3 + arch/powerpc/kernel/cpu_setup_fsl_booke.S | 114 +- arch/powerpc/kernel/cputable.c| 4 ++ arch/powerpc/kernel/head_fsl_booke.S | 74 --- arch/powerpc/platforms/85xx/smp.c | 3 +- 7 files changed, 133 insertions(+), 78 deletions(-) diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index 30b35ff..729fde4 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping)do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -extern void __flush_disable_L1(void); - extern void flush_icache_range(unsigned long, unsigned long); extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 5cf5a6d..c776efe4 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -43,6 +43,13 @@ extern int machine_check_e500(struct pt_regs *regs); extern int machine_check_e200(struct pt_regs *regs); extern int machine_check_47x(struct pt_regs *regs); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) +extern void __flush_caches_e500v2(void); +extern void __flush_caches_e500mc(void); +extern void __flush_caches_e5500(void); +extern void __flush_caches_e6500(void); +#endif + /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ struct cpu_spec { /* CPU is matched via (PVR & pvr_mask) == pvr_value */ @@ -59,6 +66,10 @@ struct cpu_spec { unsigned inticache_bsize; unsigned intdcache_bsize; +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + /* flush caches inside the current cpu */ + void (*cpu_flush_caches)(void); +#endif /* number of performance monitor counters */ unsigned intnum_pmcs; enum powerpc_pmc_type pmc_type; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 4717859..9567930 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -372,6 +372,9 @@ int main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + DEFINE(CPU_FLUSH_CACHES, offsetof(struct cpu_spec, cpu_flush_caches)); +#endif DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index dddba3e..c8c251f 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -1,7 +1,7 @@ /* * This file contains low level CPU setup functions. * Kumar Gala - * Copyright 2009 Freescale Semiconductor, Inc. + * Copyright 2009, 2015 Freescale Semiconductor, Inc. * * Based on cpu_setup_6xx code by * Benjamin Herrenschmidt @@ -13,11 +13,13 @@ * */ +#include #include #include #include #include #include +#include _GLOBAL(__e500_icache_setup) mfspr r0, SPRN_L1CSR1 @@ -233,3 +235,113 @@ _GLOBAL(__setup_cpu_e5500) mtlrr5 blr #endif + +/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */ +_GLOBAL(flush_dcache_L1) + mfmsr r10 + wrteei 0 + + mfspr r3,SPRN_L1CFG0 + rlwinm r5,r3,9,3 /* Extract cache block size */ + twlgti r5,1/* Only 32 and 64 byte cache blocks +* are currently defined. +*/ + li r4,32 + subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) - +* log2(number of ways) +*/ + slw r5,r4,r5/* r5 = cache block size */ + + rlwinm r7,r3,0,0xff/* Extract number of KiB in the cache */ + mulli r7,r7,13/* An 8-way cache will require 13 +* loads per
[PATCH 4/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
In sleep mode, the clocks of e500 cores and unused IP blocks is turned off. The IP blocks which are allowed to wake up the processor are still running. The sleep mode is equal to the Standby state in Linux. Use the command to enter sleep mode: echo standby > /sys/power/state Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig | 3 +- arch/powerpc/platforms/85xx/Kconfig| 5 +++ arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/qoriq_pm.c | 59 ++ arch/powerpc/platforms/86xx/Kconfig| 1 + 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9846c83..162eb53 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -233,7 +233,7 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ - (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ + FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \ || 44x || 40x config PPC_DCR_NATIVE @@ -747,7 +747,6 @@ config FSL_PCI config FSL_PMC bool - default y depends on SUSPEND && (PPC_85xx || PPC_86xx) help Freescale MPC85xx/MPC86xx power management controller support diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index ae1b8a2..b7c762e 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -9,6 +9,8 @@ menuconfig FSL_SOC_BOOKE select SERIAL_8250_EXTENDED if SERIAL_8250 select SERIAL_8250_SHARE_IRQ if SERIAL_8250 select FSL_CORENET_RCPM if PPC_E500MC + select FSL_QORIQ_PM if SUSPEND && PPC_E500MC + select FSL_PMC if SUSPEND && !PPC_E500MC default y if FSL_SOC_BOOKE @@ -289,3 +291,6 @@ endif # FSL_SOC_BOOKE config TQM85xx bool + +config FSL_QORIQ_PM + bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 1fe7fb9..65dfb60 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_QORIQ_PM) += qoriq_pm.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c b/arch/powerpc/platforms/85xx/qoriq_pm.c new file mode 100644 index 000..7594f08 --- /dev/null +++ b/arch/powerpc/platforms/85xx/qoriq_pm.c @@ -0,0 +1,59 @@ +/* + * Support Power Management feature + * + * Copyright 2014-2015 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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 +#include +#include + +#include + +static int qoriq_suspend_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + cur_cpu_spec->cpu_flush_caches(); + ret = qoriq_pm_ops->plat_enter_sleep(); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int qoriq_suspend_valid(suspend_state_t state) +{ + unsigned int pm_modes; + + pm_modes = qoriq_pm_ops->get_pm_modes(); + + if ((state == PM_SUSPEND_STANDBY) && (pm_modes & FSL_PM_SLEEP)) + return 1; + + return 0; +} + +static const struct platform_suspend_ops qoriq_suspend_ops = { + .valid = qoriq_suspend_valid, + .enter = qoriq_suspend_enter, +}; + +static int __init qoriq_suspend_init(void) +{ + suspend_set_ops(&qoriq_suspend_ops); + + return 0; +} +arch_initcall(qoriq_suspend_init); diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 1afd1e4..09638e0 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -5,6 +5,7 @@ menuconfig PPC_86xx select FSL_SOC select ALTIVEC select ARCH_WANT_OPTIONAL_GPIOLIB + select FSL_PMC if SUSPEND help The Freescale E600 SoCs have 74xx cores. -- 1.9.1 -- 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/
[PATCH 4/4] arm: ls1021a: set wakeup devices dynamically for sleep/deep sleep
If a device works as a wakeup source, it will keep working in the period of sleep/deep sleep. This patch sets the wakeup devices according to the wakeup attribute of device. Signed-off-by: Chenhui Zhao --- arch/arm/boot/dts/ls1021a.dtsi | 2 + arch/arm/mach-imx/pm-ls1.c | 101 + 2 files changed, 103 insertions(+) diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 0c51ce0..64534c0 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -136,6 +136,7 @@ sdhci,auto-cmd12; big-endian; bus-width = <4>; + sleep = <&rcpm 0x0080 0x0>; status = "disabled"; }; @@ -289,6 +290,7 @@ interrupts = ; clocks = <&sysclk>; clock-names = "ipg"; + sleep = <&rcpm 0x0 0x4000>; status = "disabled"; }; diff --git a/arch/arm/mach-imx/pm-ls1.c b/arch/arm/mach-imx/pm-ls1.c index 4f9ca80..b11fcb2 100644 --- a/arch/arm/mach-imx/pm-ls1.c +++ b/arch/arm/mach-imx/pm-ls1.c @@ -35,6 +35,13 @@ #define CCSR_SCFG_DPSLPCR 0 #define CCSR_SCFG_DPSLPCR_VAL 0x1 #define CCSR_SCFG_PMCINTECR0x160 +#define CCSR_SCFG_PMCINTECR_LPUART 0x4000 +#define CCSR_SCFG_PMCINTECR_FTM0x2000 +#define CCSR_SCFG_PMCINTECR_GPIO 0x1000 +#define CCSR_SCFG_PMCINTECR_IRQ0 0x0800 +#define CCSR_SCFG_PMCINTECR_IRQ1 0x0400 +#define CCSR_SCFG_PMCINTECR_ETSECRXG0 0x0080 +#define CCSR_SCFG_PMCINTECR_ETSECRXG1 0x0040 #define CCSR_SCFG_PMCINTLECR 0x164 #define CCSR_SCFG_PMCINTSR 0x168 #define CCSR_SCFG_SPARECR2 0x504 @@ -50,7 +57,11 @@ #define CCSR_RCPM_CLPCL10SETR 0x1c4 #define CCSR_RCPM_CLPCL10SETR_C0 0x1 #define CCSR_RCPM_IPPDEXPCR0 0x140 +#define CCSR_RCPM_IPPDEXPCR0_ETSEC 0x8000 +#define CCSR_RCPM_IPPDEXPCR0_GPIO 0x0040 #define CCSR_RCPM_IPPDEXPCR1 0x144 +#define CCSR_RCPM_IPPDEXPCR1_LPUART0x4000 +#define CCSR_RCPM_IPPDEXPCR1_FLEXTIMER 0x2000 #define QIXIS_CTL_SYS 0x5 #define QIXIS_CTL_SYS_EVTSW_MASK 0x0c @@ -64,6 +75,10 @@ /* use the last page of SRAM */ #define SRAM_CODE_BASE_PHY (OCRAM_BASE + OCRAM_SIZE - PAGE_SIZE) +#define SLEEP_ARRAY_SIZE 3 + +static u32 ippdexpcr0, ippdexpcr1; + struct ls1_pm_baseaddr { void __iomem *rcpm; void __iomem *epu; @@ -242,6 +257,49 @@ static void ls1_board_resume(void) iowrite8(tmp, ls1_pm_base.fpga + QIXIS_CTL_SYS); } +static void ls1_setup_pmc_int(void) +{ + u32 pmcintecr; + + pmcintecr = 0; + if (ippdexpcr0 & CCSR_RCPM_IPPDEXPCR0_ETSEC) + pmcintecr |= CCSR_SCFG_PMCINTECR_ETSECRXG0 | + CCSR_SCFG_PMCINTECR_ETSECRXG1; + + if (ippdexpcr0 & CCSR_RCPM_IPPDEXPCR0_GPIO) + pmcintecr |= CCSR_SCFG_PMCINTECR_GPIO; + + if (ippdexpcr1 & CCSR_RCPM_IPPDEXPCR1_LPUART) + pmcintecr |= CCSR_SCFG_PMCINTECR_LPUART; + + if (ippdexpcr1 & CCSR_RCPM_IPPDEXPCR1_FLEXTIMER) + pmcintecr |= CCSR_SCFG_PMCINTECR_FTM; + + /* always set external IRQ pins as wakeup source */ + pmcintecr |= CCSR_SCFG_PMCINTECR_IRQ0 | CCSR_SCFG_PMCINTECR_IRQ1; + + /* enable wakeup interrupt during deep sleep */ + iowrite32be(pmcintecr, ls1_pm_base.scfg + CCSR_SCFG_PMCINTECR); + iowrite32be(0, ls1_pm_base.scfg + CCSR_SCFG_PMCINTLECR); + /* clear PMC interrupt status */ + iowrite32be(0x, ls1_pm_base.scfg + CCSR_SCFG_PMCINTSR); +} + +static void ls1_clear_pmc_int(void) +{ + /* disable wakeup interrupt during deep sleep */ + iowrite32be(0, ls1_pm_base.scfg + CCSR_SCFG_PMCINTECR); + /* clear PMC interrupt status */ + iowrite32be(0x, ls1_pm_base.scfg + CCSR_SCFG_PMCINTSR); +} + +/* set IP powerdown exception, make them work during sleep/deep sleep */ +static void ls1_set_powerdown(void) +{ + iowrite32be(ippdexpcr0, ls1_pm_base.rcpm + CCSR_RCPM_IPPDEXPCR0); + iowrite32be(ippdexpcr1, ls1_pm_base.rcpm + CCSR_RCPM_IPPDEXPCR1); +} + static void ls1_enter_deepsleep(void) { /* save DDR data */ @@ -265,8 +323,12 @@ static void ls1_enter_deepsleep(void) /* copy the last stage code to sram */ ls1_copy_sram_code(); + ls1_setup_pmc_int(); + cpu_suspend(SRAM_CODE_BASE_PHY, ls1_start_deepsleep); + ls1_clear_pmc_int(); + /* disable Warm Device Reset */ ls1_clrsetbits_be32(ls1_pm_base.scfg + CCSR_SCFG_DPSLPCR, CCSR_SCFG_DPSLPCR_VAL, 0); @@ -274,10 +336,45 @@ static void ls1_enter_deepsleep(void) ls1
[PATCH 1/4] fsl: add EPU FSM configuration for deep sleep
T104x, T1024 and LS1021 of Freescale have a Finite State Machine (FSM) to control the hardware precedure in deep sleep. Software will start the FSM to enter deep sleep after finishing prepare work. Then, when receiving a wakeup event, the FSM will restore the SoC to work. This driver configures and clears the FSM registers for deep sleep. Note that the sequence of clearing the FSM registers does matter, should follow the sequence mentioned in the reference manual. Signed-off-by: Chenhui Zhao --- drivers/platform/Kconfig | 2 + drivers/platform/Makefile| 1 + drivers/platform/fsl/Kconfig | 11 ++ drivers/platform/fsl/Makefile| 5 + drivers/platform/fsl/sleep_fsm.c | 263 +++ drivers/platform/fsl/sleep_fsm.h | 104 6 files changed, 386 insertions(+) create mode 100644 drivers/platform/fsl/Kconfig create mode 100644 drivers/platform/fsl/Makefile create mode 100644 drivers/platform/fsl/sleep_fsm.c create mode 100644 drivers/platform/fsl/sleep_fsm.h diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 09fde58..85e3c95 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -6,3 +6,5 @@ source "drivers/platform/goldfish/Kconfig" endif source "drivers/platform/chrome/Kconfig" + +source "drivers/platform/fsl/Kconfig" diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 3656b7b..37c6f72 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_OLPC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ +obj-$(CONFIG_FSL_SOC) += fsl/ diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig new file mode 100644 index 000..a1ea46e --- /dev/null +++ b/drivers/platform/fsl/Kconfig @@ -0,0 +1,11 @@ +# +# Freescale Specific Power Management Drivers +# + +config FSL_SLEEP_FSM + bool + help + This driver configures a hardware FSM (Finite State Machine) used in deep sleep. + The FSM finishes clean-ups at the last stage of entering deep sleep, and also + wakes up system when a wake up event happens. So far, T104x, T1024 and LS1021 + need this. diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile new file mode 100644 index 000..d99ca0e --- /dev/null +++ b/drivers/platform/fsl/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for linux/drivers/platform/fsl +# Freescale Specific Power Management Drivers +# +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c new file mode 100644 index 000..0a0480a --- /dev/null +++ b/drivers/platform/fsl/sleep_fsm.c @@ -0,0 +1,263 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2014-2015 Freescale Semiconductor Inc. + * + * Author: Hongbo Zhang + * Chenhui Zhao + * + * 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 +#include +#include + +#include "sleep_fsm.h" +/* + * These values are from chip's reference manual. For example, + * the values for T1040 can be found in "8.4.3.8 Programming + * supporting deep sleep mode" of Chapter 8 "Run Control and + * Power Management (RCPM)". + * The default value can be applied to T104x, T1024 and LS1021. + */ +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x8084}, + {EPECR0 + EPECR_STRIDE * 4, 0x2084}, + {EPECR0 + EPECR_STRIDE * 5, 0x0804}, + {EPECR0 + EPECR_STRIDE * 6, 0x8084}, + {EPECR0 + EPECR_STRIDE * 7, 0x8084}, + {EPECR0 + EPECR_STRIDE * 8, 0x6084}, + {EPECR0 + EPECR_STRIDE * 9, 0x0884}, + {EPECR0 + EPECR_STRIDE * 10, 0x4284}, + {EPECR0 + EPECR_STRIDE * 11, 0x9084}, + {EPECR0 + EPECR_STRIDE * 12, 0x8084}, + {EPECR0 + EPECR_STRIDE * 13, 0x0884}, + {EPECR0 + EPECR_STRIDE * 14, 0x0284}, + {EPECR0 + EPECR_STRIDE * 15, 0x0004}, + /* +* EPEVTCR (Event Processor EVT Pin Control Registers) +* SCU8 triger EVT2, and SCU11 triger EVT9 +*/ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x8001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3,
[PATCH 3/4] arm: ls1021a: add deep sleep support
The ls1021a SoC supports deep sleep feature that can switch off most parts of the SoC when it is in deep sleep state. The DDR controller will also be powered off in deep sleep. Therefore, copy the last stage code to enter deep sleep to SRAM and run it with disabling MMU and caches. Signed-off-by: Chenhui Zhao --- arch/arm/mach-imx/Kconfig | 1 + arch/arm/mach-imx/Makefile| 2 + arch/arm/mach-imx/pm-ls1.c| 374 ++ arch/arm/mach-imx/sleep-ls1.S | 137 arch/arm/mach-imx/sleep-ls1.h | 19 +++ 5 files changed, 533 insertions(+) create mode 100644 arch/arm/mach-imx/pm-ls1.c create mode 100644 arch/arm/mach-imx/sleep-ls1.S create mode 100644 arch/arm/mach-imx/sleep-ls1.h diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e8627e0..c10acff 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -664,6 +664,7 @@ config SOC_LS1021A select HAVE_ARM_ARCH_TIMER select PCI_DOMAINS if PCI select ZONE_DMA if ARM_LPAE + select FSL_SLEEP_FSM if PM help This enable support for Freescale LS1021A processor. diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index f5ac685..358adf4 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -101,6 +101,8 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o ifeq ($(CONFIG_SUSPEND),y) AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o +AFLAGS_sleep-ls1.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SOC_LS1021A) += pm-ls1.o sleep-ls1.o endif obj-$(CONFIG_SOC_IMX6) += pm-imx6.o diff --git a/arch/arm/mach-imx/pm-ls1.c b/arch/arm/mach-imx/pm-ls1.c new file mode 100644 index 000..4f9ca80 --- /dev/null +++ b/arch/arm/mach-imx/pm-ls1.c @@ -0,0 +1,374 @@ +/* + * Support deep sleep feature for LS1 + * + * Copyright 2014-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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "sleep-ls1.h" + +#define FSL_SLEEP 0x1 +#define FSL_DEEP_SLEEP 0x2 + +#define DCSR_EPU_EPSMCR15 0x278 +#define DCSR_EPU_EPECR00x300 +#define DCSR_RCPM_CG1CR0 0x31c +#define DCSR_RCPM_CSTTACR0 0xb00 + +#define CCSR_SCFG_DPSLPCR 0 +#define CCSR_SCFG_DPSLPCR_VAL 0x1 +#define CCSR_SCFG_PMCINTECR0x160 +#define CCSR_SCFG_PMCINTLECR 0x164 +#define CCSR_SCFG_PMCINTSR 0x168 +#define CCSR_SCFG_SPARECR2 0x504 +#define CCSR_SCFG_SPARECR3 0x508 + +#define CCSR_DCFG_CRSTSR 0x400 +#define CCSR_DCFG_CRSTSR_VAL 0x0008 + +#define CCSR_RCPM_POWMGTCSR0x130 +#define CCSR_RCPM_POWMGTCSR_LPM20_REQ 0x0010 +#define CCSR_RCPM_POWMGTCSR_LPM20_ST 0x0200 +#define CCSR_RCPM_POWMGTCSR_P_LPM20_ST 0x0100 +#define CCSR_RCPM_CLPCL10SETR 0x1c4 +#define CCSR_RCPM_CLPCL10SETR_C0 0x1 +#define CCSR_RCPM_IPPDEXPCR0 0x140 +#define CCSR_RCPM_IPPDEXPCR1 0x144 + +#define QIXIS_CTL_SYS 0x5 +#define QIXIS_CTL_SYS_EVTSW_MASK 0x0c +#define QIXIS_CTL_SYS_EVTSW_IRQ0x04 + +#define QIXIS_PWR_CTL2 0x21 +#define QIXIS_PWR_CTL2_PCTL0x2 + +#define OCRAM_BASE 0x1000 +#define OCRAM_SIZE 0x1 /* 64K */ +/* use the last page of SRAM */ +#define SRAM_CODE_BASE_PHY (OCRAM_BASE + OCRAM_SIZE - PAGE_SIZE) + +struct ls1_pm_baseaddr { + void __iomem *rcpm; + void __iomem *epu; + void __iomem *dcsr_rcpm1; + void __iomem *scfg; + void __iomem *dcfg; + void __iomem *fpga; + void __iomem *sram; +}; + +/* 128 bytes buffer for restoring data broke by DDR training initialization */ +#define DDR_BUF_SIZE 128 +static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64); +static struct ls1_pm_baseaddr ls1_pm_base; +/* supported sleep modes by the present platform */ +static unsigned int sleep_modes; +static suspend_state_t ls1_pm_state; + +static inline void ls1_clrsetbits_be32(void __iomem *addr, u32 mask, u32 val) +{ + u32 tmp; + + tmp = ioread32be(addr); + tmp = (tmp & ~mask) | val; + iowrite32be(tmp, addr); +} + +static void __iomem *of_iomap_str(const char *compatible) +{ + struct device_node *np; + void __iomem *base; + + np = of_find_compatible_node(NULL, NULL, compatible); + if (!np) { + pr_err("%s: can not find the compatible \"%s\"\n", + __func__, compatible); + return NULL; + } + + base = of_iomap(np, 0); + of_node_put(np); +
[PATCH 2/4] arm: ls1021a: add dts nodes required by deep sleep
Add RCPM and DCSR nodes. Signed-off-by: Chenhui Zhao --- arch/arm/boot/dts/ls1021a-qds.dts | 6 +- arch/arm/boot/dts/ls1021a.dtsi| 117 ++ 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts index 9c5e16b..6903f43 100644 --- a/arch/arm/boot/dts/ls1021a-qds.dts +++ b/arch/arm/boot/dts/ls1021a-qds.dts @@ -157,7 +157,7 @@ fpga: board-control@3,0 { #address-cells = <1>; #size-cells = <1>; - compatible = "simple-bus"; + compatible = "fsl,ls1021aqds-fpga", "simple-bus"; reg = <0x3 0x0 0x100>; bank-width = <1>; device-width = <1>; @@ -238,3 +238,7 @@ &uart1 { status = "okay"; }; + +&rcpm { + fsl,deep-sleep; +}; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index c70bb27..0c51ce0 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -183,6 +183,11 @@ }; }; + rcpm: rcpm@1ee2000 { + compatible = "fsl,ls1021a-rcpm", "fsl,qoriq-rcpm-2.1"; + reg = <0x0 0x1ee2000 0x0 0x1>; + }; + dspi0: dspi@210 { compatible = "fsl,vf610-dspi"; #address-cells = <1>; @@ -406,4 +411,116 @@ dr_mode = "host"; }; }; + + dcsr { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,dcsr", "simple-bus"; + ranges = <0x0 0x0 0x2000 0x100>; + + dcsr-epu@0 { + compatible = "fsl,ls1021a-dcsr-epu"; + reg = <0x0 0x1>; + }; + + dcsr-gdi@10 { + compatible = "fsl,ls1021a-dcsr-gdi"; + reg = <0x10 0x1>; + }; + + dcsr-dddi@12 { + compatible = "fsl,ls1021a-dcsr-dddi"; + reg = <0x12 0x1>; + }; + + dcsr-dcfg@22 { + compatible = "fsl,ls1021a-dcsr-dcfg"; + reg = <0x22 0x1000>; + }; + + dcsr-clock@221000 { + compatible = "fsl,ls1021a-dcsr-clock"; + reg = <0x221000 0x1000>; + }; + + dcsr-rcpm@222000 { + compatible = "fsl,ls1021a-dcsr-rcpm"; + reg = <0x222000 0x1000 0x223000 0x1000>; + }; + + dcsr-ccp@225000 { + compatible = "fsl,ls1021a-dcsr-ccp"; + reg = <0x225000 0x1000>; + }; + + dcsr-fusectrl@226000 { + compatible = "fsl,ls1021a-dcsr-fusectrl"; + reg = <0x226000 0x1000>; + }; + + dcsr-dap@30 { + compatible = "fsl,ls1021a-dcsr-dap"; + reg = <0x30 0x1>; + }; + + dcsr-cstf@35 { + compatible = "fsl,ls1021a-dcsr-cstf"; + reg = <0x35 0x1000 0x3a7000 0x1000>; + }; + + dcsr-a7rom@36 { + compatible = "fsl,ls1021a-dcsr-a7rom"; + reg = <0x36 0x1>; + }; + + dcsr-a7cpu@37 { + compatible = "fsl,ls1021a-dcsr-a7cpu"; + reg = <0x37 0x8000>; + }; + + dcsr-a7cti@378000 { + compatible = "fsl,ls1021a-dcsr-a7cti"; + reg = <0x378000 0x4000>; + }; + + dcsr-etm@37c000 { + compatible = "fsl,ls1021a-dcsr-etm"; + reg = <0x37c000 0x1000 0x37d000 0x3000>; + }; + + dcsr-hugorom@3a { + compatible = "fsl,ls1021a-dcsr-hugorom"; + reg = <0x3a 0x1000>; + }; + + dcsr-etf@3a1000 { + compatible = "fsl,ls1021a-dcsr-etf"; + reg = <0x3a1000 0x1000 0x3a2000 0x1000>; + }; + + dcsr-etr@3a3000 { + compatible
[PATCH v2 1/2] pm: add FSM configuration for deep sleep
For some Freescale's SoCs which support deep sleep, such as T1040, LS1021, software will start a Finite State Machine (FSM) to control the hardware precedure to enter deep sleep and return from it. This patch configures parameters of the FSM preparing for deep sleep. Signed-off-by: Chenhui Zhao --- Changes for v2: * use iowrite32be() drivers/platform/Kconfig |1 + drivers/platform/Makefile|1 + drivers/platform/fsl/Kconfig | 10 ++ drivers/platform/fsl/Makefile|5 + drivers/platform/fsl/sleep_fsm.c | 269 ++ drivers/platform/fsl/sleep_fsm.h | 106 +++ 6 files changed, 392 insertions(+), 0 deletions(-) create mode 100644 drivers/platform/fsl/Kconfig create mode 100644 drivers/platform/fsl/Makefile create mode 100644 drivers/platform/fsl/sleep_fsm.c create mode 100644 drivers/platform/fsl/sleep_fsm.h diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 69616ae..54ada25 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -5,3 +5,4 @@ if GOLDFISH source "drivers/platform/goldfish/Kconfig" endif +source "drivers/platform/fsl/Kconfig" diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 8a44a4c..d0cce95 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_OLPC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ +obj-$(CONFIG_FSL_SOC) += fsl/ diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig new file mode 100644 index 000..72ed053 --- /dev/null +++ b/drivers/platform/fsl/Kconfig @@ -0,0 +1,10 @@ +# +# Freescale Specific Power Management Drivers +# + +config FSL_SLEEP_FSM + bool + help + This driver configures a hardware FSM (Finite State Machine) for deep sleep. + The FSM is used to finish clean-ups at the last stage of system entering deep + sleep, and also wakes up system when a wake up event happens. diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile new file mode 100644 index 000..d99ca0e --- /dev/null +++ b/drivers/platform/fsl/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for linux/drivers/platform/fsl +# Freescale Specific Power Management Drivers +# +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c new file mode 100644 index 000..32616ad --- /dev/null +++ b/drivers/platform/fsl/sleep_fsm.c @@ -0,0 +1,269 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2014 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 +#include +#include + +#include "sleep_fsm.h" +/* + * These values are from chip's reference manual. For example, + * the values for T1040 can be found in "8.4.3.8 Programming + * supporting deep sleep mode" of Chapter 8 "Run Control and + * Power Management (RCPM)". + * The default value can be applied to T104x, LS1021. + */ +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x8084}, + {EPECR0 + EPECR_STRIDE * 4, 0x2084}, + {EPECR0 + EPECR_STRIDE * 5, 0x0804}, + {EPECR0 + EPECR_STRIDE * 6, 0x8084}, + {EPECR0 + EPECR_STRIDE * 7, 0x8084}, + {EPECR0 + EPECR_STRIDE * 8, 0x6084}, + {EPECR0 + EPECR_STRIDE * 9, 0x0884}, + {EPECR0 + EPECR_STRIDE * 10, 0x4284}, + {EPECR0 + EPECR_STRIDE * 11, 0x9084}, + {EPECR0 + EPECR_STRIDE * 12, 0x8084}, + {EPECR0 + EPECR_STRIDE * 13, 0x0884}, + {EPECR0 + EPECR_STRIDE * 14, 0x0284}, + {EPECR0 + EPECR_STRIDE * 15, 0x0004}, + /* +* EPEVTCR (Event Processor EVT Pin Control Registers) +* SCU8 triger EVT2, and SCU11 triger EVT9 +*/ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x8001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB001}, + /* EPCMPR (Event Processor Counter C
[PATCH v2 2/2] arm: pm: add deep sleep support for LS1
LS1 supports deep sleep feature that can switch off most parts of the SoC when it is in deep sleep state. The DDR controller will also be powered off in deep sleep. Therefore, copy the last stage code to enter deep sleep to SRAM and run it with disabling MMU and caches. Signed-off-by: Chenhui Zhao --- Changes for v2: * use identity mapping to smooth the process of disabling MMU * change the value of registers arch/arm/mach-imx/Kconfig |1 + arch/arm/mach-imx/Makefile|1 + arch/arm/mach-imx/pm-ls1.c| 341 + arch/arm/mach-imx/sleep-ls1.S | 132 4 files changed, 475 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-imx/pm-ls1.c create mode 100644 arch/arm/mach-imx/sleep-ls1.S diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index b85534c..716bb1b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -866,6 +866,7 @@ config SOC_LS1021A select HAVE_SMP select ARCH_LAYERSCAPE select ZONE_DMA if ARM_LPAE + select FSL_SLEEP_FSM if PM help This enable support for Freescale Layerscape LS1021A processor. diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 41b8044..9931528 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o ifeq ($(CONFIG_PM),y) obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o +obj-$(CONFIG_SOC_LS1021A) += pm-ls1.o sleep-ls1.o endif # i.MX5 based machines diff --git a/arch/arm/mach-imx/pm-ls1.c b/arch/arm/mach-imx/pm-ls1.c new file mode 100644 index 000..8fd7aee --- /dev/null +++ b/arch/arm/mach-imx/pm-ls1.c @@ -0,0 +1,341 @@ +/* + * Support deep sleep feature for LS1 + * + * Copyright 2014 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define FSL_SLEEP 0x1 +#define FSL_DEEP_SLEEP 0x2 + +#define DCSR_EPU_EPSMCR15 0x278 +#define DCSR_EPU_EPECR00x300 +#define DCSR_RCPM_CG1CR0 0x31c +#define DCSR_RCPM_CSTTACR0 0xb00 + +#define CCSR_SCFG_DPSLPCR 0 +#define CCSR_SCFG_DPSLPCR_VAL 0x1 +#define CCSR_SCFG_SPARECR2 0x504 +#define CCSR_SCFG_SPARECR3 0x508 + +#define CCSR_DCFG_CRSTSR 0x400 +#define CCSR_DCFG_CRSTSR_VAL 0x0008 + +#define CCSR_RCPM_POWMGTCSR0x130 +#define CCSR_RCPM_POWMGTCSR_LPM20_REQ 0x0010 +#define CCSR_RCPM_POWMGTCSR_LPM20_ST 0x0200 +#define CCSR_RCPM_POWMGTCSR_P_LPM20_ST 0x0100 +#define CCSR_RCPM_CLPCL10SETR 0x1c4 +#define CCSR_RCPM_CLPCL10SETR_C0 0x1 + +#define OCRAM_BASE 0x1000 +#define OCRAM_SIZE 0x1 /* 64K */ +/* use the last page of SRAM */ +#define SRAM_CODE_BASE_PHY (OCRAM_BASE + OCRAM_SIZE - PAGE_SIZE) + +struct ls1_pm_baseaddr { + void __iomem *epu; + void __iomem *dcsr_rcpm1; + void __iomem *dcsr_rcpm2; + void __iomem *rcpm; + void __iomem *scfg; + void __iomem *dcfg; + void __iomem *fpga; + void __iomem *sram; +}; + +/* 128 bytes buffer for restoring data broke by DDR training initialization */ +#define DDR_BUF_SIZE 128 +static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64); +static struct ls1_pm_baseaddr ls1_pm_base; +/* supported sleep modes by the present platform */ +static unsigned int sleep_modes; + +extern void ls1_do_deepsleep(unsigned long addr); +extern void ls1_start_fsm(void); +extern void ls1_deepsleep_resume(void); +extern void ls1021a_set_secondary_entry(void); +extern int ls1_sram_code_size; +extern void fsl_epu_setup_default(void __iomem *epu_base); + +static void ls1_pm_iomap(void) +{ + struct device_node *np; + void *base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-epu"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.epu = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-rcpm"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.dcsr_rcpm1 = base; + base = of_iomap(np, 1); + BUG_ON(!base); + ls1_pm_base.dcsr_rcpm2 = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-scfg"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.scfg = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.dcfg = base; + + np = of_find_compatible_node(NULL, NULL,
Re: [PATCH 3/3] arm: pm: add deep sleep support for LS1
On Sun, Sep 28, 2014 at 03:26:33PM +0100, Russell King - ARM Linux wrote: > On Sun, Sep 28, 2014 at 07:06:40PM +0800, Chenhui Zhao wrote: > > On Fri, Sep 26, 2014 at 01:14:27PM +0100, Russell King - ARM Linux wrote: > > > On Fri, Sep 26, 2014 at 07:25:03PM +0800, Chenhui Zhao wrote: > > > > +/* > > > > + * r0: the physical entry address of SRAM code > > > > + * > > > > + */ > > > > +ENTRY(ls1_do_deepsleep) > > > > + mov r13, r0 > > > > + > > > > + /* flush cache */ > > > > + bl v7_flush_dcache_all > > > > > > Please explain the purpose of this call via a comment in the code. > > > > > > The generic code will have saved the CPU state, and will have called > > > flush_cache_louis() to flush the caches to the point of unification. > > > > > > The only data which will have been loaded into the cache between that > > > point is the stack for the return from __cpu_suspend_save, and > > > speculative prefetches. > > > > > > So, the only reason I can gather is that you need to flush data from > > > lower levels of the cache below the point of unification. > > > > > > > In deep sleep process, all caches will lost, so flush all caches to prevent > > data loss. > > You haven't answered my question. > I want to flush L1 and L2 caches of Cortex-A7 in LS1021. However, flush_cache_louis() only flushed L1 cache. Therefore, call v7_flush_dcache_all() to flush L1 and L2 cache. > > > > + > > > > + /* disable cache, C bit in SCTLR */ > > > > + mrc p15, 0, r0, c1, c0, 0 > > > > + bic r0, r0, #(1 << 2) > > > > + mcr p15, 0, r0, c1, c0, 0 > > > > + isb > > > > + > > > > + /* disable coherency, SMP bit in ACTLR */ > > > > + mrc p15, 0, r0, c1, c0, 1 > > > > + bic r0, r0, #(1 << 6) > > > > + mcr p15, 0, r0, c1, c0, 1 > > > > + isb > > > > + dsb > > > > + > > > > + /* disable MMU, M bit in SCTLR */ > > > > + mrc p15, 0, r0, c1, c0, 0 > > > > + bic r0, r0, #1 > > > > + mcr p15, 0, r0, c1, c0, 0 > > > > + isb > > > > + > > > > + /* jump to sram code using physical address */ > > > > + bx r13 > > > > > > This looks extremely fragile. You are running in virtual space, and you > > > turn the MMU off. You are reliant on the MMU still being on for the > > > following instructions to already be in the pipeline. That's not a > > > very good assumption to make (we've made it in the past and it breaks > > > every so often when things change, eg when the code is no longer laid > > > out how we expect.) > > > > > > You need to disable the MMU safely, which means using the identity map > > > page tables and executing code in the identity map region. > > > > Yes, the code will switch off MMU, and switch to physical address space. > > On LS1021, the DDR memory located at the physical address space started from > > 0x8000, the kernel space also started at 0x8000 (CONFIG_PAGE_OFFSET > > = 0x8000). > > So the virtual address of kernel code is equal to the physical address. > > You can't rely on that. > > Sorry, NAK. I'll try to use a safer method to implement it. Chenhui -- 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/
Re: [PATCH 3/3] arm: pm: add deep sleep support for LS1
On Fri, Sep 26, 2014 at 01:14:27PM +0100, Russell King - ARM Linux wrote: > On Fri, Sep 26, 2014 at 07:25:03PM +0800, Chenhui Zhao wrote: > > +static int ls1_start_deepsleep(unsigned long addr) > > +{ > > + ls1_do_deepsleep(addr); > > + > > + return 0; > > +} > ... > > + cpu_suspend(SRAM_CODE_BASE_PHY, ls1_start_deepsleep); > > What's the point of this function? Why can't ls1_do_deepsleep() just > return zero? Just leave space for adding C code in the future. > > > +/* > > + * r0: the physical entry address of SRAM code > > + * > > + */ > > +ENTRY(ls1_do_deepsleep) > > + mov r13, r0 > > + > > + /* flush cache */ > > + bl v7_flush_dcache_all > > Please explain the purpose of this call via a comment in the code. > > The generic code will have saved the CPU state, and will have called > flush_cache_louis() to flush the caches to the point of unification. > > The only data which will have been loaded into the cache between that > point is the stack for the return from __cpu_suspend_save, and > speculative prefetches. > > So, the only reason I can gather is that you need to flush data from > lower levels of the cache below the point of unification. > In deep sleep process, all caches will lost, so flush all caches to prevent data loss. > > + > > + /* disable cache, C bit in SCTLR */ > > + mrc p15, 0, r0, c1, c0, 0 > > + bic r0, r0, #(1 << 2) > > + mcr p15, 0, r0, c1, c0, 0 > > + isb > > + > > + /* disable coherency, SMP bit in ACTLR */ > > + mrc p15, 0, r0, c1, c0, 1 > > + bic r0, r0, #(1 << 6) > > + mcr p15, 0, r0, c1, c0, 1 > > + isb > > + dsb > > + > > + /* disable MMU, M bit in SCTLR */ > > + mrc p15, 0, r0, c1, c0, 0 > > + bic r0, r0, #1 > > + mcr p15, 0, r0, c1, c0, 0 > > + isb > > + > > + /* jump to sram code using physical address */ > > + bx r13 > > This looks extremely fragile. You are running in virtual space, and you > turn the MMU off. You are reliant on the MMU still being on for the > following instructions to already be in the pipeline. That's not a > very good assumption to make (we've made it in the past and it breaks > every so often when things change, eg when the code is no longer laid > out how we expect.) > > You need to disable the MMU safely, which means using the identity map > page tables and executing code in the identity map region. Yes, the code will switch off MMU, and switch to physical address space. On LS1021, the DDR memory located at the physical address space started from 0x8000, the kernel space also started at 0x8000 (CONFIG_PAGE_OFFSET = 0x8000). So the virtual address of kernel code is equal to the physical address. Chenhui -- 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/
Re: [PATCH 2/3] pm: add FSM configuration for deep sleep
On Fri, Sep 26, 2014 at 09:51:53PM +0100, Russell King - ARM Linux wrote: > On Fri, Sep 26, 2014 at 01:02:01PM +0100, Russell King - ARM Linux wrote: > > On Fri, Sep 26, 2014 at 07:25:02PM +0800, Chenhui Zhao wrote: > > > +void fsm_write32(void __iomem *addr, u32 val) > > > +{ > > > +#ifdef __arm__ > > > + iowrite32be(val, addr); > > > +#endif > > > + > > > +#ifdef __powerpc__ > > > + out_be32(addr, val); > > > +#endif > > > > The idea of iowrite* is that it should be able to address MMIO or IO > > memory irrespective of the platform. Why is PowerPC not implementing > > this accessor, or why can't it be used for PowerPC? > > > > This should just use iowrite32be(), and if it doesn't work on PowerPC, > > PowerPC needs to be fixed. > > BenH tells me that this should be able to use iowrite32be() on PowerPC > too without problems, there should be no need to use the older out_be32() > accessors here. Please can you look into using only iowrite32be() here? > > Thanks. > Thanks. I'll fix it. Chenhui -- 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/
[PATCH 2/3] pm: add FSM configuration for deep sleep
For some Freescale's SoCs which support deep sleep, such as T1040, LS1021, software will start a Finite State Machine (FSM) to control the hardware precedure to enter deep sleep and return from it. This patch configures parameters of the FSM preparing for deep sleep. Signed-off-by: Chenhui Zhao --- drivers/platform/Kconfig |1 + drivers/platform/Makefile|1 + drivers/platform/fsl/Kconfig | 10 ++ drivers/platform/fsl/Makefile|5 + drivers/platform/fsl/sleep_fsm.c | 281 ++ drivers/platform/fsl/sleep_fsm.h | 100 ++ 6 files changed, 398 insertions(+), 0 deletions(-) create mode 100644 drivers/platform/fsl/Kconfig create mode 100644 drivers/platform/fsl/Makefile create mode 100644 drivers/platform/fsl/sleep_fsm.c create mode 100644 drivers/platform/fsl/sleep_fsm.h diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 69616ae..54ada25 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -5,3 +5,4 @@ if GOLDFISH source "drivers/platform/goldfish/Kconfig" endif +source "drivers/platform/fsl/Kconfig" diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 8a44a4c..d0cce95 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_OLPC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ +obj-$(CONFIG_FSL_SOC) += fsl/ diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig new file mode 100644 index 000..72ed053 --- /dev/null +++ b/drivers/platform/fsl/Kconfig @@ -0,0 +1,10 @@ +# +# Freescale Specific Power Management Drivers +# + +config FSL_SLEEP_FSM + bool + help + This driver configures a hardware FSM (Finite State Machine) for deep sleep. + The FSM is used to finish clean-ups at the last stage of system entering deep + sleep, and also wakes up system when a wake up event happens. diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile new file mode 100644 index 000..d99ca0e --- /dev/null +++ b/drivers/platform/fsl/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for linux/drivers/platform/fsl +# Freescale Specific Power Management Drivers +# +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c new file mode 100644 index 000..d8478a1 --- /dev/null +++ b/drivers/platform/fsl/sleep_fsm.c @@ -0,0 +1,281 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2014 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 +#include +#include + +#include "sleep_fsm.h" +/* + * These values are from chip's reference manual. For example, + * the values for T1040 can be found in "8.4.3.8 Programming + * supporting deep sleep mode" of Chapter 8 "Run Control and + * Power Management (RCPM)". + * The default value can be applied to T104x, LS1021. + */ +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x8084}, + {EPECR0 + EPECR_STRIDE * 4, 0x2084}, + {EPECR0 + EPECR_STRIDE * 5, 0x0804}, + {EPECR0 + EPECR_STRIDE * 6, 0x8084}, + {EPECR0 + EPECR_STRIDE * 7, 0x8084}, + {EPECR0 + EPECR_STRIDE * 8, 0x6084}, + {EPECR0 + EPECR_STRIDE * 9, 0x0884}, + {EPECR0 + EPECR_STRIDE * 10, 0x4284}, + {EPECR0 + EPECR_STRIDE * 11, 0x9084}, + {EPECR0 + EPECR_STRIDE * 12, 0x8084}, + {EPECR0 + EPECR_STRIDE * 13, 0x0884}, + {EPECR0 + EPECR_STRIDE * 14, 0x0284}, + /* This will be written just before entering deep sleep */ + {EPECR0 + EPECR_STRIDE * 15, 0}, + /* +* EPEVTCR (Event Processor EVT Pin Control Registers) +* SCU8 triger EVT2, and SCU11 triger EVT9 +*/ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x8001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB001}, + /* EPCMPR (Event Processor Counte
[PATCH 3/3] arm: pm: add deep sleep support for LS1
LS1 supports deep sleep feature that can switch off most parts of the SoC when it is in deep sleep state. The DDR controller will also be powered off in deep sleep. Therefore, copy the last stage code to enter deep sleep to SRAM and run it with disabling MMU and caches. Signed-off-by: Chenhui Zhao --- arch/arm/mach-imx/Kconfig |1 + arch/arm/mach-imx/Makefile|1 + arch/arm/mach-imx/pm-ls1.c| 329 + arch/arm/mach-imx/sleep-ls1.S | 142 ++ 4 files changed, 473 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-imx/pm-ls1.c create mode 100644 arch/arm/mach-imx/sleep-ls1.S diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index b85534c..716bb1b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -866,6 +866,7 @@ config SOC_LS1021A select HAVE_SMP select ARCH_LAYERSCAPE select ZONE_DMA if ARM_LPAE + select FSL_SLEEP_FSM if PM help This enable support for Freescale Layerscape LS1021A processor. diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 41b8044..9931528 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o ifeq ($(CONFIG_PM),y) obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o +obj-$(CONFIG_SOC_LS1021A) += pm-ls1.o sleep-ls1.o endif # i.MX5 based machines diff --git a/arch/arm/mach-imx/pm-ls1.c b/arch/arm/mach-imx/pm-ls1.c new file mode 100644 index 000..621fdb4 --- /dev/null +++ b/arch/arm/mach-imx/pm-ls1.c @@ -0,0 +1,329 @@ +/* + * Support deep sleep feature for LS1 + * + * Copyright 2014 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define FSL_SLEEP 0x1 +#define FSL_DEEP_SLEEP 0x2 + +#define DCSR_EPU_EPECR00x300 +#define DCSR_RCPM_CG1CR0 0x31c +#define DCSR_RCPM_CSTTACR0 0xb00 + +/* in SCFG registers except for SPARECR registers, reverse bits in each byte */ +#define CCSR_SCFG_DPSLPCR 0 +#define CCSR_SCFG_DPSLPCR_VAL 0x0080 +#define CCSR_SCFG_SPARECR2 0x504 +#define CCSR_SCFG_SPARECR3 0x508 + +#define CCSR_DCFG_CRSTSR 0x400 +#define CCSR_DCFG_CRSTSR_VAL 0x0008 + +#define CCSR_RCPM_POWMGTCSR0x130 +#define CCSR_RCPM_POWMGTCSR_LPM20_REQ 0x0010 +#define CCSR_RCPM_POWMGTCSR_LPM20_ST 0x0200 +#define CCSR_RCPM_POWMGTCSR_P_LPM20_ST 0x0100 +#define CCSR_RCPM_CLPCL10SETR 0x1c4 +#define CCSR_RCPM_CLPCL10SETR_C0 0x1 + +#define QIXIS_CTL_SYS 0x5 +#define QIXIS_CTL_SYS_EVTSW_MASK 0x0c +#define QIXIS_CTL_SYS_EVTSW_IRQ0x04 + +#define QIXIS_PWR_CTL2 0x21 +#define QIXIS_PWR_CTL2_PCTL0x2 + +#define OCRAM_BASE 0x1000 +#define OCRAM_SIZE 0x1 /* 64K */ +/* use the last page of SRAM */ +#define SRAM_CODE_BASE_PHY (OCRAM_BASE + OCRAM_SIZE - PAGE_SIZE) + +struct ls1_pm_baseaddr { + void __iomem *epu; + void __iomem *dcsr_rcpm1; + void __iomem *dcsr_rcpm2; + void __iomem *rcpm; + void __iomem *scfg; + void __iomem *dcfg; + void __iomem *fpga; + void __iomem *sram; +}; + +/* 128 bytes buffer for restoring data broke by DDR training initialization */ +#define DDR_BUF_SIZE 128 +static u8 ddr_buff[DDR_BUF_SIZE] __aligned(64); +static struct ls1_pm_baseaddr ls1_pm_base; +/* supported sleep modes by the present platform */ +static unsigned int sleep_modes; + +extern void ls1_do_deepsleep(unsigned long addr); +extern void ls1_start_fsm(void); +extern void ls1_deepsleep_resume(void); +extern void ls1021a_set_secondary_entry(void); +extern int ls1_sram_code_size; +extern void fsl_epu_setup_default(void __iomem *epu_base); + +static void ls1_pm_iomap(void) +{ + struct device_node *np; + void *base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-epu"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.epu = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcsr-rcpm"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.dcsr_rcpm1 = base; + base = of_iomap(np, 1); + BUG_ON(!base); + ls1_pm_base.dcsr_rcpm2 = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-scfg"); + base = of_iomap(np, 0); + BUG_ON(!base); + ls1_pm_base.scfg = base; + + np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg"); + base
[PATCH 0/3] arm: ls1: add deep sleep support
These patches are for supporting deep sleep on LS1. They are based on the platform patches for LS1. -- 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/
[PATCH 1/3] arm: ls1: add CPU hotplug platform support
From: Zhang Zhuoyu This implements CPU hotplug for ls1. When cpu is down, it will be put in WFI state. When cpu is up, it will be waked by a IPI interrupt and reinitialized. Signed-off-by: Zhang Zhuoyu Signed-off-by: Chenhui Zhao --- arch/arm/mach-imx/common.h |4 ++ arch/arm/mach-imx/hotplug.c | 90 +++ arch/arm/mach-imx/platsmp.c | 22 -- arch/arm/mach-imx/src.c | 21 ++ 4 files changed, 132 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 203ee73..2ca32fe 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -115,6 +115,7 @@ void tzic_handle_irq(struct pt_regs *); extern void imx_enable_cpu(int cpu, bool enable); extern void imx_set_cpu_jump(int cpu, void *jump_addr); extern u32 imx_get_cpu_arg(int cpu); +extern u32 ls1_get_cpu_arg(int cpu); extern void imx_set_cpu_arg(int cpu, u32 arg); extern void v7_cpu_resume(void); #ifdef CONFIG_SMP @@ -145,6 +146,9 @@ extern void imx6q_set_chicken_bit(void); extern void imx_cpu_die(unsigned int cpu); extern int imx_cpu_kill(unsigned int cpu); +extern void ls1021a_cpu_die(unsigned int cpu); +extern int ls1021a_cpu_kill(unsigned int cpu); + #ifdef CONFIG_PM extern void imx6q_pm_init(void); extern void imx5_pm_init(void); diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 3daf1ed..646034f 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "common.h" @@ -38,6 +41,22 @@ static inline void cpu_enter_lowpower(void) : "cc"); } +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + " mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + /* * platform-specific code to shutdown a CPU * @@ -66,3 +85,74 @@ int imx_cpu_kill(unsigned int cpu) imx_set_cpu_arg(cpu, 0); return 1; } + +static inline void ls1_do_lowpower(unsigned int cpu, int *spurious) +{ + /* +* there is no power-control hardware on this platform, so all +* we can do is put the core into WFI; this is safe as the calling +* code will have already disabled interrupts +*/ + for (;;) { + wfi(); + + if (pen_release == cpu_logical_map(cpu)) { + /*OK, proper wakeup, we're done*/ + break; + } + + /* +* Getting here, means that we have come out of WFI without +* having been woken up - this shouldn't happen +* +* Just note it happening - when we're woken, we can report +* its occurrence. +*/ + (*spurious)++; + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void __ref ls1021a_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + v7_exit_coherency_flush(louis); + + /*we're ready for shutdown now, so do it*/ + ls1_do_lowpower(cpu, &spurious); + + /* +* bring this CPU back into the world of cache +* coherency, and then restore interrupts +*/ + cpu_leave_lowpower(); + + if (spurious) + pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); + + /* +* Do not return to the idle loop - jump back to the secondary +* cpu initialisation. There's some initialisation which needs +* to be repeated to undo the effects of taking the CPU offline. +*/ + __asm__("movsp, %0\n" + " mov fp, #0\n" + " b ls1021a_secondary_startup" + : + : "r" (task_stack_page(current) + THREAD_SIZE - 8)); +} + +int ls1021a_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (ls1_get_cpu_arg(cpu)) + if (time_after(jiffies, timeout)) + return 0; + return 1; +} diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 5225b69..d262b32 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -29,6 +29,7 @@ u32 g_diag_reg; static void __iomem *scu_base; +void __iomem *dcfg_base; static struct map_desc scu_io_desc __initdata = { /* .virtual and .pfn are run-ti
Re: [PATCH 9/9] powerpc/pm: support deep sleep feature on T1040
On Tue, Mar 18, 2014 at 05:42:09PM -0500, Scott Wood wrote: > On Mon, 2014-03-17 at 19:19 +0800, Chenhui Zhao wrote: > > On Fri, Mar 14, 2014 at 06:18:27PM -0500, Scott Wood wrote: > > > On Wed, 2014-03-12 at 18:40 +0800, Chenhui Zhao wrote: > > > > On Tue, Mar 11, 2014 at 08:10:24PM -0500, Scott Wood wrote: > > > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > > > From: Zhao Chenhui > > > > > > > > > > > > T1040 supports deep sleep feature, which can switch off most parts > > > > > > of > > > > > > the SoC when it is in deep sleep mode. This way, it becomes more > > > > > > energy-efficient. > > > > > > > > > > > > The DDR controller will also be powered off in deep sleep. > > > > > > Therefore, > > > > > > the last stage (the latter part of fsl_dp_enter_low) will run > > > > > > without DDR > > > > > > access. This piece of code and related TLBs will be prefetched. > > > > > > > > > > > > Due to the different initialization code between 32-bit and 64-bit, > > > > > > they > > > > > > have seperate resume entry and precedure. > > > > > > > > > > > > The feature supports 32-bit and 64-bit kernel mode. > > > > > > > > > > > > Signed-off-by: Zhao Chenhui > > > > > > --- > > > > > > arch/powerpc/include/asm/booke_save_regs.h |3 + > > > > > > arch/powerpc/kernel/cpu_setup_fsl_booke.S | 17 ++ > > > > > > arch/powerpc/kernel/head_fsl_booke.S | 30 +++ > > > > > > arch/powerpc/platforms/85xx/Makefile |2 +- > > > > > > arch/powerpc/platforms/85xx/deepsleep.c| 201 > > > > > > +++ > > > > > > arch/powerpc/platforms/85xx/qoriq_pm.c | 38 > > > > > > arch/powerpc/platforms/85xx/sleep.S| 295 > > > > > > > > > > > > arch/powerpc/sysdev/fsl_soc.h |7 + > > > > > > 8 files changed, 592 insertions(+), 1 deletions(-) > > > > > > create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c > > > > > > create mode 100644 arch/powerpc/platforms/85xx/sleep.S > > > > > > > > > > > > diff --git a/arch/powerpc/include/asm/booke_save_regs.h > > > > > > b/arch/powerpc/include/asm/booke_save_regs.h > > > > > > index 87c357a..37c1f6c 100644 > > > > > > --- a/arch/powerpc/include/asm/booke_save_regs.h > > > > > > +++ b/arch/powerpc/include/asm/booke_save_regs.h > > > > > > @@ -88,6 +88,9 @@ > > > > > > #define HIBERNATION_FLAG 1 > > > > > > #define DEEPSLEEP_FLAG 2 > > > > > > > > > > > > +#define CPLD_FLAG 1 > > > > > > +#define FPGA_FLAG 2 > > > > > > > > > > What is this? > > > > > > > > We have two kind of boards, QDS and RDB. > > > > They have different register map. Use the flag to indicate the current > > > > board is using which kind > > > > of register map. > > > > > > CPLD versus FPGA is not a meaningful difference. We don't care what > > > technology is used to implement programmable logic -- we care what > > > programming interface is exposed. Customers will have their own boards > > > that will likely not imitate either of these programming interfaces, but > > > what they do have will still probably be implemented in a CPLD or FPGA. > > > Likewise, Freescale may have future reference boards whose CPLD/FPGA is > > > not compatible. > > > > Will use a better name. > > > > > > > > So use better naming, and structure the code so it's easy to plug in > > > implementations for new or custom boards. > > > > > > > > > diff --git a/arch/powerpc/kernel/head_fsl_booke.S > > > > > > b/arch/powerpc/kernel/head_fsl_booke.S > > > > > > index 20204fe..3285752 100644 > > > > > > --- a/arch/powerpc/kernel/head_fsl_booke.S > > > > > > +++ b/arch/powerpc/kernel/head_fsl_booke.S > > > > > > @@ -162,6 +162,19 @@ _ENTRY(__early_start) > > > > > > #include "
Re: [PATCH 7/9] fsl: add EPU FSM configuration for deep sleep
On Tue, Mar 18, 2014 at 06:21:22PM -0500, Scott Wood wrote: > On Mon, 2014-03-17 at 18:27 +0800, Chenhui Zhao wrote: > > On Fri, Mar 14, 2014 at 05:51:09PM -0500, Scott Wood wrote: > > > On Wed, 2014-03-12 at 16:34 +0800, Chenhui Zhao wrote: > > > > On Tue, Mar 11, 2014 at 07:08:43PM -0500, Scott Wood wrote: > > > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > > > + /* Configure the EPU Counters */ > > > > > > + epu_write(EPCCR15, 0x9284); > > > > > > + epu_write(EPCCR14, 0x9284); > > > > > > + epu_write(EPCCR12, 0x9284); > > > > > > + epu_write(EPCCR11, 0x9284); > > > > > > + epu_write(EPCCR10, 0x9284); > > > > > > + epu_write(EPCCR9, 0x9284); > > > > > > + epu_write(EPCCR8, 0x9284); > > > > > > + epu_write(EPCCR5, 0x9284); > > > > > > + epu_write(EPCCR4, 0x9284); > > > > > > + epu_write(EPCCR2, 0x9284); > > > > > > + > > > > > > + /* Configure the SCUs Inputs */ > > > > > > + epu_write(EPSMCR15, 0x7600); > > > > > > + epu_write(EPSMCR14, 0x0031); > > > > > > + epu_write(EPSMCR13, 0x3100); > > > > > > + epu_write(EPSMCR12, 0x7F00); > > > > > > + epu_write(EPSMCR11, 0x3174); > > > > > > + epu_write(EPSMCR10, 0x6530); > > > > > > + epu_write(EPSMCR9, 0x3000); > > > > > > + epu_write(EPSMCR8, 0x6430); > > > > > > + epu_write(EPSMCR7, 0x3000); > > > > > > + epu_write(EPSMCR6, 0x7C00); > > > > > > + epu_write(EPSMCR5, 0x2E00); > > > > > > + epu_write(EPSMCR4, 0x002F); > > > > > > + epu_write(EPSMCR3, 0x2F00); > > > > > > + epu_write(EPSMCR2, 0x6C70); > > > > > > > > > > Where do these magic numbers come from? Which chips are they valid > > > > > for? > > > > > > > > They are for T1040. Can be found in the RCPM chapter of T1040RM. > > > > > > Then put in a comment to that effect, including what part of the RCPM > > > chapter. > > > > > > How do you plan to handle the addition of another SoC with different > > > values? > > > > > > -Scott > > > > Had thought that using an array to put these values (pairs of offset and > > value) > > and passing the array to the function. > > Arrays are better than a long sequence of function calls in any case. > > > However, luckily T104x and LS1 have same values for these registers > > according to the current Reference Manuals. > > If it's likely that the values will remain the same on all chips for the > near future, then a fancy mechanism to select the array to use can wait > -- but you should still use an array, and have a comment acknowledging > the possibility of needing to accommodate different values in the > future. > > -Scott OK. Will use an array to pass the values. -Chenhui -- 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/
Re: [PATCH 9/9] powerpc/pm: support deep sleep feature on T1040
On Fri, Mar 14, 2014 at 06:18:27PM -0500, Scott Wood wrote: > On Wed, 2014-03-12 at 18:40 +0800, Chenhui Zhao wrote: > > On Tue, Mar 11, 2014 at 08:10:24PM -0500, Scott Wood wrote: > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > From: Zhao Chenhui > > > > > > > > T1040 supports deep sleep feature, which can switch off most parts of > > > > the SoC when it is in deep sleep mode. This way, it becomes more > > > > energy-efficient. > > > > > > > > The DDR controller will also be powered off in deep sleep. Therefore, > > > > the last stage (the latter part of fsl_dp_enter_low) will run without > > > > DDR > > > > access. This piece of code and related TLBs will be prefetched. > > > > > > > > Due to the different initialization code between 32-bit and 64-bit, they > > > > have seperate resume entry and precedure. > > > > > > > > The feature supports 32-bit and 64-bit kernel mode. > > > > > > > > Signed-off-by: Zhao Chenhui > > > > --- > > > > arch/powerpc/include/asm/booke_save_regs.h |3 + > > > > arch/powerpc/kernel/cpu_setup_fsl_booke.S | 17 ++ > > > > arch/powerpc/kernel/head_fsl_booke.S | 30 +++ > > > > arch/powerpc/platforms/85xx/Makefile |2 +- > > > > arch/powerpc/platforms/85xx/deepsleep.c| 201 +++ > > > > arch/powerpc/platforms/85xx/qoriq_pm.c | 38 > > > > arch/powerpc/platforms/85xx/sleep.S| 295 > > > > > > > > arch/powerpc/sysdev/fsl_soc.h |7 + > > > > 8 files changed, 592 insertions(+), 1 deletions(-) > > > > create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c > > > > create mode 100644 arch/powerpc/platforms/85xx/sleep.S > > > > > > > > diff --git a/arch/powerpc/include/asm/booke_save_regs.h > > > > b/arch/powerpc/include/asm/booke_save_regs.h > > > > index 87c357a..37c1f6c 100644 > > > > --- a/arch/powerpc/include/asm/booke_save_regs.h > > > > +++ b/arch/powerpc/include/asm/booke_save_regs.h > > > > @@ -88,6 +88,9 @@ > > > > #define HIBERNATION_FLAG 1 > > > > #define DEEPSLEEP_FLAG 2 > > > > > > > > +#define CPLD_FLAG 1 > > > > +#define FPGA_FLAG 2 > > > > > > What is this? > > > > We have two kind of boards, QDS and RDB. > > They have different register map. Use the flag to indicate the current > > board is using which kind > > of register map. > > CPLD versus FPGA is not a meaningful difference. We don't care what > technology is used to implement programmable logic -- we care what > programming interface is exposed. Customers will have their own boards > that will likely not imitate either of these programming interfaces, but > what they do have will still probably be implemented in a CPLD or FPGA. > Likewise, Freescale may have future reference boards whose CPLD/FPGA is > not compatible. Will use a better name. > > So use better naming, and structure the code so it's easy to plug in > implementations for new or custom boards. > > > > > diff --git a/arch/powerpc/kernel/head_fsl_booke.S > > > > b/arch/powerpc/kernel/head_fsl_booke.S > > > > index 20204fe..3285752 100644 > > > > --- a/arch/powerpc/kernel/head_fsl_booke.S > > > > +++ b/arch/powerpc/kernel/head_fsl_booke.S > > > > @@ -162,6 +162,19 @@ _ENTRY(__early_start) > > > > #include "fsl_booke_entry_mapping.S" > > > > #undef ENTRY_MAPPING_BOOT_SETUP > > > > > > > > +#if defined(CONFIG_SUSPEND) && defined(CONFIG_FSL_CORENET_RCPM) > > > > + /* if deep_sleep_flag != 0, jump to the deep sleep resume entry > > > > */ > > > > + LOAD_REG_ADDR(r4, deep_sleep_flag) > > > > + lwz r3, 0(r4) > > > > + cmpwi r3, 0 > > > > + beq 11f > > > > + /* clear deep_sleep_flag */ > > > > + li r3, 0 > > > > + stw r3, 0(r4) > > > > + b fsl_deepsleep_resume > > > > +11: > > > > +#endif > > > > > > Why do you come in via the normal kernel entry, versus specifying a > > > direct entry point for deep sleep resume? How does U-Boot even know > > > what the normal entry is w
Re: [PATCH 8/9] powerpc/85xx: add save/restore functions for core registers
On Fri, Mar 14, 2014 at 06:01:45PM -0500, Scott Wood wrote: > On Wed, 2014-03-12 at 17:42 +0800, Chenhui Zhao wrote: > > On Tue, Mar 11, 2014 at 07:45:14PM -0500, Scott Wood wrote: > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > From: Wang Dongsheng > > > > > > > > Add booke_cpu_state_save() and booke_cpu_state_restore() functions > > > > which can be > > > > used to save/restore CPU's registers in the case of deep sleep and > > > > hibernation. > > > > > > > > Supported processors: E6500, E5500, E500MC, E500v2 and E500v1. > > > > > > > > Signed-off-by: Wang Dongsheng > > > > Signed-off-by: Chenhui Zhao > > > > --- > > > > arch/powerpc/include/asm/booke_save_regs.h | 96 > > > > arch/powerpc/kernel/Makefile |1 + > > > > arch/powerpc/kernel/booke_save_regs.S | 361 > > > > > > > > 3 files changed, 458 insertions(+), 0 deletions(-) > > > > create mode 100644 arch/powerpc/include/asm/booke_save_regs.h > > > > create mode 100644 arch/powerpc/kernel/booke_save_regs.S > > > > > > > > diff --git a/arch/powerpc/include/asm/booke_save_regs.h > > > > b/arch/powerpc/include/asm/booke_save_regs.h > > > > new file mode 100644 > > > > index 000..87c357a > > > > --- /dev/null > > > > +++ b/arch/powerpc/include/asm/booke_save_regs.h > > > > @@ -0,0 +1,96 @@ > > > > +/* > > > > + * Save/restore e500 series core registers > > > > > > Filename says booke, comment says e500. > > > > > > Filename and comment also fail to point out that this is specifically > > > for standby/suspend, not for hibernate which is implemented in > > > swsusp_booke.S/swsusp_asm64.S. > > > > Sorry for inconsistency. Will changes e500 to booke. > > Hibernation and suspend can share the code. > > Maybe they could, but AFAICT this patchset doesn't make that happen -- > and I'm not convinced that the churn would be worthwhile. Note that > swsusp_asm64.S is not just for booke, so most of that file would not be > going away if you did make such a change. OK. Let's put Hibernation aside, and change the code just for suspend. > > I also don't like the way it looks like booke_save_regs.S is a booke > version of ppc_save_regs.S, even though they serve different purposes > and ppc_save_regs.S is still relevant to booke. > > > > > + * Software-Use Registers > > > > + * SPRG1 0x260 (dw * 76), 64-bit need > > > > to save. > > > > + * SPRG3 0x268 (dw * 77), 32-bit need > > > > to save. > > > > > > What about "CPU and NUMA node for VDSO getcpu" on 64-bit? Currently > > > SPRG3, but it will need to change for critical interrupt support. > > > > > > > + * MMU Registers > > > > + * PID0 - PID2 0x270 ~ 0x280 (dw * 78 ~ dw * 80) > > > > > > PID1/PID2 are e500v1/v2 only -- and Linux doesn't use them outside of > > > KVM (and you're not in KVM when you're running this code). > > > > > > Are we ever going to have a non-zero PID at this point? > > > > I incline to the view that saving all registers regardless of used or > > unused. The good point is that it can be compliant to the future > > changes of the usage of registers. > > > > What do you think? > > I agree to a certain extent, but balance it with the complexity of > dealing with registers that don't exist on all booke chips. If they > don't really need to be saved, why go through the hassle of conditional > code? I agree. For these registers, I'll check if they are really needed. -Chenhui -- 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/
Re: [PATCH 7/9] fsl: add EPU FSM configuration for deep sleep
On Fri, Mar 14, 2014 at 05:51:09PM -0500, Scott Wood wrote: > On Wed, 2014-03-12 at 16:34 +0800, Chenhui Zhao wrote: > > On Tue, Mar 11, 2014 at 07:08:43PM -0500, Scott Wood wrote: > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > From: Hongbo Zhang > > > > > > > > In the last stage of deep sleep, software will trigger a Finite > > > > State Machine (FSM) to control the hardware precedure, such as > > > > board isolation, killing PLLs, removing power, and so on. > > > > > > > > When the system is waked up by an interrupt, the FSM controls the > > > > hardware to complete the early resume precedure. > > > > > > > > This patch configure the EPU FSM preparing for deep sleep. > > > > > > > > Signed-off-by: Hongbo Zhang > > > > Signed-off-by: Chenhui Zhao > > > > > > Couldn't this be part of qoriq_pm.c? > > > > Put the code in drivers/platform/fsl/ so that LS1 can share these code. > > How can LS1 share it if it's got hardcoded T1040 values? > > > > > diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig > > > > index 09fde58..6539e6d 100644 > > > > --- a/drivers/platform/Kconfig > > > > +++ b/drivers/platform/Kconfig > > > > @@ -6,3 +6,7 @@ source "drivers/platform/goldfish/Kconfig" > > > > endif > > > > > > > > source "drivers/platform/chrome/Kconfig" > > > > + > > > > +if FSL_SOC > > > > +source "drivers/platform/fsl/Kconfig" > > > > +endif > > > > > > Chrome doesn't need an ifdef -- why does this? > > > > Don't wish other platform see these options, and the X86 and GOLDFISH have > > ifdefs. > > The point is you can implement the dependency inside > drivers/platform/fsl/Kconfig. OK. > > > > > diff --git a/drivers/platform/fsl/Makefile > > > > b/drivers/platform/fsl/Makefile > > > > new file mode 100644 > > > > index 000..d99ca0e > > > > --- /dev/null > > > > +++ b/drivers/platform/fsl/Makefile > > > > @@ -0,0 +1,5 @@ > > > > +# > > > > +# Makefile for linux/drivers/platform/fsl > > > > +# Freescale Specific Power Management Drivers > > > > +# > > > > +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o > > > > > > Why is this here while the other stuff is in arch/powerpc/sysdev? > > > > > > > +/* Block offsets */ > > > > +#defineRCPM_BLOCK_OFFSET 0x00022000 > > > > +#defineEPU_BLOCK_OFFSET0x > > > > +#defineNPC_BLOCK_OFFSET0x1000 > > > > > > Why don't these block offsets come from the device tree? > > > > Have maped DCSR registers. Don't wish to remap them. > > We don't wish to have hardcoded CCSR/DCSR offsets in the kernel source. > Sorry. OK. > > > > > + /* Configure the EPU Counters */ > > > > + epu_write(EPCCR15, 0x9284); > > > > + epu_write(EPCCR14, 0x9284); > > > > + epu_write(EPCCR12, 0x9284); > > > > + epu_write(EPCCR11, 0x9284); > > > > + epu_write(EPCCR10, 0x9284); > > > > + epu_write(EPCCR9, 0x9284); > > > > + epu_write(EPCCR8, 0x9284); > > > > + epu_write(EPCCR5, 0x9284); > > > > + epu_write(EPCCR4, 0x9284); > > > > + epu_write(EPCCR2, 0x9284); > > > > + > > > > + /* Configure the SCUs Inputs */ > > > > + epu_write(EPSMCR15, 0x7600); > > > > + epu_write(EPSMCR14, 0x0031); > > > > + epu_write(EPSMCR13, 0x3100); > > > > + epu_write(EPSMCR12, 0x7F00); > > > > + epu_write(EPSMCR11, 0x3174); > > > > + epu_write(EPSMCR10, 0x6530); > > > > + epu_write(EPSMCR9, 0x3000); > > > > + epu_write(EPSMCR8, 0x6430); > > > > + epu_write(EPSMCR7, 0x3000); > > > > + epu_write(EPSMCR6, 0x7C00); > > > > + epu_write(EPSMCR5, 0x2E00); > > > > + epu_write(EPSMCR4, 0x002F); > > > > + epu_write(EPSMCR3, 0x2F00); > > > > + epu_write(EPSMCR2, 0x6C70); > > > > > > Where do these magic numbers come from? Which chips are they valid for? > > > > They are for T1040. Can be found in the RCPM chapter of T1040RM. > > Then put in a comment to that effect, including what part of the RCPM > chapter. > > How do you plan to handle the addition of another SoC with different > values? > > -Scott Had thought that using an array to put these values (pairs of offset and value) and passing the array to the function. However, luckily T104x and LS1 have same values for these registers according to the current Reference Manuals. -Chenhui -- 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/
Re: [PATCH 5/9] powerpc/85xx: disable irq by hardware when suspend for 64-bit
On Fri, Mar 14, 2014 at 05:41:41PM -0500, Scott Wood wrote: > On Wed, 2014-03-12 at 15:46 +0800, Chenhui Zhao wrote: > > On Tue, Mar 11, 2014 at 06:51:20PM -0500, Scott Wood wrote: > > > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > > > In 64-bit mode, kernel just clears the irq soft-enable flag > > > > in struct paca_struct to disable external irqs. But, in > > > > the case of suspend, irqs should be disabled by hardware. > > > > Therefore, hook a function to ppc_md.suspend_disable_irqs > > > > to really disable irqs. > > > > > > > > Signed-off-by: Chenhui Zhao > > > > --- > > > > arch/powerpc/platforms/85xx/corenet_generic.c | 12 > > > > 1 files changed, 12 insertions(+), 0 deletions(-) > > > > > > > > diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c > > > > b/arch/powerpc/platforms/85xx/corenet_generic.c > > > > index 3fdf9f3..983d81f 100644 > > > > --- a/arch/powerpc/platforms/85xx/corenet_generic.c > > > > +++ b/arch/powerpc/platforms/85xx/corenet_generic.c > > > > @@ -32,6 +32,13 @@ > > > > #include > > > > #include "smp.h" > > > > > > > > +#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND) > > > > +static void fsl_suspend_disable_irqs(void) > > > > +{ > > > > + __hard_irq_disable(); > > > > +} > > > > +#endif > > > > > > Why the underscore version? Don't you want PACA_IRQ_HARD_DIS to be set? > > > > > > If hard disabling is appropriate here, shouldn't we do it in > > > generic_suspend_disable_irqs()? > > > > > > Are there any existing platforms that supply a > > > ppc_md.suspend_disable_irqs()? I don't see any when grepping. > > > > > > -Scott > > > > Will use hard_irq_disable(). > > > > I think this is a general problem for powerpc. > > Should clear MSR_EE before suspend. I agree to put it > > in generic_suspend_disable_irqs(). > > BTW, make sure you test this patchset with CONFIG_DEBUG_PREEMPT and > similar debugging options to help ensure that the soft IRQ state is > being tracked properly. > > -Scott OK. I'll keep that in mind. -Chenhui -- 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/
Re: [PATCH 9/9] powerpc/pm: support deep sleep feature on T1040
On Tue, Mar 11, 2014 at 08:10:24PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > From: Zhao Chenhui > > > > T1040 supports deep sleep feature, which can switch off most parts of > > the SoC when it is in deep sleep mode. This way, it becomes more > > energy-efficient. > > > > The DDR controller will also be powered off in deep sleep. Therefore, > > the last stage (the latter part of fsl_dp_enter_low) will run without DDR > > access. This piece of code and related TLBs will be prefetched. > > > > Due to the different initialization code between 32-bit and 64-bit, they > > have seperate resume entry and precedure. > > > > The feature supports 32-bit and 64-bit kernel mode. > > > > Signed-off-by: Zhao Chenhui > > --- > > arch/powerpc/include/asm/booke_save_regs.h |3 + > > arch/powerpc/kernel/cpu_setup_fsl_booke.S | 17 ++ > > arch/powerpc/kernel/head_fsl_booke.S | 30 +++ > > arch/powerpc/platforms/85xx/Makefile |2 +- > > arch/powerpc/platforms/85xx/deepsleep.c| 201 +++ > > arch/powerpc/platforms/85xx/qoriq_pm.c | 38 > > arch/powerpc/platforms/85xx/sleep.S| 295 > > > > arch/powerpc/sysdev/fsl_soc.h |7 + > > 8 files changed, 592 insertions(+), 1 deletions(-) > > create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c > > create mode 100644 arch/powerpc/platforms/85xx/sleep.S > > > > diff --git a/arch/powerpc/include/asm/booke_save_regs.h > > b/arch/powerpc/include/asm/booke_save_regs.h > > index 87c357a..37c1f6c 100644 > > --- a/arch/powerpc/include/asm/booke_save_regs.h > > +++ b/arch/powerpc/include/asm/booke_save_regs.h > > @@ -88,6 +88,9 @@ > > #define HIBERNATION_FLAG 1 > > #define DEEPSLEEP_FLAG 2 > > > > +#define CPLD_FLAG 1 > > +#define FPGA_FLAG 2 > > What is this? We have two kind of boards, QDS and RDB. They have different register map. Use the flag to indicate the current board is using which kind of register map. > > > #ifndef __ASSEMBLY__ > > extern void booke_cpu_state_save(void *buf, int type); > > extern void *booke_cpu_state_restore(void *buf, int type); > > diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S > > b/arch/powerpc/kernel/cpu_setup_fsl_booke.S > > index e59d6de..ea9bc28 100644 > > --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S > > +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S > > @@ -318,6 +318,23 @@ flush_backside_L2_cache: > > 2: > > blr > > > > +#define CPC_CPCCSR00x0 > > +#define CPC_CPCCSR0_CPCFL 0x800 > > This is supposed to be CPU setup, not platform setup. > > > +/* r3 : the base address of CPC */ > > +_GLOBAL(fsl_flush_cpc_cache) > > + lwz r6, CPC_CPCCSR0(r3) > > + ori r6, r6, CPC_CPCCSR0_CPCFL > > + stw r6, CPC_CPCCSR0(r3) > > + sync > > + > > + /* Wait until completing the flush */ > > +1: lwz r6, CPC_CPCCSR0(r3) > > + andi. r6, r6, CPC_CPCCSR0_CPCFL > > + bne 1b > > + > > + blr > > + > > _GLOBAL(__flush_caches_e500v2) > > I'm not sure that this belongs here either. Will find a better place. > > > mflr r0 > > bl flush_dcache_L1 > > diff --git a/arch/powerpc/kernel/head_fsl_booke.S > > b/arch/powerpc/kernel/head_fsl_booke.S > > index 20204fe..3285752 100644 > > --- a/arch/powerpc/kernel/head_fsl_booke.S > > +++ b/arch/powerpc/kernel/head_fsl_booke.S > > @@ -162,6 +162,19 @@ _ENTRY(__early_start) > > #include "fsl_booke_entry_mapping.S" > > #undef ENTRY_MAPPING_BOOT_SETUP > > > > +#if defined(CONFIG_SUSPEND) && defined(CONFIG_FSL_CORENET_RCPM) > > + /* if deep_sleep_flag != 0, jump to the deep sleep resume entry */ > > + LOAD_REG_ADDR(r4, deep_sleep_flag) > > + lwz r3, 0(r4) > > + cmpwi r3, 0 > > + beq 11f > > + /* clear deep_sleep_flag */ > > + li r3, 0 > > + stw r3, 0(r4) > > + b fsl_deepsleep_resume > > +11: > > +#endif > > Why do you come in via the normal kernel entry, versus specifying a > direct entry point for deep sleep resume? How does U-Boot even know > what the normal entry is when resuming? I wish to return to a specified point (like 64-bit mode), but the code in fsl_booke_entry_mapping.S only can run in the first page. Because it only setups a temp mapping of 4KB. > > Be careful of the "beq s
Re: [PATCH 8/9] powerpc/85xx: add save/restore functions for core registers
On Tue, Mar 11, 2014 at 07:45:14PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > From: Wang Dongsheng > > > > Add booke_cpu_state_save() and booke_cpu_state_restore() functions which > > can be > > used to save/restore CPU's registers in the case of deep sleep and > > hibernation. > > > > Supported processors: E6500, E5500, E500MC, E500v2 and E500v1. > > > > Signed-off-by: Wang Dongsheng > > Signed-off-by: Chenhui Zhao > > --- > > arch/powerpc/include/asm/booke_save_regs.h | 96 > > arch/powerpc/kernel/Makefile |1 + > > arch/powerpc/kernel/booke_save_regs.S | 361 > > > > 3 files changed, 458 insertions(+), 0 deletions(-) > > create mode 100644 arch/powerpc/include/asm/booke_save_regs.h > > create mode 100644 arch/powerpc/kernel/booke_save_regs.S > > > > diff --git a/arch/powerpc/include/asm/booke_save_regs.h > > b/arch/powerpc/include/asm/booke_save_regs.h > > new file mode 100644 > > index 000..87c357a > > --- /dev/null > > +++ b/arch/powerpc/include/asm/booke_save_regs.h > > @@ -0,0 +1,96 @@ > > +/* > > + * Save/restore e500 series core registers > > Filename says booke, comment says e500. > > Filename and comment also fail to point out that this is specifically > for standby/suspend, not for hibernate which is implemented in > swsusp_booke.S/swsusp_asm64.S. Sorry for inconsistency. Will changes e500 to booke. Hibernation and suspend can share the code. > > > + * > > + * Author: Wang Dongsheng > > + * > > + * Copyright 2014 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 version 2 as > > + * published by the Free Software Foundation. > > + */ > > + > > +#ifndef __ASM_FSL_SLEEP_H > > +#define __ASM_FSL_SLEEP_H > > + > > +/* > > + * 8 bytes for each register, which is compatible with > > + * both 32-bit and 64-bit registers > > + * > > + * Acronyms: > > + * dw(data width) 0x08 > > + * > > + * Map: > > + * General-Purpose Registers > > + * GPR1(sp)0 > > + * GPR20x8 (dw * 1) > > + * GPR13 - GPR31 0x10 ~ 0xa0 (dw * 2 ~ dw * 20) > > Putting these values in a comment separate from the code that defines it > sounds like a good way to get a mismatch between the two. Ok. > > > + * Foating-point registers > > + * FPR14 - FPR31 0xa8 ~ 0x130(dw * 21 ~ dw * 38) > > Call enable_kernel_fp() or similar, rather than saving FP regs here. > Likewise with altivec. And why starting at FPR14? Volatile versus > nonvolatile is irrelevant because Linux doesn't participate in the FP > ABI. Everything is non-volatile *if* we have a user FP context > resident, and everything is volatile otherwise. Will remove them. > > > + * Timer Registers > > + * TCR 0x168 (dw * 45) > > + * TB(64bit) 0x170 (dw * 46) > > + * TBU(32bit) 0x178 (dw * 47) > > + * TBL(32bit) 0x180 (dw * 48) > > Why are you saving TBU/L separate from TB? They're the same thing. Will remove TBU and TBL. > > > + * Interrupt Registers > > + * IVPR0x188 (dw * 49) > > + * IVOR0 - IVOR15 0x190 ~ 0x208 (dw * 50 ~ dw * 65) > > + * IVOR32 - IVOR41 0x210 ~ 0x258 (dw * 66 ~ dw * 75) > > What about IVOR42 (LRAT error)? Will add it. > > > + * Software-Use Registers > > + * SPRG1 0x260 (dw * 76), 64-bit need to save. > > + * SPRG3 0x268 (dw * 77), 32-bit need to save. > > What about "CPU and NUMA node for VDSO getcpu" on 64-bit? Currently > SPRG3, but it will need to change for critical interrupt support. > > > + * MMU Registers > > + * PID0 - PID2 0x270 ~ 0x280 (dw * 78 ~ dw * 80) > > PID1/PID2 are e500v1/v2 only -- and Linux doesn't use them outside of > KVM (and you're not in KVM when you're running this code). > > Are we ever going to have a non-zero PID at this point? I incline to the view that saving all registers regardless of used or unused. The good point is that it can be compliant to the future changes of the usage of registers. What do you think? > > > + * Debug Registers > > + * DBCR0 - DBCR2 0x288 ~ 0x298 (dw *
Re: [PATCH 7/9] fsl: add EPU FSM configuration for deep sleep
On Tue, Mar 11, 2014 at 07:08:43PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > From: Hongbo Zhang > > > > In the last stage of deep sleep, software will trigger a Finite > > State Machine (FSM) to control the hardware precedure, such as > > board isolation, killing PLLs, removing power, and so on. > > > > When the system is waked up by an interrupt, the FSM controls the > > hardware to complete the early resume precedure. > > > > This patch configure the EPU FSM preparing for deep sleep. > > > > Signed-off-by: Hongbo Zhang > > Signed-off-by: Chenhui Zhao > > Couldn't this be part of qoriq_pm.c? Put the code in drivers/platform/fsl/ so that LS1 can share these code. > > > diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h > > index 9b9a34a..eb83a30 100644 > > --- a/arch/powerpc/sysdev/fsl_soc.h > > +++ b/arch/powerpc/sysdev/fsl_soc.h > > @@ -69,5 +69,8 @@ extern const struct fsl_pm_ops *qoriq_pm_ops; > > > > extern int fsl_rcpm_init(void); > > > > +extern void fsl_dp_fsm_setup(void *dcsr_base); > > +extern void fsl_dp_fsm_clean(void *dcsr_base); > > __iomem Thanks. Will add. > > > + > > #endif > > #endif > > diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig > > index 09fde58..6539e6d 100644 > > --- a/drivers/platform/Kconfig > > +++ b/drivers/platform/Kconfig > > @@ -6,3 +6,7 @@ source "drivers/platform/goldfish/Kconfig" > > endif > > > > source "drivers/platform/chrome/Kconfig" > > + > > +if FSL_SOC > > +source "drivers/platform/fsl/Kconfig" > > +endif > > Chrome doesn't need an ifdef -- why does this? Don't wish other platform see these options, and the X86 and GOLDFISH have ifdefs. > > > diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile > > index 3656b7b..37c6f72 100644 > > --- a/drivers/platform/Makefile > > +++ b/drivers/platform/Makefile > > @@ -6,3 +6,4 @@ obj-$(CONFIG_X86) += x86/ > > obj-$(CONFIG_OLPC) += olpc/ > > obj-$(CONFIG_GOLDFISH) += goldfish/ > > obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ > > +obj-$(CONFIG_FSL_SOC) += fsl/ > > diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig > > new file mode 100644 > > index 000..72ed053 > > --- /dev/null > > +++ b/drivers/platform/fsl/Kconfig > > @@ -0,0 +1,10 @@ > > +# > > +# Freescale Specific Power Management Drivers > > +# > > + > > +config FSL_SLEEP_FSM > > + bool > > + help > > + This driver configures a hardware FSM (Finite State Machine) for deep > > sleep. > > + The FSM is used to finish clean-ups at the last stage of system > > entering deep > > + sleep, and also wakes up system when a wake up event happens. > > diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile > > new file mode 100644 > > index 000..d99ca0e > > --- /dev/null > > +++ b/drivers/platform/fsl/Makefile > > @@ -0,0 +1,5 @@ > > +# > > +# Makefile for linux/drivers/platform/fsl > > +# Freescale Specific Power Management Drivers > > +# > > +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o > > Why is this here while the other stuff is in arch/powerpc/sysdev? > > > +/* Block offsets */ > > +#defineRCPM_BLOCK_OFFSET 0x00022000 > > +#defineEPU_BLOCK_OFFSET0x > > +#defineNPC_BLOCK_OFFSET0x1000 > > Why don't these block offsets come from the device tree? Have maped DCSR registers. Don't wish to remap them. > > > +static void *g_dcsr_base; > > __iomem OK. > > > + /* Configure the EPU Counters */ > > + epu_write(EPCCR15, 0x9284); > > + epu_write(EPCCR14, 0x9284); > > + epu_write(EPCCR12, 0x9284); > > + epu_write(EPCCR11, 0x9284); > > + epu_write(EPCCR10, 0x9284); > > + epu_write(EPCCR9, 0x9284); > > + epu_write(EPCCR8, 0x9284); > > + epu_write(EPCCR5, 0x9284); > > + epu_write(EPCCR4, 0x9284); > > + epu_write(EPCCR2, 0x9284); > > + > > + /* Configure the SCUs Inputs */ > > + epu_write(EPSMCR15, 0x7600); > > + epu_write(EPSMCR14, 0x0031); > > + epu_write(EPSMCR13, 0x3100); > > + epu_write(EPSMCR12, 0x7F00); > > + epu_write(EPSMCR11, 0x3174); > > + epu_write(EPSMCR10, 0x6530); > >
Re: [PATCH 6/9] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
On Tue, Mar 11, 2014 at 07:00:27PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > In sleep mode, the clocks of e500 cores and unused IP blocks is > > turned off. The IP blocks which are allowed to wake up the processor > > are still running. > > > > The sleep mode is equal to the Standby state in Linux. Use the > > command to enter sleep mode: > > echo standby > /sys/power/state > > > > Signed-off-by: Chenhui Zhao > > --- > > arch/powerpc/Kconfig |4 +- > > arch/powerpc/platforms/85xx/Makefile |3 + > > arch/powerpc/platforms/85xx/qoriq_pm.c | 78 > > > > 3 files changed, 83 insertions(+), 2 deletions(-) > > create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c > > > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > > index 05f6323..e1d6510 100644 > > --- a/arch/powerpc/Kconfig > > +++ b/arch/powerpc/Kconfig > > @@ -222,7 +222,7 @@ config ARCH_HIBERNATION_POSSIBLE > > config ARCH_SUSPEND_POSSIBLE > > def_bool y > > depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ > > - (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ > > + FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \ > >|| 44x || 40x > > > > config PPC_DCR_NATIVE > > @@ -709,7 +709,7 @@ config FSL_PCI > > config FSL_PMC > > bool > > default y > > - depends on SUSPEND && (PPC_85xx || PPC_86xx) > > + depends on SUSPEND && (PPC_85xx && !PPC_E500MC || PPC_86xx) > > Don't mix && and || without parentheses. > > Maybe convert this into being selected (similar to FSL_RCPM), rather > than default y? Yes, will do. > > > diff --git a/arch/powerpc/platforms/85xx/Makefile > > b/arch/powerpc/platforms/85xx/Makefile > > index 25cebe7..7fae817 100644 > > --- a/arch/powerpc/platforms/85xx/Makefile > > +++ b/arch/powerpc/platforms/85xx/Makefile > > @@ -2,6 +2,9 @@ > > # Makefile for the PowerPC 85xx linux kernel. > > # > > obj-$(CONFIG_SMP) += smp.o > > +ifeq ($(CONFIG_FSL_CORENET_RCPM), y) > > +obj-$(CONFIG_SUSPEND) += qoriq_pm.o > > +endif > > There should probably be a kconfig symbol for this. OK. > > > diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c > > b/arch/powerpc/platforms/85xx/qoriq_pm.c > > new file mode 100644 > > index 000..915b13b > > --- /dev/null > > +++ b/arch/powerpc/platforms/85xx/qoriq_pm.c > > @@ -0,0 +1,78 @@ > > +/* > > + * Support Power Management feature > > + * > > + * Copyright 2014 Freescale Semiconductor Inc. > > + * > > + * Author: Chenhui Zhao > > + * > > + * 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 > > +#include > > +#include > > + > > +#include > > + > > +#define FSL_SLEEP 0x1 > > +#define FSL_DEEP_SLEEP 0x2 > > FSL_DEEP_SLEEP is unused. Will be used in the last patch. [PATCH 9/9] powerpc/pm: support deep sleep feature on T1040 > > > + > > +/* specify the sleep state of the present platform */ > > +int sleep_pm_state; > > +/* supported sleep modes by the present platform */ > > +static unsigned int sleep_modes; > > Why is one signed and the other unsigned? Undesigned. Will change them all to unsigned. > > > + > > +static int qoriq_suspend_enter(suspend_state_t state) > > +{ > > + int ret = 0; > > + > > + switch (state) { > > + case PM_SUSPEND_STANDBY: > > + > > + if (cur_cpu_spec->cpu_flush_caches) > > + cur_cpu_spec->cpu_flush_caches(); > > + > > + ret = qoriq_pm_ops->plat_enter_state(sleep_pm_state); > > + > > + break; > > + > > + default: > > + ret = -EINVAL; > > + > > + } > > + > > + return ret; > > +} > > + > > +static int qoriq_suspend_valid(suspend_state_t state) > > +{ > > + if (state == PM_SUSPEND_STANDBY && (sleep_modes & FSL_SLEEP)) > > + return 1; > > + > > + return 0; > > +} > > + > > +static const struct platf
Re: [PATCH 5/9] powerpc/85xx: disable irq by hardware when suspend for 64-bit
On Tue, Mar 11, 2014 at 06:51:20PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > In 64-bit mode, kernel just clears the irq soft-enable flag > > in struct paca_struct to disable external irqs. But, in > > the case of suspend, irqs should be disabled by hardware. > > Therefore, hook a function to ppc_md.suspend_disable_irqs > > to really disable irqs. > > > > Signed-off-by: Chenhui Zhao > > --- > > arch/powerpc/platforms/85xx/corenet_generic.c | 12 > > 1 files changed, 12 insertions(+), 0 deletions(-) > > > > diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c > > b/arch/powerpc/platforms/85xx/corenet_generic.c > > index 3fdf9f3..983d81f 100644 > > --- a/arch/powerpc/platforms/85xx/corenet_generic.c > > +++ b/arch/powerpc/platforms/85xx/corenet_generic.c > > @@ -32,6 +32,13 @@ > > #include > > #include "smp.h" > > > > +#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND) > > +static void fsl_suspend_disable_irqs(void) > > +{ > > + __hard_irq_disable(); > > +} > > +#endif > > Why the underscore version? Don't you want PACA_IRQ_HARD_DIS to be set? > > If hard disabling is appropriate here, shouldn't we do it in > generic_suspend_disable_irqs()? > > Are there any existing platforms that supply a > ppc_md.suspend_disable_irqs()? I don't see any when grepping. > > -Scott Will use hard_irq_disable(). I think this is a general problem for powerpc. Should clear MSR_EE before suspend. I agree to put it in generic_suspend_disable_irqs(). -Chenhui -- 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/
Re: [PATCH 4/9] powerpc/85xx: support CPU hotplug for e500mc and e5500
On Tue, Mar 11, 2014 at 06:48:13PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:58 +0800, Chenhui Zhao wrote: > > diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c > > index ac2621a..f3f4401 100644 > > --- a/arch/powerpc/kernel/smp.c > > +++ b/arch/powerpc/kernel/smp.c > > @@ -405,8 +405,12 @@ void generic_cpu_die(unsigned int cpu) > > > > for (i = 0; i < 100; i++) { > > smp_rmb(); > > - if (per_cpu(cpu_state, cpu) == CPU_DEAD) > > + if (per_cpu(cpu_state, cpu) == CPU_DEAD) { > > +#ifdef CONFIG_PPC64 > > + paca[cpu].cpu_start = 0; > > +#endif > > Why wasn't this needed by previous ppc64 machines? If not clear, cpu can't start in the case of cpu hotpolug. The function pseries_cpu_die() in arch/powerpc/platforms/pseries/hotplug-cpu.c also clears the flag. > > > diff --git a/arch/powerpc/platforms/85xx/smp.c > > b/arch/powerpc/platforms/85xx/smp.c > > index 2e5911e..0047883 100644 > > --- a/arch/powerpc/platforms/85xx/smp.c > > +++ b/arch/powerpc/platforms/85xx/smp.c > > @@ -19,6 +19,7 @@ > > #include > > #include > > #include > > +#include > > > > #include > > #include > > @@ -46,6 +47,17 @@ static u64 timebase; > > static int tb_req; > > static int tb_valid; > > > > +#ifdef CONFIG_PPC_E500MC > > +/* specify the cpu PM state when cpu dies, PH15/NAP is the default */ > > +int qoriq_cpu_die_state = E500_PM_PH15; > > +#endif > > static? Is there any way to modify this other than modifying source > code? > > BTW, QorIQ doesn't imply an e500mc derivative. Will support e500, but for now these code support e500mc derivative in advance. Supposed qoriq_cpu_die_state can be changed by platform init code if the default value is not proper for a specific platform. > > > @@ -125,6 +138,34 @@ static void mpc85xx_take_timebase(void) > > } > > > > #ifdef CONFIG_HOTPLUG_CPU > > +#ifdef CONFIG_PPC_E500MC > > +static void qoriq_cpu_die(void) > > +{ > > + unsigned int cpu = smp_processor_id(); > > + > > + local_irq_disable(); > > +#ifdef CONFIG_PPC64 > > + __hard_irq_disable(); > > +#endif > > Why this instead of one call to hard_irq_disable() (no leading > underscores)? > > -Scott hard_irq_disable() will clear soft_enabled again. local_irq_disable() has cleared it. Will use hard_irq_disable() to replace these lines. local_irq_disable(); #ifdef CONFIG_PPC64 __hard_irq_disable(); #endif -Chenhui -- 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/
Re: [PATCH 3/9] powerpc/rcpm: add RCPM driver
On Tue, Mar 11, 2014 at 06:42:51PM -0500, Scott Wood wrote: > On Fri, 2014-03-07 at 12:57 +0800, Chenhui Zhao wrote: > > diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c > > b/arch/powerpc/platforms/85xx/corenet_generic.c > > index b756f3d..3fdf9f3 100644 > > --- a/arch/powerpc/platforms/85xx/corenet_generic.c > > +++ b/arch/powerpc/platforms/85xx/corenet_generic.c > > @@ -56,6 +56,8 @@ void __init corenet_gen_setup_arch(void) > > > > swiotlb_detect_4g(); > > > > + fsl_rcpm_init(); > > + > > pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); > > RCPM is not board-specific. Why is this in board code? Init the RCPM driver in the early stage before smp_init(). Because the time base sync calls a callback function .freeze_time_base() in the RCPM driver. Will use early_initcall() instead. > > > +static void rcpm_v1_cpu_enter_state(int cpu, int state) > > +{ > > + unsigned int hw_cpu = get_hard_smp_processor_id(cpu); > > + unsigned int mask = 1 << hw_cpu; > > + > > + switch (state) { > > + case E500_PM_PH10: > > + setbits32(&rcpm_v1_regs->cdozcr, mask); > > + break; > > + case E500_PM_PH15: > > + setbits32(&rcpm_v1_regs->cnapcr, mask); > > + break; > > + default: > > + pr_err("Unknown cpu PM state\n"); > > + break; > > + } > > +} > > Put __func__ in error messages -- and for "unknown value" type messages, > print the value. OK. > > > > +static int rcpm_v1_plat_enter_state(int state) > > +{ > > + u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr; > > + int ret = 0; > > + int result; > > + > > + switch (state) { > > + case PLAT_PM_SLEEP: > > + setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP); > > + > > + /* At this point, the device is in sleep mode. */ > > + > > + /* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */ > > + result = spin_event_timeout( > > + !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 1, 10); > > + if (!result) { > > + pr_err("%s: timeout waiting for SLP bit to be > > cleared\n", > > + __func__); > > Why are you indenting continuation lines with only two spaces (and yet > still not aligning with anything)? Will align with the previous parenthesis. > > > + ret = -ETIMEDOUT; > > + } > > + break; > > + default: > > + pr_err("Unsupported platform PM state\n"); > > + ret = -EINVAL; > > + } > > + > > + return ret; > > +} > > + > > +static void rcpm_v1_freeze_time_base(int freeze) > > +{ > > + u32 *tben_reg = &rcpm_v1_regs->ctbenr; > > + static u32 mask; > > + > > + if (freeze) { > > + mask = in_be32(tben_reg); > > + clrbits32(tben_reg, mask); > > + } else { > > + setbits32(tben_reg, mask); > > + } > > + > > + /* read back to push the previous write */ > > + in_be32(tben_reg); > > +} > > + > > +static void rcpm_v2_freeze_time_base(int freeze) > > +{ > > + u32 *tben_reg = &rcpm_v2_regs->pctbenr; > > + static u32 mask; > > + > > + if (freeze) { > > + mask = in_be32(tben_reg); > > + clrbits32(tben_reg, mask); > > + } else { > > + setbits32(tben_reg, mask); > > + } > > + > > + /* read back to push the previous write */ > > + in_be32(tben_reg); > > +} > > It looks like the only difference between these two functions is how you > calculate tben_reg -- factor the rest out into a single function. Yes. Will factor them out into a single function. > > > +int fsl_rcpm_init(void) > > +{ > > + struct device_node *np; > > + > > + np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.0"); > > + if (np) { > > + rcpm_v2_regs = of_iomap(np, 0); > > + of_node_put(np); > > + if (!rcpm_v2_regs) > > + return -ENOMEM; > > + > > + qoriq_pm_ops = &qoriq_rcpm_v2_ops; > > + > > + } else { > > + np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-1.0"); > > + if (np) { > > + rcpm_v1_regs = of_iomap(np, 0); > > +
[PATCH 6/9] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM
In sleep mode, the clocks of e500 cores and unused IP blocks is turned off. The IP blocks which are allowed to wake up the processor are still running. The sleep mode is equal to the Standby state in Linux. Use the command to enter sleep mode: echo standby > /sys/power/state Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig |4 +- arch/powerpc/platforms/85xx/Makefile |3 + arch/powerpc/platforms/85xx/qoriq_pm.c | 78 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/qoriq_pm.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 05f6323..e1d6510 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -222,7 +222,7 @@ config ARCH_HIBERNATION_POSSIBLE config ARCH_SUSPEND_POSSIBLE def_bool y depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \ - (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \ + FSL_SOC_BOOKE || PPC_86xx || PPC_PSERIES \ || 44x || 40x config PPC_DCR_NATIVE @@ -709,7 +709,7 @@ config FSL_PCI config FSL_PMC bool default y - depends on SUSPEND && (PPC_85xx || PPC_86xx) + depends on SUSPEND && (PPC_85xx && !PPC_E500MC || PPC_86xx) help Freescale MPC85xx/MPC86xx power management controller support (suspend/resume). For MPC83xx see platforms/83xx/suspend.c diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 25cebe7..7fae817 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -2,6 +2,9 @@ # Makefile for the PowerPC 85xx linux kernel. # obj-$(CONFIG_SMP) += smp.o +ifeq ($(CONFIG_FSL_CORENET_RCPM), y) +obj-$(CONFIG_SUSPEND) += qoriq_pm.o +endif obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/qoriq_pm.c b/arch/powerpc/platforms/85xx/qoriq_pm.c new file mode 100644 index 000..915b13b --- /dev/null +++ b/arch/powerpc/platforms/85xx/qoriq_pm.c @@ -0,0 +1,78 @@ +/* + * Support Power Management feature + * + * Copyright 2014 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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 +#include +#include + +#include + +#define FSL_SLEEP 0x1 +#define FSL_DEEP_SLEEP 0x2 + +/* specify the sleep state of the present platform */ +int sleep_pm_state; +/* supported sleep modes by the present platform */ +static unsigned int sleep_modes; + +static int qoriq_suspend_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + + if (cur_cpu_spec->cpu_flush_caches) + cur_cpu_spec->cpu_flush_caches(); + + ret = qoriq_pm_ops->plat_enter_state(sleep_pm_state); + + break; + + default: + ret = -EINVAL; + + } + + return ret; +} + +static int qoriq_suspend_valid(suspend_state_t state) +{ + if (state == PM_SUSPEND_STANDBY && (sleep_modes & FSL_SLEEP)) + return 1; + + return 0; +} + +static const struct platform_suspend_ops qoriq_suspend_ops = { + .valid = qoriq_suspend_valid, + .enter = qoriq_suspend_enter, +}; + +static int __init qoriq_suspend_init(void) +{ + struct device_node *np; + + sleep_modes = FSL_SLEEP; + sleep_pm_state = PLAT_PM_SLEEP; + + np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-rcpm-2.0"); + if (np) + sleep_pm_state = PLAT_PM_LPM20; + + suspend_set_ops(&qoriq_suspend_ops); + + return 0; +} +arch_initcall(qoriq_suspend_init); -- 1.7.3 -- 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/
[PATCH 9/9] powerpc/pm: support deep sleep feature on T1040
From: Zhao Chenhui T1040 supports deep sleep feature, which can switch off most parts of the SoC when it is in deep sleep mode. This way, it becomes more energy-efficient. The DDR controller will also be powered off in deep sleep. Therefore, the last stage (the latter part of fsl_dp_enter_low) will run without DDR access. This piece of code and related TLBs will be prefetched. Due to the different initialization code between 32-bit and 64-bit, they have seperate resume entry and precedure. The feature supports 32-bit and 64-bit kernel mode. Signed-off-by: Zhao Chenhui --- arch/powerpc/include/asm/booke_save_regs.h |3 + arch/powerpc/kernel/cpu_setup_fsl_booke.S | 17 ++ arch/powerpc/kernel/head_fsl_booke.S | 30 +++ arch/powerpc/platforms/85xx/Makefile |2 +- arch/powerpc/platforms/85xx/deepsleep.c| 201 +++ arch/powerpc/platforms/85xx/qoriq_pm.c | 38 arch/powerpc/platforms/85xx/sleep.S| 295 arch/powerpc/sysdev/fsl_soc.h |7 + 8 files changed, 592 insertions(+), 1 deletions(-) create mode 100644 arch/powerpc/platforms/85xx/deepsleep.c create mode 100644 arch/powerpc/platforms/85xx/sleep.S diff --git a/arch/powerpc/include/asm/booke_save_regs.h b/arch/powerpc/include/asm/booke_save_regs.h index 87c357a..37c1f6c 100644 --- a/arch/powerpc/include/asm/booke_save_regs.h +++ b/arch/powerpc/include/asm/booke_save_regs.h @@ -88,6 +88,9 @@ #define HIBERNATION_FLAG 1 #define DEEPSLEEP_FLAG 2 +#define CPLD_FLAG 1 +#define FPGA_FLAG 2 + #ifndef __ASSEMBLY__ extern void booke_cpu_state_save(void *buf, int type); extern void *booke_cpu_state_restore(void *buf, int type); diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index e59d6de..ea9bc28 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -318,6 +318,23 @@ flush_backside_L2_cache: 2: blr +#define CPC_CPCCSR00x0 +#define CPC_CPCCSR0_CPCFL 0x800 + +/* r3 : the base address of CPC */ +_GLOBAL(fsl_flush_cpc_cache) + lwz r6, CPC_CPCCSR0(r3) + ori r6, r6, CPC_CPCCSR0_CPCFL + stw r6, CPC_CPCCSR0(r3) + sync + + /* Wait until completing the flush */ +1: lwz r6, CPC_CPCCSR0(r3) + andi. r6, r6, CPC_CPCCSR0_CPCFL + bne 1b + + blr + _GLOBAL(__flush_caches_e500v2) mflr r0 bl flush_dcache_L1 diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 20204fe..3285752 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -162,6 +162,19 @@ _ENTRY(__early_start) #include "fsl_booke_entry_mapping.S" #undef ENTRY_MAPPING_BOOT_SETUP +#if defined(CONFIG_SUSPEND) && defined(CONFIG_FSL_CORENET_RCPM) + /* if deep_sleep_flag != 0, jump to the deep sleep resume entry */ + LOAD_REG_ADDR(r4, deep_sleep_flag) + lwz r3, 0(r4) + cmpwi r3, 0 + beq 11f + /* clear deep_sleep_flag */ + li r3, 0 + stw r3, 0(r4) + b fsl_deepsleep_resume +11: +#endif + set_ivor: /* Establish the interrupt vector offsets */ SET_IVOR(0, CriticalInput); @@ -343,6 +356,23 @@ set_ivor: lwz r11, 0(r12);/* Get Linux PTE */ #endif +#if defined(CONFIG_SUSPEND) && defined(CONFIG_FSL_CORENET_RCPM) +_ENTRY(__entry_deep_sleep) +/* + * Bootloader will jump to here when resuming from deep sleep. + * After executing the init code in fsl_booke_entry_mapping.S, + * will jump to the real resume entry. + */ + li r8, 1 + bl 12f +12:mflrr9 + addir9, r9, (deep_sleep_flag - 12b) + stw r8, 0(r9) + b __early_start +deep_sleep_flag: + .long 0 +#endif + /* * Interrupt vector entry code * diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 7fae817..9a4ea86 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_SMP) += smp.o ifeq ($(CONFIG_FSL_CORENET_RCPM), y) -obj-$(CONFIG_SUSPEND) += qoriq_pm.o +obj-$(CONFIG_SUSPEND) += qoriq_pm.o deepsleep.o sleep.o endif obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/deepsleep.c b/arch/powerpc/platforms/85xx/deepsleep.c new file mode 100644 index 000..ddd7185 --- /dev/null +++ b/arch/powerpc/platforms/85xx/deepsleep.c @@ -0,0 +1,201 @@ +/* + * Support deep sleep feature + * + * Copyright 2014 Freescale Semiconductor Inc. + * + * Author: Chenhui Zhao + * + * 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
[PATCH 7/9] fsl: add EPU FSM configuration for deep sleep
From: Hongbo Zhang In the last stage of deep sleep, software will trigger a Finite State Machine (FSM) to control the hardware precedure, such as board isolation, killing PLLs, removing power, and so on. When the system is waked up by an interrupt, the FSM controls the hardware to complete the early resume precedure. This patch configure the EPU FSM preparing for deep sleep. Signed-off-by: Hongbo Zhang Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/Kconfig |1 + arch/powerpc/sysdev/fsl_soc.h |3 + drivers/platform/Kconfig|4 + drivers/platform/Makefile |1 + drivers/platform/fsl/Kconfig| 10 + drivers/platform/fsl/Makefile |5 + drivers/platform/fsl/sleep_fsm.c| 415 +++ 7 files changed, 439 insertions(+), 0 deletions(-) create mode 100644 drivers/platform/fsl/Kconfig create mode 100644 drivers/platform/fsl/Makefile create mode 100644 drivers/platform/fsl/sleep_fsm.c diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 54d8843..27e2174 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -261,6 +261,7 @@ config CORENET_GENERIC select GPIO_MPC8XXX select HAS_RAPIDIO select PPC_EPAPR_HV_PIC + select FSL_SLEEP_FSM if SUSPEND help This option enables support for the FSL CoreNet based boards. For 32bit kernel, the following boards are supported: diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 9b9a34a..eb83a30 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -69,5 +69,8 @@ extern const struct fsl_pm_ops *qoriq_pm_ops; extern int fsl_rcpm_init(void); +extern void fsl_dp_fsm_setup(void *dcsr_base); +extern void fsl_dp_fsm_clean(void *dcsr_base); + #endif #endif diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 09fde58..6539e6d 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -6,3 +6,7 @@ source "drivers/platform/goldfish/Kconfig" endif source "drivers/platform/chrome/Kconfig" + +if FSL_SOC +source "drivers/platform/fsl/Kconfig" +endif diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 3656b7b..37c6f72 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_OLPC) += olpc/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ +obj-$(CONFIG_FSL_SOC) += fsl/ diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig new file mode 100644 index 000..72ed053 --- /dev/null +++ b/drivers/platform/fsl/Kconfig @@ -0,0 +1,10 @@ +# +# Freescale Specific Power Management Drivers +# + +config FSL_SLEEP_FSM + bool + help + This driver configures a hardware FSM (Finite State Machine) for deep sleep. + The FSM is used to finish clean-ups at the last stage of system entering deep + sleep, and also wakes up system when a wake up event happens. diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile new file mode 100644 index 000..d99ca0e --- /dev/null +++ b/drivers/platform/fsl/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for linux/drivers/platform/fsl +# Freescale Specific Power Management Drivers +# +obj-$(CONFIG_FSL_SLEEP_FSM)+= sleep_fsm.o diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c new file mode 100644 index 000..102 --- /dev/null +++ b/drivers/platform/fsl/sleep_fsm.c @@ -0,0 +1,415 @@ +/* + * Freescale deep sleep FSM (finite-state machine) configuration + * + * Copyright 2014 Freescale Semiconductor Inc. + * + * Author: Hongbo Zhang + * Chenhui Zhao + * + * 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 +#include + +#define FSL_STRIDE_4B 4 +#define FSL_STRIDE_8B 8 + +/* Event Processor Global Control Register */ +#defineEPGCR 0x000 + +/* Event Processor EVT Pin Control Registers */ +#defineEPEVTCR00x050 +#defineEPEVTCR10x054 +#defineEPEVTCR20x058 +#defineEPEVTCR30x05C +#defineEPEVTCR40x060 +#defineEPEVTCR50x064 +#defineEPEVTCR60x068 +#defineEPEVTCR70x06C +#defineEPEVTCR80x070 +#defineEPEVTCR90x074 + +/* Event Processor Crosstrigger Control Register */ +#defineEPXTRIGCR 0x090 + +/* Event Processor Input Mux Control Registers */ +#defineEPIMCR0 0x100 +#defineEPIMCR1 0x104 +#defin
[PATCH 5/9] powerpc/85xx: disable irq by hardware when suspend for 64-bit
In 64-bit mode, kernel just clears the irq soft-enable flag in struct paca_struct to disable external irqs. But, in the case of suspend, irqs should be disabled by hardware. Therefore, hook a function to ppc_md.suspend_disable_irqs to really disable irqs. Signed-off-by: Chenhui Zhao --- arch/powerpc/platforms/85xx/corenet_generic.c | 12 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index 3fdf9f3..983d81f 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c @@ -32,6 +32,13 @@ #include #include "smp.h" +#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND) +static void fsl_suspend_disable_irqs(void) +{ + __hard_irq_disable(); +} +#endif + void __init corenet_gen_pic_init(void) { struct mpic *mpic; @@ -58,6 +65,11 @@ void __init corenet_gen_setup_arch(void) fsl_rcpm_init(); +#if defined(CONFIG_PPC64) && defined(CONFIG_SUSPEND) + /* physically disable irq for 64-bit mode when suspend */ + ppc_md.suspend_disable_irqs = fsl_suspend_disable_irqs; +#endif + pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); } -- 1.7.3 -- 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/
[PATCH 2/9] powerpc/cache: add cache flush operation for various e500
Various e500 core have different cache architecture, so they need different cache flush operations. Therefore, add a callback function cpu_flush_caches to the struct cpu_spec. The cache flush operation for the specific kind of e500 is selected at init time. The callback function will flush all caches in the current cpu. Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/cacheflush.h |2 - arch/powerpc/include/asm/cputable.h | 11 +++ arch/powerpc/kernel/asm-offsets.c |3 + arch/powerpc/kernel/cpu_setup_fsl_booke.S | 114 - arch/powerpc/kernel/cputable.c|4 + arch/powerpc/kernel/head_fsl_booke.S | 74 --- arch/powerpc/platforms/85xx/smp.c |4 +- 7 files changed, 134 insertions(+), 78 deletions(-) diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index 5b93122..039753e 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping)do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -extern void __flush_disable_L1(void); - extern void flush_icache_range(unsigned long, unsigned long); extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 617cc76..2c497a2 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -43,6 +43,13 @@ extern int machine_check_e500(struct pt_regs *regs); extern int machine_check_e200(struct pt_regs *regs); extern int machine_check_47x(struct pt_regs *regs); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) +extern void __flush_caches_e500v2(void); +extern void __flush_caches_e500mc(void); +extern void __flush_caches_e5500(void); +extern void __flush_caches_e6500(void); +#endif + /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ struct cpu_spec { /* CPU is matched via (PVR & pvr_mask) == pvr_value */ @@ -59,6 +66,10 @@ struct cpu_spec { unsigned inticache_bsize; unsigned intdcache_bsize; +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + /* flush caches of the cpu which is running the function */ + void (*cpu_flush_caches)(void); +#endif /* number of performance monitor counters */ unsigned intnum_pmcs; enum powerpc_pmc_type pmc_type; diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8d1d94d..5157fb4 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -372,6 +372,9 @@ int main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); +#if defined(CONFIG_E500) || defined(CONFIG_PPC_E500MC) + DEFINE(CPU_FLUSH_CACHES, offsetof(struct cpu_spec, cpu_flush_caches)); +#endif DEFINE(pbe_address, offsetof(struct pbe, address)); DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address)); diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index cc2d896..e59d6de 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -1,7 +1,7 @@ /* * This file contains low level CPU setup functions. * Kumar Gala - * Copyright 2009 Freescale Semiconductor, Inc. + * Copyright 2009, 2014 Freescale Semiconductor, Inc. * * Based on cpu_setup_6xx code by * Benjamin Herrenschmidt @@ -13,11 +13,13 @@ * */ +#include #include #include #include #include #include +#include _GLOBAL(__e500_icache_setup) mfspr r0, SPRN_L1CSR1 @@ -223,3 +225,113 @@ _GLOBAL(__setup_cpu_e5500) mtlrr5 blr #endif + +/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */ +_GLOBAL(flush_dcache_L1) + mfmsr r10 + wrteei 0 + + mfspr r3,SPRN_L1CFG0 + rlwinm r5,r3,9,3 /* Extract cache block size */ + twlgti r5,1/* Only 32 and 64 byte cache blocks +* are currently defined. +*/ + li r4,32 + subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) - +* log2(number of ways) +*/ + slw r5,r4,r5/* r5 = cache block size */ + + rlwinm r7,r3,0,0xff/* Extract number of KiB in the cache */ + mulli r7,r7,13/* An 8-way cache will require 13 +* loads per
[PATCH 4/9] powerpc/85xx: support CPU hotplug for e500mc and e5500
Implemented CPU hotplug on e500mc and e5500. On e5500 both 32-bit and 64-bit modes can work. Used some callback functions implemented in RCPM driver. Signed-off-by: Chenhui Zhao --- arch/powerpc/Kconfig |2 +- arch/powerpc/kernel/smp.c |6 ++- arch/powerpc/mm/tlb_nohash.c |6 ++- arch/powerpc/platforms/85xx/smp.c | 94 ++--- 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a5e5d2e..05f6323 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -362,7 +362,7 @@ config SWIOTLB config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ - PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC)) + PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE) ---help--- Say Y here to be able to disable and re-enable individual CPUs at runtime on SMP machines. diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index ac2621a..f3f4401 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -405,8 +405,12 @@ void generic_cpu_die(unsigned int cpu) for (i = 0; i < 100; i++) { smp_rmb(); - if (per_cpu(cpu_state, cpu) == CPU_DEAD) + if (per_cpu(cpu_state, cpu) == CPU_DEAD) { +#ifdef CONFIG_PPC64 + paca[cpu].cpu_start = 0; +#endif return; + } msleep(100); } printk(KERN_ERR "CPU%d didn't die...\n", cpu); diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index b37a58e..d24e06c 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -648,8 +648,10 @@ static void __early_init_mmu(int boot_cpu) num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; linear_map_top = map_mem_in_cams(linear_map_top, num_cams); - /* limit memory so we dont have linear faults */ - memblock_enforce_memory_limit(linear_map_top); + if (boot_cpu) { + /* limit memory so we dont have linear faults */ + memblock_enforce_memory_limit(linear_map_top); + } if (book3e_htw_mode == PPC_HTW_NONE) { patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 2e5911e..0047883 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,17 @@ static u64 timebase; static int tb_req; static int tb_valid; +#ifdef CONFIG_PPC_E500MC +/* specify the cpu PM state when cpu dies, PH15/NAP is the default */ +int qoriq_cpu_die_state = E500_PM_PH15; +#endif + +#ifdef CONFIG_PPC_E500MC +static void mpc85xx_timebase_freeze(int freeze) +{ + qoriq_pm_ops->freeze_time_base(freeze); +} +#else static void mpc85xx_timebase_freeze(int freeze) { uint32_t mask; @@ -58,6 +70,7 @@ static void mpc85xx_timebase_freeze(int freeze) in_be32(&guts->devdisr); } +#endif static void mpc85xx_give_timebase(void) { @@ -125,6 +138,34 @@ static void mpc85xx_take_timebase(void) } #ifdef CONFIG_HOTPLUG_CPU +#ifdef CONFIG_PPC_E500MC +static void qoriq_cpu_die(void) +{ + unsigned int cpu = smp_processor_id(); + + local_irq_disable(); +#ifdef CONFIG_PPC64 + __hard_irq_disable(); +#endif + idle_task_exit(); + + if (qoriq_pm_ops->irq_mask) + qoriq_pm_ops->irq_mask(cpu); + + mtspr(SPRN_TCR, 0); + mtspr(SPRN_TSR, mfspr(SPRN_TSR)); + + generic_set_cpu_dead(cpu); + + if (cur_cpu_spec && cur_cpu_spec->cpu_flush_caches) + cur_cpu_spec->cpu_flush_caches(); + + qoriq_pm_ops->cpu_enter_state(cpu, qoriq_cpu_die_state); + + while (1) + ; +} +#else static void smp_85xx_mach_cpu_die(void) { unsigned int cpu = smp_processor_id(); @@ -155,6 +196,7 @@ static void smp_85xx_mach_cpu_die(void) ; } #endif +#endif static inline void flush_spin_table(void *spin_table) { @@ -208,11 +250,8 @@ static int smp_85xx_kick_cpu(int nr) spin_table = phys_to_virt(*cpu_rel_addr); local_irq_save(flags); -#ifdef CONFIG_PPC32 -#ifdef CONFIG_HOTPLUG_CPU - /* Corresponding to generic_set_cpu_dead() */ - generic_set_cpu_up(nr); +#ifdef CONFIG_HOTPLUG_CPU if (system_state == SYSTEM_RUNNING) { /* * To keep it compatible with old boot program which uses @@ -225,6 +264,12 @@ static int smp_85xx_kick_cpu(int nr) out_be32(&spin_table->addr_l, 0); flush_
[PATCH 8/9] powerpc/85xx: add save/restore functions for core registers
From: Wang Dongsheng Add booke_cpu_state_save() and booke_cpu_state_restore() functions which can be used to save/restore CPU's registers in the case of deep sleep and hibernation. Supported processors: E6500, E5500, E500MC, E500v2 and E500v1. Signed-off-by: Wang Dongsheng Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/booke_save_regs.h | 96 arch/powerpc/kernel/Makefile |1 + arch/powerpc/kernel/booke_save_regs.S | 361 3 files changed, 458 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/include/asm/booke_save_regs.h create mode 100644 arch/powerpc/kernel/booke_save_regs.S diff --git a/arch/powerpc/include/asm/booke_save_regs.h b/arch/powerpc/include/asm/booke_save_regs.h new file mode 100644 index 000..87c357a --- /dev/null +++ b/arch/powerpc/include/asm/booke_save_regs.h @@ -0,0 +1,96 @@ +/* + * Save/restore e500 series core registers + * + * Author: Wang Dongsheng + * + * Copyright 2014 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 version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_FSL_SLEEP_H +#define __ASM_FSL_SLEEP_H + +/* + * 8 bytes for each register, which is compatible with + * both 32-bit and 64-bit registers + * + * Acronyms: + * dw(data width) 0x08 + * + * Map: + * General-Purpose Registers + * GPR1(sp)0 + * GPR20x8 (dw * 1) + * GPR13 - GPR31 0x10 ~ 0xa0 (dw * 2 ~ dw * 20) + * Foating-point registers + * FPR14 - FPR31 0xa8 ~ 0x130(dw * 21 ~ dw * 38) + * Registers for Branch Operations + * CR 0x138 (dw * 39) + * LR 0x140 (dw * 40) + * Processor Control Registers + * MSR 0x148 (dw * 41) + * EPCR0x150 (dw * 42) + * + * Only e500, e500v2 need to save HID0 - HID1 + * HID0 - HID1 0x158 ~ 0x160 (dw * 43 ~ dw * 44) + * Timer Registers + * TCR 0x168 (dw * 45) + * TB(64bit) 0x170 (dw * 46) + * TBU(32bit) 0x178 (dw * 47) + * TBL(32bit) 0x180 (dw * 48) + * Interrupt Registers + * IVPR0x188 (dw * 49) + * IVOR0 - IVOR15 0x190 ~ 0x208 (dw * 50 ~ dw * 65) + * IVOR32 - IVOR41 0x210 ~ 0x258 (dw * 66 ~ dw * 75) + * Software-Use Registers + * SPRG1 0x260 (dw * 76), 64-bit need to save. + * SPRG3 0x268 (dw * 77), 32-bit need to save. + * MMU Registers + * PID0 - PID2 0x270 ~ 0x280 (dw * 78 ~ dw * 80) + * Debug Registers + * DBCR0 - DBCR2 0x288 ~ 0x298 (dw * 81 ~ dw * 83) + * IAC1 - IAC4 0x2a0 ~ 0x2b8 (dw * 84 ~ dw * 87) + * DAC1 - DAC2 0x2c0 ~ 0x2c8 (dw * 88 ~ dw * 89) + * + */ + +#define SR_GPR10x000 +#define SR_GPR20x008 +#define SR_GPR13 0x010 +#define SR_FPR14 0x0a8 +#define SR_CR 0x138 +#define SR_LR 0x140 +#define SR_MSR 0x148 +#define SR_EPCR0x150 +#define SR_HID00x158 +#define SR_TCR 0x168 +#define SR_TB 0x170 +#define SR_TBU 0x178 +#define SR_TBL 0x180 +#define SR_IVPR0x188 +#define SR_IVOR0 0x190 +#define SR_IVOR32 0x210 +#define SR_SPRG1 0x260 +#define SR_SPRG3 0x268 +#define SR_PID00x270 +#define SR_DBCR0 0x288 +#define SR_IAC10x2a0 +#define SR_DAC10x2c0 +#define REGS_BUFFER_SIZE (SR_DAC1 + 0x10) + +/* + * hibernation and deepsleep save/restore different number of registers, + * use these flags to indicate. + */ +#define HIBERNATION_FLAG 1 +#define DEEPSLEEP_FLAG 2 + +#ifndef __ASSEMBLY__ +extern void booke_cpu_state_save(void *buf, int type); +extern void *booke_cpu_state_restore(void *buf, int type); +#endif +#endif + diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index fcc9a89..64acae6 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp_booke.o else obj-$(CONFIG_HIBERNATION) += swsusp_$(CONFIG_WORD_SIZE).o endif +obj-$(CONFIG_E500) += booke_save_regs.o obj64-$(CONFIG_HIBERNATION)+= swsusp_asm64.o obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o obj-$(CONFIG_44x) += cpu_setup_44x.o diff --git a/arch/po
[PATCH 1/9] powerpc/fsl: add PVR definition for E500MC and E5500
From: Wang Dongsheng Signed-off-by: Wang Dongsheng --- arch/powerpc/include/asm/reg.h |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 62b114e..cd7b630 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1075,6 +1075,8 @@ #define PVR_8560 0x8020 #define PVR_VER_E500V1 0x8020 #define PVR_VER_E500V2 0x8021 +#define PVR_VER_E500MC 0x8023 +#define PVR_VER_E5500 0x8024 #define PVR_VER_E6500 0x8040 /* -- 1.7.3 -- 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/
[PATCH 3/9] powerpc/rcpm: add RCPM driver
There is a RCPM (Run Control/Power Management) in Freescale QorIQ series processors. The device performs tasks associated with device run control and power management. The driver implements some features: mask/unmask irq, enter/exit low power states, freeze time base, etc. There are two versions of register map in RCPM, which is specified by the compatible entry in the RCPM node of device tree. Signed-off-by: Chenhui Zhao --- arch/powerpc/include/asm/fsl_guts.h | 105 arch/powerpc/platforms/85xx/Kconfig |1 + arch/powerpc/platforms/85xx/corenet_generic.c |2 + arch/powerpc/sysdev/Kconfig |5 + arch/powerpc/sysdev/Makefile |1 + arch/powerpc/sysdev/fsl_rcpm.c| 315 + arch/powerpc/sysdev/fsl_soc.h | 24 ++ 7 files changed, 453 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/sysdev/fsl_rcpm.c diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h index 77ced0b..492534a 100644 --- a/arch/powerpc/include/asm/fsl_guts.h +++ b/arch/powerpc/include/asm/fsl_guts.h @@ -185,5 +185,110 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, #endif +struct ccsr_rcpm_v1 { + u8 res[4]; + __be32 cdozsr; /* 0x0004 Core Doze Status Register */ + u8 res0008[4]; + __be32 cdozcr; /* 0x000c Core Doze Control Register */ + u8 res0010[4]; + __be32 cnapsr; /* 0x0014 Core Nap Status Register */ + u8 res0018[4]; + __be32 cnapcr; /* 0x001c Core Nap Control Register */ + u8 res0020[4]; + __be32 cdozpsr;/* 0x0024 Core Doze Previous Status Register */ + u8 res0028[4]; + __be32 cnappsr;/* 0x002c Core Nap Previous Status Register */ + u8 res0030[4]; + __be32 cwaitsr;/* 0x0034 Core Wait Status Register */ + u8 res0038[4]; + __be32 cwdtdsr;/* 0x003c Core Watchdog Detect Status Register */ + __be32 powmgtcsr; /* 0x0040 Power Mangement Control&Status Register */ +#define RCPM_POWMGTCSR_SLP 0x0002 + u8 res0044[12]; + __be32 ippdexpcr; /* 0x0050 IP Powerdown Exception Control Register */ + u8 res0054[16]; + __be32 cpmimr; /* 0x0064 Core PM IRQ Mask Register */ + u8 res0068[4]; + __be32 cpmcimr;/* 0x006c Core PM Critical IRQ Mask Register */ + u8 res0070[4]; + __be32 cpmmcmr;/* 0x0074 Core PM Machine Check Mask Register */ + u8 res0078[4]; + __be32 cpmnmimr; /* 0x007c Core PM NMI Mask Register */ + u8 res0080[4]; + __be32 ctbenr; /* 0x0084 Core Time Base Enable Register */ + u8 res0088[4]; + __be32 ctbckselr; /* 0x008c Core Time Base Clock Select Register */ + u8 res0090[4]; + __be32 ctbhltcr; /* 0x0094 Core Time Base Halt Control Register */ + u8 res0098[4]; + __be32 cmcpmaskcr; /* 0x00a4 Core Machine Check Mask Register */ +}; + +struct ccsr_rcpm_v2 { + u8 res_00[12]; + u32 tph10sr0; /* Thread PH10 Status Register */ + u8 res_10[12]; + u32 tph10setr0; /* Thread PH10 Set Control Register */ + u8 res_20[12]; + u32 tph10clrr0; /* Thread PH10 Clear Control Register */ + u8 res_30[12]; + u32 tph10psr0; /* Thread PH10 Previous Status Register */ + u8 res_40[12]; + u32 twaitsr0; /* Thread Wait Status Register */ + u8 res_50[96]; + u32 pcph15sr; /* Physical Core PH15 Status Register */ + u32 pcph15setr; /* Physical Core PH15 Set Control Register */ + u32 pcph15clrr; /* Physical Core PH15 Clear Control Register */ + u32 pcph15psr; /* Physical Core PH15 Prev Status Register */ + u8 res_c0[16]; + u32 pcph20sr; /* Physical Core PH20 Status Register */ + u32 pcph20setr; /* Physical Core PH20 Set Control Register */ + u32 pcph20clrr; /* Physical Core PH20 Clear Control Register */ + u32 pcph20psr; /* Physical Core PH20 Prev Status Register */ + u32 pcpw20sr; /* Physical Core PW20 Status Register */ + u8 res_e0[12]; + u32 pcph30sr; /* Physical Core PH30 Status Register */ + u32 pcph30setr; /* Physical Core PH30 Set Control Register */ + u32 pcph30clrr; /* Physical Core PH30 Clear Control Register */ + u32 pcph30psr; /* Physical Core PH30 Prev Status Register */ + u8 res_100[32]; + u32 ippwrgatecr;/* IP Power Gating Control Register */ + u8 res_124[12]; + u32 powmgtcsr; /* Power Management Control & Status Reg */ +#define RCPM_POWMGTCSR_LPM20_RQ0x