[PATCH 1/3] Powerpc/4xx: Add suspend and idle support

Josh Boyer jwboyer at linux.vnet.ibm.com
Sat Oct 9 00:46:00 EST 2010


On Thu, Oct 07, 2010 at 12:07:16PM -0700, Victor Gallardo wrote:

I hit send too soon on my earlier response.  My apologies.

>--- /dev/null
>+++ b/arch/powerpc/sysdev/ppc4xx_cpm.c
>@@ -0,0 +1,339 @@
>+/*
>+ * PowerPC 4xx Clock and Power Management
>+ *
>+ * Copyright (C) 2010, Applied Micro Circuits Corporation
>+ * Victor Gallardo (vgallardo at apm.com)
>+ *
>+ * Based on arch/powerpc/platforms/44x/idle.c:
>+ * Jerone Young <jyoung5 at us.ibm.com>
>+ * Copyright 2008 IBM Corp.
>+ *
>+ * Based on arch/powerpc/sysdev/fsl_pmc.c:
>+ * Anton Vorontsov <avorontsov at ru.mvista.com>
>+ * Copyright 2009  MontaVista Software, Inc.
>+ *
>+ * See file CREDITS for list of people who contributed to this
>+ * project.
>+ *
>+ * This program is free software; you can redistribute it and/or
>+ * modify it under the terms of the GNU General Public License as
>+ * published by the Free Software Foundation; either version 2 of
>+ * the License, or (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
>+ * MA 02111-1307 USA
>+ */
>+
>+#include <linux/kernel.h>
>+#include <linux/of_platform.h>
>+#include <linux/sysfs.h>
>+#include <linux/cpu.h>
>+#include <linux/suspend.h>
>+#include <asm/dcr.h>
>+#include <asm/dcr-native.h>
>+#include <asm/machdep.h>
>+
>+#define CPM_ER	0
>+#define CPM_FR	1
>+#define CPM_SR	2
>+
>+#define CPM_IDLE_WAIT	0
>+#define CPM_IDLE_DOZE	1
>+
>+struct cpm {
>+	dcr_host_t	dcr_host;
>+	unsigned int	dcr_offset[3];
>+	unsigned int	powersave_off;
>+	unsigned int	unused;
>+	unsigned int	idle_doze;
>+	unsigned int	standby;
>+	unsigned int	suspend;
>+};
>+
>+static struct cpm cpm;
>+
>+struct cpm_idle_mode {
>+	unsigned int enabled;
>+	const char  *name;
>+};
>+
>+static struct cpm_idle_mode idle_mode[] = {
>+	[CPM_IDLE_WAIT] = { 1, "wait" }, /* default */
>+	[CPM_IDLE_DOZE] = { 0, "doze" },
>+};
>+
>+static void cpm_set(unsigned int cpm_reg, unsigned int mask)
>+{
>+	unsigned int value;
>+
>+	value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]);
>+	value |= mask;
>+	dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value);
>+}

This doesn't seem to do any sort of verification that the class 2 and
class 3 devices actually got disabled.  Or at least I don't see where we
verify anything in the SR.

Maybe in practice it doesn't matter, but we should add a comment that say
we just expect them to eventually go off when they can.

>+
>+static void cpm_idle_wait(void)
>+{
>+	unsigned long msr_save;
>+
>+	/* save off initial state */
>+	msr_save = mfmsr();
>+	/* sync required when CPM0_ER[CPU] is set */
>+	mb();
>+	/* set wait state MSR */
>+	mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE);
>+	isync();
>+	/* return to initial state */
>+	mtmsr(msr_save);
>+	isync();
>+}
>+
>+static void cpm_idle_sleep(unsigned int mask)
>+{
>+	unsigned int er_save;
>+
>+	/* update CPM_ER state */
>+	er_save = dcr_read(cpm.dcr_host, cpm.dcr_offset[CPM_ER]);
>+	dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER],
>+		  er_save | mask);
>+
>+	/* go to wait state */
>+	cpm_idle_wait();
>+
>+	/* restore CPM_ER state */
>+	dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save);
>+}

For my clarification, the CPU is a class 2 device and we expect that the
logic between the CPU and the CPM allows us to do the write to make it
sleep, but not actually sleep until we set the idle state?

josh


More information about the Linuxppc-dev mailing list