All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] powerpc/rcpm: add RCPM driver
@ 2015-06-16  9:26 ` Yuantian.Tang
  0 siblings, 0 replies; 5+ messages in thread
From: Yuantian.Tang @ 2015-06-16  9:26 UTC (permalink / raw)
  To: b07421
  Cc: linuxppc-dev, linux-kernel, devicetree, Tang Yuantian, Chenhui Zhao

From: Tang Yuantian <Yuantian.Tang@freescale.com>

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.zhao@freescale.com>
Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
---
v3:
	- added static and __init modifier to fsl_rcpm_init
v2:
	- fix code style issues
	- refine compatible string match part

 Documentation/devicetree/bindings/soc/fsl/rcpm.txt |  22 ++
 arch/powerpc/include/asm/fsl_guts.h                | 105 +++++++
 arch/powerpc/include/asm/fsl_pm.h                  |  48 +++
 arch/powerpc/platforms/85xx/Kconfig                |   1 +
 arch/powerpc/sysdev/Kconfig                        |   5 +
 arch/powerpc/sysdev/Makefile                       |   1 +
 arch/powerpc/sysdev/fsl_rcpm.c                     | 338 +++++++++++++++++++++
 7 files changed, 520 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 0000000..5318999
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
@@ -0,0 +1,22 @@
+* 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>;
+	};
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	res0000[4];
+	__be32	cdozsr;	    /* 0x0004 Core Doze Status Register */
+	u8	res0008[4];
+	__be32	cdozcr;	    /* 0x000c Core Doze Control Register */
+	u8	res0010[4];
+	__be32	cnapsr;	    /* 0x0014 Core Nap Status Register */
+	u8	res0018[4];
+	__be32	cnapcr;	    /* 0x001c Core Nap Control Register */
+	u8	res0020[4];
+	__be32	cdozpsr;    /* 0x0024 Core Doze Previous Status Register */
+	u8	res0028[4];
+	__be32	cnappsr;    /* 0x002c Core Nap Previous Status Register */
+	u8	res0030[4];
+	__be32	cwaitsr;    /* 0x0034 Core Wait Status Register */
+	u8	res0038[4];
+	__be32	cwdtdsr;    /* 0x003c Core Watchdog Detect Status Register */
+	__be32	powmgtcsr;  /* 0x0040 PM Control&Status Register */
+#define RCPM_POWMGTCSR_SLP	0x00020000
+	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 Core PH15 Prev Status Register */
+	u8	res_c0[16];
+	__be32	pcph20sr;	/* Physical Core PH20 Status Register */
+	__be32	pcph20setr;	/* Physical Core PH20 Set Control Register */
+	__be32	pcph20clrr;	/* Physical Core PH20 Clear Control Register */
+	__be32	pcph20psr;	/* Physical Core PH20 Prev Status Register */
+	__be32	pcpw20sr;	/* Physical Core PW20 Status Register */
+	u8	res_e0[12];
+	__be32	pcph30sr;	/* Physical Core PH30 Status Register */
+	__be32	pcph30setr;	/* Physical Core PH30 Set Control Register */
+	__be32	pcph30clrr;	/* Physical Core PH30 Clear Control Register */
+	__be32	pcph30psr;	/* Physical Core PH30 Prev Status Register */
+	u8	res_100[32];
+	__be32	ippwrgatecr;	/* IP Power Gating Control Register */
+	u8	res_124[12];
+	__be32	powmgtcsr;	/* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ		0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST		0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST	0x00000100
+	u8	res_134[12];
+	__be32	ippdexpcr[4];	/* IP Powerdown Exception Control Reg */
+	u8	res_150[12];
+	__be32	tpmimr0;	/* Thread PM Interrupt Mask Reg */
+	u8	res_160[12];
+	__be32	tpmcimr0;	/* Thread PM Crit Interrupt Mask Reg */
+	u8	res_170[12];
+	__be32	tpmmcmr0;	/* Thread PM Machine Check Interrupt Mask Reg */
+	u8	res_180[12];
+	__be32	tpmnmimr0;	/* Thread PM NMI Mask Reg */
+	u8	res_190[12];
+	__be32	tmcpmaskcr0;	/* Thread Machine Check Mask Control Reg */
+	__be32	pctbenr;	/* Physical Core Time Base Enable Reg */
+	__be32	pctbclkselr;	/* Physical Core Time Base Clock Select */
+	__be32	tbclkdivr;	/* Time Base Clock Divider Register */
+	u8	res_1ac[4];
+	__be32	ttbhltcr[4];	/* Thread Time Base Halt Control Register */
+	__be32	clpcl10sr;	/* Cluster PCL10 Status Register */
+	__be32	clpcl10setr;	/* Cluster PCL30 Set Control Register */
+	__be32	clpcl10clrr;	/* Cluster PCL30 Clear Control Register */
+	__be32	clpcl10psr;	/* Cluster PCL30 Prev Status Register */
+	__be32	cddslpsetr;	/* Core Domain Deep Sleep Set Register */
+	__be32	cddslpclrr;	/* Core Domain Deep Sleep Clear Register */
+	__be32	cdpwroksetr;	/* Core Domain Power OK Set Register */
+	__be32	cdpwrokclrr;	/* Core Domain Power OK Clear Register */
+	__be32	cdpwrensr;	/* Core Domain Power Enable Status Register */
+	__be32	cddslsr;	/* Core Domain Deep Sleep Status Register */
+	u8	res_1e8[8];
+	__be32	dslpcntcr[8];	/* Deep Sleep Counter Cfg Register */
+	u8	res_300[3568];
+};
+
 #endif
 #endif
diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h
new file mode 100644
index 0000000..4b09f09
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_pm.h
@@ -0,0 +1,48 @@
+/*
+ * Support Power Management
+ *
+ * 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.
+ */
+#ifndef __PPC_FSL_PM_H
+#define __PPC_FSL_PM_H
+#ifdef __KERNEL__
+
+#define E500_PM_PH10	1
+#define E500_PM_PH15	2
+#define E500_PM_PH20	3
+#define E500_PM_PH30	4
+#define E500_PM_DOZE	E500_PM_PH10
+#define E500_PM_NAP	E500_PM_PH15
+
+#define PLAT_PM_SLEEP	20
+#define PLAT_PM_LPM20	30
+
+#define FSL_PM_SLEEP		(1 << 0)
+#define FSL_PM_DEEP_SLEEP	(1 << 1)
+
+struct fsl_pm_ops {
+	/* mask pending interrupts to the RCPM from MPIC */
+	void (*irq_mask)(int cpu);
+
+	/* unmask pending interrupts to the RCPM from MPIC */
+	void (*irq_unmask)(int cpu);
+	void (*cpu_enter_state)(int cpu, int state);
+	void (*cpu_exit_state)(int cpu, int state);
+	int (*plat_enter_sleep)(void);
+	void (*freeze_time_base)(bool freeze);
+
+	/* keep the power of IP blocks during sleep/deep sleep */
+	void (*set_ip_power)(bool enable, u32 *mask);
+
+	/* get platform supported power management modes */
+	unsigned int (*get_pm_modes)(void);
+};
+
+extern const struct fsl_pm_ops *qoriq_pm_ops;
+#endif /* __KERNEL__ */
+#endif /* __PPC_FSL_PM_H */
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 2fb4b24..ae1b8a2 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
 	select FSL_PCI if PCI
 	select SERIAL_8250_EXTENDED if SERIAL_8250
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+	select FSL_CORENET_RCPM if PPC_E500MC
 	default y
 
 if FSL_SOC_BOOKE
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a19332a..52dc165 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -40,3 +40,8 @@ config SCOM_DEBUGFS
 config GE_FPGA
 	bool
 	default n
+
+config FSL_CORENET_RCPM
+	bool
+	help
+	  This option enables support for RCPM (Run Control/Power Management).
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f7cb2a1..8bbedfd 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM)	+= fsl_rcpm.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644
index 0000000..4bd2d64
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -0,0 +1,338 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2015 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao <chenhui.zhao@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/types.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <asm/fsl_guts.h>
+#include <asm/cputhreads.h>
+#include <asm/fsl_pm.h>
+
+const struct fsl_pm_ops *qoriq_pm_ops;
+
+static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs;
+static unsigned int fsl_supported_pm_modes;
+
+static void rcpm_v1_irq_mask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	setbits32(&rcpm_v1_regs->cpmimr, mask);
+	setbits32(&rcpm_v1_regs->cpmcimr, mask);
+	setbits32(&rcpm_v1_regs->cpmmcmr, mask);
+	setbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_mask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	setbits32(&rcpm_v2_regs->tpmimr0, mask);
+	setbits32(&rcpm_v2_regs->tpmcimr0, mask);
+	setbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+	setbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v1_irq_unmask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	clrbits32(&rcpm_v1_regs->cpmimr, mask);
+	clrbits32(&rcpm_v1_regs->cpmcimr, mask);
+	clrbits32(&rcpm_v1_regs->cpmmcmr, mask);
+	clrbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_unmask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	clrbits32(&rcpm_v2_regs->tpmimr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmcimr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+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);
+}
+
+static void rcpm_v1_cpu_enter_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	switch (state) {
+	case E500_PM_PH10:
+		setbits32(&rcpm_v1_regs->cdozcr, mask);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v1_regs->cnapcr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+		break;
+	}
+}
+
+static void rcpm_v2_cpu_enter_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+	switch (state) {
+	case E500_PM_PH10:
+		/* one bit corresponds to one thread for PH10 of 6500 */
+		setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v2_regs->pcph15setr, mask);
+		break;
+	case E500_PM_PH20:
+		setbits32(&rcpm_v2_regs->pcph20setr, mask);
+		break;
+	case E500_PM_PH30:
+		setbits32(&rcpm_v2_regs->pcph30setr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+	}
+}
+
+static void rcpm_v1_cpu_exit_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	switch (state) {
+	case E500_PM_PH10:
+		clrbits32(&rcpm_v1_regs->cdozcr, mask);
+		break;
+	case E500_PM_PH15:
+		clrbits32(&rcpm_v1_regs->cnapcr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+		break;
+	}
+}
+
+static void rcpm_v2_cpu_exit_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+	switch (state) {
+	case E500_PM_PH10:
+		setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v2_regs->pcph15clrr, mask);
+		break;
+	case E500_PM_PH20:
+		setbits32(&rcpm_v2_regs->pcph20clrr, mask);
+		break;
+	case E500_PM_PH30:
+		setbits32(&rcpm_v2_regs->pcph30clrr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+	}
+}
+
+static int rcpm_v1_plat_enter_state(int state)
+{
+	u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
+	int ret = 0;
+	int result;
+
+	switch (state) {
+	case PLAT_PM_SLEEP:
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);
+
+		/* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
+		result = spin_event_timeout(
+		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
+		if (!result) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+			       __func__);
+			ret = -ETIMEDOUT;
+		}
+		break;
+	default:
+		pr_warn("%s: Unknown platform PM state (%d)\n",
+		       __func__, state);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rcpm_v2_plat_enter_state(int state)
+{
+	u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr;
+	int ret = 0;
+	int result;
+
+	switch (state) {
+	case PLAT_PM_LPM20:
+		/* clear previous LPM20 status */
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST);
+		/* enter LPM20 status */
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ);
+
+		/* At this point, the device is in LPM20 status. */
+
+		/* resume ... */
+		result = spin_event_timeout(
+		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10);
+		if (!result) {
+			pr_err("%s: timeout waiting for LPM20 bit to be cleared\n",
+			       __func__);
+			ret = -ETIMEDOUT;
+		}
+		break;
+	default:
+		pr_warn("%s: Unknown platform PM state (%d)\n",
+		       __func__, state);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rcpm_v1_plat_enter_sleep(void)
+{
+	return rcpm_v1_plat_enter_state(PLAT_PM_SLEEP);
+}
+
+static int rcpm_v2_plat_enter_sleep(void)
+{
+	return rcpm_v2_plat_enter_state(PLAT_PM_LPM20);
+}
+
+static void rcpm_common_freeze_time_base(u32 *tben_reg, int freeze)
+{
+	static u32 mask;
+
+	if (freeze) {
+		mask = in_be32(tben_reg);
+		clrbits32(tben_reg, mask);
+	} else {
+		setbits32(tben_reg, mask);
+	}
+
+	/* read back to push the previous write */
+	in_be32(tben_reg);
+}
+
+static void rcpm_v1_freeze_time_base(bool freeze)
+{
+	rcpm_common_freeze_time_base(&rcpm_v1_regs->ctbenr, freeze);
+}
+
+static void rcpm_v2_freeze_time_base(bool freeze)
+{
+	rcpm_common_freeze_time_base(&rcpm_v2_regs->pctbenr, freeze);
+}
+
+static unsigned int rcpm_get_pm_modes(void)
+{
+	return fsl_supported_pm_modes;
+}
+
+static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
+	.irq_mask = rcpm_v1_irq_mask,
+	.irq_unmask = rcpm_v1_irq_unmask,
+	.cpu_enter_state = rcpm_v1_cpu_enter_state,
+	.cpu_exit_state = rcpm_v1_cpu_exit_state,
+	.plat_enter_sleep = rcpm_v1_plat_enter_sleep,
+	.set_ip_power = rcpm_v1_set_ip_power,
+	.freeze_time_base = rcpm_v1_freeze_time_base,
+	.get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
+	.irq_mask = rcpm_v2_irq_mask,
+	.irq_unmask = rcpm_v2_irq_unmask,
+	.cpu_enter_state = rcpm_v2_cpu_enter_state,
+	.cpu_exit_state = rcpm_v2_cpu_exit_state,
+	.plat_enter_sleep = rcpm_v2_plat_enter_sleep,
+	.set_ip_power = rcpm_v2_set_ip_power,
+	.freeze_time_base = rcpm_v2_freeze_time_base,
+	.get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct of_device_id rcpm_matches[] = {
+	{
+		.compatible = "fsl,qoriq-rcpm-1.0",
+		.data = (void *)&qoriq_rcpm_v1_ops,
+	},
+	{
+		.compatible = "fsl,qoriq-rcpm-2.0",
+		.data = (void *)&qoriq_rcpm_v2_ops,
+	},
+	{},
+};
+
+static int __init fsl_rcpm_init(void)
+{
+	struct device_node *np;
+	const struct of_device_id *match;
+	void __iomem *base;
+
+	np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
+	if (!np) {
+		pr_err("%s: can't find the rcpm node.\n", __func__);
+		return -ENODEV;
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: of_iomap() error.\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* support sleep by default */
+	fsl_supported_pm_modes = FSL_PM_SLEEP;
+	of_node_put(np);
+
+	rcpm_v1_regs = base;
+	rcpm_v2_regs = base;
+
+	qoriq_pm_ops = match->data;
+
+	return 0;
+}
+
+/* need to call this before SMP init */
+early_initcall(fsl_rcpm_init);
-- 
2.1.0.27.g96db324


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

* [PATCH v3] powerpc/rcpm: add RCPM driver
@ 2015-06-16  9:26 ` Yuantian.Tang
  0 siblings, 0 replies; 5+ messages in thread
From: Yuantian.Tang @ 2015-06-16  9:26 UTC (permalink / raw)
  To: b07421
  Cc: linuxppc-dev, linux-kernel, devicetree, Tang Yuantian, Chenhui Zhao

From: Tang Yuantian <Yuantian.Tang@freescale.com>

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.zhao@freescale.com>
Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
---
v3:
	- added static and __init modifier to fsl_rcpm_init
v2:
	- fix code style issues
	- refine compatible string match part

 Documentation/devicetree/bindings/soc/fsl/rcpm.txt |  22 ++
 arch/powerpc/include/asm/fsl_guts.h                | 105 +++++++
 arch/powerpc/include/asm/fsl_pm.h                  |  48 +++
 arch/powerpc/platforms/85xx/Kconfig                |   1 +
 arch/powerpc/sysdev/Kconfig                        |   5 +
 arch/powerpc/sysdev/Makefile                       |   1 +
 arch/powerpc/sysdev/fsl_rcpm.c                     | 338 +++++++++++++++++++++
 7 files changed, 520 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 0000000..5318999
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
@@ -0,0 +1,22 @@
+* 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>;
+	};
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	res0000[4];
+	__be32	cdozsr;	    /* 0x0004 Core Doze Status Register */
+	u8	res0008[4];
+	__be32	cdozcr;	    /* 0x000c Core Doze Control Register */
+	u8	res0010[4];
+	__be32	cnapsr;	    /* 0x0014 Core Nap Status Register */
+	u8	res0018[4];
+	__be32	cnapcr;	    /* 0x001c Core Nap Control Register */
+	u8	res0020[4];
+	__be32	cdozpsr;    /* 0x0024 Core Doze Previous Status Register */
+	u8	res0028[4];
+	__be32	cnappsr;    /* 0x002c Core Nap Previous Status Register */
+	u8	res0030[4];
+	__be32	cwaitsr;    /* 0x0034 Core Wait Status Register */
+	u8	res0038[4];
+	__be32	cwdtdsr;    /* 0x003c Core Watchdog Detect Status Register */
+	__be32	powmgtcsr;  /* 0x0040 PM Control&Status Register */
+#define RCPM_POWMGTCSR_SLP	0x00020000
+	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 Core PH15 Prev Status Register */
+	u8	res_c0[16];
+	__be32	pcph20sr;	/* Physical Core PH20 Status Register */
+	__be32	pcph20setr;	/* Physical Core PH20 Set Control Register */
+	__be32	pcph20clrr;	/* Physical Core PH20 Clear Control Register */
+	__be32	pcph20psr;	/* Physical Core PH20 Prev Status Register */
+	__be32	pcpw20sr;	/* Physical Core PW20 Status Register */
+	u8	res_e0[12];
+	__be32	pcph30sr;	/* Physical Core PH30 Status Register */
+	__be32	pcph30setr;	/* Physical Core PH30 Set Control Register */
+	__be32	pcph30clrr;	/* Physical Core PH30 Clear Control Register */
+	__be32	pcph30psr;	/* Physical Core PH30 Prev Status Register */
+	u8	res_100[32];
+	__be32	ippwrgatecr;	/* IP Power Gating Control Register */
+	u8	res_124[12];
+	__be32	powmgtcsr;	/* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ		0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST		0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST	0x00000100
+	u8	res_134[12];
+	__be32	ippdexpcr[4];	/* IP Powerdown Exception Control Reg */
+	u8	res_150[12];
+	__be32	tpmimr0;	/* Thread PM Interrupt Mask Reg */
+	u8	res_160[12];
+	__be32	tpmcimr0;	/* Thread PM Crit Interrupt Mask Reg */
+	u8	res_170[12];
+	__be32	tpmmcmr0;	/* Thread PM Machine Check Interrupt Mask Reg */
+	u8	res_180[12];
+	__be32	tpmnmimr0;	/* Thread PM NMI Mask Reg */
+	u8	res_190[12];
+	__be32	tmcpmaskcr0;	/* Thread Machine Check Mask Control Reg */
+	__be32	pctbenr;	/* Physical Core Time Base Enable Reg */
+	__be32	pctbclkselr;	/* Physical Core Time Base Clock Select */
+	__be32	tbclkdivr;	/* Time Base Clock Divider Register */
+	u8	res_1ac[4];
+	__be32	ttbhltcr[4];	/* Thread Time Base Halt Control Register */
+	__be32	clpcl10sr;	/* Cluster PCL10 Status Register */
+	__be32	clpcl10setr;	/* Cluster PCL30 Set Control Register */
+	__be32	clpcl10clrr;	/* Cluster PCL30 Clear Control Register */
+	__be32	clpcl10psr;	/* Cluster PCL30 Prev Status Register */
+	__be32	cddslpsetr;	/* Core Domain Deep Sleep Set Register */
+	__be32	cddslpclrr;	/* Core Domain Deep Sleep Clear Register */
+	__be32	cdpwroksetr;	/* Core Domain Power OK Set Register */
+	__be32	cdpwrokclrr;	/* Core Domain Power OK Clear Register */
+	__be32	cdpwrensr;	/* Core Domain Power Enable Status Register */
+	__be32	cddslsr;	/* Core Domain Deep Sleep Status Register */
+	u8	res_1e8[8];
+	__be32	dslpcntcr[8];	/* Deep Sleep Counter Cfg Register */
+	u8	res_300[3568];
+};
+
 #endif
 #endif
diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h
new file mode 100644
index 0000000..4b09f09
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_pm.h
@@ -0,0 +1,48 @@
+/*
+ * Support Power Management
+ *
+ * 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.
+ */
+#ifndef __PPC_FSL_PM_H
+#define __PPC_FSL_PM_H
+#ifdef __KERNEL__
+
+#define E500_PM_PH10	1
+#define E500_PM_PH15	2
+#define E500_PM_PH20	3
+#define E500_PM_PH30	4
+#define E500_PM_DOZE	E500_PM_PH10
+#define E500_PM_NAP	E500_PM_PH15
+
+#define PLAT_PM_SLEEP	20
+#define PLAT_PM_LPM20	30
+
+#define FSL_PM_SLEEP		(1 << 0)
+#define FSL_PM_DEEP_SLEEP	(1 << 1)
+
+struct fsl_pm_ops {
+	/* mask pending interrupts to the RCPM from MPIC */
+	void (*irq_mask)(int cpu);
+
+	/* unmask pending interrupts to the RCPM from MPIC */
+	void (*irq_unmask)(int cpu);
+	void (*cpu_enter_state)(int cpu, int state);
+	void (*cpu_exit_state)(int cpu, int state);
+	int (*plat_enter_sleep)(void);
+	void (*freeze_time_base)(bool freeze);
+
+	/* keep the power of IP blocks during sleep/deep sleep */
+	void (*set_ip_power)(bool enable, u32 *mask);
+
+	/* get platform supported power management modes */
+	unsigned int (*get_pm_modes)(void);
+};
+
+extern const struct fsl_pm_ops *qoriq_pm_ops;
+#endif /* __KERNEL__ */
+#endif /* __PPC_FSL_PM_H */
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 2fb4b24..ae1b8a2 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
 	select FSL_PCI if PCI
 	select SERIAL_8250_EXTENDED if SERIAL_8250
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+	select FSL_CORENET_RCPM if PPC_E500MC
 	default y
 
 if FSL_SOC_BOOKE
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index a19332a..52dc165 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -40,3 +40,8 @@ config SCOM_DEBUGFS
 config GE_FPGA
 	bool
 	default n
+
+config FSL_CORENET_RCPM
+	bool
+	help
+	  This option enables support for RCPM (Run Control/Power Management).
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f7cb2a1..8bbedfd 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM)	+= fsl_rcpm.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644
index 0000000..4bd2d64
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -0,0 +1,338 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2015 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao <chenhui.zhao@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/types.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <asm/fsl_guts.h>
+#include <asm/cputhreads.h>
+#include <asm/fsl_pm.h>
+
+const struct fsl_pm_ops *qoriq_pm_ops;
+
+static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs;
+static unsigned int fsl_supported_pm_modes;
+
+static void rcpm_v1_irq_mask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	setbits32(&rcpm_v1_regs->cpmimr, mask);
+	setbits32(&rcpm_v1_regs->cpmcimr, mask);
+	setbits32(&rcpm_v1_regs->cpmmcmr, mask);
+	setbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_mask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	setbits32(&rcpm_v2_regs->tpmimr0, mask);
+	setbits32(&rcpm_v2_regs->tpmcimr0, mask);
+	setbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+	setbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v1_irq_unmask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	clrbits32(&rcpm_v1_regs->cpmimr, mask);
+	clrbits32(&rcpm_v1_regs->cpmcimr, mask);
+	clrbits32(&rcpm_v1_regs->cpmmcmr, mask);
+	clrbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_unmask(int cpu)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	clrbits32(&rcpm_v2_regs->tpmimr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmcimr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+	clrbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+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);
+}
+
+static void rcpm_v1_cpu_enter_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	switch (state) {
+	case E500_PM_PH10:
+		setbits32(&rcpm_v1_regs->cdozcr, mask);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v1_regs->cnapcr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+		break;
+	}
+}
+
+static void rcpm_v2_cpu_enter_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+	switch (state) {
+	case E500_PM_PH10:
+		/* one bit corresponds to one thread for PH10 of 6500 */
+		setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v2_regs->pcph15setr, mask);
+		break;
+	case E500_PM_PH20:
+		setbits32(&rcpm_v2_regs->pcph20setr, mask);
+		break;
+	case E500_PM_PH30:
+		setbits32(&rcpm_v2_regs->pcph30setr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+	}
+}
+
+static void rcpm_v1_cpu_exit_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	unsigned int mask = 1 << hw_cpu;
+
+	switch (state) {
+	case E500_PM_PH10:
+		clrbits32(&rcpm_v1_regs->cdozcr, mask);
+		break;
+	case E500_PM_PH15:
+		clrbits32(&rcpm_v1_regs->cnapcr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+		break;
+	}
+}
+
+static void rcpm_v2_cpu_exit_state(int cpu, int state)
+{
+	int hw_cpu = get_hard_smp_processor_id(cpu);
+	u32 mask = 1 << cpu_core_index_of_thread(hw_cpu);
+
+	switch (state) {
+	case E500_PM_PH10:
+		setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
+		break;
+	case E500_PM_PH15:
+		setbits32(&rcpm_v2_regs->pcph15clrr, mask);
+		break;
+	case E500_PM_PH20:
+		setbits32(&rcpm_v2_regs->pcph20clrr, mask);
+		break;
+	case E500_PM_PH30:
+		setbits32(&rcpm_v2_regs->pcph30clrr, mask);
+		break;
+	default:
+		pr_warn("%s: Unknown cpu PM state (%d)\n", __func__, state);
+	}
+}
+
+static int rcpm_v1_plat_enter_state(int state)
+{
+	u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
+	int ret = 0;
+	int result;
+
+	switch (state) {
+	case PLAT_PM_SLEEP:
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);
+
+		/* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
+		result = spin_event_timeout(
+		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
+		if (!result) {
+			pr_err("%s: timeout waiting for SLP bit to be cleared\n",
+			       __func__);
+			ret = -ETIMEDOUT;
+		}
+		break;
+	default:
+		pr_warn("%s: Unknown platform PM state (%d)\n",
+		       __func__, state);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rcpm_v2_plat_enter_state(int state)
+{
+	u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr;
+	int ret = 0;
+	int result;
+
+	switch (state) {
+	case PLAT_PM_LPM20:
+		/* clear previous LPM20 status */
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST);
+		/* enter LPM20 status */
+		setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ);
+
+		/* At this point, the device is in LPM20 status. */
+
+		/* resume ... */
+		result = spin_event_timeout(
+		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10);
+		if (!result) {
+			pr_err("%s: timeout waiting for LPM20 bit to be cleared\n",
+			       __func__);
+			ret = -ETIMEDOUT;
+		}
+		break;
+	default:
+		pr_warn("%s: Unknown platform PM state (%d)\n",
+		       __func__, state);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int rcpm_v1_plat_enter_sleep(void)
+{
+	return rcpm_v1_plat_enter_state(PLAT_PM_SLEEP);
+}
+
+static int rcpm_v2_plat_enter_sleep(void)
+{
+	return rcpm_v2_plat_enter_state(PLAT_PM_LPM20);
+}
+
+static void rcpm_common_freeze_time_base(u32 *tben_reg, int freeze)
+{
+	static u32 mask;
+
+	if (freeze) {
+		mask = in_be32(tben_reg);
+		clrbits32(tben_reg, mask);
+	} else {
+		setbits32(tben_reg, mask);
+	}
+
+	/* read back to push the previous write */
+	in_be32(tben_reg);
+}
+
+static void rcpm_v1_freeze_time_base(bool freeze)
+{
+	rcpm_common_freeze_time_base(&rcpm_v1_regs->ctbenr, freeze);
+}
+
+static void rcpm_v2_freeze_time_base(bool freeze)
+{
+	rcpm_common_freeze_time_base(&rcpm_v2_regs->pctbenr, freeze);
+}
+
+static unsigned int rcpm_get_pm_modes(void)
+{
+	return fsl_supported_pm_modes;
+}
+
+static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
+	.irq_mask = rcpm_v1_irq_mask,
+	.irq_unmask = rcpm_v1_irq_unmask,
+	.cpu_enter_state = rcpm_v1_cpu_enter_state,
+	.cpu_exit_state = rcpm_v1_cpu_exit_state,
+	.plat_enter_sleep = rcpm_v1_plat_enter_sleep,
+	.set_ip_power = rcpm_v1_set_ip_power,
+	.freeze_time_base = rcpm_v1_freeze_time_base,
+	.get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
+	.irq_mask = rcpm_v2_irq_mask,
+	.irq_unmask = rcpm_v2_irq_unmask,
+	.cpu_enter_state = rcpm_v2_cpu_enter_state,
+	.cpu_exit_state = rcpm_v2_cpu_exit_state,
+	.plat_enter_sleep = rcpm_v2_plat_enter_sleep,
+	.set_ip_power = rcpm_v2_set_ip_power,
+	.freeze_time_base = rcpm_v2_freeze_time_base,
+	.get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct of_device_id rcpm_matches[] = {
+	{
+		.compatible = "fsl,qoriq-rcpm-1.0",
+		.data = (void *)&qoriq_rcpm_v1_ops,
+	},
+	{
+		.compatible = "fsl,qoriq-rcpm-2.0",
+		.data = (void *)&qoriq_rcpm_v2_ops,
+	},
+	{},
+};
+
+static int __init fsl_rcpm_init(void)
+{
+	struct device_node *np;
+	const struct of_device_id *match;
+	void __iomem *base;
+
+	np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
+	if (!np) {
+		pr_err("%s: can't find the rcpm node.\n", __func__);
+		return -ENODEV;
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: of_iomap() error.\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* support sleep by default */
+	fsl_supported_pm_modes = FSL_PM_SLEEP;
+	of_node_put(np);
+
+	rcpm_v1_regs = base;
+	rcpm_v2_regs = base;
+
+	qoriq_pm_ops = match->data;
+
+	return 0;
+}
+
+/* need to call this before SMP init */
+early_initcall(fsl_rcpm_init);
-- 
2.1.0.27.g96db324

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

* Re: [PATCH v3] powerpc/rcpm: add RCPM driver
  2015-06-16  9:26 ` Yuantian.Tang
  (?)
@ 2015-06-16 18:00 ` Bob Cochran
  2015-06-17  3:48   ` Yuantian Tang
  2015-06-17 20:23   ` Scott Wood
  -1 siblings, 2 replies; 5+ messages in thread
From: Bob Cochran @ 2015-06-16 18:00 UTC (permalink / raw)
  To: Yuantian.Tang, b07421; +Cc: linuxppc-dev, Chenhui Zhao

On 06/16/2015 05:26 AM, Yuantian.Tang@freescale.com wrote:
> From: Tang Yuantian <Yuantian.Tang@freescale.com>
>
> 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.zhao@freescale.com>
> Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
> ---
> v3:
> 	- added static and __init modifier to fsl_rcpm_init
> v2:
> 	- fix code style issues
> 	- refine compatible string match part
>
>   Documentation/devicetree/bindings/soc/fsl/rcpm.txt |  22 ++
>   arch/powerpc/include/asm/fsl_guts.h                | 105 +++++++
>   arch/powerpc/include/asm/fsl_pm.h                  |  48 +++
>   arch/powerpc/platforms/85xx/Kconfig                |   1 +
>   arch/powerpc/sysdev/Kconfig                        |   5 +
>   arch/powerpc/sysdev/Makefile                       |   1 +
>   arch/powerpc/sysdev/fsl_rcpm.c                     | 338 +++++++++++++++++++++
>   7 files changed, 520 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 0000000..5318999
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
> @@ -0,0 +1,22 @@
> +* 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".


I just checked both my T1040 RM and datasheet, and I didn't see mention 
of the RCPM version that's used ( I assume it's 2.0 ).  Is there a 
general rule for which SoCs have which version?  If so, perhaps you'll 
want to include it here along with your examples.



> +
> +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>;
> +	};

-- cut ---

> diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h
> new file mode 100644
> index 0000000..4b09f09
> --- /dev/null
> +++ b/arch/powerpc/include/asm/fsl_pm.h
> @@ -0,0 +1,48 @@
> +/*
> + * Support Power Management
> + *
> + * 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.
> + */
> +#ifndef __PPC_FSL_PM_H
> +#define __PPC_FSL_PM_H
> +#ifdef __KERNEL__
> +
> +#define E500_PM_PH10	1
> +#define E500_PM_PH15	2
> +#define E500_PM_PH20	3
> +#define E500_PM_PH30	4
> +#define E500_PM_DOZE	E500_PM_PH10
> +#define E500_PM_NAP	E500_PM_PH15


Are you using "E500" in your labels for historical reasons? I can use 
this driver with E5500 and E6500 cores, right?  However, maybe I'm 
mistaken since some of your states don't seem to map to my E5500 / T1040 
(e.g., my RCPM doesn't seem to support PH20 or PH30, but I do have LPM10 
and LPM35, which I don't think your driver supports).  My RM states that 
LPM35 is a newer PM state, so maybe this is future work to be done?


> +
> +#define PLAT_PM_SLEEP	20
> +#define PLAT_PM_LPM20	30
> +
> +#define FSL_PM_SLEEP		(1 << 0)
> +#define FSL_PM_DEEP_SLEEP	(1 << 1)


I don't see where you use FSL_PM_DEEP_SLEEP, and I'm wondering if this 
was provisioned for LPM35, which is documented to be a deep sleep mode.


> +
> +struct fsl_pm_ops {
> +	/* mask pending interrupts to the RCPM from MPIC */
> +	void (*irq_mask)(int cpu);
> +
> +	/* unmask pending interrupts to the RCPM from MPIC */
> +	void (*irq_unmask)(int cpu);
> +	void (*cpu_enter_state)(int cpu, int state);
> +	void (*cpu_exit_state)(int cpu, int state);
> +	int (*plat_enter_sleep)(void);
> +	void (*freeze_time_base)(bool freeze);
> +
> +	/* keep the power of IP blocks during sleep/deep sleep */
> +	void (*set_ip_power)(bool enable, u32 *mask);
> +
> +	/* get platform supported power management modes */
> +	unsigned int (*get_pm_modes)(void);
> +};
> +
> +extern const struct fsl_pm_ops *qoriq_pm_ops;
> +#endif /* __KERNEL__ */
> +#endif /* __PPC_FSL_PM_H */

-- cut ---

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

* RE: [PATCH v3] powerpc/rcpm: add RCPM driver
  2015-06-16 18:00 ` Bob Cochran
@ 2015-06-17  3:48   ` Yuantian Tang
  2015-06-17 20:23   ` Scott Wood
  1 sibling, 0 replies; 5+ messages in thread
From: Yuantian Tang @ 2015-06-17  3:48 UTC (permalink / raw)
  To: Bob Cochran, Scott Wood; +Cc: linuxppc-dev, Zhao C.H.

UGxlYXNlIHNlZSBteSByZXBsYXkgaW5saW5lLg0KDQpUaGFua3MsDQpZdWFudGlhbg0KDQoNCj4g
LS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQm9iIENvY2hyYW4gW21haWx0bzpw
cGNAbWluZGNoYXNlcnMuY29tXQ0KPiBTZW50OiBXZWRuZXNkYXksIEp1bmUgMTcsIDIwMTUgMjow
MCBBTQ0KPiBUbzogVGFuZyBZdWFudGlhbi1CMjk5ODM7IFdvb2QgU2NvdHQtQjA3NDIxDQo+IENj
OiBsaW51eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZzsgWmhhbyBDaGVuaHVpLUIzNTMzNg0KPiBT
dWJqZWN0OiBSZTogW1BBVENIIHYzXSBwb3dlcnBjL3JjcG06IGFkZCBSQ1BNIGRyaXZlcg0KPiAN
Cj4gT24gMDYvMTYvMjAxNSAwNToyNiBBTSwgWXVhbnRpYW4uVGFuZ0BmcmVlc2NhbGUuY29tIHdy
b3RlOg0KPiA+IEZyb206IFRhbmcgWXVhbnRpYW4gPFl1YW50aWFuLlRhbmdAZnJlZXNjYWxlLmNv
bT4NCj4gPg0KPiA+IFRoZXJlIGlzIGEgUkNQTSAoUnVuIENvbnRyb2wvUG93ZXIgTWFuYWdlbWVu
dCkgaW4gRnJlZXNjYWxlIFFvcklRDQo+ID4gc2VyaWVzIHByb2Nlc3NvcnMuIFRoZSBkZXZpY2Ug
cGVyZm9ybXMgdGFza3MgYXNzb2NpYXRlZCB3aXRoIGRldmljZQ0KPiA+IHJ1biBjb250cm9sIGFu
ZCBwb3dlciBtYW5hZ2VtZW50Lg0KPiA+DQo+ID4gVGhlIGRyaXZlciBpbXBsZW1lbnRzIHNvbWUg
ZmVhdHVyZXM6IG1hc2svdW5tYXNrIGlycSwgZW50ZXIvZXhpdCBsb3cNCj4gPiBwb3dlciBzdGF0
ZXMsIGZyZWV6ZSB0aW1lIGJhc2UsIGV0Yy4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IENoZW5o
dWkgWmhhbyA8Y2hlbmh1aS56aGFvQGZyZWVzY2FsZS5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTog
VGFuZyBZdWFudGlhbiA8WXVhbnRpYW4uVGFuZ0BmcmVlc2NhbGUuY29tPg0KPiA+IC0tLQ0KPiA+
IHYzOg0KPiA+IAktIGFkZGVkIHN0YXRpYyBhbmQgX19pbml0IG1vZGlmaWVyIHRvIGZzbF9yY3Bt
X2luaXQNCj4gPiB2MjoNCj4gPiAJLSBmaXggY29kZSBzdHlsZSBpc3N1ZXMNCj4gPiAJLSByZWZp
bmUgY29tcGF0aWJsZSBzdHJpbmcgbWF0Y2ggcGFydA0KPiA+DQo+ID4gICBEb2N1bWVudGF0aW9u
L2RldmljZXRyZWUvYmluZGluZ3Mvc29jL2ZzbC9yY3BtLnR4dCB8ICAyMiArKw0KPiA+ICAgYXJj
aC9wb3dlcnBjL2luY2x1ZGUvYXNtL2ZzbF9ndXRzLmggICAgICAgICAgICAgICAgfCAxMDUgKysr
KysrKw0KPiA+ICAgYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNtL2ZzbF9wbS5oICAgICAgICAgICAg
ICAgICAgfCAgNDggKysrDQo+ID4gICBhcmNoL3Bvd2VycGMvcGxhdGZvcm1zLzg1eHgvS2NvbmZp
ZyAgICAgICAgICAgICAgICB8ICAgMSArDQo+ID4gICBhcmNoL3Bvd2VycGMvc3lzZGV2L0tjb25m
aWcgICAgICAgICAgICAgICAgICAgICAgICB8ICAgNSArDQo+ID4gICBhcmNoL3Bvd2VycGMvc3lz
ZGV2L01ha2VmaWxlICAgICAgICAgICAgICAgICAgICAgICB8ICAgMSArDQo+ID4gICBhcmNoL3Bv
d2VycGMvc3lzZGV2L2ZzbF9yY3BtLmMgICAgICAgICAgICAgICAgICAgICB8IDMzOA0KPiArKysr
KysrKysrKysrKysrKysrKysNCj4gPiAgIDcgZmlsZXMgY2hhbmdlZCwgNTIwIGluc2VydGlvbnMo
KykNCj4gPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu
ZGluZ3Mvc29jL2ZzbC9yY3BtLnR4dA0KPiA+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IGFyY2gvcG93
ZXJwYy9pbmNsdWRlL2FzbS9mc2xfcG0uaA0KPiA+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IGFyY2gv
cG93ZXJwYy9zeXNkZXYvZnNsX3JjcG0uYw0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL0RvY3VtZW50
YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9zb2MvZnNsL3JjcG0udHh0DQo+ID4gYi9Eb2N1bWVu
dGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3Mvc29jL2ZzbC9yY3BtLnR4dA0KPiA+IG5ldyBmaWxl
IG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAwMC4uNTMxODk5OQ0KPiA+IC0tLSAvZGV2L251
bGwNCj4gPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3Mvc29jL2ZzbC9y
Y3BtLnR4dA0KPiA+IEBAIC0wLDAgKzEsMjIgQEANCj4gPiArKiBSdW4gQ29udHJvbCBhbmQgUG93
ZXIgTWFuYWdlbWVudA0KPiA+ICsNCj4gPiArVGhlIFJDUE0gcGVyZm9ybXMgYWxsIGRldmljZS1s
ZXZlbCB0YXNrcyBhc3NvY2lhdGVkIHdpdGggZGV2aWNlIHJ1bg0KPiA+ICtjb250cm9sIGFuZCBw
b3dlciBtYW5hZ2VtZW50Lg0KPiA+ICsNCj4gPiArUmVxdWlyZWQgcHJvcGVyaXRlczoNCj4gPiAr
ICAtIHJlZyA6IE9mZnNldCBhbmQgbGVuZ3RoIG9mIHRoZSByZWdpc3RlciBzZXQgb2YgUkNQTSBi
bG9jay4NCj4gPiArICAtIGNvbXBhdGlibGUgOiBTcGVjaWZpZXMgdGhlIGNvbXBhdGliaWxpdHkg
bGlzdCBmb3IgdGhlIFJDUE0uIFRoZQ0KPiB0eXBlDQo+ID4gKyAgICBzaG91bGQgYmUgc3RyaW5n
LCBzdWNoIGFzICJmc2wscW9yaXEtcmNwbS0xLjAiLCAiZnNsLHFvcmlxLXJjcG0tDQo+IDIuMCIu
DQo+IA0KPiANCj4gSSBqdXN0IGNoZWNrZWQgYm90aCBteSBUMTA0MCBSTSBhbmQgZGF0YXNoZWV0
LCBhbmQgSSBkaWRuJ3Qgc2VlIG1lbnRpb24NCj4gb2YgdGhlIFJDUE0gdmVyc2lvbiB0aGF0J3Mg
dXNlZCAoIEkgYXNzdW1lIGl0J3MgMi4wICkuIElzIHRoZXJlIGENCj4gZ2VuZXJhbCBydWxlIGZv
ciB3aGljaCBTb0NzIGhhdmUgd2hpY2ggdmVyc2lvbj8gIElmIHNvLCBwZXJoYXBzIHlvdSdsbA0K
PiB3YW50IHRvIGluY2x1ZGUgaXQgaGVyZSBhbG9uZyB3aXRoIHlvdXIgZXhhbXBsZXMuDQo+IA0K
Tm8gc3VjaCBydWxlIGV4aXN0cy4gVGhlIG9ubHkgd2F5IHlvdSBjYW4gZ2V0IHRoZSBSQ1BNIHZl
cnNpb24gaXMgdG8gcmVmZXIgdG8gdGhlIERUUy4NCg0KPiANCj4gDQo+ID4gKw0KPiA+ICtFeGFt
cGxlOg0KPiA+ICtUaGUgUkNQTSBub2RlIGZvciBUNDI0MDoNCj4gPiArCXJjcG06IGdsb2JhbC11
dGlsaXRpZXNAZTIwMDAgew0KPiA+ICsJCWNvbXBhdGlibGUgPSAiZnNsLHQ0MjQwLXJjcG0iLCAi
ZnNsLHFvcmlxLXJjcG0tMi4wIjsNCj4gPiArCQlyZWcgPSA8MHhlMjAwMCAweDEwMDA+Ow0KPiA+
ICsJfTsNCj4gPiArDQo+ID4gK1RoZSBSQ1BNIG5vZGUgZm9yIFA0MDgwOg0KPiA+ICsJcmNwbTog
Z2xvYmFsLXV0aWxpdGllc0BlMjAwMCB7DQo+ID4gKwkJY29tcGF0aWJsZSA9ICJmc2wscW9yaXEt
cmNwbS0xLjAiOw0KPiA+ICsJCXJlZyA9IDwweGUyMDAwIDB4MTAwMD47DQo+ID4gKwl9Ow0KPiAN
Cj4gLS0gY3V0IC0tLQ0KPiANCj4gPiBkaWZmIC0tZ2l0IGEvYXJjaC9wb3dlcnBjL2luY2x1ZGUv
YXNtL2ZzbF9wbS5oDQo+ID4gYi9hcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vZnNsX3BtLmgNCj4g
PiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjRiMDlmMDkNCj4gPiAt
LS0gL2Rldi9udWxsDQo+ID4gKysrIGIvYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNtL2ZzbF9wbS5o
DQo+ID4gQEAgLTAsMCArMSw0OCBAQA0KPiA+ICsvKg0KPiA+ICsgKiBTdXBwb3J0IFBvd2VyIE1h
bmFnZW1lbnQNCj4gPiArICoNCj4gPiArICogQ29weXJpZ2h0IDIwMTQtMjAxNSBGcmVlc2NhbGUg
U2VtaWNvbmR1Y3RvciBJbmMuDQo+ID4gKyAqDQo+ID4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVl
IHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSAgaXQgYW5kL29yDQo+ID4gK21vZGlmeSBp
dA0KPiA+ICsgKiB1bmRlciAgdGhlIHRlcm1zIG9mICB0aGUgR05VIEdlbmVyYWwgIFB1YmxpYyBM
aWNlbnNlIGFzIHB1Ymxpc2hlZA0KPiA+ICtieSB0aGUNCj4gPiArICogRnJlZSBTb2Z0d2FyZSBG
b3VuZGF0aW9uOyAgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgIExpY2Vuc2UsIG9yDQo+ID4gKyhh
dCB5b3VyDQo+ID4gKyAqIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uDQo+ID4gKyAqLw0KPiA+
ICsjaWZuZGVmIF9fUFBDX0ZTTF9QTV9IDQo+ID4gKyNkZWZpbmUgX19QUENfRlNMX1BNX0gNCj4g
PiArI2lmZGVmIF9fS0VSTkVMX18NCj4gPiArDQo+ID4gKyNkZWZpbmUgRTUwMF9QTV9QSDEwCTEN
Cj4gPiArI2RlZmluZSBFNTAwX1BNX1BIMTUJMg0KPiA+ICsjZGVmaW5lIEU1MDBfUE1fUEgyMAkz
DQo+ID4gKyNkZWZpbmUgRTUwMF9QTV9QSDMwCTQNCj4gPiArI2RlZmluZSBFNTAwX1BNX0RPWkUJ
RTUwMF9QTV9QSDEwDQo+ID4gKyNkZWZpbmUgRTUwMF9QTV9OQVAJRTUwMF9QTV9QSDE1DQo+IA0K
PiANCj4gQXJlIHlvdSB1c2luZyAiRTUwMCIgaW4geW91ciBsYWJlbHMgZm9yIGhpc3RvcmljYWwg
cmVhc29ucz8gSSBjYW4gdXNlDQo+IHRoaXMgZHJpdmVyIHdpdGggRTU1MDAgYW5kIEU2NTAwIGNv
cmVzLCByaWdodD8gIEhvd2V2ZXIsIG1heWJlIEknbQ0KPiBtaXN0YWtlbiBzaW5jZSBzb21lIG9m
IHlvdXIgc3RhdGVzIGRvbid0IHNlZW0gdG8gbWFwIHRvIG15IEU1NTAwIC8gVDEwNDANCj4gKGUu
Zy4sIG15IFJDUE0gZG9lc24ndCBzZWVtIHRvIHN1cHBvcnQgUEgyMCBvciBQSDMwLCBidXQgSSBk
byBoYXZlIExQTTEwDQo+IGFuZCBMUE0zNSwgd2hpY2ggSSBkb24ndCB0aGluayB5b3VyIGRyaXZl
ciBzdXBwb3J0cykuICBNeSBSTSBzdGF0ZXMgdGhhdA0KPiBMUE0zNSBpcyBhIG5ld2VyIFBNIHN0
YXRlLCBzbyBtYXliZSB0aGlzIGlzIGZ1dHVyZSB3b3JrIHRvIGJlIGRvbmU/DQo+IA0KVGhlc2Ug
YXJlIGFsbCB0aGUgUE0gc3RhdGVzIGZvciBFNTAwIHNlcmllcyBzb2NzLiBUaGUgc3RhdGVzIGEg
Ym9hcmQgc3VwcG9ydHMgYXJlIGZyb20gb25lIHRvIHRoZSBvdGhlci4NClQxMDQwIGFuZCBzb21l
IG90aGVyIHBsYXRmb3JtcyBzdXBwb3J0IExQTTM1IHdoaWNoIHdpbGwgYmUgaW1wbGVtZW50ZWQg
aW4gZnV0dXJlIHBhdGNoLg0KDQpSZWdhcmRzLA0KWXVhbnRpYW4NCg0KPiANCj4gPiArDQo+ID4g
KyNkZWZpbmUgUExBVF9QTV9TTEVFUAkyMA0KPiA+ICsjZGVmaW5lIFBMQVRfUE1fTFBNMjAJMzAN
Cj4gPiArDQo+ID4gKyNkZWZpbmUgRlNMX1BNX1NMRUVQCQkoMSA8PCAwKQ0KPiA+ICsjZGVmaW5l
IEZTTF9QTV9ERUVQX1NMRUVQCSgxIDw8IDEpDQo+IA0KPiANCj4gSSBkb24ndCBzZWUgd2hlcmUg
eW91IHVzZSBGU0xfUE1fREVFUF9TTEVFUCwgYW5kIEknbSB3b25kZXJpbmcgaWYgdGhpcw0KPiB3
YXMgcHJvdmlzaW9uZWQgZm9yIExQTTM1LCB3aGljaCBpcyBkb2N1bWVudGVkIHRvIGJlIGEgZGVl
cCBzbGVlcCBtb2RlLg0KPiANCj4gDQo+ID4gKw0KPiA+ICtzdHJ1Y3QgZnNsX3BtX29wcyB7DQo+
ID4gKwkvKiBtYXNrIHBlbmRpbmcgaW50ZXJydXB0cyB0byB0aGUgUkNQTSBmcm9tIE1QSUMgKi8N
Cj4gPiArCXZvaWQgKCppcnFfbWFzaykoaW50IGNwdSk7DQo+ID4gKw0KPiA+ICsJLyogdW5tYXNr
IHBlbmRpbmcgaW50ZXJydXB0cyB0byB0aGUgUkNQTSBmcm9tIE1QSUMgKi8NCj4gPiArCXZvaWQg
KCppcnFfdW5tYXNrKShpbnQgY3B1KTsNCj4gPiArCXZvaWQgKCpjcHVfZW50ZXJfc3RhdGUpKGlu
dCBjcHUsIGludCBzdGF0ZSk7DQo+ID4gKwl2b2lkICgqY3B1X2V4aXRfc3RhdGUpKGludCBjcHUs
IGludCBzdGF0ZSk7DQo+ID4gKwlpbnQgKCpwbGF0X2VudGVyX3NsZWVwKSh2b2lkKTsNCj4gPiAr
CXZvaWQgKCpmcmVlemVfdGltZV9iYXNlKShib29sIGZyZWV6ZSk7DQo+ID4gKw0KPiA+ICsJLyog
a2VlcCB0aGUgcG93ZXIgb2YgSVAgYmxvY2tzIGR1cmluZyBzbGVlcC9kZWVwIHNsZWVwICovDQo+
ID4gKwl2b2lkICgqc2V0X2lwX3Bvd2VyKShib29sIGVuYWJsZSwgdTMyICptYXNrKTsNCj4gPiAr
DQo+ID4gKwkvKiBnZXQgcGxhdGZvcm0gc3VwcG9ydGVkIHBvd2VyIG1hbmFnZW1lbnQgbW9kZXMg
Ki8NCj4gPiArCXVuc2lnbmVkIGludCAoKmdldF9wbV9tb2Rlcykodm9pZCk7DQo+ID4gK307DQo+
ID4gKw0KPiA+ICtleHRlcm4gY29uc3Qgc3RydWN0IGZzbF9wbV9vcHMgKnFvcmlxX3BtX29wczsN
Cj4gPiArI2VuZGlmIC8qIF9fS0VSTkVMX18gKi8NCj4gPiArI2VuZGlmIC8qIF9fUFBDX0ZTTF9Q
TV9IICovDQo+IA0KPiAtLSBjdXQgLS0tDQo+IA0KDQo=

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

* Re: [PATCH v3] powerpc/rcpm: add RCPM driver
  2015-06-16 18:00 ` Bob Cochran
  2015-06-17  3:48   ` Yuantian Tang
@ 2015-06-17 20:23   ` Scott Wood
  1 sibling, 0 replies; 5+ messages in thread
From: Scott Wood @ 2015-06-17 20:23 UTC (permalink / raw)
  To: Bob Cochran; +Cc: Yuantian.Tang, b07421, linuxppc-dev, Chenhui Zhao

On Tue, 2015-06-16 at 14:00 -0400, Bob Cochran wrote:
> On 06/16/2015 05:26 AM,  Yuantian.Tang@freescale.comwrote:
> > From: Tang Yuantian <Yuantian.Tang@freescale.com>
> > 
> > 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.zhao@freescale.com>
> > Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
> > ---
> > v3:
> >     - added static and __init modifier to fsl_rcpm_init
> > v2:
> >     - fix code style issues
> >     - refine compatible string match part
> > 
> >   Documentation/devicetree/bindings/soc/fsl/rcpm.txt |  22 ++
> >   arch/powerpc/include/asm/fsl_guts.h                | 105 +++++++
> >   arch/powerpc/include/asm/fsl_pm.h                  |  48 +++
> >   arch/powerpc/platforms/85xx/Kconfig                |   1 +
> >   arch/powerpc/sysdev/Kconfig                        |   5 +
> >   arch/powerpc/sysdev/Makefile                       |   1 +
> >   arch/powerpc/sysdev/fsl_rcpm.c                     | 338 
> > +++++++++++++++++++++
> >   7 files changed, 520 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 0000000..5318999
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
> > @@ -0,0 +1,22 @@
> > +* 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".
> 
> 
> I just checked both my T1040 RM and datasheet, and I didn't see 
> mention 
> of the RCPM version that's used ( I assume it's 2.0 ).  Is there a 
> general rule for which SoCs have which version?  If so, perhaps 
> you'll 
> want to include it here along with your examples.

It should be the same as the list in 
Documentation/devicetree/bindings/clock/qoriq-clock.txt, but yes, it'd 
be good to include it here.  FWIW, while T1040 is often labelled as 
having "2.0" blocks, it's not quite the same (e.g. the clock block is 
missing CLKCGnHWACSR) and should probably be labelled something else.

There should also be a sperific-chip compatible (which is shown in the 
t4240 example, but not in the p4080 example or the property 
description).

+
> > +#define E500_PM_PH10       1
> > +#define E500_PM_PH15       2
> > +#define E500_PM_PH20       3
> > +#define E500_PM_PH30       4
> > +#define E500_PM_DOZE       E500_PM_PH10
> > +#define E500_PM_NAP        E500_PM_PH15
> 
> 
> Are you using "E500" in your labels for historical reasons? I can 
> use 
> this driver with E5500 and E6500 cores, right? 

We often use "e500" to refer to the entire family of e500 derivatives.

> However, maybe I'm 
> mistaken since some of your states don't seem to map to my E5500 / 
> T1040 
> (e.g., my RCPM doesn't seem to support PH20 or PH30, but I do have 
> LPM10 
> and LPM35, which I don't think your driver supports).  My RM states 
> that 
> LPM35 is a newer PM state, so maybe this is future work to be done?

PH20 and PH30 were introduced in e6500.

-Scott

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

end of thread, other threads:[~2015-06-17 20:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-16  9:26 [PATCH v3] powerpc/rcpm: add RCPM driver Yuantian.Tang
2015-06-16  9:26 ` Yuantian.Tang
2015-06-16 18:00 ` Bob Cochran
2015-06-17  3:48   ` Yuantian Tang
2015-06-17 20:23   ` Scott Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.