LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc: Check rc of notifier chain for memory remove
From: Nathan Fontenot @ 2008-08-25 19:33 UTC (permalink / raw)
  To: linuxppc-dev

The return code from invocation of the notifier for
pSeries_reconfig_chain during update of the device tree is not 
checked.  This causes writes to /proc/ppc64/ofdt to update memory
properties (i.e. ibm,dyamic-reconfiguration-memory) to always 
return success, instead of the result of the notifier chain.

This happens specifically when we remove/add memory from the
device tree on machines using memory specified in the
ibm,dynamic-reconfiguration-memory property of the device tree.

Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---

Index: linux-2.6-paulus/arch/powerpc/platforms/pseries/reconfig.c
===================================================================
--- linux-2.6-paulus.orig/arch/powerpc/platforms/pseries/reconfig.c	2008-08-25 13:08:27.000000000 -0500
+++ linux-2.6-paulus/arch/powerpc/platforms/pseries/reconfig.c	2008-08-25 13:45:12.000000000 -0500
@@ -466,11 +466,11 @@
 		else
 			action = PSERIES_DRCONF_MEM_REMOVE;
 
-		blocking_notifier_call_chain(&pSeries_reconfig_chain,
-					     action, value);
+		rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+						  action, value);
 	}
 
-	return 0;
+	return rc;
 }
 
 /**

^ permalink raw reply

* Re: Why does one "stw" fail with address translation disabled in PPC405EP?
From: Zhou Rui @ 2008-08-25 19:16 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-dev
In-Reply-To: <20080824185547.94A0724899@gemini.denx.de>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 4697 bytes --]

Hi,
I think maybe you have known this project named XtratuM
(http://www.xtratum.org). I'm porting it from x86 to PPC405. The
implementation on PPC440 has been basically finished
(ftp://dslab.lzu.edu.cn/pub/xtratum/xtratum-ppc/snapshots/xtratum-ppc-20071205.tar.bz2) and I know there was discussion about it in this mail list before. XtratuM is an ADEOS based nano kernel. It aims for realtime and is designed to provide virtual timer, virtual interrupt and memory space sperations for domains. Each domain is loaded by a userspace program (instead of the root domain as a kernel module) and the loader will load the domain's (ELF staticly excutable) PT_LOAD section into memory, and then raise a properly system call (passing the structurized loaded data as arguments) to load the domain via load_domain_sys() of XtratuM, and at the last step of loading the domain, xtratum will jump to the entry code of the new domain(asm wrappered start() routine) and then everything should be fine. 0x100000a0 is the entry point of the test domain, and that is why I need to start execution from it.

I think I can say something of my analysis so far for the cause of my
problem. Thanks for the mention of memory size. Once the kernel module
of XtratuM is loaded, the symbols of it are placed to virtual addresses
like 0xc3xxxxxx. Because in normal state, address translation is enabled
(MSR[IR, DR] = [1, 1]), these addresses are okay. However, when loading
the domain, because the entry point 0x100000a0 is not in TLB and it
should be reloaded, Data TLB Miss Exception arises and DTLBMiss is
called. The exception clears MSR[IR, DR], so address translation is
disabled and physical address should be used at this moment. If we want
something at the virtual address of 0xc3xxxxxx, we must access the
physical addresses like 0x03xxxxxx. Nevertheless, the limitation of 32MB
memory makes the valid physical address range from 0x0 to 0x1ffffff.
Therefore, during the exception handling, the addresses out of range
should not be accessed, but the instructions cannot know the memory
limitation in advance and tries to do something in addresses such as
0x03072da0 based on the address translation mechanism, which leads to
machine check.
I haved tried to append "mem=32M" to kernel command line but no help. I
think it is because when loading the kernel in normal state, address
translation is enabled and the virtual addresses are okay. Kernel cannot
foresee that there is going to be a TLB miss exception and the illegal
physical addresses like 0x03xxxxxx may be accessed.

So any ideas for this problem are welcome.

Thank you very much for taking care.

Best Wishes

Zhou Rui
2008-08-25

在 2008-08-24日的 20:55 +0200,Wolfgang Denk写道:
> Dear Zhou Rui,
> 
> In message <1219479992.7565.17.camel@localhost> you wrote:
> >
> > > >    I am running a kernel module which will execute a user space
> > > >application. The entry point of the application is 0x100000a0. At the
> > > 
> > > That should be the first clue that you are doing it wrong.  Don't do
> > > stuff like that in modules...
> > 
> > Oh, but our project needs a function like that ...
> 
> You should really think about this. Why do you think you  need  this?
> What  exactly  are  you  trying  to  do?  [Probably  there are better
> approaches to solve your problem...]

> > It is physical address at this moment. Address translation is disabled
> > automatically (MSR[IR, DR] = [0, 0]) because of TLB Miss Exception and
> > Instrunction Storage Exception.
> 
> Hm.. are you absolutely sure that the 0x100000a0 mentioned above is a
> physical address?
> 
> > > Do you have enough DRAM to cover that?  Some of those boards only come
> > > with 32MiB of DRAM.
> > 
> > My board only has 32MB DRAM. Do you mean 32MB is not enough for that?
> 
> Well, 0x1000'00A0 is above 256 MB, while you  have  only  32  MB  RAM
> which is most probably mapped from 0x0000'0000...0x01FF'FFFF... So
> what you claim to be a physical address (and I think your claim is
> wrong) is far outside available physical memory.
> 
> > The same codes can run well in a PPC440EP (Yosemite Board) which owns
> > 256MB DRAM. At the beginning of my work, I thought memory size may be
> > the cause of failure. But I did not know how to demonstrate it. So if
> > the limitation of 32MB DRAM leads to the failure, are there any methods
> > for the codes to solve it?
> 
> I think you got lost on the wrong track. Please describe  which  task
> you  want  to  implement, and there might be another, better approach
> for it.
> 
> Best regards,
> 
> Wolfgang Denk

__________________________________________________
¸Ï¿ì×¢²áÑÅ»¢³¬´óÈÝÁ¿Ãâ·ÑÓÊÏä?
http://cn.mail.yahoo.com

^ permalink raw reply

* Re: gdb problems with threads on mpc512x
From: Wolfgang Denk @ 2008-08-25 18:20 UTC (permalink / raw)
  To: Daniele Bosi; +Cc: linuxppc-dev
In-Reply-To: <48B28A65.2050409@selcomgroup.com>

Dear Daniele Bosi,

In message <48B28A65.2050409@selcomgroup.com> you wrote:
>
> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> <html>

Please post plain text only on mailing lists.

> I encountered several problem debugging multithreated software with gdb
> on mpc512x, remotely (gdbserver) and locally.<br>
> I built gdb 6.8 from scratch, but it's crashing when I stop execution
> into a thread.<br>
> <br>
> Did anyone get it to work correctly?<br>

We use GDB 6.7 in our ELDK 4.2; we didn't encounter such problems in
our tests.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
I often quote myself; it adds spice to my conversation.  - G. B. Shaw

^ permalink raw reply

* Re: porting linux 2.6.27 to embedded powerpc board
From: Laxmikant Rashinkar @ 2008-08-25 16:51 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hi,

I now have the system booted all the up to the shell prompt.
However, my two NIC cards are not up.

When the system is booting, I get the following error:

TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
24520:00 not found
eth0: Could not attach to PHY
IP-Config: Failed to open eth0
IP-Config: Device `eth0' not found.

here is the networking section from my .dts file

                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "fsl,gianfar-mdio";
                        reg = <0x24520 0x20>;

                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&ipic>;
                                interrupts = <17 0x8>;
                                reg = <0x0>;
                                device_type = "ethernet-phy";
                        };
                        phy1: ethernet-phy@1 {
                                interrupt-parent = <&ipic>;
                                interrupts = <18 0x8>;
                                reg = <0x1>;
                                device_type = "ethernet-phy";
                        };
                };

                enet0: ethernet@24000 {
                        cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x24000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <32 0x8 33 0x8 34 0x8>;
                        interrupt-parent = <&ipic>;
                        phy-handle = <&phy0>;
                        linux,network-index = <0>;
                };

                enet1: ethernet@25000 {
                        cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <0x25000 0x1000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <35 0x8 36 0x8 37 0x8>;
                        interrupt-parent = <&ipic>;
                        phy-handle = <&phy1>;
                        linux,network-index = <1>;
                };

Does anything here seem to be wrong?

thanks for your help
LK




----- Original Message ----
From: David Jander <david.jander@protonic.nl>
To: linuxppc-embedded@ozlabs.org
Cc: Laxmikant Rashinkar <lk.atwork@yahoo.com>
Sent: Thursday, August 21, 2008 2:43:45 AM
Subject: Re: porting linux 2.6.27 to embedded powerpc board

On Thursday 21 August 2008 01:24:46 Laxmikant Rashinkar wrote:
> Hi,
>
> I have an embedded PowerPC (MPC8347) board that works fine with uboot and
> Linux 2.6.15.
>
> I am trying to upgrade the kernel so that it runs on the latest release -
> Linux 2.6.27. So far, I have gotten the kernel to compile on my platform,
> but of course it does not boot.

Well, honestly I don't know where to look for information either (other than 
the source-code and examples from others), but here is a list with points to 
look out for (I have just done the same thing as you for a MPC5200B-based 
board):

1. Upgrade to latest u-boot first (recent git seems to be fine). There have 
been a lot of changes in u-boot lately about OF and device-tree related 
things. I suspect you need a fairly recent version of u-boot to go well with 
the latest kernel. It's also generally a good idea IMHO.

2. I assume you are porting to arch/powerpc (the old arch/ppc you used back in 
2.6.15 is obsolete and broken now).

3. Look at other platforms that use the same processor, and pick a simple one 
as starting point. Look out for the dts (device-tree-source file in 
arch/powerpc/boot/dts), copy and modify one to reflect your hardware. 
Recently a lot of changes happend in the kernel, changing device names, 
obsoleting "device-type" tags, etc..., so some of the current DTS sources 
included in the kernel might not even work (wrong device name, missing 
information, wrong use of "device-type", etc...), so watch out for these kind 
of issues too.

4. Be sure that the device(s) necessary to produce output on your console are 
correctly placed in the DT. Also make sure that u-boot knows about it 
(#define OF_STDOUT_PATH... in your u-boot board config file)

5. When compiling the device tree, it may be necessary to add some extra 
reserved entries to the compiled tree (I am using dtc -p 10240 -R 20, which 
might be slightly exaggerated), because u-boot may add something to it, and 
if it can't, linux won't boot.

6. Remember to always specify the "rootfstype=" option on the commandline if 
booting from anything other than NFS. This was not necessary back in the 
2.6.15-times AFAICR.

7. Boot with a device-tree (in u-boot: "bootm $addrofkernel - $addrofdtb", 
don't forget the dash if you are not using an initrd). If you don't do this, 
u-boot can't fix your DT, and the kernel probably won't find it either.

8. Be sure to use the correct version of the DTC (DT compiler) for your kernel 
(the sources are included nowadays, somewhere in arch/powerpc/boot IIRC). The 
command used to compile, should probably be something like this:

$ ./dtc -p 10240 -R 20 -I dts -o myplatform.dtb -O dtb -b 0 dts/myplatform.dts

Load the resulting .dtb file directly with u-boot (don't make an u-image out 
of it).

That's all I remember right now... hope it helps.

Regards,

-- 
David Jander



      

[-- Attachment #2: Type: text/html, Size: 11524 bytes --]

^ permalink raw reply

* Re: virt_to_phys() in drivers w/dma - MPC8xxx
From: Scott Wood @ 2008-08-25 15:33 UTC (permalink / raw)
  To: rmcguire; +Cc: linuxppc-embedded
In-Reply-To: <6FC450394F2147FDB7EC1D1EB168EB8B@absolutdaddy>

Russell McGuire wrote:
> So shouldn't we be using like dma_alloc_coherent, and then tracking the dma
> address separately as a variable, and use it when necessary instead of
> calling virt_to_phys()?

Yes.  On 8xxx (but not 8xx, and not with 36-bit memory), there'll be no 
practical difference, but the DMA mapping API *should* be used.

-Scott

^ permalink raw reply

* MPC5200 FEC problems
From: Gary Thomas @ 2008-08-25 15:36 UTC (permalink / raw)
  To: linuxppc-dev

I'm adding the Analogue & Micro Boa (MPC5200/B) platform to the
public 2.6.26 tree.  Under heavy network load (sometimes even
not so heavy!), I get this error:
   net eth0: FEC_IEVENT_RFIFO_ERROR
I've read the thread about how this leads to an incorrect call
to the PHY code in the ISR.  It's good to know that part of the
problem is being worked on.

My question is - what exactly does this error imply?  Looking at
the MPC5200 manual doesn't give much info - just that there was
a Rx FIFO error.

I'm also perplexed by the fact that I have two slightly different
Boa boards (same CPU rev, speed, etc).  About the only thing that's
different is the SDRAM setup.  One board is rock solid while the
other gets this error almost immediately.

Also, I sometimes get a Tx timeout on this platform (the one that
fails as above).
   net eth0: transmit timed out
Note that I don't have any trouble with this platform running RedBoot
or eCos, just Linux :-(

Here's the basic info on my platform:

root@ppc_target:~ cat /proc/cpuinfo
processor       : 0
cpu             : G2_LE
clock           : 396.000000MHz
revision        : 1.4 (pvr 8082 2014)
bogomips        : 49.40
timebase        : 24750000

Ideas?  Any help graciously accepted.

n.b. I'm not currently subscribed to this list, so please CC
me on any replies.

Thanks

-- 
------------------------------------------------------------
Gary Thomas                 |  Consulting for the
MLB Associates              |    Embedded world
------------------------------------------------------------

^ permalink raw reply

* Re: [PATCH V2] MPC52XX: Don't touch pipelining for MPC5200B
From: Scott Wood @ 2008-08-25 15:36 UTC (permalink / raw)
  To: roger blofeld; +Cc: Wolfram Sang, Arnd Bergmann, linuxppc-embedded
In-Reply-To: <957941.2462.qm@web53504.mail.re2.yahoo.com>

roger blofeld wrote:
> Hi
>  Since this bug is ATA specific, shouldn't this code be conditioned by CONFIG_IDE ?

And then what happens if IDE is built as a module?

-Scott

^ permalink raw reply

* Re: initramfs vs initrd
From: Sébastien Chrétien @ 2008-08-25 15:37 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <319b0ac50808250729i2043c4d6h57577e0a2eda7ed8@mail.gmail.com>

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

When the kernel is booting, is it possible to check if the initrd is good ?

2008/8/25, Sébastien Chrétien <sebastien.chretien.enseirb@gmail.com>:
>
> ok thank you
>
>
>
> 2008/8/25, Josh Boyer <jwboyer@linux.vnet.ibm.com>:
>>
>> On Mon, Aug 25, 2008 at 02:57:14PM +0200,
>> =?ISO-8859-1?Q?S=E9bastien_Chr=E9tien_ wrote:
>> >Hello,
>> >
>> >What is the difference between initramfs and initrd ?
>>
>>
>> You could poke around in the Documentation directory of the kernel.  That
>> should answer your question.
>>
>> Briefly, initramfs is a gzipped cpio archive.  initrd is typically a
>> compressed ext2 filesystem and requires a ramdisk to be unpacked to.
>>
>> josh
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>>
>
>

[-- Attachment #2: Type: text/html, Size: 1784 bytes --]

^ permalink raw reply

* [RFC PATCH 2/2] powerpc/83xx: mpc836x_mds: add support for USB Host
From: Anton Vorontsov @ 2008-08-25 15:27 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Li Yang

Various changes to support QE USB Host on a MPC8360E-MDS board:

- Update the device tree per QE USB bindings;
- Configure QE Par IO;
- Set up BCSR for both USB Host and Peripheral modes;
- Add timer (GTM) node;
- Add gpio-controller node for BCSR13 bank;
- Select FSL_GTM, QE_GPIO and OF_SIMPLE_GPIO.

The work is loosely based on Li Yang's patch[1], which is used
to support peripheral mode only.

[1] http://ozlabs.org/pipermail/linuxppc-dev/2008-August/061357.html

The s-o-b line of the original patch preserved here.

Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/boot/dts/mpc836x_mds.dts     |   44 +++++++++++++++++++++++++++-
 arch/powerpc/platforms/83xx/Kconfig       |    3 ++
 arch/powerpc/platforms/83xx/mpc836x_mds.c |   31 +++++++++++++++++++-
 3 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index ada8446..0be98f3 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -69,8 +69,19 @@
 		};
 
 		bcsr@1,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			device_type = "board-control";
 			reg = <1 0 0x8000>;
+			ranges = <0 1 0 0x8000>;
+
+			bcsr13: gpio-controller@d {
+				#gpio-cells = <2>;
+				compatible = "fsl,mpc8360mds-bcsr-gpio",
+					     "simple-gpio-bank";
+				reg = <0xd 1>;
+				gpio-controller;
+			};
 		};
 	};
 
@@ -191,10 +202,21 @@
 		};
 
 		par_io@1400 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			reg = <0x1400 0x100>;
+			ranges = <0 0x1400 0x100>;
 			device_type = "par_io";
 			num-ports = <7>;
 
+			qe_pio_b: gpio-controller@18 {
+				#gpio-cells = <2>;
+				compatible = "fsl,mpc8360-qe-pario-bank",
+					     "fsl,mpc8323-qe-pario-bank";
+				reg = <0x18 0x18>;
+				gpio-controller;
+			};
+
 			pio1: ucc_pin@01 {
 				pio-map = <
 			/* port  pin  dir  open_drain  assignment  has_irq */
@@ -278,6 +300,15 @@
 			};
 		};
 
+		timer@440 {
+			compatible = "fsl,mpc8360-qe-gtm",
+				     "fsl,qe-gtm", "fsl,gtm";
+			reg = <0x440 0x40>;
+			clock-frequency = <132000000>;
+			interrupts = <12 13 14 15>;
+			interrupt-parent = <&qeic>;
+		};
+
 		spi@4c0 {
 			cell-index = <0>;
 			compatible = "fsl,spi";
@@ -297,11 +328,20 @@
 		};
 
 		usb@6c0 {
-			compatible = "qe_udc";
+			compatible = "fsl,mpc8360-qe-usb",
+				     "fsl,mpc8323-qe-usb";
 			reg = <0x6c0 0x40 0x8b00 0x100>;
 			interrupts = <11>;
 			interrupt-parent = <&qeic>;
-			mode = "slave";
+			fsl,fullspeed-clock = "clk21";
+			fsl,lowspeed-clock = "brg9";
+			gpios = <&qe_pio_b  2 0   /* USBOE */
+				 &qe_pio_b  3 0   /* USBTP */
+				 &qe_pio_b  8 0   /* USBTN */
+				 &qe_pio_b  9 0   /* USBRP */
+				 &qe_pio_b 11 0   /* USBRN */
+				 &bcsr13    5 0   /* SPEED */
+				 &bcsr13    4 1>; /* POWER */
 		};
 
 		enet0: ucc@2000 {
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 6159c5d..558458d 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -58,6 +58,9 @@ config MPC836x_MDS
 	bool "Freescale MPC836x MDS"
 	select DEFAULT_UIMAGE
 	select QUICC_ENGINE
+	select QE_GPIO
+	select OF_SIMPLE_GPIO
+	select FSL_GTM
 	help
 	  This option enables support for the MPC836x MDS Processor Board.
 
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 9d46e5b..58aabfb 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -127,9 +127,38 @@ static void __init mpc836x_mds_setup_arch(void)
 			iounmap(immap);
 		}
 
-		iounmap(bcsr_regs);
 		of_node_put(np);
 	}
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb");
+	if (np) {
+		const char *mode = of_get_property(np, "mode", NULL);
+
+		par_io_config_pin(1,  2, 1, 0, 3, 0); /* USBOE  */
+		par_io_config_pin(1,  3, 1, 0, 3, 0); /* USBTP  */
+		par_io_config_pin(1,  8, 1, 0, 1, 0); /* USBTN  */
+		par_io_config_pin(1, 10, 2, 0, 3, 0); /* USBRXD */
+		par_io_config_pin(1,  9, 2, 1, 3, 0); /* USBRP  */
+		par_io_config_pin(1, 11, 2, 1, 3, 0); /* USBRN  */
+		par_io_config_pin(2, 20, 2, 0, 1, 0); /* CLK21  */
+
+#define BCSR13_USBMASK	0x0f
+#define BCSR13_nUSBEN	0x08 /* 1 - Disable, 0 - Enable			*/
+#define BCSR13_USBSPEED 0x04 /* 1 - Full, 0 - Low			*/
+#define BCSR13_USBMODE	0x02 /* 1 - Host, 0 - Function			*/
+#define BCSR13_nUSBVCC	0x01 /* 1 - gets VBUS, 0 - supplies VBUS 	*/
+
+		clrsetbits_8(&bcsr_regs[13], BCSR13_USBMASK, BCSR13_USBSPEED);
+
+		if (mode && !strcmp(mode, "peripheral"))
+			setbits8(&bcsr_regs[13], BCSR13_nUSBVCC);
+		else
+			setbits8(&bcsr_regs[13], BCSR13_USBMODE);
+
+		of_node_put(np);
+	}
+
+	iounmap(bcsr_regs);
 #endif				/* CONFIG_QUICC_ENGINE */
 }
 
-- 
1.5.6.3

^ permalink raw reply related

* [RFC PATCH 1/2] powerpc: add driver for simple GPIO banks
From: Anton Vorontsov @ 2008-08-25 15:27 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Li Yang

The driver supports very simple GPIO controllers, that is, when a
controller provides just a 'data' register. Such controllers may
be found in various BCSRs (Board's FPGAs used to control board's
switches, LEDs, chip-selects, Ethernet/USB PHY power, etc).

So far we support only 1-byte GPIO banks. Support for other widths
may be implemented when/if needed.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---

This is evolution of the `PIXIS FPGA' GPIO controller:
http://ozlabs.org/pipermail/linuxppc-dev/2008-May/056731.html

Since for MPC8360E-MDS I need the same driver, I though it
would be great to do something generic.

 arch/powerpc/sysdev/Kconfig          |    8 ++
 arch/powerpc/sysdev/Makefile         |    2 +
 arch/powerpc/sysdev/of_simple_gpio.c |  154 ++++++++++++++++++++++++++++++++++
 3 files changed, 164 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/sysdev/of_simple_gpio.c

diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 72fb35b..33c8a15 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -6,3 +6,11 @@ config PPC4xx_PCI_EXPRESS
 	bool
 	depends on PCI && 4xx
 	default n
+
+config OF_SIMPLE_GPIO
+	bool
+	depends on PPC
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Support for simple, memory-mapped GPIO controllers.
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a90054b..239d7e8 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -36,6 +36,8 @@ ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_4xx)		+= ppc4xx_pci.o
 endif
 
+obj-$(CONFIG_OF_SIMPLE_GPIO)	+= of_simple_gpio.o
+
 # Temporary hack until we have migrated to asm-powerpc
 ifeq ($(ARCH),powerpc)
 obj-$(CONFIG_CPM)		+= cpm_common.o
diff --git a/arch/powerpc/sysdev/of_simple_gpio.c b/arch/powerpc/sysdev/of_simple_gpio.c
new file mode 100644
index 0000000..536c0c2
--- /dev/null
+++ b/arch/powerpc/sysdev/of_simple_gpio.c
@@ -0,0 +1,154 @@
+/*
+ * Simple Memory-Mapped GPIOs
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+
+struct u8_gpio_chip {
+	struct of_mm_gpio_chip mm_gc;
+	spinlock_t lock;
+
+	/* shadowed data register to clear/set bits safely */
+	u8 data;
+};
+
+static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc)
+{
+	return container_of(mm_gc, struct u8_gpio_chip, mm_gc);
+}
+
+static u8 u8_pin2mask(unsigned int pin)
+{
+	return 1 << (8 - 1 - pin);
+}
+
+static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+
+	return in_8(mm_gc->regs) & u8_pin2mask(gpio);
+}
+
+static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&u8_gc->lock, flags);
+
+	if (val)
+		u8_gc->data |= u8_pin2mask(gpio);
+	else
+		u8_gc->data &= ~u8_pin2mask(gpio);
+
+	out_8(mm_gc->regs, u8_gc->data);
+
+	spin_unlock_irqrestore(&u8_gc->lock, flags);
+}
+
+static int u8_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	return 0;
+}
+
+static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	u8_gpio_set(gc, gpio, val);
+	return 0;
+}
+
+static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+	struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+
+	u8_gc->data = in_8(mm_gc->regs);
+}
+
+static int __init u8_simple_gpiochip_add(struct device_node *np)
+{
+	int ret;
+	struct u8_gpio_chip *u8_gc;
+	struct of_mm_gpio_chip *mm_gc;
+	struct of_gpio_chip *of_gc;
+	struct gpio_chip *gc;
+
+	u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL);
+	if (!u8_gc)
+		return -ENOMEM;
+
+	spin_lock_init(&u8_gc->lock);
+
+	mm_gc = &u8_gc->mm_gc;
+	of_gc = &mm_gc->of_gc;
+	gc = &of_gc->gc;
+
+	mm_gc->save_regs = u8_gpio_save_regs;
+	of_gc->gpio_cells = 2;
+	gc->ngpio = 8;
+	gc->direction_input = u8_gpio_dir_in;
+	gc->direction_output = u8_gpio_dir_out;
+	gc->get = u8_gpio_get;
+	gc->set = u8_gpio_set;
+
+	ret = of_mm_gpiochip_add(np, mm_gc);
+	if (ret)
+		goto err;
+	return 0;
+err:
+	kfree(u8_gc);
+	return ret;
+}
+
+static int __init simple_gpiochip_init(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "simple-gpio-bank") {
+		int ret;
+		struct resource r;
+
+		ret = of_address_to_resource(np, 0, &r);
+		if (ret)
+			goto err;
+
+		switch (resource_size(&r)) {
+		case 1:
+			ret = u8_simple_gpiochip_add(np);
+			if (ret)
+				goto err;
+			break;
+		default:
+			/*
+			 * Whenever you need support for GPIO bank width > 1,
+			 * please just turn u8_ code into huge macros, and
+			 * construct needed uX_ code with it.
+			 */
+			ret = -ENOSYS;
+			goto err;
+		}
+		continue;
+err:
+		pr_err("%s: registration failed, status %d\n",
+		       np->full_name, ret);
+	}
+	return 0;
+}
+arch_initcall(simple_gpiochip_init);
-- 
1.5.6.3

^ permalink raw reply related

* Re: [PATCH] [RFC] Fix level IRQ handling on Xilinx INTC with ARCH=powerpc
From: Sergey Temerkhanov @ 2008-08-25 15:02 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <fa686aa40808250726q69a40f9crd814ce52685c071b@mail.gmail.com>

On Monday 25 August 2008 18:26:54 Grant Likely wrote:
>This
> patch unconditionally adds what is essentially a device specific fixup
> to *every* Linux platform.  I cannot see that flying very far.
>

I know that. But without IRQ_CHIP_UNMASK_ACK set this fixup won'be applied so 
setups that are not affected should work as before.

This problem was already discussed before: 
http://www.nabble.com/Level-IRQ-handling-on-Xilinx-INTC-with-ARCH%3Dpowerpc-td18711173.html

Of course, I can just modify xilinx_intc_unmask() routine to perform 
acknowledge as I did before, but it seems a hack to me.

^ permalink raw reply

* ml403  u-boot can't load linux with nfs
From: hsongjiang @ 2008-08-25 14:38 UTC (permalink / raw)
  To: linuxppc-embedded


hi all:
   now i want to use u-boot load linux with avnet minimodule(like ml403 or
ml405) and EDK 10.1 .
   
  after compliling  the  kernel, i use xmd down zImage.elf (nfs root),it
success
like this:
/////////////////////////////////////////////////////////////////////////
loaded at:     00400000 005501A0
board data at: 0054E124 0054E1A0
relocated to:  004050B4 00405130
zimage at:     00405EE9 0054D16F
avail ram:     00551000 04000000

Linux/PPC load: console=ttyS0,38400
ip=192.168.0.3:192.168.0.5:192.168.0.1:255.255.255.0 rw root=/dev/nfs
nfsroot=192.168.0.5:/myrootfs init=/bin/sh

 Kernel command line: console=ttyS0,38400 root=/dev/nfs rw
nfsroot=192.168.0.5:/myrootfs
ip=192.168.0.3:192.168.0.5:192.168.0.1:255.255.255.0 init=/bin/sh

Uncompressing Linux...done.
Now booting the kernel
[    0.000000] Linux version 2.6.26 (root@ioe) (gcc version 4.1.1) #13
PREEMPT Sat Aug 23 17:02:29 CST 2008
[    0.000000] Xilinx Generic PowerPC board support package (Xilinx ML405)
(Virtex-4 FX)
[    0.000000] Zone PFN ranges:
[    0.000000]   DMA             0 ->    16384
   ......
[    0.000000] Kernel command line: console=ttyS0,38400
ip=192.168.0.3:192.168.0.5:192.168.0.1:255.255.255.0 rw root=/dev/nfs
nfsroot=192.168.0.5:/myrootfs init=/bin/sh
[    0.000000] Xilinx INTC #0 at 0x81800000 mapped to 0xFDFFE000
......
[   15.894120] eth0: XLlTemac: We renegotiated the speed to: 100
[   15.921479] eth0: XLlTemac: speed set to 100Mb/s
[   15.935472] eth0: XLlTemac: Send Threshold = 24, Receive Threshold = 4
[   15.955208] eth0: XLlTemac: Send Wait bound = 254, Receive Wait bound =
254
[   16.979388] IP-Config: Complete:
[   16.988691]      device=eth0, addr=192.168.0.3, mask=255.255.255.0,
gw=192.168.0.1,
[   17.011779]      host=192.168.0.3, domain=, nis-domain=(none),
[   17.029405]      bootserver=192.168.0.5, rootserver=192.168.0.5,
rootpath=
[   17.051293] Looking up port of RPC 100003/2 on 192.168.0.5
[   17.078738] Looking up port of RPC 100005/1 on 192.168.0.5
[   17.150065] VFS: Mounted root (nfs filesystem).
[   17.164245] Freeing unused kernel memory: 96k init
# 
/////////////////////////////////////////////////////////////////////////
   but when i use u-boot load,it die.
///////////////////////////////////////////////////////////////////////
## Booting image at 00400000 ...
   Image Name:   Linux-2.6.26
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    1339912 Bytes =  1.3 MB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
[    0.000000] Linux version 2.6.26 (root@ioe) (gcc version 4.1.1) #14
PREEMPT Sat Aug 23 20:53:05 CST 2008
[    0.000000] Xilinx Generic PowerPC board support package (Xilinx ML405)
(Virtex-4 FX)
[    0.000000] Kernel command line: root=/dev/nfs console=ttyS0,38400
ip=192.168.0.3:192.168.0.5:192.168.0.1:255.255.255.0 rw
nfsroot=192.168.0.5:/myrootfs init=/bin/sh
[    0.000000] Xilinx INTC #0 at 0x81800000 mapped to 0xFDFFE000
[    0.000000] PID hash table entries: 128 (order: 7, 512 bytes)

[    1.234613] mice: PS/2 mouse device common for all mice
[    1.255086] TCP cubic registered
[    1.264907] NET: Registered protocol family 17
[    1.279754] RPC: Registered udp transport module.
[    1.294061] RPC: Registered tcp transport module.
[    1.817329] eth0: XLlTemac: Options: 0x3fa
[    1.829839] eth0: XLlTemac: allocating interrupt 0 for dma mode tx.
[    1.848830] eth0: XLlTemac: allocating interrupt 1 for dma mode rx.
[   13.840446] eth0: XLlTemac: Not able to set the speed to 1000 (status:
0x7949)
[   15.858277] eth0: XLlTemac: We renegotiated the speed to: 100
[   15.885639] eth0: XLlTemac: speed set to 100Mb/s
[   15.899634] eth0: XLlTemac: Send Threshold = 24, Receive Threshold = 4
[   15.919370] eth0: XLlTemac: Send Wait bound = 254, Receive Wait bound =
254
[   16.943365] IP-Config: Complete:
[   16.952670]      device=eth0, addr=192.168.0.3, mask=255.255.255.0,
gw=192.168.0.1,
[   16.975732]      host=192.168.0.3, domain=, nis-domain=(none),
[   16.993359]      bootserver=192.168.0.5, rootserver=192.168.0.5,
rootpath=
[   17.015238] Looking up port of RPC 100003/2 on 192.168.0.5
[   17.055939] Looking up port of RPC 100005/1 on 192.168.0.5
[   17.230661] VFS: Mounted root (nfs filesystem).
[   17.244815] Freeing unused kernel memory: 96k init
[   17.338452] ------------[ cut here ]------------
[   17.352390] Badness at kernel/mutex.c:134
[   17.364431] NIP: c021bd20 LR: c021bd08 CTR: c00e0794


  I find they are the same process except [   17.338452] ----[ cut here ]--
so i trace the code.and find
run_init_process("/bin/sh")->kernel_execve(),here may be the proplem. but i
am not sure.
   any suggestion will be very appreciated.thank you!
                         
                                                               hsongjiang 
-- 
View this message in context: http://www.nabble.com/ml403--u-boot-can%27t-load-linux-with-nfs-tp19145094p19145094.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.

^ permalink raw reply

* Re: initramfs vs initrd
From: Sébastien Chrétien @ 2008-08-25 14:29 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev
In-Reply-To: <20080825131018.GA4199@yoda.jdub.homelinux.org>

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

ok thank you



2008/8/25, Josh Boyer <jwboyer@linux.vnet.ibm.com>:
>
> On Mon, Aug 25, 2008 at 02:57:14PM +0200,
> =?ISO-8859-1?Q?S=E9bastien_Chr=E9tien_ wrote:
> >Hello,
> >
> >What is the difference between initramfs and initrd ?
>
>
> You could poke around in the Documentation directory of the kernel.  That
> should answer your question.
>
> Briefly, initramfs is a gzipped cpio archive.  initrd is typically a
> compressed ext2 filesystem and requires a ramdisk to be unpacked to.
>
> josh
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>

[-- Attachment #2: Type: text/html, Size: 1085 bytes --]

^ permalink raw reply

* Re: [PATCH] [RFC] Fix level IRQ handling on Xilinx INTC with ARCH=powerpc
From: Grant Likely @ 2008-08-25 14:26 UTC (permalink / raw)
  To: temerkhanov; +Cc: linuxppc-dev
In-Reply-To: <200808251656.00247.temerkhanov@yandex.ru>

On Mon, Aug 25, 2008 at 6:55 AM, Sergey Temerkhanov
<temerkhanov@yandex.ru> wrote:
> This fixes the missing acknowledge at the end of handle_level_irq().
>
> It adds a field flags to struct irq_chip. If IRQ_CHIP_UNMASK_ACK is set in
> this field, acknowledge is performed before unmasking.

Can this fix be handled in the XINTC controller driver itself?  This
patch unconditionally adds what is essentially a device specific fixup
to *every* Linux platform.  I cannot see that flying very far.

g.

^ permalink raw reply

* ttyS0
From: Sébastien Chrétien @ 2008-08-25 14:16 UTC (permalink / raw)
  To: linuxppc-dev

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

Hello,

I must create a ttyS0 console for my ppc board. Can someone advice an
example ?

Thanks
Sébastien Chrétien

[-- Attachment #2: Type: text/html, Size: 145 bytes --]

^ permalink raw reply

* Re: initramfs vs initrd
From: Josh Boyer @ 2008-08-25 13:10 UTC (permalink / raw)
  To: =?ISO-8859-1?Q?S=E9bastien_Chr=E9tien_, ?=; +Cc: linuxppc-dev
In-Reply-To: <319b0ac50808250557g4bd1d267t14e3bd8887c76e24@mail.gmail.com>

On Mon, Aug 25, 2008 at 02:57:14PM +0200, =?ISO-8859-1?Q?S=E9bastien_Chr=E9tien_ wrote:
>Hello,
>
>What is the difference between initramfs and initrd ?

You could poke around in the Documentation directory of the kernel.  That
should answer your question.

Briefly, initramfs is a gzipped cpio archive.  initrd is typically a
compressed ext2 filesystem and requires a ramdisk to be unpacked to.

josh

^ permalink raw reply

* Re: Efficient memcpy()/memmove() for G2/G3 cores...
From: David Jander @ 2008-08-25 13:06 UTC (permalink / raw)
  To: Matt Sealey; +Cc: linuxppc-dev
In-Reply-To: <48B290BA.7060202@genesi-usa.com>

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


Hi Matt,

On Monday 25 August 2008 13:00:10 Matt Sealey wrote:
> The focus has definitely been on VMX but that's not to say lower power
> processors were forgotten :)

lower-power (pun intended) is coming strong these days, as energy-efficiency 
is getteing more important every day. And the MPC5121 is a brand-new embedded 
processor, that will pop-up in quite a lot devices around you most 
probably ;-)

> Gunnar von Boehn did some benchmarking with an assembly optimized routine,
> for Cell, 603e and so on (basically the whole gamut from embedded up to
> sever class IBM chips) and got some pretty good results;
>
> http://www.powerdeveloper.org/forums/viewtopic.php?t=1426
>
> It is definitely something that needs fixing. The generic routine in glibc
> just copies words with no benefit of knowing the cache line size or any
> cache block buffers in the chip, and certainly no use of cache control or
> data streaming on higher end chips.
>
> With knowledge of the right way to unroll the loops, how many copies to
> do at once to try and get a burst, reducing cache usage etc. you can get
> very impressive performance (as you can see, 50MB up to 78MB at the
> smallest size, the basic improvement is 2x performance).
>
> I hope that helps you a little bit. Gunnar posted code to this list not
> long after. I have a copy of the "e300 optimized" routine but I thought
> best he should post it here, than myself.

Ok, I think I found it on the thread. The only problem is, that AFAICS it can 
be much better... at least on my platform (e300 core), and I don't know why! 
Can you explain this?

I did this:

I took Gunnars code (copy-paste from the forum), renamed the function from 
memcpy_e300 to memcpy and put it in a file called "memcpy_e300.S". Then I 
did:

$ gcc -O2 -Wall -shared -o libmemcpye300.so memcpy_e300.S

I tried the performance with the small program in the attachment:

$ gcc -O2 -Wall -o pruvmem pruvmem.c
$ LD_PRELOAD=..../libmemcpye300.so ./pruvmem

Data rate:  45.9 MiB/s

Now I did the same thing with my own memcpy written in C (see attached file 
mymemcpy.c):

$ LD_PRELOAD=..../libmymemcpy.so ./pruvmem

Data rate:  72.9 MiB/s

Now, can someone please explain this?

As a reference, here's glibc's performance:

$ ./pruvmem

Data rate:  14.8 MiB/s

> There is a lot of scope I think for optimizing several points (glibc,
> kernel, some applications) for embedded processors which nobody is
> really taking on. But, not many people want to do this kind of work..

They should! It makes a HUGE difference. I surely will of course.

Greetings,

-- 
David Jander

[-- Attachment #2: pruvmem.c --]
[-- Type: text/x-csrc, Size: 1629 bytes --]

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
        int f;
        unsigned long int *mem,*src,*dst;
        int t;
        long int usecs;
        unsigned long int secs, count;
        double rate;
        struct timeval tv, tv0, tv1;

        printf("Opening fb0\n");
        f = open("/dev/fb0", O_RDWR);
        if(f<0) {
                perror("opening fb0");
                return 1;
        }
        printf("mmapping fb0\n");

        mem = mmap(NULL, 0x00300000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,f,0);

        printf("mmap returned: %08x\n",(unsigned int)mem);
        perror("mmap");
        if(mem==-1)
                return 1;

        gettimeofday(&tv, NULL);
        for(t=0; t<0x000c0000; t++)
                mem[t] = (tv.tv_usec ^ tv.tv_sec) ^ t;
        count = 0;
        gettimeofday(&tv0, NULL);
        for(t=0; t<10; t++) {
                src = mem;
                dst = mem+0x00040000;
                memcpy(dst, src, 0x00100000);
                count += 0x00100000;
        }
        gettimeofday(&tv1, NULL);
        secs = tv1.tv_sec-tv0.tv_sec;
        usecs = tv1.tv_usec-tv0.tv_usec;
        if(usecs<0) {
                usecs += 1000000;
                secs -= 1;
        }
        printf("Time elapsed: %ld secs, %ld usecs data transferred: %ld bytes\n",secs, usecs, count);
        rate = (double)count/((double)secs + (double)usecs/1000000.0);
        printf("Data rate: %5.3g MiB/s\n", rate/(1024.0*1024.0));

        return 0;
}

[-- Attachment #3: mymemcpy.c --]
[-- Type: text/x-csrc, Size: 2289 bytes --]

#include <stdlib.h>
void * memcpy(void * dst, void const * src, size_t len)
{
        unsigned long int a,b,c,d;
        unsigned long int a1,b1,c1,d1;
        unsigned long int a2,b2,c2,d2;
        unsigned long int a3,b3,c3,d3;
    long * plDst = (long *) dst;
    long const * plSrc = (long const *) src;
    //if (!((unsigned long)src & 0xFFFFFFFC) && !((unsigned long)dst & 0xFFFFFFFC))
    //{
        while (len >= 64)
        {
                        a =  plSrc[0];
                        b =  plSrc[1];
                        c =  plSrc[2];
                        d =  plSrc[3];
                        a1 = plSrc[4];
                        b1 = plSrc[5];
                        c1 = plSrc[6];
                        d1 = plSrc[7];
                        a2 = plSrc[8];
                        b2 = plSrc[9];
                        c2 = plSrc[10];
                        d2 = plSrc[11];
                        a3 = plSrc[12];
                        b3 = plSrc[13];
                        c3 = plSrc[14];
                        d3 = plSrc[15];
                        plSrc += 16;
                        plDst[0] = a;
                        plDst[1] = b;
                        plDst[2] = c;
                        plDst[3] = d;
                        plDst[4] = a1;
                        plDst[5] = b1;
                        plDst[6] = c1;
                        plDst[7] = d1;
                        plDst[8] = a2;
                        plDst[9] = b2;
                        plDst[10] = c2;
                        plDst[11] = d2;
                        plDst[12] = a3;
                        plDst[13] = b3;
                        plDst[14] = c3;
                        plDst[15] = d3;
                        plDst += 16;
            len -= 64;
        }
        while(len >= 16) {
            a =  plSrc[0];
            b =  plSrc[1];
            c =  plSrc[2];
            d =  plSrc[3];
            plSrc += 4;
            plDst[0] = a;
            plDst[1] = b;
            plDst[2] = c;
            plDst[3] = d;
            plDst += 4;
            len -= 16;
        }
    //}
    char * pcDst = (char *) plDst;
    char const * pcSrc = (char const *) plSrc;

    while (len--)
    {
        *pcDst++ = *pcSrc++;
    }
    return (dst);
}

^ permalink raw reply

* initramfs vs initrd
From: Sébastien Chrétien @ 2008-08-25 12:57 UTC (permalink / raw)
  To: linuxppc-dev

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

Hello,

What is the difference between initramfs and initrd ?

Sébastien Chrétien

[-- Attachment #2: Type: text/html, Size: 107 bytes --]

^ permalink raw reply

* [PATCH] [RFC] Fix level IRQ handling on Xilinx INTC with ARCH=powerpc
From: Sergey Temerkhanov @ 2008-08-25 12:55 UTC (permalink / raw)
  To: linuxppc-dev

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

This fixes the missing acknowledge at the end of handle_level_irq().

It adds a field flags to struct irq_chip. If IRQ_CHIP_UNMASK_ACK is set in 
this field, acknowledge is performed before unmasking.

[-- Attachment #2: fix-level-irq-handling.patch --]
[-- Type: text/x-diff, Size: 1696 bytes --]

diff -r 6b0915754563 arch/powerpc/sysdev/xilinx_intc.c
--- a/arch/powerpc/sysdev/xilinx_intc.c	Mon Jul 28 19:59:22 2008 +0400
+++ b/arch/powerpc/sysdev/xilinx_intc.c	Fri Aug 08 13:13:52 2008 +0400
@@ -73,6 +73,7 @@
 	.mask = xilinx_intc_mask,
 	.unmask = xilinx_intc_unmask,
 	.ack = xilinx_intc_ack,
+	.flags = IRQ_CHIP_UNMASK_ACK,
 };
 
 /*
@@ -107,8 +108,8 @@
 	}
 	regs = ioremap(res.start, 32);
 
-	printk(KERN_INFO "Xilinx intc at 0x%08LX mapped to 0x%p\n",
-		res.start, regs);
+	printk(KERN_INFO "Xilinx intc at 0x%p mapped to 0x%p\n",
+		(void *)res.start, regs);
 
 	/* Setup interrupt controller */
 	out_be32(regs + XINTC_IER, 0); /* disable all irqs */
diff -r 6b0915754563 include/linux/irq.h
--- a/include/linux/irq.h	Mon Jul 28 19:59:22 2008 +0400
+++ b/include/linux/irq.h	Fri Aug 08 13:13:52 2008 +0400
@@ -114,6 +114,9 @@
 	int		(*retrigger)(unsigned int irq);
 	int		(*set_type)(unsigned int irq, unsigned int flow_type);
 	int		(*set_wake)(unsigned int irq, unsigned int on);
+
+	unsigned int	flags;
+#define IRQ_CHIP_UNMASK_ACK	0x00000001
 
 	/* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
diff -r 6b0915754563 kernel/irq/chip.c
--- a/kernel/irq/chip.c	Mon Jul 28 19:59:22 2008 +0400
+++ b/kernel/irq/chip.c	Fri Aug 08 13:13:52 2008 +0400
@@ -377,8 +377,12 @@
 
 	spin_lock(&desc->lock);
 	desc->status &= ~IRQ_INPROGRESS;
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(irq);
+	if (!(desc->status & IRQ_DISABLED)) {
+		if (desc->chip->flags & IRQ_CHIP_UNMASK_ACK)
+			desc->chip->ack(irq);
+		if (desc->chip->unmask)
+			desc->chip->unmask(irq);
+	}
 out_unlock:
 	spin_unlock(&desc->lock);
 }

^ permalink raw reply

* Re: [PATCH 4/4] Add kernel doc for the completion, fix kernel-doc-nano-HOWTO.txt
From: Ingo Molnar @ 2008-08-25 12:42 UTC (permalink / raw)
  To: Kevin Diggs; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <48B29696.3070808@hypersurf.com>


* Kevin Diggs <kevdig@hypersurf.com> wrote:

> This patch adds kernel doc for the completion feature. It is in 
> kernel/sched.c and include/linux/completion.h.

this patch is whitespace damaged. Could you resend it as attachment, or 
set up your email client as per Documentation/email-clients.txt?

	Ingo

^ permalink raw reply

* Re: [PATCH 2/4] Add cpufreq driver for the IBM PowerPC 750GX
From: Arnd Bergmann @ 2008-08-25 11:43 UTC (permalink / raw)
  To: Kevin Diggs; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <48B28F23.1000906@hypersurf.com>

On Monday 25 August 2008, Kevin Diggs wrote:
> + * cf750gx.c - cpufreq driver for the dual PLLs in the 750gx

Thanks for posting this driver and for your attention for detail
and for documentation in particular. Few people bother to write
documentation at this level.

I don't understand enough of cpufreq or your hardware to comment
on that, but please let me give you a few hints on coding style.

> + * =A0Copyright (C) 2008 =A0 =A0 =A0 kevin Diggs

Most people list their email address here as well

> +#define cf750gxmChangingPll=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0(0x800000=
00)
> +#define cf750gxmChangingPllBit=A0=A0=A0=A0=A0=A0=A0=A0=A0(31)
> +#define cf750gxmTurningIdlePllOff=A0=A0=A0=A0=A0=A0(0x40000000)
> +#define cf750gxmTurningIdlePllOffBit=A0=A0=A0(30)

constants should be ALL_CAPS, not sIllYCaPS.

> +struct pll_750fgx_t {
> +=A0=A0=A0=A0=A0=A0=A0unsigned short min_ratio;=A0=A0=A0=A0=A0=A0=A0/* mi=
n bus ratio */
> +=A0=A0=A0=A0=A0=A0=A0unsigned short max_ratio;=A0=A0=A0=A0=A0=A0=A0/* ma=
x bus ratio */
> +=A0=A0=A0=A0=A0=A0=A0unsigned int min_core;=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0/* min core frequency per spec (KHz) */
> +=A0=A0=A0=A0=A0=A0=A0unsigned int max_core;=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0/* max core frequency per spec (KHz) */
> +};

please drop the _t at the end of the identifier.

> +MODULE_AUTHOR("Kevin Diggs");
> +MODULE_DESCRIPTION("750GX Dual PLL cpufreq driver");
> +MODULE_LICENSE("GPL");

Move this to the end.

> +struct cf750gx_t_call_data {
> +=A0=A0=A0=A0=A0=A0=A0struct cpufreq_freqs freqs;
> +=A0=A0=A0=A0=A0=A0=A0unsigned long current_pll;
> +=A0=A0=A0=A0=A0=A0=A0int idle_pll_off;
> +};

drop the _t here, or make explicit what is meant by it.

> +static const struct pll_750fgx_t __initdata pll_750fx =3D {
> +=A0=A0=A0=A0=A0=A0=A0.min_ratio =3D 2,
> +=A0=A0=A0=A0=A0=A0=A0.max_ratio =3D 20,
> +=A0=A0=A0=A0=A0=A0=A0.min_core =3D 400000,
> +=A0=A0=A0=A0=A0=A0=A0.max_core =3D 800000,
> +};
> +
> +static const struct pll_750fgx_t __initdata pll_750gx =3D {
> +=A0=A0=A0=A0=A0=A0=A0.min_ratio =3D 2,
> +=A0=A0=A0=A0=A0=A0=A0.max_ratio =3D 20,
> +=A0=A0=A0=A0=A0=A0=A0.min_core =3D 500000,
> +=A0=A0=A0=A0=A0=A0=A0.max_core =3D 1000000,
> +};

Are these correct on any board? If they can be different
depending on the board design, it would be better to get
this data from the device tree.

> +static DECLARE_COMPLETION(cf750gx_v_exit_completion);
> +
> +static unsigned int override_min_core =3D 0;
> +static unsigned int override_max_core =3D 0;
> +static unsigned int minmaxmode =3D 0;
> +
> +static unsigned int cf750gx_v_min_core =3D 0;
> +static unsigned int cf750gx_v_max_core =3D 0;
> +static int cf750gx_v_idle_pll_off =3D 0;
> +static int cf750gx_v_min_max_mode =3D 0;
> +static unsigned long cf750gx_v_state_bits =3D 0;

Is 0 a meaningful value for these? If it just means 'uninitialized',
then better don't initialize them in the first place, for clarity.

> +static struct cpufreq_frequency_table *cf750gx_v_f_table;
> +static struct cpufreq_frequency_table *cf750gx_v_freq_table;
> +static struct cpufreq_frequency_table *cf750gx_v_min_max_freq_table;
> +
> +static struct cf750gx_t_call_data cf750gx_v_switch_call_data;
> +static struct cf750gx_t_call_data cf750gx_v_lock_call_data;
> +static struct notifier_block cf750gx_v_pll_switch_nb;
> +static struct notifier_block cf750gx_v_pll_lock_nb;

Also, in general, try to avoid global variables here, even=20
in file scope (static), but rather put all device specific
data into a per-device data structure.

> +static int cf750gx_pll_switch_cb(struct notifier_block *nb, unsigned long
> +=A0=A0=A0=A0=A0=A0=A0action, void *data)
> +{
> +struct cf750gx_t_call_data *cd;
> +unsigned int idle_pll;
> +unsigned int pll_off_cmd;
> +unsigned int new_pll;

The whitespace appears damaged here.

> +=A0=A0=A0=A0=A0=A0=A0cd =3D (struct cf750gx_t_call_data *)data;

data is a void pointer, so you don't need the cast, and shouldn't
have it therefore.
> +static int cf750gx_pll_lock_cb(struct notifier_block *nb, unsigned long =
action,
> +=A0=A0=A0=A0=A0=A0=A0void *data)
> +{
> +struct cf750gx_t_call_data *cd;
> +
> +=A0=A0=A0=A0=A0=A0=A0cd =3D (struct cf750gx_t_call_data *)data;

same here.

> +static int cf750gx_target(struct cpufreq_policy *policy,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =
=A0 =A0 =A0 unsigned int target_freq, unsigned int relation)
> +{
> +unsigned int next_index =3D 0;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0/* Index =
into freq_table */
> +unsigned int next_freq =3D 0;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0/* next=
 frequency from perf table */
> +unsigned int next_perf_state =3D 0;=A0=A0=A0=A0=A0=A0/* Index from perf =
table */
> +int result =3D 0;

Don't initialize local variables in the declaration, as that will prevent
the compiler from warning about uninitialized use.

> +unsigned int pll;
> +unsigned int new_pll;
> +unsigned int active_pll;
> +struct cpufreq_freqs freqs;
> +struct cpufreq_frequency_table *ft =3D cf750gx_v_f_table;

more whitespace damage. Maybe there is something wrong with your
text editor.

> +=A0=A0=A0=A0=A0=A0=A0dprintk(__FILE__">%s(, %u KHz, relation %u)-%d: =A0=
on cpu %d\n",
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0__func__, target_freq, rela=
tion, __LINE__, policy->cpu);
> +
> +=A0=A0=A0=A0=A0=A0=A0if (test_and_set_bit(cf750gxmChangingPllBit, &cf750=
gx_v_state_bits))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return -EAGAIN;
> +
> +=A0=A0=A0=A0=A0=A0=A0INIT_COMPLETION(cf750gx_v_exit_completion);
> +
> +=A0=A0=A0=A0=A0=A0=A0result =3D cpufreq_frequency_table_target(policy,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ft,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0target=
_freq,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0relati=
on, &next_index);
> +
> +=A0=A0=A0=A0=A0=A0=A0if (unlikely(result))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0goto cf750gxTargetNoFreq;

The unlikely() here looks like overoptimization, drop it in favor of
readability unless you can measure a real-world difference.

> +=A0=A0=A0=A0=A0=A0=A0if (active_pll) {
> +=A0=A0=A0=A0=A0=A0=A0unsigned int current_state;

whitespace damage.

> +=A0=A0=A0=A0=A0=A0=A0dprintk(__FILE__">%s()-%d: =A0Modifying PLL: =A00x%=
x\n", __func__, __LINE__,
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0new_pll);

Please go through all your dprintk and see if you really really need all of=
 them.
Usually they are useful while you are doing the initial code, but only get =
in the
way as soon as it starts working.

> +cf750gxTargetOut:
> +=A0=A0=A0=A0=A0=A0=A0return result;
> +
> +cf750gxTargetNoFreq:
> +=A0=A0=A0=A0=A0=A0=A0result =3D -ENODEV;
> +
> +=A0=A0=A0=A0=A0=A0=A0goto cf750gxTargetUnlock;
> +cf750gxTargetFreqSet:
> +=A0=A0=A0=A0=A0=A0=A0result =3D 0;
> +
> +=A0=A0=A0=A0=A0=A0=A0goto cf750gxTargetUnlock;
> +cf750gxTargetUnlock:
> +=A0=A0=A0=A0=A0=A0=A0clear_bit(cf750gxmChangingPllBit, &cf750gx_v_state_=
bits);
> +=A0=A0=A0=A0=A0=A0=A0complete(&cf750gx_v_exit_completion);
> +
> +=A0=A0=A0=A0=A0=A0=A0goto cf750gxTargetOut;

The conventional way to write this would be:

	result =3D -ENODEV;
	if (foo)
		goto out_unlock;

	result =3D 0;
	if (bar)
		goto out_unlock;

	return 0;

out_unlock:
	clear_bit(cf750gxmChangingPllBit, &cf750gx_v_state_bits);
	complete(&cf750gx_v_exit_completion);
out:
	return result;

> +/*=A0=A0=A0=A0=A0policy->cpuinfo.transition_latency =3D CPUFREQ_ETERNAL;=
 */
> +=A0=A0=A0=A0=A0=A0=A0policy->cpuinfo.transition_latency =3D pllif_get_la=
tency();

The comment does not really explain anything. If you just want to disable
code, use #if 0, but better drop it right away and add a comment about
what might need changing.

> +=A0=A0=A0=A0=A0=A0=A0result =3D cpufreq_frequency_table_cpuinfo(policy, =
cf750gx_v_f_table);
> +=A0=A0=A0=A0=A0=A0=A0if (result)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0goto err_freqfree;
> +
> +=A0=A0=A0=A0=A0=A0=A0cpufreq_frequency_table_get_attr(cf750gx_v_f_table,=
 policy->cpu);
> +
> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_switch_nb.notifier_call =3D cf750gx_p=
ll_switch_cb;
> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_switch_nb.next =3D (struct notifier_b=
lock *)
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0&cf750gx_v_switch_call_data;
> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_switch_nb.priority =3D 0;
> +
> +=A0=A0=A0=A0=A0=A0=A0result =3D pllif_register_pll_switch_cb(&cf750gx_v_=
pll_switch_nb);
> +
> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_lock_nb.notifier_call =3D cf750gx_pll=
_lock_cb;
> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_lock_nb.next =3D
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0(struct notifier_block *)&c=
f750gx_v_lock_call_data;

These casts look wrong, cf750gx_v_lock_call_data is not a notifier_block.
What are you trying to do here?

> +=A0=A0=A0=A0=A0=A0=A0cf750gx_v_pll_lock_nb.priority =3D 0;
> +
> +=A0=A0=A0=A0=A0=A0=A0result =3D pllif_register_pll_lock_cb(&cf750gx_v_pl=
l_lock_nb);
> +
> +=A0=A0=A0=A0=A0=A0=A0return result;
> +
> +err_freqfree:
> +=A0=A0=A0=A0=A0=A0=A0return result;
> +}

The first 'return result' is redundant, drop it.

> +
> +static int cf750gx_cpu_exit(struct cpufreq_policy *policy)
> +{
> +=A0=A0=A0=A0=A0=A0=A0dprintk("%s()\n", __func__);
> +
> +=A0=A0=A0=A0=A0=A0=A0/*
> +=A0=A0=A0=A0=A0=A0=A0 * Wait for any active requests to ripple through b=
efore exiting
> +=A0=A0=A0=A0=A0=A0=A0 */
> +=A0=A0=A0=A0=A0=A0=A0wait_for_completion(&cf750gx_v_exit_completion);

This "wait for anything" use of wait_for_completion looks wrong,=20
because once any other function has done the 'complete', you won't
wait here any more.

What exactly are you trying to accomplish with this?

> +static int __init cf750gx_init(void)
> +{
> +int ret;
> +unsigned int freq, i, j, rng, bus_clock;
> +unsigned short min_ratio, max_ratio;
> +struct cpufreq_frequency_table *tbp;
> +const struct pll_750fgx_t *pll_defaults;

whitespace.

> +=A0=A0=A0=A0=A0=A0=A0dprintk("%s()\n", __func__);
> +
> +=A0=A0=A0=A0=A0=A0=A0if (!cpu_has_feature(CPU_FTR_DUAL_PLL_750FX))
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0return 0;

Is this purely a feature of the CPU or does it need logic
in the board design? If you need external hardware for it,
you need to check the device tree for the presence of that
hardware.

> +=A0=A0=A0=A0=A0=A0=A0if (cf750gx_v_freq_table =3D=3D NULL) {
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0ret =3D -ENOMEM;
> +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0goto ErrSimple;
> +=A0=A0=A0=A0=A0=A0=A0}

ret =3D -ENOMEM;
if (!cf750gx_freq_table)
	goto err_simple;


	Arnd <><

^ permalink raw reply

* Re: [PATCH 1/4] Add low level PLL config register interface module
From: Kumar Gala @ 2008-08-25 11:40 UTC (permalink / raw)
  To: Kevin Diggs; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <48B28C62.2000600@hypersurf.com>


On Aug 25, 2008, at 5:41 AM, Kevin Diggs wrote:

> This adds a small module to handle the low level details of dealing  
> with the
> PLL config register (HID1) found in the IBM 750GX. It provides 2  
> possible
> interfaces, both selectable via kernel config options. One is a  
> sysfs attribute
> and the other is a normal function API. It is called pll_if.
>
> The determination of the bus frequency is what worked on a PowerMac  
> 8600. Any
> suggestions on a more general solution are welcome.
>
> WARNING - I used some #ifdefs - Let the fur fly!
>
> My name is Kevin Diggs and I approve this patch.

This really should be split into two patches.  One for the perl script  
and one for the actual kernel code.

Scanning the actual kernel code you have a lot of #ifdef's that should  
be cleaned up:

Can't #ifdef CONFIG_PPC_750GX_DUAL_PLL_IF_SYSFS just be #ifdef  
CONFIG_SYSFS and the same for CONFIG_PPC_750GX_DUAL_PLL_IF_HRTIMER &  
CONFIG_PPC_750GX_DUAL_PLL_IF_CPU_FREQ?

#ifdef CONFIG_PPC_OF seems unnecessary as all PPC always has this set.

What's up with #define MULFIRST and the #if 0?

- k

^ permalink raw reply

* [PATCH 4/4] Add kernel doc for the completion, fix kernel-doc-nano-HOWTO.txt
From: Kevin Diggs @ 2008-08-25 11:25 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel, mingo

This patch adds kernel doc for the completion feature. It is in kernel/sched.c
and include/linux/completion.h.

An error in the split-man.pl PERL snippet in kernel-doc-nano-HOWTO.txt is
also fixed.

My name is Kevin Diggs and I approve this patch.

Signed-off-by: Kevin Diggs <kevdig@hypersurf.com>
Index: Documentation/kernel-doc-nano-HOWTO.txt
===================================================================
--- Documentation/kernel-doc-nano-HOWTO.txt.orig	2008-08-13 02:18:53.000000000 -0700
+++ Documentation/kernel-doc-nano-HOWTO.txt	2008-08-19 14:21:43.000000000 -0700
@@ -168,10 +168,10 @@ if ($#ARGV < 0) {
  mkdir $ARGV[0],0777;
  $state = 0;
  while (<STDIN>) {
-    if (/^\.TH \"[^\"]*\" 4 \"([^\"]*)\"/) {
+    if (/^\.TH \"[^\"]*\" 9 \"([^\"]*)\"/) {
  	if ($state == 1) { close OUT }
  	$state = 1;
-	$fn = "$ARGV[0]/$1.4";
+	$fn = "$ARGV[0]/$1.9";
  	print STDERR "Creating $fn\n";
  	open OUT, ">$fn" or die "can't open $fn: $!\n";
  	print OUT $_;
Index: include/linux/completion.h
===================================================================
--- include/linux/completion.h.orig	2008-08-13 00:56:52.000000000 -0700
+++ include/linux/completion.h	2008-08-20 01:47:21.000000000 -0700
@@ -10,6 +10,18 @@

  #include <linux/wait.h>

+/**
+ * struct completion - structure used to maintain state for a "completion"
+ *
+ * This is the opaque structure used to maintain the state for a "completion".
+ * Completions currently use a FIFO to queue threads that have to wait for
+ * the "completion" event.
+ *
+ * See also:  complete(), wait_for_completion() (and friends _timeout,
+ * _interruptible, _interruptible_timeout, and _killable), init_completion(),
+ * and macros DECLARE_COMPLETION(), DECLARE_COMPLETION_ONSTACK(), and
+ * INIT_COMPLETION().
+ */
  struct completion {
  	unsigned int done;
  	wait_queue_head_t wait;
@@ -21,6 +33,14 @@ struct completion {
  #define COMPLETION_INITIALIZER_ONSTACK(work) \
  	({ init_completion(&work); work; })

+/**
+ * DECLARE_COMPLETION: - declare and initialize a completion structure
+ * @work:  identifier for the completion structure
+ *
+ * This macro declares and initializes a completion structure. Generally used
+ * for static declarations. You should use the _ONSTACK variant for automatic
+ * variables.
+ */
  #define DECLARE_COMPLETION(work) \
  	struct completion work = COMPLETION_INITIALIZER(work)

@@ -29,6 +49,13 @@ struct completion {
   * completions - so we use the _ONSTACK() variant for those that
   * are on the kernel stack:
   */
+/**
+ * DECLARE_COMPLETION_ONSTACK: - declare and initialize a completion structure
+ * @work:  identifier for the completion structure
+ *
+ * This macro declares and initializes a completion structure on the kernel
+ * stack.
+ */
  #ifdef CONFIG_LOCKDEP
  # define DECLARE_COMPLETION_ONSTACK(work) \
  	struct completion work = COMPLETION_INITIALIZER_ONSTACK(work)
@@ -36,6 +63,13 @@ struct completion {
  # define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
  #endif

+/**
+ * init_completion: - Initialize a dynamically allocated completion
+ * @x:  completion structure that is to be initialized
+ *
+ * This inline function will initialize a dynamically created completion
+ * structure.
+ */
  static inline void init_completion(struct completion *x)
  {
  	x->done = 0;
@@ -53,6 +87,13 @@ extern unsigned long wait_for_completion
  extern void complete(struct completion *);
  extern void complete_all(struct completion *);

+/**
+ * INIT_COMPLETION: - reinitialize a completion structure
+ * @x:  completion structure to be reinitialized
+ *
+ * This macro should be used to reinitialize a completion structure so it can
+ * be reused. This is especially important after complete_all() is used.
+ */
  #define INIT_COMPLETION(x)	((x).done = 0)

  #endif
Index: kernel/sched.c
===================================================================
--- kernel/sched.c.orig	2008-08-13 02:22:42.000000000 -0700
+++ kernel/sched.c	2008-08-20 12:36:01.000000000 -0700
@@ -4363,6 +4363,15 @@ __wake_up_sync(wait_queue_head_t *q, uns
  }
  EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */

+/**
+ * complete: - signals a single thread waiting on this completion
+ * @x:  holds the state of this particular completion
+ *
+ * This will wake up a single thread waiting on this completion. Threads will be
+ * awakened in the same order in which they were queued.
+ *
+ * See also complete_all(), wait_for_completion() and related routines.
+ */
  void complete(struct completion *x)
  {
  	unsigned long flags;
@@ -4374,6 +4383,12 @@ void complete(struct completion *x)
  }
  EXPORT_SYMBOL(complete);

+/**
+ * complete_all: - signals all threads waiting on this completion
+ * @x:  holds the state of this particular completion
+ *
+ * This will wake up all threads waiting on this particular completion event.
+ */
  void complete_all(struct completion *x)
  {
  	unsigned long flags;
@@ -4425,12 +4440,31 @@ wait_for_common(struct completion *x, lo
  	return timeout;
  }

+/**
+ * wait_for_completion: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout.
+ *
+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
+ * and interrupt capability. Also see complete().
+ */
  void __sched wait_for_completion(struct completion *x)
  {
  	wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
  }
  EXPORT_SYMBOL(wait_for_completion);

+/**
+ * wait_for_completion_timeout: - waits for completion of a task (w/timeout)
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be signaled or for a
+ * specified timeout to expire. The timeout is in jiffies. It is not
+ * interruptible.
+ */
  unsigned long __sched
  wait_for_completion_timeout(struct completion *x, unsigned long timeout)
  {
@@ -4438,6 +4472,13 @@ wait_for_completion_timeout(struct compl
  }
  EXPORT_SYMBOL(wait_for_completion_timeout);

+/**
+ * wait_for_completion_interruptible: - waits for completion of a task (w/intr)
+ * @x:  holds the state of this particular completion
+ *
+ * This waits for completion of a specific task to be signaled. It is
+ * interruptible.
+ */
  int __sched wait_for_completion_interruptible(struct completion *x)
  {
  	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
@@ -4447,6 +4488,14 @@ int __sched wait_for_completion_interrup
  }
  EXPORT_SYMBOL(wait_for_completion_interruptible);

+/**
+ * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr))
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be signaled or for a
+ * specified timeout to expire. It is interruptible. The timeout is in jiffies.
+ */
  unsigned long __sched
  wait_for_completion_interruptible_timeout(struct completion *x,
  					  unsigned long timeout)
@@ -4455,6 +4504,13 @@ wait_for_completion_interruptible_timeou
  }
  EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);

+/**
+ * wait_for_completion_killable: - waits for completion of a task (killable)
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It can be
+ * interrupted by a kill signal.
+ */
  int __sched wait_for_completion_killable(struct completion *x)
  {
  	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE);

^ permalink raw reply

* [PATCH 3/4] Various arch/powerpc changes to support the 750GX cpufreq driver
From: Kevin Diggs @ 2008-08-25 11:03 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel

This patch includes various changes necessary to support the cpufreq driver for
the PowerPC 750GX. Highlights include adding entries to recognize the 750GX to
the cputable (This includes the ... unfortunate pvr that the 750GX used in the
PowerLogix PowerForce 750GX => 0x0008 0203). The PLL switch in idle_6xx.S
during sleep (or nap) was also removed (I tried to add ability to disable this
but the result would not boot?).

My name is Kevin Diggs and I approve this patch.

Signed-off-by: Kevin Diggs <kevdig@hypersurf.com>
Index: arch/powerpc/kernel/Makefile
===================================================================
--- arch/powerpc/kernel/Makefile.orig	2008-08-13 02:19:18.000000000 -0700
+++ arch/powerpc/kernel/Makefile	2008-08-14 02:50:18.000000000 -0700
@@ -17,6 +17,7 @@ obj-y				:= cputable.o ptrace.o syscalls
  				   init_task.o process.o systbl.o idle.o \
  				   signal.o
  obj-y				+= vdso32/
+obj-y				+= cpu/
  obj-$(CONFIG_PPC64)		+= setup_64.o sys_ppc32.o \
  				   signal_64.o ptrace32.o \
  				   paca.o cpu_setup_ppc970.o \
Index: arch/powerpc/kernel/cputable.c
===================================================================
--- arch/powerpc/kernel/cputable.c.orig	2008-08-13 02:19:19.000000000 -0700
+++ arch/powerpc/kernel/cputable.c	2008-08-14 03:00:51.000000000 -0700
@@ -42,9 +42,11 @@ extern void __setup_cpu_604(unsigned lon
  extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
  extern void __setup_cpu_750cx(unsigned long offset, struct cpu_spec* spec);
  extern void __setup_cpu_750fx(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_750gx(unsigned long offset, struct cpu_spec* spec);
  extern void __setup_cpu_7400(unsigned long offset, struct cpu_spec* spec);
  extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
  extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
+
  #endif /* CONFIG_PPC32 */
  #ifdef CONFIG_PPC64
  extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
@@ -660,7 +662,7 @@ static struct cpu_spec __initdata cpu_sp
  		.machine_check		= machine_check_generic,
  		.platform		= "ppc750",
  	},
-	{	/* 750GX */
+	{	/* 750GX rev 1.x */
  		.pvr_mask		= 0xffff0000,
  		.pvr_value		= 0x70020000,
  		.cpu_name		= "750GX",
@@ -669,7 +671,33 @@ static struct cpu_spec __initdata cpu_sp
  		.icache_bsize		= 32,
  		.dcache_bsize		= 32,
  		.num_pmcs		= 4,
-		.cpu_setup		= __setup_cpu_750fx,
+		.cpu_setup		= __setup_cpu_750gx,
+		.machine_check		= machine_check_generic,
+		.platform		= "ppc750",
+	},
+	{	/* 750GX (rev 2.3, as used on PowerLogix 750GX upgrade card */
+		.pvr_mask		= 0xffffffff,
+		.pvr_value		= 0x00080203,
+		.cpu_name		= "750GX",
+		.cpu_features		= CPU_FTRS_750GX,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.num_pmcs		= 4,
+		.cpu_setup		= __setup_cpu_750gx,
+		.machine_check		= machine_check_generic,
+		.platform		= "ppc750",
+	},
+	{	/* 750GX (All revs >= 2.0) */
+		.pvr_mask		= 0xffffff00,
+		.pvr_value		= 0x70020200,
+		.cpu_name		= "750GX",
+		.cpu_features		= CPU_FTRS_750GX,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.num_pmcs		= 4,
+		.cpu_setup		= __setup_cpu_750gx,
  		.machine_check		= machine_check_generic,
  		.platform		= "ppc750",
  	},
Index: arch/powerpc/kernel/cpu_setup_6xx.S
===================================================================
--- arch/powerpc/kernel/cpu_setup_6xx.S.orig	2008-08-13 02:19:19.000000000 -0700
+++ arch/powerpc/kernel/cpu_setup_6xx.S	2008-08-14 02:44:30.000000000 -0700
@@ -53,6 +53,14 @@ _GLOBAL(__setup_cpu_750fx)
  	bl	setup_750fx
  	mtlr	r4
  	blr
+_GLOBAL(__setup_cpu_750gx)
+	mflr	r4
+	bl	__init_fpu_registers
+	bl	setup_common_caches
+	bl	setup_750_7400_hid0
+	bl	setup_750gx
+	mtlr	r4
+	blr
  _GLOBAL(__setup_cpu_7400)
  	mflr	r4
  	bl	__init_fpu_registers
@@ -200,6 +208,11 @@ setup_750cx:
  setup_750fx:
  	blr

+/* 750gx specific
+ */
+setup_750gx:
+	blr
+
  /* MPC 745x
   * Enable Store Gathering (SGE), Branch Folding (FOLD)
   * Branch History Table (BHTE), Branch Target ICache (BTIC)
Index: arch/powerpc/kernel/idle_6xx.S
===================================================================
--- arch/powerpc/kernel/idle_6xx.S.orig	2008-02-25 18:10:30.000000000 -0800
+++ arch/powerpc/kernel/idle_6xx.S	2008-08-14 02:44:30.000000000 -0700
@@ -45,11 +45,6 @@ BEGIN_FTR_SECTION
  	addis	r6,r5, nap_save_msscr0@ha
  	stw	r4,nap_save_msscr0@l(r6)
  END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
-	mfspr	r4,SPRN_HID1
-	addis	r6,r5,nap_save_hid1@ha
-	stw	r4,nap_save_hid1@l(r6)
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
  	blr

  /*
@@ -107,18 +102,6 @@ BEGIN_FTR_SECTION
  	dcbf	0,r4
  END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
  2:
-BEGIN_FTR_SECTION
-	/* Go to low speed mode on some 750FX */
-	lis	r4,powersave_lowspeed@ha
-	lwz	r4,powersave_lowspeed@l(r4)
-	cmpwi	0,r4,0
-	beq	1f
-	mfspr	r4,SPRN_HID1
-	oris	r4,r4,0x0001
-	mtspr	SPRN_HID1,r4
-1:	
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
-
  	/* Go to NAP or DOZE now */	
  	mfspr	r4,SPRN_HID0
  	lis	r5,(HID0_NAP|HID0_SLEEP)@h
@@ -178,20 +161,9 @@ BEGIN_FTR_SECTION
  	isync
  1:
  END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-BEGIN_FTR_SECTION
-	addis	r9,r11,(nap_save_hid1-KERNELBASE)@ha
-	lwz	r9,nap_save_hid1@l(r9)
-	mtspr	SPRN_HID1, r9
-END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
  	b	transfer_to_handler_cont

  	.data

  _GLOBAL(nap_save_msscr0)
  	.space	4*NR_CPUS
-
-_GLOBAL(nap_save_hid1)
-	.space	4*NR_CPUS
-
-_GLOBAL(powersave_lowspeed)
-	.long	0
Index: arch/powerpc/platforms/powermac/feature.c
===================================================================
--- arch/powerpc/platforms/powermac/feature.c.orig	2008-08-13 00:54:02.000000000 -0700
+++ arch/powerpc/platforms/powermac/feature.c	2008-08-14 02:44:30.000000000 -0700
@@ -48,10 +48,6 @@
  #define DBG(fmt...)
  #endif

-#ifdef CONFIG_6xx
-extern int powersave_lowspeed;
-#endif
-
  extern int powersave_nap;
  extern struct device_node *k2_skiplist[2];

@@ -2534,11 +2530,6 @@ found:
  		break;
  	}

-	/* On CPUs that support it (750FX), lowspeed by default during
-	 * NAP mode
-	 */
-	powersave_lowspeed = 1;
-
  #else /* CONFIG_POWER4 */
  	powersave_nap = 1;
  #endif  /* CONFIG_POWER4 */
Index: arch/powerpc/platforms/Kconfig
===================================================================
--- arch/powerpc/platforms/Kconfig.orig	2008-08-13 02:19:26.000000000 -0700
+++ arch/powerpc/platforms/Kconfig	2008-08-14 02:44:30.000000000 -0700
@@ -174,7 +174,7 @@ config GENERIC_IOMAP
  	bool
  	default n

-source "drivers/cpufreq/Kconfig"
+source "arch/powerpc/kernel/cpu/cpufreq/Kconfig"

  menu "CPU Frequency drivers"
  	depends on CPU_FREQ
Index: arch/powerpc/platforms/Kconfig.cputype
===================================================================
--- arch/powerpc/platforms/Kconfig.cputype.orig	2008-08-13 02:19:26.000000000 -0700
+++ arch/powerpc/platforms/Kconfig.cputype	2008-08-14 02:44:30.000000000 -0700
@@ -234,4 +234,34 @@ config NOT_COHERENT_CACHE
  config CHECK_CACHE_COHERENCY
  	bool

+config PPC_750GX_DUAL_PLL_IF
+	tristate 'Add interface for 750GX PLL' if 6xx
+	---help---
+	  This adds code to provide control of the pll config register in IBM
+	  750GX (and FX?). This is also needed by the cpufreq driver for the
+	  750GX. At least one of the interfaces below must be selected.
+
+	  If in doubt, say N here.
+
+config PPC_750GX_DUAL_PLL_IF_HRTIMER
+	bool "Use HRtimer for PLL lock delay"
+	depends on PPC_750GX_DUAL_PLL_IF
+	default n
+	help
+	  Uses HRtimers for lower latency on PLL locks.
+
+config PPC_750GX_DUAL_PLL_IF_CPU_FREQ
+	bool "Include CPUFreq interface"
+	depends on PPC_750GX_DUAL_PLL_IF
+	default n
+	help
+	  Include code to provide CPUFreq driver API.
+
+config PPC_750GX_DUAL_PLL_IF_SYSFS
+	bool "Include sysfs interface"
+	depends on PPC_750GX_DUAL_PLL_IF
+	default n
+	help
+	  Include code to provide sysfs interface.
+
  endmenu
Index: include/asm-powerpc/cputable.h
===================================================================
--- include/asm-powerpc/cputable.h.orig	2008-08-13 00:56:46.000000000 -0700
+++ include/asm-powerpc/cputable.h	2008-08-14 02:44:30.000000000 -0700
@@ -263,7 +263,8 @@ extern void do_feature_fixups(unsigned l
  #define CPU_FTRS_750FX2	(CPU_FTRS_750 | CPU_FTR_NO_DPM)
  #define CPU_FTRS_750FX	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
  		CPU_FTR_HAS_HIGH_BATS)
-#define CPU_FTRS_750GX	(CPU_FTRS_750FX)
+#define CPU_FTRS_750GX	(CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \
+		CPU_FTR_HAS_HIGH_BATS)
  #define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | \
  	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
  	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \

^ permalink raw reply

* Re: Efficient memcpy()/memmove() for G2/G3 cores...
From: Matt Sealey @ 2008-08-25 11:00 UTC (permalink / raw)
  To: David Jander; +Cc: linuxppc-dev
In-Reply-To: <200808251131.02071.david.jander@protonic.nl>

Hi David,

The focus has definitely been on VMX but that's not to say lower power
processors were forgotten :)

Gunnar von Boehn did some benchmarking with an assembly optimized routine,
for Cell, 603e and so on (basically the whole gamut from embedded up to
sever class IBM chips) and got some pretty good results;

http://www.powerdeveloper.org/forums/viewtopic.php?t=1426

It is definitely something that needs fixing. The generic routine in glibc
just copies words with no benefit of knowing the cache line size or any
cache block buffers in the chip, and certainly no use of cache control or
data streaming on higher end chips.

With knowledge of the right way to unroll the loops, how many copies to
do at once to try and get a burst, reducing cache usage etc. you can get
very impressive performance (as you can see, 50MB up to 78MB at the
smallest size, the basic improvement is 2x performance).

I hope that helps you a little bit. Gunnar posted code to this list not
long after. I have a copy of the "e300 optimized" routine but I thought
best he should post it here, than myself.

There is a lot of scope I think for optimizing several points (glibc,
kernel, some applications) for embedded processors which nobody is
really taking on. But, not many people want to do this kind of work..

-- 
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations

David Jander wrote:
> Hello,
> 
> I was wondering if there is a good replacement for GLibc memcpy() functions, 
> that doesn't have horrendous performance on embedded PowerPC processors (such 
> as Glibc has).
> 
> I did some simple benchmarks with this implementation on our custom MPC5121 
> based board (Freescale e300 core, something like a PPC603e, G2, without VMX):
> 
> ...
> unsigned long int a,b,c,d;
> unsigned long int a1,b1,c1,d1;
> ...
> while (len >= 32)
> {
>     a =  plSrc[0];
>     b =  plSrc[1];
>     c =  plSrc[2];
>     d =  plSrc[3];
>     a1 = plSrc[4];
>     b1 = plSrc[5];
>     c1 = plSrc[6];
>     d1 = plSrc[7];
>     plSrc += 8;
>     plDst[0] = a;
>     plDst[1] = b;
>     plDst[2] = c;
>     plDst[3] = d;
>     plDst[4] = a1;
>     plDst[5] = b1;
>     plDst[6] = c1;
>     plDst[7] = d1;
>     plDst += 8;
>     len -= 32;
> }
> ...
> 
> And the results are more than telling.... by linking this with LD_PRELOAD, 
> some programs get an enourmous performance boost.
> For example a small test program that copies frames into video memory (just 
> RAM) improved throughput from 13.2 MiB/s to 69.5 MiB/s.
> I have googled for this issue, but most optimized versions of memcpy() and 
> friends seem to focus on AltiVec/VMX, which this processor does not have.
> Now I am certain that most of the G2/G3 users on this list _must_ have a 
> better solution for this. Any suggestions?
> 
> Btw, the tests are done on Ubuntu/PowerPC 7.10, don't know if that matters 
> though...
> 
> Best regards,
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox