All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] MPC5200 and Lite5200b low power modes
@ 2007-03-01  7:53 Domen Puncer
  2007-03-01  7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
                   ` (9 more replies)
  0 siblings, 10 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:53 UTC (permalink / raw)
  To: linuxppc-embedded

Hi!

Patches are based on latest mainline git tree + fec patches:
Fec_MPC5200_eth_driver.patch
Copy_bestcomm_support_files_into_arch_powerpc.patch
Make_FEC_work_on_the_lite5200.patch


This patchset includes the following patches:
- [PATCH 1/7] mpc52xx suspend: bestcomm
- [PATCH 2/7] mpc52xx suspend: UART
- [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
- [PATCH 4/7] mpc52xx suspend: USB
- [PATCH 5/7] mpc52xx suspend: deep-sleep
- [PATCH 6/7] lite5200b suspend: PIC
- [u-boot patch] support lite5200b wakeup in u-boot
- [PATCH 7/7] lite5200b suspend: low-power mode


I would appreaciate any comments, suggestions etc.


	Domen

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

* [PATCH 1/7] mpc52xx suspend: bestcomm
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-01  7:54 ` Domen Puncer
  2007-03-01  7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:54 UTC (permalink / raw)
  To: linuxppc-embedded

Save and restore bestcomm registers and SRAM.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/arch/powerpc/platforms/52xx/bestcomm.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/bestcomm.c
+++ grant.git/arch/powerpc/platforms/52xx/bestcomm.c
@@ -395,4 +395,75 @@ EXPORT_SYMBOL(sdma_set_initiator);
 EXPORT_SYMBOL(sdma_free);
 EXPORT_SYMBOL(sdma);
 
+#ifdef CONFIG_PM
+static struct mpc52xx_sdma sdma_regs;
+static char saved_sram[0x4000]; /* copy of 16kB internal SRAM */
 
+int mpc52xx_sdma_suspend(void)
+{
+	int i;
+
+	sdma_regs.taskBar =	in_be32(&sdma.io->taskBar);
+	sdma_regs.currentPointer = in_be32(&sdma.io->currentPointer);
+	sdma_regs.endPointer =	in_be32(&sdma.io->endPointer);
+	sdma_regs.variablePointer = in_be32(&sdma.io->variablePointer);
+	sdma_regs.IntVect1 =	in_8(&sdma.io->IntVect1);
+	sdma_regs.IntVect2 =	in_8(&sdma.io->IntVect2);
+	sdma_regs.PtdCntrl =	in_be16(&sdma.io->PtdCntrl);
+	sdma_regs.IntPend =	in_be32(&sdma.io->IntPend);
+	sdma_regs.IntMask =	in_be32(&sdma.io->IntMask);
+
+	for (i=0; i<16; i++)
+		sdma_regs.tcr[i] = in_be16(&sdma.io->tcr[i]);
+	for (i=0; i<32; i++)
+		sdma_regs.ipr[i] = in_8(&sdma.io->ipr[i]);
+
+	sdma_regs.cReqSelect =	in_be32(&sdma.io->cReqSelect);
+	sdma_regs.task_size0 = in_be32(&sdma.io->task_size0);
+	sdma_regs.task_size1 = in_be32(&sdma.io->task_size1);
+	sdma_regs.MDEDebug =	in_be32(&sdma.io->MDEDebug);
+	sdma_regs.ADSDebug =	in_be32(&sdma.io->ADSDebug);
+	sdma_regs.Value1 =	in_be32(&sdma.io->Value1);
+	sdma_regs.Value2 =	in_be32(&sdma.io->Value2);
+	sdma_regs.Control =	in_be32(&sdma.io->Control);
+	sdma_regs.Status =	in_be32(&sdma.io->Status);
+	sdma_regs.PTDDebug =	in_be32(&sdma.io->PTDDebug);
+
+	memcpy(saved_sram, sdma.sram, sdma.sram_size);
+	return 0;
+}
+
+int mpc52xx_sdma_resume(void)
+{
+	int i;
+
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+	out_be32(&sdma.io->taskBar, sdma_regs.taskBar);
+	out_be32(&sdma.io->currentPointer, sdma_regs.currentPointer);
+	out_be32(&sdma.io->endPointer, sdma_regs.endPointer);
+	out_be32(&sdma.io->variablePointer, sdma_regs.variablePointer);
+	out_8(&sdma.io->IntVect1, sdma_regs.IntVect1);
+	out_8(&sdma.io->IntVect2, sdma_regs.IntVect2);
+	out_be16(&sdma.io->PtdCntrl, sdma_regs.PtdCntrl);
+	out_be32(&sdma.io->IntPend, sdma_regs.IntPend);
+	out_be32(&sdma.io->IntMask, sdma_regs.IntMask);
+
+	for (i=0; i<16; i++)
+		out_be16(&sdma.io->tcr[i], sdma_regs.tcr[i]);
+	for (i=0; i<32; i++)
+		out_8(&sdma.io->ipr[i], sdma_regs.ipr[i]);
+
+	out_be32(&sdma.io->cReqSelect, sdma_regs.cReqSelect);
+	out_be32(&sdma.io->task_size0, sdma_regs.task_size0);
+	out_be32(&sdma.io->task_size1, sdma_regs.task_size1);
+	out_be32(&sdma.io->MDEDebug, sdma_regs.MDEDebug);
+	out_be32(&sdma.io->ADSDebug, sdma_regs.ADSDebug);
+	out_be32(&sdma.io->Value1, sdma_regs.Value1);
+	out_be32(&sdma.io->Value2, sdma_regs.Value2);
+	out_be32(&sdma.io->Control, sdma_regs.Control);
+	out_be32(&sdma.io->Status, sdma_regs.Status);
+	out_be32(&sdma.io->PTDDebug, sdma_regs.PTDDebug);
+	return 0;
+}
+#endif
Index: grant.git/arch/powerpc/platforms/52xx/bestcomm.h
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/bestcomm.h
+++ grant.git/arch/powerpc/platforms/52xx/bestcomm.h
@@ -473,6 +473,11 @@ extern void *sdma_sram_alloc(int size, i
 extern void sdma_init_bd(struct sdma *s);
 extern void sdma_init_bd2(struct sdma *s);
 
+#ifdef CONFIG_PM
+extern int mpc52xx_sdma_suspend(void);
+extern int mpc52xx_sdma_resume(void);
+#endif
+
 #define FIELD_OFFSET(s,f) ((unsigned long)(&(((struct s*)0)->f)))
 
 #endif  /* __BESTCOMM_BESTCOMM_H__ */

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

* [PATCH 2/7] mpc52xx suspend: UART
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
  2007-03-01  7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
@ 2007-03-01  7:55 ` Domen Puncer
  2007-03-01  7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:55 UTC (permalink / raw)
  To: linuxppc-embedded

MPC52xx uart power management.
Not sure how exactly this should be written, but this seems
to work, and works around a few seconds delay in resume.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/drivers/serial/mpc52xx_uart.c
===================================================================
--- grant.git.orig/drivers/serial/mpc52xx_uart.c
+++ grant.git/drivers/serial/mpc52xx_uart.c
@@ -418,6 +418,22 @@ mpc52xx_uart_verify_port(struct uart_por
 	return 0;
 }
 
+/* just Reenable TX and RX */
+static void mpc52xx_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+	struct mpc52xx_psc __iomem *psc = PSC(port);
+	unsigned long flags;
+
+	/* Get the lock */
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Reenable TX & RX */
+	out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
+	out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
+
+	/* We're all set, release the lock */
+	spin_unlock_irqrestore(&port->lock, flags);
+}
 
 static struct uart_ops mpc52xx_uart_ops = {
 	.tx_empty	= mpc52xx_uart_tx_empty,
@@ -432,8 +448,10 @@ static struct uart_ops mpc52xx_uart_ops 
 	.startup	= mpc52xx_uart_startup,
 	.shutdown	= mpc52xx_uart_shutdown,
 	.set_termios	= mpc52xx_uart_set_termios,
-/*	.pm		= mpc52xx_uart_pm,		Not supported yet */
-/*	.set_wake	= mpc52xx_uart_set_wake,	Not supported yet */
+
+	.pm		= mpc52xx_uart_pm,
+/*	.set_wake	= mpc52xx_uart_set_wake,*/
+
 	.type		= mpc52xx_uart_type,
 	.release_port	= mpc52xx_uart_release_port,
 	.request_port	= mpc52xx_uart_request_port,

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

* [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
  2007-03-01  7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
  2007-03-01  7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
@ 2007-03-01  7:55 ` Domen Puncer
  2007-03-01  7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:55 UTC (permalink / raw)
  To: linuxppc-embedded

Suspend and resume for FEC on MPC52xx.

It just turns off (and on) leds, and even this in a hackish way.
The right way is probably to figure out how BMCR_PDOWN works.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/drivers/net/fec_mpc52xx/fec.c
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec.c
+++ grant.git/drivers/net/fec_mpc52xx/fec.c
@@ -801,6 +801,58 @@ mpc52xx_fec_remove(struct device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+int mpc52xx_fec_suspend(struct of_device *op, pm_message_t state)
+{
+	struct net_device *ndev = dev_get_drvdata(&op->dev);
+	struct fec_priv *priv = ndev->priv;
+	struct mpc52xx_fec *fec = priv->fec;
+
+	netif_stop_queue(ndev);
+	out_be32(&fec->imask, 0x0);
+
+	/* Disable the rx and tx tasks. */
+	sdma_disable(priv->rx_sdma);
+	sdma_disable(priv->tx_sdma);
+
+	fec_free_rx_buffers(priv->rx_sdma);
+
+	/* Stop FEC */
+	out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~0x2);
+
+	fec_mii_suspend(ndev);
+
+	return 0;
+}
+
+int mpc52xx_fec_resume(struct of_device *op)
+{
+	struct net_device *ndev = dev_get_drvdata(&op->dev);
+	struct fec_priv *priv = ndev->priv;
+	struct mpc52xx_fec *fec = priv->fec;
+
+	//fec_mii_resume(ndev);
+
+	fec_mii_init(ndev);
+
+	fec_hw_init(ndev);
+
+	/* restore leds. ugly hack, but fec_mii_resume doesn't work for me */
+	out_be32(&fec->mii_data, 0x50020000 | (0x14 << 18) | 0x0422);
+
+	/* Restart the DMA tasks */
+	sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo, FEC_RX_BUFFER_SIZE);
+	sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
+
+	if (priv->sequence_done) {		 /* redo the fec_open() */
+		fec_free_rx_buffers(priv->rx_sdma);
+		fec_open(ndev);
+	}
+
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_PPC_MERGE)
 static struct of_device_id mpc52xx_fec_of_match[] = {
 	{ .compatible = "mpc5200-ethernet", },
@@ -815,8 +867,8 @@ static struct of_platform_driver mpc52xx
 	.probe = mpc52xx_fec_probe,
 	.remove = mpc52xx_fec_remove,
 #ifdef CONFIG_PM
-/*	.suspend = mpc52xx_fec_suspend, TODO */
-/*	.resume = mpc52xx_fec_resume, TODO */
+	.suspend = mpc52xx_fec_suspend,
+	.resume = mpc52xx_fec_resume,
 #endif
 	.driver = {
 		.name = DRIVER_NAME,
Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.c
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.c
+++ grant.git/drivers/net/fec_mpc52xx/fec_phy.c
@@ -77,6 +77,7 @@ static int mii_queue(struct net_device *
 #define MII_REG_ANER	 6	/* A-N Expansion Register */
 #define MII_REG_ANNPTR	 7	/* A-N Next Page Transmit Register */
 #define MII_REG_ANLPRNPR 8	/* A-N Link Partner Received Next Page Reg. */
+#define MII_REG_LED	20	/* LED Configuration Register */
 
 /* values for phy_status */
 
@@ -527,6 +528,23 @@ int fec_mii_wait(struct net_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+phy_cmd_t phy_cmd_leds_off[] ={ { mk_mii_write(MII_REG_LED, 0x9992), NULL },
+				{ mk_mii_end, } };
+phy_cmd_t phy_cmd_leds_on[] = {	{ mk_mii_write(MII_REG_LED, 0x0422), NULL },
+				{ mk_mii_end, } };
+
+void fec_mii_suspend(struct net_device *dev)
+{
+	mii_do_cmd(dev, phy_cmd_leds_off);
+}
+
+void fec_mii_resume(struct net_device *dev)
+{
+	mii_do_cmd(dev, phy_cmd_leds_on);
+}
+#endif
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Dale Farnsworth");
 MODULE_DESCRIPTION("PHY driver for Motorola MPC52xx FEC");
Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.h
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.h
+++ grant.git/drivers/net/fec_mpc52xx/fec_phy.h
@@ -71,3 +71,8 @@ extern int fec_mii_wait(struct net_devic
 extern void fec_mii(struct net_device *dev);
 
 extern int fec_ioctl(struct net_device *, struct ifreq *rq, int cmd);
+
+#ifdef CONFIG_PM
+extern void fec_mii_suspend(struct net_device *dev);
+extern void fec_mii_resume(struct net_device *dev);
+#endif

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

* [PATCH 4/7] mpc52xx suspend: USB
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (2 preceding siblings ...)
  2007-03-01  7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
@ 2007-03-01  7:56 ` Domen Puncer
  2007-03-01  7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:56 UTC (permalink / raw)
  To: linuxppc-embedded

Trivial suspend and resume OF OHCI.
On MPC52xx turn off and on power to ports.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/drivers/usb/host/ohci-ppc-of.c
===================================================================
--- grant.git.orig/drivers/usb/host/ohci-ppc-of.c
+++ grant.git/drivers/usb/host/ohci-ppc-of.c
@@ -214,6 +214,32 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_
 #endif
 
 
+#ifdef CONFIG_PM
+static u32 descr_a;
+static int ohci_hcd_ppc_soc_drv_suspend(struct of_device *op,
+		pm_message_t state)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+#ifdef CONFIG_PPC_MPC52xx
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+	descr_a = in_be32(&ohci->regs->roothub.a);
+	out_be32(&ohci->regs->roothub.a, (descr_a & ~0x200) | 0x100);
+#endif
+	return 0;
+}
+static int ohci_hcd_ppc_soc_drv_resume(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+#ifdef CONFIG_PPC_MPC52xx
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+	out_be32(&ohci->regs->roothub.a, descr_a);
+#endif
+	return 0;
+}
+#endif
+
 static struct of_platform_driver ohci_hcd_ppc_of_driver = {
 	.name		= "ppc-of-ohci",
 	.match_table	= ohci_hcd_ppc_of_match,
@@ -221,8 +247,8 @@ static struct of_platform_driver ohci_hc
 	.remove		= ohci_hcd_ppc_of_remove,
 	.shutdown 	= ohci_hcd_ppc_of_shutdown,
 #ifdef CONFIG_PM
-	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
-	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
+	.suspend	= ohci_hcd_ppc_soc_drv_suspend,
+	.resume		= ohci_hcd_ppc_soc_drv_resume,
 #endif
 	.driver		= {
 		.name	= "ppc-of-ohci",

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

* [PATCH 5/7] mpc52xx suspend: deep-sleep
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (3 preceding siblings ...)
  2007-03-01  7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
@ 2007-03-01  7:56 ` Domen Puncer
  2007-03-01  7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:56 UTC (permalink / raw)
  To: linuxppc-embedded

Implement deep-sleep on MPC52xx.
SDRAM is put into self-refresh with help of SRAM code
(alternatives would be code in FLASH, I-cache).
Interrupt code must also not be in SDRAM, so put it
in I-cache.
MPC52xx core is static, so contents will remain intact even
with clocks turned off.

There seems to be a race with decrementer interrupt (uncomment
#define TESTING, and execute `echo standby > /sys/power/state`
couple thousands of times to reproduce it). :-(


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/arch/powerpc/platforms/52xx/Makefile
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/Makefile
+++ grant.git/arch/powerpc/platforms/52xx/Makefile
@@ -10,3 +10,5 @@ endif
 
 obj-$(CONFIG_PPC_EFIKA)		+= efika.o
 obj-$(CONFIG_PPC_LITE5200)	+= lite5200.o
+
+obj-$(CONFIG_PM)		+= mpc52xx_sleep.o mpc52xx_pm.o
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -0,0 +1,123 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+#include "mpc52xx_pic.h"
+
+extern void mpc52xx_deep_sleep(void *, void *);
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int mpc52xx_pm_prepare(suspend_state_t state)
+{
+	return 0;
+}
+
+/* you will want to change this, to match your board gpios, rtc or whatever */
+static void mpc52xx_set_wakeup_mode(void)
+{
+	struct mpc52xx_gpio_wkup __iomem *gpiow;
+	struct mpc52xx_intr __iomem *intr;
+	int pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */
+	u16 tmp;
+
+	gpiow = mpc52xx_find_and_map("mpc5200-gpio-wkup");
+	intr = mpc52xx_find_and_map("mpc5200-pic");
+	if (!gpiow || !intr) {
+		printk(KERN_ERR "%s: couldn't map io space\n", __func__);
+		goto out;
+	}
+
+	/* enable gpio */
+	out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin));
+	/* set as input */
+	out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin));
+	/* enable deep sleep interrupt */
+	out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin));
+	/* low level creates wakeup interrupt */
+	tmp = in_be16(&gpiow->wkup_itype);
+	tmp &= 2 << (pin * 2);
+	tmp |= 2 << (pin * 2);
+	out_be16(&gpiow->wkup_itype, tmp);
+	/* master enable */
+	out_8(&gpiow->wkup_maste, 1);
+
+	/* enable wakeup gpio interrupt in PIC */
+	out_be32(&intr->main_mask, in_be32(&intr->main_mask) & ~(1 << 8));
+ out:
+	iounmap(gpiow);
+	iounmap(intr);
+}
+
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+	int err = 0;
+	void __iomem *mbar;
+	struct mpc52xx_cdm __iomem *cdm;
+	u32 clk_enables;
+
+	if (state != PM_SUSPEND_STANDBY)
+		return 0;
+
+	mpc52xx_set_wakeup_mode();
+
+	/* is there a nicer way? */
+	mbar = ioremap_nocache(0xf0000000, 0x8000);
+	cdm = mpc52xx_find_and_map("mpc5200-cdm");
+	if (!mbar || !cdm) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		err = -ENOSYS;
+		goto out;
+	}
+
+	mpc52xx_sdma_suspend();
+
+	out_8(&cdm->ccs_sleep_enable, 1);
+	out_8(&cdm->osc_sleep_enable, 1);
+	out_8(&cdm->ccs_qreq_test, 1);
+
+	/* disable all but SDRAM, bestcomm (SRAM) and timer clocks */
+	clk_enables = in_be32(&cdm->clk_enables);
+	out_be32(&cdm->clk_enables, clk_enables & 0x00088002);
+
+	mpc52xx_deep_sleep(sdma.sram, mbar);
+
+	out_be32(&cdm->clk_enables, clk_enables);
+	out_8(&cdm->ccs_sleep_enable, 0);
+	out_8(&cdm->osc_sleep_enable, 0);
+
+	mpc52xx_sdma_resume();
+
+	iounmap(mbar);
+ out:
+	return err;
+}
+
+static int mpc52xx_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+static struct pm_ops mpc52xx_pm_ops = {
+	.valid		= mpc52xx_pm_valid,
+	.prepare	= mpc52xx_pm_prepare,
+	.enter		= mpc52xx_pm_enter,
+	.finish		= mpc52xx_pm_finish,
+};
+
+static int __init mpc52xx_pm_init(void)
+{
+	pm_set_ops(&mpc52xx_pm_ops);
+	return 0;
+}
+
+arch_initcall(mpc52xx_pm_init);
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
@@ -0,0 +1,277 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+
+// Tck is cca. 2000 cpu cycles here
+#define TCK 2000
+
+#define TMR0_ENABLE 0x600
+#define TMR0_INPUT 0x604
+
+#define SDRAM_CTRL	0x104
+
+#define CDM_CE		0x214
+#define CDM_CCSCR	0x21c
+
+#define INTR_MAIN_MASK	0x514
+#define INTR_ENC_STAT	0x524
+
+
+//#define TESTING
+
+// mpc5200b puts sdram automatically in self-refresh, previous versions don't
+#define SELF_REFRESH
+
+	.globl mpc52xx_deep_sleep
+mpc52xx_deep_sleep:
+
+	mr	r7, r3	// SRAM va
+	mr	r8, r4	// MBAR va
+	mflr	r9
+
+	// we don't want DEC expiring anytime soon, but not very late either
+	lis	r4, 0x1
+	mtspr	SPRN_DEC, r4
+
+
+	// setup power mode bits
+	mfmsr	r11
+	mr	r10, r11
+	oris	r10, r10, 0x0004
+	xoris	r10, r10, 0x0004	// POW = 0
+	sync; isync;
+	mtmsr	r10
+	sync; isync;
+
+	mfspr	r12, SPRN_HID0
+	mr	r10, r12
+	oris	r10, r10, 0x00f0
+	xoris	r10, r10, 0x00d0	// disable all power modes but sleep
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+	// copy code to sram
+	mr	r4, r7
+	subi	r4, r4, 4
+	li	r3, (sram_code_end-sram_code)/4
+	mtctr	r3
+	lis	r3, (sram_code-4)@h
+	ori	r3, r3, (sram_code-4)@l
+1:
+	lwzu	r5, 4(r3)
+	stwu	r5, 4(r4)
+	bdnz	1b
+
+
+	// save original irq handler, and write a new one
+	lis	r3, (orig_0x500-4)@h
+	ori	r3, r3, (orig_0x500-4)@l
+	li	r4, (cached_code_end - cached_code)/4
+	mtctr	r4
+	lis	r4, CONFIG_KERNEL_START@h
+	ori	r4, r4, 0x500
+	lis	r10, (cached_code-4)@h
+	ori	r10, r10, (cached_code-4)@l
+1:
+	lwz	r5, 0(r4)
+	stwu	r5, 4(r3)
+	lwzu	r5, 4(r10)
+	stw	r5, 0(r4)
+
+	dcbf	0, r4
+	icbi	0, r4
+	addi	r4, r4, 4
+
+	bdnz-	1b
+
+
+	// enable tmr0 interrupt
+	lwz	r4, INTR_MAIN_MASK(r8)
+	ori	r4, r4, 0x0080
+	xori	r4, r4, 0x0080
+	stw	r4, INTR_MAIN_MASK(r8)
+	sync
+
+	li	r5, 0 // flag that irq handler sets
+
+	// enable interrupts
+	mfmsr	r3
+	ori	r3, r3, 0x8000 // EE
+	mtmsr	r3
+	sync; isync;
+
+	// trigger tmr interrupt to cache the code
+	lis	r4, 0x100
+	ori	r4, r4, 0x1
+	stw	r4, TMR0_INPUT(r8)
+	sync
+	li	r4, 0x1104
+	stw	r4, TMR0_ENABLE(r8)
+	sync
+
+1:
+	cmpi	cr0, r5, 1
+	bne	cr0, 1b
+
+	// lock icache
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+	// jump to sram
+	mtlr	r7
+	blrl
+
+
+	// unlock icache
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	xori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+
+	// restore former power mode (and re-disable interrupts)
+	mfmsr	r10
+	oris	r10, r10, 0x0004
+	xoris	r10, r10, 0x0004	// POW = 0
+	sync; isync;
+	mtmsr	r10
+	sync; isync;
+
+	mtspr	SPRN_HID0, r12
+	sync; isync;
+
+	mtmsr	r11
+	sync; isync;
+
+	// restore original irq handler
+	lis	r3, (orig_0x500-4)@h
+	ori	r3, r3, (orig_0x500-4)@l
+	li	r4, (cached_code_end - cached_code)/4
+	mtctr	r4
+	lis	r4, CONFIG_KERNEL_START@h
+	ori	r4, r4, 0x500
+1:
+	lwzu	r5, 4(r3)
+	stw	r5, 0(r4)
+
+	dcbf	0, r4
+	icbi	0, r4
+	addi	r4, r4, 4
+
+	bdnz-	1b
+
+
+	mtlr	r9
+	blr
+
+
+sram_code:
+	// self refresh
+#ifdef SELF_REFRESH
+	lwz	r4, SDRAM_CTRL(r8)
+
+	oris	r4, r4, 0x8000 //mode_en
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	ori	r4, r4, 0x0002 // soft_pre
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+	xori	r4, r4, 0x0002
+
+	xoris	r4, r4, 0x8000 //mode_en
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	// delay one sdram cycle
+	li	r5, TCK
+	mtctr	r5
+1:
+	bdnz-	1b
+
+	oris	r4, r4, 0x5000
+	xoris	r4, r4, 0x4000 // ref_en !cke
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	// delay for 2 sdram cycles
+	li	r4, 2*TCK
+	mtctr	r4
+1:
+	bdnz-	1b
+
+	// disable clock
+	lwz	r4, CDM_CE(r8)
+	ori	r4, r4, 0x0008
+	xori	r4, r4, 0x0008
+	stw	r4, CDM_CE(r8)
+	sync
+#endif
+
+#ifndef TESTING
+	// put it to sleep
+	mfmsr	r10
+	oris	r10, r10, 0x0004	// POW = 1
+	sync; isync;
+	mtmsr	r10
+	sync; isync;
+#endif
+
+#ifdef SELF_REFRESH
+	// enable clock
+	lwz	r4, CDM_CE(r8)
+	ori	r4, r4, 0x0008
+	stw	r4, CDM_CE(r8)
+	sync
+
+	// get ram out of self-refresh
+	lwz	r4, SDRAM_CTRL(r8)
+	oris	r4, r4, 0x5000 // cke ref_en
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	li	r4, 2*TCK
+	mtctr	r4
+1:
+	bdnz-	1b
+#endif
+
+	blr
+sram_code_end:
+
+
+// ### interrupt handler for wakeup from deep-sleep ###
+cached_code:
+	// disable timer
+	mfspr	r3, 311	// MBAR
+	addi	r3, r3, TMR0_ENABLE
+	li	r4, 0
+	stw	r4, 0(r3)
+	sync
+	dcbf	0, r3
+
+	// acknowledge wakeup, so CCS releases power pown
+	mfspr	r3, 311	// MBAR
+	addi	r3, r3, INTR_ENC_STAT
+	lwz	r4, 0(r3)
+	ori	r4, r4, 0x0400
+	stw	r4, 0(r3)
+	sync
+	dcbf	0, r3
+
+	// flag that we handled an interrupt
+	li	r5, 1
+
+	rfi
+cached_code_end:
+
+
+orig_0x500:
+	.space (cached_code_end - cached_code)

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

* [PATCH 6/7] lite5200b suspend: PIC
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (4 preceding siblings ...)
  2007-03-01  7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
@ 2007-03-01  7:57 ` Domen Puncer
  2007-03-01  7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:57 UTC (permalink / raw)
  To: linuxppc-embedded

Save and restore MPC52xx PIC registers.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pic.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -471,3 +471,45 @@ unsigned int mpc52xx_get_irq(void)
 
 	return irq_linear_revmap(mpc52xx_irqhost, irq);
 }
+
+#ifdef CONFIG_PM
+/* save and restore registers for suspend to ram */
+static struct mpc52xx_intr saved_intr;
+void mpc52xx_pic_suspend(void)
+{
+	saved_intr.per_mask = in_be32(&intr->per_mask);
+	saved_intr.per_pri1 = in_be32(&intr->per_pri1);
+	saved_intr.per_pri2 = in_be32(&intr->per_pri2);
+	saved_intr.per_pri3 = in_be32(&intr->per_pri3);
+	saved_intr.ctrl =     in_be32(&intr->ctrl);
+	saved_intr.main_mask = in_be32(&intr->main_mask);
+	saved_intr.main_pri1 = in_be32(&intr->main_pri1);
+	saved_intr.main_pri2 = in_be32(&intr->main_pri2);
+	saved_intr.reserved1 = in_be32(&intr->reserved1);
+	saved_intr.enc_status = in_be32(&intr->enc_status);
+	saved_intr.crit_status = in_be32(&intr->crit_status);
+	saved_intr.main_status = in_be32(&intr->main_status);
+	saved_intr.per_status = in_be32(&intr->per_status);
+	saved_intr.reserved2 = in_be32(&intr->reserved2);
+	saved_intr.per_error = in_be32(&intr->per_error);
+}
+
+void mpc52xx_pic_resume(void)
+{
+	out_be32(&intr->per_mask, saved_intr.per_mask);
+	out_be32(&intr->per_pri1, saved_intr.per_pri1);
+	out_be32(&intr->per_pri2, saved_intr.per_pri2);
+	out_be32(&intr->per_pri3, saved_intr.per_pri3);
+	out_be32(&intr->ctrl,     saved_intr.ctrl);
+	out_be32(&intr->main_mask, saved_intr.main_mask);
+	out_be32(&intr->main_pri1, saved_intr.main_pri1);
+	out_be32(&intr->main_pri2, saved_intr.main_pri2);
+	out_be32(&intr->reserved1, saved_intr.reserved1);
+	out_be32(&intr->enc_status, saved_intr.enc_status);
+	out_be32(&intr->crit_status, saved_intr.crit_status);
+	out_be32(&intr->main_status, saved_intr.main_status);
+	out_be32(&intr->per_status, saved_intr.per_status);
+	out_be32(&intr->reserved2, saved_intr.reserved2);
+	out_be32(&intr->per_error, saved_intr.per_error);
+}
+#endif

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

* [u-boot patch] support lite5200b wakeup in u-boot
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (5 preceding siblings ...)
  2007-03-01  7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
@ 2007-03-01  7:59 ` Domen Puncer
  2007-03-01  8:49   ` Stefan Roese
  2007-03-01  8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  7:59 UTC (permalink / raw)
  To: linuxppc-embedded

U-Boot part of Lite5200b low power mode support.
Puts SDRAM out of self-refresh and transfers control to
address saved at physical 0x0


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

diff --git a/board/icecube/icecube.c b/board/icecube/icecube.c
index 9b222da..4b35776 100644
--- a/board/icecube/icecube.c
+++ b/board/icecube/icecube.c
@@ -42,6 +42,54 @@ # else
 #include "mt48lc16m16a2-75.h"
 # endif
 #endif
+
+#ifdef CONFIG_LITE5200B
+/* u-boot part of low-power mode implementation */
+#define SAVED_ADDR (*(void **)0x00000000)
+#define PSC2_4 0x02
+
+void lite5200b_wakeup(void)
+{
+	unsigned char wakeup_pin;
+	void (*linux_wakeup)(void);
+
+	/* check PSC2_4, if it's down "QT" is signaling we have a wakeup
+	 * from low power mode */
+	*(vu_char *)MPC5XXX_WU_GPIO_ENABLE = PSC2_4;
+	__asm__ volatile ("sync");
+
+	wakeup_pin = *(vu_char *)MPC5XXX_WU_GPIO_DATA_I;
+	if (wakeup_pin & PSC2_4)
+		return;
+
+	/* acknowledge to "QT"
+	 * by holding pin at 1 for 10 uS */
+	*(vu_char *)MPC5XXX_WU_GPIO_DIR = PSC2_4;
+	__asm__ volatile ("sync");
+	*(vu_char *)MPC5XXX_WU_GPIO_DATA = PSC2_4;
+	__asm__ volatile ("sync");
+	udelay(10);
+
+	/* put ram out of self-refresh */
+	*(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x80000000;	// mode_en
+	__asm__ volatile ("sync");
+	*(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x50000000;	// cke ref_en
+	__asm__ volatile ("sync");
+	*(vu_long *)MPC5XXX_SDRAM_CTRL &= ~0x80000000;	// !mode_en
+	__asm__ volatile ("sync");
+	udelay(10); /* wait a bit */
+
+	/* jump back to linux kernel code */
+	linux_wakeup = SAVED_ADDR;
+	printf("\n\nLooks like we just woke, transferring control to 0x%08lx\n",
+			linux_wakeup);
+	linux_wakeup();
+}
+#else
+#define lite5200b_wakeup
+#endif
+
+
 #ifndef CFG_RAMBOOT
 static void sdram_start (int hi_addr)
 {
@@ -208,6 +256,8 @@ #endif /* CFG_RAMBOOT */
 		__asm__ volatile ("sync");
 	}
 
+	lite5200b_wakeup();
+
 	return dramsize + dramsize2;
 }
 
diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h
index 1d20d1d..c7eb090 100644
--- a/include/mpc5xxx.h
+++ b/include/mpc5xxx.h
@@ -189,6 +189,7 @@ #define MPC5XXX_WU_GPIO_ENABLE  (MPC5XXX
 #define MPC5XXX_WU_GPIO_ODE     (MPC5XXX_WU_GPIO + 0x0004)
 #define MPC5XXX_WU_GPIO_DIR     (MPC5XXX_WU_GPIO + 0x0008)
 #define MPC5XXX_WU_GPIO_DATA    (MPC5XXX_WU_GPIO + 0x000c)
+#define MPC5XXX_WU_GPIO_DATA_I  (MPC5XXX_WU_GPIO + 0x0020)
 
 /* PCI registers */
 #define MPC5XXX_PCI_CMD		(MPC5XXX_PCI + 0x04)

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

* [PATCH 7/7] lite5200b suspend: low-power mode
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (6 preceding siblings ...)
  2007-03-01  7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
@ 2007-03-01  8:00 ` Domen Puncer
  2007-03-02 18:57   ` Scott Wood
  2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
  2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
  9 siblings, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-01  8:00 UTC (permalink / raw)
  To: linuxppc-embedded

Low-power mode implementation for Lite5200b.

A patch to U-Boot that wakes up SDRAM, and transfers control
to address saved at physical 0x0 is needed.


Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -0,0 +1,101 @@
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+
+extern void lite5200_low_power(void *sram, void *mbar);
+extern int mpc52xx_pm_enter(suspend_state_t);
+extern void mpc52xx_pic_suspend(void);
+extern void mpc52xx_pic_resume(void);
+
+static int lite5200_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int lite5200_pm_prepare(suspend_state_t state)
+{
+	return 0;
+}
+
+static int lite5200_pm_enter(suspend_state_t state)
+{
+	int err = 0;
+	struct mpc52xx_gpio __iomem *gpio;
+	void __iomem *mbar;
+	u32 gpio_saved_pc;
+
+	/* deep sleep? let mpc52xx code handle that */
+	if (state == PM_SUSPEND_STANDBY)
+		return mpc52xx_pm_enter(state);
+
+	if (state != PM_SUSPEND_MEM)
+		return -ENOSYS;
+
+	/* Map zones */
+	gpio = mpc52xx_find_and_map("mpc5200-gpio");
+	if (!gpio) {
+		printk(KERN_ERR "%s:%i Error mapping io zones\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+
+	/* save ie. ethernet pins configuration */
+	gpio_saved_pc = in_be32(&gpio->port_config);
+
+	mpc52xx_sdma_suspend();
+	mpc52xx_pic_suspend();
+
+
+	mbar = ioremap_nocache(0xf0000000, 0x8000);
+	/* is there a nicer way? */
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		err = -ENOSYS;
+		goto out_unmap;
+	}
+	lite5200_low_power(sdma.sram, mbar);
+	iounmap(mbar);
+
+
+	out_be32(&gpio->port_config, gpio_saved_pc);
+	iounmap(gpio);
+
+	mpc52xx_setup_cpu();
+
+	mpc52xx_pic_resume();
+	mpc52xx_sdma_resume();
+
+	return 0;
+
+ out_unmap:
+	iounmap(gpio);
+	return err;
+}
+
+static int lite5200_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+static struct pm_ops lite5200_pm_ops = {
+	.valid		= lite5200_pm_valid,
+	.prepare	= lite5200_pm_prepare,
+	.enter		= lite5200_pm_enter,
+	.finish		= lite5200_pm_finish,
+};
+
+static int __init lite5200_pm_init(void)
+{
+	pm_set_ops(&lite5200_pm_ops);
+	return 0;
+}
+
+arch_initcall(lite5200_pm_init);
Index: grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
@@ -0,0 +1,419 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+
+#define SDRAM_MODE	0x100
+#define SDRAM_CTRL	0x104
+#define SC_MODE_EN	(1<<31)
+#define SC_CKE		(1<<30)
+#define SC_REF_EN	(1<<28)
+#define SC_SOFT_PRE	(1<<1)
+
+#define GPIOW_GPIOE	0xc00
+#define GPIOW_ODE	0xc04
+#define GPIOW_DDR	0xc08
+#define GPIOW_DVO	0xc0c
+#define GPIOW_INTEN	0xc10
+
+#define CDM_CE		0x214
+#define CDM_SDRAM	(1<<3)
+
+
+// about 2000 cpu cycles for one sdram cycle here
+// just increase, to be on the safe side?
+#define TCK	5000
+
+
+#define DONT_DEBUG 1
+
+// helpers... beware: r10 and r4 are overwritten
+#define SAVE_SPRN(reg, addr)		\
+	mfspr	r10, SPRN_##reg;	\
+	stw	r10, ((addr)*4)(r4);
+
+#define LOAD_SPRN(reg, addr)		\
+	lwz	r10, ((addr)*4)(r4);	\
+	mtspr	SPRN_##reg, r10;	\
+	sync;				\
+	isync;
+
+// XXX it uses cca. 10 mA less if registers are saved in .text. WTF
+// is this still true?
+//	.data
+registers:
+	.space 0x5c*4
+//	.text
+
+// ----------------------------------------------------------------------
+// low-power mode with help of M68HLC908QT1
+
+	.globl lite5200_low_power
+lite5200_low_power:
+
+	mr	r7, r3	// save SRAM va
+	mr	r8, r4	// save MBAR va
+
+	// setup wakeup address for u-boot at physical location 0x0
+	lis	r3, CONFIG_KERNEL_START@h
+	lis	r4, lite5200_wakeup@h
+	ori	r4, r4, lite5200_wakeup@l
+	sub	r4, r4, r3
+	stw	r4, 0(r3)
+
+
+	// save stuff BDI overwrites
+	/* save 0xf0 (0xe0->0x100 gets overwritten when BDI connected;
+	 *   even when CONFIG_BDI* is disabled and MMU XLAT commented; heisenbug?))
+	 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,
+	 *   possibly because BDI sets SDRAM registers before wakeup code does */
+	lis	r4, registers@h
+	ori	r4, r4, registers@l
+	lwz	r10, 0xf0(r3)
+	stw	r10, (0x1d*4)(r4)
+
+	// save registers to r4 [destroys r10]
+	SAVE_SPRN(LR, 0x1c)
+	bl	save_regs
+
+	// flush caches [destroys r3, r4]
+	bl	flush_data_cache
+
+
+	// copy code to sram
+	mr	r4, r7
+	li	r3, (sram_code_end - sram_code)/4
+	mtctr	r3
+	lis	r3, sram_code@h
+	ori	r3, r3, sram_code@l
+1:
+	lwz	r5, 0(r3)
+	stw	r5, 0(r4)
+	addi	r3, r3, 4
+	addi	r4, r4, 4
+	bdnz	1b
+
+	// disable I and D caches
+	mfspr	r3, SPRN_HID0
+	ori	r3, r3, HID0_ICE | HID0_DCE
+	xori	r3, r3, HID0_ICE | HID0_DCE
+	sync; isync;
+	mtspr	SPRN_HID0, r3
+	sync; isync;
+
+#if DONT_DEBUG
+	// jump to sram
+	mtlr	r7
+	blrl
+	// doesn't return
+#else
+	// debugging
+	b	lite5200_wakeup
+#endif
+
+
+sram_code:
+	// self refresh
+	lwz	r4, SDRAM_CTRL(r8)
+
+	// send NOP (precharge)
+	oris	r4, r4, SC_MODE_EN@h	// mode_en
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	ori	r4, r4, SC_SOFT_PRE	// soft_pre
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+	xori	r4, r4, SC_SOFT_PRE
+
+	xoris	r4, r4, SC_MODE_EN@h	// !mode_en
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	// delay for one sdram cycle (for NOP to finish)
+	li	r5, TCK
+	mtctr	r5
+1:	bdnz-	1b
+
+	// mode_en must not be set when enabling self-refresh
+	// send AR with CKE low (self-refresh)
+	oris	r4, r4, (SC_REF_EN | SC_CKE)@h
+	xoris	r4, r4, (SC_CKE)@h	// ref_en !cke
+	stw	r4, SDRAM_CTRL(r8)
+	sync
+
+	// delay for two sdram cycles (after !CKE there should be two cycles)
+	li	r5, 2*TCK
+	mtctr	r5
+1:	bdnz-	1b
+
+	// disable clock
+	lwz	r4, CDM_CE(r8)
+	ori	r4, r4, CDM_SDRAM
+	xori	r4, r4, CDM_SDRAM
+	stw	r4, CDM_CE(r8)
+	sync
+
+	// delay for two sdram cycles
+	li	r5, 2*TCK
+	mtctr	r5
+1:	bdnz-	1b
+
+
+	// turn off with QT chip
+	li	r4, 0x02
+	stb	r4, GPIOW_GPIOE(r8)	// enable gpio_wkup1
+	sync
+
+	stb	r4, GPIOW_DVO(r8)	// "output" high
+	sync
+	stb	r4, GPIOW_DDR(r8)	// output
+	sync
+	stb	r4, GPIOW_DVO(r8)	// output high
+	sync
+
+	// delay
+	// 2000 cycles is cca 12 uS, 10uS should be enough
+	li	r4, 2000
+	mtctr	r4
+1:
+	bdnz-	1b
+
+	// turn off
+	li	r4, 0
+	stb	r4, GPIOW_DVO(r8)	// output low
+	sync
+
+	// wait until we're offline
+1:
+	b	1b
+sram_code_end:
+
+
+
+// uboot jumps here on resume
+lite5200_wakeup:
+	bl	restore_regs
+
+
+	// HIDs, MSR
+	LOAD_SPRN(HID1, 0x19)
+	LOAD_SPRN(HID2, 0x1a)
+
+
+	// address translation is tricky (see turn_on_mmu)
+	mfmsr	r10
+	ori	r10, r10, MSR_DR | MSR_IR
+
+
+	mtspr	SPRN_SRR1, r10
+	lis	r10, mmu_on@h
+	ori	r10, r10, mmu_on@l
+	mtspr	SPRN_SRR0, r10
+	sync
+	rfi
+mmu_on:
+	// kernel offset (r4 is still set from restore_registers)
+	addis	r4, r4, CONFIG_KERNEL_START@h
+
+
+	// restore MSR
+	lwz	r10, (4*0x1b)(r4)
+	mtmsr	r10
+	sync; isync;
+
+	// setup DEC somewhere in the 1/HZ range
+	// if you don't do this, timer interrupt will trigger a few
+	//	seconds later, and that is not good.
+	lis	r3, 0x10
+	mtdec	r3
+
+	// invalidate caches
+	mfspr	r10, SPRN_HID0
+	ori	r5, r10, HID0_ICFI | HID0_DCI
+	mtspr	SPRN_HID0, r5	// invalidate caches
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+	// enable caches
+	lwz	r10, (4*0x18)(r4)
+	mtspr	SPRN_HID0, r10	// restore (enable caches, DPM)
+	// ^ this has to be after address translation set in MSR
+	sync
+	isync
+
+
+	// restore 0xf0 (BDI2000)
+	lis	r3, CONFIG_KERNEL_START@h
+	lwz	r10, (0x1d*4)(r4)
+	stw	r10, 0xf0(r3)
+
+	LOAD_SPRN(LR, 0x1c)
+
+
+	blr
+
+
+// ----------------------------------------------------------------------
+// boring code: helpers
+
+// save registers
+#define SAVE_BAT(n, addr)		\
+	SAVE_SPRN(DBAT##n##L, addr);	\
+	SAVE_SPRN(DBAT##n##U, addr+1);	\
+	SAVE_SPRN(IBAT##n##L, addr+2);	\
+	SAVE_SPRN(IBAT##n##U, addr+3);
+
+#define SAVE_SR(n, addr)		\
+	mfsr	r10, n;			\
+	stw	r10, ((addr)*4)(r4);
+
+#define SAVE_4SR(n, addr)	\
+	SAVE_SR(n, addr);	\
+	SAVE_SR(n+1, addr+1);	\
+	SAVE_SR(n+2, addr+2);	\
+	SAVE_SR(n+3, addr+3);
+
+save_regs:
+	stw	r0, 0(r4)
+	stw	r1, 0x4(r4)
+	stw	r2, 0x8(r4)
+	stmw	r11, 0xc(r4) // 0xc -> 0x5f, (0x18*4-1)
+
+	SAVE_SPRN(HID0, 0x18)
+	SAVE_SPRN(HID1, 0x19)
+	SAVE_SPRN(HID2, 0x1a)
+	mfmsr	r10
+	stw	r10, (4*0x1b)(r4)
+	//SAVE_SPRN(LR, 0x1c) have to save it before the call
+	// 0x1d reserved by 0xf0
+	SAVE_SPRN(RPA,   0x1e)
+	SAVE_SPRN(SDR1,  0x1f)
+
+	// save MMU regs
+	SAVE_BAT(0, 0x20)
+	SAVE_BAT(1, 0x24)
+	SAVE_BAT(2, 0x28)
+	SAVE_BAT(3, 0x2c)
+	SAVE_BAT(4, 0x30)
+	SAVE_BAT(5, 0x34)
+	SAVE_BAT(6, 0x38)
+	SAVE_BAT(7, 0x3c)
+
+	SAVE_4SR(0, 0x40)
+	SAVE_4SR(4, 0x44)
+	SAVE_4SR(8, 0x48)
+	SAVE_4SR(12, 0x4c)
+
+	SAVE_SPRN(SPRG0, 0x50)
+	SAVE_SPRN(SPRG1, 0x51)
+	SAVE_SPRN(SPRG2, 0x52)
+	SAVE_SPRN(SPRG3, 0x53)
+	SAVE_SPRN(SPRG4, 0x54)
+	SAVE_SPRN(SPRG5, 0x55)
+	SAVE_SPRN(SPRG6, 0x56)
+	SAVE_SPRN(SPRG7, 0x57)
+
+	SAVE_SPRN(IABR,  0x58)
+	SAVE_SPRN(DABR,  0x59)
+	SAVE_SPRN(TBRL,  0x5a)
+	SAVE_SPRN(TBRU,  0x5b)
+
+	blr
+
+
+// restore registers
+#define LOAD_BAT(n, addr)		\
+	LOAD_SPRN(DBAT##n##L, addr);	\
+	LOAD_SPRN(DBAT##n##U, addr+1);	\
+	LOAD_SPRN(IBAT##n##L, addr+2);	\
+	LOAD_SPRN(IBAT##n##U, addr+3);
+
+#define LOAD_SR(n, addr)		\
+	lwz	r10, ((addr)*4)(r4);	\
+	mtsr	n, r10;
+
+#define LOAD_4SR(n, addr)	\
+	LOAD_SR(n, addr);	\
+	LOAD_SR(n+1, addr+1);	\
+	LOAD_SR(n+2, addr+2);	\
+	LOAD_SR(n+3, addr+3);
+
+restore_regs:
+	lis	r4, registers@h
+	ori	r4, r4, registers@l
+#ifdef DONT_DEBUG
+	subis	r4, r4, CONFIG_KERNEL_START@h
+#endif
+
+	lwz	r0, 0(r4)
+	lwz	r1, 0x4(r4)
+	lwz	r2, 0x8(r4)
+	lmw	r11, 0xc(r4)
+
+	// these are a bit tricky
+	/*
+	0x18 - HID0
+	0x19 - HID1
+	0x1a - HID2
+	0x1b - MSR
+	0x1c - LR
+	0x1d - reserved by 0xf0 (BDI2000)
+	*/
+	LOAD_SPRN(RPA,   0x1e);
+	LOAD_SPRN(SDR1,  0x1f);
+
+	// restore MMU regs
+	LOAD_BAT(0, 0x20)
+	LOAD_BAT(1, 0x24)
+	LOAD_BAT(2, 0x28)
+	LOAD_BAT(3, 0x2c)
+	LOAD_BAT(4, 0x30)
+	LOAD_BAT(5, 0x34)
+	LOAD_BAT(6, 0x38)
+	LOAD_BAT(7, 0x3c)
+
+	LOAD_4SR(0, 0x40)
+	LOAD_4SR(4, 0x44)
+	LOAD_4SR(8, 0x48)
+	LOAD_4SR(12, 0x4c)
+
+	// rest of regs
+	LOAD_SPRN(SPRG0, 0x50);
+	LOAD_SPRN(SPRG1, 0x51);
+	LOAD_SPRN(SPRG2, 0x52);
+	LOAD_SPRN(SPRG3, 0x53);
+	LOAD_SPRN(SPRG4, 0x54);
+	LOAD_SPRN(SPRG5, 0x55);
+	LOAD_SPRN(SPRG6, 0x56);
+	LOAD_SPRN(SPRG7, 0x57);
+
+	LOAD_SPRN(IABR,  0x58);
+	LOAD_SPRN(DABR,  0x59);
+	LOAD_SPRN(TBWL,  0x5a);	// these two have separate R/W regs
+	LOAD_SPRN(TBWU,  0x5b);
+
+	blr
+
+
+
+// cache flushing code. copied from arch/ppc/boot/util.S
+#define NUM_CACHE_LINES (128*8)
+
+/*
+ * Flush data cache
+ * Do this by just reading lots of stuff into the cache.
+ */
+        .globl flush_data_cache
+flush_data_cache:
+	lis	r3,CONFIG_KERNEL_START@h
+	ori	r3,r3,CONFIG_KERNEL_START@l
+	li	r4,NUM_CACHE_LINES
+	mtctr	r4
+1:
+	lwz	r4,0(r3)
+	addi	r3,r3,L1_CACHE_BYTES	/* Next line, please */
+	bdnz	1b
+	blr
Index: grant.git/arch/powerpc/platforms/52xx/Makefile
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/Makefile
+++ grant.git/arch/powerpc/platforms/52xx/Makefile
@@ -12,3 +12,6 @@ obj-$(CONFIG_PPC_EFIKA)		+= efika-setup.
 obj-$(CONFIG_PPC_LITE5200)	+= lite5200.o
 
 obj-$(CONFIG_PM)		+= mpc52xx_sleep.o mpc52xx_pm.o
+ifeq ($(CONFIG_PPC_LITE5200),y)
+	obj-$(CONFIG_PM)	+= lite5200_sleep.o lite5200_pm.o
+endif
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_common.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -76,7 +76,7 @@ mpc52xx_find_ipb_freq(struct device_node
 EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
 
 
-void __init
+void
 mpc52xx_setup_cpu(void)
 {
 	struct mpc52xx_cdm  __iomem *cdm;

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

* Re: [u-boot patch] support lite5200b wakeup in u-boot
  2007-03-01  7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
@ 2007-03-01  8:49   ` Stefan Roese
  0 siblings, 0 replies; 21+ messages in thread
From: Stefan Roese @ 2007-03-01  8:49 UTC (permalink / raw)
  To: linuxppc-embedded

On Thursday 01 March 2007 08:59, Domen Puncer wrote:
> U-Boot part of Lite5200b low power mode support.
> Puts SDRAM out of self-refresh and transfers control to
> address saved at physical 0x0

Please post this patch to the U-Boot mailing list.

Best regards,
Stefan

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (7 preceding siblings ...)
  2007-03-01  8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
@ 2007-03-01 14:25 ` Grant Likely
  2007-03-01 14:51   ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
  2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
  9 siblings, 1 reply; 21+ messages in thread
From: Grant Likely @ 2007-03-01 14:25 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Hi!
>
> Patches are based on latest mainline git tree + fec patches:
> Fec_MPC5200_eth_driver.patch
> Copy_bestcomm_support_files_into_arch_powerpc.patch
> Make_FEC_work_on_the_lite5200.patch
>
---8<---snip--->8---
>
> I would appreaciate any comments, suggestions etc.

Cool, good work.  I'll try to do a proper review today.

Note on the Bestcomm stuff; the patches that you've referenced above
will not be going into mainline.  They will be replaced by a new set
of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
patches there will need some rework.

Cheers,
g.

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

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

* New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes)
  2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
@ 2007-03-01 14:51   ` Bartlomiej Sieka
  2007-03-02  7:31     ` Domen Puncer
  0 siblings, 1 reply; 21+ messages in thread
From: Bartlomiej Sieka @ 2007-03-01 14:51 UTC (permalink / raw)
  To: linuxppc-embedded

Grant Likely wrote:
> On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
>> Hi!
>>
>> Patches are based on latest mainline git tree + fec patches:
>> Fec_MPC5200_eth_driver.patch
>> Copy_bestcomm_support_files_into_arch_powerpc.patch
>> Make_FEC_work_on_the_lite5200.patch
>>
> ---8<---snip--->8---
>> I would appreaciate any comments, suggestions etc.
> 
> Cool, good work.  I'll try to do a proper review today.
> 
> Note on the Bestcomm stuff; the patches that you've referenced above
> will not be going into mainline.  They will be replaced by a new set
> of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
> patches there will need some rework.

Hello,

I am working on porting arch/powerpc Linux to a custom MPC5200B-based 
board, and currently using your 52xx-dev branch. Is this new set of 
bestcomm/FEC patches already in any of your publicly available branches, 
or is it something completely fresh? I am seeing some networking 
problems, and would be interested in giving new patches a try.

Regards,
Bartlomiej

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

* Re: New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes)
  2007-03-01 14:51   ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
@ 2007-03-02  7:31     ` Domen Puncer
  0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-02  7:31 UTC (permalink / raw)
  To: Bartlomiej Sieka; +Cc: linuxppc-embedded

On 01/03/07 15:51 +0100, Bartlomiej Sieka wrote:
> Grant Likely wrote:
> > On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> >> Hi!
> >>
> >> Patches are based on latest mainline git tree + fec patches:
> >> Fec_MPC5200_eth_driver.patch
> >> Copy_bestcomm_support_files_into_arch_powerpc.patch
> >> Make_FEC_work_on_the_lite5200.patch
> >>
> > ---8<---snip--->8---
> >> I would appreaciate any comments, suggestions etc.
> > 
> > Cool, good work.  I'll try to do a proper review today.
> > 
> > Note on the Bestcomm stuff; the patches that you've referenced above
> > will not be going into mainline.  They will be replaced by a new set
> > of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
> > patches there will need some rework.
> 
> Hello,
> 
> I am working on porting arch/powerpc Linux to a custom MPC5200B-based 
> board, and currently using your 52xx-dev branch. Is this new set of 
> bestcomm/FEC patches already in any of your publicly available branches, 
> or is it something completely fresh? I am seeing some networking 
> problems, and would be interested in giving new patches a try.

Patches I used were from Grant's 52xx-dev branch.


	Domen

> 
> Regards,
> Bartlomiej
> 
> 
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

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

* Re: [PATCH 7/7] lite5200b suspend: low-power mode
  2007-03-01  8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
@ 2007-03-02 18:57   ` Scott Wood
  2007-03-03  7:15     ` Domen Puncer
  0 siblings, 1 reply; 21+ messages in thread
From: Scott Wood @ 2007-03-02 18:57 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On Thu, Mar 01, 2007 at 09:00:08AM +0100, Domen Puncer wrote:
> +static int lite5200_pm_enter(suspend_state_t state)
> +{
[snip]
> +	mbar = ioremap_nocache(0xf0000000, 0x8000);

You can't do ioremap with interrupts disabled (it will fail with spinlock
debugging enabled); the mapping should be set up at boot time.

-Scott

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (8 preceding siblings ...)
  2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
@ 2007-03-02 21:35 ` Sylvain Munaut
  2007-03-03  7:33   ` Domen Puncer
  9 siblings, 1 reply; 21+ messages in thread
From: Sylvain Munaut @ 2007-03-02 21:35 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

Hi,

Thanks for providing theses.
I hadn't a chance to test them yet, I'll try that this week end. A
couple of comments already though :

 - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
those when at sleep ?
 - And if it is, won't a memcpy_io of the whole zone do the trick ?
 - On a more general note, there seem to be a lot of stuff decided by
#ifdef ... that's not really good as we can build a single kernel that
could run on several platform so those need to somehow be enable
disabled dynamically.
 - I may miss something but turning port power off for USB seem like a
sane thing to do for every one. Isn't that implemented somehow for all
controller somewhere ?


Sylvain

 
Domen Puncer wrote:
> Hi!
>
> Patches are based on latest mainline git tree + fec patches:
> Fec_MPC5200_eth_driver.patch
> Copy_bestcomm_support_files_into_arch_powerpc.patch
> Make_FEC_work_on_the_lite5200.patch
>
>
> This patchset includes the following patches:
> - [PATCH 1/7] mpc52xx suspend: bestcomm
> - [PATCH 2/7] mpc52xx suspend: UART
> - [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
> - [PATCH 4/7] mpc52xx suspend: USB
> - [PATCH 5/7] mpc52xx suspend: deep-sleep
> - [PATCH 6/7] lite5200b suspend: PIC
> - [u-boot patch] support lite5200b wakeup in u-boot
> - [PATCH 7/7] lite5200b suspend: low-power mode
>
>
> I would appreaciate any comments, suggestions etc.
>
>
> 	Domen
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>   

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

* Re: [PATCH 7/7] lite5200b suspend: low-power mode
  2007-03-02 18:57   ` Scott Wood
@ 2007-03-03  7:15     ` Domen Puncer
  0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-03  7:15 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-embedded

On 02/03/07 12:57 -0600, Scott Wood wrote:
> On Thu, Mar 01, 2007 at 09:00:08AM +0100, Domen Puncer wrote:
> > +static int lite5200_pm_enter(suspend_state_t state)
> > +{
> [snip]
> > +	mbar = ioremap_nocache(0xf0000000, 0x8000);
> 
> You can't do ioremap with interrupts disabled (it will fail with spinlock
> debugging enabled); the mapping should be set up at boot time.

>From what I see, it could also be set up in prepare(), no?
I'll try that with spinlock debugging on monday.

Thanks!


	Domen
> 
> -Scott

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
@ 2007-03-03  7:33   ` Domen Puncer
  2007-03-03 19:58     ` Endianness versus too many byte swaps?? Charles Krinke
  2007-03-05 10:53     ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
  0 siblings, 2 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-03  7:33 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-embedded

On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
> Hi,
> 
> Thanks for providing theses.
> I hadn't a chance to test them yet, I'll try that this week end. A
> couple of comments already though :
> 
>  - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
> those when at sleep ?

For deep-sleep this is true, but not for low-power mode (the CPU
isn't even powered in that case).

>  - And if it is, won't a memcpy_io of the whole zone do the trick ?

Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.

>  - On a more general note, there seem to be a lot of stuff decided by
> #ifdef ... that's not really good as we can build a single kernel that
> could run on several platform so those need to somehow be enable
> disabled dynamically.

CONFIG_PM - well... it doesn't make sense too keep the code if
	power management is disabled.
SELF_REFRESH, TESTING - both are provided for debugging, final
	version is former on, latter off.

>  - I may miss something but turning port power off for USB seem like a
> sane thing to do for every one. Isn't that implemented somehow for all
> controller somewhere ?

The "USB power led" on lite5200b says it isn't.

Thanks!


	Domen

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

* Endianness versus too many byte swaps??
  2007-03-03  7:33   ` Domen Puncer
@ 2007-03-03 19:58     ` Charles Krinke
  2007-03-05 10:53     ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
  1 sibling, 0 replies; 21+ messages in thread
From: Charles Krinke @ 2007-03-03 19:58 UTC (permalink / raw)
  To: linuxppc-embedded

This is probably a Timur question, but any enlightment is appreciated. =
This concerns Linux-2.6.17.11 from kernel.org with some modifications =
for our custom 8541 board. The original BSP was evolved from =
mpc85xx_cds.
=20
Down in the guts of arch/ppc/syslib/ppc85xx_seteup.c is a routine called =
mpc85xx_setup_pci1(). In this routine we do an assignment of some =
outbound window registers and I am most interested in POTAR2, POWAR2 & =
POWBAR2 right now.
=20
This routine uses a ccsr_pci struct to assign potar2, powar2, powbar2 =
and others like this:
=20
pci->potar2     =3D 0x00100000;
pci->powar2   =3D 0x8004401a;
pci->powbar2 =3D 0x00888000;
=20
Where I have changed the constants for our board. The issue is that when =
I call readl to read back these same registers at the end of this same =
subroutine, I get into endianess issues. That is, I read back
=20
POTAR2     =3D=3D 0x00001000
POWAR2   =3D=3D 0x1A400480
POWBAR2 =3D=3D 0x00800800
=20
Where the four bytes in each 32bit word are now exchanged so that =
80_04_40_1A became 1A_40_04_80.
=20
I understand big versus little endian, that isn't the question. The =
question is "What is really in the POTAR2, POWAR2 & POWBAR2 registers =
and how can I prove that what is in the registers is really what I wish =
to be in the registers?"
=20
It may be that one or more endian swap things are going on within Linux =
and I have inherited some source from others, so actually proving what =
is in the registers is becoming important.
=20
Charles

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-03  7:33   ` Domen Puncer
  2007-03-03 19:58     ` Endianness versus too many byte swaps?? Charles Krinke
@ 2007-03-05 10:53     ` Domen Puncer
  2007-03-05 10:58       ` Sylvain Munaut
  1 sibling, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-05 10:53 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-embedded

On 03/03/07 08:33 +0100, Domen Puncer wrote:
> On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
> > Hi,
> > 
> > Thanks for providing theses.
> > I hadn't a chance to test them yet, I'll try that this week end. A
> > couple of comments already though :
> > 
> >  - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
> > those when at sleep ?
> 
> For deep-sleep this is true, but not for low-power mode (the CPU
> isn't even powered in that case).
> 
> >  - And if it is, won't a memcpy_io of the whole zone do the trick ?
> 
> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.

OK, one can't copy the whole zone :-(
Ie. reading from MBAR+0x3B00 seems to freeze Linux.

Currently I'm having something like (obsoletes PIC and SDMA patches):


Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -0,0 +1,125 @@
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include "mpc52xx_pic.h"
+#include "bestcomm.h"
+
+extern void lite5200_low_power(void *sram, void *mbar);
+extern int mpc52xx_pm_enter(suspend_state_t);
+extern int mpc52xx_pm_prepare(suspend_state_t);
+
+static void __iomem *mbar;
+
+static int lite5200_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int lite5200_pm_prepare(suspend_state_t state)
+{
+	/* deep sleep? let mpc52xx code handle that */
+	if (state == PM_SUSPEND_STANDBY)
+		return mpc52xx_pm_prepare(state);
+
+	if (state != PM_SUSPEND_MEM)
+		return -EINVAL;
+
+	/* map registers */
+	mbar = ioremap_nocache(0xf0000000, 0x8000);
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+/* save and restore registers not bound to any real devices */
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_cdm scdm;
+static struct mpc52xx_intr __iomem *pic;
+static struct mpc52xx_intr spic;
+static struct mpc52xx_sdma __iomem *bes;
+static struct mpc52xx_sdma sbes;
+static struct mpc52xx_xlb __iomem *xlb;
+static struct mpc52xx_xlb sxlb;
+static struct mpc52xx_gpio __iomem *gps;
+static struct mpc52xx_gpio sgps;
+static struct mpc52xx_gpio_wkup __iomem *gpw;
+static struct mpc52xx_gpio_wkup sgpw;
+extern char saved_sram[0x4000];
+
+static void lite5200_save_regs(void)
+{
+	_memcpy_fromio(&sbes, bes, sizeof(*bes));
+	_memcpy_fromio(&spic, pic, sizeof(*pic));
+	_memcpy_fromio(&scdm, cdm, sizeof(*cdm));
+	_memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
+	_memcpy_fromio(&sgps, gps, sizeof(*gps));
+	_memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
+
+	memcpy(saved_sram, sdma.sram, sdma.sram_size);
+}
+
+static void lite5200_restore_regs(void)
+{
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+	_memcpy_toio(gpw, &sgpw, sizeof(*gpw));
+	_memcpy_toio(gps, &sgps, sizeof(*gps));
+	_memcpy_toio(xlb, &sxlb, sizeof(*xlb));
+	_memcpy_toio(cdm, &scdm, sizeof(*cdm));
+	_memcpy_toio(pic, &spic, sizeof(*pic));
+	_memcpy_toio(bes, &sbes, sizeof(*bes));
+}
+
+static int lite5200_pm_enter(suspend_state_t state)
+{
+	/* deep sleep? let mpc52xx code handle that */
+	if (state == PM_SUSPEND_STANDBY) {
+		return mpc52xx_pm_enter(state);
+	}
+
+	cdm = mbar + 0x200;
+	pic = mbar + 0x500;
+	gps = mbar + 0xb00;
+	gpw = mbar + 0xc00;
+	bes = mbar + 0x1200;
+	xlb = mbar + 0x1f00;
+	lite5200_save_regs();
+
+	lite5200_low_power(sdma.sram, mbar);
+
+	lite5200_restore_regs();
+
+	iounmap(mbar);
+	return 0;
+}
+
+static int lite5200_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+static struct pm_ops lite5200_pm_ops = {
+	.valid		= lite5200_pm_valid,
+	.prepare	= lite5200_pm_prepare,
+	.enter		= lite5200_pm_enter,
+	.finish		= lite5200_pm_finish,
+};
+
+static int __init lite5200_pm_init(void)
+{
+	pm_set_ops(&lite5200_pm_ops);
+	return 0;
+}
+
+arch_initcall(lite5200_pm_init);

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-05 10:53     ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-05 10:58       ` Sylvain Munaut
  2007-03-05 20:21         ` Domen Puncer
  0 siblings, 1 reply; 21+ messages in thread
From: Sylvain Munaut @ 2007-03-05 10:58 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

Domen Puncer wrote:
> On 03/03/07 08:33 +0100, Domen Puncer wrote:
>   
>> On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
>>     
>>> Hi,
>>>
>>> Thanks for providing theses.
>>> I hadn't a chance to test them yet, I'll try that this week end. A
>>> couple of comments already though :
>>>
>>>  - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
>>> those when at sleep ?
>>>       
>> For deep-sleep this is true, but not for low-power mode (the CPU
>> isn't even powered in that case).
>>
>>     
>>>  - And if it is, won't a memcpy_io of the whole zone do the trick ?
>>>       
>> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
>>     
>
> OK, one can't copy the whole zone :-(
> Ie. reading from MBAR+0x3B00 seems to freeze Linux.
>
> Currently I'm having something like (obsoletes PIC and SDMA patches):
>   
And does that work ?

I was also wondering if some registers don't need to be restored last.
For example,
the task status in sdma would be restored to 0 then just at the end set
to their "real value".

Saving / Restoring all theses system zones makes more sense to me than
to just save / restore the pic & sdma and hoping than mpc52xx_setup_cpu
will make the rest ...

But saving/restoring all the mbar isn't good either because peripheral
drivers should handle their own setup restore. The suspend / resume
method of the peripheral should differentiate how deep their suspending
/ resuming and do what's necessary accordingly.


    Sylvain

>
> Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
> ===================================================================
> --- /dev/null
> +++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
> @@ -0,0 +1,125 @@
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/pm.h>
> +#include <asm/io.h>
> +#include <asm/mpc52xx.h>
> +#include "mpc52xx_pic.h"
> +#include "bestcomm.h"
> +
> +extern void lite5200_low_power(void *sram, void *mbar);
> +extern int mpc52xx_pm_enter(suspend_state_t);
> +extern int mpc52xx_pm_prepare(suspend_state_t);
> +
> +static void __iomem *mbar;
> +
> +static int lite5200_pm_valid(suspend_state_t state)
> +{
> +	switch (state) {
> +	case PM_SUSPEND_STANDBY:
> +	case PM_SUSPEND_MEM:
> +		return 1;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int lite5200_pm_prepare(suspend_state_t state)
> +{
> +	/* deep sleep? let mpc52xx code handle that */
> +	if (state == PM_SUSPEND_STANDBY)
> +		return mpc52xx_pm_prepare(state);
> +
> +	if (state != PM_SUSPEND_MEM)
> +		return -EINVAL;
> +
> +	/* map registers */
> +	mbar = ioremap_nocache(0xf0000000, 0x8000);
> +	if (!mbar) {
> +		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
> +		return -ENOSYS;
> +	}
> +
> +	return 0;
> +}
> +
> +/* save and restore registers not bound to any real devices */
> +static struct mpc52xx_cdm __iomem *cdm;
> +static struct mpc52xx_cdm scdm;
> +static struct mpc52xx_intr __iomem *pic;
> +static struct mpc52xx_intr spic;
> +static struct mpc52xx_sdma __iomem *bes;
> +static struct mpc52xx_sdma sbes;
> +static struct mpc52xx_xlb __iomem *xlb;
> +static struct mpc52xx_xlb sxlb;
> +static struct mpc52xx_gpio __iomem *gps;
> +static struct mpc52xx_gpio sgps;
> +static struct mpc52xx_gpio_wkup __iomem *gpw;
> +static struct mpc52xx_gpio_wkup sgpw;
> +extern char saved_sram[0x4000];
> +
> +static void lite5200_save_regs(void)
> +{
> +	_memcpy_fromio(&sbes, bes, sizeof(*bes));
> +	_memcpy_fromio(&spic, pic, sizeof(*pic));
> +	_memcpy_fromio(&scdm, cdm, sizeof(*cdm));
> +	_memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
> +	_memcpy_fromio(&sgps, gps, sizeof(*gps));
> +	_memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
> +
> +	memcpy(saved_sram, sdma.sram, sdma.sram_size);
> +}
> +
> +static void lite5200_restore_regs(void)
> +{
> +	memcpy(sdma.sram, saved_sram, sdma.sram_size);
> +
> +	_memcpy_toio(gpw, &sgpw, sizeof(*gpw));
> +	_memcpy_toio(gps, &sgps, sizeof(*gps));
> +	_memcpy_toio(xlb, &sxlb, sizeof(*xlb));
> +	_memcpy_toio(cdm, &scdm, sizeof(*cdm));
> +	_memcpy_toio(pic, &spic, sizeof(*pic));
> +	_memcpy_toio(bes, &sbes, sizeof(*bes));
> +}
> +
> +static int lite5200_pm_enter(suspend_state_t state)
> +{
> +	/* deep sleep? let mpc52xx code handle that */
> +	if (state == PM_SUSPEND_STANDBY) {
> +		return mpc52xx_pm_enter(state);
> +	}
> +
> +	cdm = mbar + 0x200;
> +	pic = mbar + 0x500;
> +	gps = mbar + 0xb00;
> +	gpw = mbar + 0xc00;
> +	bes = mbar + 0x1200;
> +	xlb = mbar + 0x1f00;
> +	lite5200_save_regs();
> +
> +	lite5200_low_power(sdma.sram, mbar);
> +
> +	lite5200_restore_regs();
> +
> +	iounmap(mbar);
> +	return 0;
> +}
> +
> +static int lite5200_pm_finish(suspend_state_t state)
> +{
> +	return 0;
> +}
> +
> +static struct pm_ops lite5200_pm_ops = {
> +	.valid		= lite5200_pm_valid,
> +	.prepare	= lite5200_pm_prepare,
> +	.enter		= lite5200_pm_enter,
> +	.finish		= lite5200_pm_finish,
> +};
> +
> +static int __init lite5200_pm_init(void)
> +{
> +	pm_set_ops(&lite5200_pm_ops);
> +	return 0;
> +}
> +
> +arch_initcall(lite5200_pm_init);
>
>   

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

* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
  2007-03-05 10:58       ` Sylvain Munaut
@ 2007-03-05 20:21         ` Domen Puncer
  0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-05 20:21 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-embedded

On 05/03/07 11:58 +0100, Sylvain Munaut wrote:
> Domen Puncer wrote:
> >   
> >>     
> >>>  - And if it is, won't a memcpy_io of the whole zone do the trick ?
> >>>       
> >> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
> >>     
> >
> > OK, one can't copy the whole zone :-(
> > Ie. reading from MBAR+0x3B00 seems to freeze Linux.
> >
> > Currently I'm having something like (obsoletes PIC and SDMA patches):
> >   
> And does that work ?

Yes, it does.

> 
> I was also wondering if some registers don't need to be restored last.
> For example,
> the task status in sdma would be restored to 0 then just at the end set
> to their "real value".

I was wondering about that, but it seems to work as-is.
Any real test cases for which it would matter?

> 
> Saving / Restoring all theses system zones makes more sense to me than
> to just save / restore the pic & sdma and hoping than mpc52xx_setup_cpu
> will make the rest ...
> 
> But saving/restoring all the mbar isn't good either because peripheral
> drivers should handle their own setup restore. The suspend / resume
> method of the peripheral should differentiate how deep their suspending
> / resuming and do what's necessary accordingly.

I was aiming for that.


	Domen

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

end of thread, other threads:[~2007-03-05 20:21 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-01  7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-01  7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
2007-03-01  7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
2007-03-01  7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
2007-03-01  7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
2007-03-01  7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
2007-03-01  7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
2007-03-01  7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
2007-03-01  8:49   ` Stefan Roese
2007-03-01  8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
2007-03-02 18:57   ` Scott Wood
2007-03-03  7:15     ` Domen Puncer
2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
2007-03-01 14:51   ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
2007-03-02  7:31     ` Domen Puncer
2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
2007-03-03  7:33   ` Domen Puncer
2007-03-03 19:58     ` Endianness versus too many byte swaps?? Charles Krinke
2007-03-05 10:53     ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-05 10:58       ` Sylvain Munaut
2007-03-05 20:21         ` Domen Puncer

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.