All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes
@ 2007-03-15 10:39 Domen Puncer
  2007-03-15 10:41 ` [PATCH 1/5] mpc52xx suspend: UART Domen Puncer
                   ` (5 more replies)
  0 siblings, 6 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:39 UTC (permalink / raw)
  To: linuxppc-embedded

Hi!

Some fixes, improvements from last time:
- saving/restoring of some registers inside sleep code
  (so bestcomm and pic patches can be dropped, yay)
- improvements in FEC code for deep-sleep
- set up wakeup GPIO so Efika can wake too
- patch against latest u-boot (doh)


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/5] mpc52xx suspend: UART
- [PATCH 2/5] mpc52xx suspend: FEC (ethernet)
- [PATCH 3/5] mpc52xx suspend: USB
- [PATCH 4/5] mpc52xx suspend: deep-sleep
- [PATCH] icecube/lite5200b: wakeup from low-power support
- [PATCH 5/5] lite5200b suspend: low-power mode


	Domen

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

* [PATCH 1/5] mpc52xx suspend: UART
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-15 10:41 ` Domen Puncer
  2007-03-15 10:41 ` [PATCH 2/5] mpc52xx suspend: FEC (ethernet) Domen Puncer
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:41 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] 48+ messages in thread

* [PATCH 2/5] mpc52xx suspend: FEC (ethernet)
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
  2007-03-15 10:41 ` [PATCH 1/5] mpc52xx suspend: UART Domen Puncer
@ 2007-03-15 10:41 ` Domen Puncer
  2007-03-15 13:35   ` Grant Likely
  2007-03-15 10:42 ` [PATCH 3/5] mpc52xx suspend: USB Domen Puncer
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:41 UTC (permalink / raw)
  To: linuxppc-embedded

Suspend and resume for FEC on MPC52xx.

Note that resume is a bit different for lite5200b low-power mode.


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

---
 drivers/net/fec_mpc52xx/fec.c     |   60 ++++++++++++++++++++++++++++++++++++--
 drivers/net/fec_mpc52xx/fec_phy.c |   17 ++++++++++
 drivers/net/fec_mpc52xx/fec_phy.h |    5 +++
 3 files changed, 80 insertions(+), 2 deletions(-)

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,62 @@ mpc52xx_fec_remove(struct device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static 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_device_detach(ndev);
+
+	/* 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;
+
+	/* XXX ugly hack */
+	/* not deep-sleep (but low-power), so re-init hw */
+	if (*(unsigned long *)CONFIG_KERNEL_START != 0x60000000) {
+		*(unsigned long *)CONFIG_KERNEL_START = 0x60000000; // restore
+		fec_mii_init(ndev);
+		fec_hw_init(ndev);
+	} else
+		fec_mii_resume(ndev);
+
+	/* 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);
+
+	/* Start FEC */
+	out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) | 0x2);
+
+	netif_device_attach(ndev);
+
+	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 +871,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
@@ -527,6 +527,23 @@ int fec_mii_wait(struct net_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+phy_cmd_t phy_cmd_off[] = { { mk_mii_write(MII_BMCR, BMCR_PDOWN), NULL },
+			{ mk_mii_end, } };
+phy_cmd_t phy_cmd_on[] =  { { mk_mii_write(MII_BMCR, 0), NULL },
+			{ mk_mii_end, } };
+
+void fec_mii_suspend(struct net_device *dev)
+{
+	mii_do_cmd(dev, phy_cmd_off);
+}
+
+void fec_mii_resume(struct net_device *dev)
+{
+	mii_do_cmd(dev, phy_cmd_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] 48+ messages in thread

* [PATCH 3/5] mpc52xx suspend: USB
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
  2007-03-15 10:41 ` [PATCH 1/5] mpc52xx suspend: UART Domen Puncer
  2007-03-15 10:41 ` [PATCH 2/5] mpc52xx suspend: FEC (ethernet) Domen Puncer
@ 2007-03-15 10:42 ` Domen Puncer
  2007-03-15 13:24   ` Grant Likely
  2007-03-15 10:43 ` [PATCH 4/5] mpc52xx suspend: deep-sleep Domen Puncer
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:42 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] 48+ messages in thread

* [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (2 preceding siblings ...)
  2007-03-15 10:42 ` [PATCH 3/5] mpc52xx suspend: USB Domen Puncer
@ 2007-03-15 10:43 ` Domen Puncer
  2007-03-23 15:58   ` Grant Likely
  2007-03-15 10:44   ` [U-Boot-Users] " Domen Puncer
  2007-03-15 10:44 ` [PATCH 5/5] lite5200b suspend: low-power mode Domen Puncer
  5 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:43 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.


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

---
 arch/powerpc/platforms/52xx/Makefile        |    2 
 arch/powerpc/platforms/52xx/mpc52xx_pm.c    |  124 ++++++++++++
 arch/powerpc/platforms/52xx/mpc52xx_sleep.S |  277 ++++++++++++++++++++++++++++
 3 files changed, 403 insertions(+)

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,124 @@
+#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 void __iomem *mbar;
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return 1;
+	default:
+		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;
+#ifdef CONFIG_PPC_LITE5200
+	int pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */
+	int level_low = 1; /* wakeup on low level */
+#elif defined CONFIG_PPC_EFIKA
+	int pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
+	int level_low = 0; /* wakeup on high level */
+	/* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
+#else
+#warning "define how would you like your board to wake"
+#endif
+	u16 tmp;
+
+	gpiow = mbar + 0xc00;
+	intr = mbar + 0x500;
+
+	/* 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/high level creates wakeup interrupt */
+	tmp = in_be16(&gpiow->wkup_itype);
+	tmp &= (level_low + 1) << (pin * 2);
+	tmp |= (level_low + 1) << (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));
+}
+
+int mpc52xx_pm_prepare(suspend_state_t state)
+{
+	if (state != PM_SUSPEND_STANDBY)
+		return -EINVAL;
+
+	/* map registers */
+	mbar = ioremap_nocache(0xf0000000, 0x8000);
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+
+	mpc52xx_set_wakeup_mode();
+
+	return 0;
+}
+
+char saved_sram[0x4000];
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+	static struct mpc52xx_cdm __iomem *cdm;
+	u32 clk_enables;
+	cdm = mbar + 0x200;
+
+	memcpy(saved_sram, sdma.sram, sdma.sram_size);
+
+	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);
+
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+	iounmap(mbar);
+	return 0;
+}
+
+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] 48+ messages in thread

* [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-15 10:44   ` Domen Puncer
  2007-03-15 10:41 ` [PATCH 2/5] mpc52xx suspend: FEC (ethernet) Domen Puncer
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:44 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: u-boot-users

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


---
 board/icecube/icecube.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

Index: u-boot.git/board/icecube/icecube.c
===================================================================
--- u-boot.git.orig/board/icecube/icecube.c
+++ u-boot.git/board/icecube/icecube.c
@@ -42,6 +42,54 @@
 #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_O = 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 @@ long int initdram (int board_type)
 		__asm__ volatile ("sync");
 	}
 
+	lite5200b_wakeup();
+
 	return dramsize + dramsize2;
 }
 

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-03-15 10:44   ` Domen Puncer
  0 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:44 UTC (permalink / raw)
  To: u-boot

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


---
 board/icecube/icecube.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

Index: u-boot.git/board/icecube/icecube.c
===================================================================
--- u-boot.git.orig/board/icecube/icecube.c
+++ u-boot.git/board/icecube/icecube.c
@@ -42,6 +42,54 @@
 #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_O = 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 @@ long int initdram (int board_type)
 		__asm__ volatile ("sync");
 	}
 
+	lite5200b_wakeup();
+
 	return dramsize + dramsize2;
 }
 

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

* [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
                   ` (4 preceding siblings ...)
  2007-03-15 10:44   ` [U-Boot-Users] " Domen Puncer
@ 2007-03-15 10:44 ` Domen Puncer
  2007-03-15 14:09   ` Grant Likely
  5 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 10:44 UTC (permalink / raw)
  To: linuxppc-embedded

Low-power mode implementation for Lite5200b.
Some I/O registers are also saved here.

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>

---
 arch/powerpc/platforms/52xx/Makefile         |    3 
 arch/powerpc/platforms/52xx/lite5200_pm.c    |  125 ++++++++
 arch/powerpc/platforms/52xx/lite5200_sleep.S |  419 +++++++++++++++++++++++++++
 3 files changed, 547 insertions(+)

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);
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.o
 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

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

* Re: [PATCH 3/5] mpc52xx suspend: USB
  2007-03-15 10:42 ` [PATCH 3/5] mpc52xx suspend: USB Domen Puncer
@ 2007-03-15 13:24   ` Grant Likely
  2007-03-15 14:37     ` Wrong board info for ML403 Leonid
  2007-03-22  7:44     ` [PATCH 3/5 v2] mpc52xx suspend: USB Domen Puncer
  0 siblings, 2 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-15 13:24 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Trivial suspend and resume OF OHCI.
> On MPC52xx turn off and on power to ports.
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

Nak; see below

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

#ifdef blocks are a bad idea.  It is now possible to boot one kernel
image on multiple platforms.  Chip model should be determined ahead of
time from the device tree and choose the code path accordingly at
runtime.



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

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

* Re: [PATCH 2/5] mpc52xx suspend: FEC (ethernet)
  2007-03-15 10:41 ` [PATCH 2/5] mpc52xx suspend: FEC (ethernet) Domen Puncer
@ 2007-03-15 13:35   ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-15 13:35 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Suspend and resume for FEC on MPC52xx.
>
> Note that resume is a bit different for lite5200b low-power mode.
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>

This of course cannot be applied until a mpc5200 ethernet driver is
actually in mainline.  :-)

Haven't tested, but I don't see anything evil here, other than the
"ugly hack"  :-)

g.

> +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;
> +
> +       /* XXX ugly hack */
> +       /* not deep-sleep (but low-power), so re-init hw */
> +       if (*(unsigned long *)CONFIG_KERNEL_START != 0x60000000) {
> +               *(unsigned long *)CONFIG_KERNEL_START = 0x60000000; // restore

Please avoid c++ style comments; even within ugly hacks.  :-)

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

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-15 10:44 ` [PATCH 5/5] lite5200b suspend: low-power mode Domen Puncer
@ 2007-03-15 14:09   ` Grant Likely
  2007-03-15 16:36     ` Domen Puncer
  2007-04-17  7:11     ` Domen Puncer
  0 siblings, 2 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-15 14:09 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Low-power mode implementation for Lite5200b.
> Some I/O registers are also saved here.
>
> A patch to U-Boot that wakes up SDRAM, and transfers control
> to address saved at physical 0x0 is needed.

I don't see any structural problems with this code, but I have a few
comments below.  I'm also concerned about the blind register
save/restore by memcpy_to/fromio.  I haven't looked at the chip
documentation, but it looks scary.  Is it safe to restore those
registers in that manner?

Cheers,
g.

>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
>
> ---
>  arch/powerpc/platforms/52xx/Makefile         |    3
>  arch/powerpc/platforms/52xx/lite5200_pm.c    |  125 ++++++++
>  arch/powerpc/platforms/52xx/lite5200_sleep.S |  419 +++++++++++++++++++++++++++
>  3 files changed, 547 insertions(+)
>
> 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 @@
<snip>
> +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);

Magic numbers?  Really?  This should be retrieved from the device
tree.  There is always the possibility of mbar getting moved.

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

Hmmm.  I have not dug into this deeply, but blind save/restore to
blocks of registers scares me.

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

Again, magic numbers


> 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

Please avoid c++ comments

> +
> +
> +#define DONT_DEBUG 1

Convention is to #define DEBUG to enable debugging (as opposed to
#defining something to disable it)

> +restore_regs:
> +       lis     r4, registers@h
> +       ori     r4, r4, registers@l
> +#ifdef DONT_DEBUG

should be #if !defined(DEBUG)

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

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

* Wrong board info for ML403.
  2007-03-15 13:24   ` Grant Likely
@ 2007-03-15 14:37     ` Leonid
  2007-03-16  8:15       ` Andrei Konovalov
  2007-03-22  7:44     ` [PATCH 3/5 v2] mpc52xx suspend: USB Domen Puncer
  1 sibling, 1 reply; 48+ messages in thread
From: Leonid @ 2007-03-15 14:37 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 5818 bytes --]

Hi:

I'm trying to bring up Linux on Xilinx ML403 reference board.

I took 2.6.19.2 kernel from DENX. EDK project for ML403 I took from
official Xilinx site.

I could bring up u-boot on the board, everything is working fine (see
ml403.h file attached). Then I compiled uImage for kernel and tried to
download it - I don't see any kernel's outputs:

TFTP from server 192.168.0.141; our IP address is 192.168.0.203
Filename 'LM200/rel/1.0.1d-403/uImage'.
Load address: 0x1000000
Loading: T
#################################################################
 
#################################################################
         #######################################
done
Bytes transferred = 861735 (d2627 hex)
## Booting image at 01000000 ...
   Image Name:   Linux-2.6.19.2
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    861671 Bytes = 841.5 kB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
## Current stack ends at 0x03E676F0 => set upper limit to 0x00800000
## cmdline at 0x007FFF00 ... 0x007FFFF8
memstart    = 0x00000000
memsize     = 0x04000000
flashstart  = 0x28000000
flashsize   = 0x00800000
flashoffset = 0x00000000
sramstart   = 0x00000000
sramsize    = 0x00000000
bootflags   = 0x0000003C
procfreq    =    300 MHz
plb_busfreq =    100 MHz
ethaddr     = 00:01:02:CB:CB:71
IP addr     = 192.168.0.203
baudrate    = 115200 bps
No initrd
## Transferring control to Linux (at address 00000000) ...

I have read a lot of posts and reviewed the source code and I think
these kernel trees I'm using are properly patched for using u-boot; I
only included asm/ppcboot.h into xilinx_403.h:

/* U-boot expects the bd_t to look like the one in ppcboot.h, not like
this. */
#ifdef NOT_USING_UBOOT
typedef struct board_info {
	unsigned int	 bi_memsize;		/* DRAM installed, in
bytes */
	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC
address */
	unsigned int	 bi_intfreq;		/* Processor speed, in
Hz */
	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz
*/
	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz
*/
} bd_t;

/* Some 4xx parts use a different timebase frequency from the internal
clock.
*/
#define bi_tbfreq bi_intfreq

#else
#include <asm/ppcboot.h>
#endif /* UBOOT */

Anyway I tried to compile zImage.elf and download it directly to RAM
using XMD. Here I had partial success: first time after FPGA image
downloading I try it, I see the following (it doesn't happen if I try to
repeat downloading again without reloading FPGA image first):

====
loaded at:     00400000 004DA13C
board data at: 004D8124 004D813C
relocated to:  00404090 004040A8
zimage at:     00404E1D 004D7401
avail ram:     004DB000 04000000

Linux/PPC load: console=ttyS0,115200
Uncompressing Linux...done.
Now booting the kernel
[    0.000000] Linux version 2.6.19.2 (root@mylinux.a-k-a.local) (gcc
version 4.0.0 (DENX ELDK 4.1 4.0.0)) #6 Thu Mar 15 05:46:09 PST 2007
[    0.000000] Xilinx ML403 Reference System (Virtex-4 FX)
[    0.000000] Zone PFN ranges:
[    0.000000]   DMA             0 ->    16384
[    0.000000]   Normal      16384 ->    16384
[    0.000000] early_node_map[1] active PFN ranges
[    0.000000]     0:        0 ->    16384
[    0.000000] Built 1 zonelists.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyS0,115200
[    0.000000] Xilinx INTC #0 at 0xD1000FC0 mapped to 0xFDFFEFC0
[    0.000000] PID hash table entries: 256 (order: 8, 1024 bytes)
[    0.000188] Console: colour dummy device 80x25
[    0.000701] Dentry cache hash table entries: 8192 (order: 3, 32768
bytes)
[    0.001489] Inode-cache hash table entries: 4096 (order: 2, 16384
bytes)
[    0.015326] Memory: 63104k available (1324k kernel code, 436k data,
92k init, 0k highmem)
[    0.108476] Mount-cache hash table entries: 512
[    0.114051] NET: Registered protocol family 16
[    0.128395] NET: Registered protocol family 2
[    0.168472] IP route cache hash table entries: 512 (order: -1, 2048
bytes)
[    0.169340] TCP established hash table entries: 2048 (order: 1, 8192
bytes)
[    0.169539] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[    0.169648] TCP: Hash tables configured (established 2048 bind 1024)
[    0.169679] TCP reno registered
[    0.173555] io scheduler noop registered
[    0.173600] io scheduler anticipatory registered (default)
[    0.173630] io scheduler deadline registered
[    0.173756] io scheduler cfq registered
[    0.221629] Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ
sharing disabled
[    0.227023] serial8250.0: ttyS0 at MMIO 0xa0001003 (irq = 9) is a
16450
[    0.398738] RAMDISK driver initialized: 16 RAM disks of 65536K size
1024 blocksize
[    0.407941] tun: Universal TUN/TAP device driver, 1.6
[    0.412993] tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
[    0.420583] mice: PS/2 mouse device common for all mice
[    0.426040] TCP cubic registered
[    0.429347] NET: Registered protocol family 1
[    0.433727] NET: Registered protocol family 17
[    0.439482] VFS: Cannot open root device "<NULL>" or
unknown-block(0,0)
[    0.446095] Please append a correct "root=" boot option
[    0.451282] Kernel panic - not syncing: VFS: Unable to mount root fs
on unknown-block(0,0)
[    0.459492]  <0>Rebooting in 180 seconds..

I don't care about kernel panic for now - it's to be expected since I
don't provide any filesystem. 

So, kernel itself is workable, it looks like uImage doesn't pick up
correct board info parameters from u-boot. Where u-boot write them and
where Linux looks for them? What is the simplest way to sync between
u-boot and kernel?

Thanks,

Leonid.



[-- Attachment #2: ml403.h --]
[-- Type: application/octet-stream, Size: 9114 bytes --]

/*
 * ML403.h: ML403 specific config options
 *
 * http://www.xilinx.com/ml403
 *
 * Derived from : ml300.h
 *
 *     Author: Xilinx, 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.
 *
 *
 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
 *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
 *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR
 *     OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
 *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
 *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
 *     FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 *     Xilinx products are not intended for use in life support appliances,
 *     devices, or systems. Use in such applications is expressly prohibited.
 *
 *
 *     (c) Copyright 2002-2005 Xilinx Inc.
 *     All rights reserved.
 *
 *
 *     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.,
 *     675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifndef __CONFIG_H
#define __CONFIG_H

/* #define DEBUG */
/* #define ET_DEBUG 1 */

/*
 * High Level Configuration Options
 * (easy to change)
 */

#define CONFIG_405		1	/* This is a PPC405 CPU		*/
#define CONFIG_4xx		1	/* ...member of PPC4xx family	*/
#define CONFIG_XILINX_ML403	1	/* ...on a Xilinx ML403 board	*/

#include "../board/xilinx/ml403/xparameters.h"

/*  Make some configuration choices based on the hardware design
 *  specified in xparameters.h.
 */

#define CONFIG_FLASH_START         XPAR_OPB_EMC_0_MEM1_BASEADDR
#define CONFIG_FLASH_BOOT_START	   CONFIG_FLASH_START
#define CONFIG_FLASH_BOOT_SIZE		                0x80000
#define CONFIG_FLASH_BOOTENV_START (CONFIG_FLASH_BOOT_START+CONFIG_FLASH_BOOT_SIZE)
#define CONFIG_FLASH_BOOTENV_SIZE		        0x40000
#define CONFIG_FLASH_CONFIG_START  (CONFIG_FLASH_BOOTENV_START+CONFIG_FLASH_BOOTENV_SIZE)
#define CONFIG_FLASH_CONFIG_SIZE		        0x40000
#define CONFIG_TEXT_BASE                             0x03e00000

#ifdef XPAR_SYSACE_0_DEVICE_ID
#define CONFIG_SYSTEMACE	1
#define CONFIG_DOS_PARTITION	1
#define CFG_SYSTEMACE_BASE	XPAR_SYSACE_0_BASEADDR
#define CFG_SYSTEMACE_WIDTH	XPAR_SYSACE_0_MEM_WIDTH
#define ADD_SYSTEMACE_CMDS      | CFG_CMD_FAT
#define RM_SYSTEMACE_CMDS
#else
#define ADD_SYSTEMACE_CMDS
#define RM_SYSTEMACE_CMDS       | CFG_CMD_FAT
#endif

#if 1  /* assume that we do not have Flash */
#define CFG_ENV_IS_IN_FLASH	1	/* environment is in FLASH */
#define ADD_FLASH_CMDS          | CFG_CMD_FLASH
#define RM_FLASH_CMDS
#else
#define ADD_FLASH_CMDS
#define RM_FLASH_CMDS           | CFG_CMD_FLASH
#define CFG_NO_FLASH            1
#endif

#ifdef XPAR_IIC_0_DEVICE_ID
#if ! defined(CFG_ENV_IS_IN_FLASH)
#define CFG_ENV_IS_IN_EEPROM	1	/* environment is in IIC EEPROM */
#endif
#define ADD_IIC_CMDS            | CFG_CMD_I2C
#define RM_IIC_CMDS
#else
#define ADD_IIC_CMDS
#define RM_IIC_CMDS             | CFG_CMD_I2C
#endif

#ifdef XPAR_EMAC_0_DEVICE_ID
#define CONFIG_ETHADDR          00:0a:35:00:22:01
#define ADD_NET_CMDS            | CFG_CMD_PING | CFG_CMD_NET | CFG_CMD_DHCP
#define RM_NET_CMDS
#else
#define ADD_NET_CMDS
#define RM_NET_CMDS             | CFG_CMD_PING | CFG_CMD_NET | CFG_CMD_DHCP
#endif

#if ! (defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_IS_IN_EEPROM))
#define CFG_ENV_IS_NOWHERE      1       /* no space to store environment */
#define CFG_ENV_SIZE		1024
#define CFG_MONITOR_BASE	0x02000000
#endif

/* following are used only if env is in EEPROM */
#ifdef	CFG_ENV_IS_IN_EEPROM
#define CFG_I2C_EEPROM_ADDR             (0xA0 >> 1)
#define CFG_I2C_EEPROM_ADDR_LEN         1
#define CFG_I2C_EEPROM_ADDR_OVERFLOW    0x1
#define CFG_ENV_OFFSET                  0
#define CFG_ENV_SIZE                    256
#define CFG_EEPROM_PAGE_WRITE_BITS      5
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS  5
#define CONFIG_ENV_OVERWRITE            1  /* writable ethaddr and serial# */
#define CFG_MONITOR_BASE                0x02000000
#endif

/* following are used only if env is in Flash */
#ifdef CFG_ENV_IS_IN_FLASH
#define CFG_FLASH_BASE		CONFIG_FLASH_START
#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks        */
#define CFG_MAX_FLASH_SECT	256	/* max number of sectors on one chip */
#define CFG_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)   */
#define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)   */
#define CFG_FLASH_CFI
#define CFG_FLASH_CFI_DRIVER
#define CFG_ENV_ADDR		CONFIG_FLASH_BOOTENV_START
#define CFG_ENV_OFFSET          CONFIG_FLASH_BOOTENV_START
#define CFG_ENV_SIZE            CONFIG_FLASH_BOOTENV_SIZE
#define CONFIG_ENV_OVERWRITE    1       /* writable ethaddr and serial# */
  #if defined(CONFIG_BOOT_ROM)
  #define CFG_MONITOR_BASE	0xFFFC0000
  #else
  #define CFG_MONITOR_BASE	CONFIG_TEXT_BASE
  #endif
#endif

#define CONFIG_BAUDRATE         115200 
#define CONFIG_BOOTDELAY        5       /* autoboot after 3 seconds	*/

#define CONFIG_BOOTCOMMAND      "bootm ffe00000" /* autoboot command	*/

#define CONFIG_BOOTARGS         "console=ttyS0,115200 ip=off " \
                                "root=/dev/xsysace/disc0/part2 rw"

#define CONFIG_LOADS_ECHO       1       /* echo on for serial download	*/
#define CFG_LOADS_BAUD_CHANGE   1       /* allow baudrate change	*/

#define REMOVE_COMMANDS	       0

/*
#define REMOVE_COMMANDS	       (CFG_CMD_LOADS | \
                                CFG_CMD_IMLS \
                                RM_IIC_CMDS \
                                RM_SYSTEMACE_CMDS \
			        RM_NET_CMDS \
                                RM_FLASH_CMDS)
*/

#define CONFIG_COMMANDS	       ((CONFIG_CMD_DFL | CFG_CMD_ELF \
                                 ADD_IIC_CMDS \
                                 ADD_SYSTEMACE_CMDS \
                                 ADD_NET_CMDS \
                                 ADD_FLASH_CMDS) \
				& ~REMOVE_COMMANDS)

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>

/*
 * Miscellaneous configurable options
 */
#define CFG_LONGHELP		/* undef to save memory		*/
#define CFG_PROMPT	"=> "	/* Monitor Command Prompt	*/

#define CFG_CBSIZE	256	/* Console I/O Buffer Size	*/

#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print Buffer Size */
#define CFG_MAXARGS	16	/* max number of command args	*/
#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/

#define CFG_MEMTEST_START	0x0400000	/* memtest works on	*/
#define CFG_MEMTEST_END		0x0C00000	/* 4 ... 12 MB in DRAM	*/

#define CFG_DUART_CHAN		0
#define CFG_NS16550_REG_SIZE   -4
#define CFG_NS16550             1
#define CFG_INIT_CHAN1	        1

/* The following table includes the supported baudrates */
#define CFG_BAUDRATE_TABLE  \
    {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}

#define CFG_LOAD_ADDR		0x400000	/* default load address */
#define CFG_EXTBDINFO		1	/* To use extended board_into (bd_t) */

#define CFG_HZ		1000	/* decrementer freq: 1 ms ticks */

/*-----------------------------------------------------------------------
 * Start addresses for the final memory configuration
 * (Set up by the startup code)
 * Please note that CFG_SDRAM_BASE _must_ start at 0
 */
#define CFG_SDRAM_BASE		0x00000000
#define CFG_MONITOR_LEN		(192 * 1024)	/* Reserve 196 kB for Monitor	*/
#define CFG_MALLOC_LEN		(1024 * 1024)	/* Reserve 128 kB for malloc()	*/

/*
 * For booting Linux, the board info and command line data
 * have to be in the first 8 MB of memory, since this is
 * the maximum mapped by the Linux kernel during initialization.
 */
#define CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux */

/*-----------------------------------------------------------------------
 * Cache Configuration
 */
#define CFG_DCACHE_SIZE		16384	/* Virtex-II Pro PPC 405 CPUs	*/
#define CFG_CACHELINE_SIZE	32	/* ...			        */

/*-----------------------------------------------------------------------
 * Definitions for initial stack pointer and data area (in DPRAM)
 */

#define CFG_INIT_RAM_ADDR	0x800000  /* inside of SDRAM */
#define CFG_INIT_RAM_END	0x2000	  /* End of used area in RAM */
#define CFG_GBL_DATA_SIZE	128	  /* size in bytes reserved for initial data */
#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
#define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET

/*
 * Internal Definitions
 *
 * Boot Flags
 */
#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH	*/
#define BOOTFLAG_WARM	0x02	/* Software reboot			*/

#endif				/* __CONFIG_H */

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-15 14:09   ` Grant Likely
@ 2007-03-15 16:36     ` Domen Puncer
  2007-03-22  7:41       ` Domen Puncer
  2007-04-17  7:11     ` Domen Puncer
  1 sibling, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-15 16:36 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

On 15/03/07 08:09 -0600, Grant Likely wrote:
> On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> >Low-power mode implementation for Lite5200b.
> >Some I/O registers are also saved here.
> >
> >A patch to U-Boot that wakes up SDRAM, and transfers control
> >to address saved at physical 0x0 is needed.
> 
> I don't see any structural problems with this code, but I have a few
> comments below.  I'm also concerned about the blind register
> save/restore by memcpy_to/fromio.  I haven't looked at the chip
> documentation, but it looks scary.  Is it safe to restore those
> registers in that manner?
> 
...
> >+       /* map registers */
> >+       mbar = ioremap_nocache(0xf0000000, 0x8000);
> 
> Magic numbers?  Really?  This should be retrieved from the device
> tree.  There is always the possibility of mbar getting moved.
> 
...
> >+       gpw = mbar + 0xc00;
> >+       bes = mbar + 0x1200;
> >+       xlb = mbar + 0x1f00;
> 
> Again, magic numbers

Well... the code is only applicable for Lite5200b/mpc5200
and numbers are from specs.
And it's shorter than mpc52xx_find_and_map() lines.
I guess I could rewrite it.

> >+       _memcpy_fromio(&scdm, cdm, sizeof(*cdm));
> >+       _memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
> >+       _memcpy_fromio(&sgps, gps, sizeof(*gps));
> >+       _memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
> 
> Hmmm.  I have not dug into this deeply, but blind save/restore to
> blocks of registers scares me.

Seems to work (tm), I'll look at datasheet.

> >+// about 2000 cpu cycles for one sdram cycle here
> >+// just increase, to be on the safe side?
> >+#define TCK    5000
> 
> Please avoid c++ comments

// are in ANSI C99 too, but ok, I know kernel folks don't like them :-)


> >+#define DONT_DEBUG 1
> 
> Convention is to #define DEBUG to enable debugging (as opposed to
> #defining something to disable it)

Yeah, makes sense.


	Domen

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

* Re: Wrong board info for ML403.
  2007-03-15 14:37     ` Wrong board info for ML403 Leonid
@ 2007-03-16  8:15       ` Andrei Konovalov
  0 siblings, 0 replies; 48+ messages in thread
From: Andrei Konovalov @ 2007-03-16  8:15 UTC (permalink / raw)
  To: Leonid; +Cc: linuxppc-embedded

Hello,

Haven't tried using u-boot with these boards, but here are couple earlier postings
to this list (sorry if you have look through them already):

-------- Original Message --------
Subject: Re: ML403 patch for UBOOT
Date: Mon, 25 Sep 2006 09:19:10 -0700
From: Peter Ryser <peter.ryser@xilinx.com>
To: Linuxppc-embedded@ozlabs.org

You might want to start with XAPP542
http://direct.xilinx.com/bvdocs/appnotes/xapp542.pdf
http://direct.xilinx.com/bvdocs/appnotes/xapp542.zip

The zip file includes the U-Boot patch for Linux kernel 2.4.

- Peter
-------- End of Original Message --------


-------- Original Message --------
Subject: Re: Led astray? Xilinx ml410 + u-boot + Linux?
Date: Thu, 01 Feb 2007 06:57:50 -0800
From: Peter Ryser <peter.ryser@xilinx.com>
To: linuxppc-embedded@ozlabs.org

Joe,

please have a look at http://www.xilinx.com/ml410-p. The pages do
contain information, documentation, and examples on how to use U-Boot
and Linux 2.4 on the ML410.
<snip>
-------- End of Original Message --------

For me this sounds like
1) patching kernel is required to get the correct params from u-boot
2) Xilinx has the recipes for 2.4 kernel
3) there is no ready-to-use recipe for 2.6 kernel, but it should not
    be too difficult to adapt the one for 2.4 kernel


Thanks,
Andrei

Leonid wrote:
> Hi:
> 
> I'm trying to bring up Linux on Xilinx ML403 reference board.
> 
> I took 2.6.19.2 kernel from DENX. EDK project for ML403 I took from
> official Xilinx site.
> 
> I could bring up u-boot on the board, everything is working fine (see
> ml403.h file attached). Then I compiled uImage for kernel and tried to
> download it - I don't see any kernel's outputs:
> 
> TFTP from server 192.168.0.141; our IP address is 192.168.0.203
> Filename 'LM200/rel/1.0.1d-403/uImage'.
> Load address: 0x1000000
> Loading: T
> #################################################################
>  
> #################################################################
>          #######################################
> done
> Bytes transferred = 861735 (d2627 hex)
> ## Booting image at 01000000 ...
>    Image Name:   Linux-2.6.19.2
>    Image Type:   PowerPC Linux Kernel Image (gzip compressed)
>    Data Size:    861671 Bytes = 841.5 kB
>    Load Address: 00000000
>    Entry Point:  00000000
>    Verifying Checksum ... OK
>    Uncompressing Kernel Image ... OK
> ## Current stack ends at 0x03E676F0 => set upper limit to 0x00800000
> ## cmdline at 0x007FFF00 ... 0x007FFFF8
> memstart    = 0x00000000
> memsize     = 0x04000000
> flashstart  = 0x28000000
> flashsize   = 0x00800000
> flashoffset = 0x00000000
> sramstart   = 0x00000000
> sramsize    = 0x00000000
> bootflags   = 0x0000003C
> procfreq    =    300 MHz
> plb_busfreq =    100 MHz
> ethaddr     = 00:01:02:CB:CB:71
> IP addr     = 192.168.0.203
> baudrate    = 115200 bps
> No initrd
> ## Transferring control to Linux (at address 00000000) ...
> 
> I have read a lot of posts and reviewed the source code and I think
> these kernel trees I'm using are properly patched for using u-boot; I
> only included asm/ppcboot.h into xilinx_403.h:
> 
> /* U-boot expects the bd_t to look like the one in ppcboot.h, not like
> this. */
> #ifdef NOT_USING_UBOOT
> typedef struct board_info {
> 	unsigned int	 bi_memsize;		/* DRAM installed, in
> bytes */
> 	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC
> address */
> 	unsigned int	 bi_intfreq;		/* Processor speed, in
> Hz */
> 	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz
> */
> 	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz
> */
> } bd_t;
> 
> /* Some 4xx parts use a different timebase frequency from the internal
> clock.
> */
> #define bi_tbfreq bi_intfreq
> 
> #else
> #include <asm/ppcboot.h>
> #endif /* UBOOT */
> 
> Anyway I tried to compile zImage.elf and download it directly to RAM
> using XMD. Here I had partial success: first time after FPGA image
> downloading I try it, I see the following (it doesn't happen if I try to
> repeat downloading again without reloading FPGA image first):
> 
> ====
> loaded at:     00400000 004DA13C
> board data at: 004D8124 004D813C
> relocated to:  00404090 004040A8
> zimage at:     00404E1D 004D7401
> avail ram:     004DB000 04000000
> 
> Linux/PPC load: console=ttyS0,115200
> Uncompressing Linux...done.
> Now booting the kernel
> [    0.000000] Linux version 2.6.19.2 (root@mylinux.a-k-a.local) (gcc
> version 4.0.0 (DENX ELDK 4.1 4.0.0)) #6 Thu Mar 15 05:46:09 PST 2007
> [    0.000000] Xilinx ML403 Reference System (Virtex-4 FX)
> [    0.000000] Zone PFN ranges:
> [    0.000000]   DMA             0 ->    16384
> [    0.000000]   Normal      16384 ->    16384
> [    0.000000] early_node_map[1] active PFN ranges
> [    0.000000]     0:        0 ->    16384
> [    0.000000] Built 1 zonelists.  Total pages: 16256
> [    0.000000] Kernel command line: console=ttyS0,115200
> [    0.000000] Xilinx INTC #0 at 0xD1000FC0 mapped to 0xFDFFEFC0
> [    0.000000] PID hash table entries: 256 (order: 8, 1024 bytes)
> [    0.000188] Console: colour dummy device 80x25
> [    0.000701] Dentry cache hash table entries: 8192 (order: 3, 32768
> bytes)
> [    0.001489] Inode-cache hash table entries: 4096 (order: 2, 16384
> bytes)
> [    0.015326] Memory: 63104k available (1324k kernel code, 436k data,
> 92k init, 0k highmem)
> [    0.108476] Mount-cache hash table entries: 512
> [    0.114051] NET: Registered protocol family 16
> [    0.128395] NET: Registered protocol family 2
> [    0.168472] IP route cache hash table entries: 512 (order: -1, 2048
> bytes)
> [    0.169340] TCP established hash table entries: 2048 (order: 1, 8192
> bytes)
> [    0.169539] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> [    0.169648] TCP: Hash tables configured (established 2048 bind 1024)
> [    0.169679] TCP reno registered
> [    0.173555] io scheduler noop registered
> [    0.173600] io scheduler anticipatory registered (default)
> [    0.173630] io scheduler deadline registered
> [    0.173756] io scheduler cfq registered
> [    0.221629] Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ
> sharing disabled
> [    0.227023] serial8250.0: ttyS0 at MMIO 0xa0001003 (irq = 9) is a
> 16450
> [    0.398738] RAMDISK driver initialized: 16 RAM disks of 65536K size
> 1024 blocksize
> [    0.407941] tun: Universal TUN/TAP device driver, 1.6
> [    0.412993] tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
> [    0.420583] mice: PS/2 mouse device common for all mice
> [    0.426040] TCP cubic registered
> [    0.429347] NET: Registered protocol family 1
> [    0.433727] NET: Registered protocol family 17
> [    0.439482] VFS: Cannot open root device "<NULL>" or
> unknown-block(0,0)
> [    0.446095] Please append a correct "root=" boot option
> [    0.451282] Kernel panic - not syncing: VFS: Unable to mount root fs
> on unknown-block(0,0)
> [    0.459492]  <0>Rebooting in 180 seconds..
> 
> I don't care about kernel panic for now - it's to be expected since I
> don't provide any filesystem. 
> 
> So, kernel itself is workable, it looks like uImage doesn't pick up
> correct board info parameters from u-boot. Where u-boot write them and
> where Linux looks for them? What is the simplest way to sync between
> u-boot and kernel?
> 
> Thanks,
> 
> Leonid.
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-15 16:36     ` Domen Puncer
@ 2007-03-22  7:41       ` Domen Puncer
  2007-03-26 13:23         ` Domen Puncer
  0 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-22  7:41 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

On 15/03/07 17:36 +0100, Domen Puncer wrote:
> On 15/03/07 08:09 -0600, Grant Likely wrote:
> > On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> ...
> > >+       /* map registers */
> > >+       mbar = ioremap_nocache(0xf0000000, 0x8000);
> > 
> > Magic numbers?  Really?  This should be retrieved from the device
> > tree.  There is always the possibility of mbar getting moved.
> > 
> ...
> > >+       gpw = mbar + 0xc00;
> > >+       bes = mbar + 0x1200;
> > >+       xlb = mbar + 0x1f00;
> > 
> > Again, magic numbers
> 
> Well... the code is only applicable for Lite5200b/mpc5200
> and numbers are from specs.
> And it's shorter than mpc52xx_find_and_map() lines.
> I guess I could rewrite it.

In asm code I need access to SDRAM controller registers (MBAR+0x100).
Do I add an entry to dts, or do you have other suggestions?


	Domen

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

* [PATCH 3/5 v2] mpc52xx suspend: USB
  2007-03-15 13:24   ` Grant Likely
  2007-03-15 14:37     ` Wrong board info for ML403 Leonid
@ 2007-03-22  7:44     ` Domen Puncer
  2007-03-23 11:56       ` Sylvain Munaut
  1 sibling, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-22  7:44 UTC (permalink / raw)
  To: Grant Likely; +Cc: 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>

---
 drivers/usb/host/ohci-ppc-of.c |   30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

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);
+	if (machine_is_compatible("generic-mpc5200")) {
+		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);
+	}
+	return 0;
+}
+static int ohci_hcd_ppc_soc_drv_resume(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+	if (machine_is_compatible("generic-mpc5200")) {
+		struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+		out_be32(&ohci->regs->roothub.a, descr_a);
+	}
+	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] 48+ messages in thread

* Re: [PATCH 3/5 v2] mpc52xx suspend: USB
  2007-03-22  7:44     ` [PATCH 3/5 v2] mpc52xx suspend: USB Domen Puncer
@ 2007-03-23 11:56       ` Sylvain Munaut
  2007-03-23 16:00         ` Grant Likely
  0 siblings, 1 reply; 48+ messages in thread
From: Sylvain Munaut @ 2007-03-23 11:56 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

Domen Puncer wrote:
> +	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
> +	if (machine_is_compatible("generic-mpc5200")) {
> +		struct ohci_hcd *ohci = hcd_to_ohci(hcd);
>
>   
Not good, what if you have a Ohci PCI card on a 5200 board ...

You somehow need to check the compatible list of the of_node associated
with the particular instance you're putting to sleep.


    Sylvain
 

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

* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-03-15 10:43 ` [PATCH 4/5] mpc52xx suspend: deep-sleep Domen Puncer
@ 2007-03-23 15:58   ` Grant Likely
  2007-04-04  7:37     ` Domen Puncer
  0 siblings, 1 reply; 48+ messages in thread
From: Grant Likely @ 2007-03-23 15:58 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> 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.

Some more comments...

> Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
> ===================================================================
> --- /dev/null
> +++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
> +/* 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;
> +#ifdef CONFIG_PPC_LITE5200
> +       int pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */
> +       int level_low = 1; /* wakeup on low level */
> +#elif defined CONFIG_PPC_EFIKA
> +       int pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
> +       int level_low = 0; /* wakeup on high level */
> +       /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
> +#else
> +#warning "define how would you like your board to wake"
> +#endif

The EFIKA and LITE5200 support needs to coexist.  efika.c and
lite5200.c should each have their own set_wakeup_mode function.  The
correct function pointer should be selected from *_setup_arch().

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

Adding a new arch_initcall is dangerous.  It gets called on *all*
architectures if the 5200 support is compiled in.  mp52xx_pm_init
should be called from the setup_arch hook; lite5200_setup_arch() &
efika_setup_arch()

Cheers,
g.

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

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

* Re: [PATCH 3/5 v2] mpc52xx suspend: USB
  2007-03-23 11:56       ` Sylvain Munaut
@ 2007-03-23 16:00         ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-23 16:00 UTC (permalink / raw)
  To: Sylvain Munaut, Domen Puncer; +Cc: linuxppc-embedded

On 3/23/07, Sylvain Munaut <tnt@246tnt.com> wrote:
> Domen Puncer wrote:
> > +     struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
> > +     if (machine_is_compatible("generic-mpc5200")) {
> > +             struct ohci_hcd *ohci = hcd_to_ohci(hcd);
> >
> >
> Not good, what if you have a Ohci PCI card on a 5200 board ...
>
> You somehow need to check the compatible list of the of_node associated
> with the particular instance you're putting to sleep.

Also, I don't think the device tree should be queried at runtime
inside the suspend/resume functions.  All device tree queries should
probably go into the probe() routine and the results cached.

However, I'm no longer convinced that this is the correct approach.
I've gone and looked at the 5200b usb documentation, and it looks to
me like the handling of port power is really a board/system specific
thing.  For example, a new system might require port power to be
forced on when the processor is suspended.

I think this code should be moved to the board support code in
arch/powerpc/platforms/52xx.

Cheers,
g.

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

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-22  7:41       ` Domen Puncer
@ 2007-03-26 13:23         ` Domen Puncer
  2007-03-26 15:54           ` Grant Likely
  0 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-03-26 13:23 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

On 22/03/07 08:41 +0100, Domen Puncer wrote:
> On 15/03/07 17:36 +0100, Domen Puncer wrote:
> > On 15/03/07 08:09 -0600, Grant Likely wrote:
> > > On 3/15/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> > ...
> > > >+       /* map registers */
> > > >+       mbar = ioremap_nocache(0xf0000000, 0x8000);
> > > 
> > > Magic numbers?  Really?  This should be retrieved from the device
> > > tree.  There is always the possibility of mbar getting moved.
> > > 
> > ...
> > > >+       gpw = mbar + 0xc00;
> > > >+       bes = mbar + 0x1200;
> > > >+       xlb = mbar + 0x1f00;
> > > 
> > > Again, magic numbers
> > 
> > Well... the code is only applicable for Lite5200b/mpc5200
> > and numbers are from specs.
> > And it's shorter than mpc52xx_find_and_map() lines.
> > I guess I could rewrite it.
> 
> In asm code I need access to SDRAM controller registers (MBAR+0x100).
> Do I add an entry to dts, or do you have other suggestions?

And on efika, the same problem + there is no CDM nor (wakeup)
gpio's in device tree. What to do there?


	Domen

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-26 13:23         ` Domen Puncer
@ 2007-03-26 15:54           ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-26 15:54 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 3/26/07, Domen Puncer <domen@coderock.org> wrote:
> On 22/03/07 08:41 +0100, Domen Puncer wrote:
> > On 15/03/07 17:36 +0100, Domen Puncer wrote:
> > > Well... the code is only applicable for Lite5200b/mpc5200
> > > and numbers are from specs.
> > > And it's shorter than mpc52xx_find_and_map() lines.
> > > I guess I could rewrite it.
> >
> > In asm code I need access to SDRAM controller registers (MBAR+0x100).
> > Do I add an entry to dts, or do you have other suggestions?

Fair enough; this is chip-specific code after all; not device driver
code.  MBAR must always be retrieved from the device tree, but these
offsets from MBAR will never move, so you don't need to pull them from
the device tree.  At least comment it as to where the numbers came
from.

g.

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

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-03-15 10:44   ` [U-Boot-Users] " Domen Puncer
@ 2007-03-26 16:08     ` Grant Likely
  -1 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-26 16:08 UTC (permalink / raw)
  To: Domen Puncer; +Cc: u-boot-users, linuxppc-embedded

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.

This looks pretty straight forward.

My only comment is that psc2_4 is probably used as GPIO instead of
power control by some users (The lite5200 is an eval board after all).
 Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
CONFIG_LITE5200B) so that it can be easily compiled out.

Also, '//' style comments should be changed to '/* */'

Otherwise;
Acked-by: Grant Likely <grant.likely@secretlab.ca>

g.

>
> ---
>  board/icecube/icecube.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
>
> Index: u-boot.git/board/icecube/icecube.c
> ===================================================================
> --- u-boot.git.orig/board/icecube/icecube.c
> +++ u-boot.git/board/icecube/icecube.c
> @@ -42,6 +42,54 @@
>  #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_O = 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 @@ long int initdram (int board_type)
>                 __asm__ volatile ("sync");
>         }
>
> +       lite5200b_wakeup();
> +
>         return dramsize + dramsize2;
>  }

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-03-26 16:08     ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-03-26 16:08 UTC (permalink / raw)
  To: u-boot

On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.

This looks pretty straight forward.

My only comment is that psc2_4 is probably used as GPIO instead of
power control by some users (The lite5200 is an eval board after all).
 Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
CONFIG_LITE5200B) so that it can be easily compiled out.

Also, '//' style comments should be changed to '/* */'

Otherwise;
Acked-by: Grant Likely <grant.likely@secretlab.ca>

g.

>
> ---
>  board/icecube/icecube.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
>
> Index: u-boot.git/board/icecube/icecube.c
> ===================================================================
> --- u-boot.git.orig/board/icecube/icecube.c
> +++ u-boot.git/board/icecube/icecube.c
> @@ -42,6 +42,54 @@
>  #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_O = 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 @@ long int initdram (int board_type)
>                 __asm__ volatile ("sync");
>         }
>
> +       lite5200b_wakeup();
> +
>         return dramsize + dramsize2;
>  }

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-03-15 10:44   ` [U-Boot-Users] " Domen Puncer
@ 2007-03-31 17:20     ` Rafal Jaworowski
  -1 siblings, 0 replies; 48+ messages in thread
From: Rafal Jaworowski @ 2007-03-31 17:20 UTC (permalink / raw)
  To: Domen Puncer; +Cc: u-boot-users, linuxppc-embedded

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.
> 

Hi Domen,

As I understand while waking up from the low-power mode the machine is 
effectively powering on, similarly to the cold reset, so U-Boot runs 
from the beginning as usual, but after the SDRAM controller has been 
initialised we detect the wakeup and teleport to the saved DRAM address.

Since in case of a wakeup from the low-power mode we skip everything in 
U-Boot that is happening past initdram(), please clarify the following:

- are you sure there are no steps beyond init_func_ram()/board_init_f() 
that should be performed while waking up? For example:

- are all timers settings properly re-stored?

- wouldn't the host/PCI bridge need to be re-initialised and 
re-configured as part of the wakeup process? Did you happen to test some 
PCI devices and would they survive after wakeup from the the low-power 
mode? (A similar question would apply to the USB controller)

Also, a more general question: isn't time base update required after the 
wakeup, specially if it's been a long sleep?

kind regards,
Rafal

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-03-31 17:20     ` Rafal Jaworowski
  0 siblings, 0 replies; 48+ messages in thread
From: Rafal Jaworowski @ 2007-03-31 17:20 UTC (permalink / raw)
  To: u-boot

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.
> 

Hi Domen,

As I understand while waking up from the low-power mode the machine is 
effectively powering on, similarly to the cold reset, so U-Boot runs 
from the beginning as usual, but after the SDRAM controller has been 
initialised we detect the wakeup and teleport to the saved DRAM address.

Since in case of a wakeup from the low-power mode we skip everything in 
U-Boot that is happening past initdram(), please clarify the following:

- are you sure there are no steps beyond init_func_ram()/board_init_f() 
that should be performed while waking up? For example:

- are all timers settings properly re-stored?

- wouldn't the host/PCI bridge need to be re-initialised and 
re-configured as part of the wakeup process? Did you happen to test some 
PCI devices and would they survive after wakeup from the the low-power 
mode? (A similar question would apply to the USB controller)

Also, a more general question: isn't time base update required after the 
wakeup, specially if it's been a long sleep?

kind regards,
Rafal

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-03-31 17:20     ` [U-Boot-Users] " Rafal Jaworowski
@ 2007-03-31 18:38       ` Domen Puncer
  -1 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-31 18:38 UTC (permalink / raw)
  To: u-boot

[ Gah, saw it didn't make it to u-boot ML, resending ]

On 31/03/07 19:20 +0200, Rafal Jaworowski wrote:
> 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.
> >
> 
> Hi Domen,

Hi!
> 
> As I understand while waking up from the low-power mode the machine is 
> effectively powering on, similarly to the cold reset, so U-Boot runs 
> from the beginning as usual, but after the SDRAM controller has been 
> initialised we detect the wakeup and teleport to the saved DRAM address.

Right.

> 
> Since in case of a wakeup from the low-power mode we skip everything in 
> U-Boot that is happening past initdram(), please clarify the following:
> 
> - are you sure there are no steps beyond init_func_ram()/board_init_f() 
> that should be performed while waking up? For example:
> 
> - are all timers settings properly re-stored?

Hmm... right, I forgot to restart watchdog... but that will be done in
Linux code.

> 
> - wouldn't the host/PCI bridge need to be re-initialised and 
> re-configured as part of the wakeup process? Did you happen to test some 
> PCI devices and would they survive after wakeup from the the low-power 
> mode? (A similar question would apply to the USB controller)

Honestly, I don't know for PCI. IIRC some time ago, kernel compiled
with CONFIG_PCI didn't boot for me.

USB controller/devices survived the wakeup last time I checked.

> 
> Also, a more general question: isn't time base update required after the 
> wakeup, specially if it's been a long sleep?

Lite5200b doesn't have an external time source.


Thanks!

	Domen

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-03-31 18:38       ` Domen Puncer
  0 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-03-31 18:38 UTC (permalink / raw)
  To: Rafal Jaworowski; +Cc: u-boot-users, linuxppc-embedded

On 31/03/07 19:20 +0200, Rafal Jaworowski wrote:
> 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.
> >
> 
> Hi Domen,

Hi!
> 
> As I understand while waking up from the low-power mode the machine is 
> effectively powering on, similarly to the cold reset, so U-Boot runs 
> from the beginning as usual, but after the SDRAM controller has been 
> initialised we detect the wakeup and teleport to the saved DRAM address.

Right.

> 
> Since in case of a wakeup from the low-power mode we skip everything in 
> U-Boot that is happening past initdram(), please clarify the following:
> 
> - are you sure there are no steps beyond init_func_ram()/board_init_f() 
> that should be performed while waking up? For example:
> 
> - are all timers settings properly re-stored?

Hmm... right, I forgot to restart watchdog... but that will be done in
Linux code.

> 
> - wouldn't the host/PCI bridge need to be re-initialised and 
> re-configured as part of the wakeup process? Did you happen to test some 
> PCI devices and would they survive after wakeup from the the low-power 
> mode? (A similar question would apply to the USB controller)

Honestly, I don't know for PCI. IIRC some time ago, kernel compiled
with CONFIG_PCI didn't boot for me.

USB controller/devices survived the wakeup last time I checked.

> 
> Also, a more general question: isn't time base update required after the 
> wakeup, specially if it's been a long sleep?

Lite5200b doesn't have an external time source.


Thanks!

	Domen

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-03-26 16:08     ` [U-Boot-Users] " Grant Likely
@ 2007-04-03  8:46       ` Domen Puncer
  -1 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-03  8:46 UTC (permalink / raw)
  To: Grant Likely; +Cc: u-boot-users, 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.


---
On 26/03/07 10:08 -0600, Grant Likely wrote:
> On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.
> 
> This looks pretty straight forward.
> 
> My only comment is that psc2_4 is probably used as GPIO instead of
> power control by some users (The lite5200 is an eval board after all).
> Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
> CONFIG_LITE5200B) so that it can be easily compiled out.
> 
> Also, '//' style comments should be changed to '/* */'
> 
> Otherwise;
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 

OK. This one should be better:

 Makefile                |    5 ++++
 board/icecube/icecube.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

Index: u-boot.git/board/icecube/icecube.c
===================================================================
--- u-boot.git.orig/board/icecube/icecube.c
+++ u-boot.git/board/icecube/icecube.c
@@ -42,6 +42,53 @@
 #include "mt48lc16m16a2-75.h"
 # endif
 #endif
+
+#ifdef CONFIG_LITE5200B_PM
+/* 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_O = 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 +255,8 @@ long int initdram (int board_type)
 		__asm__ volatile ("sync");
 	}
 
+	lite5200b_wakeup();
+
 	return dramsize + dramsize2;
 }
 
Index: u-boot.git/Makefile
===================================================================
--- u-boot.git.orig/Makefile
+++ u-boot.git/Makefile
@@ -430,6 +430,7 @@ inka4x0_config:	unconfig
 	@$(MKCONFIG) inka4x0 ppc mpc5xxx inka4x0
 
 lite5200b_config	\
+lite5200b_PM_config	\
 lite5200b_LOWBOOT_config:	unconfig
 	@mkdir -p $(obj)include
 	@mkdir -p $(obj)board/icecube
@@ -438,6 +439,10 @@ lite5200b_LOWBOOT_config:	unconfig
 	@ echo "... DDR memory revision"
 	@ echo "#define CONFIG_MPC5200"		>>$(obj)include/config.h
 	@ echo "#define CONFIG_LITE5200B"	>>$(obj)include/config.h
+	@[ -z "$(findstring _PM_,$@)" ] || \
+		{ echo "#define CONFIG_LITE5200B_PM"	>>$(obj)include/config.h ; \
+		  echo "... with power management (low-power mode) support" ; \
+		}
 	@[ -z "$(findstring LOWBOOT_,$@)" ] || \
 		{ echo "TEXT_BASE = 0xFF000000" >$(obj)board/icecube/config.tmp ; \
 		  echo "... with LOWBOOT configuration" ; \

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-04-03  8:46       ` Domen Puncer
  0 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-03  8:46 UTC (permalink / raw)
  To: u-boot

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


---
On 26/03/07 10:08 -0600, Grant Likely wrote:
> On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.
> 
> This looks pretty straight forward.
> 
> My only comment is that psc2_4 is probably used as GPIO instead of
> power control by some users (The lite5200 is an eval board after all).
> Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
> CONFIG_LITE5200B) so that it can be easily compiled out.
> 
> Also, '//' style comments should be changed to '/* */'
> 
> Otherwise;
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 

OK. This one should be better:

 Makefile                |    5 ++++
 board/icecube/icecube.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

Index: u-boot.git/board/icecube/icecube.c
===================================================================
--- u-boot.git.orig/board/icecube/icecube.c
+++ u-boot.git/board/icecube/icecube.c
@@ -42,6 +42,53 @@
 #include "mt48lc16m16a2-75.h"
 # endif
 #endif
+
+#ifdef CONFIG_LITE5200B_PM
+/* 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_O = 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 +255,8 @@ long int initdram (int board_type)
 		__asm__ volatile ("sync");
 	}
 
+	lite5200b_wakeup();
+
 	return dramsize + dramsize2;
 }
 
Index: u-boot.git/Makefile
===================================================================
--- u-boot.git.orig/Makefile
+++ u-boot.git/Makefile
@@ -430,6 +430,7 @@ inka4x0_config:	unconfig
 	@$(MKCONFIG) inka4x0 ppc mpc5xxx inka4x0
 
 lite5200b_config	\
+lite5200b_PM_config	\
 lite5200b_LOWBOOT_config:	unconfig
 	@mkdir -p $(obj)include
 	@mkdir -p $(obj)board/icecube
@@ -438,6 +439,10 @@ lite5200b_LOWBOOT_config:	unconfig
 	@ echo "... DDR memory revision"
 	@ echo "#define CONFIG_MPC5200"		>>$(obj)include/config.h
 	@ echo "#define CONFIG_LITE5200B"	>>$(obj)include/config.h
+	@[ -z "$(findstring _PM_,$@)" ] || \
+		{ echo "#define CONFIG_LITE5200B_PM"	>>$(obj)include/config.h ; \
+		  echo "... with power management (low-power mode) support" ; \
+		}
 	@[ -z "$(findstring LOWBOOT_,$@)" ] || \
 		{ echo "TEXT_BASE = 0xFF000000" >$(obj)board/icecube/config.tmp ; \
 		  echo "... with LOWBOOT configuration" ; \

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

* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-03-23 15:58   ` Grant Likely
@ 2007-04-04  7:37     ` Domen Puncer
  2007-04-16  5:40       ` Grant Likely
  0 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-04-04  7:37 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

Hi!

How about something like the following.
Changes:
- lots of code moved from asm to C
- add compatible "mpc5200" to lite5200x soc (already is this
  way on efika). And change Efika's soc device_type to "soc".
- add wakeup supported with RTC (1 to 24*60-1 minutes)
- each board now configures it's wakeup mode and possibly
  board suspend and resume functions it needs to call (USB on lite)


This code survived > 70k suspend/resume cycles :-)


Comments?



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.


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

---
 arch/powerpc/boot/dts/lite5200.dts          |    1 
 arch/powerpc/boot/dts/lite5200b.dts         |    1 
 arch/powerpc/kernel/prom_init.c             |    2 
 arch/powerpc/platforms/52xx/Makefile        |    2 
 arch/powerpc/platforms/52xx/efika.c         |    8 
 arch/powerpc/platforms/52xx/lite5200.c      |   28 +++
 arch/powerpc/platforms/52xx/mpc52xx_pm.c    |  230 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/52xx/mpc52xx_sleep.S |  161 +++++++++++++++++++
 include/asm-powerpc/mpc52xx.h               |   63 +++++++
 9 files changed, 495 insertions(+), 1 deletion(-)

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,230 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+
+#undef DEBUG /* define for 1s wakeups */
+extern void mpc52xx_deep_sleep(void *sram, void *, struct mpc52xx_cdm *, struct mpc52xx_intr *);
+
+static void __iomem *mbar;
+static void __iomem *sdram;
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_rtc __iomem *rtc;
+static struct mpc52xx_gpio_wkup __iomem *gpiow;
+
+struct mpc52xx_wakeup mpc52xx_wakeup;
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
+{
+	u16 tmp;
+
+	/* 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/high level creates wakeup interrupt */
+	tmp = in_be16(&gpiow->wkup_itype);
+	tmp &= ~(0x3 << (pin * 2));
+	tmp |= (!level + 1) << (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));
+
+	return 0;
+}
+
+static int mpc52xx_set_wakeup_rtc(int delay)
+{
+#ifndef DEBUG
+	u8 hour;
+	u8 minute;
+
+	if (delay < 0)
+		return -EINVAL;
+	else if (delay == 0)
+		return 0;
+
+	hour = in_8(&rtc->hour);
+	minute = in_8(&rtc->minute);
+
+	hour += delay / 60;
+	hour %= 24;
+	minute += delay % 60 + 1;
+	if (minute >= 60) {
+		minute -= 60;
+		hour++;
+	}
+
+	out_8(&rtc->alm_hour_set, hour);
+	out_8(&rtc->alm_min_set, minute);
+	out_8(&rtc->alm_enable, 1);
+#else
+	u8 tmp = in_8(&rtc->int_enable);
+	out_8(&rtc->int_enable, (tmp & ~0x8) | 0x1); /* every second */
+#endif
+
+	return 0;
+}
+
+int mpc52xx_pm_prepare(suspend_state_t state)
+{
+	if (state != PM_SUSPEND_STANDBY)
+		return -EINVAL;
+
+	/* map the whole register space */
+	mbar = mpc52xx_find_and_map("mpc5200");
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+	/* these offsets are from mpc5200 users manual */
+	sdram = mbar + 0x100;
+	cdm = mbar + 0x200;
+	intr = mbar + 0x500;
+	rtc = mbar + 0x800;
+	gpiow = mbar + 0xc00;
+
+
+#ifdef DEBUG
+	mpc52xx_wakeup.mask |= WAKEUP_RTC;
+#endif
+	if (mpc52xx_wakeup.mask == 0) {
+		printk(KERN_ALERT "%s: %i don't know how to wake up the board\n",
+				__func__, __LINE__);
+		goto out_unmap;
+	}
+	if (mpc52xx_wakeup.mask & WAKEUP_GPIO) {
+		if (mpc52xx_set_wakeup_gpio(mpc52xx_wakeup.pin, mpc52xx_wakeup.level))
+			goto out_unmap;
+	}
+	if (mpc52xx_wakeup.mask & WAKEUP_RTC) {
+		if (mpc52xx_set_wakeup_rtc(mpc52xx_wakeup.delay))
+			goto out_unmap;
+	}
+	if (mpc52xx_wakeup.mask & WAKEUP_MSCAN) {
+		/* TODO */
+	}
+
+	/* call board suspend code, if applicable */
+	if (mpc52xx_wakeup.board_suspend_prepare)
+		mpc52xx_wakeup.board_suspend_prepare(mbar);
+
+	return 0;
+
+ out_unmap:
+	iounmap(mbar);
+	return -ENOSYS;
+}
+
+extern void mpc52xx_ds_sram(void);
+extern const long mpc52xx_ds_sram_size;
+extern void mpc52xx_ds_cached(void);
+extern const long mpc52xx_ds_cached_size;
+
+static char saved_sram[0x4000];
+
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+	u32 clk_enables;
+	u32 msr, hid0;
+	void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+	unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
+	char saved_0x500[mpc52xx_ds_cached_size];
+
+	/* don't let DEC expire any time soon */
+	mtspr(SPRN_DEC, 0x7fffffff);
+
+	/* save SRAM */
+	memcpy(saved_sram, sdma.sram, sdma.sram_size);
+
+	/* copy low level suspend code to sram */
+	memcpy(sdma.sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size);
+
+	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 and bestcomm (SRAM) clocks */
+	clk_enables = in_be32(&cdm->clk_enables);
+	out_be32(&cdm->clk_enables, clk_enables & 0x00088000);
+
+	/* disable power management */
+	msr = mfmsr();
+	mtmsr(msr & ~MSR_POW);
+
+	/* enable sleep mode, disable others */
+	hid0 = mfspr(SPRN_HID0);
+	mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP);
+
+	/* save original, copy our irq handler, flush from dcache and invalidate icache */
+	memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size);
+	memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size);
+	flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+	/* call low-level sleep code */
+	mpc52xx_deep_sleep(sdma.sram, sdram, cdm, intr);
+
+	/* restore original irq handler */
+	memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size);
+	flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+	/* restore old power mode */
+	mtmsr(msr & ~MSR_POW);
+	mtspr(SPRN_HID0, hid0);
+	mtmsr(msr);
+
+	out_be32(&cdm->clk_enables, clk_enables);
+	out_8(&cdm->ccs_sleep_enable, 0);
+	out_8(&cdm->osc_sleep_enable, 0);
+
+	/* restore SRAM */
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+	/* restart jiffies */
+	wakeup_decrementer();
+
+	return 0;
+}
+
+static int mpc52xx_pm_finish(suspend_state_t state)
+{
+	/* call board resume code */
+	if (mpc52xx_wakeup.board_resume_finish)
+		mpc52xx_wakeup.board_resume_finish(mbar);
+
+	iounmap(mbar);
+
+	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,
+};
+
+int __init mpc52xx_pm_init(void)
+{
+	pm_set_ops(&mpc52xx_pm_ops);
+	return 0;
+}
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
@@ -0,0 +1,161 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+
+#undef DEBUG /* doesn't halt the cpu. useful for bdi2000 debugging  */
+
+/* mpc5200b puts sdram automatically in self-refresh, previous versions don't */
+#define SELF_REFRESH
+
+.text
+	.globl mpc52xx_deep_sleep
+mpc52xx_deep_sleep: /* args r3-r6: SRAM, SDRAM regs, CDM regs, INTR regs */
+
+	/* enable interrupts */
+	mfmsr	r7
+	ori	r7, r7, 0x8000 /* EE */
+	mtmsr	r7
+	sync; isync;
+
+	li	r10, 0 /* flag that irq handler sets */
+
+	/* enable tmr7 (or any other) interrupt */
+	lwz	r8, 0x14(r6) /* intr->main_mask */
+	ori	r8, r8, 0x1
+	xori	r8, r8, 0x1
+	stw	r8, 0x14(r6)
+	sync
+
+	/* emulate tmr7 interrupt */
+	li	r8, 0x1
+	stw	r8, 0x40(r6) /* intr->main_emulate */
+	sync
+
+	/* wait for it to happen */
+1:
+	cmpi	cr0, r10, 1
+	bne	cr0, 1b
+
+	/* lock icache */
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+
+	mflr	r9 /* save LR */
+
+	/* jump to sram */
+	mtlr	r3
+	blrl
+
+	mtlr	r9 /* restore LR */
+
+	/* unlock icache */
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	xori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+
+	/* return to C code */
+	blr
+
+
+_GLOBAL(mpc52xx_ds_sram)
+mpc52xx_ds_sram:
+#ifdef SELF_REFRESH
+	lwz	r8, 0x4(r4)	/* sdram->ctrl */
+
+	oris	r8, r8, 0x8000 /* mode_en */
+	stw	r8, 0x4(r4)
+	sync
+
+	ori	r8, r8, 0x0002 /* soft_pre */
+	stw	r8, 0x4(r4)
+	sync
+	xori	r8, r8, 0x0002
+
+	xoris	r8, r8, 0x8000 /* mode_en */
+	stw	r8, 0x4(r4)
+	sync
+
+	oris	r8, r8, 0x5000
+	xoris	r8, r8, 0x4000 /* ref_en !cke */
+	stw	r8, 0x4(r4)
+	sync
+
+	/* disable SDRAM clock */
+	lwz	r8, 0x14(r5) /* cdm->clkenable */
+	ori	r8, r8, 0x0008
+	xori	r8, r8, 0x0008
+	stw	r8, 0x14(r5)
+	sync
+#endif
+
+#ifndef DEBUG
+	/* 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	r8, 0x14(r5)
+	ori	r8, r8, 0x0008
+	stw	r8, 0x14(r5)
+	sync
+
+	/* get ram out of self-refresh */
+	lwz	r8, 0x4(r4)
+	oris	r8, r8, 0x5000 /* cke ref_en */
+	stw	r8, 0x4(r4)
+	sync
+#endif
+
+	blr
+_GLOBAL(mpc52xx_ds_sram_size)
+mpc52xx_ds_sram_size:
+	.long $-mpc52xx_ds_sram
+
+
+/* ### interrupt handler for wakeup from deep-sleep ### */
+_GLOBAL(mpc52xx_ds_cached)
+mpc52xx_ds_cached:
+	mtspr	SPRN_SPRG0, r7
+	mtspr	SPRN_SPRG1, r8
+
+	/* disable emulated interrupt */
+	mfspr	r7, 311 /* MBAR */
+	addi	r7, r7, 0x540	/* intr->main_emul */
+	li	r8, 0
+	stw	r8, 0(r7)
+	sync
+	dcbf	0, r7
+
+	/* acknowledge wakeup, so CCS releases power pown */
+	mfspr	r7, 311	/* MBAR */
+	addi	r7, r7, 0x524	/* intr->enc_status */
+	lwz	r8, 0(r7)
+	ori	r8, r8, 0x0400
+	stw	r8, 0(r7)
+	sync
+	dcbf	0, r7
+
+	/* flag - we handled the interrupt */
+	li	r10, 1
+
+	mfspr	r8, SPRN_SPRG1
+	mfspr	r7, SPRN_SPRG0
+
+	rfi
+_GLOBAL(mpc52xx_ds_cached_size)
+mpc52xx_ds_cached_size:
+	.long $-mpc52xx_ds_cached
Index: grant.git/arch/powerpc/platforms/52xx/efika.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/efika.c
+++ grant.git/arch/powerpc/platforms/52xx/efika.c
@@ -200,6 +200,14 @@ static void __init efika_setup_arch(void
 
 	efika_pcisetup();
 
+#ifdef CONFIG_PM
+	mpc52xx_wakeup.mask = WAKEUP_GPIO | WAKEUP_RTC;
+	mpc52xx_wakeup.pin = 4;		/* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
+	mpc52xx_wakeup.level = 1;	/* wakeup on high level */
+	/* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
+	mpc52xx_pm_init();
+#endif
+
 	if (ppc_md.progress)
 		ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
 }
Index: grant.git/arch/powerpc/platforms/52xx/lite5200.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/lite5200.c
+++ grant.git/arch/powerpc/platforms/52xx/lite5200.c
@@ -85,6 +85,24 @@ error:
 	iounmap(gpio);
 }
 
+#ifdef CONFIG_PM
+static u32 descr_a;
+static void lite5200_suspend_prepare(void __iomem *mbar)
+{
+	/*
+	 * power down usb port
+	 * this needs to be called before of-ohci suspend code
+	 */
+	descr_a = in_be32(mbar + 0x1048);
+	out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100);
+}
+
+static void lite5200_resume_finish(void __iomem *mbar)
+{
+	out_be32(mbar + 0x1048, descr_a);
+}
+#endif
+
 static void __init lite5200_setup_arch(void)
 {
 	struct device_node *np;
@@ -107,6 +125,16 @@ static void __init lite5200_setup_arch(v
 	mpc52xx_setup_cpu();	/* Generic */
 	lite5200_setup_cpu();	/* Platorm specific */
 
+#ifdef CONFIG_PM
+	mpc52xx_wakeup.mask = WAKEUP_GPIO | WAKEUP_RTC;
+	mpc52xx_wakeup.pin = 1;		/* GPIO_WKUP_1 (GPIO_PSC2_4) */
+	mpc52xx_wakeup.level = 0;	/* wakeup on low level */
+	/* mpc52xx_wakeup.delay = 10;	 wake after 10 minutes (RTC) */
+	mpc52xx_wakeup.board_suspend_prepare = lite5200_suspend_prepare;
+	mpc52xx_wakeup.board_resume_finish = lite5200_resume_finish;
+	mpc52xx_pm_init();
+#endif
+
 #ifdef CONFIG_PCI
 	np = of_find_node_by_type(np, "pci");
 	if (np)
Index: grant.git/include/asm-powerpc/mpc52xx.h
===================================================================
--- grant.git.orig/include/asm-powerpc/mpc52xx.h
+++ grant.git/include/asm-powerpc/mpc52xx.h
@@ -232,6 +232,51 @@ struct mpc52xx_cdm {
 	u16 mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
 };
 
+/* RTC */
+struct mpc52xx_rtc {
+	u8	set_time;	/* RTC + 0x00 */
+	u8	hour_set;	/* RTC + 0x01 */
+	u8	minute_set;	/* RTC + 0x02 */
+	u8	second_set;	/* RTC + 0x03 */
+
+	u8	set_date;	/* RTC + 0x04 */
+	u8	month_set;	/* RTC + 0x05 */
+	u8	weekday_set;	/* RTC + 0x06 */
+	u8	date_set;	/* RTC + 0x07 */
+
+	u8	write_sw;	/* RTC + 0x08 */
+	u8	sw_set;		/* RTC + 0x09 */
+	u16	year_set;	/* RTC + 0x0a */
+
+	u8	alm_enable;	/* RTC + 0x0c */
+	u8	alm_hour_set;	/* RTC + 0x0d */
+	u8	alm_min_set;	/* RTC + 0x0e */
+	u8 	int_enable;	/* RTC + 0x0f */
+
+	u8	reserved1;
+	u8	hour;		/* RTC + 0x11 */
+	u8	minute;		/* RTC + 0x12 */
+	u8	second;		/* RTC + 0x13 */
+
+	u8	month;		/* RTC + 0x14 */
+	u8	wday_mday;	/* RTC + 0x15 */
+	u16	year;		/* RTC + 0x16 */
+
+	u8	int_alm;	/* RTC + 0x18 */
+	u8	int_sw;		/* RTC + 0x19 */
+	u8	alm_status;	/* RTC + 0x1a */
+	u8	sw_minute;	/* RTC + 0x1b */
+
+	u8	bus_error_1;	/* RTC + 0x1c */
+	u8	int_day;	/* RTC + 0x1d */
+	u8	int_min;	/* RTC + 0x1e */
+	u8	int_sec;	/* RTC + 0x1f */
+
+	u8	pterm;		/* RTC + 0x20 */
+	u8	eterm;		/* RTC + 0x21 */
+	u16	reserved2;
+};
+
 #endif /* __ASSEMBLY__ */
 
 
@@ -253,5 +298,23 @@ extern int __init mpc52xx_add_bridge(str
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_PM
+#define WAKEUP_GPIO	(1<<1)
+#define WAKEUP_RTC	(2<<1)
+#define WAKEUP_MSCAN	(3<<1)
+struct mpc52xx_wakeup {
+	u8 mask;
+	u8 pin;		/* which wakeup GPIO */
+	u8 level;	/* transition to high or to low level */
+	u16 delay;	/* after how many minutes (RTC) */
+
+	void (*board_suspend_prepare)(void __iomem *mbar);
+	void (*board_resume_finish)(void __iomem *mbar);
+};
+
+extern struct mpc52xx_wakeup mpc52xx_wakeup;
+int __init mpc52xx_pm_init(void);
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_POWERPC_MPC52xx_H__ */
 
Index: grant.git/arch/powerpc/boot/dts/lite5200.dts
===================================================================
--- grant.git.orig/arch/powerpc/boot/dts/lite5200.dts
+++ grant.git/arch/powerpc/boot/dts/lite5200.dts
@@ -49,6 +49,7 @@
 
 	soc5200@f0000000 {
 		model = "fsl,mpc5200";
+		compatible = "mpc5200";
 		revision = ""			// from bootloader
 		#interrupt-cells = <3>;
 		device_type = "soc";
Index: grant.git/arch/powerpc/boot/dts/lite5200b.dts
===================================================================
--- grant.git.orig/arch/powerpc/boot/dts/lite5200b.dts
+++ grant.git/arch/powerpc/boot/dts/lite5200b.dts
@@ -49,6 +49,7 @@
 
 	soc5200@f0000000 {
 		model = "fsl,mpc5200b";
+		compatible = "mpc5200";
 		revision = "";			// from bootloader
 		#interrupt-cells = <3>;
 		device_type = "soc";
Index: grant.git/arch/powerpc/kernel/prom_init.c
===================================================================
--- grant.git.orig/arch/powerpc/kernel/prom_init.c
+++ grant.git/arch/powerpc/kernel/prom_init.c
@@ -2142,7 +2142,7 @@ static void __init fixup_device_tree_efi
 	                             3,12,0, 3,13,0, 3,14,0, 3,15,0 };
 	struct subst_entry efika_subst_table[] = {
 		{ "/",			"device_type",	prop_cstr("efika") },
-		{ "/builtin",		"compatible",	prop_cstr("soc") },
+		{ "/builtin",		"device_type",	prop_cstr("soc") },
 		{ "/builtin/ata",	"compatible",	prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
 		{ "/builtin/bestcomm",	"compatible",	prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
 		{ "/builtin/bestcomm",	"interrupts",	prop_bcomm_irq, sizeof(prop_bcomm_irq) },

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-03  8:46       ` [U-Boot-Users] " Domen Puncer
@ 2007-04-16  4:45         ` Grant Likely
  -1 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-04-16  4:45 UTC (permalink / raw)
  To: Domen Puncer, Stefan Roese; +Cc: u-boot-users, linuxppc-embedded

On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.

Looks good; almost there.  Only one thing missing... you need to add
your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
in the Linux source tree.  (You can just reply to this message, and
whoever merges the patch will add the line to the commit message)

Acked-by: Grant Likely <grant.likely@secretlab.ca>

Stefan; since there is no 5200 custodian, can you please pick up this
patch once Domen sends a Signed-of-by replay?

Cheers,
g.

>
>
> ---
> On 26/03/07 10:08 -0600, Grant Likely wrote:
> > On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.
> >
> > This looks pretty straight forward.
> >
> > My only comment is that psc2_4 is probably used as GPIO instead of
> > power control by some users (The lite5200 is an eval board after all).
> > Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
> > CONFIG_LITE5200B) so that it can be easily compiled out.
> >
> > Also, '//' style comments should be changed to '/* */'
> >
> > Otherwise;
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> >
>
> OK. This one should be better:
>
>  Makefile                |    5 ++++
>  board/icecube/icecube.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
>
> Index: u-boot.git/board/icecube/icecube.c
> ===================================================================
> --- u-boot.git.orig/board/icecube/icecube.c
> +++ u-boot.git/board/icecube/icecube.c
> @@ -42,6 +42,53 @@
>  #include "mt48lc16m16a2-75.h"
>  # endif
>  #endif
> +
> +#ifdef CONFIG_LITE5200B_PM
> +/* 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_O = 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 +255,8 @@ long int initdram (int board_type)
>                 __asm__ volatile ("sync");
>         }
>
> +       lite5200b_wakeup();
> +
>         return dramsize + dramsize2;
>  }
>
> Index: u-boot.git/Makefile
> ===================================================================
> --- u-boot.git.orig/Makefile
> +++ u-boot.git/Makefile
> @@ -430,6 +430,7 @@ inka4x0_config:     unconfig
>         @$(MKCONFIG) inka4x0 ppc mpc5xxx inka4x0
>
>  lite5200b_config       \
> +lite5200b_PM_config    \
>  lite5200b_LOWBOOT_config:      unconfig
>         @mkdir -p $(obj)include
>         @mkdir -p $(obj)board/icecube
> @@ -438,6 +439,10 @@ lite5200b_LOWBOOT_config:  unconfig
>         @ echo "... DDR memory revision"
>         @ echo "#define CONFIG_MPC5200"         >>$(obj)include/config.h
>         @ echo "#define CONFIG_LITE5200B"       >>$(obj)include/config.h
> +       @[ -z "$(findstring _PM_,$@)" ] || \
> +               { echo "#define CONFIG_LITE5200B_PM"    >>$(obj)include/config.h ; \
> +                 echo "... with power management (low-power mode) support" ; \
> +               }
>         @[ -z "$(findstring LOWBOOT_,$@)" ] || \
>                 { echo "TEXT_BASE = 0xFF000000" >$(obj)board/icecube/config.tmp ; \
>                   echo "... with LOWBOOT configuration" ; \
>


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

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-04-16  4:45         ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-04-16  4:45 UTC (permalink / raw)
  To: u-boot

On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.

Looks good; almost there.  Only one thing missing... you need to add
your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
in the Linux source tree.  (You can just reply to this message, and
whoever merges the patch will add the line to the commit message)

Acked-by: Grant Likely <grant.likely@secretlab.ca>

Stefan; since there is no 5200 custodian, can you please pick up this
patch once Domen sends a Signed-of-by replay?

Cheers,
g.

>
>
> ---
> On 26/03/07 10:08 -0600, Grant Likely wrote:
> > On 3/15/07, Domen Puncer <domen.puncer@telargo.com> 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.
> >
> > This looks pretty straight forward.
> >
> > My only comment is that psc2_4 is probably used as GPIO instead of
> > power control by some users (The lite5200 is an eval board after all).
> > Maybe wrap the code with #ifdef CONFIG_LITE5200B_PM (instead of
> > CONFIG_LITE5200B) so that it can be easily compiled out.
> >
> > Also, '//' style comments should be changed to '/* */'
> >
> > Otherwise;
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> >
>
> OK. This one should be better:
>
>  Makefile                |    5 ++++
>  board/icecube/icecube.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
>
> Index: u-boot.git/board/icecube/icecube.c
> ===================================================================
> --- u-boot.git.orig/board/icecube/icecube.c
> +++ u-boot.git/board/icecube/icecube.c
> @@ -42,6 +42,53 @@
>  #include "mt48lc16m16a2-75.h"
>  # endif
>  #endif
> +
> +#ifdef CONFIG_LITE5200B_PM
> +/* 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_O = 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 +255,8 @@ long int initdram (int board_type)
>                 __asm__ volatile ("sync");
>         }
>
> +       lite5200b_wakeup();
> +
>         return dramsize + dramsize2;
>  }
>
> Index: u-boot.git/Makefile
> ===================================================================
> --- u-boot.git.orig/Makefile
> +++ u-boot.git/Makefile
> @@ -430,6 +430,7 @@ inka4x0_config:     unconfig
>         @$(MKCONFIG) inka4x0 ppc mpc5xxx inka4x0
>
>  lite5200b_config       \
> +lite5200b_PM_config    \
>  lite5200b_LOWBOOT_config:      unconfig
>         @mkdir -p $(obj)include
>         @mkdir -p $(obj)board/icecube
> @@ -438,6 +439,10 @@ lite5200b_LOWBOOT_config:  unconfig
>         @ echo "... DDR memory revision"
>         @ echo "#define CONFIG_MPC5200"         >>$(obj)include/config.h
>         @ echo "#define CONFIG_LITE5200B"       >>$(obj)include/config.h
> +       @[ -z "$(findstring _PM_,$@)" ] || \
> +               { echo "#define CONFIG_LITE5200B_PM"    >>$(obj)include/config.h ; \
> +                 echo "... with power management (low-power mode) support" ; \
> +               }
>         @[ -z "$(findstring LOWBOOT_,$@)" ] || \
>                 { echo "TEXT_BASE = 0xFF000000" >$(obj)board/icecube/config.tmp ; \
>                   echo "... with LOWBOOT configuration" ; \
>


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

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

* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-04-04  7:37     ` Domen Puncer
@ 2007-04-16  5:40       ` Grant Likely
  2007-04-17  7:05         ` Domen Puncer
  0 siblings, 1 reply; 48+ messages in thread
From: Grant Likely @ 2007-04-16  5:40 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 4/4/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Hi!
>
> How about something like the following.
> Changes:
> - lots of code moved from asm to C
> - add compatible "mpc5200" to lite5200x soc (already is this
>   way on efika). And change Efika's soc device_type to "soc".
> - add wakeup supported with RTC (1 to 24*60-1 minutes)
> - each board now configures it's wakeup mode and possibly
>   board suspend and resume functions it needs to call (USB on lite)

Sorry it took so long for me to review and get back to you on this
patch.  I got wrapped up in other tasks.

I mostly like the approach that you're taking here to allow each board
to select it's own wakeup method, but I think it should be taken a
step farther.  Instead of providing a set of stock
mpc52xx_set_wakeup_*() functions, I think it would make for simpler
and more flexible code if each board takes care of its own wakeup
configuration in the board_suspend_prepare hook.  In fact, the
mpc52xx_set_wakeup_*() functions themselves make a lot of sense, and
are useful utility functions.  But rather than trying to codify which
pins/rtc to configure for wakeup via the .mask, .level, .pin and
.delay items, those functions should be called directly by
lite5200_suspend_prepare() and efika_suspend_prepare().  Doing this
will drop 19 lines of common code in exchange for adding 2 lines to
each board port.

As an added bonus, doing it this way allows multiple pins to be used
for wakeup.  :-)

> This code survived > 70k suspend/resume cycles :-)

That's pretty good evidence.  :-)

> Comments?

A few more comments below

> --- /dev/null
> +++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
<snip>
> +extern void mpc52xx_ds_sram(void);
> +extern const long mpc52xx_ds_sram_size;
> +extern void mpc52xx_ds_cached(void);
> +extern const long mpc52xx_ds_cached_size;

This *looks* like dangerous code (function prototypes not in a shared
header).  You should add a big comment here to the fact that these are
assembly functions that are only ever referenced in this file.

===================================================================
> --- grant.git.orig/arch/powerpc/boot/dts/lite5200.dts
> +++ grant.git/arch/powerpc/boot/dts/lite5200.dts
> @@ -49,6 +49,7 @@
>
>         soc5200@f0000000 {
>                 model = "fsl,mpc5200";
> +               compatible = "mpc5200";
>                 revision = ""                   // from bootloader
>                 #interrupt-cells = <3>;
>                 device_type = "soc";
> Index: grant.git/arch/powerpc/boot/dts/lite5200b.dts
> ===================================================================
> --- grant.git.orig/arch/powerpc/boot/dts/lite5200b.dts
> +++ grant.git/arch/powerpc/boot/dts/lite5200b.dts
> @@ -49,6 +49,7 @@
>
>         soc5200@f0000000 {
>                 model = "fsl,mpc5200b";
> +               compatible = "mpc5200";
>                 revision = "";                  // from bootloader
>                 #interrupt-cells = <3>;
>                 device_type = "soc";

Put these two changes in a seperate patch, and I'll ACK them right away

===================================================================
> --- grant.git.orig/arch/powerpc/kernel/prom_init.c
> +++ grant.git/arch/powerpc/kernel/prom_init.c
> @@ -2142,7 +2142,7 @@ static void __init fixup_device_tree_efi
>                                      3,12,0, 3,13,0, 3,14,0, 3,15,0 };
>         struct subst_entry efika_subst_table[] = {
>                 { "/",                  "device_type",  prop_cstr("efika") },
> -               { "/builtin",           "compatible",   prop_cstr("soc") },
> +               { "/builtin",           "device_type",  prop_cstr("soc") },
>                 { "/builtin/ata",       "compatible",   prop_cstr("mpc5200b-ata\0mpc5200-ata"), },
>                 { "/builtin/bestcomm",  "compatible",   prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") },
>                 { "/builtin/bestcomm",  "interrupts",   prop_bcomm_irq, sizeof(prop_bcomm_irq) },
>

This should also be a seperate patch.

Cheers,
g.

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

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

* Re: [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16  4:45         ` [U-Boot-Users] " Grant Likely
@ 2007-04-16  6:25           ` Domen Puncer
  -1 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-16  6:25 UTC (permalink / raw)
  To: Grant Likely; +Cc: u-boot-users, Stefan Roese, linuxppc-embedded

On 15/04/07 22:45 -0600, Grant Likely wrote:
> On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
> 
> Looks good; almost there.  Only one thing missing... you need to add
> your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> in the Linux source tree.  (You can just reply to this message, and
> whoever merges the patch will add the line to the commit message)
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 
> Stefan; since there is no 5200 custodian, can you please pick up this
> patch once Domen sends a Signed-of-by replay?

I thought Signed-off-by's are Linux specific.


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


Thanks!

	Domen

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
@ 2007-04-16  6:25           ` Domen Puncer
  0 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-16  6:25 UTC (permalink / raw)
  To: u-boot

On 15/04/07 22:45 -0600, Grant Likely wrote:
> On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
> 
> Looks good; almost there.  Only one thing missing... you need to add
> your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> in the Linux source tree.  (You can just reply to this message, and
> whoever merges the patch will add the line to the commit message)
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 
> Stefan; since there is no 5200 custodian, can you please pick up this
> patch once Domen sends a Signed-of-by replay?

I thought Signed-off-by's are Linux specific.


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


Thanks!

	Domen

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16  6:25           ` [U-Boot-Users] " Domen Puncer
  (?)
@ 2007-04-16  7:10           ` Wolfgang Denk
  -1 siblings, 0 replies; 48+ messages in thread
From: Wolfgang Denk @ 2007-04-16  7:10 UTC (permalink / raw)
  To: u-boot

In message <20070416062533.GH18236@moe.telargo.com> you wrote:
>
> I thought Signed-off-by's are Linux specific.

Please read the docs.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Systems programmers are the high priests of a low cult.
                                                       -- R.S. Barton

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16  4:45         ` [U-Boot-Users] " Grant Likely
  (?)
  (?)
@ 2007-04-16 12:04         ` Stefan Roese
  2007-04-16 13:08           ` Domen Puncer
  2007-04-17 11:29           ` Stefan Roese
  -1 siblings, 2 replies; 48+ messages in thread
From: Stefan Roese @ 2007-04-16 12:04 UTC (permalink / raw)
  To: u-boot

On Monday 16 April 2007 06:45, Grant Likely wrote:
> On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
>
> Looks good; almost there.  Only one thing missing... you need to add
> your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> in the Linux source tree.  (You can just reply to this message, and
> whoever merges the patch will add the line to the commit message)
>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>
> Stefan; since there is no 5200 custodian, can you please pick up this
> patch once Domen sends a Signed-of-by replay?

Done.

But this brings me to a new idea: Why not create a 5200er custodian repository 
and perhaps we can find somebody (Stefan looks in Grants direction ;-)) to 
volunteer to maintain this 5200er repository?

Grant?

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
=====================================================================

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16 12:04         ` Stefan Roese
@ 2007-04-16 13:08           ` Domen Puncer
  2007-04-16 13:36             ` Grant Likely
  2007-04-20 12:13             ` Stefan Roese
  2007-04-17 11:29           ` Stefan Roese
  1 sibling, 2 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-16 13:08 UTC (permalink / raw)
  To: u-boot

On 16/04/07 14:04 +0200, Stefan Roese wrote:
> On Monday 16 April 2007 06:45, Grant Likely wrote:
> > On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
> >
> > Looks good; almost there.  Only one thing missing... you need to add
> > your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> > in the Linux source tree.  (You can just reply to this message, and
> > whoever merges the patch will add the line to the commit message)
> >
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> >
> > Stefan; since there is no 5200 custodian, can you please pick up this
> > patch once Domen sends a Signed-of-by replay?
> 
> Done.

Thanks!

While at it, can you also take care of (Grant already agreed
with the change):


G2 core reference manual says decrementer and time base
are decreasing/increasing once every 4 bus clock cycles.
Lets fix it, so time in Linux won't run twice as fast

Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
---
 include/configs/IceCube.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: u-boot.git/include/configs/IceCube.h
===================================================================
--- u-boot.git.orig/include/configs/IceCube.h
+++ u-boot.git/include/configs/IceCube.h
@@ -182,7 +182,7 @@
 
 #define OF_CPU			"PowerPC,5200 at 0"
 #define OF_SOC			"soc5200 at f0000000"
-#define OF_TBCLK		(bd->bi_busfreq / 8)
+#define OF_TBCLK		(bd->bi_busfreq / 4)
 #define OF_STDOUT_PATH		"/soc5200 at f0000000/serial at 2000"
 
 /*

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16 13:08           ` Domen Puncer
@ 2007-04-16 13:36             ` Grant Likely
  2007-04-20 12:13             ` Stefan Roese
  1 sibling, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-04-16 13:36 UTC (permalink / raw)
  To: u-boot

On 4/16/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> On 16/04/07 14:04 +0200, Stefan Roese wrote:
> > On Monday 16 April 2007 06:45, Grant Likely wrote:
> > > On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
> > >
> > > Looks good; almost there.  Only one thing missing... you need to add
> > > your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> > > in the Linux source tree.  (You can just reply to this message, and
> > > whoever merges the patch will add the line to the commit message)
> > >
> > > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> > >
> > > Stefan; since there is no 5200 custodian, can you please pick up this
> > > patch once Domen sends a Signed-of-by replay?
> >
> > Done.
>
> Thanks!
>
> While at it, can you also take care of (Grant already agreed
> with the change):
>
>
> G2 core reference manual says decrementer and time base
> are decreasing/increasing once every 4 bus clock cycles.
> Lets fix it, so time in Linux won't run twice as fast
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>

> ---
>  include/configs/IceCube.h |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> Index: u-boot.git/include/configs/IceCube.h
> ===================================================================
> --- u-boot.git.orig/include/configs/IceCube.h
> +++ u-boot.git/include/configs/IceCube.h
> @@ -182,7 +182,7 @@
>
>  #define OF_CPU                 "PowerPC,5200 at 0"
>  #define OF_SOC                 "soc5200 at f0000000"
> -#define OF_TBCLK               (bd->bi_busfreq / 8)
> +#define OF_TBCLK               (bd->bi_busfreq / 4)
>  #define OF_STDOUT_PATH         "/soc5200 at f0000000/serial at 2000"
>
>  /*
>


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

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

* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-04-16  5:40       ` Grant Likely
@ 2007-04-17  7:05         ` Domen Puncer
  2007-04-17  7:10           ` Grant Likely
  0 siblings, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-04-17  7:05 UTC (permalink / raw)
  To: Grant Likely; +Cc: 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.


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

---
 arch/powerpc/platforms/52xx/Makefile        |    2 
 arch/powerpc/platforms/52xx/efika.c         |   15 ++
 arch/powerpc/platforms/52xx/lite5200.c      |   28 ++++
 arch/powerpc/platforms/52xx/mpc52xx_pm.c    |  187 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/52xx/mpc52xx_sleep.S |  154 +++++++++++++++++++++++
 include/asm-powerpc/mpc52xx.h               |   11 +
 6 files changed, 397 insertions(+)

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,187 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+
+
+/* these are defined in mpc52xx_sleep.S, and only used here */
+extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs,
+		struct mpc52xx_cdm *, struct mpc52xx_intr *);
+extern void mpc52xx_ds_sram(void);
+extern const long mpc52xx_ds_sram_size;
+extern void mpc52xx_ds_cached(void);
+extern const long mpc52xx_ds_cached_size;
+
+static void __iomem *mbar;
+static void __iomem *sdram;
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_gpio_wkup __iomem *gpiow;
+
+struct mpc52xx_suspend mpc52xx_suspend;
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
+{
+	u16 tmp;
+
+	/* 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/high level creates wakeup interrupt */
+	tmp = in_be16(&gpiow->wkup_itype);
+	tmp &= ~(0x3 << (pin * 2));
+	tmp |= (!level + 1) << (pin * 2);
+	out_be16(&gpiow->wkup_itype, tmp);
+	/* master enable */
+	out_8(&gpiow->wkup_maste, 1);
+
+	return 0;
+}
+
+int mpc52xx_pm_prepare(suspend_state_t state)
+{
+	if (state != PM_SUSPEND_STANDBY)
+		return -EINVAL;
+
+	/* map the whole register space */
+	mbar = mpc52xx_find_and_map("mpc5200");
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+	/* these offsets are from mpc5200 users manual */
+	sdram = mbar + 0x100;
+	cdm = mbar + 0x200;
+	intr = mbar + 0x500;
+	gpiow = mbar + 0xc00;
+
+
+	/* call board suspend code, if applicable */
+	if (mpc52xx_suspend.board_suspend_prepare)
+		mpc52xx_suspend.board_suspend_prepare(mbar);
+	else {
+		printk(KERN_ALERT "%s: %i don't know how to wake up the board\n",
+				__func__, __LINE__);
+		goto out_unmap;
+	}
+
+	return 0;
+
+ out_unmap:
+	iounmap(mbar);
+	return -ENOSYS;
+}
+
+
+char saved_sram[0x4000];
+
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+	u32 clk_enables;
+	u32 msr, hid0;
+	u32 intr_main_mask;
+	void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500;
+	unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
+	char saved_0x500[mpc52xx_ds_cached_size];
+
+	/* disable all interrupts in PIC */
+	intr_main_mask = in_be32(&intr->main_mask);
+	out_be32(&intr->main_mask, intr_main_mask | 0x1ffff);
+
+	/* don't let DEC expire any time soon */
+	mtspr(SPRN_DEC, 0x7fffffff);
+
+	/* save SRAM */
+	memcpy(saved_sram, sdma.sram, sdma.sram_size);
+
+	/* copy low level suspend code to sram */
+	memcpy(sdma.sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size);
+
+	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 and bestcomm (SRAM) clocks */
+	clk_enables = in_be32(&cdm->clk_enables);
+	out_be32(&cdm->clk_enables, clk_enables & 0x00088000);
+
+	/* disable power management */
+	msr = mfmsr();
+	mtmsr(msr & ~MSR_POW);
+
+	/* enable sleep mode, disable others */
+	hid0 = mfspr(SPRN_HID0);
+	mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP);
+
+	/* save original, copy our irq handler, flush from dcache and invalidate icache */
+	memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size);
+	memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size);
+	flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+	/* call low-level sleep code */
+	mpc52xx_deep_sleep(sdma.sram, sdram, cdm, intr);
+
+	/* restore original irq handler */
+	memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size);
+	flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
+
+	/* restore old power mode */
+	mtmsr(msr & ~MSR_POW);
+	mtspr(SPRN_HID0, hid0);
+	mtmsr(msr);
+
+	out_be32(&cdm->clk_enables, clk_enables);
+	out_8(&cdm->ccs_sleep_enable, 0);
+	out_8(&cdm->osc_sleep_enable, 0);
+
+	/* restore SRAM */
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+	/* restart jiffies */
+	wakeup_decrementer();
+
+	/* reenable interrupts in PIC */
+	out_be32(&intr->main_mask, intr_main_mask);
+
+	return 0;
+}
+
+int mpc52xx_pm_finish(suspend_state_t state)
+{
+	/* call board resume code */
+	if (mpc52xx_suspend.board_resume_finish)
+		mpc52xx_suspend.board_resume_finish(mbar);
+
+	iounmap(mbar);
+
+	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,
+};
+
+int __init mpc52xx_pm_init(void)
+{
+	pm_set_ops(&mpc52xx_pm_ops);
+	return 0;
+}
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
@@ -0,0 +1,154 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+
+.text
+
+_GLOBAL(mpc52xx_deep_sleep)
+mpc52xx_deep_sleep: /* args r3-r6: SRAM, SDRAM regs, CDM regs, INTR regs */
+
+	/* enable interrupts */
+	mfmsr	r7
+	ori	r7, r7, 0x8000 /* EE */
+	mtmsr	r7
+	sync; isync;
+
+	li	r10, 0 /* flag that irq handler sets */
+
+	/* enable tmr7 (or any other) interrupt */
+	lwz	r8, 0x14(r6) /* intr->main_mask */
+	ori	r8, r8, 0x1
+	xori	r8, r8, 0x1
+	stw	r8, 0x14(r6)
+	sync
+
+	/* emulate tmr7 interrupt */
+	li	r8, 0x1
+	stw	r8, 0x40(r6) /* intr->main_emulate */
+	sync
+
+	/* wait for it to happen */
+1:
+	cmpi	cr0, r10, 1
+	bne	cr0, 1b
+
+	/* lock icache */
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+
+	mflr	r9 /* save LR */
+
+	/* jump to sram */
+	mtlr	r3
+	blrl
+
+	mtlr	r9 /* restore LR */
+
+	/* unlock icache */
+	mfspr	r10, SPRN_HID0
+	ori	r10, r10, 0x2000
+	xori	r10, r10, 0x2000
+	sync; isync;
+	mtspr	SPRN_HID0, r10
+	sync; isync;
+
+
+	/* return to C code */
+	blr
+
+
+_GLOBAL(mpc52xx_ds_sram)
+mpc52xx_ds_sram:
+	/* put SDRAM into self-refresh */
+	lwz	r8, 0x4(r4)	/* sdram->ctrl */
+
+	oris	r8, r8, 0x8000 /* mode_en */
+	stw	r8, 0x4(r4)
+	sync
+
+	ori	r8, r8, 0x0002 /* soft_pre */
+	stw	r8, 0x4(r4)
+	sync
+	xori	r8, r8, 0x0002
+
+	xoris	r8, r8, 0x8000 /* !mode_en */
+	stw	r8, 0x4(r4)
+	sync
+
+	oris	r8, r8, 0x5000
+	xoris	r8, r8, 0x4000 /* ref_en !cke */
+	stw	r8, 0x4(r4)
+	sync
+
+	/* disable SDRAM clock */
+	lwz	r8, 0x14(r5) /* cdm->clkenable */
+	ori	r8, r8, 0x0008
+	xori	r8, r8, 0x0008
+	stw	r8, 0x14(r5)
+	sync
+
+
+	/* put mpc5200 to sleep */
+	mfmsr	r10
+	oris	r10, r10, 0x0004	/* POW = 1 */
+	sync; isync;
+	mtmsr	r10
+	sync; isync;
+
+
+	/* enable clock */
+	lwz	r8, 0x14(r5)
+	ori	r8, r8, 0x0008
+	stw	r8, 0x14(r5)
+	sync
+
+	/* get ram out of self-refresh */
+	lwz	r8, 0x4(r4)
+	oris	r8, r8, 0x5000 /* cke ref_en */
+	stw	r8, 0x4(r4)
+	sync
+
+	blr
+_GLOBAL(mpc52xx_ds_sram_size)
+mpc52xx_ds_sram_size:
+	.long $-mpc52xx_ds_sram
+
+
+/* ### interrupt handler for wakeup from deep-sleep ### */
+_GLOBAL(mpc52xx_ds_cached)
+mpc52xx_ds_cached:
+	mtspr	SPRN_SPRG0, r7
+	mtspr	SPRN_SPRG1, r8
+
+	/* disable emulated interrupt */
+	mfspr	r7, 311 /* MBAR */
+	addi	r7, r7, 0x540	/* intr->main_emul */
+	li	r8, 0
+	stw	r8, 0(r7)
+	sync
+	dcbf	0, r7
+
+	/* acknowledge wakeup, so CCS releases power pown */
+	mfspr	r7, 311	/* MBAR */
+	addi	r7, r7, 0x524	/* intr->enc_status */
+	lwz	r8, 0(r7)
+	ori	r8, r8, 0x0400
+	stw	r8, 0(r7)
+	sync
+	dcbf	0, r7
+
+	/* flag - we handled the interrupt */
+	li	r10, 1
+
+	mfspr	r8, SPRN_SPRG1
+	mfspr	r7, SPRN_SPRG0
+
+	rfi
+_GLOBAL(mpc52xx_ds_cached_size)
+mpc52xx_ds_cached_size:
+	.long $-mpc52xx_ds_cached
Index: grant.git/arch/powerpc/platforms/52xx/efika.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/efika.c
+++ grant.git/arch/powerpc/platforms/52xx/efika.c
@@ -185,6 +185,16 @@ static void efika_show_cpuinfo(struct se
 	of_node_put(root);
 }
 
+#ifdef CONFIG_PM
+static void efika_suspend_prepare(void __iomem *mbar)
+{
+	u8 pin = 4;	/* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */
+	u8 level = 1;	/* wakeup on high level */
+	/* IOW. to wake it up, short pins 1 and 3 on IRDA connector */
+	mpc52xx_set_wakeup_gpio(pin, level);
+}
+#endif
+
 static void __init efika_setup_arch(void)
 {
 	rtas_initialize();
@@ -200,6 +210,11 @@ static void __init efika_setup_arch(void
 
 	efika_pcisetup();
 
+#ifdef CONFIG_PM
+	mpc52xx_suspend.board_suspend_prepare = efika_suspend_prepare;
+	mpc52xx_pm_init();
+#endif
+
 	if (ppc_md.progress)
 		ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
 }
Index: grant.git/arch/powerpc/platforms/52xx/lite5200.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/lite5200.c
+++ grant.git/arch/powerpc/platforms/52xx/lite5200.c
@@ -85,6 +85,28 @@ error:
 	iounmap(gpio);
 }
 
+#ifdef CONFIG_PM
+static u32 descr_a;
+static void lite5200_suspend_prepare(void __iomem *mbar)
+{
+	u8 pin = 1;	/* GPIO_WKUP_1 (GPIO_PSC2_4) */
+	u8 level = 0;	/* wakeup on low level */
+	mpc52xx_set_wakeup_gpio(pin, level);
+
+	/*
+	 * power down usb port
+	 * this needs to be called before of-ohci suspend code
+	 */
+	descr_a = in_be32(mbar + 0x1048);
+	out_be32(mbar + 0x1048, (descr_a & ~0x200) | 0x100);
+}
+
+static void lite5200_resume_finish(void __iomem *mbar)
+{
+	out_be32(mbar + 0x1048, descr_a);
+}
+#endif
+
 static void __init lite5200_setup_arch(void)
 {
 	struct device_node *np;
@@ -107,6 +129,12 @@ static void __init lite5200_setup_arch(v
 	mpc52xx_setup_cpu();	/* Generic */
 	lite5200_setup_cpu();	/* Platorm specific */
 
+#ifdef CONFIG_PM
+	mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
+	mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
+	mpc52xx_pm_init();
+#endif
+
 #ifdef CONFIG_PCI
 	np = of_find_node_by_type(np, "pci");
 	if (np)
Index: grant.git/include/asm-powerpc/mpc52xx.h
===================================================================
--- grant.git.orig/include/asm-powerpc/mpc52xx.h
+++ grant.git/include/asm-powerpc/mpc52xx.h
@@ -253,5 +253,16 @@ extern int __init mpc52xx_add_bridge(str
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_PM
+struct mpc52xx_suspend {
+	void (*board_suspend_prepare)(void __iomem *mbar);
+	void (*board_resume_finish)(void __iomem *mbar);
+};
+
+extern struct mpc52xx_suspend mpc52xx_suspend;
+extern int __init mpc52xx_pm_init(void);
+extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level);
+#endif /* CONFIG_PM */
+
 #endif /* __ASM_POWERPC_MPC52xx_H__ */
 

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

* Re: [PATCH 4/5] mpc52xx suspend: deep-sleep
  2007-04-17  7:05         ` Domen Puncer
@ 2007-04-17  7:10           ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-04-17  7:10 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 4/17/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> 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.
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-03-15 14:09   ` Grant Likely
  2007-03-15 16:36     ` Domen Puncer
@ 2007-04-17  7:11     ` Domen Puncer
  2007-04-17  7:25       ` Grant Likely
  1 sibling, 1 reply; 48+ messages in thread
From: Domen Puncer @ 2007-04-17  7:11 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded

Low-power mode implementation for Lite5200b.  (Most of devices
on board, including the CPU, are powered down)

Some I/O registers are also saved here.

A patch to U-Boot that wakes up SDRAM, and transfers control
to address saved at physical 0x0 is needed, and is already
merged in git://www.denx.de/git/u-boot-ppc4xx.git tree.


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

---
 arch/powerpc/platforms/52xx/Makefile         |    3 
 arch/powerpc/platforms/52xx/lite5200.c       |    2 
 arch/powerpc/platforms/52xx/lite5200_pm.c    |  210 +++++++++++++
 arch/powerpc/platforms/52xx/lite5200_sleep.S |  413 +++++++++++++++++++++++++++
 include/asm-powerpc/mpc52xx.h                |   10 
 5 files changed, 637 insertions(+), 1 deletion(-)

Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -0,0 +1,210 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+
+/* defined in lite5200_sleep.S and only used here */
+extern void lite5200_low_power(void *sram, void *mbar);
+
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_intr __iomem *pic;
+static struct mpc52xx_sdma __iomem *bes;
+static struct mpc52xx_xlb __iomem *xlb;
+static struct mpc52xx_gpio __iomem *gps;
+static struct mpc52xx_gpio_wkup __iomem *gpw;
+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 = mpc52xx_find_and_map("mpc5200");
+	if (!mbar) {
+		printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+		return -ENOSYS;
+	}
+
+	cdm = mbar + 0x200;
+	pic = mbar + 0x500;
+	gps = mbar + 0xb00;
+	gpw = mbar + 0xc00;
+	bes = mbar + 0x1200;
+	xlb = mbar + 0x1f00;
+
+	return 0;
+}
+
+/* save and restore registers not bound to any real devices */
+static struct mpc52xx_cdm scdm;
+static struct mpc52xx_intr spic;
+static struct mpc52xx_sdma sbes;
+static struct mpc52xx_xlb sxlb;
+static struct mpc52xx_gpio sgps;
+static struct mpc52xx_gpio_wkup sgpw;
+
+static void lite5200_save_regs(void)
+{
+	_memcpy_fromio(&spic, pic, sizeof(*pic));
+	_memcpy_fromio(&sbes, bes, sizeof(*bes));
+	_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)
+{
+	int i;
+	memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+
+	/*
+	 * GPIOs. Interrupt Master Enable has higher address then other
+	 * registers, so just memcpy is ok.
+	 */
+	_memcpy_toio(gpw, &sgpw, sizeof(*gpw));
+	_memcpy_toio(gps, &sgps, sizeof(*gps));
+
+
+	/* XLB Arbitrer */
+	out_be32(&xlb->snoop_window, sxlb.snoop_window);
+	out_be32(&xlb->master_priority, sxlb.master_priority);
+	out_be32(&xlb->master_pri_enable, sxlb.master_pri_enable);
+
+	/* enable */
+	out_be32(&xlb->int_enable, sxlb.int_enable);
+	out_be32(&xlb->config, sxlb.config);
+
+
+	/* CDM - Clock Distribution Module */
+	out_8(&cdm->ipb_clk_sel, scdm.ipb_clk_sel);
+	out_8(&cdm->pci_clk_sel, scdm.pci_clk_sel);
+
+	out_8(&cdm->ext_48mhz_en, scdm.ext_48mhz_en);
+	out_8(&cdm->fd_enable, scdm.fd_enable);
+	out_be16(&cdm->fd_counters, scdm.fd_counters);
+
+	out_be32(&cdm->clk_enables, scdm.clk_enables);
+
+	out_8(&cdm->osc_disable, scdm.osc_disable);
+
+	out_be16(&cdm->mclken_div_psc1, scdm.mclken_div_psc1);
+	out_be16(&cdm->mclken_div_psc2, scdm.mclken_div_psc2);
+	out_be16(&cdm->mclken_div_psc3, scdm.mclken_div_psc3);
+	out_be16(&cdm->mclken_div_psc6, scdm.mclken_div_psc6);
+
+
+	/* BESTCOMM */
+	out_be32(&bes->taskBar, sbes.taskBar);
+	out_be32(&bes->currentPointer, sbes.currentPointer);
+	out_be32(&bes->endPointer, sbes.endPointer);
+	out_be32(&bes->variablePointer, sbes.variablePointer);
+
+	out_8(&bes->IntVect1, sbes.IntVect1);
+	out_8(&bes->IntVect2, sbes.IntVect2);
+	out_be16(&bes->PtdCntrl, sbes.PtdCntrl);
+
+	for (i=0; i<32; i++)
+		out_8(&bes->ipr[i], sbes.ipr[i]);
+
+	out_be32(&bes->cReqSelect, sbes.cReqSelect);
+	out_be32(&bes->task_size0, sbes.task_size0);
+	out_be32(&bes->task_size1, sbes.task_size1);
+	out_be32(&bes->MDEDebug, sbes.MDEDebug);
+	out_be32(&bes->ADSDebug, sbes.ADSDebug);
+	out_be32(&bes->Value1, sbes.Value1);
+	out_be32(&bes->Value2, sbes.Value2);
+	out_be32(&bes->Control, sbes.Control);
+	out_be32(&bes->Status, sbes.Status);
+	out_be32(&bes->PTDDebug, sbes.PTDDebug);
+
+	/* restore tasks */
+	for (i=0; i<16; i++)
+		out_be16(&bes->tcr[i], sbes.tcr[i]);
+
+	/* enable interrupts */
+	out_be32(&bes->IntPend, sbes.IntPend);
+	out_be32(&bes->IntMask, sbes.IntMask);
+
+
+	/* PIC */
+	out_be32(&pic->per_pri1, spic.per_pri1);
+	out_be32(&pic->per_pri2, spic.per_pri2);
+	out_be32(&pic->per_pri3, spic.per_pri3);
+
+	out_be32(&pic->main_pri1, spic.main_pri1);
+	out_be32(&pic->main_pri2, spic.main_pri2);
+
+	out_be32(&pic->enc_status, spic.enc_status);
+
+	/* unmask and enable interrupts */
+	out_be32(&pic->per_mask, spic.per_mask);
+	out_be32(&pic->main_mask, spic.main_mask);
+	out_be32(&pic->ctrl, spic.ctrl);
+}
+
+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);
+	}
+
+	lite5200_save_regs();
+
+	/* effectively save FP regs */
+	enable_kernel_fp();
+
+	lite5200_low_power(sdma.sram, mbar);
+
+	lite5200_restore_regs();
+
+	/* restart jiffies */
+	wakeup_decrementer();
+
+	iounmap(mbar);
+	return 0;
+}
+
+static int lite5200_pm_finish(suspend_state_t state)
+{
+	/* deep sleep? let mpc52xx code handle that */
+	if (state == PM_SUSPEND_STANDBY) {
+		return mpc52xx_pm_finish(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,
+};
+
+int __init lite5200_pm_init(void)
+{
+	pm_set_ops(&lite5200_pm_ops);
+	return 0;
+}
Index: grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
@@ -0,0 +1,413 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+
+#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_DDR	0xc08
+#define GPIOW_DVO	0xc0c
+
+#define CDM_CE		0x214
+#define CDM_SDRAM	(1<<3)
+
+
+/* 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;
+
+
+	.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
+	 * 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
+
+	/* get tb_ticks_per_usec */
+	lis	r3, tb_ticks_per_usec@h
+	lwz	r11, tb_ticks_per_usec@l(r3)
+
+	/* 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;
+
+	/* jump to sram */
+	mtlr	r7
+	blrl
+	/* doesn't return */
+
+
+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 NOP to finish) */
+	li	r12, 1
+	bl	udelay
+
+	/*
+	 * 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 (after !CKE there should be two cycles) */
+	li	r12, 1
+	bl	udelay
+
+	/* disable clock */
+	lwz	r4, CDM_CE(r8)
+	ori	r4, r4, CDM_SDRAM
+	xori	r4, r4, CDM_SDRAM
+	stw	r4, CDM_CE(r8)
+	sync
+
+	/* delay a bit */
+	li	r12, 1
+	bl	udelay
+
+
+	/* 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
+
+	/* 10uS delay */
+	li	r12, 10
+	bl	udelay
+
+	/* turn off */
+	li	r4, 0
+	stb	r4, GPIOW_DVO(r8)	/* output low */
+	sync
+
+	/* wait until we're offline */
+  1:
+	b	1b
+
+
+	/* local udelay in sram is needed */
+  udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */
+	mullw	r12, r12, r11
+	mftb	r13	/* start */
+	addi	r12, r13, r12 /* end */
+    1:
+	mftb	r13	/* current */
+	cmp	cr0, r13, r12
+	blt	1b
+	blr
+
+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;
+
+	/* 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
+
+	/* MMU is not up yet */
+	subis	r4, r4, CONFIG_KERNEL_START@h
+
+	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.o
 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/lite5200.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/lite5200.c
+++ grant.git/arch/powerpc/platforms/52xx/lite5200.c
@@ -132,7 +132,7 @@ static void __init lite5200_setup_arch(v
 #ifdef CONFIG_PM
 	mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
 	mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
-	mpc52xx_pm_init();
+ 	lite5200_pm_init();
 #endif
 
 #ifdef CONFIG_PCI
Index: grant.git/include/asm-powerpc/mpc52xx.h
===================================================================
--- grant.git.orig/include/asm-powerpc/mpc52xx.h
+++ grant.git/include/asm-powerpc/mpc52xx.h
@@ -262,6 +262,16 @@ struct mpc52xx_suspend {
 extern struct mpc52xx_suspend mpc52xx_suspend;
 extern int __init mpc52xx_pm_init(void);
 extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level);
+
+#ifdef CONFIG_PPC_LITE5200
+extern int __init lite5200_pm_init(void);
+
+/* lite5200 calls mpc5200 suspend functions, so here they are */
+extern int mpc52xx_pm_prepare(suspend_state_t);
+extern int mpc52xx_pm_enter(suspend_state_t);
+extern int mpc52xx_pm_finish(suspend_state_t);
+extern char saved_sram[0x4000]; /* reuse buffer from mpc52xx suspend */
+#endif
 #endif /* CONFIG_PM */
 
 #endif /* __ASM_POWERPC_MPC52xx_H__ */

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

* Re: [PATCH 5/5] lite5200b suspend: low-power mode
  2007-04-17  7:11     ` Domen Puncer
@ 2007-04-17  7:25       ` Grant Likely
  0 siblings, 0 replies; 48+ messages in thread
From: Grant Likely @ 2007-04-17  7:25 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linuxppc-embedded

On 4/17/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Low-power mode implementation for Lite5200b.  (Most of devices
> on board, including the CPU, are powered down)
>
> Some I/O registers are also saved here.
>
> A patch to U-Boot that wakes up SDRAM, and transfers control
> to address saved at physical 0x0 is needed, and is already
> merged in git://www.denx.de/git/u-boot-ppc4xx.git tree.
>
>
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16 12:04         ` Stefan Roese
  2007-04-16 13:08           ` Domen Puncer
@ 2007-04-17 11:29           ` Stefan Roese
  2007-04-17 14:50             ` Wolfgang Denk
  1 sibling, 1 reply; 48+ messages in thread
From: Stefan Roese @ 2007-04-17 11:29 UTC (permalink / raw)
  To: u-boot

Hi Domen,

On Monday 16 April 2007 14:04, Stefan Roese wrote:
> On Monday 16 April 2007 06:45, Grant Likely wrote:
> > On 4/3/07, Domen Puncer <domen.puncer@telargo.com> 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.
> >
> > Looks good; almost there.  Only one thing missing... you need to add
> > your "Signed-off-by" line.  :-)  See Documentation/SubmittingPatches
> > in the Linux source tree.  (You can just reply to this message, and
> > whoever merges the patch will add the line to the commit message)
> >
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> >
> > Stefan; since there is no 5200 custodian, can you please pick up this
> > patch once Domen sends a Signed-of-by replay?
>
> Done.

Rafal mentioned to me off-list that some documentation about this 
suspend/wakeup mechanism would be preferable. Here his notes:

"
- regarding the U-Boot piece I'd only like to see some explanation (as a 
comment or short readme file) of the overall concept and scenario as it 
is not intuitive at all and rather difficult to understand all the 
ramifications and constraints from looking at the code only
"

So Domen, could you please either send a reworked patch with this 
documentation (preferable some file in doc/README.xxx) or just send a new 
patch with only this documentation?

Thanks.

BTW: Wolfgang reminded me, that putting this stuff into the u-boot-ppc4xx 
repository is not a good solution. I'll try to move this over to 
u-boot-testing.

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
=====================================================================

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-17 11:29           ` Stefan Roese
@ 2007-04-17 14:50             ` Wolfgang Denk
  2007-04-18  5:55               ` [U-Boot-Users] [PATCH] icecube/lite5200b: document " Domen Puncer
  0 siblings, 1 reply; 48+ messages in thread
From: Wolfgang Denk @ 2007-04-17 14:50 UTC (permalink / raw)
  To: u-boot

Dear Domen,

in message <200704171329.37002.sr@denx.de> Stefan Roese wrote:
> 
> - regarding the U-Boot piece I'd only like to see some explanation (as a 
> comment or short readme file) of the overall concept and scenario as it 
> is not intuitive at all and rather difficult to understand all the 
> ramifications and constraints from looking at the code only
> "
> 
> So Domen, could you please either send a reworked patch with this 
> documentation (preferable some file in doc/README.xxx) or just send a new 
> patch with only this documentation?

The documentation should  also  include  information  which  configu-
rations  have  been  tested,  i. e. if PCI, IDE, USB, ... device have
been attached to the system during these test cycles,  and  if  these
survived.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Marriage is the sole cause of divorce.

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: document wakeup from low-power support
  2007-04-17 14:50             ` Wolfgang Denk
@ 2007-04-18  5:55               ` Domen Puncer
  0 siblings, 0 replies; 48+ messages in thread
From: Domen Puncer @ 2007-04-18  5:55 UTC (permalink / raw)
  To: u-boot

Document what Lite5200B low-power is about.


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

---
 doc/README.Lite5200B_low_power |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Index: u-boot.git/doc/README.Lite5200B_low_power
===================================================================
--- /dev/null
+++ u-boot.git/doc/README.Lite5200B_low_power
@@ -0,0 +1,22 @@
+Lite5200B wakeup from low-power mode (CONFIG_LITE5200B_PM)
+----------------------------------------------------------
+
+Low-power mode as described in Lite5200B User's Manual, means that
+with support of MC68HLC908QT1 microcontroller (refered to as QT),
+everything but the SDRAM can be powered down. This brings
+maximum power saving, while one can still restore previous state
+quickly.
+
+Quick overview where U-Boot comes into the picture:
+- OS saves device states
+- OS saves wakeup handler address to physical 0x0, puts SDRAM into
+  self-refresh and signals to QT, it should power down the board
+- / board is sleeping here /
+- someone presses SW4 (connected to QT)
+- U-Boot checks PSC2_4 pin, if QT drives it down, then we woke up,
+  so get SDRAM out of self-refresh and transfer control to OS
+  wakeup handler
+- OS restores device states
+
+This was tested on Linux with USB and Ethernet in use. Adding
+support for other devices is an OS issue.

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-16 13:08           ` Domen Puncer
  2007-04-16 13:36             ` Grant Likely
@ 2007-04-20 12:13             ` Stefan Roese
  2007-04-20 13:47               ` Wolfgang Denk
  1 sibling, 1 reply; 48+ messages in thread
From: Stefan Roese @ 2007-04-20 12:13 UTC (permalink / raw)
  To: u-boot

Hi Domen,

On Monday 16 April 2007 15:08, Domen Puncer wrote:
> While at it, can you also take care of (Grant already agreed
> with the change):

since we don't have a 52xx repository, I commited it into the u-boot-testing 
repository:

git://www.denx.de/git/u-boot-testing.git

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
=====================================================================

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

* [U-Boot-Users] [PATCH] icecube/lite5200b: wakeup from low-power support
  2007-04-20 12:13             ` Stefan Roese
@ 2007-04-20 13:47               ` Wolfgang Denk
  0 siblings, 0 replies; 48+ messages in thread
From: Wolfgang Denk @ 2007-04-20 13:47 UTC (permalink / raw)
  To: u-boot

In message <200704201413.05902.sr@denx.de> you wrote:
>
> since we don't have a 52xx repository, I commited it into the u-boot-testing 
> repository:
> 
> git://www.denx.de/git/u-boot-testing.git

Merged.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk
Office:  Kirchenstr. 5,       D-82194 Groebenzell,            Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The first thing we do is kill all the lawyers.
(Shakespeare. II Henry VI, Act IV, scene ii)

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

end of thread, other threads:[~2007-04-20 13:47 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-15 10:39 [PATCH 0/5 v2] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-15 10:41 ` [PATCH 1/5] mpc52xx suspend: UART Domen Puncer
2007-03-15 10:41 ` [PATCH 2/5] mpc52xx suspend: FEC (ethernet) Domen Puncer
2007-03-15 13:35   ` Grant Likely
2007-03-15 10:42 ` [PATCH 3/5] mpc52xx suspend: USB Domen Puncer
2007-03-15 13:24   ` Grant Likely
2007-03-15 14:37     ` Wrong board info for ML403 Leonid
2007-03-16  8:15       ` Andrei Konovalov
2007-03-22  7:44     ` [PATCH 3/5 v2] mpc52xx suspend: USB Domen Puncer
2007-03-23 11:56       ` Sylvain Munaut
2007-03-23 16:00         ` Grant Likely
2007-03-15 10:43 ` [PATCH 4/5] mpc52xx suspend: deep-sleep Domen Puncer
2007-03-23 15:58   ` Grant Likely
2007-04-04  7:37     ` Domen Puncer
2007-04-16  5:40       ` Grant Likely
2007-04-17  7:05         ` Domen Puncer
2007-04-17  7:10           ` Grant Likely
2007-03-15 10:44 ` [PATCH] icecube/lite5200b: wakeup from low-power support Domen Puncer
2007-03-15 10:44   ` [U-Boot-Users] " Domen Puncer
2007-03-26 16:08   ` Grant Likely
2007-03-26 16:08     ` [U-Boot-Users] " Grant Likely
2007-04-03  8:46     ` Domen Puncer
2007-04-03  8:46       ` [U-Boot-Users] " Domen Puncer
2007-04-16  4:45       ` Grant Likely
2007-04-16  4:45         ` [U-Boot-Users] " Grant Likely
2007-04-16  6:25         ` Domen Puncer
2007-04-16  6:25           ` [U-Boot-Users] " Domen Puncer
2007-04-16  7:10           ` Wolfgang Denk
2007-04-16 12:04         ` Stefan Roese
2007-04-16 13:08           ` Domen Puncer
2007-04-16 13:36             ` Grant Likely
2007-04-20 12:13             ` Stefan Roese
2007-04-20 13:47               ` Wolfgang Denk
2007-04-17 11:29           ` Stefan Roese
2007-04-17 14:50             ` Wolfgang Denk
2007-04-18  5:55               ` [U-Boot-Users] [PATCH] icecube/lite5200b: document " Domen Puncer
2007-03-31 17:20   ` [PATCH] icecube/lite5200b: " Rafal Jaworowski
2007-03-31 17:20     ` [U-Boot-Users] " Rafal Jaworowski
2007-03-31 18:38     ` Domen Puncer
2007-03-31 18:38       ` Domen Puncer
2007-03-15 10:44 ` [PATCH 5/5] lite5200b suspend: low-power mode Domen Puncer
2007-03-15 14:09   ` Grant Likely
2007-03-15 16:36     ` Domen Puncer
2007-03-22  7:41       ` Domen Puncer
2007-03-26 13:23         ` Domen Puncer
2007-03-26 15:54           ` Grant Likely
2007-04-17  7:11     ` Domen Puncer
2007-04-17  7:25       ` Grant Likely

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.