Bruce_Leonard | 1 Mar 2007 02:35

Kernel support for the TI1520 PCI-CardBus bridge?

Hi all,

We're designing a new product and we want to put a CF card in it.  We're 
thinking the easiest way to do that is to put in a PCI-CF bridge and we 
would like to use the TI1520 because it's industrial rated which we need. 
We can get the parts but TI is refusing to give us any support because 
they're devoting 100% of their time to dealing with the Vista release. I'm 
curious if anyone has ever successfully gotten this part to work in linux. 
 I found it listed in pci_ids.h, but that doesn't mean it's actually 
used/working.  I'm not looking for a detailed explination right now, we're 
just trying to gage if this part would be a couple of weeks of work or a 
couple of months.  Thanks for any info.

See 'ya!

Bruce
Sendhilraj T | 1 Mar 2007 07:33
Favicon

mount time for JFFS and JFFS2 file systems


Hi all,

I wonder if any one could let me know the normal mount time for JFFS and JFFS2 fiel systems.
Which one takes more time to get mounted?
Why JFFS2 takes more time to mount ,eventhough it has Log Structured File system?

T.Senthil
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded <at> ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Mohammad Sadegh Sadri | 1 Mar 2007 07:29
Picon
Favicon

Re: Please help me with compiling the kernel for ML403


Glenn,

I studied your post carefuly,

You are using a patch: paulus, 
I looked at some parts of these patches, 
most of them are already applied to the kernel, 
Do I really need to apply these patches? 
Is this true for newer versions of the kernel , like 2.6.20? or the devel version from montavista
You have applied these patches to 2.6.14 , from kernel.org, Yes?

one of the persons here, told me that I'm mixing different methods for building the kernel,
I think that he may be true, Am I using a correct set of tools?

Thanks.

------------------------------------------------------------------------------------------------
Date: Wed, 28 Feb 2007 16:53:39 -0500
From: Glenn.G.Hart <at> us.westinghouse.com
Subject: Re: Please help me with compiling the kernel for ML403
To: linuxppc-embedded <at> ozlabs.org
Message-ID:
	
Content-Type: text/plain; charset="us-ascii"

 
Mohammad,

I didn't have much success copying the entire BSP into the kernel.  Please
see my post titled "Linux w/ML403 PLB TEMAC".  It is basically the tutorial
of how I got Linux working on an ML403 board.

Glenn

 

                                                                                                     
 (Embedded     Mohammad Sadegh Sadri  <at> ozlabs.org                              
 image moved   02/28/2007 04:21 PM                                                                   
 to file:                                                                                            
 pic26924.pcx)                                                                                       

                                                                                                     

 
Sent by:
       linuxppc-embedded-bounces+glenn.g.hart=us.westinghouse.com <at> ozlabs.org

 
To:    
cc:
Subject:    Please help me with compiling the kernel for ML403

Security Level:?              Internal

 

Hi

It is some thing more than 2 weeks that I'm trying to compile the kernel
for ML403.
Posted to questions here, but unfortunately, didn't get any answer from the
experts here.
I have tested every thing I knew ( with my limited knowledge ) and now, I
really need your help.

I'm using the following set of tools:
EDK 8.2.02,  ( Latest )
ELDK 4.1 ( Latest )

-I want to compile the 2.6.20 kernel, downloaded from kernel.org

-As the first step, in EDK, I choose linux 2.6 in software platform
generation settings,

-I generate the BSP.

-In the generated BSP , I convert all of the 40x strings to 403, also I
change the name of xparameters_ml40x to xparameters_ml403

-I copy the 2.6.20 kernel /eldk/ppc_4xx/usr/src/linux , and set all of the
needed env variables for cross compile, and set the needed changes in the
linux Makefile. ( ARCH and
CROSS_COMPILE )

-I copy the entire BSP into the root of the linux kernel.

-I edit the linux/arch/ppc/Kconfig file, and add these lines into it:
config XILINX_OCP
 bool "Xilinx OCP"
 default y

config XILINX_TEMAC
 bool "Xilinx TEMAC"
 default y

config XILINX_SYSACE
 bool "Xilinx System ACE"
 default y

config XILINX_EDK
 bool "Xilinx EDK Support"
 default y

-In the linux folder I execute the cow.tcl script provided with the BSP
from EDK ( I execute tclsh cow.tcl )

-I make a symbolic link , for config.h file, ( I go to linux/include/linux
and then ln -s autoconf.h config.h )

-I begin the menuconfig and set all of the needed parameters

-Now, I begin the make process by simply typing : make

- I encounter the following error:
arch/ppc/platforms/4xx/virtex.c:20: error: array type has incomplete
element type
arch/ppc/platforms/4xx/virtex.c:60: error: field name not in record or
union initializer
arch/ppc/platforms/4xx/virtex.c:60: error: (near initialization for
'core_ocp')
make[1]: *** [arch/ppc/platforms/4xx/virtex.o] Error 1
make: *** [arch/ppc/platforms/4xx] Error 2

- I can prevent this error by commenting these lines of
/arch/ppc/platforms/4xx/virtex.c file:
/* Have OCP take care of the serial ports. */
struct ocp_def core_ocp[] = {
#ifdef XPAR_UARTNS550_0_BASEADDR
 { .vendor  = OCP_VENDOR_XILINX,
   .function      = OCP_FUNC_16550,
   .index   = 0,
   .paddr   = XPAR_UARTNS550_0_BASEADDR,
   .irq           = XPAR_INTC_0_UARTNS550_0_VEC_ID,
   .pm            = OCP_CPM_NA
 },
#ifdef XPAR_UARTNS550_1_BASEADDR
 { .vendor  = OCP_VENDOR_XILINX,
   .function      = OCP_FUNC_16550,
   .index   = 1,
   .paddr   = XPAR_UARTNS550_1_BASEADDR,
   .irq           = XPAR_INTC_0_UARTNS550_1_VEC_ID,
   .pm            = OCP_CPM_NA
 },
#ifdef XPAR_UARTNS550_2_BASEADDR
 { .vendor  = OCP_VENDOR_XILINX,
   .function      = OCP_FUNC_16550,
   .index   = 2,
   .paddr   = XPAR_UARTNS550_2_BASEADDR,
   .irq           = XPAR_INTC_0_UARTNS550_2_VEC_ID,
   .pm            = OCP_CPM_NA
 },
#ifdef XPAR_UARTNS550_3_BASEADDR
 { .vendor  = OCP_VENDOR_XILINX,
   .function      = OCP_FUNC_16550,
   .index   = 3,
   .paddr   = XPAR_UARTNS550_3_BASEADDR,
   .irq           = XPAR_INTC_0_UARTNS550_3_VEC_ID,
   .pm            = OCP_CPM_NA
 },
#ifdef XPAR_UARTNS550_4_BASEADDR
#error Edit this file to add more devices.
#endif                  /* 4 */
#endif                  /* 3 */
#endif                  /* 2 */
#endif                  /* 1 */
#endif                  /* 0 */
 { .vendor  = OCP_VENDOR_INVALID
 }
};

- Instead of the ebove lines, I just put one simple line: ( I use uart lite
and not the 16550 so there should be no problem commenting these lines? )
struct ocp_def * core_ocp;

- now, I begin the make process again, The make process goes ahead but
  after a long time it generates another error:
  GEN     .version
  CHK     include/linux/compile.h
  UPD     include/linux/compile.h
  CC      init/version.o
  LD      init/built-in.o
  LD      .tmp_vmlinux1
arch/ppc/syslib/built-in.o: In function `ppc_sys_device_remove':
: undefined reference to `ppc_sys_platform_devices'
arch/ppc/syslib/built-in.o: In function `ppc_sys_device_remove':
: undefined reference to `ppc_sys_platform_devices'
arch/ppc/syslib/built-in.o: In function `ppc_sys_device_initfunc':
: undefined reference to `ppc_sys_platform_devices'
arch/ppc/syslib/built-in.o: In function `ppc_sys_device_initfunc':
: undefined reference to `ppc_sys_platform_devices'
arch/ppc/syslib/built-in.o: In function `ppc_sys_device_setfunc':
: undefined reference to `ppc_sys_platform_devices'
arch/ppc/syslib/built-in.o:: more undefined references to
`ppc_sys_platform_devices' follow
make: *** [.tmp_vmlinux1] Error 1

- If I do not add the BSP files from EDK to my kernel and compile the
kernel for ML403, every thing will be completely OK. ( But I want TEMAC )

- when I look in the original virtex.c file, I see that it has defined
ppc_sys_platform_devices but when I look at the virtex.c generated by
Xilinx, I see that it has a completely different structure, it has no
definition of this variable. It is completely different from the original
virtex.c

- I have tested the same things above, with different versions of 2.6
kernel, such as, 2.6.17.1 and 26-xilinx-devel ( which I download from
montavista using git near two weeks ago ) , I also changed the version of
eldk to 4.0 and to 3.5 ( with 3.5 I could not compile the kernel at all )

Any idea, Any suggestion and any thing which can help even a litte, is
welcome,
I really do not know what to do more.

Thanks.

_________________________________________________________________
Discover the new Windows Vista
http://search.msn.com/results.aspx?q=windows+vista&mkt=en-US&form=QBRE
Domen Puncer | 1 Mar 2007 08:53

[PATCH 0/7] MPC5200 and Lite5200b low power modes

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
Domen Puncer | 1 Mar 2007 08:54

[PATCH 1/7] mpc52xx suspend: bestcomm

Save and restore bestcomm registers and SRAM.

Signed-off-by: Domen Puncer <domen.puncer <at> 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
 <at>  <at>  -395,4 +395,75  <at>  <at>  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
 <at>  <at>  -473,6 +473,11  <at>  <at>  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__ */
Domen Puncer | 1 Mar 2007 08:55

[PATCH 2/7] mpc52xx suspend: UART

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 <at> 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
 <at>  <at>  -418,6 +418,22  <at>  <at>  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,
 <at>  <at>  -432,8 +448,10  <at>  <at>  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,
Domen Puncer | 1 Mar 2007 08:55

[PATCH 3/7] mpc52xx suspend: FEC (ethernet)

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 <at> 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
 <at>  <at>  -801,6 +801,58  <at>  <at>  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", },
 <at>  <at>  -815,8 +867,8  <at>  <at>  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
 <at>  <at>  -77,6 +77,7  <at>  <at>  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 */

 <at>  <at>  -527,6 +528,23  <at>  <at>  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
 <at>  <at>  -71,3 +71,8  <at>  <at>  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
Domen Puncer | 1 Mar 2007 08:56

[PATCH 4/7] mpc52xx suspend: USB

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

Signed-off-by: Domen Puncer <domen.puncer <at> 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
 <at>  <at>  -214,6 +214,32  <at>  <at>  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,
 <at>  <at>  -221,8 +247,8  <at>  <at>  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",
Domen Puncer | 1 Mar 2007 08:56

[PATCH 5/7] mpc52xx suspend: deep-sleep

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 <at> 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
 <at>  <at>  -10,3 +10,5  <at>  <at>  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
 <at>  <at>  -0,0 +1,123  <at>  <at> 
+#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
 <at>  <at>  -0,0 +1,277  <at>  <at> 
+#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) <at> h
+	ori	r3, r3, (sram_code-4) <at> 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) <at> h
+	ori	r3, r3, (orig_0x500-4) <at> l
+	li	r4, (cached_code_end - cached_code)/4
+	mtctr	r4
+	lis	r4, CONFIG_KERNEL_START <at> h
+	ori	r4, r4, 0x500
+	lis	r10, (cached_code-4) <at> h
+	ori	r10, r10, (cached_code-4) <at> 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) <at> h
+	ori	r3, r3, (orig_0x500-4) <at> l
+	li	r4, (cached_code_end - cached_code)/4
+	mtctr	r4
+	lis	r4, CONFIG_KERNEL_START <at> 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)
Domen Puncer | 1 Mar 2007 08:57

[PATCH 6/7] lite5200b suspend: PIC

Save and restore MPC52xx PIC registers.

Signed-off-by: Domen Puncer <domen.puncer <at> 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
 <at>  <at>  -471,3 +471,45  <at>  <at>  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

Gmane