* [PATCH 0/7] MPC5200 and Lite5200b low power modes
@ 2007-03-01 7:53 Domen Puncer
2007-03-01 7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
` (9 more replies)
0 siblings, 10 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:53 UTC (permalink / raw)
To: linuxppc-embedded
Hi!
Patches are based on latest mainline git tree + fec patches:
Fec_MPC5200_eth_driver.patch
Copy_bestcomm_support_files_into_arch_powerpc.patch
Make_FEC_work_on_the_lite5200.patch
This patchset includes the following patches:
- [PATCH 1/7] mpc52xx suspend: bestcomm
- [PATCH 2/7] mpc52xx suspend: UART
- [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
- [PATCH 4/7] mpc52xx suspend: USB
- [PATCH 5/7] mpc52xx suspend: deep-sleep
- [PATCH 6/7] lite5200b suspend: PIC
- [u-boot patch] support lite5200b wakeup in u-boot
- [PATCH 7/7] lite5200b suspend: low-power mode
I would appreaciate any comments, suggestions etc.
Domen
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/7] mpc52xx suspend: bestcomm
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-01 7:54 ` Domen Puncer
2007-03-01 7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
` (8 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:54 UTC (permalink / raw)
To: linuxppc-embedded
Save and restore bestcomm registers and SRAM.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/arch/powerpc/platforms/52xx/bestcomm.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/bestcomm.c
+++ grant.git/arch/powerpc/platforms/52xx/bestcomm.c
@@ -395,4 +395,75 @@ EXPORT_SYMBOL(sdma_set_initiator);
EXPORT_SYMBOL(sdma_free);
EXPORT_SYMBOL(sdma);
+#ifdef CONFIG_PM
+static struct mpc52xx_sdma sdma_regs;
+static char saved_sram[0x4000]; /* copy of 16kB internal SRAM */
+int mpc52xx_sdma_suspend(void)
+{
+ int i;
+
+ sdma_regs.taskBar = in_be32(&sdma.io->taskBar);
+ sdma_regs.currentPointer = in_be32(&sdma.io->currentPointer);
+ sdma_regs.endPointer = in_be32(&sdma.io->endPointer);
+ sdma_regs.variablePointer = in_be32(&sdma.io->variablePointer);
+ sdma_regs.IntVect1 = in_8(&sdma.io->IntVect1);
+ sdma_regs.IntVect2 = in_8(&sdma.io->IntVect2);
+ sdma_regs.PtdCntrl = in_be16(&sdma.io->PtdCntrl);
+ sdma_regs.IntPend = in_be32(&sdma.io->IntPend);
+ sdma_regs.IntMask = in_be32(&sdma.io->IntMask);
+
+ for (i=0; i<16; i++)
+ sdma_regs.tcr[i] = in_be16(&sdma.io->tcr[i]);
+ for (i=0; i<32; i++)
+ sdma_regs.ipr[i] = in_8(&sdma.io->ipr[i]);
+
+ sdma_regs.cReqSelect = in_be32(&sdma.io->cReqSelect);
+ sdma_regs.task_size0 = in_be32(&sdma.io->task_size0);
+ sdma_regs.task_size1 = in_be32(&sdma.io->task_size1);
+ sdma_regs.MDEDebug = in_be32(&sdma.io->MDEDebug);
+ sdma_regs.ADSDebug = in_be32(&sdma.io->ADSDebug);
+ sdma_regs.Value1 = in_be32(&sdma.io->Value1);
+ sdma_regs.Value2 = in_be32(&sdma.io->Value2);
+ sdma_regs.Control = in_be32(&sdma.io->Control);
+ sdma_regs.Status = in_be32(&sdma.io->Status);
+ sdma_regs.PTDDebug = in_be32(&sdma.io->PTDDebug);
+
+ memcpy(saved_sram, sdma.sram, sdma.sram_size);
+ return 0;
+}
+
+int mpc52xx_sdma_resume(void)
+{
+ int i;
+
+ memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+ out_be32(&sdma.io->taskBar, sdma_regs.taskBar);
+ out_be32(&sdma.io->currentPointer, sdma_regs.currentPointer);
+ out_be32(&sdma.io->endPointer, sdma_regs.endPointer);
+ out_be32(&sdma.io->variablePointer, sdma_regs.variablePointer);
+ out_8(&sdma.io->IntVect1, sdma_regs.IntVect1);
+ out_8(&sdma.io->IntVect2, sdma_regs.IntVect2);
+ out_be16(&sdma.io->PtdCntrl, sdma_regs.PtdCntrl);
+ out_be32(&sdma.io->IntPend, sdma_regs.IntPend);
+ out_be32(&sdma.io->IntMask, sdma_regs.IntMask);
+
+ for (i=0; i<16; i++)
+ out_be16(&sdma.io->tcr[i], sdma_regs.tcr[i]);
+ for (i=0; i<32; i++)
+ out_8(&sdma.io->ipr[i], sdma_regs.ipr[i]);
+
+ out_be32(&sdma.io->cReqSelect, sdma_regs.cReqSelect);
+ out_be32(&sdma.io->task_size0, sdma_regs.task_size0);
+ out_be32(&sdma.io->task_size1, sdma_regs.task_size1);
+ out_be32(&sdma.io->MDEDebug, sdma_regs.MDEDebug);
+ out_be32(&sdma.io->ADSDebug, sdma_regs.ADSDebug);
+ out_be32(&sdma.io->Value1, sdma_regs.Value1);
+ out_be32(&sdma.io->Value2, sdma_regs.Value2);
+ out_be32(&sdma.io->Control, sdma_regs.Control);
+ out_be32(&sdma.io->Status, sdma_regs.Status);
+ out_be32(&sdma.io->PTDDebug, sdma_regs.PTDDebug);
+ return 0;
+}
+#endif
Index: grant.git/arch/powerpc/platforms/52xx/bestcomm.h
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/bestcomm.h
+++ grant.git/arch/powerpc/platforms/52xx/bestcomm.h
@@ -473,6 +473,11 @@ extern void *sdma_sram_alloc(int size, i
extern void sdma_init_bd(struct sdma *s);
extern void sdma_init_bd2(struct sdma *s);
+#ifdef CONFIG_PM
+extern int mpc52xx_sdma_suspend(void);
+extern int mpc52xx_sdma_resume(void);
+#endif
+
#define FIELD_OFFSET(s,f) ((unsigned long)(&(((struct s*)0)->f)))
#endif /* __BESTCOMM_BESTCOMM_H__ */
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 2/7] mpc52xx suspend: UART
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-01 7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
@ 2007-03-01 7:55 ` Domen Puncer
2007-03-01 7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
` (7 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:55 UTC (permalink / raw)
To: linuxppc-embedded
MPC52xx uart power management.
Not sure how exactly this should be written, but this seems
to work, and works around a few seconds delay in resume.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/drivers/serial/mpc52xx_uart.c
===================================================================
--- grant.git.orig/drivers/serial/mpc52xx_uart.c
+++ grant.git/drivers/serial/mpc52xx_uart.c
@@ -418,6 +418,22 @@ mpc52xx_uart_verify_port(struct uart_por
return 0;
}
+/* just Reenable TX and RX */
+static void mpc52xx_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+ struct mpc52xx_psc __iomem *psc = PSC(port);
+ unsigned long flags;
+
+ /* Get the lock */
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Reenable TX & RX */
+ out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
+ out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
+
+ /* We're all set, release the lock */
+ spin_unlock_irqrestore(&port->lock, flags);
+}
static struct uart_ops mpc52xx_uart_ops = {
.tx_empty = mpc52xx_uart_tx_empty,
@@ -432,8 +448,10 @@ static struct uart_ops mpc52xx_uart_ops
.startup = mpc52xx_uart_startup,
.shutdown = mpc52xx_uart_shutdown,
.set_termios = mpc52xx_uart_set_termios,
-/* .pm = mpc52xx_uart_pm, Not supported yet */
-/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
+
+ .pm = mpc52xx_uart_pm,
+/* .set_wake = mpc52xx_uart_set_wake,*/
+
.type = mpc52xx_uart_type,
.release_port = mpc52xx_uart_release_port,
.request_port = mpc52xx_uart_request_port,
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-01 7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
2007-03-01 7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
@ 2007-03-01 7:55 ` Domen Puncer
2007-03-01 7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
` (6 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:55 UTC (permalink / raw)
To: linuxppc-embedded
Suspend and resume for FEC on MPC52xx.
It just turns off (and on) leds, and even this in a hackish way.
The right way is probably to figure out how BMCR_PDOWN works.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/drivers/net/fec_mpc52xx/fec.c
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec.c
+++ grant.git/drivers/net/fec_mpc52xx/fec.c
@@ -801,6 +801,58 @@ mpc52xx_fec_remove(struct device *dev)
return 0;
}
+#ifdef CONFIG_PM
+int mpc52xx_fec_suspend(struct of_device *op, pm_message_t state)
+{
+ struct net_device *ndev = dev_get_drvdata(&op->dev);
+ struct fec_priv *priv = ndev->priv;
+ struct mpc52xx_fec *fec = priv->fec;
+
+ netif_stop_queue(ndev);
+ out_be32(&fec->imask, 0x0);
+
+ /* Disable the rx and tx tasks. */
+ sdma_disable(priv->rx_sdma);
+ sdma_disable(priv->tx_sdma);
+
+ fec_free_rx_buffers(priv->rx_sdma);
+
+ /* Stop FEC */
+ out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~0x2);
+
+ fec_mii_suspend(ndev);
+
+ return 0;
+}
+
+int mpc52xx_fec_resume(struct of_device *op)
+{
+ struct net_device *ndev = dev_get_drvdata(&op->dev);
+ struct fec_priv *priv = ndev->priv;
+ struct mpc52xx_fec *fec = priv->fec;
+
+ //fec_mii_resume(ndev);
+
+ fec_mii_init(ndev);
+
+ fec_hw_init(ndev);
+
+ /* restore leds. ugly hack, but fec_mii_resume doesn't work for me */
+ out_be32(&fec->mii_data, 0x50020000 | (0x14 << 18) | 0x0422);
+
+ /* Restart the DMA tasks */
+ sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo, FEC_RX_BUFFER_SIZE);
+ sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
+
+ if (priv->sequence_done) { /* redo the fec_open() */
+ fec_free_rx_buffers(priv->rx_sdma);
+ fec_open(ndev);
+ }
+
+ return 0;
+}
+#endif
+
#if defined(CONFIG_PPC_MERGE)
static struct of_device_id mpc52xx_fec_of_match[] = {
{ .compatible = "mpc5200-ethernet", },
@@ -815,8 +867,8 @@ static struct of_platform_driver mpc52xx
.probe = mpc52xx_fec_probe,
.remove = mpc52xx_fec_remove,
#ifdef CONFIG_PM
-/* .suspend = mpc52xx_fec_suspend, TODO */
-/* .resume = mpc52xx_fec_resume, TODO */
+ .suspend = mpc52xx_fec_suspend,
+ .resume = mpc52xx_fec_resume,
#endif
.driver = {
.name = DRIVER_NAME,
Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.c
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.c
+++ grant.git/drivers/net/fec_mpc52xx/fec_phy.c
@@ -77,6 +77,7 @@ static int mii_queue(struct net_device *
#define MII_REG_ANER 6 /* A-N Expansion Register */
#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */
#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */
+#define MII_REG_LED 20 /* LED Configuration Register */
/* values for phy_status */
@@ -527,6 +528,23 @@ int fec_mii_wait(struct net_device *dev)
return 0;
}
+#ifdef CONFIG_PM
+phy_cmd_t phy_cmd_leds_off[] ={ { mk_mii_write(MII_REG_LED, 0x9992), NULL },
+ { mk_mii_end, } };
+phy_cmd_t phy_cmd_leds_on[] = { { mk_mii_write(MII_REG_LED, 0x0422), NULL },
+ { mk_mii_end, } };
+
+void fec_mii_suspend(struct net_device *dev)
+{
+ mii_do_cmd(dev, phy_cmd_leds_off);
+}
+
+void fec_mii_resume(struct net_device *dev)
+{
+ mii_do_cmd(dev, phy_cmd_leds_on);
+}
+#endif
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dale Farnsworth");
MODULE_DESCRIPTION("PHY driver for Motorola MPC52xx FEC");
Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.h
===================================================================
--- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.h
+++ grant.git/drivers/net/fec_mpc52xx/fec_phy.h
@@ -71,3 +71,8 @@ extern int fec_mii_wait(struct net_devic
extern void fec_mii(struct net_device *dev);
extern int fec_ioctl(struct net_device *, struct ifreq *rq, int cmd);
+
+#ifdef CONFIG_PM
+extern void fec_mii_suspend(struct net_device *dev);
+extern void fec_mii_resume(struct net_device *dev);
+#endif
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 4/7] mpc52xx suspend: USB
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (2 preceding siblings ...)
2007-03-01 7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
@ 2007-03-01 7:56 ` Domen Puncer
2007-03-01 7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
` (5 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:56 UTC (permalink / raw)
To: linuxppc-embedded
Trivial suspend and resume OF OHCI.
On MPC52xx turn off and on power to ports.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/drivers/usb/host/ohci-ppc-of.c
===================================================================
--- grant.git.orig/drivers/usb/host/ohci-ppc-of.c
+++ grant.git/drivers/usb/host/ohci-ppc-of.c
@@ -214,6 +214,32 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_
#endif
+#ifdef CONFIG_PM
+static u32 descr_a;
+static int ohci_hcd_ppc_soc_drv_suspend(struct of_device *op,
+ pm_message_t state)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+#ifdef CONFIG_PPC_MPC52xx
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ descr_a = in_be32(&ohci->regs->roothub.a);
+ out_be32(&ohci->regs->roothub.a, (descr_a & ~0x200) | 0x100);
+#endif
+ return 0;
+}
+static int ohci_hcd_ppc_soc_drv_resume(struct of_device *op)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+#ifdef CONFIG_PPC_MPC52xx
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ out_be32(&ohci->regs->roothub.a, descr_a);
+#endif
+ return 0;
+}
+#endif
+
static struct of_platform_driver ohci_hcd_ppc_of_driver = {
.name = "ppc-of-ohci",
.match_table = ohci_hcd_ppc_of_match,
@@ -221,8 +247,8 @@ static struct of_platform_driver ohci_hc
.remove = ohci_hcd_ppc_of_remove,
.shutdown = ohci_hcd_ppc_of_shutdown,
#ifdef CONFIG_PM
- /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
- /*.resume = ohci_hcd_ppc_soc_drv_resume,*/
+ .suspend = ohci_hcd_ppc_soc_drv_suspend,
+ .resume = ohci_hcd_ppc_soc_drv_resume,
#endif
.driver = {
.name = "ppc-of-ohci",
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 5/7] mpc52xx suspend: deep-sleep
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (3 preceding siblings ...)
2007-03-01 7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
@ 2007-03-01 7:56 ` Domen Puncer
2007-03-01 7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
` (4 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:56 UTC (permalink / raw)
To: linuxppc-embedded
Implement deep-sleep on MPC52xx.
SDRAM is put into self-refresh with help of SRAM code
(alternatives would be code in FLASH, I-cache).
Interrupt code must also not be in SDRAM, so put it
in I-cache.
MPC52xx core is static, so contents will remain intact even
with clocks turned off.
There seems to be a race with decrementer interrupt (uncomment
#define TESTING, and execute `echo standby > /sys/power/state`
couple thousands of times to reproduce it). :-(
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/arch/powerpc/platforms/52xx/Makefile
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/Makefile
+++ grant.git/arch/powerpc/platforms/52xx/Makefile
@@ -10,3 +10,5 @@ endif
obj-$(CONFIG_PPC_EFIKA) += efika.o
obj-$(CONFIG_PPC_LITE5200) += lite5200.o
+
+obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c
@@ -0,0 +1,123 @@
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+#include "mpc52xx_pic.h"
+
+extern void mpc52xx_deep_sleep(void *, void *);
+
+static int mpc52xx_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int mpc52xx_pm_prepare(suspend_state_t state)
+{
+ return 0;
+}
+
+/* you will want to change this, to match your board gpios, rtc or whatever */
+static void mpc52xx_set_wakeup_mode(void)
+{
+ struct mpc52xx_gpio_wkup __iomem *gpiow;
+ struct mpc52xx_intr __iomem *intr;
+ int pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */
+ u16 tmp;
+
+ gpiow = mpc52xx_find_and_map("mpc5200-gpio-wkup");
+ intr = mpc52xx_find_and_map("mpc5200-pic");
+ if (!gpiow || !intr) {
+ printk(KERN_ERR "%s: couldn't map io space\n", __func__);
+ goto out;
+ }
+
+ /* enable gpio */
+ out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin));
+ /* set as input */
+ out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin));
+ /* enable deep sleep interrupt */
+ out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin));
+ /* low level creates wakeup interrupt */
+ tmp = in_be16(&gpiow->wkup_itype);
+ tmp &= 2 << (pin * 2);
+ tmp |= 2 << (pin * 2);
+ out_be16(&gpiow->wkup_itype, tmp);
+ /* master enable */
+ out_8(&gpiow->wkup_maste, 1);
+
+ /* enable wakeup gpio interrupt in PIC */
+ out_be32(&intr->main_mask, in_be32(&intr->main_mask) & ~(1 << 8));
+ out:
+ iounmap(gpiow);
+ iounmap(intr);
+}
+
+int mpc52xx_pm_enter(suspend_state_t state)
+{
+ int err = 0;
+ void __iomem *mbar;
+ struct mpc52xx_cdm __iomem *cdm;
+ u32 clk_enables;
+
+ if (state != PM_SUSPEND_STANDBY)
+ return 0;
+
+ mpc52xx_set_wakeup_mode();
+
+ /* is there a nicer way? */
+ mbar = ioremap_nocache(0xf0000000, 0x8000);
+ cdm = mpc52xx_find_and_map("mpc5200-cdm");
+ if (!mbar || !cdm) {
+ printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+ err = -ENOSYS;
+ goto out;
+ }
+
+ mpc52xx_sdma_suspend();
+
+ out_8(&cdm->ccs_sleep_enable, 1);
+ out_8(&cdm->osc_sleep_enable, 1);
+ out_8(&cdm->ccs_qreq_test, 1);
+
+ /* disable all but SDRAM, bestcomm (SRAM) and timer clocks */
+ clk_enables = in_be32(&cdm->clk_enables);
+ out_be32(&cdm->clk_enables, clk_enables & 0x00088002);
+
+ mpc52xx_deep_sleep(sdma.sram, mbar);
+
+ out_be32(&cdm->clk_enables, clk_enables);
+ out_8(&cdm->ccs_sleep_enable, 0);
+ out_8(&cdm->osc_sleep_enable, 0);
+
+ mpc52xx_sdma_resume();
+
+ iounmap(mbar);
+ out:
+ return err;
+}
+
+static int mpc52xx_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+static struct pm_ops mpc52xx_pm_ops = {
+ .valid = mpc52xx_pm_valid,
+ .prepare = mpc52xx_pm_prepare,
+ .enter = mpc52xx_pm_enter,
+ .finish = mpc52xx_pm_finish,
+};
+
+static int __init mpc52xx_pm_init(void)
+{
+ pm_set_ops(&mpc52xx_pm_ops);
+ return 0;
+}
+
+arch_initcall(mpc52xx_pm_init);
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S
@@ -0,0 +1,277 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+
+// Tck is cca. 2000 cpu cycles here
+#define TCK 2000
+
+#define TMR0_ENABLE 0x600
+#define TMR0_INPUT 0x604
+
+#define SDRAM_CTRL 0x104
+
+#define CDM_CE 0x214
+#define CDM_CCSCR 0x21c
+
+#define INTR_MAIN_MASK 0x514
+#define INTR_ENC_STAT 0x524
+
+
+//#define TESTING
+
+// mpc5200b puts sdram automatically in self-refresh, previous versions don't
+#define SELF_REFRESH
+
+ .globl mpc52xx_deep_sleep
+mpc52xx_deep_sleep:
+
+ mr r7, r3 // SRAM va
+ mr r8, r4 // MBAR va
+ mflr r9
+
+ // we don't want DEC expiring anytime soon, but not very late either
+ lis r4, 0x1
+ mtspr SPRN_DEC, r4
+
+
+ // setup power mode bits
+ mfmsr r11
+ mr r10, r11
+ oris r10, r10, 0x0004
+ xoris r10, r10, 0x0004 // POW = 0
+ sync; isync;
+ mtmsr r10
+ sync; isync;
+
+ mfspr r12, SPRN_HID0
+ mr r10, r12
+ oris r10, r10, 0x00f0
+ xoris r10, r10, 0x00d0 // disable all power modes but sleep
+ sync; isync;
+ mtspr SPRN_HID0, r10
+ sync; isync;
+
+ // copy code to sram
+ mr r4, r7
+ subi r4, r4, 4
+ li r3, (sram_code_end-sram_code)/4
+ mtctr r3
+ lis r3, (sram_code-4)@h
+ ori r3, r3, (sram_code-4)@l
+1:
+ lwzu r5, 4(r3)
+ stwu r5, 4(r4)
+ bdnz 1b
+
+
+ // save original irq handler, and write a new one
+ lis r3, (orig_0x500-4)@h
+ ori r3, r3, (orig_0x500-4)@l
+ li r4, (cached_code_end - cached_code)/4
+ mtctr r4
+ lis r4, CONFIG_KERNEL_START@h
+ ori r4, r4, 0x500
+ lis r10, (cached_code-4)@h
+ ori r10, r10, (cached_code-4)@l
+1:
+ lwz r5, 0(r4)
+ stwu r5, 4(r3)
+ lwzu r5, 4(r10)
+ stw r5, 0(r4)
+
+ dcbf 0, r4
+ icbi 0, r4
+ addi r4, r4, 4
+
+ bdnz- 1b
+
+
+ // enable tmr0 interrupt
+ lwz r4, INTR_MAIN_MASK(r8)
+ ori r4, r4, 0x0080
+ xori r4, r4, 0x0080
+ stw r4, INTR_MAIN_MASK(r8)
+ sync
+
+ li r5, 0 // flag that irq handler sets
+
+ // enable interrupts
+ mfmsr r3
+ ori r3, r3, 0x8000 // EE
+ mtmsr r3
+ sync; isync;
+
+ // trigger tmr interrupt to cache the code
+ lis r4, 0x100
+ ori r4, r4, 0x1
+ stw r4, TMR0_INPUT(r8)
+ sync
+ li r4, 0x1104
+ stw r4, TMR0_ENABLE(r8)
+ sync
+
+1:
+ cmpi cr0, r5, 1
+ bne cr0, 1b
+
+ // lock icache
+ mfspr r10, SPRN_HID0
+ ori r10, r10, 0x2000
+ sync; isync;
+ mtspr SPRN_HID0, r10
+ sync; isync;
+
+ // jump to sram
+ mtlr r7
+ blrl
+
+
+ // unlock icache
+ mfspr r10, SPRN_HID0
+ ori r10, r10, 0x2000
+ xori r10, r10, 0x2000
+ sync; isync;
+ mtspr SPRN_HID0, r10
+ sync; isync;
+
+
+ // restore former power mode (and re-disable interrupts)
+ mfmsr r10
+ oris r10, r10, 0x0004
+ xoris r10, r10, 0x0004 // POW = 0
+ sync; isync;
+ mtmsr r10
+ sync; isync;
+
+ mtspr SPRN_HID0, r12
+ sync; isync;
+
+ mtmsr r11
+ sync; isync;
+
+ // restore original irq handler
+ lis r3, (orig_0x500-4)@h
+ ori r3, r3, (orig_0x500-4)@l
+ li r4, (cached_code_end - cached_code)/4
+ mtctr r4
+ lis r4, CONFIG_KERNEL_START@h
+ ori r4, r4, 0x500
+1:
+ lwzu r5, 4(r3)
+ stw r5, 0(r4)
+
+ dcbf 0, r4
+ icbi 0, r4
+ addi r4, r4, 4
+
+ bdnz- 1b
+
+
+ mtlr r9
+ blr
+
+
+sram_code:
+ // self refresh
+#ifdef SELF_REFRESH
+ lwz r4, SDRAM_CTRL(r8)
+
+ oris r4, r4, 0x8000 //mode_en
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ ori r4, r4, 0x0002 // soft_pre
+ stw r4, SDRAM_CTRL(r8)
+ sync
+ xori r4, r4, 0x0002
+
+ xoris r4, r4, 0x8000 //mode_en
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ // delay one sdram cycle
+ li r5, TCK
+ mtctr r5
+1:
+ bdnz- 1b
+
+ oris r4, r4, 0x5000
+ xoris r4, r4, 0x4000 // ref_en !cke
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ // delay for 2 sdram cycles
+ li r4, 2*TCK
+ mtctr r4
+1:
+ bdnz- 1b
+
+ // disable clock
+ lwz r4, CDM_CE(r8)
+ ori r4, r4, 0x0008
+ xori r4, r4, 0x0008
+ stw r4, CDM_CE(r8)
+ sync
+#endif
+
+#ifndef TESTING
+ // put it to sleep
+ mfmsr r10
+ oris r10, r10, 0x0004 // POW = 1
+ sync; isync;
+ mtmsr r10
+ sync; isync;
+#endif
+
+#ifdef SELF_REFRESH
+ // enable clock
+ lwz r4, CDM_CE(r8)
+ ori r4, r4, 0x0008
+ stw r4, CDM_CE(r8)
+ sync
+
+ // get ram out of self-refresh
+ lwz r4, SDRAM_CTRL(r8)
+ oris r4, r4, 0x5000 // cke ref_en
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ li r4, 2*TCK
+ mtctr r4
+1:
+ bdnz- 1b
+#endif
+
+ blr
+sram_code_end:
+
+
+// ### interrupt handler for wakeup from deep-sleep ###
+cached_code:
+ // disable timer
+ mfspr r3, 311 // MBAR
+ addi r3, r3, TMR0_ENABLE
+ li r4, 0
+ stw r4, 0(r3)
+ sync
+ dcbf 0, r3
+
+ // acknowledge wakeup, so CCS releases power pown
+ mfspr r3, 311 // MBAR
+ addi r3, r3, INTR_ENC_STAT
+ lwz r4, 0(r3)
+ ori r4, r4, 0x0400
+ stw r4, 0(r3)
+ sync
+ dcbf 0, r3
+
+ // flag that we handled an interrupt
+ li r5, 1
+
+ rfi
+cached_code_end:
+
+
+orig_0x500:
+ .space (cached_code_end - cached_code)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 6/7] lite5200b suspend: PIC
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (4 preceding siblings ...)
2007-03-01 7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
@ 2007-03-01 7:57 ` Domen Puncer
2007-03-01 7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
` (3 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:57 UTC (permalink / raw)
To: linuxppc-embedded
Save and restore MPC52xx PIC registers.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pic.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -471,3 +471,45 @@ unsigned int mpc52xx_get_irq(void)
return irq_linear_revmap(mpc52xx_irqhost, irq);
}
+
+#ifdef CONFIG_PM
+/* save and restore registers for suspend to ram */
+static struct mpc52xx_intr saved_intr;
+void mpc52xx_pic_suspend(void)
+{
+ saved_intr.per_mask = in_be32(&intr->per_mask);
+ saved_intr.per_pri1 = in_be32(&intr->per_pri1);
+ saved_intr.per_pri2 = in_be32(&intr->per_pri2);
+ saved_intr.per_pri3 = in_be32(&intr->per_pri3);
+ saved_intr.ctrl = in_be32(&intr->ctrl);
+ saved_intr.main_mask = in_be32(&intr->main_mask);
+ saved_intr.main_pri1 = in_be32(&intr->main_pri1);
+ saved_intr.main_pri2 = in_be32(&intr->main_pri2);
+ saved_intr.reserved1 = in_be32(&intr->reserved1);
+ saved_intr.enc_status = in_be32(&intr->enc_status);
+ saved_intr.crit_status = in_be32(&intr->crit_status);
+ saved_intr.main_status = in_be32(&intr->main_status);
+ saved_intr.per_status = in_be32(&intr->per_status);
+ saved_intr.reserved2 = in_be32(&intr->reserved2);
+ saved_intr.per_error = in_be32(&intr->per_error);
+}
+
+void mpc52xx_pic_resume(void)
+{
+ out_be32(&intr->per_mask, saved_intr.per_mask);
+ out_be32(&intr->per_pri1, saved_intr.per_pri1);
+ out_be32(&intr->per_pri2, saved_intr.per_pri2);
+ out_be32(&intr->per_pri3, saved_intr.per_pri3);
+ out_be32(&intr->ctrl, saved_intr.ctrl);
+ out_be32(&intr->main_mask, saved_intr.main_mask);
+ out_be32(&intr->main_pri1, saved_intr.main_pri1);
+ out_be32(&intr->main_pri2, saved_intr.main_pri2);
+ out_be32(&intr->reserved1, saved_intr.reserved1);
+ out_be32(&intr->enc_status, saved_intr.enc_status);
+ out_be32(&intr->crit_status, saved_intr.crit_status);
+ out_be32(&intr->main_status, saved_intr.main_status);
+ out_be32(&intr->per_status, saved_intr.per_status);
+ out_be32(&intr->reserved2, saved_intr.reserved2);
+ out_be32(&intr->per_error, saved_intr.per_error);
+}
+#endif
^ permalink raw reply [flat|nested] 21+ messages in thread
* [u-boot patch] support lite5200b wakeup in u-boot
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (5 preceding siblings ...)
2007-03-01 7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
@ 2007-03-01 7:59 ` Domen Puncer
2007-03-01 8:49 ` Stefan Roese
2007-03-01 8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
` (2 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 7:59 UTC (permalink / raw)
To: linuxppc-embedded
U-Boot part of Lite5200b low power mode support.
Puts SDRAM out of self-refresh and transfers control to
address saved at physical 0x0
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
diff --git a/board/icecube/icecube.c b/board/icecube/icecube.c
index 9b222da..4b35776 100644
--- a/board/icecube/icecube.c
+++ b/board/icecube/icecube.c
@@ -42,6 +42,54 @@ # else
#include "mt48lc16m16a2-75.h"
# endif
#endif
+
+#ifdef CONFIG_LITE5200B
+/* u-boot part of low-power mode implementation */
+#define SAVED_ADDR (*(void **)0x00000000)
+#define PSC2_4 0x02
+
+void lite5200b_wakeup(void)
+{
+ unsigned char wakeup_pin;
+ void (*linux_wakeup)(void);
+
+ /* check PSC2_4, if it's down "QT" is signaling we have a wakeup
+ * from low power mode */
+ *(vu_char *)MPC5XXX_WU_GPIO_ENABLE = PSC2_4;
+ __asm__ volatile ("sync");
+
+ wakeup_pin = *(vu_char *)MPC5XXX_WU_GPIO_DATA_I;
+ if (wakeup_pin & PSC2_4)
+ return;
+
+ /* acknowledge to "QT"
+ * by holding pin at 1 for 10 uS */
+ *(vu_char *)MPC5XXX_WU_GPIO_DIR = PSC2_4;
+ __asm__ volatile ("sync");
+ *(vu_char *)MPC5XXX_WU_GPIO_DATA = PSC2_4;
+ __asm__ volatile ("sync");
+ udelay(10);
+
+ /* put ram out of self-refresh */
+ *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x80000000; // mode_en
+ __asm__ volatile ("sync");
+ *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x50000000; // cke ref_en
+ __asm__ volatile ("sync");
+ *(vu_long *)MPC5XXX_SDRAM_CTRL &= ~0x80000000; // !mode_en
+ __asm__ volatile ("sync");
+ udelay(10); /* wait a bit */
+
+ /* jump back to linux kernel code */
+ linux_wakeup = SAVED_ADDR;
+ printf("\n\nLooks like we just woke, transferring control to 0x%08lx\n",
+ linux_wakeup);
+ linux_wakeup();
+}
+#else
+#define lite5200b_wakeup
+#endif
+
+
#ifndef CFG_RAMBOOT
static void sdram_start (int hi_addr)
{
@@ -208,6 +256,8 @@ #endif /* CFG_RAMBOOT */
__asm__ volatile ("sync");
}
+ lite5200b_wakeup();
+
return dramsize + dramsize2;
}
diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h
index 1d20d1d..c7eb090 100644
--- a/include/mpc5xxx.h
+++ b/include/mpc5xxx.h
@@ -189,6 +189,7 @@ #define MPC5XXX_WU_GPIO_ENABLE (MPC5XXX
#define MPC5XXX_WU_GPIO_ODE (MPC5XXX_WU_GPIO + 0x0004)
#define MPC5XXX_WU_GPIO_DIR (MPC5XXX_WU_GPIO + 0x0008)
#define MPC5XXX_WU_GPIO_DATA (MPC5XXX_WU_GPIO + 0x000c)
+#define MPC5XXX_WU_GPIO_DATA_I (MPC5XXX_WU_GPIO + 0x0020)
/* PCI registers */
#define MPC5XXX_PCI_CMD (MPC5XXX_PCI + 0x04)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/7] lite5200b suspend: low-power mode
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (6 preceding siblings ...)
2007-03-01 7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
@ 2007-03-01 8:00 ` Domen Puncer
2007-03-02 18:57 ` Scott Wood
2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
9 siblings, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-01 8:00 UTC (permalink / raw)
To: linuxppc-embedded
Low-power mode implementation for Lite5200b.
A patch to U-Boot that wakes up SDRAM, and transfers control
to address saved at physical 0x0 is needed.
Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -0,0 +1,101 @@
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include "bestcomm.h"
+
+extern void lite5200_low_power(void *sram, void *mbar);
+extern int mpc52xx_pm_enter(suspend_state_t);
+extern void mpc52xx_pic_suspend(void);
+extern void mpc52xx_pic_resume(void);
+
+static int lite5200_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int lite5200_pm_prepare(suspend_state_t state)
+{
+ return 0;
+}
+
+static int lite5200_pm_enter(suspend_state_t state)
+{
+ int err = 0;
+ struct mpc52xx_gpio __iomem *gpio;
+ void __iomem *mbar;
+ u32 gpio_saved_pc;
+
+ /* deep sleep? let mpc52xx code handle that */
+ if (state == PM_SUSPEND_STANDBY)
+ return mpc52xx_pm_enter(state);
+
+ if (state != PM_SUSPEND_MEM)
+ return -ENOSYS;
+
+ /* Map zones */
+ gpio = mpc52xx_find_and_map("mpc5200-gpio");
+ if (!gpio) {
+ printk(KERN_ERR "%s:%i Error mapping io zones\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+ /* save ie. ethernet pins configuration */
+ gpio_saved_pc = in_be32(&gpio->port_config);
+
+ mpc52xx_sdma_suspend();
+ mpc52xx_pic_suspend();
+
+
+ mbar = ioremap_nocache(0xf0000000, 0x8000);
+ /* is there a nicer way? */
+ if (!mbar) {
+ printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+ err = -ENOSYS;
+ goto out_unmap;
+ }
+ lite5200_low_power(sdma.sram, mbar);
+ iounmap(mbar);
+
+
+ out_be32(&gpio->port_config, gpio_saved_pc);
+ iounmap(gpio);
+
+ mpc52xx_setup_cpu();
+
+ mpc52xx_pic_resume();
+ mpc52xx_sdma_resume();
+
+ return 0;
+
+ out_unmap:
+ iounmap(gpio);
+ return err;
+}
+
+static int lite5200_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+static struct pm_ops lite5200_pm_ops = {
+ .valid = lite5200_pm_valid,
+ .prepare = lite5200_pm_prepare,
+ .enter = lite5200_pm_enter,
+ .finish = lite5200_pm_finish,
+};
+
+static int __init lite5200_pm_init(void)
+{
+ pm_set_ops(&lite5200_pm_ops);
+ return 0;
+}
+
+arch_initcall(lite5200_pm_init);
Index: grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S
@@ -0,0 +1,419 @@
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+
+#define SDRAM_MODE 0x100
+#define SDRAM_CTRL 0x104
+#define SC_MODE_EN (1<<31)
+#define SC_CKE (1<<30)
+#define SC_REF_EN (1<<28)
+#define SC_SOFT_PRE (1<<1)
+
+#define GPIOW_GPIOE 0xc00
+#define GPIOW_ODE 0xc04
+#define GPIOW_DDR 0xc08
+#define GPIOW_DVO 0xc0c
+#define GPIOW_INTEN 0xc10
+
+#define CDM_CE 0x214
+#define CDM_SDRAM (1<<3)
+
+
+// about 2000 cpu cycles for one sdram cycle here
+// just increase, to be on the safe side?
+#define TCK 5000
+
+
+#define DONT_DEBUG 1
+
+// helpers... beware: r10 and r4 are overwritten
+#define SAVE_SPRN(reg, addr) \
+ mfspr r10, SPRN_##reg; \
+ stw r10, ((addr)*4)(r4);
+
+#define LOAD_SPRN(reg, addr) \
+ lwz r10, ((addr)*4)(r4); \
+ mtspr SPRN_##reg, r10; \
+ sync; \
+ isync;
+
+// XXX it uses cca. 10 mA less if registers are saved in .text. WTF
+// is this still true?
+// .data
+registers:
+ .space 0x5c*4
+// .text
+
+// ----------------------------------------------------------------------
+// low-power mode with help of M68HLC908QT1
+
+ .globl lite5200_low_power
+lite5200_low_power:
+
+ mr r7, r3 // save SRAM va
+ mr r8, r4 // save MBAR va
+
+ // setup wakeup address for u-boot at physical location 0x0
+ lis r3, CONFIG_KERNEL_START@h
+ lis r4, lite5200_wakeup@h
+ ori r4, r4, lite5200_wakeup@l
+ sub r4, r4, r3
+ stw r4, 0(r3)
+
+
+ // save stuff BDI overwrites
+ /* save 0xf0 (0xe0->0x100 gets overwritten when BDI connected;
+ * even when CONFIG_BDI* is disabled and MMU XLAT commented; heisenbug?))
+ * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,
+ * possibly because BDI sets SDRAM registers before wakeup code does */
+ lis r4, registers@h
+ ori r4, r4, registers@l
+ lwz r10, 0xf0(r3)
+ stw r10, (0x1d*4)(r4)
+
+ // save registers to r4 [destroys r10]
+ SAVE_SPRN(LR, 0x1c)
+ bl save_regs
+
+ // flush caches [destroys r3, r4]
+ bl flush_data_cache
+
+
+ // copy code to sram
+ mr r4, r7
+ li r3, (sram_code_end - sram_code)/4
+ mtctr r3
+ lis r3, sram_code@h
+ ori r3, r3, sram_code@l
+1:
+ lwz r5, 0(r3)
+ stw r5, 0(r4)
+ addi r3, r3, 4
+ addi r4, r4, 4
+ bdnz 1b
+
+ // disable I and D caches
+ mfspr r3, SPRN_HID0
+ ori r3, r3, HID0_ICE | HID0_DCE
+ xori r3, r3, HID0_ICE | HID0_DCE
+ sync; isync;
+ mtspr SPRN_HID0, r3
+ sync; isync;
+
+#if DONT_DEBUG
+ // jump to sram
+ mtlr r7
+ blrl
+ // doesn't return
+#else
+ // debugging
+ b lite5200_wakeup
+#endif
+
+
+sram_code:
+ // self refresh
+ lwz r4, SDRAM_CTRL(r8)
+
+ // send NOP (precharge)
+ oris r4, r4, SC_MODE_EN@h // mode_en
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ ori r4, r4, SC_SOFT_PRE // soft_pre
+ stw r4, SDRAM_CTRL(r8)
+ sync
+ xori r4, r4, SC_SOFT_PRE
+
+ xoris r4, r4, SC_MODE_EN@h // !mode_en
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ // delay for one sdram cycle (for NOP to finish)
+ li r5, TCK
+ mtctr r5
+1: bdnz- 1b
+
+ // mode_en must not be set when enabling self-refresh
+ // send AR with CKE low (self-refresh)
+ oris r4, r4, (SC_REF_EN | SC_CKE)@h
+ xoris r4, r4, (SC_CKE)@h // ref_en !cke
+ stw r4, SDRAM_CTRL(r8)
+ sync
+
+ // delay for two sdram cycles (after !CKE there should be two cycles)
+ li r5, 2*TCK
+ mtctr r5
+1: bdnz- 1b
+
+ // disable clock
+ lwz r4, CDM_CE(r8)
+ ori r4, r4, CDM_SDRAM
+ xori r4, r4, CDM_SDRAM
+ stw r4, CDM_CE(r8)
+ sync
+
+ // delay for two sdram cycles
+ li r5, 2*TCK
+ mtctr r5
+1: bdnz- 1b
+
+
+ // turn off with QT chip
+ li r4, 0x02
+ stb r4, GPIOW_GPIOE(r8) // enable gpio_wkup1
+ sync
+
+ stb r4, GPIOW_DVO(r8) // "output" high
+ sync
+ stb r4, GPIOW_DDR(r8) // output
+ sync
+ stb r4, GPIOW_DVO(r8) // output high
+ sync
+
+ // delay
+ // 2000 cycles is cca 12 uS, 10uS should be enough
+ li r4, 2000
+ mtctr r4
+1:
+ bdnz- 1b
+
+ // turn off
+ li r4, 0
+ stb r4, GPIOW_DVO(r8) // output low
+ sync
+
+ // wait until we're offline
+1:
+ b 1b
+sram_code_end:
+
+
+
+// uboot jumps here on resume
+lite5200_wakeup:
+ bl restore_regs
+
+
+ // HIDs, MSR
+ LOAD_SPRN(HID1, 0x19)
+ LOAD_SPRN(HID2, 0x1a)
+
+
+ // address translation is tricky (see turn_on_mmu)
+ mfmsr r10
+ ori r10, r10, MSR_DR | MSR_IR
+
+
+ mtspr SPRN_SRR1, r10
+ lis r10, mmu_on@h
+ ori r10, r10, mmu_on@l
+ mtspr SPRN_SRR0, r10
+ sync
+ rfi
+mmu_on:
+ // kernel offset (r4 is still set from restore_registers)
+ addis r4, r4, CONFIG_KERNEL_START@h
+
+
+ // restore MSR
+ lwz r10, (4*0x1b)(r4)
+ mtmsr r10
+ sync; isync;
+
+ // setup DEC somewhere in the 1/HZ range
+ // if you don't do this, timer interrupt will trigger a few
+ // seconds later, and that is not good.
+ lis r3, 0x10
+ mtdec r3
+
+ // invalidate caches
+ mfspr r10, SPRN_HID0
+ ori r5, r10, HID0_ICFI | HID0_DCI
+ mtspr SPRN_HID0, r5 // invalidate caches
+ sync; isync;
+ mtspr SPRN_HID0, r10
+ sync; isync;
+
+ // enable caches
+ lwz r10, (4*0x18)(r4)
+ mtspr SPRN_HID0, r10 // restore (enable caches, DPM)
+ // ^ this has to be after address translation set in MSR
+ sync
+ isync
+
+
+ // restore 0xf0 (BDI2000)
+ lis r3, CONFIG_KERNEL_START@h
+ lwz r10, (0x1d*4)(r4)
+ stw r10, 0xf0(r3)
+
+ LOAD_SPRN(LR, 0x1c)
+
+
+ blr
+
+
+// ----------------------------------------------------------------------
+// boring code: helpers
+
+// save registers
+#define SAVE_BAT(n, addr) \
+ SAVE_SPRN(DBAT##n##L, addr); \
+ SAVE_SPRN(DBAT##n##U, addr+1); \
+ SAVE_SPRN(IBAT##n##L, addr+2); \
+ SAVE_SPRN(IBAT##n##U, addr+3);
+
+#define SAVE_SR(n, addr) \
+ mfsr r10, n; \
+ stw r10, ((addr)*4)(r4);
+
+#define SAVE_4SR(n, addr) \
+ SAVE_SR(n, addr); \
+ SAVE_SR(n+1, addr+1); \
+ SAVE_SR(n+2, addr+2); \
+ SAVE_SR(n+3, addr+3);
+
+save_regs:
+ stw r0, 0(r4)
+ stw r1, 0x4(r4)
+ stw r2, 0x8(r4)
+ stmw r11, 0xc(r4) // 0xc -> 0x5f, (0x18*4-1)
+
+ SAVE_SPRN(HID0, 0x18)
+ SAVE_SPRN(HID1, 0x19)
+ SAVE_SPRN(HID2, 0x1a)
+ mfmsr r10
+ stw r10, (4*0x1b)(r4)
+ //SAVE_SPRN(LR, 0x1c) have to save it before the call
+ // 0x1d reserved by 0xf0
+ SAVE_SPRN(RPA, 0x1e)
+ SAVE_SPRN(SDR1, 0x1f)
+
+ // save MMU regs
+ SAVE_BAT(0, 0x20)
+ SAVE_BAT(1, 0x24)
+ SAVE_BAT(2, 0x28)
+ SAVE_BAT(3, 0x2c)
+ SAVE_BAT(4, 0x30)
+ SAVE_BAT(5, 0x34)
+ SAVE_BAT(6, 0x38)
+ SAVE_BAT(7, 0x3c)
+
+ SAVE_4SR(0, 0x40)
+ SAVE_4SR(4, 0x44)
+ SAVE_4SR(8, 0x48)
+ SAVE_4SR(12, 0x4c)
+
+ SAVE_SPRN(SPRG0, 0x50)
+ SAVE_SPRN(SPRG1, 0x51)
+ SAVE_SPRN(SPRG2, 0x52)
+ SAVE_SPRN(SPRG3, 0x53)
+ SAVE_SPRN(SPRG4, 0x54)
+ SAVE_SPRN(SPRG5, 0x55)
+ SAVE_SPRN(SPRG6, 0x56)
+ SAVE_SPRN(SPRG7, 0x57)
+
+ SAVE_SPRN(IABR, 0x58)
+ SAVE_SPRN(DABR, 0x59)
+ SAVE_SPRN(TBRL, 0x5a)
+ SAVE_SPRN(TBRU, 0x5b)
+
+ blr
+
+
+// restore registers
+#define LOAD_BAT(n, addr) \
+ LOAD_SPRN(DBAT##n##L, addr); \
+ LOAD_SPRN(DBAT##n##U, addr+1); \
+ LOAD_SPRN(IBAT##n##L, addr+2); \
+ LOAD_SPRN(IBAT##n##U, addr+3);
+
+#define LOAD_SR(n, addr) \
+ lwz r10, ((addr)*4)(r4); \
+ mtsr n, r10;
+
+#define LOAD_4SR(n, addr) \
+ LOAD_SR(n, addr); \
+ LOAD_SR(n+1, addr+1); \
+ LOAD_SR(n+2, addr+2); \
+ LOAD_SR(n+3, addr+3);
+
+restore_regs:
+ lis r4, registers@h
+ ori r4, r4, registers@l
+#ifdef DONT_DEBUG
+ subis r4, r4, CONFIG_KERNEL_START@h
+#endif
+
+ lwz r0, 0(r4)
+ lwz r1, 0x4(r4)
+ lwz r2, 0x8(r4)
+ lmw r11, 0xc(r4)
+
+ // these are a bit tricky
+ /*
+ 0x18 - HID0
+ 0x19 - HID1
+ 0x1a - HID2
+ 0x1b - MSR
+ 0x1c - LR
+ 0x1d - reserved by 0xf0 (BDI2000)
+ */
+ LOAD_SPRN(RPA, 0x1e);
+ LOAD_SPRN(SDR1, 0x1f);
+
+ // restore MMU regs
+ LOAD_BAT(0, 0x20)
+ LOAD_BAT(1, 0x24)
+ LOAD_BAT(2, 0x28)
+ LOAD_BAT(3, 0x2c)
+ LOAD_BAT(4, 0x30)
+ LOAD_BAT(5, 0x34)
+ LOAD_BAT(6, 0x38)
+ LOAD_BAT(7, 0x3c)
+
+ LOAD_4SR(0, 0x40)
+ LOAD_4SR(4, 0x44)
+ LOAD_4SR(8, 0x48)
+ LOAD_4SR(12, 0x4c)
+
+ // rest of regs
+ LOAD_SPRN(SPRG0, 0x50);
+ LOAD_SPRN(SPRG1, 0x51);
+ LOAD_SPRN(SPRG2, 0x52);
+ LOAD_SPRN(SPRG3, 0x53);
+ LOAD_SPRN(SPRG4, 0x54);
+ LOAD_SPRN(SPRG5, 0x55);
+ LOAD_SPRN(SPRG6, 0x56);
+ LOAD_SPRN(SPRG7, 0x57);
+
+ LOAD_SPRN(IABR, 0x58);
+ LOAD_SPRN(DABR, 0x59);
+ LOAD_SPRN(TBWL, 0x5a); // these two have separate R/W regs
+ LOAD_SPRN(TBWU, 0x5b);
+
+ blr
+
+
+
+// cache flushing code. copied from arch/ppc/boot/util.S
+#define NUM_CACHE_LINES (128*8)
+
+/*
+ * Flush data cache
+ * Do this by just reading lots of stuff into the cache.
+ */
+ .globl flush_data_cache
+flush_data_cache:
+ lis r3,CONFIG_KERNEL_START@h
+ ori r3,r3,CONFIG_KERNEL_START@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+1:
+ lwz r4,0(r3)
+ addi r3,r3,L1_CACHE_BYTES /* Next line, please */
+ bdnz 1b
+ blr
Index: grant.git/arch/powerpc/platforms/52xx/Makefile
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/Makefile
+++ grant.git/arch/powerpc/platforms/52xx/Makefile
@@ -12,3 +12,6 @@ obj-$(CONFIG_PPC_EFIKA) += efika-setup.
obj-$(CONFIG_PPC_LITE5200) += lite5200.o
obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o
+ifeq ($(CONFIG_PPC_LITE5200),y)
+ obj-$(CONFIG_PM) += lite5200_sleep.o lite5200_pm.o
+endif
Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_common.c
===================================================================
--- grant.git.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -76,7 +76,7 @@ mpc52xx_find_ipb_freq(struct device_node
EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
-void __init
+void
mpc52xx_setup_cpu(void)
{
struct mpc52xx_cdm __iomem *cdm;
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [u-boot patch] support lite5200b wakeup in u-boot
2007-03-01 7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
@ 2007-03-01 8:49 ` Stefan Roese
0 siblings, 0 replies; 21+ messages in thread
From: Stefan Roese @ 2007-03-01 8:49 UTC (permalink / raw)
To: linuxppc-embedded
On Thursday 01 March 2007 08:59, Domen Puncer wrote:
> U-Boot part of Lite5200b low power mode support.
> Puts SDRAM out of self-refresh and transfers control to
> address saved at physical 0x0
Please post this patch to the U-Boot mailing list.
Best regards,
Stefan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (7 preceding siblings ...)
2007-03-01 8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
@ 2007-03-01 14:25 ` Grant Likely
2007-03-01 14:51 ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
9 siblings, 1 reply; 21+ messages in thread
From: Grant Likely @ 2007-03-01 14:25 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded
On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> Hi!
>
> Patches are based on latest mainline git tree + fec patches:
> Fec_MPC5200_eth_driver.patch
> Copy_bestcomm_support_files_into_arch_powerpc.patch
> Make_FEC_work_on_the_lite5200.patch
>
---8<---snip--->8---
>
> I would appreaciate any comments, suggestions etc.
Cool, good work. I'll try to do a proper review today.
Note on the Bestcomm stuff; the patches that you've referenced above
will not be going into mainline. They will be replaced by a new set
of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
patches there will need some rework.
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply [flat|nested] 21+ messages in thread
* New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes)
2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
@ 2007-03-01 14:51 ` Bartlomiej Sieka
2007-03-02 7:31 ` Domen Puncer
0 siblings, 1 reply; 21+ messages in thread
From: Bartlomiej Sieka @ 2007-03-01 14:51 UTC (permalink / raw)
To: linuxppc-embedded
Grant Likely wrote:
> On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
>> Hi!
>>
>> Patches are based on latest mainline git tree + fec patches:
>> Fec_MPC5200_eth_driver.patch
>> Copy_bestcomm_support_files_into_arch_powerpc.patch
>> Make_FEC_work_on_the_lite5200.patch
>>
> ---8<---snip--->8---
>> I would appreaciate any comments, suggestions etc.
>
> Cool, good work. I'll try to do a proper review today.
>
> Note on the Bestcomm stuff; the patches that you've referenced above
> will not be going into mainline. They will be replaced by a new set
> of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
> patches there will need some rework.
Hello,
I am working on porting arch/powerpc Linux to a custom MPC5200B-based
board, and currently using your 52xx-dev branch. Is this new set of
bestcomm/FEC patches already in any of your publicly available branches,
or is it something completely fresh? I am seeing some networking
problems, and would be interested in giving new patches a try.
Regards,
Bartlomiej
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes)
2007-03-01 14:51 ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
@ 2007-03-02 7:31 ` Domen Puncer
0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-02 7:31 UTC (permalink / raw)
To: Bartlomiej Sieka; +Cc: linuxppc-embedded
On 01/03/07 15:51 +0100, Bartlomiej Sieka wrote:
> Grant Likely wrote:
> > On 3/1/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> >> Hi!
> >>
> >> Patches are based on latest mainline git tree + fec patches:
> >> Fec_MPC5200_eth_driver.patch
> >> Copy_bestcomm_support_files_into_arch_powerpc.patch
> >> Make_FEC_work_on_the_lite5200.patch
> >>
> > ---8<---snip--->8---
> >> I would appreaciate any comments, suggestions etc.
> >
> > Cool, good work. I'll try to do a proper review today.
> >
> > Note on the Bestcomm stuff; the patches that you've referenced above
> > will not be going into mainline. They will be replaced by a new set
> > of bestcomm/FEC patches, hopfully in the .22 timeframe, so your
> > patches there will need some rework.
>
> Hello,
>
> I am working on porting arch/powerpc Linux to a custom MPC5200B-based
> board, and currently using your 52xx-dev branch. Is this new set of
> bestcomm/FEC patches already in any of your publicly available branches,
> or is it something completely fresh? I am seeing some networking
> problems, and would be interested in giving new patches a try.
Patches I used were from Grant's 52xx-dev branch.
Domen
>
> Regards,
> Bartlomiej
>
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] lite5200b suspend: low-power mode
2007-03-01 8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
@ 2007-03-02 18:57 ` Scott Wood
2007-03-03 7:15 ` Domen Puncer
0 siblings, 1 reply; 21+ messages in thread
From: Scott Wood @ 2007-03-02 18:57 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded
On Thu, Mar 01, 2007 at 09:00:08AM +0100, Domen Puncer wrote:
> +static int lite5200_pm_enter(suspend_state_t state)
> +{
[snip]
> + mbar = ioremap_nocache(0xf0000000, 0x8000);
You can't do ioremap with interrupts disabled (it will fail with spinlock
debugging enabled); the mapping should be set up at boot time.
-Scott
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
` (8 preceding siblings ...)
2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
@ 2007-03-02 21:35 ` Sylvain Munaut
2007-03-03 7:33 ` Domen Puncer
9 siblings, 1 reply; 21+ messages in thread
From: Sylvain Munaut @ 2007-03-02 21:35 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded
Hi,
Thanks for providing theses.
I hadn't a chance to test them yet, I'll try that this week end. A
couple of comments already though :
- Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
those when at sleep ?
- And if it is, won't a memcpy_io of the whole zone do the trick ?
- On a more general note, there seem to be a lot of stuff decided by
#ifdef ... that's not really good as we can build a single kernel that
could run on several platform so those need to somehow be enable
disabled dynamically.
- I may miss something but turning port power off for USB seem like a
sane thing to do for every one. Isn't that implemented somehow for all
controller somewhere ?
Sylvain
Domen Puncer wrote:
> Hi!
>
> Patches are based on latest mainline git tree + fec patches:
> Fec_MPC5200_eth_driver.patch
> Copy_bestcomm_support_files_into_arch_powerpc.patch
> Make_FEC_work_on_the_lite5200.patch
>
>
> This patchset includes the following patches:
> - [PATCH 1/7] mpc52xx suspend: bestcomm
> - [PATCH 2/7] mpc52xx suspend: UART
> - [PATCH 3/7] mpc52xx suspend: FEC (ethernet)
> - [PATCH 4/7] mpc52xx suspend: USB
> - [PATCH 5/7] mpc52xx suspend: deep-sleep
> - [PATCH 6/7] lite5200b suspend: PIC
> - [u-boot patch] support lite5200b wakeup in u-boot
> - [PATCH 7/7] lite5200b suspend: low-power mode
>
>
> I would appreaciate any comments, suggestions etc.
>
>
> Domen
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/7] lite5200b suspend: low-power mode
2007-03-02 18:57 ` Scott Wood
@ 2007-03-03 7:15 ` Domen Puncer
0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-03 7:15 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-embedded
On 02/03/07 12:57 -0600, Scott Wood wrote:
> On Thu, Mar 01, 2007 at 09:00:08AM +0100, Domen Puncer wrote:
> > +static int lite5200_pm_enter(suspend_state_t state)
> > +{
> [snip]
> > + mbar = ioremap_nocache(0xf0000000, 0x8000);
>
> You can't do ioremap with interrupts disabled (it will fail with spinlock
> debugging enabled); the mapping should be set up at boot time.
>From what I see, it could also be set up in prepare(), no?
I'll try that with spinlock debugging on monday.
Thanks!
Domen
>
> -Scott
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
@ 2007-03-03 7:33 ` Domen Puncer
2007-03-03 19:58 ` Endianness versus too many byte swaps?? Charles Krinke
2007-03-05 10:53 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
0 siblings, 2 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-03 7:33 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: linuxppc-embedded
On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
> Hi,
>
> Thanks for providing theses.
> I hadn't a chance to test them yet, I'll try that this week end. A
> couple of comments already though :
>
> - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
> those when at sleep ?
For deep-sleep this is true, but not for low-power mode (the CPU
isn't even powered in that case).
> - And if it is, won't a memcpy_io of the whole zone do the trick ?
Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
> - On a more general note, there seem to be a lot of stuff decided by
> #ifdef ... that's not really good as we can build a single kernel that
> could run on several platform so those need to somehow be enable
> disabled dynamically.
CONFIG_PM - well... it doesn't make sense too keep the code if
power management is disabled.
SELF_REFRESH, TESTING - both are provided for debugging, final
version is former on, latter off.
> - I may miss something but turning port power off for USB seem like a
> sane thing to do for every one. Isn't that implemented somehow for all
> controller somewhere ?
The "USB power led" on lite5200b says it isn't.
Thanks!
Domen
^ permalink raw reply [flat|nested] 21+ messages in thread
* Endianness versus too many byte swaps??
2007-03-03 7:33 ` Domen Puncer
@ 2007-03-03 19:58 ` Charles Krinke
2007-03-05 10:53 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
1 sibling, 0 replies; 21+ messages in thread
From: Charles Krinke @ 2007-03-03 19:58 UTC (permalink / raw)
To: linuxppc-embedded
This is probably a Timur question, but any enlightment is appreciated. =
This concerns Linux-2.6.17.11 from kernel.org with some modifications =
for our custom 8541 board. The original BSP was evolved from =
mpc85xx_cds.
=20
Down in the guts of arch/ppc/syslib/ppc85xx_seteup.c is a routine called =
mpc85xx_setup_pci1(). In this routine we do an assignment of some =
outbound window registers and I am most interested in POTAR2, POWAR2 & =
POWBAR2 right now.
=20
This routine uses a ccsr_pci struct to assign potar2, powar2, powbar2 =
and others like this:
=20
pci->potar2 =3D 0x00100000;
pci->powar2 =3D 0x8004401a;
pci->powbar2 =3D 0x00888000;
=20
Where I have changed the constants for our board. The issue is that when =
I call readl to read back these same registers at the end of this same =
subroutine, I get into endianess issues. That is, I read back
=20
POTAR2 =3D=3D 0x00001000
POWAR2 =3D=3D 0x1A400480
POWBAR2 =3D=3D 0x00800800
=20
Where the four bytes in each 32bit word are now exchanged so that =
80_04_40_1A became 1A_40_04_80.
=20
I understand big versus little endian, that isn't the question. The =
question is "What is really in the POTAR2, POWAR2 & POWBAR2 registers =
and how can I prove that what is in the registers is really what I wish =
to be in the registers?"
=20
It may be that one or more endian swap things are going on within Linux =
and I have inherited some source from others, so actually proving what =
is in the registers is becoming important.
=20
Charles
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-03 7:33 ` Domen Puncer
2007-03-03 19:58 ` Endianness versus too many byte swaps?? Charles Krinke
@ 2007-03-05 10:53 ` Domen Puncer
2007-03-05 10:58 ` Sylvain Munaut
1 sibling, 1 reply; 21+ messages in thread
From: Domen Puncer @ 2007-03-05 10:53 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: linuxppc-embedded
On 03/03/07 08:33 +0100, Domen Puncer wrote:
> On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
> > Hi,
> >
> > Thanks for providing theses.
> > I hadn't a chance to test them yet, I'll try that this week end. A
> > couple of comments already though :
> >
> > - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
> > those when at sleep ?
>
> For deep-sleep this is true, but not for low-power mode (the CPU
> isn't even powered in that case).
>
> > - And if it is, won't a memcpy_io of the whole zone do the trick ?
>
> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
OK, one can't copy the whole zone :-(
Ie. reading from MBAR+0x3B00 seems to freeze Linux.
Currently I'm having something like (obsoletes PIC and SDMA patches):
Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
===================================================================
--- /dev/null
+++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
@@ -0,0 +1,125 @@
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+#include "mpc52xx_pic.h"
+#include "bestcomm.h"
+
+extern void lite5200_low_power(void *sram, void *mbar);
+extern int mpc52xx_pm_enter(suspend_state_t);
+extern int mpc52xx_pm_prepare(suspend_state_t);
+
+static void __iomem *mbar;
+
+static int lite5200_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int lite5200_pm_prepare(suspend_state_t state)
+{
+ /* deep sleep? let mpc52xx code handle that */
+ if (state == PM_SUSPEND_STANDBY)
+ return mpc52xx_pm_prepare(state);
+
+ if (state != PM_SUSPEND_MEM)
+ return -EINVAL;
+
+ /* map registers */
+ mbar = ioremap_nocache(0xf0000000, 0x8000);
+ if (!mbar) {
+ printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+/* save and restore registers not bound to any real devices */
+static struct mpc52xx_cdm __iomem *cdm;
+static struct mpc52xx_cdm scdm;
+static struct mpc52xx_intr __iomem *pic;
+static struct mpc52xx_intr spic;
+static struct mpc52xx_sdma __iomem *bes;
+static struct mpc52xx_sdma sbes;
+static struct mpc52xx_xlb __iomem *xlb;
+static struct mpc52xx_xlb sxlb;
+static struct mpc52xx_gpio __iomem *gps;
+static struct mpc52xx_gpio sgps;
+static struct mpc52xx_gpio_wkup __iomem *gpw;
+static struct mpc52xx_gpio_wkup sgpw;
+extern char saved_sram[0x4000];
+
+static void lite5200_save_regs(void)
+{
+ _memcpy_fromio(&sbes, bes, sizeof(*bes));
+ _memcpy_fromio(&spic, pic, sizeof(*pic));
+ _memcpy_fromio(&scdm, cdm, sizeof(*cdm));
+ _memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
+ _memcpy_fromio(&sgps, gps, sizeof(*gps));
+ _memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
+
+ memcpy(saved_sram, sdma.sram, sdma.sram_size);
+}
+
+static void lite5200_restore_regs(void)
+{
+ memcpy(sdma.sram, saved_sram, sdma.sram_size);
+
+ _memcpy_toio(gpw, &sgpw, sizeof(*gpw));
+ _memcpy_toio(gps, &sgps, sizeof(*gps));
+ _memcpy_toio(xlb, &sxlb, sizeof(*xlb));
+ _memcpy_toio(cdm, &scdm, sizeof(*cdm));
+ _memcpy_toio(pic, &spic, sizeof(*pic));
+ _memcpy_toio(bes, &sbes, sizeof(*bes));
+}
+
+static int lite5200_pm_enter(suspend_state_t state)
+{
+ /* deep sleep? let mpc52xx code handle that */
+ if (state == PM_SUSPEND_STANDBY) {
+ return mpc52xx_pm_enter(state);
+ }
+
+ cdm = mbar + 0x200;
+ pic = mbar + 0x500;
+ gps = mbar + 0xb00;
+ gpw = mbar + 0xc00;
+ bes = mbar + 0x1200;
+ xlb = mbar + 0x1f00;
+ lite5200_save_regs();
+
+ lite5200_low_power(sdma.sram, mbar);
+
+ lite5200_restore_regs();
+
+ iounmap(mbar);
+ return 0;
+}
+
+static int lite5200_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+static struct pm_ops lite5200_pm_ops = {
+ .valid = lite5200_pm_valid,
+ .prepare = lite5200_pm_prepare,
+ .enter = lite5200_pm_enter,
+ .finish = lite5200_pm_finish,
+};
+
+static int __init lite5200_pm_init(void)
+{
+ pm_set_ops(&lite5200_pm_ops);
+ return 0;
+}
+
+arch_initcall(lite5200_pm_init);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-05 10:53 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
@ 2007-03-05 10:58 ` Sylvain Munaut
2007-03-05 20:21 ` Domen Puncer
0 siblings, 1 reply; 21+ messages in thread
From: Sylvain Munaut @ 2007-03-05 10:58 UTC (permalink / raw)
To: Domen Puncer; +Cc: linuxppc-embedded
Domen Puncer wrote:
> On 03/03/07 08:33 +0100, Domen Puncer wrote:
>
>> On 02/03/07 22:35 +0100, Sylvain Munaut wrote:
>>
>>> Hi,
>>>
>>> Thanks for providing theses.
>>> I hadn't a chance to test them yet, I'll try that this week end. A
>>> couple of comments already though :
>>>
>>> - Is saving the SDMA / PIC registers necessary ? Doesn't the cpu keep
>>> those when at sleep ?
>>>
>> For deep-sleep this is true, but not for low-power mode (the CPU
>> isn't even powered in that case).
>>
>>
>>> - And if it is, won't a memcpy_io of the whole zone do the trick ?
>>>
>> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
>>
>
> OK, one can't copy the whole zone :-(
> Ie. reading from MBAR+0x3B00 seems to freeze Linux.
>
> Currently I'm having something like (obsoletes PIC and SDMA patches):
>
And does that work ?
I was also wondering if some registers don't need to be restored last.
For example,
the task status in sdma would be restored to 0 then just at the end set
to their "real value".
Saving / Restoring all theses system zones makes more sense to me than
to just save / restore the pic & sdma and hoping than mpc52xx_setup_cpu
will make the rest ...
But saving/restoring all the mbar isn't good either because peripheral
drivers should handle their own setup restore. The suspend / resume
method of the peripheral should differentiate how deep their suspending
/ resuming and do what's necessary accordingly.
Sylvain
>
> Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
> ===================================================================
> --- /dev/null
> +++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c
> @@ -0,0 +1,125 @@
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/pm.h>
> +#include <asm/io.h>
> +#include <asm/mpc52xx.h>
> +#include "mpc52xx_pic.h"
> +#include "bestcomm.h"
> +
> +extern void lite5200_low_power(void *sram, void *mbar);
> +extern int mpc52xx_pm_enter(suspend_state_t);
> +extern int mpc52xx_pm_prepare(suspend_state_t);
> +
> +static void __iomem *mbar;
> +
> +static int lite5200_pm_valid(suspend_state_t state)
> +{
> + switch (state) {
> + case PM_SUSPEND_STANDBY:
> + case PM_SUSPEND_MEM:
> + return 1;
> + default:
> + return 0;
> + }
> +}
> +
> +static int lite5200_pm_prepare(suspend_state_t state)
> +{
> + /* deep sleep? let mpc52xx code handle that */
> + if (state == PM_SUSPEND_STANDBY)
> + return mpc52xx_pm_prepare(state);
> +
> + if (state != PM_SUSPEND_MEM)
> + return -EINVAL;
> +
> + /* map registers */
> + mbar = ioremap_nocache(0xf0000000, 0x8000);
> + if (!mbar) {
> + printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
> + return -ENOSYS;
> + }
> +
> + return 0;
> +}
> +
> +/* save and restore registers not bound to any real devices */
> +static struct mpc52xx_cdm __iomem *cdm;
> +static struct mpc52xx_cdm scdm;
> +static struct mpc52xx_intr __iomem *pic;
> +static struct mpc52xx_intr spic;
> +static struct mpc52xx_sdma __iomem *bes;
> +static struct mpc52xx_sdma sbes;
> +static struct mpc52xx_xlb __iomem *xlb;
> +static struct mpc52xx_xlb sxlb;
> +static struct mpc52xx_gpio __iomem *gps;
> +static struct mpc52xx_gpio sgps;
> +static struct mpc52xx_gpio_wkup __iomem *gpw;
> +static struct mpc52xx_gpio_wkup sgpw;
> +extern char saved_sram[0x4000];
> +
> +static void lite5200_save_regs(void)
> +{
> + _memcpy_fromio(&sbes, bes, sizeof(*bes));
> + _memcpy_fromio(&spic, pic, sizeof(*pic));
> + _memcpy_fromio(&scdm, cdm, sizeof(*cdm));
> + _memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
> + _memcpy_fromio(&sgps, gps, sizeof(*gps));
> + _memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
> +
> + memcpy(saved_sram, sdma.sram, sdma.sram_size);
> +}
> +
> +static void lite5200_restore_regs(void)
> +{
> + memcpy(sdma.sram, saved_sram, sdma.sram_size);
> +
> + _memcpy_toio(gpw, &sgpw, sizeof(*gpw));
> + _memcpy_toio(gps, &sgps, sizeof(*gps));
> + _memcpy_toio(xlb, &sxlb, sizeof(*xlb));
> + _memcpy_toio(cdm, &scdm, sizeof(*cdm));
> + _memcpy_toio(pic, &spic, sizeof(*pic));
> + _memcpy_toio(bes, &sbes, sizeof(*bes));
> +}
> +
> +static int lite5200_pm_enter(suspend_state_t state)
> +{
> + /* deep sleep? let mpc52xx code handle that */
> + if (state == PM_SUSPEND_STANDBY) {
> + return mpc52xx_pm_enter(state);
> + }
> +
> + cdm = mbar + 0x200;
> + pic = mbar + 0x500;
> + gps = mbar + 0xb00;
> + gpw = mbar + 0xc00;
> + bes = mbar + 0x1200;
> + xlb = mbar + 0x1f00;
> + lite5200_save_regs();
> +
> + lite5200_low_power(sdma.sram, mbar);
> +
> + lite5200_restore_regs();
> +
> + iounmap(mbar);
> + return 0;
> +}
> +
> +static int lite5200_pm_finish(suspend_state_t state)
> +{
> + return 0;
> +}
> +
> +static struct pm_ops lite5200_pm_ops = {
> + .valid = lite5200_pm_valid,
> + .prepare = lite5200_pm_prepare,
> + .enter = lite5200_pm_enter,
> + .finish = lite5200_pm_finish,
> +};
> +
> +static int __init lite5200_pm_init(void)
> +{
> + pm_set_ops(&lite5200_pm_ops);
> + return 0;
> +}
> +
> +arch_initcall(lite5200_pm_init);
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes
2007-03-05 10:58 ` Sylvain Munaut
@ 2007-03-05 20:21 ` Domen Puncer
0 siblings, 0 replies; 21+ messages in thread
From: Domen Puncer @ 2007-03-05 20:21 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: linuxppc-embedded
On 05/03/07 11:58 +0100, Sylvain Munaut wrote:
> Domen Puncer wrote:
> >
> >>
> >>> - And if it is, won't a memcpy_io of the whole zone do the trick ?
> >>>
> >> Oh, nice. I wasn't aware of _memcpy_{to,from}io. I'll try it.
> >>
> >
> > OK, one can't copy the whole zone :-(
> > Ie. reading from MBAR+0x3B00 seems to freeze Linux.
> >
> > Currently I'm having something like (obsoletes PIC and SDMA patches):
> >
> And does that work ?
Yes, it does.
>
> I was also wondering if some registers don't need to be restored last.
> For example,
> the task status in sdma would be restored to 0 then just at the end set
> to their "real value".
I was wondering about that, but it seems to work as-is.
Any real test cases for which it would matter?
>
> Saving / Restoring all theses system zones makes more sense to me than
> to just save / restore the pic & sdma and hoping than mpc52xx_setup_cpu
> will make the rest ...
>
> But saving/restoring all the mbar isn't good either because peripheral
> drivers should handle their own setup restore. The suspend / resume
> method of the peripheral should differentiate how deep their suspending
> / resuming and do what's necessary accordingly.
I was aiming for that.
Domen
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2007-03-05 20:21 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-01 7:53 [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-01 7:54 ` [PATCH 1/7] mpc52xx suspend: bestcomm Domen Puncer
2007-03-01 7:55 ` [PATCH 2/7] mpc52xx suspend: UART Domen Puncer
2007-03-01 7:55 ` [PATCH 3/7] mpc52xx suspend: FEC (ethernet) Domen Puncer
2007-03-01 7:56 ` [PATCH 4/7] mpc52xx suspend: USB Domen Puncer
2007-03-01 7:56 ` [PATCH 5/7] mpc52xx suspend: deep-sleep Domen Puncer
2007-03-01 7:57 ` [PATCH 6/7] lite5200b suspend: PIC Domen Puncer
2007-03-01 7:59 ` [u-boot patch] support lite5200b wakeup in u-boot Domen Puncer
2007-03-01 8:49 ` Stefan Roese
2007-03-01 8:00 ` [PATCH 7/7] lite5200b suspend: low-power mode Domen Puncer
2007-03-02 18:57 ` Scott Wood
2007-03-03 7:15 ` Domen Puncer
2007-03-01 14:25 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Grant Likely
2007-03-01 14:51 ` New Bestcomm/FEC patches (was: Re: [PATCH 0/7] MPC5200 and Lite5200b low power modes) Bartlomiej Sieka
2007-03-02 7:31 ` Domen Puncer
2007-03-02 21:35 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Sylvain Munaut
2007-03-03 7:33 ` Domen Puncer
2007-03-03 19:58 ` Endianness versus too many byte swaps?? Charles Krinke
2007-03-05 10:53 ` [PATCH 0/7] MPC5200 and Lite5200b low power modes Domen Puncer
2007-03-05 10:58 ` Sylvain Munaut
2007-03-05 20:21 ` Domen Puncer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.