Re: [PATCH] powerpc: Update MPC5xxx and Xilinx Virtex maintainer entries
Grant Likely wrote: From: Grant Likely grant.lik...@secretlab.ca - Add git tree URLs - Drop Sylvain from the 5xxx maintainers list. He hasn't been active for a while now. Signed-off-by: Grant Likely grant.lik...@secretlab.ca Confirmed. --- MAINTAINERS |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index ef03abe..4a8d367 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3434,11 +3434,10 @@ L:linuxppc-dev@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED MPC5XXX -P: Sylvain Munaut -M: t...@246tnt.com P: Grant Likely M: grant.lik...@secretlab.ca L: linuxppc-dev@ozlabs.org +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC4XX @@ -3456,6 +3455,7 @@ P: Grant Likely M: grant.lik...@secretlab.ca W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex L: linuxppc-dev@ozlabs.org +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC8XX ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[Fwd: fix for drivers/serial/mpc52xx_uart.c]
Patch, obviously correct, sent to me personally instead of the list. Sylvain ---BeginMessage--- Here is a fix for the unterminated mpc52xx_uart_of_match array when CONFIG_PPC_MPC512x is not defined. Should be quite self explonary, but if not feel free to bug me about it. Patch applies against 2.6.25 and 2.6.25.1 at least. Patch can be credited to Harry Sintonen [EMAIL PROTECTED]. Regards, -- l=2001;main(i){float o,O,_,I,D;for(;O=I=l/571.-1.75,l;)for(putchar(--l%80? i:10),o=D=l%80*.05-2,i=31;_=O*O,O=2*o*O+I,o=o*o-_+D,o+_+_4+Di++87;);puts ( Harry 'Piru' Sintonen [EMAIL PROTECTED] http://www.iki.fi/sintonen;);}--- drivers/serial/mpc52xx_uart.c-orig 2008-05-05 22:50:56.0 +0300 +++ drivers/serial/mpc52xx_uart.c 2008-05-05 22:51:56.0 +0300 @@ -1220,10 +1220,10 @@ { .compatible = mpc5200-serial, .data = mpc52xx_psc_ops, }, #endif #ifdef CONFIG_PPC_MPC512x { .compatible = fsl,mpc5121-psc-uart, .data = mpc512x_psc_ops, }, - {}, #endif + {}, }; static int __devinit mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) ---End Message--- ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: BestComm/FEC Linux system crash
Hi I hereby take the liberty to contact you regarding an issue we experience with the MPC5200 BestComm/FEC in our system. I found that you are the writer of the drivers for these, so apparently with a lot of experience with these devices. I hope you can find the time and inspiration to look into our case. Well, feel free to CC me to bring my attention to it, but such question should still go to the list. It's been a while since I worked on the 5200 and some other people might have more recent expertise than I do. Plus, it's actually Domen Puncer who reworked a lot of the network driver code quite recently ... We are running a Lunix based system based on a MPC5200 Need more precision. - 5200 or 5200B ? - What kernel version (version ?, where did you get it ?, external patch applied ?) This process dies after several minutes due to a FEC RxFifo overflow interrupt. This interrupt now causes the FEC to be re-initialized, but for some reason the receiver channel still does not work properly, causing the RxFifo overflow to occur nearly immediately again, causing a subsequent FEC re-init again, again resulting in failing receiver channel, causing another RxFifo overflow interrupt etc etc etc.. Huh ... you transmit lots of data ... and it's the RX fifo that overlow ... In the FEC driver we stumbled upon the following code: static irqreturn_t fec_rx_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct fec_priv *priv = (struct fec_priv *)dev-priv; for (;;) { struct sk_buff *skb; struct sk_buff *rskb; struct bcom_fec_bd *bd; u32 status; if (!bcom_buffer_done(priv-rx_dmatsk)) break; [...snipped...] Now what we see is that the statement in the FEC interrupt handler if (!bcom_buffer_done(priv-rx_dmatsk)) break; is executed frequently. Can you explain why this statement is there? Well ... that test is inside an infinite loop ( for(;;) ... ), so yes, hopefully it will be 'break' at some point ... What we do here is that we try to process as much receive buffer as possible ... So we loop indefinitly until no more buffers are ready ... During debug, after receiving the first RxFifo overflow interrupt, we suspended all further FEC processing and dumped various system status, of which the BestComm receiver descriptors. Here we found that always all but one were initialized to 0x405f2, but the different one to 0x0840. Theses are Receive Buffer descriptor. So it the BCOM_BD_READY bit is _set_, that means, that they're _not_ done (i.e. they are ready for bestcomm to fill). If you check the definition of bcom_buffer_done, you'll see that we check if the bit is _cleared_ So the situation you are describing is essentially : - One of the buffer is filled with some received packet (length = 0x40) - All the other buffers are ready for bestcomm and they can contain at maximum 1522 bytes (0x5f2) There is nothing 'wrong' about this situation. This all directs us somewhat to the believe that the following is occurring: For some reason the BestComm gets confused during FEC reception causing a descriptor not to be handled properly, which causes its status never to be set to 'ready' (BCOM_BD_READY 0x4000ul). Eventually, because of all receiving traffic to be ceased, the RxFifo will overflow causing the described interrupt and following re-initialization actions. But the BestComm FEC receiver channel fails to re-initialize (or even does not get re-initialized at all) and/or the BestComm FEC receiver descriptor table does not get re-initialized, causing the 0x0840 status to remain in there. So either BestComm fails to work at all for the FEC Receiver channel and/or BestComm eventually stumbles upon the 'incorrect' descriptor causing the FEC receiver to stall again causing an RxFifo overflow again etc etc etc. Well, given you misunderstood the meaning of BCOM_BD_READY, this theory doesn't make much sense sorry ... The re-initialize process should work however ... there is a bug there. This all seems plausible for what we experience so far, but does get confirmed by any data we can find in datasheets and hard-/software descriptions. The FEC receiver has the highest priority within BestComm and thus should always get serviced. The thing we can not find however is what system impact the PCI DMA by the PLX9056 is causing on the BestComm performance. The only interference I see would be contention on the XLB bus ... Maybe you can try to play with the xlb priority and give a higher one to bestcomm or a lower one to the PCI. Look in the platform setup there is some code setting xlb priorities. And refer to the 'XLB arbiter' section of the manual for the registers to tweak. What kind of bandwidth are you using for RX/TX on ethernet and PCI ? Does your PCI card do _very_ long bursts without releasing the bus (locking the xlb for a long time), or _very_
Re: State of the MPC5200 PSC AC97 driver
Last year you have posted a MPC5200 PSC AC97 driver patch [PATCH 9/9] sound: Add support for Freescale MPC5200 AC97 interface. with the following comment: Not quite a clean driver, but it get things done (well, mostly). Only included to be able to test functionalityi/usage of the BestComm driver. Yes ... and it still applies. There are various FIXMEs and commented out code here and there. Could you elaborate a bit on the overall state of the driver's functionality, which areas need improvement and attention? It's a minimum boiler plate. I filled the function at the minimum to get some sound output and being able to hear music coming out of it :) I also completely skipped the 5200 (not B) support ... At first there was no DMA at all (full software copy). I added some simple DMA later just to prove it could work and how to use the API. I just wrote it to get some sound, prove the interface could work under linux and to show how to use DMA. I had hoped someone else would finish it ... (yeah, I know ... big mistake). Seems that you mainly tested BestComm with this driver, what was the overall BestComm performance, any issues here? Did you use any specific test setup involving some dedicated application, etc.? My test was listening to Gorrillaz Feel Good inc using mplayer ... Did anyone else tried it and/or has a updated version or can share experience? At the time several other people tried it and it worked ... unless you did lots of harddrive IO and then it crumbled ... Sylvain ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH 1/7] powerpc: exports rheap symbol to modules
Theses can be useful in modules too. So we export them. Signed-off-by: Sylvain Munaut [EMAIL PROTECTED] --- arch/powerpc/lib/rheap.c | 15 +++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index ada5b42..22c3b4f 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c @@ -15,6 +15,7 @@ #include linux/types.h #include linux/errno.h #include linux/kernel.h +#include linux/module.h #include linux/mm.h #include linux/err.h #include linux/slab.h @@ -275,6 +276,7 @@ rh_info_t *rh_create(unsigned int alignment) return info; } +EXPORT_SYMBOL_GPL(rh_create); /* * Destroy a dynamically created remote heap. Deallocate only if the areas @@ -288,6 +290,7 @@ void rh_destroy(rh_info_t * info) if ((info-flags RHIF_STATIC_INFO) == 0) kfree(info); } +EXPORT_SYMBOL_GPL(rh_destroy); /* * Initialize in place a remote heap info block. This is needed to support @@ -320,6 +323,7 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks, for (i = 0, blk = block; i max_blocks; i++, blk++) list_add(blk-list, info-empty_list); } +EXPORT_SYMBOL_GPL(rh_init); /* Attach a free memory region, coalesces regions if adjuscent */ int rh_attach_region(rh_info_t * info, unsigned long start, int size) @@ -360,6 +364,7 @@ int rh_attach_region(rh_info_t * info, unsigned long start, int size) return 0; } +EXPORT_SYMBOL_GPL(rh_attach_region); /* Detatch given address range, splits free block if needed. */ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) @@ -428,6 +433,7 @@ unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size) return s; } +EXPORT_SYMBOL_GPL(rh_detach_region); /* Allocate a block of memory at the specified alignment. The value returned * is an offset into the buffer initialized by rh_init(), or a negative number @@ -502,6 +508,7 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch return start; } +EXPORT_SYMBOL_GPL(rh_alloc_align); /* Allocate a block of memory at the default alignment. The value returned is * an offset into the buffer initialized by rh_init(), or a negative number if @@ -511,6 +518,7 @@ unsigned long rh_alloc(rh_info_t * info, int size, const char *owner) { return rh_alloc_align(info, size, info-alignment, owner); } +EXPORT_SYMBOL_GPL(rh_alloc); /* Allocate a block of memory at the given offset, rounded up to the default * alignment. The value returned is an offset into the buffer initialized by @@ -594,6 +602,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co return start; } +EXPORT_SYMBOL_GPL(rh_alloc_fixed); /* Deallocate the memory previously allocated by one of the rh_alloc functions. * The return value is the size of the deallocated block, or a negative number @@ -626,6 +635,7 @@ int rh_free(rh_info_t * info, unsigned long start) return size; } +EXPORT_SYMBOL_GPL(rh_free); int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) { @@ -663,6 +673,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats) return nr; } +EXPORT_SYMBOL_GPL(rh_get_stats); int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) { @@ -687,6 +698,7 @@ int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner) return size; } +EXPORT_SYMBOL_GPL(rh_set_owner); void rh_dump(rh_info_t * info) { @@ -722,6 +734,7 @@ void rh_dump(rh_info_t * info) st[i].size, st[i].owner != NULL ? st[i].owner : ); printk(KERN_INFO \n); } +EXPORT_SYMBOL_GPL(rh_dump); void rh_dump_blk(rh_info_t * info, rh_block_t * blk) { @@ -729,3 +742,5 @@ void rh_dump_blk(rh_info_t * info, rh_block_t * blk) blk @0x%p: 0x%lx-0x%lx (%u)\n, blk, blk-start, blk-start + blk-size, blk-size); } +EXPORT_SYMBOL_GPL(rh_dump_blk); + -- 1.5.3 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH 2/7] powerpc: Changes the config mechanism for rheap
Instead of having in the makefile all the option that requires rheap, we define a configuration symbol and when needed we make sure it's selected. Signed-off-by: Sylvain Munaut [EMAIL PROTECTED] --- arch/powerpc/Kconfig |2 ++ arch/powerpc/lib/Kconfig |3 +++ arch/powerpc/lib/Makefile |5 + arch/powerpc/platforms/Kconfig |2 ++ arch/powerpc/platforms/Kconfig.cputype |1 + 5 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 arch/powerpc/lib/Kconfig diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 00099ef..76063b9 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -634,6 +634,8 @@ source fs/Kconfig source arch/powerpc/sysdev/qe_lib/Kconfig +source arch/powerpc/lib/Kconfig + source lib/Kconfig menu Instrumentation Support diff --git a/arch/powerpc/lib/Kconfig b/arch/powerpc/lib/Kconfig new file mode 100644 index 000..f383ad4 --- /dev/null +++ b/arch/powerpc/lib/Kconfig @@ -0,0 +1,3 @@ +config PPC_LIB_RHEAP + bool + default n diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 0a486d4..f75c2a1 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -13,7 +13,6 @@ endif obj-$(CONFIG_PPC64)+= checksum_64.o copypage_64.o copyuser_64.o \ memcpy_64.o usercopy_64.o mem_64.o string.o -obj-$(CONFIG_QUICC_ENGINE) += rheap.o obj-$(CONFIG_XMON) += sstep.o obj-$(CONFIG_KPROBES) += sstep.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o @@ -22,6 +21,4 @@ ifeq ($(CONFIG_PPC64),y) obj-$(CONFIG_SMP) += locks.o endif -# Temporary hack until we have migrated to asm-powerpc -obj-$(CONFIG_8xx) += rheap.o -obj-$(CONFIG_CPM2) += rheap.o +obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 19d4628..9189ba5 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -257,6 +257,7 @@ config TAU_AVERAGE config QUICC_ENGINE bool + select PPC_LIB_RHEAP help The QUICC Engine (QE) is a new generation of communications coprocessors on Freescale embedded CPUs (akin to CPM in older chips). @@ -266,6 +267,7 @@ config QUICC_ENGINE config CPM2 bool default n + select PPC_LIB_RHEAP help The CPM2 (Communications Processor Module) is a coprocessor on embedded CPUs made by Freescale. Selecting this option means that diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index e4b2aee..29d8eff 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -36,6 +36,7 @@ config PPC_8xx bool Freescale 8xx select FSL_SOC select 8xx + select PPC_LIB_RHEAP config 40x bool AMCC 40x -- 1.5.3 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH 3/7] powerpc/ppc32: Update mpc52xx_psc structure with B revision changes
On the mpc5200b the ccr register is 32 bits wide while on the mpc5200 it's only 16 bits. It's up to the driver to use the correct format depending on the chip it's running on. The 5200b also offers some more registers status in AC97 mode. Again, if not running on a 5200b the driver should not use those. Signed-off-by: Sylvain Munaut [EMAIL PROTECTED] --- include/asm-ppc/mpc52xx_psc.h | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h index 9d850b2..c82b8d4 100644 --- a/include/asm-ppc/mpc52xx_psc.h +++ b/include/asm-ppc/mpc52xx_psc.h @@ -28,6 +28,10 @@ #define MPC52xx_PSC_MAXNUM 6 /* Programmable Serial Controller (PSC) status register bits */ +#define MPC52xx_PSC_SR_UNEX_RX 0x0001 +#define MPC52xx_PSC_SR_DATA_VAL0x0002 +#define MPC52xx_PSC_SR_DATA_OVR0x0004 +#define MPC52xx_PSC_SR_CMDSEND 0x0008 #define MPC52xx_PSC_SR_CDE 0x0080 #define MPC52xx_PSC_SR_RXRDY 0x0100 #define MPC52xx_PSC_SR_RXFULL 0x0200 @@ -132,8 +136,10 @@ struct mpc52xx_psc { u8 reserved5[3]; u8 ctlr; /* PSC + 0x1c */ u8 reserved6[3]; - u16 ccr;/* PSC + 0x20 */ - u8 reserved7[14]; + u32 ccr;/* PSC + 0x20 */ + u32 ac97_slots; /* PSC + 0x24 */ + u32 ac97_cmd; /* PSC + 0x28 */ + u32 ac97_data; /* PSC + 0x2c */ u8 ivr;/* PSC + 0x30 */ u8 reserved8[3]; u8 ip; /* PSC + 0x34 */ -- 1.5.3 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH 5/7] powerpc: BestComm ATA task support
This is the microcode for the ATA task and the associated support code. The microcode itself comes directly from the offical API (v2.2) Signed-off-by: Sylvain Munaut [EMAIL PROTECTED] --- arch/powerpc/sysdev/bestcomm/Kconfig |7 + arch/powerpc/sysdev/bestcomm/Makefile|2 + arch/powerpc/sysdev/bestcomm/ata.c | 154 ++ arch/powerpc/sysdev/bestcomm/ata.h | 37 ++ arch/powerpc/sysdev/bestcomm/bcom_ata_task.c | 67 +++ 5 files changed, 267 insertions(+), 0 deletions(-) create mode 100644 arch/powerpc/sysdev/bestcomm/ata.c create mode 100644 arch/powerpc/sysdev/bestcomm/ata.h create mode 100644 arch/powerpc/sysdev/bestcomm/bcom_ata_task.c diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig index 3366e24..9d087ce 100644 --- a/arch/powerpc/sysdev/bestcomm/Kconfig +++ b/arch/powerpc/sysdev/bestcomm/Kconfig @@ -16,3 +16,10 @@ config PPC_BESTCOMM If you want to use drivers that require DMA operations, answer Y or M. Otherwise say N. +config PPC_BESTCOMM_ATA + tristate Bestcomm ATA task support + depends on PPC_BESTCOMM + default n + help + This option enables the support for the ATA task. + diff --git a/arch/powerpc/sysdev/bestcomm/Makefile b/arch/powerpc/sysdev/bestcomm/Makefile index a24aa06..b7a6a40 100644 --- a/arch/powerpc/sysdev/bestcomm/Makefile +++ b/arch/powerpc/sysdev/bestcomm/Makefile @@ -3,6 +3,8 @@ # bestcomm-core-objs := bestcomm.o sram.o +bestcomm-ata-objs := ata.o bcom_ata_task.o obj-$(CONFIG_PPC_BESTCOMM) += bestcomm-core.o +obj-$(CONFIG_PPC_BESTCOMM_ATA) += bestcomm-ata.o diff --git a/arch/powerpc/sysdev/bestcomm/ata.c b/arch/powerpc/sysdev/bestcomm/ata.c new file mode 100644 index 000..4b213b1 --- /dev/null +++ b/arch/powerpc/sysdev/bestcomm/ata.c @@ -0,0 +1,154 @@ +/* + * Bestcomm ATA task driver + * + * + * Patterned after bestcomm/fec.c by Dale Farnsworth [EMAIL PROTECTED] + * 2003-2004 (c) MontaVista, Software, Inc. + * + * Copyright (C) 2006-2007 Sylvain Munaut [EMAIL PROTECTED] + * Copyright (C) 2006 Freescale - John Rigby + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed as is without any warranty of any + * kind, whether express or implied. + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/types.h +#include asm/io.h + +#include bestcomm.h +#include bestcomm_priv.h +#include ata.h + + +/* */ +/* Task image/var/inc */ +/* */ + +/* ata task image */ +extern u32 bcom_ata_task[]; + +/* ata task vars that need to be set before enabling the task */ +struct bcom_ata_var { + u32 enable; /* (u16*) address of task's control register */ + u32 bd_base;/* (struct bcom_bd*) beginning of ring buffer */ + u32 bd_last;/* (struct bcom_bd*) end of ring buffer */ + u32 bd_start; /* (struct bcom_bd*) current bd */ + u32 buffer_size;/* size of receive buffer */ +}; + +/* ata task incs that need to be set before enabling the task */ +struct bcom_ata_inc { + u16 pad0; + s16 incr_bytes; + u16 pad1; + s16 incr_dst; + u16 pad2; + s16 incr_src; +}; + + +/* */ +/* Task support code*/ +/* */ + +struct bcom_task * +bcom_ata_init(int queue_len, int maxbufsize) +{ + struct bcom_task *tsk; + struct bcom_ata_var *var; + struct bcom_ata_inc *inc; + + tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_ata_bd), 0); + if (!tsk) + return NULL; + + tsk-flags = BCOM_FLAGS_NONE; + + bcom_ata_reset_bd(tsk); + + var = (struct bcom_ata_var *) bcom_task_var(tsk-tasknum); + inc = (struct bcom_ata_inc *) bcom_task_inc(tsk-tasknum); + + if (bcom_load_image(tsk-tasknum, bcom_ata_task)) { + bcom_task_release(tsk); + return NULL; + } + + var-enable = bcom_eng-regs_base + + offsetof(struct mpc52xx_sdma, tcr[tsk-tasknum]); + var-bd_base= tsk-bd_pa; + var-bd_last= tsk-bd_pa + ((tsk-num_bd-1) * tsk-bd_size); + var-bd_start = tsk-bd_pa; + var-buffer_size = maxbufsize; + + /* Configure some stuff */ + bcom_set_task_pragma(tsk-tasknum, BCOM_ATA_PRAGMA); + bcom_set_task_auto_start(tsk-tasknum, tsk-tasknum); + + out_8(bcom_eng-regs-ipr[BCOM_INITIATOR_ATA_RX], BCOM_IPR_ATA_RX
[PATCH] powerpc: mpc5200 low power mode
From: Domen Puncer [EMAIL PROTECTED] Low-power mode implementation for Lite5200b. Some I/O registers are also saved here. A recent U-Boot that supports this (lite5200b_PM_config) is needed. Signed-off-by: Domen Puncer [EMAIL PROTECTED] Signed-off-by: Sylvain Munaut [EMAIL PROTECTED] --- Hi Paulus, Could you push this with you next merge ? It's the support for lite5200 low power mode, posted on -embedded a few days ago. Sylvain --- arch/powerpc/platforms/52xx/Makefile |3 + arch/powerpc/platforms/52xx/lite5200.c | 14 +- arch/powerpc/platforms/52xx/lite5200_pm.c| 213 + arch/powerpc/platforms/52xx/lite5200_sleep.S | 413 ++ include/asm-powerpc/mpc52xx.h| 10 + 5 files changed, 648 insertions(+), 5 deletions(-) create mode 100644 arch/powerpc/platforms/52xx/lite5200_pm.c create mode 100644 arch/powerpc/platforms/52xx/lite5200_sleep.S diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile index b91e39c..307dbc1 100644 --- a/arch/powerpc/platforms/52xx/Makefile +++ b/arch/powerpc/platforms/52xx/Makefile @@ -10,3 +10,6 @@ obj-$(CONFIG_PPC_EFIKA) += efika.o obj-$(CONFIG_PPC_LITE5200) += lite5200.o obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o +ifeq ($(CONFIG_PPC_LITE5200),y) + obj-$(CONFIG_PM)+= lite5200_sleep.o lite5200_pm.o +endif diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 5c46e89..16eb5ad 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -86,7 +86,6 @@ error: } #ifdef CONFIG_PM -static u32 descr_a; static void lite5200_suspend_prepare(void __iomem *mbar) { u8 pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ @@ -97,13 +96,18 @@ static void lite5200_suspend_prepare(void __iomem *mbar) * power down usb port * this needs to be called before of-ohci suspend code */ - descr_a = in_be32(mbar + 0x1048); - out_be32(mbar + 0x1048, (descr_a ~0x200) | 0x100); + + /* set ports to power switched and powered at the same time +* USB Rh descriptor A: NPS = 0, PSM = 0 */ + out_be32(mbar + 0x1048, in_be32(mbar + 0x1048) ~0x300); + /* USB Rh status: LPS = 1 - turn off power */ + out_be32(mbar + 0x1050, 0x0001); } static void lite5200_resume_finish(void __iomem *mbar) { - out_be32(mbar + 0x1048, descr_a); + /* USB Rh status: LPSC = 1 - turn on power */ + out_be32(mbar + 0x1050, 0x0001); } #endif @@ -132,7 +136,7 @@ static void __init lite5200_setup_arch(void) #ifdef CONFIG_PM mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare; mpc52xx_suspend.board_resume_finish = lite5200_resume_finish; - mpc52xx_pm_init(); + lite5200_pm_init(); #endif #ifdef CONFIG_PCI diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c new file mode 100644 index 000..f26afcd --- /dev/null +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -0,0 +1,213 @@ +#include linux/init.h +#include linux/pm.h +#include asm/io.h +#include asm/time.h +#include asm/mpc52xx.h +#include mpc52xx_pic.h + +/* defined in lite5200_sleep.S and only used here */ +extern void lite5200_low_power(void __iomem *sram, void __iomem *mbar); + +static struct mpc52xx_cdm __iomem *cdm; +static struct mpc52xx_intr __iomem *pic; +static struct mpc52xx_sdma __iomem *bes; +static struct mpc52xx_xlb __iomem *xlb; +static struct mpc52xx_gpio __iomem *gps; +static struct mpc52xx_gpio_wkup __iomem *gpw; +static void __iomem *sram; +static const int sram_size = 0x4000; /* 16 kBytes */ +static void __iomem *mbar; + +static int lite5200_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + default: + return 0; + } +} + +static int lite5200_pm_prepare(suspend_state_t state) +{ + /* deep sleep? let mpc52xx code handle that */ + if (state == PM_SUSPEND_STANDBY) + return mpc52xx_pm_prepare(state); + + if (state != PM_SUSPEND_MEM) + return -EINVAL; + + /* map registers */ + mbar = mpc52xx_find_and_map(mpc5200); + if (!mbar) { + printk(KERN_ERR %s:%i Error mapping registers\n, __func__, __LINE__); + return -ENOSYS; + } + + cdm = mbar + 0x200; + pic = mbar + 0x500; + gps = mbar + 0xb00; + gpw = mbar + 0xc00; + bes = mbar + 0x1200; + xlb = mbar + 0x1f00; + sram = mbar + 0x8000; + + return 0; +} + +/* save and restore registers not bound to any real devices */ +static struct mpc52xx_cdm scdm; +static struct mpc52xx_intr spic; +static struct mpc52xx_sdma sbes; +static struct mpc52xx_xlb sxlb; +static struct mpc52xx_gpio sgps; +static struct