[PATCH] cpuidle: remove cpu_pm calls when entering a idle state

2016-10-21 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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



[PATCH] cpuidle: remove cpu_pm calls when entering a idle state

2016-10-21 Thread Chenhui Zhao
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

2016-08-02 Thread Chenhui Zhao
On Mon, Aug 1, 2016 at 8:25 PM, Arnd Bergmann <a...@arndb.de> 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 <chenhui.z...@nxp.com>
>
> 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

2016-08-02 Thread Chenhui Zhao
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

2016-08-02 Thread Chenhui Zhao
On Mon, Aug 1, 2016 at 9:22 PM, Marc Zyngier <marc.zyng...@arm.com> 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 <chenhui.z...@nxp.com>
> > ---
> >  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


Re: [PATCH 2/2] soc: nxp: Add a RCPM driver

2016-08-02 Thread Chenhui Zhao
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

2016-08-02 Thread Chenhui Zhao
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 0/5] powerpc/pm: QorIQ deep sleep

2016-08-02 Thread Chenhui Zhao
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

2016-08-02 Thread Chenhui Zhao
Signed-off-by: Chenhui Zhao <chenhui.z...@nxp.com>
---
 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 = < 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 
 
 _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 = < 29 GPIO_ACTIVE_HIGH>;
};
 
sfp: sfp@e8000 {
-- 
1.9.1



[PATCH v3 1/5] powerpc/dts: add mcke-gpios for PM feature

2016-08-02 Thread Chenhui Zhao
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 = < 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 
 
 _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 = < 29 GPIO_ACTIVE_HIGH>;
};
 
sfp: sfp@e8000 {
-- 
1.9.1



[PATCH v3 3/5] powerpc: pm: add EPU FSM configuration for deep sleep

2016-08-02 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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 <hongbo.zh...@nxp.com>
+ * Chenhui Zhao <chenhui.z...@nxp.com>
+ *
+ * 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_ST

[PATCH v3 3/5] powerpc: pm: add EPU FSM configuration for deep sleep

2016-08-02 Thread Chenhui Zhao
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},
+   {EPCCR0 

[PATCH v3 2/5] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM

2016-08-02 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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 <chenhui.z...@nxp.com>
+ *
+ * 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(_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 @@ men

[PATCH v3 2/5] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM

2016-08-02 Thread Chenhui Zhao
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(_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

[PATCH v3 5/5] powerpc/pm: save and restore registers during deep sleep

2016-08-02 Thread Chenhui Zhao
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 <yuantian.t...@nxp.com>
Signed-off-by: Chenhui Zhao <chenhui.z...@nxp.com>
---
 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(>lawbarh);
+   dst->lawbarl = in_be32(>lawbarl);
+   dst->lawar = in_be32(>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(>lawar);
+   if (((attr >> 20) & 0xff) == MC1_TRGT_ID)
+   continue;
+   out_be32(>lawar, 0);
+   out_be32(>lawbarl, src->lawbarl);
+   out_be32(>lawbarh, src->lawbarh);
+   out_be32(>lawar, src->lawar);
+   src++;
+   dst++;
+   }
+}
+
 static void fsl

[PATCH v3 5/5] powerpc/pm: save and restore registers during deep sleep

2016-08-02 Thread Chenhui Zhao
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(>lawbarh);
+   dst->lawbarl = in_be32(>lawbarl);
+   dst->lawar = in_be32(>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(>lawar);
+   if (((attr >> 20) & 0xff) == MC1_TRGT_ID)
+   continue;
+   out_be32(>lawar, 0);
+   out_be32(>lawbarl, src->lawbarl);
+   out_be32(>lawbarh, src->lawbarh);
+   out_be32(>lawar, src->lawar);
+   src++;
+   dst++;
+   }
+}
+
 static void fsl_dp_set_resume_pointer(void)
 {
u32 resume_addr;
@@ -132,

[PATCH v3 4/5] powerpc/pm: support deep sleep feature on T104x

2016-08-02 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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 sub

[PATCH v3 1/5] powerpc/dts: add mcke-gpios for PM feature

2016-08-02 Thread Chenhui Zhao
Signed-off-by: Chenhui Zhao <chenhui.z...@nxp.com>
---
 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 = < 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 
 
 _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 = < 29 GPIO_ACTIVE_HIGH>;
};
 
sfp: sfp@e8000 {
-- 
1.9.1



[PATCH v3 1/5] powerpc/dts: add mcke-gpios for PM feature

2016-08-02 Thread Chenhui Zhao
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 = < 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 
 
 _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 = < 29 GPIO_ACTIVE_HIGH>;
};
 
sfp: sfp@e8000 {
-- 
1.9.1



[PATCH v3 4/5] powerpc/pm: support deep sleep feature on T104x

2016-08-02 Thread Chenhui Zhao
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

2016-08-01 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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 -E

[PATCH 2/2] soc: nxp: Add a RCPM driver

2016-08-01 Thread Chenhui Zhao
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-wakeup-cel

[PATCH 1/2] ARM: dts: ls1043a: add a rcpm node

2016-08-01 Thread Chenhui Zhao
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 <chenhui.z...@nxp.com>
---
 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 1/2] ARM: dts: ls1043a: add a rcpm node

2016-08-01 Thread Chenhui Zhao
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

2016-04-15 Thread Chenhui Zhao
For T1040, T1042, T1023, and T1024, they should use the compatible
string "fsl,qoriq-rcpm-2.1".

Signed-off-by: Chenhui Zhao <chenhui.z...@nxp.com>
---
 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] powerpc/dts: fix rcpm compatible string

2016-04-15 Thread Chenhui Zhao
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

2015-12-23 Thread Chenhui Zhao
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/


[PATCH v4 1/6] powerpc/mm: any thread in one core can be the first to setup TLB1

2015-12-23 Thread Chenhui Zhao
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 <chenhui.z...@freescale.com>
---
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

2015-08-27 Thread Chenhui Zhao



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_sibling(nr);

   

Re: [PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-27 Thread Chenhui Zhao



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/


Re: [PATCH v2,5/5] PowerPC/mpc85xx: Add CPU hotplug support for E6500

2015-08-27 Thread Chenhui Zhao



On Thu, Aug 27, 2015 at 6:42 AM, Scott Wood scottw...@freescale.com 
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_sibling(nr);

if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT

Re: [PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-27 Thread Chenhui Zhao



On Thu, Aug 27, 2015 at 4:55 AM, Scott Wood scottw...@freescale.com 
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

2015-08-26 Thread Chenhui Zhao
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(>devdisr, mask);
+   else
+   clrbits32(>devdisr, mask);
+
+   in_be32(>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 = _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 struct ccsr_guts __iomem *

[PATCH v2,2/5] powerpc/rcpm: add RCPM driver

2015-08-26 Thread Chenhui Zhao
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 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 

[PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-26 Thread Chenhui Zhao
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
-   /* T

[PATCH v2,5/5] PowerPC/mpc85xx: Add CPU hotplug support for E6500

2015-08-26 Thread Chenhui Zhao
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

2015-08-26 Thread Chenhui Zhao
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

[PATCH v2,3/5] Powerpc: mpc85xx: refactor the PM operations

2015-08-26 Thread Chenhui Zhao
Freescale CoreNet-based and Non-CoreNet-based platforms require
different PM operations. This patch extracted existing PM operations
on Non-CoreNet-based platforms to a new file which can accommodate
both platforms.
In this way, PM operation codes are clearer structurally.

Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
Signed-off-by: Tang Yuantian yuantian.t...@feescale.com
---
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 linux/kernel.h
+#include linux/of.h
+#include linux/of_address.h
+
+#include asm/io.h
+#include asm/fsl_guts.h
+#include asm/fsl_pm.h
+
+static struct ccsr_guts __iomem *guts;
+
+static 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 aflem...@freescale.com
  *Kumar Gala ga...@kernel.crashing.org
  *
- * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012, 2015 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -15,7 +15,6 @@
 #include linux/init.h
 #include linux/delay.h
 #include linux/of.h
-#include linux/of_address.h
 #include linux/kexec.h
 #include linux/highmem.h
 #include linux/cpu.h
@@ -26,9 +25,9 @@
 #include asm/mpic.h
 #include asm/cacheflush.h
 #include asm/dbell.h
-#include asm/fsl_guts.h
 #include asm

[PATCH v2,4/5] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
Signed-off-by: Tang Yuantian yuantian.t...@feescale.com
---
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 linux/stddef.h
 #include linux/kernel.h
 #include linux/init.h
@@ -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
-   /* Threads don't

[PATCH v2,5/5] PowerPC/mpc85xx: Add CPU hotplug support for E6500

2015-08-26 Thread Chenhui Zhao
Support Freescale E6500 core-based platforms, like t4240.
Support disabling/enabling individual CPU thread dynamically.

Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
---
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 linux/cpumask.h
 
 /*
@@ -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 asm/kvm_book3s_asm.h
 #include asm/ptrace.h
 #include asm/hw_irq.h
+#include asm/cputhreads.h
 
 /* 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

[PATCH v2,1/5] powerpc/cache: add cache flush operation for various e500

2015-08-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
Signed-off-by: Tang Yuantian yuantian.t...@feescale.com
---
 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 asm/page.h
 #include asm/processor.h
 #include asm/cputable.h
 #include asm/ppc_asm.h
 #include asm/mmu-book3e.h
 #include asm/asm-offsets.h
+#include asm/mpc85xx.h
 
 _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

[PATCH v2,2/5] powerpc/rcpm: add RCPM driver

2015-08-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
Signed-off-by: Tang Yuantian yuantian.t...@freescale.com
---
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,chip-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 ControlStatus 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

Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-06 Thread Chenhui Zhao



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

2015-08-06 Thread Chenhui Zhao



On Fri, Aug 7, 2015 at 2:02 AM, Scott Wood scottw...@freescale.com 
wrote:

On Thu, 2015-08-06 at 13:54 +0800, Chenhui Zhao wrote:

 On Thu, Aug 6, 2015 at 1:46 PM, Scott Wood scottw...@freescale.com
 wrote:
  On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote:
On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood
   scottw...@freescale.com
wrote:
 On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote:
   On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood
   scottw...@freescale.com
   wrote:
On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote:
  
   
  On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood
  scottw...@freescale.com
  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

2015-08-05 Thread Chenhui Zhao



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

2015-08-05 Thread Chenhui Zhao



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

2015-08-05 Thread Chenhui Zhao



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

2015-08-05 Thread Chenhui Zhao



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

2015-08-05 Thread Chenhui Zhao



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(_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

2015-08-05 Thread Chenhui Zhao



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 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-05 Thread Chenhui Zhao



On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood scottw...@freescale.com 
wrote:

On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote:

 



 On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood scottw...@freescale.com
 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 2/3] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-05 Thread Chenhui Zhao



On Tue, Aug 4, 2015 at 5:18 AM, Scott Wood scottw...@freescale.com 
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 scottw...@freescale.com
 wrote:
  On Fri, 2015-07-31 at 17:20 +0800,  b29983@freescale.comwrote:
From: Tang Yuantian yuantian.t...@freescale.com
  
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 chenhui.z...@freescale.com
Signed-off-by: Tang Yuantian yuantian.t...@feescale.com




 +{
+ 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 3/3] PowerPC/mpc85xx: Add hotplug support on E6500 cores

2015-08-05 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood scottw...@freescale.com 
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 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-05 Thread Chenhui Zhao



On Thu, Aug 6, 2015 at 1:46 PM, Scott Wood scottw...@freescale.com 
wrote:

On Thu, 2015-08-06 at 12:20 +0800, Chenhui Zhao wrote:
 On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood 
scottw...@freescale.com

 wrote:
  On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote:
On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood 
scottw...@freescale.com

wrote:
 On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote:
   

   On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood
   scottw...@freescale.com
   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 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-05 Thread Chenhui Zhao



On Thu, Aug 6, 2015 at 10:57 AM, Scott Wood scottw...@freescale.com 
wrote:

On Wed, 2015-08-05 at 18:11 +0800, Chenhui Zhao wrote:

 On Tue, Aug 4, 2015 at 4:26 AM, Scott Wood scottw...@freescale.com
 wrote:
  On Mon, 2015-08-03 at 19:32 +0800, Chenhui Zhao wrote:

 
On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood 
scottw...@freescale.com

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

2015-08-05 Thread Chenhui Zhao



On Thu, Aug 6, 2015 at 11:16 AM, Scott Wood scottw...@freescale.com 
wrote:

On Wed, 2015-08-05 at 19:08 +0800, Chenhui Zhao wrote:

 On Sat, Aug 1, 2015 at 8:22 AM, Scott Wood scottw...@freescale.com
 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 v5] powerpc/rcpm: add RCPM driver

2015-08-03 Thread Chenhui Zhao



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(_v1_regs->ippdexpcr, *mask);
 > >  + else
 > >  + clrbits32(_v1_regs->ippdexpcr, *mask);
 > >  +}
 > >  +
 > >  +static void rcpm_v2_set_ip_power(bool enable, u32 *mask)
 > >  +{
 > >  + if (enable)
 > >  + setbits32(_v2_regs->ippdexpcr[0], *mask);
 > >  + else
 > >  + clrbits32(_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

2015-08-03 Thread Chenhui Zhao



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

2015-08-03 Thread Chenhui Zhao



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(_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

Re: [PATCH 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-03 Thread Chenhui Zhao



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

2015-08-03 Thread Chenhui Zhao



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(_v1_regs->ippdexpcr, *mask);
 + else
 + clrbits32(_v1_regs->ippdexpcr, *mask);
 +}
 +
 +static void rcpm_v2_set_ip_power(bool enable, u32 *mask)
 +{
 + if (enable)
 + setbits32(_v2_regs->ippdexpcr[0], *mask);
 + else
 + clrbits32(_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

2015-08-03 Thread Chenhui Zhao



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/


Re: [PATCH v5] powerpc/rcpm: add RCPM driver

2015-08-03 Thread Chenhui Zhao



On Tue, Aug 4, 2015 at 4:23 AM, Scott Wood scottw...@freescale.com 
wrote:

On Mon, 2015-08-03 at 19:14 +0800, Chenhui Zhao wrote:

 On Sat, Aug 1, 2015 at 8:45 AM, Scott Wood scottw...@freescale.com
 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] powerpc/85xx: add sleep and deep sleep support

2015-08-03 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 10:57 AM, Scott Wood scottw...@freescale.com 
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/


Re: [PATCH v5] powerpc/rcpm: add RCPM driver

2015-08-03 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 8:45 AM, Scott Wood scottw...@freescale.com 
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 1/3] Powerpc: mpc85xx: refactor the PM operations

2015-08-03 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 7:59 AM, Scott Wood scottw...@freescale.com 
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 2/3] PowerPC/mpc85xx: Add hotplug support on E5500 and E500MC cores

2015-08-03 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 8:14 AM, Scott Wood scottw...@freescale.com 
wrote:

On Fri, 2015-07-31 at 17:20 +0800, b29...@freescale.com wrote:

 From: Tang Yuantian yuantian.t...@freescale.com

 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 chenhui.z...@freescale.com
 Signed-off-by: Tang Yuantian yuantian.t...@feescale.com
 ---
  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

Re: [PATCH 3/4] powerpc: pm: add EPU FSM configuration for deep sleep

2015-08-03 Thread Chenhui Zhao



On Sat, Aug 1, 2015 at 8:41 AM, Scott Wood scottw...@freescale.com 
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 chenhui.z...@freescale.com
 ---
  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/


[PATCH 2/4] powerpc: get the physical base address of DCSR

2015-07-31 Thread Chenhui Zhao
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", );
+   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

2015-07-31 Thread Chenhui Zhao
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

2015-07-31 Thread Chenhui Zhao
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 
+#include

[PATCH 1/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM

2015-07-31 Thread Chenhui Zhao
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(_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 1/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM

2015-07-31 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
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 chenhui.z...@freescale.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include linux/kernel.h
+#include linux/suspend.h
+#include linux/of_platform.h
+
+#include asm/fsl_pm.h
+
+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 4/4] powerpc: pm: support deep sleep feature on T104x

2015-07-31 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 chenhui.z...@freescale.com
+ *
+ * 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

[PATCH 3/4] powerpc: pm: add EPU FSM configuration for deep sleep

2015-07-31 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 hongbo.zh...@freescale.com
+ * Chenhui Zhao chenhui.z...@freescale.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include linux/kernel.h
+#include linux/io.h
+#include linux/types.h
+
+#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

[PATCH 2/4] powerpc: get the physical base address of DCSR

2015-07-31 Thread Chenhui Zhao
Add get_dcsrbase() to get the physical base address of DCSR.

Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
---
 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] powerpc/85xx: add sleep and deep sleep support

2015-07-24 Thread Chenhui Zhao
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 sleep r

[PATCH] powerpc/85xx: add sleep and deep sleep support

2015-07-24 Thread Chenhui Zhao
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 le...@freescale.com
Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
---
 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 scottw...@freescale.com
+ *
+ * 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 asm/page.h
+#include asm/ppc_asm.h
+#include asm/reg.h
+#include asm/asm-offsets.h
+
+#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

[PATCH] powerpc/corenet: use the mixed mode of MPIC when enabling CPU hotplug

2015-07-22 Thread Chenhui Zhao
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] powerpc/corenet: use the mixed mode of MPIC when enabling CPU hotplug

2015-07-22 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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

2015-03-26 Thread Chenhui Zhao
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 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 Control Re

[PATCH 3/4] powerpc: support CPU hotplug for e500mc, e5500 and e6500

2015-03-26 Thread Chenhui Zhao
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

2015-03-26 Thread Chenhui Zhao
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

2015-03-26 Thread Chenhui Zhao
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(_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 3/4] powerpc: support CPU hotplug for e500mc, e5500 and e6500

2015-03-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 aflem...@freescale.com
  *Kumar Gala ga...@kernel.crashing.org
  *
- * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
+ * Copyright 2006-2008

[PATCH 2/4] powerpc/rcpm: add RCPM driver

2015-03-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 ControlStatus 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 Control Register */
+   __be32  pcph15psr;  /* Physical

[PATCH 4/4] powerpc/85xx: support sleep feature on QorIQ SoCs with RCPM

2015-03-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 chenhui.z...@freescale.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include linux/kernel.h
+#include linux/suspend.h
+#include linux/of_platform.h
+
+#include asm/fsl_pm.h
+
+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 1/4] powerpc/cache: add cache flush operation for various e500

2015-03-26 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 ga...@kernel.crashing.org
- * Copyright 2009 Freescale Semiconductor, Inc.
+ * Copyright 2009, 2015 Freescale Semiconductor, Inc.
  *
  * Based on cpu_setup_6xx code by
  * Benjamin Herrenschmidt b...@kernel.crashing.org
@@ -13,11 +13,13 @@
  *
  */
 
+#include asm/page.h
 #include asm/processor.h
 #include asm/cputable.h
 #include asm/ppc_asm.h
 #include asm/mmu-book3e.h
 #include asm/asm-offsets.h
+#include asm/mpc85xx.h
 
 _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

[PATCH 4/4] arm: ls1021a: set wakeup devices dynamically for sleep/deep sleep

2015-01-30 Thread Chenhui Zhao
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 = < 0x0080 0x0>;
status = "disabled";
};
 
@@ -289,6 +290,7 @@
interrupts = ;
clocks = <>;
clock-names = "ipg";
+   sleep = < 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_board_resume();
 }
 
+static vo

[PATCH 1/4] fsl: add EPU FSM configuration for deep sleep

2015-01-30 Thread Chenhui Zhao
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, 0},
+

[PATCH 3/4] arm: ls1021a: add deep sleep support

2015-01-30 Thread Chenhui Zhao
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

2015-01-30 Thread Chenhui Zhao
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 @@
  {
status = "okay";
 };
+
+ {
+   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 = "fsl,ls1021a

[PATCH 4/4] arm: ls1021a: set wakeup devices dynamically for sleep/deep sleep

2015-01-30 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 = GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH;
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_board_resume();
 }
 
+static void ls1_set_power_except

[PATCH 2/4] arm: ls1021a: add dts nodes required by deep sleep

2015-01-30 Thread Chenhui Zhao
Add RCPM and DCSR nodes.

Signed-off-by: Chenhui Zhao chenhui.z...@freescale.com
---
 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 = fsl,ls1021a-dcsr-etr;
+   reg = 0x3a3000 0x1000;
+   };
+
+   dcsr-cti@3a4000 {
+   compatible = fsl,ls1021a-dcsr-cti;
+   reg = 0x3a4000 0x1000 0x3a5000 0x1000 0x3a6000 0x1000;
+   };
+
+   dcsr-atbrepl@3a8000 {
+   compatible = fsl,ls1021a-dcsr-atbrepl;
+   reg = 0x3a8000 0x1000;
+   };
+
+   dcsr-tsgen-ctrl@3a9000

[PATCH 3/4] arm: ls1021a: add deep sleep support

2015-01-30 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 linux/kernel.h
+#include linux/suspend.h
+#include linux/io.h
+#include linux/of_platform.h
+#include linux/of_address.h
+#include linux/cpu_pm.h
+#include asm/suspend.h
+#include asm/delay.h
+#include asm/cp15.h
+#include asm/cacheflush.h
+#include asm/idmap.h
+
+#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__

[PATCH 1/4] fsl: add EPU FSM configuration for deep sleep

2015-01-30 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
 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 hongbo.zh...@freescale.com
+ * Chenhui Zhao chenhui.z...@freescale.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include linux/kernel.h
+#include linux/io.h
+#include linux/types.h
+
+#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

[PATCH v2 1/2] pm: add FSM configuration for deep sleep

2014-10-22 Thread Chenhui Zhao
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 Compare Reg

[PATCH v2 2/2] arm: pm: add deep sleep support for LS1

2014-10-22 Thread Chenhui Zhao
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, 

[PATCH v2 2/2] arm: pm: add deep sleep support for LS1

2014-10-22 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
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 linux/kernel.h
+#include linux/suspend.h
+#include linux/io.h
+#include linux/of_platform.h
+#include linux/of_address.h
+#include linux/cpu_pm.h
+#include asm/suspend.h
+#include asm/delay.h
+#include asm/cp15.h
+#include asm/cacheflush.h
+#include asm/idmap.h
+
+#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

[PATCH v2 1/2] pm: add FSM configuration for deep sleep

2014-10-22 Thread Chenhui Zhao
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 chenhui.z...@freescale.com
---
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 linux/kernel.h
+#include linux/io.h
+#include linux/types.h
+
+#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

  1   2   >