linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] QCOM 8074 cpuidle driver
@ 2014-09-04 22:35 Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 1/7] msm: scm: Add SCM warmboot flags for quad core targets Lina Iyer
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Changes since v4:
[ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10327.html ]
- Update to the v8 of ARM generic idle states patches
- Use platform device model for cpuidle-qcom
- Clean up msm-pm.c to remove unnecessary include files and functions
- Update commit text and documentation for all idle states
- Remove scm-boot relocate patch from this series, submitted earlier
[ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10518.html ]

Changes since v3:
[ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10288.html ]
- Fix CONFIG_QCOM_PM Kconfig as bool
- More clean ups in spm.c and spm-devices.c
	- Removed and re-organized data structures to make initialization simple
	- Remove export of sequence flush functions
	- Updated commit text
	- Comments for use of barriers.
- Rebase on top of 3.17-rc1

Changes since v2:
[ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10148.html ]
- Prune all the drivers to support basic WFI and power down cpuidle
  functionality. Remove debug code.
- Integrate KConfig changes into the drivers' patches.
- Use Lorenzo's ARM idle-states patches as the basis for reading cpuidle
  c-states from DT.
  [ http://marc.info/?l=linux-pm&m=140794514812383&w=2 ]
- Incorporate review comments
- Rebase on top of 3.16

Changes since v1/RFC:
[ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10065.html ]
- Remove hotplug from the patch series. Will submit it separately.
- Fix SPM drivers per the review comments
- Modify patch sequence to compile SPM drivers independent of msm-pm, so as to
  allow wfi() calls to use SPM even without SoC interface driver.

8074 like any ARM SoC can do architectural clock gating, that helps save on
power, but not enough of leakage power.  Leakage power of the SoC can be
further reduced by turning off power to the core. To aid this, every core (cpu
and L2) is accompanied by a Sub-system Power Manager (SPM), that can be
configured to indicate the low power mode, the core would be put into and the
SPM programs the peripheral h/w accordingly to enter low power and turn off the
power rail to the core.

The idle invocation hierarchy - 

	CPUIDLE
	|
	cpuidle-qcom.c [CPUIdle driver]
	|
	------>	msm-pm.c [SoC Interface layer for QCOM chipsets]
		|
		------> spm-devices.c [SPM devices manager]
		|	|
		|	------>	spm.c [SPM h/w driver]
		|
		------> scm-boot.c [SCM interface layer]		
			|
------------------------|--------------------------
(EL)			Secure Monitor Code
			|
			|
			wfi(); 
------------------------|--------------------------
(HW)			[CPU] {clock gate}
			|
			-----> [SPM] {statemachine}
			

The patchset does the following -

- Add new Secure Monitor flags to support warmboot of a quad core system.

- Introduce the SPM driver to control power to the core. The SPM h/w IP works
in conjunction with the Krait CPU/L2. When the core executes WFI instruction,
the core is clockgated and the SPM state machine takes over and powers the core
down. An interrupt from GIC, resumes the SPM state machine which brings the cpu
out of the low power mode.

- Add a SPM device manager to configure multiple SPM devices.

- Add the device tree configuration for each of the SPM nodes. There is one for
each cpu. There is one for each cpu.

- Introduce the SoC driver interface layer to configure SPM per the core's idle
 state. To power down the cpu core, the SPM h/w needs to be set up correctly
to power down the core, when the core executes WFI. Linux is expected to call
into Secure Monitor to power down the core. At reset, the core will start in
seure mode and will be returned back to Linux. 

- Add CPUIDLE driver for QCOM cpus. The cpuidle driver uses the SoC interface
layer to configure the SPM to allow Krait to be powered down. The cpuidle driver
is based on ARM idle-state framework for cpuidle drivers.

- Provide device configuration for 8074 SoC. Current support is for WFI and
standalone power collapse, which powers only the core independent of the
other cores and caches.

Thanks,
Lina



Lina Iyer (7):
  msm: scm: Add SCM warmboot flags for quad core targets.
  qcom: spm: Add Subsystem Power Manager driver (SAW2)
  qcom: spm-devices: Add SPM device manager for the SoC
  arm: dts: qcom: Add SPM device bindings for 8974
  qcom: msm-pm: Add cpu low power mode functions
  qcom: cpuidle: Add cpuidle driver for QCOM cpus
  arm: dts: qcom: Add idle states device nodes for 8974

 .../bindings/arm/msm/qcom,idle-state.txt           |  72 ++++++++
 Documentation/devicetree/bindings/arm/msm/spm.txt  |  47 +++++
 arch/arm/boot/dts/qcom-msm8974-pm.dtsi             |  69 +++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi                |  30 +++-
 drivers/cpuidle/Kconfig.arm                        |   7 +
 drivers/cpuidle/Makefile                           |   1 +
 drivers/cpuidle/cpuidle-qcom.c                     |  87 +++++++++
 drivers/soc/qcom/Kconfig                           |   8 +
 drivers/soc/qcom/Makefile                          |   1 +
 drivers/soc/qcom/msm-pm.c                          | 106 +++++++++++
 drivers/soc/qcom/spm-devices.c                     | 198 +++++++++++++++++++++
 drivers/soc/qcom/spm-drv.h                         |  69 +++++++
 drivers/soc/qcom/spm.c                             | 192 ++++++++++++++++++++
 include/soc/qcom/pm.h                              |  31 ++++
 include/soc/qcom/scm-boot.h                        |   2 +
 include/soc/qcom/spm.h                             |  38 ++++
 16 files changed, 954 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
 create mode 100644 Documentation/devicetree/bindings/arm/msm/spm.txt
 create mode 100644 arch/arm/boot/dts/qcom-msm8974-pm.dtsi
 create mode 100644 drivers/cpuidle/cpuidle-qcom.c
 create mode 100644 drivers/soc/qcom/msm-pm.c
 create mode 100644 drivers/soc/qcom/spm-devices.c
 create mode 100644 drivers/soc/qcom/spm-drv.h
 create mode 100644 drivers/soc/qcom/spm.c
 create mode 100644 include/soc/qcom/pm.h
 create mode 100644 include/soc/qcom/spm.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 1/7] msm: scm: Add SCM warmboot flags for quad core targets.
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2) Lina Iyer
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Quad core targets like APQ8074, APQ8064, APQ8084 need SCM support set up
warm boot addresses in the Secure Monitor. Extend the SCM flags to
support warmboot addresses for secondary cores.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
---
 include/soc/qcom/scm-boot.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/soc/qcom/scm-boot.h b/include/soc/qcom/scm-boot.h
index 6aabb24..02b445c 100644
--- a/include/soc/qcom/scm-boot.h
+++ b/include/soc/qcom/scm-boot.h
@@ -18,6 +18,8 @@
 #define SCM_FLAG_COLDBOOT_CPU3		0x20
 #define SCM_FLAG_WARMBOOT_CPU0		0x04
 #define SCM_FLAG_WARMBOOT_CPU1		0x02
+#define SCM_FLAG_WARMBOOT_CPU2		0x10
+#define SCM_FLAG_WARMBOOT_CPU3		0x40
 
 int scm_set_boot_addr(phys_addr_t addr, int flags);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2)
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 1/7] msm: scm: Add SCM warmboot flags for quad core targets Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-08  9:48   ` Pramod Gurav
  2014-09-04 22:35 ` [PATCH v5 3/7] qcom: spm-devices: Add SPM device manager for the SoC Lina Iyer
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Based on work by many authors, available at codeaurora.org

SPM is a hardware block that controls the peripheral logic surrounding
the application cores (cpu/l$). When the core executes WFI instruction,
the SPM takes over the putting the core in low power state as
configured. The wake up for the SPM is an interrupt at the GIC, which
then completes the rest of low power mode sequence and brings the core
out of low power mode.

The SPM has a set of control registers that configure the SPMs
individually based on the type of the core and the runtime conditions.
SPM is a finite state machine block to which a sequence is provided and
it interprets the bytes  and executes them in sequence. Each low power
mode that the core can enter into is provided to the SPM as a sequence.

Configure the SPM to set the core (cpu or L2) into its low power mode,
the index of the first command in the sequence is set in the SPM_CTL
register. When the core executes ARM wfi instruction, it triggers the
SPM state machine to start executing from that index. The SPM state
machine waits until the interrupt occurs and starts executing the rest
of the sequence until it hits the end of the sequence. The end of the
sequence jumps the core out of its low power mode.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
[lina: simplify the driver for initial submission, clean up and update
commit text]
---
 drivers/soc/qcom/Makefile  |   1 +
 drivers/soc/qcom/spm-drv.h |  69 ++++++++++++++++
 drivers/soc/qcom/spm.c     | 192 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+)
 create mode 100644 drivers/soc/qcom/spm-drv.h
 create mode 100644 drivers/soc/qcom/spm.c

diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 70d52ed..20b329f 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
+obj-$(CONFIG_QCOM_PM)	+=	spm.o
 CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
 obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
diff --git a/drivers/soc/qcom/spm-drv.h b/drivers/soc/qcom/spm-drv.h
new file mode 100644
index 0000000..e91df44
--- /dev/null
+++ b/drivers/soc/qcom/spm-drv.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#ifndef __QCOM_SPM_DRIVER_H
+#define __QCOM_SPM_DRIVER_H
+
+enum {
+	MSM_SPM_REG_SAW2_CFG,
+	MSM_SPM_REG_SAW2_AVS_CTL,
+	MSM_SPM_REG_SAW2_AVS_HYSTERESIS,
+	MSM_SPM_REG_SAW2_SPM_CTL,
+	MSM_SPM_REG_SAW2_PMIC_DLY,
+	MSM_SPM_REG_SAW2_AVS_LIMIT,
+	MSM_SPM_REG_SAW2_AVS_DLY,
+	MSM_SPM_REG_SAW2_SPM_DLY,
+	MSM_SPM_REG_SAW2_PMIC_DATA_0,
+	MSM_SPM_REG_SAW2_PMIC_DATA_1,
+	MSM_SPM_REG_SAW2_PMIC_DATA_2,
+	MSM_SPM_REG_SAW2_PMIC_DATA_3,
+	MSM_SPM_REG_SAW2_PMIC_DATA_4,
+	MSM_SPM_REG_SAW2_PMIC_DATA_5,
+	MSM_SPM_REG_SAW2_PMIC_DATA_6,
+	MSM_SPM_REG_SAW2_PMIC_DATA_7,
+	MSM_SPM_REG_SAW2_RST,
+
+	MSM_SPM_REG_NR_INITIALIZE = MSM_SPM_REG_SAW2_RST,
+
+	MSM_SPM_REG_SAW2_ID,
+	MSM_SPM_REG_SAW2_SECURE,
+	MSM_SPM_REG_SAW2_STS0,
+	MSM_SPM_REG_SAW2_STS1,
+	MSM_SPM_REG_SAW2_STS2,
+	MSM_SPM_REG_SAW2_VCTL,
+	MSM_SPM_REG_SAW2_SEQ_ENTRY,
+	MSM_SPM_REG_SAW2_SPM_STS,
+	MSM_SPM_REG_SAW2_AVS_STS,
+	MSM_SPM_REG_SAW2_PMIC_STS,
+	MSM_SPM_REG_SAW2_VERSION,
+
+	MSM_SPM_REG_NR,
+};
+
+struct msm_spm_mode {
+	u32 mode;
+	u8 *cmd;
+	u32 start_addr;
+};
+
+struct msm_spm_driver_data {
+	void __iomem *reg_base_addr;
+	u32 reg_shadow[MSM_SPM_REG_NR];
+	u32 *reg_offsets;
+	struct msm_spm_mode *modes;
+	u32 num_modes;
+};
+
+int msm_spm_drv_init(struct msm_spm_driver_data *dev);
+int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, u32 addr);
+int msm_spm_drv_set_spm_enable(struct msm_spm_driver_data *dev, bool enable);
+
+#endif /* __QCOM_SPM_DRIVER_H */
diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c
new file mode 100644
index 0000000..81e578c
--- /dev/null
+++ b/drivers/soc/qcom/spm.c
@@ -0,0 +1,192 @@
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "spm-drv.h"
+
+#define NUM_SEQ_ENTRY 32
+#define SPM_CTL_ENABLE BIT(0)
+
+static u32 msm_spm_reg_offsets_saw2_v2_1[MSM_SPM_REG_NR] = {
+	[MSM_SPM_REG_SAW2_SECURE]		= 0x00,
+	[MSM_SPM_REG_SAW2_ID]			= 0x04,
+	[MSM_SPM_REG_SAW2_CFG]			= 0x08,
+	[MSM_SPM_REG_SAW2_SPM_STS]		= 0x0C,
+	[MSM_SPM_REG_SAW2_AVS_STS]		= 0x10,
+	[MSM_SPM_REG_SAW2_PMIC_STS]		= 0x14,
+	[MSM_SPM_REG_SAW2_RST]			= 0x18,
+	[MSM_SPM_REG_SAW2_VCTL]			= 0x1C,
+	[MSM_SPM_REG_SAW2_AVS_CTL]		= 0x20,
+	[MSM_SPM_REG_SAW2_AVS_LIMIT]		= 0x24,
+	[MSM_SPM_REG_SAW2_AVS_DLY]		= 0x28,
+	[MSM_SPM_REG_SAW2_AVS_HYSTERESIS]	= 0x2C,
+	[MSM_SPM_REG_SAW2_SPM_CTL]		= 0x30,
+	[MSM_SPM_REG_SAW2_SPM_DLY]		= 0x34,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_0]		= 0x40,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_1]		= 0x44,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_2]		= 0x48,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_3]		= 0x4C,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_4]		= 0x50,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_5]		= 0x54,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_6]		= 0x58,
+	[MSM_SPM_REG_SAW2_PMIC_DATA_7]		= 0x5C,
+	[MSM_SPM_REG_SAW2_SEQ_ENTRY]		= 0x80,
+	[MSM_SPM_REG_SAW2_VERSION]		= 0xFD0,
+};
+
+static void flush_shadow(struct msm_spm_driver_data *drv, u32 reg_index)
+{
+	writel_relaxed(drv->reg_shadow[reg_index],
+			drv->reg_base_addr + drv->reg_offsets[reg_index]);
+}
+
+static void load_shadow(struct msm_spm_driver_data *drv, u32 reg_index)
+{
+	drv->reg_shadow[reg_index] = readl_relaxed(drv->reg_base_addr +
+						drv->reg_offsets[reg_index]);
+}
+
+static inline void set_start_addr(struct msm_spm_driver_data *drv, u32 addr)
+{
+	/* Update bits 10:4 in the SPM CTL register */
+	addr &= 0x7F;
+	addr <<= 4;
+	drv->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F;
+	drv->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr;
+}
+
+int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *drv, u32 mode)
+{
+	int i;
+	u32 start_addr = 0;
+
+	for (i = 0; i < drv->num_modes; i++) {
+		if (drv->modes[i].mode == mode) {
+			start_addr = drv->modes[i].start_addr;
+			break;
+		}
+	}
+
+	if (i == drv->num_modes)
+		return -EINVAL;
+
+	set_start_addr(drv, start_addr);
+	flush_shadow(drv, MSM_SPM_REG_SAW2_SPM_CTL);
+	/* Barrier to ensure we have written the start address */
+	wmb();
+
+	/* Update our shadow with the status changes, if any */
+	load_shadow(drv, MSM_SPM_REG_SAW2_SPM_STS);
+
+	return 0;
+}
+
+int msm_spm_drv_set_spm_enable(struct msm_spm_driver_data *drv, bool enable)
+{
+	u32 value = enable ? 0x01 : 0x00;
+
+	/* Update SPM_CTL to enable/disable the SPM */
+	if ((drv->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] & SPM_CTL_ENABLE)
+								!= value) {
+		/* Clear the existing value and update */
+		drv->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= ~0x1;
+		drv->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= value;
+		flush_shadow(drv, MSM_SPM_REG_SAW2_SPM_CTL);
+		/* Ensure we have enabled/disabled before returning */
+		wmb();
+	}
+
+	return 0;
+}
+
+static void flush_seq_data(struct msm_spm_driver_data *drv, u32 *reg_seq_entry)
+{
+	int i;
+
+	/* Write the 32 byte array into the SPM registers */
+	for (i = 0; i < NUM_SEQ_ENTRY; i++) {
+		writel_relaxed(reg_seq_entry[i],
+			drv->reg_base_addr
+			+ drv->reg_offsets[MSM_SPM_REG_SAW2_SEQ_ENTRY]
+			+ 4 * i);
+	}
+	/* Ensure that the changes are written */
+	wmb();
+}
+
+static void write_seq_data(struct msm_spm_driver_data *drv,
+		u32 *reg_seq_entry, u8 *cmd, u32 *offset)
+{
+	u32 cmd_w;
+	u32 offset_w = *offset / 4;
+	u8 last_cmd;
+
+	while (1) {
+		int i;
+
+		cmd_w = 0;
+		last_cmd = 0;
+		cmd_w = reg_seq_entry[offset_w];
+
+		for (i = (*offset % 4); i < 4; i++) {
+			last_cmd = *(cmd++);
+			cmd_w |=  last_cmd << (i * 8);
+			(*offset)++;
+			if (last_cmd == 0x0f)
+				break;
+		}
+
+		reg_seq_entry[offset_w++] = cmd_w;
+		if (last_cmd == 0x0f)
+			break;
+	}
+
+}
+
+int msm_spm_drv_init(struct msm_spm_driver_data *drv)
+{
+	int i;
+	int offset = 0;
+	u32 sequences[NUM_SEQ_ENTRY/4] = {0};
+
+	drv->reg_offsets = msm_spm_reg_offsets_saw2_v2_1;
+
+	/**
+	 * Compose the uint32 array based on the individual bytes of the SPM
+	 * sequence for each low power mode that we read from the DT.
+	 * The sequences are appended if there is space available in the
+	 * u32 after the end of the previous sequence.
+	 */
+	for (i = 0; i < drv->num_modes; i++) {
+		drv->modes[i].start_addr = offset;
+		write_seq_data(drv, &sequences[0], drv->modes[i].cmd, &offset);
+	}
+
+	/* Flush the integer array */
+	flush_seq_data(drv, &sequences[0]);
+
+	/**
+	 * Initialize the hardware with the control registers that
+	 * we have read.
+	 */
+	for (i = 0; i < MSM_SPM_REG_SAW2_PMIC_DATA_0; i++)
+		flush_shadow(drv, i);
+
+	return 0;
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 3/7] qcom: spm-devices: Add SPM device manager for the SoC
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 1/7] msm: scm: Add SCM warmboot flags for quad core targets Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2) Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 4/7] arm: dts: qcom: Add SPM device bindings for 8974 Lina Iyer
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Based on work by many authors, available at codeaurora.org

Each cpu or an L2$ has an SPM device. They are identical instances of
the same SPM block. This allows for multiple instances be grouped and
managed collectively. spm-devices.c is the SPM device manager managing
multiple SPM devices on top of the driver layer.

Device configuration of each SPM is picked up from the DTS. The hardware
configuration of each of the SPM is handled by the driver (spm.c).

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
[lina: simplify the driver for initial submission, clean up and update
commit text]
---
 Documentation/devicetree/bindings/arm/msm/spm.txt |  47 +++++
 drivers/soc/qcom/Kconfig                          |   8 +
 drivers/soc/qcom/Makefile                         |   2 +-
 drivers/soc/qcom/spm-devices.c                    | 198 ++++++++++++++++++++++
 include/soc/qcom/spm.h                            |  38 +++++
 5 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/spm.txt
 create mode 100644 drivers/soc/qcom/spm-devices.c
 create mode 100644 include/soc/qcom/spm.h

diff --git a/Documentation/devicetree/bindings/arm/msm/spm.txt b/Documentation/devicetree/bindings/arm/msm/spm.txt
new file mode 100644
index 0000000..30623b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm.txt
@@ -0,0 +1,47 @@
+* Subsystem Power Manager (SAW2)
+
+S4 generation of MSMs have SPM hardware blocks to control the Application
+Processor Sub-System power. These SPM blocks run individual state machine
+to determine what the core (L2 or Krait/Scorpion) would do when the WFI
+instruction is executed by the core.
+
+The devicetree representation of the SPM block should be:
+
+Required properties
+
+- compatible: Could be one of -
+		"qcom,spm-v2.1"
+- reg: The physical address and the size of the SPM's memory mapped registers
+- qcom,cpu: phandle for the CPU that the SPM block is attached to.
+	This field is required on only for SPMs that control the CPU.
+- qcom,saw2-clk-div: SAW2 configuration register to program the SPM runtime
+	clocks.
+- qcom,saw2-delays: The SPM delay values that SPM sequences would refer to.
+- qcom,saw2-enable: The SPM control register to enable/disable the sleep state
+	machine.
+
+Optional properties
+
+- qcom,saw2-spm-cmd-wfi: The WFI command sequence
+- qcom,saw2-spm-cmd-ret: The Retention command sequence
+- qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
+- qcom,saw2-spm-cmd-pc: The Power Collapse command sequence. This sequence may
+	turn off other SoC components.
+- qcom,saw2-spm-cmd-gdhs: GDHS (Globally Distributed Head Switch) command
+	sequence. This sequence will retain the memory but turn off the logic.
+-
+Example:
+	spm at f9089000 {
+		compatible = "qcom,spm-v2.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9089000 0x1000>;
+		qcom,cpu = <&CPU0>;
+		qcom,saw2-clk-div = <0x1>;
+		qcom,saw2-delays = <0x20000400>;
+		qcom,saw2-enable = <0x1>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
+				a0 b0 03 68 70 3b 92 a0 b0
+				82 2b 50 10 30 02 22 30 0f];
+	};
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 7dcd554..cd249c4 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -11,3 +11,11 @@ config QCOM_GSBI
 
 config QCOM_SCM
 	bool
+
+config QCOM_PM
+	bool "Qualcomm Power Management"
+	depends on PM && ARCH_QCOM
+	help
+	  QCOM Platform specific power driver to manage cores and L2 low power
+	  modes. It interface with various system drivers to put the cores in
+	  low power modes.
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 20b329f..9457b2a 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
-obj-$(CONFIG_QCOM_PM)	+=	spm.o
+obj-$(CONFIG_QCOM_PM)	+=	spm.o spm-devices.o
 CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
 obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
diff --git a/drivers/soc/qcom/spm-devices.c b/drivers/soc/qcom/spm-devices.c
new file mode 100644
index 0000000..776c0af
--- /dev/null
+++ b/drivers/soc/qcom/spm-devices.c
@@ -0,0 +1,198 @@
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <soc/qcom/spm.h>
+
+#include "spm-drv.h"
+
+/**
+ * All related information for an SPM device
+ * Helps manage the collective.
+ */
+struct msm_spm_device {
+	bool initialized;
+	struct msm_spm_driver_data drv;
+};
+
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
+
+/**
+ * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
+ * @mode: SPM LPM mode to enter
+ */
+int msm_spm_set_low_power_mode(u32 mode)
+{
+	struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
+	int ret = -EINVAL;
+
+	if (!dev->initialized)
+		return -ENXIO;
+
+	if (mode == MSM_SPM_MODE_DISABLED)
+		ret = msm_spm_drv_set_spm_enable(&dev->drv, false);
+	else if (!msm_spm_drv_set_spm_enable(&dev->drv, true))
+		ret = msm_spm_drv_set_low_power_mode(&dev->drv, mode);
+
+	return ret;
+}
+EXPORT_SYMBOL(msm_spm_set_low_power_mode);
+
+static int get_cpu_id(struct device_node *node)
+{
+	struct device_node *cpu_node;
+	u32 cpu;
+	int ret = -EINVAL;
+	char *key = "qcom,cpu";
+
+	cpu_node = of_parse_phandle(node, key, 0);
+	if (cpu_node) {
+		for_each_possible_cpu(cpu) {
+			if (of_get_cpu_node(cpu, NULL) == cpu_node)
+				return cpu;
+		}
+	}
+	return ret;
+}
+
+static struct msm_spm_device *msm_spm_get_device(struct platform_device *pdev)
+{
+	struct msm_spm_device *dev = NULL;
+	int cpu = get_cpu_id(pdev->dev.of_node);
+
+	if ((cpu >= 0) && cpu < num_possible_cpus())
+		dev = &per_cpu(msm_cpu_spm_device, cpu);
+
+	return dev;
+}
+
+static int msm_spm_dev_probe(struct platform_device *pdev)
+{
+	int ret;
+	int i;
+	struct device_node *node = pdev->dev.of_node;
+	char *key;
+	u32 val;
+	struct msm_spm_mode modes[MSM_SPM_MODE_NR];
+	struct msm_spm_device *spm_dev;
+	struct resource *res;
+	u32 mode_count = 0;
+
+	struct spm_of {
+		char *key;
+		u32 id;
+	};
+
+	/* SPM Configuration registers */
+	struct spm_of spm_of_data[] = {
+		{"qcom,saw2-clk-div", MSM_SPM_REG_SAW2_CFG},
+		{"qcom,saw2-enable", MSM_SPM_REG_SAW2_SPM_CTL},
+		{"qcom,saw2-delays", MSM_SPM_REG_SAW2_SPM_DLY},
+	};
+
+	/* SPM sleep sequences */
+	struct spm_of mode_of_data[] = {
+		{"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING},
+		{"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE},
+		{"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_RETENTION},
+	};
+
+	 /* Get the right SPM device */
+	spm_dev = msm_spm_get_device(pdev);
+	if (IS_ERR_OR_NULL(spm_dev))
+		return -EINVAL;
+
+	/* Get the SAW start address */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -EINVAL;
+		goto fail;
+	}
+	spm_dev->drv.reg_base_addr = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!spm_dev->drv.reg_base_addr) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* Read the SPM configuration register values */
+	for (i = 0; i < ARRAY_SIZE(spm_of_data); i++) {
+		ret = of_property_read_u32(node, spm_of_data[i].key, &val);
+		if (ret)
+			continue;
+		spm_dev->drv.reg_shadow[spm_of_data[i].id] = val;
+	}
+
+	/* Read the byte arrays for the SPM sleep sequences */
+	for (i = 0; i < ARRAY_SIZE(mode_of_data); i++) {
+		modes[mode_count].start_addr = 0;
+		key = mode_of_data[i].key;
+		modes[mode_count].cmd =
+			(u8 *)of_get_property(node, key, &val);
+		if (!modes[mode_count].cmd)
+			continue;
+		modes[mode_count].mode = mode_of_data[i].id;
+		mode_count++;
+	}
+
+	spm_dev->drv.modes = devm_kcalloc(&pdev->dev, mode_count,
+						sizeof(modes[0]), GFP_KERNEL);
+	if (!spm_dev->drv.modes)
+		return -ENOMEM;
+	spm_dev->drv.num_modes = mode_count;
+	memcpy(spm_dev->drv.modes, &modes[0], sizeof(modes[0]) * mode_count);
+
+	/* Initialize the hardware */
+	ret = msm_spm_drv_init(&spm_dev->drv);
+	if (ret) {
+		kfree(spm_dev->drv.modes);
+		return ret;
+	}
+
+	spm_dev->initialized = true;
+	return ret;
+
+fail:
+	dev_err(&pdev->dev, "SPM device probe failed: %d\n", ret);
+	return ret;
+}
+
+static struct of_device_id msm_spm_match_table[] = {
+	{.compatible = "qcom,spm-v2.1"},
+	{},
+};
+
+static struct platform_driver msm_spm_device_driver = {
+	.probe = msm_spm_dev_probe,
+	.driver = {
+		.name = "spm-v2",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_spm_match_table,
+	},
+};
+
+static int __init msm_spm_device_init(void)
+{
+	return platform_driver_register(&msm_spm_device_driver);
+}
+device_initcall(msm_spm_device_init);
diff --git a/include/soc/qcom/spm.h b/include/soc/qcom/spm.h
new file mode 100644
index 0000000..29686ef
--- /dev/null
+++ b/include/soc/qcom/spm.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef __QCOM_SPM_H
+#define __QCOM_SPM_H
+
+enum {
+	MSM_SPM_MODE_DISABLED,
+	MSM_SPM_MODE_CLOCK_GATING,
+	MSM_SPM_MODE_RETENTION,
+	MSM_SPM_MODE_GDHS,
+	MSM_SPM_MODE_POWER_COLLAPSE,
+	MSM_SPM_MODE_NR
+};
+
+struct msm_spm_device;
+
+#if defined(CONFIG_QCOM_PM)
+
+int msm_spm_set_low_power_mode(u32 mode);
+
+#else
+
+static inline int msm_spm_set_low_power_mode(u32 mode)
+{ return -ENOSYS; }
+
+#endif  /* CONFIG_QCOM_PM */
+
+#endif  /* __QCOM_SPM_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 4/7] arm: dts: qcom: Add SPM device bindings for 8974
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
                   ` (2 preceding siblings ...)
  2014-09-04 22:35 ` [PATCH v5 3/7] qcom: spm-devices: Add SPM device manager for the SoC Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 5/7] qcom: msm-pm: Add cpu low power mode functions Lina Iyer
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Add SPM device bindings for QCOM 8974 based cpus. SPM is the sub-system
power manager and controls the logic around the cores (cpu and L2).

Each core has an instance of SPM and controls only that core. Each cpu
SPM is configured to support WFI and SPC (standalone-power collapse).

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
---
 arch/arm/boot/dts/qcom-msm8974-pm.dtsi | 69 ++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi    | 10 +++--
 2 files changed, 75 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/boot/dts/qcom-msm8974-pm.dtsi

diff --git a/arch/arm/boot/dts/qcom-msm8974-pm.dtsi b/arch/arm/boot/dts/qcom-msm8974-pm.dtsi
new file mode 100644
index 0000000..bbfb1d5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8974-pm.dtsi
@@ -0,0 +1,69 @@
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+&soc {
+	spm at f9089000 {
+		compatible = "qcom,spm-v2.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9089000 0x1000>;
+		qcom,cpu = <&CPU0>;
+		qcom,saw2-clk-div = <0x01>;
+		qcom,saw2-delays = <0x3C102800>;
+		qcom,saw2-enable = <0x01>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	spm at f9099000 {
+		compatible = "qcom,spm-v2.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf9099000 0x1000>;
+		qcom,cpu = <&CPU1>;
+		qcom,saw2-clk-div = <0x01>;
+		qcom,saw2-delays = <0x3C102800>;
+		qcom,saw2-enable = <0x01>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	spm at f90a9000 {
+		compatible = "qcom,spm-v2.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90a9000 0x1000>;
+		qcom,cpu = <&CPU2>;
+		qcom,saw2-clk-div = <0x01>;
+		qcom,saw2-delays = <0x3C102800>;
+		qcom,saw2-enable = <0x01>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+
+	spm at f90b9000 {
+		compatible = "qcom,spm-v2.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xf90b9000 0x1000>;
+		qcom,cpu = <&CPU3>;
+		qcom,saw2-clk-div = <0x01>;
+		qcom,saw2-delays = <0x3C102800>;
+		qcom,saw2-enable = <0x01>;
+		qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+		qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+			30 06 26 30 0F];
+	};
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 69dca2a..0580bc2 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -14,7 +14,7 @@
 		#size-cells = <0>;
 		interrupts = <1 9 0xf04>;
 
-		cpu at 0 {
+		CPU0: cpu at 0 {
 			compatible = "qcom,krait";
 			enable-method = "qcom,kpss-acc-v2";
 			device_type = "cpu";
@@ -23,7 +23,7 @@
 			qcom,acc = <&acc0>;
 		};
 
-		cpu at 1 {
+		CPU1: cpu at 1 {
 			compatible = "qcom,krait";
 			enable-method = "qcom,kpss-acc-v2";
 			device_type = "cpu";
@@ -32,7 +32,7 @@
 			qcom,acc = <&acc1>;
 		};
 
-		cpu at 2 {
+		CPU2: cpu at 2 {
 			compatible = "qcom,krait";
 			enable-method = "qcom,kpss-acc-v2";
 			device_type = "cpu";
@@ -41,7 +41,7 @@
 			qcom,acc = <&acc2>;
 		};
 
-		cpu at 3 {
+		CPU3: cpu at 3 {
 			compatible = "qcom,krait";
 			enable-method = "qcom,kpss-acc-v2";
 			device_type = "cpu";
@@ -238,3 +238,5 @@
 		};
 	};
 };
+
+#include "qcom-msm8974-pm.dtsi"
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 5/7] qcom: msm-pm: Add cpu low power mode functions
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
                   ` (3 preceding siblings ...)
  2014-09-04 22:35 ` [PATCH v5 4/7] arm: dts: qcom: Add SPM device bindings for 8974 Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 6/7] qcom: cpuidle: Add cpuidle driver for QCOM cpus Lina Iyer
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Based on work by many authors, available at codeaurora.org

Add interface layer to abstract and handle hardware specific
functionality for executing various cpu low power modes in QCOM
chipsets.

QCOM cpus support multiple low power modes. The C-States are defined as -

    * WFI (clock gating)
    * Retention (clock gating at lower power)
    * Standalone Power Collapse (Standalone PC or SPC) - The power to
    	the cpu is lost and the cpu warmboots.
    * Power Collapse (PC) - Same as SPC, but is a cognizant of the fact
    	that the SoC may do deeper sleep modes.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
[lina: simplify the driver for an initial submission, add commit text
description of idle states]
---
 drivers/soc/qcom/Makefile |   2 +-
 drivers/soc/qcom/msm-pm.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++
 include/soc/qcom/pm.h     |  31 ++++++++++++++
 3 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soc/qcom/msm-pm.c
 create mode 100644 include/soc/qcom/pm.h

diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 9457b2a..acdd6fa 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
-obj-$(CONFIG_QCOM_PM)	+=	spm.o spm-devices.o
+obj-$(CONFIG_QCOM_PM)	+=	spm.o spm-devices.o msm-pm.o
 CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
 obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
diff --git a/drivers/soc/qcom/msm-pm.c b/drivers/soc/qcom/msm-pm.c
new file mode 100644
index 0000000..8926c71
--- /dev/null
+++ b/drivers/soc/qcom/msm-pm.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include <soc/qcom/pm.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/scm-boot.h>
+#include <soc/qcom/spm.h>
+
+#define SCM_CMD_TERMINATE_PC	(0x2)
+#define SCM_FLUSH_FLAG_MASK	(0x3)
+
+static int set_up_boot_address(void *entry, int cpu)
+{
+	static int flags[NR_CPUS] = {
+		SCM_FLAG_WARMBOOT_CPU0,
+		SCM_FLAG_WARMBOOT_CPU1,
+		SCM_FLAG_WARMBOOT_CPU2,
+		SCM_FLAG_WARMBOOT_CPU3,
+	};
+	static DEFINE_PER_CPU(void *, last_known_entry);
+
+	if (entry == per_cpu(last_known_entry, cpu))
+		return 0;
+
+	per_cpu(last_known_entry, cpu) = entry;
+	return scm_set_boot_addr(virt_to_phys(entry), flags[cpu]);
+}
+
+static int msm_pm_collapse(unsigned long int unused)
+{
+	int ret;
+	enum msm_pm_l2_scm_flag flag;
+
+	ret = set_up_boot_address(cpu_resume, raw_smp_processor_id());
+	if (ret) {
+		pr_err("Failed to set warm boot address for cpu %d\n",
+				raw_smp_processor_id());
+		return ret;
+	}
+
+	flag = MSM_SCM_L2_ON & SCM_FLUSH_FLAG_MASK;
+	scm_call_atomic1(SCM_SVC_BOOT, SCM_CMD_TERMINATE_PC, flag);
+
+	return 0;
+}
+
+/**
+ * msm_cpu_pm_enter_sleep(): Enter a low power mode on current cpu
+ *
+ * @mode - sleep mode to enter
+ *
+ * The code should be called with interrupts disabled and on the core on
+ * which the low power mode is to be executed.
+ *
+ */
+static int msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode)
+{
+	int ret;
+
+	switch (mode) {
+	case MSM_PM_SLEEP_MODE_SPC:
+		msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE);
+		ret = cpu_suspend(0, msm_pm_collapse);
+		break;
+	default:
+	case MSM_PM_SLEEP_MODE_WFI:
+		msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING);
+		ret = cpu_do_idle();
+		break;
+	}
+
+	local_irq_enable();
+
+	return ret;
+}
+
+static struct platform_device qcom_cpuidle_device = {
+	.name              = "qcom_cpuidle",
+	.id                = -1,
+	.dev.platform_data = msm_cpu_pm_enter_sleep,
+};
+
+static int __init msm_pm_device_init(void)
+{
+	platform_device_register(&qcom_cpuidle_device);
+
+	return 0;
+}
+device_initcall(msm_pm_device_init);
diff --git a/include/soc/qcom/pm.h b/include/soc/qcom/pm.h
new file mode 100644
index 0000000..c2f006b
--- /dev/null
+++ b/include/soc/qcom/pm.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __QCOM_PM_H
+#define __QCOM_PM_H
+
+enum msm_pm_sleep_mode {
+	MSM_PM_SLEEP_MODE_WFI,
+	MSM_PM_SLEEP_MODE_RET,
+	MSM_PM_SLEEP_MODE_SPC,
+	MSM_PM_SLEEP_MODE_PC,
+	MSM_PM_SLEEP_MODE_NR,
+};
+
+enum msm_pm_l2_scm_flag {
+	MSM_SCM_L2_ON = 0,
+	MSM_SCM_L2_OFF = 1
+};
+
+#endif  /* __QCOM_PM_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 6/7] qcom: cpuidle: Add cpuidle driver for QCOM cpus
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
                   ` (4 preceding siblings ...)
  2014-09-04 22:35 ` [PATCH v5 5/7] qcom: msm-pm: Add cpu low power mode functions Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-04 22:35 ` [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974 Lina Iyer
  2014-09-11  6:59 ` [PATCH v5 0/7] QCOM 8074 cpuidle driver Pramod Gurav
  7 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Add cpuidle driver interface to allow cpus to go into C-States. Use the
cpuidle DT interface common across ARM architectures to provide the
C-State information to the cpuidle framework.

Supported modes at this time are clock gating (wfi) and cpu power down
(Standalone PC or spc).

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
---
 .../bindings/arm/msm/qcom,idle-state.txt           | 72 ++++++++++++++++++
 drivers/cpuidle/Kconfig.arm                        |  7 ++
 drivers/cpuidle/Makefile                           |  1 +
 drivers/cpuidle/cpuidle-qcom.c                     | 87 ++++++++++++++++++++++
 4 files changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
 create mode 100644 drivers/cpuidle/cpuidle-qcom.c

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt b/Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
new file mode 100644
index 0000000..47095b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
@@ -0,0 +1,72 @@
+QCOM Idle States for cpuidle driver
+
+ARM provides idle-state node to define the cpuidle states, as defined in [1].
+cpuidle-qcom is the cpuidle driver for Qualcomm SoCs and uses these idle
+states. Idle states have different enter/exit latency and residency values.
+The idle states supported by the QCOM SoC are defined as -
+
+    * WFI
+    * Retention
+    * Standalone Power Collapse (Standalone PC or SPC)
+    * Power Collapse (PC)
+
+WFI: WFI does a little more in addition to architectural clock gating.  ARM
+processors when execute the wfi instruction will gate their internal clocks.
+QCOM cpus use this instruction as a trigger for the SPM state machine. Usually
+with a cpu entering WFI, the SPM is configured to do clock-gating as well. The
+SPM state machine waits for the interrrupt to trigger the core back in to
+active. When all CPUs in the SoC, clock gate using the ARM wfi instruction, the
+second level cache usually can also clock gate sensing no cpu activity. When a
+cpu is ready to run, it needs the cache to be active before starting execution.
+Allowing the SPM to execute the clock gating statemachine and waiting for
+interrupt on behalf of the processor has a benefit of guaranteeing that the
+system state is conducive for the core to resume execution.
+
+Retention: Retention is a low power state where the core is clockgated and the
+memory and the registers associated with the core are retained.  The voltage
+may be reduced to the minimum value needed to keep the processor registers
+active. Retention is triggered when the core executes wfi instruction. The SPM
+should be configured to execute the retention sequence and would wait for
+interrupt, before restoring the cpu to execution state. Retention may have a
+slightly higher latency than WFI.
+
+Standalone PC: A cpu can power down and warmboot if there is a sufficient time
+between now and the next know wake up. SPC mode is used to indicate a core
+entering a power down state without consulting any other cpu or the system
+resources. This helps save power only on that core. Like WFI and Retention, the
+core executes wfi and the SPM programmed to do SPC would use the cpu control
+logic to power down the core's supply and restore it back when woken up by an
+interrupt.  Applying power and reseting the core causes the core to warmboot
+back into secure mode which trampolines the control back to the kernel. To
+enter a power down state the kernel needs to call into the secure layer which
+would then execute the ARM wfi instruction. Failing to do so, would result in a
+crash enforced by the warm boot code in the secure layer. On a SoC with
+write-back L1 cache, the cache would need to be flushed.
+
+Power Collapse: This state is similiar to the SPC mode, but distinguishes
+itself in the fact that the cpu acknowledges and permits the SoC to enter
+deeper sleep modes. In a hierarchical power domain SoC, this means L2 and other
+caches can be flushed, system bus, clocks - lowered, and SoC main XO turned off
+and voltages reduced, provided all cpus enter this state. In other words, it is
+a coupled idle state.  Since the span of low power modes possible at this state
+is vast, the exit latency and the residency of this low power mode would be
+considered high even though at a cpu level, this essentially is cpu power down.
+The SPM in this state also may handshake with the Resource power manager
+processor in the SoC to indicate a complete subsystem shut down.
+
+The idle-state for QCOM SoCs are distinguished by the compatible property of
+the node. They indicate to the cpuidle driver the entry point to use for
+cpuidle. The devicetree representation of the idle state should be -
+
+Required properties:
+
+- compatible: Must be "arm,idle-state"
+		and one of -
+			"qcom,idle-state-wfi",
+			"qcom,idle-state-ret",
+			"qcom,idle-state-spc",
+			"qcom,idle-state-pc",
+
+Other required and optional properties are specified in [1].
+
+[1]. Documentation/devicetree/bindings/arm/idle-states.txt
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 38cff69..6a9ee12 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -62,3 +62,10 @@ config ARM_MVEBU_V7_CPUIDLE
 	depends on ARCH_MVEBU
 	help
 	  Select this to enable cpuidle on Armada 370, 38x and XP processors.
+
+config ARM_QCOM_CPUIDLE
+	bool "CPU Idle drivers for Qualcomm processors"
+	depends on QCOM_PM
+	select DT_IDLE_STATES
+	help
+	  Select this to enable cpuidle for QCOM processors
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 4d177b9..6c222d5 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)		+= cpuidle-zynq.o
 obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
 obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
 obj-$(CONFIG_ARM_EXYNOS_CPUIDLE)        += cpuidle-exynos.o
+obj-$(CONFIG_ARM_QCOM_CPUIDLE)		+= cpuidle-qcom.o
 
 ###############################################################################
 # MIPS drivers
diff --git a/drivers/cpuidle/cpuidle-qcom.c b/drivers/cpuidle/cpuidle-qcom.c
new file mode 100644
index 0000000..f3e033b
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-qcom.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <soc/qcom/pm.h>
+#include "dt_idle_states.h"
+
+static void (*qcom_idle_enter)(enum msm_pm_sleep_mode);
+
+static int qcom_lpm_enter_wfi(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv, int index)
+{
+	qcom_idle_enter(MSM_PM_SLEEP_MODE_WFI);
+
+	return index;
+}
+
+static int qcom_lpm_enter_spc(struct cpuidle_device *dev,
+				struct cpuidle_driver *drv, int index)
+{
+	cpu_pm_enter();
+	qcom_idle_enter(MSM_PM_SLEEP_MODE_SPC);
+	cpu_pm_exit();
+
+	return index;
+}
+
+static struct cpuidle_driver qcom_cpuidle_driver = {
+	.name	= "qcom_cpuidle",
+	.owner	= THIS_MODULE,
+};
+
+static const struct of_device_id qcom_idle_state_match[] __initconst = {
+	{ .compatible = "qcom,idle-state-wfi", .data = qcom_lpm_enter_wfi },
+	{ .compatible = "qcom,idle-state-spc", .data = qcom_lpm_enter_spc },
+	{ },
+};
+
+static int qcom_cpuidle_probe(struct platform_device *pdev)
+{
+	struct cpuidle_driver *drv = &qcom_cpuidle_driver;
+	int ret;
+
+	qcom_idle_enter = (void *)(pdev->dev.platform_data);
+
+	 /* Probe for other states including platform WFI */
+	ret = dt_init_idle_driver(drv, qcom_idle_state_match, 0);
+	if (ret <= 0) {
+		pr_err("%s: No cpuidle state found.\n", __func__);
+		return ret;
+	}
+
+	ret = cpuidle_register(drv, NULL);
+	if (ret) {
+		pr_err("%s: failed to register cpuidle driver\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver qcom_cpuidle_plat_driver = {
+	.probe	= qcom_cpuidle_probe,
+	.driver = {
+		.name = "qcom_cpuidle",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(qcom_cpuidle_plat_driver);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
                   ` (5 preceding siblings ...)
  2014-09-04 22:35 ` [PATCH v5 6/7] qcom: cpuidle: Add cpuidle driver for QCOM cpus Lina Iyer
@ 2014-09-04 22:35 ` Lina Iyer
  2014-09-05 19:58   ` Kevin Hilman
  2014-09-05 19:59   ` Lina Iyer
  2014-09-11  6:59 ` [PATCH v5 0/7] QCOM 8074 cpuidle driver Pramod Gurav
  7 siblings, 2 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-04 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

Add allowable C-States for each cpu using the cpu-idle-states node.
ARM spec dictates WFI as the default idle state at 0. Support standalone
power collapse (power down that does not affect any SoC idle states) for
each cpu.

Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 0580bc2..041c8b6 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -21,6 +21,7 @@
 			reg = <0>;
 			next-level-cache = <&L2>;
 			qcom,acc = <&acc0>;
+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
 		};
 
 		CPU1: cpu at 1 {
@@ -30,6 +31,7 @@
 			reg = <1>;
 			next-level-cache = <&L2>;
 			qcom,acc = <&acc1>;
+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
 		};
 
 		CPU2: cpu at 2 {
@@ -39,6 +41,7 @@
 			reg = <2>;
 			next-level-cache = <&L2>;
 			qcom,acc = <&acc2>;
+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
 		};
 
 		CPU3: cpu at 3 {
@@ -48,6 +51,7 @@
 			reg = <3>;
 			next-level-cache = <&L2>;
 			qcom,acc = <&acc3>;
+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
 		};
 
 		L2: l2-cache {
@@ -55,6 +59,22 @@
 			cache-level = <2>;
 			qcom,saw = <&saw_l2>;
 		};
+
+		idle-states {
+			CPU_WFI: cpu-idle-state-0 {
+				compatible = "qcom,idle-state-wfi", "arm,idle-state";
+				entry-latency-us = <1>;
+				exit-latency-us = <1>;
+				min-residency-us = <2>;
+			};
+
+			CPU_SPC: cpu-idle-state-1 {
+				compatible = "qcom,idle-state-spc", "arm,idle-state";
+				entry-latency-us = <150>;
+				exit-latency-us = <200>;
+				min-residency-us = <2000>;
+			};
+		};
 	};
 
 	cpu-pmu {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974
  2014-09-04 22:35 ` [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974 Lina Iyer
@ 2014-09-05 19:58   ` Kevin Hilman
  2014-09-05 19:59   ` Lina Iyer
  1 sibling, 0 replies; 13+ messages in thread
From: Kevin Hilman @ 2014-09-05 19:58 UTC (permalink / raw)
  To: linux-arm-kernel

Lina Iyer <lina.iyer@linaro.org> writes:

> Add allowable C-States for each cpu using the cpu-idle-states node.
> ARM spec dictates WFI as the default idle state at 0. Support standalone
> power collapse (power down that does not affect any SoC idle states) for
> each cpu.
>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>

[...]

> @@ -55,6 +59,22 @@
>  			cache-level = <2>;
>  			qcom,saw = <&saw_l2>;
>  		};
> +
> +		idle-states {
> +			CPU_WFI: cpu-idle-state-0 {
			         ^^^^^^^^^^^^^^^^
Minor nit:

This name is what's being used to populate the idle state's ->name field
in the CPUidle driver, which in turn is used by tools like powertop to
display state names, etc.

So first, that name field has to be short (it currently gets truncated,
dropping the zero), and second that field should be more descriptive,
like 'WFI', so viewing in the various tools shows something useful.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974
  2014-09-04 22:35 ` [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974 Lina Iyer
  2014-09-05 19:58   ` Kevin Hilman
@ 2014-09-05 19:59   ` Lina Iyer
  1 sibling, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-05 19:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 04 2014 at 16:36 -0600, Lina Iyer wrote:
>Add allowable C-States for each cpu using the cpu-idle-states node.
>ARM spec dictates WFI as the default idle state at 0. Support standalone
>power collapse (power down that does not affect any SoC idle states) for
>each cpu.
>
>Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
>---
> arch/arm/boot/dts/qcom-msm8974.dtsi | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
>diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
>index 0580bc2..041c8b6 100644
>--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
>+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
>@@ -21,6 +21,7 @@
> 			reg = <0>;
> 			next-level-cache = <&L2>;
> 			qcom,acc = <&acc0>;
>+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
> 		};
>
> 		CPU1: cpu at 1 {
>@@ -30,6 +31,7 @@
> 			reg = <1>;
> 			next-level-cache = <&L2>;
> 			qcom,acc = <&acc1>;
>+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
> 		};
>
> 		CPU2: cpu at 2 {
>@@ -39,6 +41,7 @@
> 			reg = <2>;
> 			next-level-cache = <&L2>;
> 			qcom,acc = <&acc2>;
>+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
> 		};
>
> 		CPU3: cpu at 3 {
>@@ -48,6 +51,7 @@
> 			reg = <3>;
> 			next-level-cache = <&L2>;
> 			qcom,acc = <&acc3>;
>+			cpu-idle-states = <&CPU_WFI &CPU_SPC>;
> 		};
>
> 		L2: l2-cache {
>@@ -55,6 +59,22 @@
> 			cache-level = <2>;
> 			qcom,saw = <&saw_l2>;
> 		};
>+
>+		idle-states {
>+			CPU_WFI: cpu-idle-state-0 {
I will rename the device node name to something more relevant. The name is
used as the idle-state name.
>+				compatible = "qcom,idle-state-wfi", "arm,idle-state";
>+				entry-latency-us = <1>;
>+				exit-latency-us = <1>;
>+				min-residency-us = <2>;
>+			};
>+
>+			CPU_SPC: cpu-idle-state-1 {
>+				compatible = "qcom,idle-state-spc", "arm,idle-state";
>+				entry-latency-us = <150>;
>+				exit-latency-us = <200>;
>+				min-residency-us = <2000>;
>+			};
>+		};
> 	};
>
> 	cpu-pmu {
>-- 
>1.9.1
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2)
  2014-09-04 22:35 ` [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2) Lina Iyer
@ 2014-09-08  9:48   ` Pramod Gurav
  0 siblings, 0 replies; 13+ messages in thread
From: Pramod Gurav @ 2014-09-08  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lina,

On Friday 05 September 2014 04:05 AM, Lina Iyer wrote:

>  drivers/soc/qcom/spm.c     | 192 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 262 insertions(+)
>  create mode 100644 drivers/soc/qcom/spm-drv.h
>  create mode 100644 drivers/soc/qcom/spm.c
> 
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index 70d52ed..20b329f 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
> +obj-$(CONFIG_QCOM_PM)	+=	spm.o

CONFIG_QCOM_PM is missing in Kconfig hence this driver wont build. I see
it is added in patch #3. Please move it to this patch so that this
driver builds.

>  CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
>  obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
> diff --git a/drivers/soc/qcom/spm-drv.h b/drivers/soc/qcom/spm-drv.h
> new file mode 100644
> index 0000000..e91df44

Thanks
Pramod

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 0/7] QCOM 8074 cpuidle driver
  2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
                   ` (6 preceding siblings ...)
  2014-09-04 22:35 ` [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974 Lina Iyer
@ 2014-09-11  6:59 ` Pramod Gurav
  2014-09-11 14:48   ` Lina Iyer
  7 siblings, 1 reply; 13+ messages in thread
From: Pramod Gurav @ 2014-09-11  6:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lina,

With your patchset on top of 3.17-rc4 with v9 of ARM generic idle states
patches from Lorenzo I have tested cpuidle on dragonboard8974 with
Linaro test suites. All testcases report pass. Also verified manually
through sysfs to see changes in usage count and other details about each
state on all cpus.

So,
Tested-by:  Pramod Gurav <pramod.gurav@smartplayin.com>

I have a comment/observation only on name entry for each state which
reflects only "cpu-idle-state-" as Lorenzo dt-idle driver limits
CPUIDLE_NAME_LEN to 16.

Thanks
Pramod.
On Friday 05 September 2014 04:05 AM, Lina Iyer wrote:
> Changes since v4:
> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10327.html ]
> - Update to the v8 of ARM generic idle states patches
> - Use platform device model for cpuidle-qcom
> - Clean up msm-pm.c to remove unnecessary include files and functions
> - Update commit text and documentation for all idle states
> - Remove scm-boot relocate patch from this series, submitted earlier
> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10518.html ]
> 
> Changes since v3:
> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10288.html ]
> - Fix CONFIG_QCOM_PM Kconfig as bool
> - More clean ups in spm.c and spm-devices.c
> 	- Removed and re-organized data structures to make initialization simple
> 	- Remove export of sequence flush functions
> 	- Updated commit text
> 	- Comments for use of barriers.
> - Rebase on top of 3.17-rc1
> 
> Changes since v2:
> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10148.html ]
> - Prune all the drivers to support basic WFI and power down cpuidle
>   functionality. Remove debug code.
> - Integrate KConfig changes into the drivers' patches.
> - Use Lorenzo's ARM idle-states patches as the basis for reading cpuidle
>   c-states from DT.
>   [ http://marc.info/?l=linux-pm&m=140794514812383&w=2 ]
> - Incorporate review comments
> - Rebase on top of 3.16
> 
> Changes since v1/RFC:
> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10065.html ]
> - Remove hotplug from the patch series. Will submit it separately.
> - Fix SPM drivers per the review comments
> - Modify patch sequence to compile SPM drivers independent of msm-pm, so as to
>   allow wfi() calls to use SPM even without SoC interface driver.
> 
> 8074 like any ARM SoC can do architectural clock gating, that helps save on
> power, but not enough of leakage power.  Leakage power of the SoC can be
> further reduced by turning off power to the core. To aid this, every core (cpu
> and L2) is accompanied by a Sub-system Power Manager (SPM), that can be
> configured to indicate the low power mode, the core would be put into and the
> SPM programs the peripheral h/w accordingly to enter low power and turn off the
> power rail to the core.
> 
> The idle invocation hierarchy - 
> 
> 	CPUIDLE
> 	|
> 	cpuidle-qcom.c [CPUIdle driver]
> 	|
> 	------>	msm-pm.c [SoC Interface layer for QCOM chipsets]
> 		|
> 		------> spm-devices.c [SPM devices manager]
> 		|	|
> 		|	------>	spm.c [SPM h/w driver]
> 		|
> 		------> scm-boot.c [SCM interface layer]		
> 			|
> ------------------------|--------------------------
> (EL)			Secure Monitor Code
> 			|
> 			|
> 			wfi(); 
> ------------------------|--------------------------
> (HW)			[CPU] {clock gate}
> 			|
> 			-----> [SPM] {statemachine}
> 			
> 
> The patchset does the following -
> 
> - Add new Secure Monitor flags to support warmboot of a quad core system.
> 
> - Introduce the SPM driver to control power to the core. The SPM h/w IP works
> in conjunction with the Krait CPU/L2. When the core executes WFI instruction,
> the core is clockgated and the SPM state machine takes over and powers the core
> down. An interrupt from GIC, resumes the SPM state machine which brings the cpu
> out of the low power mode.
> 
> - Add a SPM device manager to configure multiple SPM devices.
> 
> - Add the device tree configuration for each of the SPM nodes. There is one for
> each cpu. There is one for each cpu.
> 
> - Introduce the SoC driver interface layer to configure SPM per the core's idle
>  state. To power down the cpu core, the SPM h/w needs to be set up correctly
> to power down the core, when the core executes WFI. Linux is expected to call
> into Secure Monitor to power down the core. At reset, the core will start in
> seure mode and will be returned back to Linux. 
> 
> - Add CPUIDLE driver for QCOM cpus. The cpuidle driver uses the SoC interface
> layer to configure the SPM to allow Krait to be powered down. The cpuidle driver
> is based on ARM idle-state framework for cpuidle drivers.
> 
> - Provide device configuration for 8074 SoC. Current support is for WFI and
> standalone power collapse, which powers only the core independent of the
> other cores and caches.
> 
> Thanks,
> Lina
> 
> 
> 
> Lina Iyer (7):
>   msm: scm: Add SCM warmboot flags for quad core targets.
>   qcom: spm: Add Subsystem Power Manager driver (SAW2)
>   qcom: spm-devices: Add SPM device manager for the SoC
>   arm: dts: qcom: Add SPM device bindings for 8974
>   qcom: msm-pm: Add cpu low power mode functions
>   qcom: cpuidle: Add cpuidle driver for QCOM cpus
>   arm: dts: qcom: Add idle states device nodes for 8974
> 
>  .../bindings/arm/msm/qcom,idle-state.txt           |  72 ++++++++
>  Documentation/devicetree/bindings/arm/msm/spm.txt  |  47 +++++
>  arch/arm/boot/dts/qcom-msm8974-pm.dtsi             |  69 +++++++
>  arch/arm/boot/dts/qcom-msm8974.dtsi                |  30 +++-
>  drivers/cpuidle/Kconfig.arm                        |   7 +
>  drivers/cpuidle/Makefile                           |   1 +
>  drivers/cpuidle/cpuidle-qcom.c                     |  87 +++++++++
>  drivers/soc/qcom/Kconfig                           |   8 +
>  drivers/soc/qcom/Makefile                          |   1 +
>  drivers/soc/qcom/msm-pm.c                          | 106 +++++++++++
>  drivers/soc/qcom/spm-devices.c                     | 198 +++++++++++++++++++++
>  drivers/soc/qcom/spm-drv.h                         |  69 +++++++
>  drivers/soc/qcom/spm.c                             | 192 ++++++++++++++++++++
>  include/soc/qcom/pm.h                              |  31 ++++
>  include/soc/qcom/scm-boot.h                        |   2 +
>  include/soc/qcom/spm.h                             |  38 ++++
>  16 files changed, 954 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/msm/spm.txt
>  create mode 100644 arch/arm/boot/dts/qcom-msm8974-pm.dtsi
>  create mode 100644 drivers/cpuidle/cpuidle-qcom.c
>  create mode 100644 drivers/soc/qcom/msm-pm.c
>  create mode 100644 drivers/soc/qcom/spm-devices.c
>  create mode 100644 drivers/soc/qcom/spm-drv.h
>  create mode 100644 drivers/soc/qcom/spm.c
>  create mode 100644 include/soc/qcom/pm.h
>  create mode 100644 include/soc/qcom/spm.h
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v5 0/7] QCOM 8074 cpuidle driver
  2014-09-11  6:59 ` [PATCH v5 0/7] QCOM 8074 cpuidle driver Pramod Gurav
@ 2014-09-11 14:48   ` Lina Iyer
  0 siblings, 0 replies; 13+ messages in thread
From: Lina Iyer @ 2014-09-11 14:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 11 2014 at 00:55 -0600, Pramod Gurav wrote:
>Hi Lina,
>
>With your patchset on top of 3.17-rc4 with v9 of ARM generic idle states
>patches from Lorenzo I have tested cpuidle on dragonboard8974 with
>Linaro test suites. All testcases report pass. Also verified manually
>through sysfs to see changes in usage count and other details about each
>state on all cpus.
>
>So,
>Tested-by:  Pramod Gurav <pramod.gurav@smartplayin.com>
>
Thanks!
>I have a comment/observation only on name entry for each state which
>reflects only "cpu-idle-state-" as Lorenzo dt-idle driver limits
>CPUIDLE_NAME_LEN to 16.
>
Yes, Kevin pointed that out. I will address them in the next revision.

>Thanks
>Pramod.
>On Friday 05 September 2014 04:05 AM, Lina Iyer wrote:
>> Changes since v4:
>> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10327.html ]
>> - Update to the v8 of ARM generic idle states patches
>> - Use platform device model for cpuidle-qcom
>> - Clean up msm-pm.c to remove unnecessary include files and functions
>> - Update commit text and documentation for all idle states
>> - Remove scm-boot relocate patch from this series, submitted earlier
>> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10518.html ]
>>
>> Changes since v3:
>> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10288.html ]
>> - Fix CONFIG_QCOM_PM Kconfig as bool
>> - More clean ups in spm.c and spm-devices.c
>> 	- Removed and re-organized data structures to make initialization simple
>> 	- Remove export of sequence flush functions
>> 	- Updated commit text
>> 	- Comments for use of barriers.
>> - Rebase on top of 3.17-rc1
>>
>> Changes since v2:
>> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10148.html ]
>> - Prune all the drivers to support basic WFI and power down cpuidle
>>   functionality. Remove debug code.
>> - Integrate KConfig changes into the drivers' patches.
>> - Use Lorenzo's ARM idle-states patches as the basis for reading cpuidle
>>   c-states from DT.
>>   [ http://marc.info/?l=linux-pm&m=140794514812383&w=2 ]
>> - Incorporate review comments
>> - Rebase on top of 3.16
>>
>> Changes since v1/RFC:
>> [ https://www.mail-archive.com/linux-arm-msm at vger.kernel.org/msg10065.html ]
>> - Remove hotplug from the patch series. Will submit it separately.
>> - Fix SPM drivers per the review comments
>> - Modify patch sequence to compile SPM drivers independent of msm-pm, so as to
>>   allow wfi() calls to use SPM even without SoC interface driver.
>>
>> 8074 like any ARM SoC can do architectural clock gating, that helps save on
>> power, but not enough of leakage power.  Leakage power of the SoC can be
>> further reduced by turning off power to the core. To aid this, every core (cpu
>> and L2) is accompanied by a Sub-system Power Manager (SPM), that can be
>> configured to indicate the low power mode, the core would be put into and the
>> SPM programs the peripheral h/w accordingly to enter low power and turn off the
>> power rail to the core.
>>
>> The idle invocation hierarchy -
>>
>> 	CPUIDLE
>> 	|
>> 	cpuidle-qcom.c [CPUIdle driver]
>> 	|
>> 	------>	msm-pm.c [SoC Interface layer for QCOM chipsets]
>> 		|
>> 		------> spm-devices.c [SPM devices manager]
>> 		|	|
>> 		|	------>	spm.c [SPM h/w driver]
>> 		|
>> 		------> scm-boot.c [SCM interface layer]		
>> 			|
>> ------------------------|--------------------------
>> (EL)			Secure Monitor Code
>> 			|
>> 			|
>> 			wfi();
>> ------------------------|--------------------------
>> (HW)			[CPU] {clock gate}
>> 			|
>> 			-----> [SPM] {statemachine}
>> 			
>>
>> The patchset does the following -
>>
>> - Add new Secure Monitor flags to support warmboot of a quad core system.
>>
>> - Introduce the SPM driver to control power to the core. The SPM h/w IP works
>> in conjunction with the Krait CPU/L2. When the core executes WFI instruction,
>> the core is clockgated and the SPM state machine takes over and powers the core
>> down. An interrupt from GIC, resumes the SPM state machine which brings the cpu
>> out of the low power mode.
>>
>> - Add a SPM device manager to configure multiple SPM devices.
>>
>> - Add the device tree configuration for each of the SPM nodes. There is one for
>> each cpu. There is one for each cpu.
>>
>> - Introduce the SoC driver interface layer to configure SPM per the core's idle
>>  state. To power down the cpu core, the SPM h/w needs to be set up correctly
>> to power down the core, when the core executes WFI. Linux is expected to call
>> into Secure Monitor to power down the core. At reset, the core will start in
>> seure mode and will be returned back to Linux.
>>
>> - Add CPUIDLE driver for QCOM cpus. The cpuidle driver uses the SoC interface
>> layer to configure the SPM to allow Krait to be powered down. The cpuidle driver
>> is based on ARM idle-state framework for cpuidle drivers.
>>
>> - Provide device configuration for 8074 SoC. Current support is for WFI and
>> standalone power collapse, which powers only the core independent of the
>> other cores and caches.
>>
>> Thanks,
>> Lina
>>
>>
>>
>> Lina Iyer (7):
>>   msm: scm: Add SCM warmboot flags for quad core targets.
>>   qcom: spm: Add Subsystem Power Manager driver (SAW2)
>>   qcom: spm-devices: Add SPM device manager for the SoC
>>   arm: dts: qcom: Add SPM device bindings for 8974
>>   qcom: msm-pm: Add cpu low power mode functions
>>   qcom: cpuidle: Add cpuidle driver for QCOM cpus
>>   arm: dts: qcom: Add idle states device nodes for 8974
>>
>>  .../bindings/arm/msm/qcom,idle-state.txt           |  72 ++++++++
>>  Documentation/devicetree/bindings/arm/msm/spm.txt  |  47 +++++
>>  arch/arm/boot/dts/qcom-msm8974-pm.dtsi             |  69 +++++++
>>  arch/arm/boot/dts/qcom-msm8974.dtsi                |  30 +++-
>>  drivers/cpuidle/Kconfig.arm                        |   7 +
>>  drivers/cpuidle/Makefile                           |   1 +
>>  drivers/cpuidle/cpuidle-qcom.c                     |  87 +++++++++
>>  drivers/soc/qcom/Kconfig                           |   8 +
>>  drivers/soc/qcom/Makefile                          |   1 +
>>  drivers/soc/qcom/msm-pm.c                          | 106 +++++++++++
>>  drivers/soc/qcom/spm-devices.c                     | 198 +++++++++++++++++++++
>>  drivers/soc/qcom/spm-drv.h                         |  69 +++++++
>>  drivers/soc/qcom/spm.c                             | 192 ++++++++++++++++++++
>>  include/soc/qcom/pm.h                              |  31 ++++
>>  include/soc/qcom/scm-boot.h                        |   2 +
>>  include/soc/qcom/spm.h                             |  38 ++++
>>  16 files changed, 954 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
>>  create mode 100644 Documentation/devicetree/bindings/arm/msm/spm.txt
>>  create mode 100644 arch/arm/boot/dts/qcom-msm8974-pm.dtsi
>>  create mode 100644 drivers/cpuidle/cpuidle-qcom.c
>>  create mode 100644 drivers/soc/qcom/msm-pm.c
>>  create mode 100644 drivers/soc/qcom/spm-devices.c
>>  create mode 100644 drivers/soc/qcom/spm-drv.h
>>  create mode 100644 drivers/soc/qcom/spm.c
>>  create mode 100644 include/soc/qcom/pm.h
>>  create mode 100644 include/soc/qcom/spm.h
>>

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2014-09-11 14:48 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-04 22:35 [PATCH v5 0/7] QCOM 8074 cpuidle driver Lina Iyer
2014-09-04 22:35 ` [PATCH v5 1/7] msm: scm: Add SCM warmboot flags for quad core targets Lina Iyer
2014-09-04 22:35 ` [PATCH v5 2/7] qcom: spm: Add Subsystem Power Manager driver (SAW2) Lina Iyer
2014-09-08  9:48   ` Pramod Gurav
2014-09-04 22:35 ` [PATCH v5 3/7] qcom: spm-devices: Add SPM device manager for the SoC Lina Iyer
2014-09-04 22:35 ` [PATCH v5 4/7] arm: dts: qcom: Add SPM device bindings for 8974 Lina Iyer
2014-09-04 22:35 ` [PATCH v5 5/7] qcom: msm-pm: Add cpu low power mode functions Lina Iyer
2014-09-04 22:35 ` [PATCH v5 6/7] qcom: cpuidle: Add cpuidle driver for QCOM cpus Lina Iyer
2014-09-04 22:35 ` [PATCH v5 7/7] arm: dts: qcom: Add idle states device nodes for 8974 Lina Iyer
2014-09-05 19:58   ` Kevin Hilman
2014-09-05 19:59   ` Lina Iyer
2014-09-11  6:59 ` [PATCH v5 0/7] QCOM 8074 cpuidle driver Pramod Gurav
2014-09-11 14:48   ` Lina Iyer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).