[PATCH] [1/2] PM support for Ebony
Geoff Levand
geoffrey.levand at am.sony.com
Sat Jun 4 09:22:40 EST 2005
I rebased this to apply to Benjamin's ppc32-rework-pm.diff, but
didn't recode it to take advantage of the extra hooks. More work
is certainly needed for wake-on-lan. Any comments on improvement
would be most welcome.
I could also make one available against a 2.6.12-rc if requested.
-Geoff
* pm-on-ebony.patch
This patch provides power management support for the IBM PPC440GP Ebony
Reference Platform. The main portion of the patch implements the platform
specific pm_ops structure required by the kernel power management sub-system.
The current implementation only supports suspend-to-memory (PM_SUSPEND_MEM),
though unpublished suspend-to-disk work has been started.
This implementation arranges for the U44 switch on the Ebony platform,
connected to the SMI interrupt handler, to be used as a system resume trigger.
Signed-off-by: Geoff Levand <geoffrey.levand at am.sony.com> for CELF
--
Index: linux-2.6.12-bhpm/arch/ppc/platforms/4xx/Kconfig
===================================================================
--- linux-2.6.12-bhpm.orig/arch/ppc/platforms/4xx/Kconfig 2005-06-03 16:14:44.000000000 -0700
+++ linux-2.6.12-bhpm/arch/ppc/platforms/4xx/Kconfig 2005-06-03 16:15:07.000000000 -0700
@@ -214,10 +214,6 @@
depends on 4xx
default y
-config PM
- bool "Power Management support (EXPERIMENTAL)"
- depends on 4xx && EXPERIMENTAL
-
choice
prompt "TTYS0 device and default console"
depends on 40x
Index: linux-2.6.12-bhpm/arch/ppc/platforms/4xx/Makefile
===================================================================
--- linux-2.6.12-bhpm.orig/arch/ppc/platforms/4xx/Makefile 2005-06-03 16:14:44.000000000 -0700
+++ linux-2.6.12-bhpm/arch/ppc/platforms/4xx/Makefile 2005-06-03 16:15:07.000000000 -0700
@@ -25,3 +25,6 @@
obj-$(CONFIG_405EP) += ibm405ep.o
obj-$(CONFIG_405GPR) += ibm405gpr.o
obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o
+ifeq ($(CONFIG_PM),y)
+obj-$(CONFIG_EBONY) += ebony_pm.o ibm440gp_sleep.o
+endif
Index: linux-2.6.12-bhpm/arch/ppc/platforms/4xx/ebony_pm.c
===================================================================
--- linux-2.6.12-bhpm.orig/arch/ppc/platforms/4xx/ebony_pm.c 2005-06-01 08:52:49.947684744 -0700
+++ linux-2.6.12-bhpm/arch/ppc/platforms/4xx/ebony_pm.c 2005-06-03 16:15:07.000000000 -0700
@@ -0,0 +1,202 @@
+/*
+ * ebony_pm.c - This file contains the PM functions for Ebony.
+ *
+ * Copyright 2004 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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/types.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <asm/ibm44x.h>
+
+#define IBM_CPM_ALL (IBM_CPM_IIC0 | IBM_CPM_IIC1 | IBM_CPM_PCI | \
+ IBM_CPM_CPU | IBM_CPM_DMA | IBM_CPM_BGO | IBM_CPM_BGI | \
+ IBM_CPM_EBC | IBM_CPM_EBM | IBM_CPM_DMC | IBM_CPM_PLB | IBM_CPM_SRAM | \
+ IBM_CPM_PPM | IBM_CPM_UIC1 | IBM_CPM_GPIO0 | IBM_CPM_UART0 | IBM_CPM_UART1 | \
+ IBM_CPM_UIC0 | IBM_CPM_TMRCLK )
+
+#define UIC0_EIR5_BIT (1<<(31-28)) /* External Intr 5 == SMI */
+#define UIC0_UIC1NC_BIT (1<<(31-30))
+
+extern void serial8250_suspend_port_busy(int line);
+extern void serial8250_resume_port_busy(int line);
+
+void ibm440gp_sleep(__u32 CPM, __u32 MSR_OR);
+
+#define DEBUG
+
+#ifdef DEBUG
+
+/* #define USE_ETHER_TO_RESUME */
+
+static int __tm_printk(const char *fmt, ...)
+{
+ char buf[512];
+ va_list args;
+ int i;
+ unsigned long long tt;
+ unsigned long us, ms;
+
+ tt = sched_clock();
+ ms = tt >> 10; /* convert to usec */
+ us = ms % 1000;
+ ms = ms / 1000;
+
+ i = sprintf(buf, "%6.6lu.%3.3lums:", ms,us);
+ va_start(args, fmt);
+ i = vsnprintf(buf+i, sizeof(buf)-i, fmt, args);
+ va_end(args);
+ printk(buf);
+
+ return i;
+}
+
+#endif /* DEBUG */
+
+
+/*
+ * PM ops for EBONY board.
+ */
+
+static int ebony_pm_enter(suspend_state_t state)
+{
+ __u32 uic_save_er;
+ __u32 save_msr;
+ __u32 cpm_save_er;
+ __u32 cpm_er;
+
+ if (state != PM_SUSPEND_MEM)
+ return -EINVAL;
+
+ /* Save MSR and Stop all interrupts */
+ save_msr = mfmsr();
+ _nmask_and_or_msr((MSR_CE|MSR_EE), 0);
+
+ /* save current CPM */
+ cpm_save_er = mfdcr(DCRN_CPC0_ER);
+
+ /* save UIC0 enable registers */
+ uic_save_er = mfdcr(DCRN_UIC_ER(UIC0));
+
+#ifdef USE_ETHER_TO_RESUME
+ mtdcr(DCRN_UIC_ER(UIC0), UIC0_EIR5_BIT|UIC0_UIC1NC_BIT);
+#else
+ /* mask UIC0 interrupts, except External Intr #5 */
+ mtdcr(DCRN_UIC_ER(UIC0), UIC0_EIR5_BIT);
+#endif
+
+#ifdef DEBUG
+ __tm_printk("UIC0_ER:0x%8.8x -> 0x%8.8x\n",uic_save_er, mfdcr(DCRN_UIC_ER(UIC0)));
+#endif
+
+ /* set up CPM */
+ cpm_er = IBM_CPM_ALL & ~IBM_CPM_UIC0;
+#ifdef USE_ETHER_TO_RESUME
+ cpm_er &= ~CPM_UIC1;
+#endif
+
+#ifdef DEBUG
+ __tm_printk("UIC0_SR:0x%8.8x\n", mfdcr(DCRN_UIC_SR(UIC0)));
+ __tm_printk("CPM_ER:0x%8.8x\n", cpm_er);
+ __tm_printk("SLEEP\n");
+#endif
+
+ /* we need this to work with printk on serial console */
+ serial8250_suspend_port_busy(0);
+
+ /* Enable interrupts and Enter SLEEP mode */
+ ibm440gp_sleep(cpm_er, (MSR_EE|MSR_WE));
+
+ /* Stop all interrupts, again */
+ _nmask_and_or_msr((MSR_CE|MSR_EE), 0);
+
+ /* Restore CPM, before resume serials for printk() */
+ mtdcr(DCRN_CPC0_ER, cpm_save_er);
+
+ /* we need this to work with printk on serial console */
+ serial8250_resume_port_busy(0);
+
+ __tm_printk("WAKEUP\n");
+
+ /* Restore UIC0 enable registers */
+ mtdcr(DCRN_UIC_ER(UIC0), uic_save_er);
+
+ /* Restore MSR */
+ mtmsr(save_msr);
+
+ return 0;
+}
+
+static int ebony_pm_prepare(suspend_state_t state)
+{
+
+ if (state != PM_SUSPEND_MEM)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int ebony_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+static struct pm_ops ebony_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .prepare = ebony_pm_prepare,
+ .enter = ebony_pm_enter,
+ .finish = ebony_pm_finish,
+};
+
+static int __init ebony_pm_init(void)
+{
+ pm_set_ops(&ebony_pm_ops);
+ return 0;
+}
+
+late_initcall(ebony_pm_init);
+
+/*
+ * SMI handler for resume
+ */
+
+#define PPC440GP_EXT_INT5_INTR 28 /* SMI: See ebony.c */
+
+static irqreturn_t
+smi_handler(int cpl, void *dev_id, struct pt_regs *regs)
+{
+#ifdef DEBUG
+ printk("SMI INTR\n");
+#endif
+ return IRQ_HANDLED;
+}
+
+static int __init init_smi(void)
+{
+ /* Enable SMI interrupt */
+ if (request_irq(PPC440GP_EXT_INT5_INTR, smi_handler,
+ SA_INTERRUPT, "SMI", NULL)) {
+ printk(KERN_ERR "SMI: cannot register IRQ:%d\n", PPC440GP_EXT_INT5_INTR);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+late_initcall(init_smi);
+
+
Index: linux-2.6.12-bhpm/arch/ppc/platforms/4xx/ibm440gp_sleep.S
===================================================================
--- linux-2.6.12-bhpm.orig/arch/ppc/platforms/4xx/ibm440gp_sleep.S 2005-06-01 08:52:49.947684744 -0700
+++ linux-2.6.12-bhpm/arch/ppc/platforms/4xx/ibm440gp_sleep.S 2005-06-03 16:15:07.000000000 -0700
@@ -0,0 +1,44 @@
+/*
+ * ibm440gp_sleep.S - This file contains the sleep function for 440GP CPU.
+ *
+ * Copyright 2004 Sony Corp.
+ *
+ * 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.
+ *
+ * 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/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+
+
+ .text
+
+/*
+ * ibm440gp_sleep (CPC0_ER_VAL, MSR_OR_VAL)
+ * r3: new CPC0_ER value
+ * r4: MSR value to be OR
+ */
+_GLOBAL(ibm440gp_sleep)
+ mfmsr r0
+ or r0,r0,r4
+ sync
+ mtdcr 177,r3 // 177: DCRN_CPC0_ER
+ sync
+ mtmsr r0
+ sync
+
+ blr
+
+
Index: linux-2.6.12-bhpm/include/asm-ppc/ocp.h
===================================================================
--- linux-2.6.12-bhpm.orig/include/asm-ppc/ocp.h 2005-06-03 16:14:44.000000000 -0700
+++ linux-2.6.12-bhpm/include/asm-ppc/ocp.h 2005-06-03 16:15:07.000000000 -0700
@@ -151,13 +151,21 @@
static inline void
ocp_force_power_off(struct ocp_device *odev)
{
+#ifdef CONFIG_44x
+ mtdcr(DCRN_CPC0_FR, mfdcr(DCRN_CPC0_FR) | odev->def->pm);
+#else
mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm);
+#endif
}
static inline void
ocp_force_power_on(struct ocp_device *odev)
{
+#ifdef CONFIG_44x
+ mtdcr(DCRN_CPC0_FR, mfdcr(DCRN_CPC0_FR) & ~odev->def->pm);
+#else
mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->def->pm);
+#endif
}
#else
#define ocp_force_power_off(x) (void)(x)
-EOF
More information about the Linuxppc-embedded
mailing list