LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: linux-next: build failure after merge of the final tree (ubi tree related)
From: Artem Bityutskiy @ 2011-03-16 11:48 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linux-next, Paul Mackerras, linux-kernel, linuxppc-dev
In-Reply-To: <20110316175041.67c4f371.sfr@canb.auug.org.au>

On Wed, 2011-03-16 at 17:50 +1100, Stephen Rothwell wrote:
> After merging the final tree, today's linux-next build (powerpc
> allyesconfig) failed like this:
> 
> drivers/mtd/ubi/io.c: In function 'ubi_dbg_check_write':
> drivers/mtd/ubi/io.c:1348: error: 'PAGE_KERNEL' undeclared (first use in this function)
> drivers/mtd/ubi/io.c: In function 'ubi_dbg_check_all_ff':
> drivers/mtd/ubi/io.c:1412: error: 'PAGE_KERNEL' undeclared (first use in this function)
> 
> Caused by commit 823ed5091113 ("UBI: allocate write checking buffer on demand").
> 
> I don't know how to fix this, so I have left it for today.

Fixed, sorry for the hassle and thank you!

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

^ permalink raw reply

* Powerpc gcc error for mpc8315erdb board
From: Vasanth Ragavendran @ 2011-03-16 12:25 UTC (permalink / raw)
  To: linuxppc-dev


Hi

I am facing a problem with my powerpc gcc. Actually i am using a ltib to
configure the kernel and the file system for my mpc8315erdb board from linux
2.6 host machine. and the installation of kernel and filesystem is
successful. i don't have "make" installed in the board and i wanted to
compile cgic library  (an ANSI C library for cgi) for the board, hence i
compiled it on the linux host machine itself but instead of using gcc i used
powerpc-e300c3-linux-gnu-gcc which corresponds to the gcc of the mpc8315erdb
board. however i get an error saying 

powerpc-e300c3-linux-gnu-gcc: error trying to exec 'cc1': execvp: No such
file or directory

however powerpc-e300c3-linux-gnu-gcc is present in /usr/local/bin on the
linux host machine and this directory is part of the path. so powerpc does
exist on the host machine. 

if the error comes on the host linux then i would look for
/usr/libexec/gcc/i486-slackware-linux/4.2.4/ but how do i rectify in this
scenario. the makefile for the cgic was modified according to the powerpc
architecture and i am attaching here. Kindly help! plz!
http://old.nabble.com/file/p31162962/Makefile Makefile 
-- 
View this message in context: http://old.nabble.com/Powerpc-gcc-error-for-mpc8315erdb-board-tp31162962p31162962.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* Powerpc gcc error for mpc8315erdb board
From: Vasanth Ragavendran @ 2011-03-16 12:27 UTC (permalink / raw)
  To: linuxppc-dev


Hi

I am facing a problem with my powerpc gcc. Actually i am using a ltib to
configure the kernel and the file system for my mpc8315erdb board from linux
2.6 host machine. and the installation of kernel and filesystem is
successful. i don't have "make" installed in the board and i wanted to
compile cgic library  (an ANSI C library for cgi) for the board, hence i
compiled it on the linux host machine itself but instead of using gcc i used
powerpc-e300c3-linux-gnu-gcc which corresponds to the gcc of the mpc8315erdb
board. however i get an error saying

powerpc-e300c3-linux-gnu-gcc: error trying to exec 'cc1': execvp: No such
file or directory

however powerpc-e300c3-linux-gnu-gcc is present in /usr/local/bin on the
linux host machine and this directory is part of the path. so powerpc does
exist on the host machine.

if the error comes on the host linux then i would look for
/usr/libexec/gcc/i486-slackware-linux/4.2.4/ but how do i rectify in this
scenario. the makefile for the cgic was modified according to the powerpc
architecture and i am attaching here below. Kindly help! plz!

http://old.nabble.com/file/p31162979/Makefile Makefile 


-- 
View this message in context: http://old.nabble.com/Powerpc-gcc-error-for-mpc8315erdb-board-tp31162979p31162979.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH] powerpc: perf: Handle events that raise an exception without overflowing
From: Ingo Molnar @ 2011-03-16 12:50 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linuxppc-dev, paulus, a.p.zijlstra, acme
In-Reply-To: <20110309143842.6c22845e@kryten>


* Anton Blanchard <anton@samba.org> wrote:

> 
> Events on POWER7 can roll back if a speculative event doesn't
> eventually complete. Unfortunately in some rare cases they will
> raise a performance monitor exception. We need to catch this to
> ensure we reset the PMC. In all cases the PMC will be 256 or less
> cycles from overflow.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>
> Cc: stable@kernel.org
> ---
> 
> I would prefer not to add the PVR check, but I think we want to limit
> this workaround to POWER7. Would a cpu feature be preferable?

There was no objection from the PowerPC folks so i'll send this fix Linuswards, ok?

Thanks,

	Ingo

^ permalink raw reply

* [PATCH v2] powerpc/ptrace: remove BUG_ON when full register set not available
From: Michael Wolf @ 2011-03-16 13:37 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey, anton

In some cases during a threaded core dump not all 
the threads will have a full register set.  This
will cause problems when the sigkill is sent to
the thread.  To solve this problem a poison value
(0xdeadbeef) will be placed in the buffer in place 
of the actual register values.  This will affect
gpr14 to gpr31.

Signed-off-by: Mike Wolf <mjw@linux.vnet.ibm.com>

----------
--- linux-2.6.32-71.el6.ppc64.orig/arch/powerpc/include/asm/ptrace.h	2010-08-31 23:56:50.000000000 -0500
+++ linux-2.6.32-71.el6.ppc64/arch/powerpc/include/asm/ptrace.h	2011-03-14 11:43:33.176667099 -0500
@@ -123,8 +123,14 @@ extern int ptrace_put_reg(struct task_st
 #define TRAP(regs)		((regs)->trap & ~0xF)
 #ifdef __powerpc64__
 #define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1)
+#define PARTIAL_REG_FILL	0xdeadbeefdeadbeefUL
+#define PARTIAL_REG_START	14
+#define PARTIAL_REG_END		31
 #else
 #define CHECK_FULL_REGS(regs)						      \
+#define PARTIAL_REG_FILL	0xdeadbeef
+#define PARTIAL_REG_START	14
+#define PARTIAL_REG_END		31
 do {									      \
 	if ((regs)->trap & 1)						      \
 		printk(KERN_CRIT "%s: partial register set\n", __func__); \
--- linux-2.6.32-71.el6.ppc64.orig/arch/powerpc/kernel/ptrace.c	2009-12-02 21:51:21.000000000 -0600
+++ linux-2.6.32-71.el6.ppc64/arch/powerpc/kernel/ptrace.c	2011-03-14 13:01:51.955586126 -0500
@@ -125,11 +125,16 @@ static int gpr_get(struct task_struct *t
 		   void *kbuf, void __user *ubuf)
 {
 	int ret;
+	int partial_reg;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs))
+	   /* We have a partial register set.  Fill 14-31 with bogus values */
+	   for(partial_reg=PARTIAL_REG_START;partial_reg <= PARTIAL_REG_END;
+		partial_reg++)
+           	target->thread.regs->gpr[partial_reg] = PARTIAL_REG_FILL; 
 
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				  target->thread.regs,
@@ -536,11 +541,16 @@ static int gpr32_get(struct task_struct 
 	compat_ulong_t *k = kbuf;
 	compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
+	int partial_reg;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs))
+	   /* We have a partial register set.  Fill 14-31 with bogus values */
+	   for(partial_reg=PARTIAL_REG_START;partial_reg <= PARTIAL_REG_END;
+		partial_reg++)
+           	target->thread.regs->gpr[partial_reg] = PARTIAL_REG_FILL; 
 
 	pos /= sizeof(reg);
 	count /= sizeof(reg);

^ permalink raw reply

* Re: [PATCH V12 0/4] ptp: IEEE 1588 hardware clock support
From: Richard Cochran @ 2011-03-16 14:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: Thomas Gleixner, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
	linux-api, devicetree-discuss, Russell King, Paul Mackerras,
	John Stultz, linux-arm-kernel, netdev, Mike Frysinger,
	Christoph Lameter, linuxppc-dev, David Miller, Alan Cox,
	Krzysztof Halasa
In-Reply-To: <cover.1298878618.git.richard.cochran@omicron.at>

On Mon, Feb 28, 2011 at 08:57:03AM +0100, Richard Cochran wrote:
> * PHC Patch ChangeLog
> ** v12
> *** gianfar_ptp
>    - fixed up device tree
>    - inlined the header file
>    - use platform_ calls instead of deprecated of_ calls
>    - removed static global single instance
>    - removed John Stultz's ack from this patch

@Thomas and John:

Can I get your acks on the remaining patches?

Can this be merged for 2.6.39?

Thanks,

Richard

^ permalink raw reply

* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Paul Mundt @ 2011-03-16 15:36 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
	linux-kernel, Ben Dooks, Randy Dunlap, linuxppc-dev,
	Wolfgang Denk
In-Reply-To: <4D7F14B0.1030008@denx.de>

On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
> > 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
> > 
> >  Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++
> >  drivers/mfd/sm501.c                          |    9 +++++-
> >  drivers/video/sm501fb.c                      |   42 ++++++++++++++++++++++++--
> >  3 files changed, 81 insertions(+), 4 deletions(-)
> >  create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
> 
> This patchset is pending know for a while. I got Acked by from
> 
> Samuel Ortiz for the mfd part, see here:
> 
> http://www.spinics.net/lists/linux-fbdev/msg02550.html
> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
> 
> and for the DTS part from Benjamin Herrenschmidt:
> 
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
> 
> Are there some more issues?
> 
Not that I remember off the top of my head, but I think they've been lost
in my backlog. Could you re-send the current series with the appropriate
acked-bys? If there's nothing else obvious outstanding I'll roll them in.

^ permalink raw reply

* Re: [PATCH] powerpc: perf: Handle events that raise an exception without overflowing
From: Benjamin Herrenschmidt @ 2011-03-16 20:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linuxppc-dev, paulus, Anton Blanchard, acme, a.p.zijlstra
In-Reply-To: <20110316125053.GA7387@elte.hu>

On Wed, 2011-03-16 at 13:50 +0100, Ingo Molnar wrote:
> * Anton Blanchard <anton@samba.org> wrote:
> 
> > 
> > Events on POWER7 can roll back if a speculative event doesn't
> > eventually complete. Unfortunately in some rare cases they will
> > raise a performance monitor exception. We need to catch this to
> > ensure we reset the PMC. In all cases the PMC will be 256 or less
> > cycles from overflow.
> > 
> > Signed-off-by: Anton Blanchard <anton@samba.org>
> > Cc: stable@kernel.org
> > ---
> > 
> > I would prefer not to add the PVR check, but I think we want to limit
> > this workaround to POWER7. Would a cpu feature be preferable?
> 
> There was no objection from the PowerPC folks so i'll send this fix Linuswards, ok?

Ah yes.

Ack.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH v2 21/28] powerpc: sysdev/mpc8xxx_gpio irq_data conversion.
From: Peter Korsgaard @ 2011-03-16 21:25 UTC (permalink / raw)
  To: Lennert Buytenhek; +Cc: Thomas Gleixner, linuxppc-dev
In-Reply-To: <20110309082658.GR16649@mail.wantstofly.org>

>>>>> "Lennert" == Lennert Buytenhek <buytenh@wantstofly.org> writes:

 Lennert> Signed-off-by: Lennert Buytenhek <buytenh@secretlab.ca>
 Lennert> ---
 Lennert> v2: get_irq_chip_data(d->irq) => irq_data_get_irq_chip_data(d)

Acked-by: Peter Korsgaard <jacmet@sunsite.dk>

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* [PATCH 1/4] powerpc/mpc512x: Add initial support for TWR-MPC5125
From: Vladimir Ermakov @ 2011-03-16 23:29 UTC (permalink / raw)
  To: linuxppc-dev

Adds Freescale TWR-MPC5125 device tree and platform code.
    
Currently following is supported:
 - NAND
 - FEC1 and FEC2
 - RTC
 - PSC UART

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---

diff --git a/arch/powerpc/boot/dts/mpc5125twr.dts b/arch/powerpc/boot/dts/mpc5125twr.dts
new file mode 100644
index 0000000..54f568f
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc5125twr.dts
@@ -0,0 +1,394 @@
+/*
+ * STx/Freescale ADS5125 MPC5125 silicon
+ *
+ * Copyright (C) 2009 Freescale Semiconductor Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "mpc5125ads";
+	compatible = "fsl,mpc5125ads";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5125@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <0x20>;	// 32 bytes
+			i-cache-line-size = <0x20>;	// 32 bytes
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			timebase-frequency = <49500000>;// 49.5 MHz (csb/4)
+			bus-frequency = <198000000>;	// 198 MHz csb bus
+			clock-frequency = <396000000>;	// 396 MHz ppc core
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;	// 256MB at 0
+	};
+
+	sram@30000000 {
+		compatible = "fsl,mpc5121-sram";
+		reg = <0x30000000 0x08000>;		// 32K at 0x30000000
+	};
+
+	nfc@40000000 {
+		compatible = "fsl,mpc5125-nfc";
+		reg = <0x40000000 0x100000>;	// 1M at 0x40000000
+		interrupts = <6 0x8>;
+		interrupt-parent = < &ipic >;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		bank-width = <1>;
+		write-size = <4096>;
+		spare-size = <128>;
+		chips = <1>;
+		// NOTE: partition map different than in BSP
+		nand-spl@0 {
+			label = "loader";
+			reg = <0x00000000 0x00100000>;
+			read-only;
+		};
+		uboot@100000 {
+			label = "uboot";
+			reg = <0x00100000 0x00100000>;
+			read-only;
+		};
+		uboot-env@200000 {
+			label = "uboot-env";
+			reg = <0x00200000 0x00100000>;
+			read-only;
+		};
+		kernel300000 {
+			label = "kernel";
+			reg = <0x00300000 0x00800000>;
+		};
+		device-tree00000 {
+			label = "device-tree";
+			reg = <0x00b00000 0x00100000>;
+		};
+		ramboot-rootfs@c00000 {
+			label = "ramboot-rootfs";
+			reg = <0x00c00000 0x00800000>;
+		};
+		rootfs@1400000 {
+			label = "rootfs";
+			reg = <0x01400000 0x01400000>;
+		};
+		user@2800000 {
+			label = "user";
+			reg = <0x02800000 0x01400000>;
+		};
+		SRAM@4200000 {
+			label = "SRAM"; // NVRAM emul
+			reg = <0x04200000 0x01400000>;
+		};
+		prom@5600000 {
+			label = "prom";
+			reg = <0x05600000 0x01400000>;
+		};
+		//data@2800000 {
+		//	label = "data";
+		//	reg = <0x28000000 0xeac00000>;
+		//};
+	};
+
+	soc@80000000 {
+		compatible = "fsl,mpc5121-immr";
+		device_type = "soc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		ranges = <0x0 0x80000000 0x400000>;
+		reg = <0x80000000 0x400000>;
+		bus-frequency = <66000000>;	// 66 MHz ips bus
+
+
+		// IPIC
+		// interrupts cell = <intr #, sense>
+		// sense values match linux IORESOURCE_IRQ_* defines:
+		// sense == 8: Level, low assertion
+		// sense == 2: Edge, high-to-low change
+		//
+		ipic: interrupt-controller@c00 {
+			compatible = "fsl,mpc5121-ipic", "fsl,ipic";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0xc00 0x100>;
+		};
+
+		rtc@a00 {	// Real time clock
+			compatible = "fsl,mpc5121-rtc";
+			reg = <0xa00 0x100>;
+			interrupts = <79 0x8 80 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		reset@e00 {	// Reset module
+			compatible = "fsl,mpc5121-reset";
+			reg = <0xe00 0x100>;
+		};
+
+		clock@f00 {	// Clock control
+			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
+			reg = <0xf00 0x100>;
+		};
+
+		pmc@1000{  // Power Management Controller
+			compatible = "fsl,mpc5121-pmc";
+			reg = <0x1000 0x100>;
+			interrupts = <83 0x2>;
+			interrupt-parent = < &ipic >;
+		};
+
+		gpio@1100 {
+			compatible = "fsl,mpc5125-gpio";
+			cell-index = <0>;
+			reg = <0x1100 0x080>;
+			interrupts = <78 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		gpio@1180 {
+			compatible = "fsl,mpc5125-gpio1";
+			cell-index = <1>;
+			reg = <0x1180 0x080>;
+			interrupts = <78 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		can@1300 { // CAN rev.2
+			compatible = "fsl,mpc5121-mscan";
+			cell-index = <0>;
+			interrupts = <12 0x8>;
+			interrupt-parent = < &ipic >;
+			reg = <0x1300 0x80>;
+		};
+
+		can@1380 {
+			compatible = "fsl,mpc5121-mscan";
+			cell-index = <1>;
+			interrupts = <13 0x8>;
+			interrupt-parent = < &ipic >;
+			reg = <0x1380 0x80>;
+		};
+
+		sdhc@1500 {
+			compatible = "fsl,mpc5125-sdhc";
+			interrupts = <8 0x8>;
+			interrupt-parent = < &ipic >;
+			reg = <0x1500 0x100>;
+		};
+
+		i2c@1700 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <0>;
+			reg = <0x1700 0x20>;
+			interrupts = <0x9 0x8>;
+			interrupt-parent = < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2c@1720 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <1>;
+			reg = <0x1720 0x20>;
+			interrupts = <0xa 0x8>;
+			interrupt-parent = < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2c@1740 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <2>;
+			reg = <0x1740 0x20>;
+			interrupts = <0xb 0x8>;
+			interrupt-parent = < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2ccontrol@1760 {
+			compatible = "fsl,mpc5121-i2c-ctrl";
+			reg = <0x1760 0x8>;
+		};
+
+		//diu@2100 {
+		//	device_type = "display";
+		//	compatible = "fsl-diu";
+		//	reg = <0x2100 0x100>;
+		//	interrupts = <64 0x8>;
+		//	interrupt-parent = < &ipic >;
+		//};
+
+		// MPC5125e has two more CAN ports
+		// but they are not used on ADS5125
+		//can@2300 {
+		//	compatible = "fsl,mpc5121-mscan";
+		//	cell-index = <2>;
+		//	interrupts = <90 0x8>;
+		//	interrupt-parent = < &ipic >;
+		//	reg = <0x2300 0x80>;
+		//};
+
+		//can@2380 {
+		//	compatible = "fsl,mpc5121-mscan";
+		//	cell-index = <3>;
+		//	interrupts = <91 0x8>;
+		//	interrupt-parent = < &ipic >;
+		//	reg = <0x2380 0x80>;
+		//};
+
+		mdio@2800 {
+			device_type = "mdio";
+			compatible = "fsl,mpc5121-fec-mdio";
+			reg = <0x2800 0x800>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy0: ethernet-phy@0 {
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@2800 {
+			device_type = "network";
+			compatible = "fsl,mpc5121-fec";
+			reg = <0x2800 0x800>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <4 0x8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy0 >;
+		};
+
+		// USB ULPI1
+		//usb@3000 {
+		//	device_type = "usb";
+		//	compatible = "fsl-usb2-dr";
+		//	reg = <0x3000 0x400>;
+		//	#address-cells = <1>;
+		//	#size-cells = <0>;
+		//	interrupt-parent = < &ipic >;
+		//	interrupts = <43 0x8>;
+		//	dr_mode = "host";
+		//	phy_type = "ulpi";
+		//	big-endian-regs;
+		//};
+
+		// USB ULPI2
+		//usb@4000 {
+		//	device_type = "usb";
+		//	compatible = "fsl-usb2-dr";
+		//	reg = <0x4000 0x400>;
+		//	#address-cells = <1>;
+		//	#size-cells = <0>;
+		//	interrupt-parent = < &ipic >;
+		//	interrupts = <44 0x8>;
+		//	dr_mode = "otg";
+		//	phy_type = "ulpi";
+		//	big-endian-regs;
+		//};
+
+		mdio@4800 {
+			device_type = "mdio";
+			compatible = "fsl,mpc5121-fec-mdio";
+			reg = <0x4800 0x800>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy1: ethernet-phy@0 {
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@4800 {
+			device_type = "network";
+			compatible = "fsl,mpc5121-fec";
+			reg = <0x4800 0x800>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <5 0x8>;
+			interrupt-parent = < &ipic >;
+			phy-handle = < &phy1 >;
+		};
+
+		// IO control
+		ioctl@a000 {
+			compatible = "fsl,mpc5125-ioctl";
+			reg = <0xA000 0x1000>;
+		};
+
+		// PSC0 in ac97 mode
+		//ac97@11000 {
+		//	device_type = "sound";
+		//	compatible = "fsl,mpc5125-psc-ac97", "fsl,mpc5125-psc";
+		//	cell-index = <0>;
+		//	reg = <0x11000 0x100>;
+		//	interrupts = <40 0x8>;
+		//	interrupt-parent = < &ipic >;
+		//	fsl,mode = "ac97-slave";
+		//	rx-fifo-size = <384>;
+		//	tx-fifo-size = <384>;
+		//};
+
+		// 5125 PSCs are not 52xx or 5121 PSC compatible
+		// PSC1 uart0 aka ttyPSC0
+		serial@11100 {
+			device_type = "serial";
+			compatible = "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number = <0>;
+			cell-index = <1>;
+			reg = <0x11100 0x100>;
+			interrupts = <40 0x8 71 0x8>;
+			interrupt-parent = < &ipic >;
+			fsl,rx-fifo-size = <16>;
+			fsl,tx-fifo-size = <16>;
+			nodcd;
+		};
+
+		// PSC9 uart1 aka ttyPSC1
+		serial@11900 {
+			device_type = "serial";
+			compatible = "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number = <1>;
+			cell-index = <9>;
+			reg = <0x11900 0x100>;
+			interrupts = <40 0x8 32 0x8>;
+			interrupt-parent = < &ipic >;
+			fsl,rx-fifo-size = <16>;
+			fsl,tx-fifo-size = <16>;
+			nodcd;
+		};
+
+		pscfifo@11f00 {
+			compatible = "fsl,mpc5121-psc-fifo";
+			reg = <0x11f00 0x100>;
+			interrupts = <40 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+
+		dma@14000 {
+			compatible = "fsl,mpc5121-dma"; // old name: "mpc512x-dma2"
+			reg = <0x14000 0x1800>;
+			interrupts = <65 0x8>;
+			interrupt-parent = < &ipic >;
+		};
+	};
+};
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index 27b0651..0dde4b0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -26,6 +26,20 @@ config MPC5121_GENERIC
 	  Compatible boards include:  Protonic LVT base boards (ZANMCU
 	  and VICVT2).
 
+config PPC_MPC5125
+	bool "Generic support for MPC5125 based boards"
+	depends on PPC_MPC512x
+	select DEFAULT_UIMAGE
+	select PPC_INDIRECT_PCI
+	default n
+
+config MPC5125_TWR
+	bool "Freescale MPC5125 Tower system"
+	depends on PPC_MPC512x
+	select PPC_MPC5125
+	help
+	  This option enables support for the MPC5125 TWR board.
+
 config PDM360NG
 	bool "ifm PDM360NG board"
 	depends on PPC_MPC512x
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 4efc1c4..5c17561 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -5,3 +5,4 @@ obj-y				+= clock.o mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC5121_GENERIC)	+= mpc5121_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
+obj-$(CONFIG_MPC5125_TWR)	+= mpc5125_twr.o
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index 3dc2a8d..962c0ba 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -669,6 +669,13 @@ static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
 	clk->rate = mclk_src / mclk_div;
 }
 
+
+#ifdef CONFIG_PPC_MPC5125
+#define PSC_PREFIX "mpc5125"
+#else
+#define PSC_PREFIX "mpc5121"
+#endif
+
 /*
  * Find all psc nodes in device tree and assign a clock
  * with name "psc%d_mclk" and dev pointing at the device
@@ -680,7 +687,7 @@ static void psc_clks_init(void)
 	const u32 *cell_index;
 	struct platform_device *ofdev;
 
-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	for_each_compatible_node(np, NULL, "fsl," PSC_PREFIX "-psc") {
 		cell_index = of_get_property(np, "cell-index", NULL);
 		if (cell_index) {
 			int pscnum = *cell_index;
diff --git a/arch/powerpc/platforms/512x/mpc5125_twr.c b/arch/powerpc/platforms/512x/mpc5125_twr.c
new file mode 100644
index 0000000..c35b0d8
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc5125_twr.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2010 LimePC Multimedia Technologies Co., Limited
+ * Copyright (C) 2011 Vladimir Ermakov <vooon341@gmail.com>
+ *
+ * Based on original Freescale Semiconductor BSP
+ * written by Cloudy Chen <chen_yunsong@mtcera.com>
+ *
+ * MPC5125 Tower board setup
+ *
+ * This 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/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include <linux/bootmem.h>
+#include <asm/rheap.h>
+
+#include "mpc512x.h"
+
+static void mpc5125_psc_iopad_init(void __iomem *ioctl, char *name)
+{
+	struct device_node *np;
+	const u32 *cell_index;
+	char *default_psc = "fsl,mpc5125-psc";
+	char *psc_name;
+
+	if (name)
+		psc_name = name;
+	else
+		psc_name = default_psc;
+
+	for_each_compatible_node(np, NULL, psc_name) {
+		cell_index = of_get_property(np, "cell-index", NULL);
+		if (cell_index) {
+			u8 __iomem *pscioctl;
+			int psc_num = *cell_index;
+			if (psc_num > 1)
+				continue;
+
+			pscioctl = ioctl + 0x76 + 5 * psc_num;
+			out_8(pscioctl++, 0x07);
+			out_8(pscioctl++, 0x03);
+			out_8(pscioctl++, 0x03);
+			out_8(pscioctl++, 0x03);
+			out_8(pscioctl++, 0x03);
+		}
+	}
+}
+
+static void mpc5125_fec2_usb_io_init(void __iomem *ioctl, int isusb)
+{
+#define FEC2_INIT 0
+#define USB_INIT  1
+	int i;
+	const u8 offset[12] = {
+		0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+		0x6b, 0x6c, 0x6d, 0x6e
+	};
+	const u8 init[2][12] = {
+		[FEC2_INIT] = {
+			0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43,
+			0x43, 0x43, 0x43, 0x43},
+		[USB_INIT] = {
+			0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+			0x03, 0x03, 0x03, 0x03}
+	};
+
+	isusb = (isusb) ? USB_INIT : FEC2_INIT;
+	for (i = 0; i < ARRAY_SIZE(offset); i++)
+		out_8(ioctl + offset[i], init[isusb][i]);
+#undef FEC2_INIT
+#undef USB_INIT
+}
+
+static void __init mpc5125_board_setup(void)
+{
+	struct device_node *np;
+
+	/*
+	 * io pad config
+	 */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5125-ioctl");
+	if (np) {
+		void __iomem *ioctl = of_iomap(np, 0);
+
+		mpc5125_psc_iopad_init(ioctl, NULL);
+		mpc5125_fec2_usb_io_init(ioctl, 0);
+
+		of_node_put(np);
+		iounmap(ioctl);
+	}
+}
+
+static void __init mpc5125_ads_setup_arch(void)
+{
+	printk(KERN_INFO "MPC5125 ADS board from Freescale Semiconductor\n");
+
+	mpc5125_board_setup();
+}
+
+static struct of_device_id __initdata of_bus_ids[] = {
+	{ .name = "soc", },
+	{},
+};
+
+static void __init mpc5125_ads_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
+		printk(KERN_ERR __FILE__ ": "
+			"Error while probing of_platform bus\n");
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5125-nfc");
+	if (np) {
+		of_platform_device_create(np, NULL, NULL);
+		of_node_put(np);
+	}
+}
+
+static void __init mpc5125_ads_init(void)
+{
+	mpc5125_ads_declare_of_platform_devices();
+	mpc5121_clk_init();
+	mpc512x_restart_init();
+	mpc512x_psc_fifo_init("fsl,mpc5125-psc");
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc5125_ads_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,mpc5125ads");
+}
+
+define_machine(mpc5125_ads) {
+	.name			= "MPC5125 ADS",
+	.probe			= mpc5125_ads_probe,
+	.setup_arch		= mpc5125_ads_setup_arch,
+	.init			= mpc5125_ads_init,
+	.init_IRQ		= mpc512x_init_IRQ,
+	.get_irq		= ipic_get_irq,
+	.calibrate_decr		= generic_calibrate_decr,
+	.restart		= mpc512x_restart,
+};
diff --git a/arch/powerpc/platforms/512x/mpc512x.h b/arch/powerpc/platforms/512x/mpc512x.h
index 1ab6d11..70c66c6 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -13,8 +13,10 @@
 #define __MPC512X_H__
 extern void __init mpc512x_init_IRQ(void);
 extern void __init mpc512x_init(void);
+extern void __init mpc512x_restart_init(void);
 extern int __init mpc5121_clk_init(void);
-void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_psc_fifo_init(char *psc_name);
 extern void mpc512x_restart(char *cmd);
 extern void mpc512x_init_diu(void);
 extern void mpc512x_setup_diu(void);
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index e41ebbd..411fc9d 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -32,7 +32,7 @@
 
 static struct mpc512x_reset_module __iomem *reset_module_base;
 
-static void __init mpc512x_restart_init(void)
+void __init mpc512x_restart_init(void)
 {
 	struct device_node *np;
 
@@ -401,15 +401,19 @@ static unsigned int __init get_fifo_size(struct device_node *np,
 		    ((u32)(_base) + sizeof(struct mpc52xx_psc)))
 
 /* Init PSC FIFO space for TX and RX slices */
-void __init mpc512x_psc_fifo_init(void)
+void __init mpc512x_psc_fifo_init(char *psc_name)
 {
 	struct device_node *np;
 	void __iomem *psc;
 	unsigned int tx_fifo_size;
 	unsigned int rx_fifo_size;
+	char *default_psc = "fsl,mpc5121-psc";
 	int fifobase = 0; /* current fifo address in 32 bit words */
 
-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	if (!psc_name)
+		psc_name = default_psc;
+
+	for_each_compatible_node(np, NULL, psc_name) {
 		tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
 		rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");
 
@@ -461,5 +465,5 @@ void __init mpc512x_init(void)
 	mpc512x_declare_of_platform_devices();
 	mpc5121_clk_init();
 	mpc512x_restart_init();
-	mpc512x_psc_fifo_init();
+	mpc512x_psc_fifo_init(NULL);
 }

^ permalink raw reply related

* Re: any chance to use a modern linux kernel on Pegasos1 G3 ?
From: nello martuscielli @ 2011-03-16 23:39 UTC (permalink / raw)
  To: Gerhard Pircher; +Cc: linuxppc-dev, acrux_it
In-Reply-To: <20110315171448.100300@gmx.net>

hi all,

here instead the log from serial debug console booting the last
working kernel i.e. linux-2.16.62 compiled with arch=ppc .


[...]
do_load: dev="/ide/disk:0" dlen=11 args="CRUX root=/dev/hdb
video=radeonfb:800x600" alen=41
do_load: alstr=""
try_load: dev="/ide/disk:0" dlen=11 args="CRUX root=/dev/hdb
video=radeonfb:800x600" alen=41
create_well_formed_chain: pkg=0xFD57D58 parent=0xFD53B90
currpkg=0xFD53B90 inst=0xFE6EE50
        pkg=/pci@80000000 parent=/ currpkg=/ currinst=/
create_well_formed_chain: pkg=0xFD53B90 parent=0x0 currpkg=0xFD53B90
inst=0xFE6EE50
        pkg=/ parent= currpkg=/ currinst=/
        pkg=0xFD57D58:/pci@80000000 parent=0xFE6EE50:/
inst=0xFE6EEA8:/pci@80000000 instparent=0xFE6EE50
ata_disk_open: pkg=0xFD5B870 parent=0xFD5B2C8
ata_disk_open: CTLR=0x0 ID=0x0
ata_disk_open: args="0"
deblocker open
ata_disk_max_transfer: 512
deblocker open: block-size=0x200 max-transfer=0x200
deblocker open: return 0
open-package: ret=0:no error r=-1
ata_disk_open: $open-package deblocker ret=0
ata_disk_open: deblocker=0xFE6EFC8
disk-label open
disk-label open: self=0xFE702B0 s->buf=0xFE71000
disk-label open: return 0
open-package: ret=0:no error r=-1
ata_disk_open: $open-package disk-label ret=0
ata_disk_open: disklabel=0xFE70258
disk-label load: addr=0x400000 loadargs=CRUX root=/dev/hdb
video=radeonfb:800x600 args=0,CRUX root=/dev/hdb
video=radeonfb:800x600
file_system: e=0xFD00008 disk=0xFE6EF58 loc=0x0 start=0x0
path=0xFE703C0 buf=0xFE71000 size=512
file_system: probing filesys dos-partition

dos_partition: enter
dos-partition: boot_sect_sig0/1=0x55.0xAA jump=0x0 boot_signature=0x0
drive_number=0x0
dos_partition: partition=0 size=0x32F8E start=0x3F typ=0x6
        flag=0x80 shd=0x1 ssect=0x1 scyl=0x0 ehd=0xFE esect=0x3F ecyl=0xC
file_system: e=0xFD00008 disk=0xFE6EF58 loc=0x7E00 start=0x3F
path=0xFE703C2 buf=0xFE71000 size=512
file_system: probing filesys dos-partition
file_system: probing filesys dos-fat
file_system: return end (-4089)
file_system: return end (-4089)
disk-label return len=1782093 ret=end (-4089)
ata_disk_close
disk-label close:
checking exec type Fcode
fcode_is_exec: load=0x400000 loadlen=1782093
checking exec type Forth
checking exec type ELF
f_go:
checking exec type Fcode
fcode_is_exec: load=0x400000 loadlen=1782093
checking exec type Forth
checking exec type ELF
alloc_aligned: a 0xFD548E8 align 0xFD5491C size 0xFD54918 addr 0xFD54914
alloc_constrained: min 0x0, max 0xFFFFFFFF, align 0x1000, mask
0xFFFFFFFF, size 0x7E0000, addr 0x300000
alloc_constrained: acells 0x1 scells 0x1 t1 0xC t2 0xFD5490C u1
0xFD54910 u2 0xFD54914 u3 0xFD54918
alloc_constrained: allocator_block 0xFD54930, next 0x0 addr 0x300000
size 0xFD00000
alloc_constrained: fsblock 0x0
alloc_constrained: addr[] 0x300000
alloc_constrained: bsize[] 0xFD00000
alloc_constrained: passed min check
alloc_constrained: addr 0x300000, align 0xFFF, off 0x69696969
sum 0x0
alloc_constrained: passed align check
alloc_constrained: passed max check
alloc_constrained: passed mask check
alloc_constrained: passed full size check
alloc_constrained: passed size check


i'm not an expert but from a quick logs comparison I saw two times the
alloc_aligned,alloc_constrained section instead in the working one i
see it only one time.
Maybe it's an usefull observation.


cheers,
Nell
--
1861 - 2011: 150 years of Italian Unity

^ permalink raw reply

* [PATCH 2/4] serial: Add initial support for TWR-MPC5125
From: Vladimir Ermakov @ 2011-03-16 23:33 UTC (permalink / raw)
  To: linuxppc-dev

Adds PSC UART support for MPC5125 SoC.
    
MPC5125 has different registers than in MPC5121.

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---

diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h
index 2966df6..7bff52f 100644
--- a/arch/powerpc/include/asm/mpc52xx_psc.h
+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
@@ -150,6 +150,51 @@
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
+#ifdef CONFIG_PPC_MPC5125
+	u8		mr1;		/* PSC + 0x00 */
+	u8		reserved0[3];
+	u8		mr2;		/* PSC + 0x04 */
+	u8		reserved1[3];
+	u16		mpc52xx_psc_status; /* PSC + 0x08 */
+	u8		reserved2[2];
+	u8		mpc52xx_psc_clock_select; /* PSC + 0x0c */
+	u8		reserved3[3];
+	u8		command;	/* PSC + 0x10 */
+	u8		reserved4[3];
+	union {				/* PSC + 0x14 */
+		u8	buffer_8;
+		u16	buffer_16;
+		u32	buffer_32;
+	} buffer;
+#define mpc52xx_psc_buffer_8	buffer.buffer_8
+#define mpc52xx_psc_buffer_16	buffer.buffer_16
+#define mpc52xx_psc_buffer_32	buffer.buffer_32
+	u8		mpc52xx_psc_ipcr;	/* PSC + 0x18 */
+	u8		reserved5[3];
+	u8		mpc52xx_psc_acr;	/* PSC + 0x1c */
+	u8		reserved6[3];
+	u16		mpc52xx_psc_isr;	/* PSC + 0x20 */
+	u8		reserved7[2];
+	u16		mpc52xx_psc_imr;	/* PSC + 0x24 */
+	u8		reserved8[2];
+	u8		ctur;			/* PSC + 0x28 */
+	u8		reserved9[3];
+	u8		ctlr;			/* PSC + 0x2c */
+	u8		reserved10[3];
+	u32             ccr;            	/* PSC + 0x30 */
+	u32             ac97slots;      	/* PSC + 0x34 */
+	u32             ac97cmd;        	/* PSC + 0x38 */
+	u32             ac97data;       	/* PSC + 0x3c */
+	u8		reserved11[4];
+	u8		ip;			/* PSC + 0x44 */
+	u8		reserved12[3];
+	u8		op1;			/* PSC + 0x48 */
+	u8		reserved13[3];
+	u8		op0;			/* PSC + 0x4c */
+	u8		reserved14[3];
+	u32		sicr;			/* PSC + 0x50 */
+	u8		reserved15[4];
+#else
 	u8		mode;		/* PSC + 0x00 */
 	u8		reserved0[3];
 	union {				/* PSC + 0x04 */
@@ -212,6 +257,7 @@ struct mpc52xx_psc {
 	u8		reserved16[3];
 	u8		irfdr;		/* PSC + 0x54 */
 	u8		reserved17[3];
+#endif
 };
 
 struct mpc52xx_psc_fifo {
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index a0bcd8a..8e4c6b0 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -128,7 +128,11 @@ static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc,
 				       u16 prescaler, unsigned int divisor)
 {
 	/* select prescaler */
+#ifdef CONFIG_PPC_MPC5125
+	out_8(&psc->mpc52xx_psc_clock_select, prescaler >> 8);
+#else
 	out_be16(&psc->mpc52xx_psc_clock_select, prescaler);
+#endif
 	out_8(&psc->ctur, divisor >> 8);
 	out_8(&psc->ctlr, divisor & 0xff);
 }
@@ -345,7 +349,11 @@ static unsigned int psc_fifoc_irq;
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
 	/* /32 prescaler */
+#ifdef CONFIG_PPC_MPC5125
+	out_8(&PSC(port)->mpc52xx_psc_clock_select, 0xdd);
+#else
 	out_be16(&PSC(port)->mpc52xx_psc_clock_select, 0xdd00);
+#endif
 
 	out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
 	out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
@@ -816,9 +824,14 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
 	out_8(&psc->command, MPC52xx_PSC_RST_TX);
 
 	/* Send new mode settings */
+#ifdef CONFIG_PPC_MPC5125
+	out_8(&psc->mr1, mr1);
+	out_8(&psc->mr2, mr2);
+#else
 	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
 	out_8(&psc->mode, mr1);
 	out_8(&psc->mode, mr2);
+#endif
 	baud = psc_ops->set_baudrate(port, new, old);
 
 	/* Update the per-port timeout */
@@ -1107,8 +1120,12 @@ mpc52xx_console_get_options(struct uart_port *port,
 	pr_debug("mpc52xx_console_get_options(port=%p)\n", port);
 
 	/* Read the mode registers */
+#ifdef CONFIG_PPC_MPC5125
+	mr1 = in_8(&psc->mr1);
+#else
 	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
 	mr1 = in_8(&psc->mode);
+#endif
 
 	/* CT{U,L}R are write-only ! */
 	*baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
@@ -1296,9 +1313,13 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
 	/* binding used by efika: */
 	{ .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, },
 #endif
-#ifdef CONFIG_PPC_MPC512x
+#if defined(CONFIG_PPC_MPC512x) && !defined(CONFIG_PPC_MPC5125)
 	{ .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
 #endif
+#ifdef CONFIG_PPC_MPC5125
+	{ .compatible = "fsl,mpc5125-psc-uart", .data = &mpc512x_psc_ops, },
+#endif
+
 	{},
 };
 

^ permalink raw reply related

* [PATCH 3/4] fs_enet: Add initial support for TWR-MPC5125
From: Vladimir Ermakov @ 2011-03-16 23:37 UTC (permalink / raw)
  To: linuxppc-dev

Add PHY interface selection.
    
On TWR-MPC5125 PHY2 connected through RMII.

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---

diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index fc073b5..132966b 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -32,3 +32,16 @@ config FS_ENET_MDIO_FCC
 	tristate "MDIO driver for FCC"
 	depends on FS_ENET && CPM2
 	select MDIO_BITBANG
+
+choice FS_ENET_RCNTRL
+	prompt "PHY connection interface"
+	default FS_ENET_MII
+	depends on FS_ENET_MPC5121_FEC
+
+config FS_ENET_RCNTRL_MII
+	bool "MII"
+
+config FS_ENET_RCNTRL_RMII
+	bool "RMII"
+
+endchoice
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
index e980527..468be6e 100644
--- a/drivers/net/fs_enet/fec.h
+++ b/drivers/net/fs_enet/fec.h
@@ -26,6 +26,7 @@
 #define FEC_RCNTRL_BC_REJ	0x00000010
 #define FEC_RCNTRL_PROM		0x00000008
 #define FEC_RCNTRL_MII_MODE	0x00000004
+#define FEC_RCNTRL_RMII_MODE	0x00000124
 #define FEC_RCNTRL_DRT		0x00000002
 #define FEC_RCNTRL_LOOP		0x00000001
 
@@ -33,6 +34,11 @@
 #define FEC_TCNTRL_HBC		0x00000002
 #define FEC_TCNTRL_GTS		0x00000001
 
+#ifdef CONFIG_FS_ENET_RCNTRL_MII
+#define FEC_RCNTRL_PHY_MODE FEC_RCNTRL_MII_MODE
+#else /* CONFIG_FS_ENET_RCNTRL_RMII */
+#define FEC_RCNTRL_PHY_MODE FEC_RCNTRL_RMII_MODE
+#endif
 
 
 /*
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 61035fc..d43e56d 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -319,13 +319,13 @@ static void restart(struct net_device *dev)
 #ifndef CONFIG_FS_ENET_MPC5121_FEC
 	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
 
-	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	FW(fecp, r_cntrl, FEC_RCNTRL_PHY_MODE);	/* MII/RMII enable */
 #else
 	/*
-	 * Only set MII mode - do not touch maximum frame length
+	 * Only set MII/RMII mode - do not touch maximum frame length
 	 * configured before.
 	 */
-	FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	FS(fecp, r_cntrl, FEC_RCNTRL_PHY_MODE);
 #endif
 	/*
 	 * adjust to duplex mode
@@ -381,7 +381,7 @@ static void stop(struct net_device *dev)
 
 	/* shut down FEC1? that's where the mii bus is */
 	if (fpi->has_phy) {
-		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+		FS(fecp, r_cntrl, FEC_RCNTRL_PHY_MODE);	/* MII/RMII enable */
 		FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
 		FW(fecp, ievent, FEC_ENET_MII);
 		FW(fecp, mii_speed, feci->mii_speed);
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 7e840d3..bb61ff6 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -161,7 +161,7 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 
 	fec->mii_speed = speed << 1;
 
-	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_PHY_MODE);
 	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
 	                                  FEC_ECNTRL_ETHER_EN);
 	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);

^ permalink raw reply related

* [PATCH 4/4] mtd/nand: Add initial support for TWR-MPC5125
From: Vladimir Ermakov @ 2011-03-16 23:46 UTC (permalink / raw)
  To: linuxppc-dev

Adds NAND Flash Controller driver for MPC5125.
Also adds chip id for Micron's NAND used in TWR-MPC5125.

Driver ported from original Freescale BSP (kernel 2.6.29.1).

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index a92054e..eb660a8 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -472,6 +472,26 @@ config MTD_NAND_MPC5121_NFC
 	  This enables the driver for the NAND flash controller on the
 	  MPC5121 SoC.
 
+config MTD_NAND_MPC5125_NFC
+	tristate "MPC5125 built-in NAND Flash Controller support"
+	depends on PPC_MPC512x
+	help
+	  This enables the driver for the NAND flash controller on the
+	  MPC5125 SoC.
+
+config MTD_NAND_MPC5125_HWECC
+	bool "Enable hardware ECC"
+	depends on MTD_NAND_MPC5125_NFC
+	help
+	  This enables the support for Software ECC handling. By
+	  default FSL NAND controller Hardware ECC is supported.
+
+config NFC_DMA_ENABLE
+	bool "Enable NAND Flash DMA"
+	depends on MTD_NAND_MPC5125_NFC
+	help
+	  This enables the nfc dma support
+
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
 	depends on IMX_HAVE_PLATFORM_MXC_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 5745d83..bd354cd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_MTD_NAND_NUC900)		+= nuc900_nand.o
 obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
 obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
+obj-$(CONFIG_MTD_NAND_MPC5125_NFC)	+= mpc5125_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 
diff --git a/drivers/mtd/nand/mpc5125_nfc.c b/drivers/mtd/nand/mpc5125_nfc.c
new file mode 100644
index 0000000..aea3186
--- /dev/null
+++ b/drivers/mtd/nand/mpc5125_nfc.c
@@ -0,0 +1,1290 @@
+/*
+ * Copyright (C) 2009 Freescale Semiconductor, Inc.
+ *
+ * MPC5125 Nand driver.
+ *
+ * Based on original driver from Freescale Semiconductor
+ * written by Shaohui Xie <b21989@freescale.com> on basis
+ * of drivers/mtd/nand/mpc5121_nfc.c.
+ * Modyfied by Cloudy Chen <chen_yunsong@mtcera.com>.
+ * Reworked by Vladimir Ermakov <vooon341@gmail.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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/gfp.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include "mpc5125_nfc.h"
+
+#define	DRV_NAME		"mpc5125_nfc"
+
+#define	SPARE_BUFFER_MAX_SIZE	0x400
+#define	DATA_BUFFER_MAX_SIZE	0x2000
+
+/* Timeouts */
+#define NFC_RESET_TIMEOUT	1000		/* 1 ms */
+#define NFC_TIMEOUT		(HZ / 10)	/* 1/10 s */
+
+#ifdef CONFIG_NFC_DMA_ENABLE
+#define NFC_DMA_ENABLE		1
+#else
+#define NFC_DMA_ENABLE		0
+#endif
+
+struct mpc5125_nfc_prv {
+	struct mtd_info		mtd;
+	struct nand_chip	chip;
+	int			irq;
+	void __iomem		*regs;
+	struct clk		*clk;
+	wait_queue_head_t	irq_waitq;
+	uint			column;
+	int			spareonly;
+	u32		irq_stat;
+	u32		wait_timeout;
+	void __iomem		*csreg;
+	struct device		*dev;
+	void			*data_buffers;
+	dma_addr_t		data_buffers_phyaddr;
+	void			*ops_buffer;
+	dma_addr_t		ops_buffer_phyaddr;
+	void			*tmp_buf;
+	unsigned int		sync_flags;
+};
+
+static int get_status;
+static int get_id;
+
+#define	NFC_IRQ_ENABLE	(IDLE_EN_MASK|WERR_EN_MASK)
+#define	NFC_IRQ_MASK	(IDLE_IRQ_MASK|WERR_IRQ_MASK)
+
+#define	MPC5125_NFC_ECC_STATUS_ADD	(NFC_SPARE_AREA(0)+0xf0)
+
+#if 1
+/* for ECC_MODE=0x6 45bytes*2 */
+static struct nand_ecclayout nand_hw_eccoob_4k_128 = {
+	.eccbytes = 90,	/* actually 72 but only room for 64 */
+	.eccpos = {
+		/* 9 bytes of ecc for each 512 bytes of data */
+		19,  20,  21,  22,  23,  24,  25,  26,  27,
+		28,  29,  30,  31,  32,  33,  34,  35,  36,
+		37,  38,  39,  40,  41,  42,  43,  44,  45,
+		46,  47,  48,  49,  50,  51,  52,  53,  54,
+		55,  56,  57,  58,  59,  60,  61,  62,  63,
+
+		83,  84,  85,  86,  87,  88,  89,  90,  91,
+		92,  93,  94,  95,  96,  97,  98,  99, 100,
+		101,102, 103, 104, 105, 106, 107, 108, 109,
+		110,111, 112, 113, 114, 115, 116, 117, 118,
+		119,120, 121, 122, 123, 124, 125, 126, 127
+		/* 120, 121, 122, 123, 124, 125, 126, 127, */
+	},
+	.oobavail = 30,
+	.oobfree = {
+		{4, 15},
+		{68, 15}
+	}
+};
+#else
+/* for ECC_MODE=0x5 30bytes*2 */
+static struct nand_ecclayout nand_hw_eccoob_4k_128 = {
+	.eccbytes = 60,	/* actually 72 but only room for 64 */
+	.eccpos = {
+		/* 9 bytes of ecc for each 512 bytes of data */
+		34,  35,  36,  37,  38,  39,  40,  41,  42,
+		43,  44,  45,  46,  47,  48,  49,  50,  51,
+		52,  53,  54,  55,  56,  57,  58,  59,  60,
+		61,  62,  63,
+
+		98,  99, 100,
+		101,102, 103, 104, 105, 106, 107, 108, 109,
+		110,111, 112, 113, 114, 115, 116, 117, 118,
+		119,120, 121, 122, 123, 124, 125, 126, 127
+		/* 120, 121, 122, 123, 124, 125, 126, 127, */
+	},
+	.oobavail = 48,
+	.oobfree = {
+		{8, 24},
+		{68, 24}
+	}
+};
+#endif
+
+static struct nand_ecclayout nand_hw_eccoob_4k_218 = {
+	.eccbytes = 64,	/* actually 144 but only room for 64 */
+	.eccpos = {
+		/* 18 bytes of ecc for each 512 bytes of data */
+		7, 8, 9, 10, 11, 12, 13, 14, 15,
+		    16, 17, 18, 19, 20, 21, 22, 23, 24,
+		33, 34, 35, 36, 37, 38, 39, 40, 41,
+		    42, 43, 44, 45, 46, 47, 48, 49, 50,
+		59, 60, 61, 62, 63, 64, 65, 66, 67,
+		    68, 69, 70, 71, 72, 73, 74, 75, 76,
+		85, 86, 87, 88, 89, 90, 91, 92, 93,
+		    94, /* 95, 96, 97, 98, 99, 100, 101, 102,
+		111, 112, 113, 114, 115, 116, 117, 118, 119,
+		    120, 121, 122, 123, 124, 125, 126, 127, 128,
+		137, 138, 139, 140, 141, 142, 143, 144, 145,
+		    146, 147, 148, 149, 150, 151, 152, 153, 154,
+		163, 164, 165, 166, 167, 168, 169, 170, 171,
+		    172, 173, 174, 175, 176, 177, 178, 179, 180,
+		189, 190, 191, 192, 193, 194, 195, 196, 197,
+		    198, 199, 200, 201, 202, 203, 204, 205, 206, */
+	},
+	.oobavail = 4,
+	.oobfree = {
+		{0, 5}, {26, 8},
+		{52, 8}, {78, 8},
+		{104, 8}, {130, 8},
+		{156, 8}, {182, 8}
+	}
+};
+
+
+#if NFC_DMA_ENABLE
+static void mpc5125_dma_config(struct mtd_info *mtd, struct nand_chip *chip, unsigned isRead);
+static void mpc5125_nand_dma_wait(struct mtd_info *mtd, struct nand_chip *chip);
+#endif
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *mpc5125_nfc_pprobes[] = { "cmdlinepart", NULL };
+#endif
+
+/* Read NFC register */
+static inline u32 nfc_read(struct mtd_info *mtd, uint reg)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	return in_be32(prv->regs + reg);
+}
+
+/* Write NFC register */
+static inline void nfc_write(struct mtd_info *mtd, uint reg, u32 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	out_be32(prv->regs + reg, val);
+}
+
+/* Set bits in NFC register */
+static inline void nfc_set(struct mtd_info *mtd, uint reg, u32 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
+}
+
+/* Clear bits in NFC register */
+static inline void nfc_clear(struct mtd_info *mtd, uint reg, u32 bits)
+{
+	nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
+}
+
+
+static inline void
+nfc_set_field(struct mtd_info *mtd, u32 reg, u32 mask, u32 shift, u32 val)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	out_be32(prv->regs + reg,
+			(in_be32(prv->regs + reg) & (~mask))
+			| val << shift);
+}
+
+static inline int
+nfc_get_field(struct mtd_info *mtd, u32 reg, u32 field_mask)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	return in_be32(prv->regs + reg) & field_mask;
+}
+
+static inline u8 nfc_check_status(struct mtd_info *mtd)
+{
+	u8 fls_status = 0;
+	fls_status = nfc_get_field(mtd, NFC_FLASH_STATUS2, STATUS_BYTE1_MASK);
+	return fls_status;
+}
+
+/* clear cmd_done and cmd_idle falg for the coming command */
+static void mpc5125_nfc_clear(struct mtd_info *mtd)
+{
+	nfc_write(mtd, NFC_IRQ_STATUS, 1 << CMD_DONE_CLEAR_SHIFT);
+	nfc_write(mtd, NFC_IRQ_STATUS, 1 << IDLE_CLEAR_SHIFT);
+	nfc_write(mtd, NFC_IRQ_STATUS, 1 << WERR_CLEAR_SHIFT);
+}
+
+/* Wait for operation complete */
+static void mpc5125_nfc_done(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	int rv;
+	unsigned int wait_time = NFC_TIMEOUT;
+
+	mpc5125_nfc_clear(mtd);
+	nfc_set(mtd, NFC_IRQ_STATUS, NFC_IRQ_ENABLE);
+	prv->wait_timeout = 0;
+	prv->sync_flags = 0;
+	nfc_set_field(mtd, NFC_FLASH_CMD2, START_MASK,
+			START_SHIFT, 1);
+
+	if ((nfc_read(mtd, NFC_IRQ_STATUS) & NFC_IRQ_MASK) == 0){
+		rv = wait_event_timeout(prv->irq_waitq,
+			(nfc_read(mtd, NFC_IRQ_STATUS) & NFC_IRQ_MASK), wait_time);
+
+		if (!rv) {
+			prv->irq_stat = nfc_read(mtd, NFC_IRQ_STATUS);
+
+			if(!prv->sync_flags)
+				dev_warn(prv->dev, "Lost irq.\n");
+
+			dev_warn(prv->dev,
+				"Timeout while waiting for interrupt.\n");
+			prv->wait_timeout = 1;
+		}
+	}
+
+	mpc5125_nfc_clear(mtd);
+}
+
+static inline u8 mpc5125_nfc_get_id(struct mtd_info *mtd, int col)
+{
+	u32 flash_id1 = 0;
+	u8 *pid;
+
+	flash_id1 = nfc_read(mtd, NFC_FLASH_STATUS1);
+	pid = (u8 *)&flash_id1;
+
+	return *(pid + col);
+}
+
+static inline u8 mpc5125_nfc_get_status(struct mtd_info *mtd)
+{
+	u32 flash_status = 0;
+	u8 *pstatus;
+
+	flash_status = nfc_read(mtd, NFC_FLASH_STATUS2);
+	pstatus = (u8 *)&flash_status;
+
+	return *(pstatus + 3);
+}
+
+/* Invoke command cycle */
+static inline void
+mpc5125_nfc_send_cmd(struct mtd_info *mtd, u32 cmd_byte1,
+		u32 cmd_byte2, u32 cmd_code)
+{
+	mpc5125_nfc_clear(mtd);
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+			CMD_BYTE1_SHIFT, cmd_byte1);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD1, CMD_BYTE2_MASK,
+			CMD_BYTE2_SHIFT, cmd_byte2);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_CODE_MASK,
+			CMD_CODE_SHIFT, cmd_code);
+
+	if (cmd_code == RANDOM_OUT_CMD_CODE)
+		nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 1);
+}
+
+/* Receive ID and status from NAND flash */
+static inline void
+mpc5125_nfc_send_one_byte(struct mtd_info *mtd, u32 cmd_byte1, u32 cmd_code)
+{
+	mpc5125_nfc_clear(mtd);
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+			CMD_BYTE1_SHIFT, cmd_byte1);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_CODE_MASK,
+			CMD_CODE_SHIFT, cmd_code);
+}
+
+/* NFC interrupt handler */
+static irqreturn_t mpc5125_nfc_irq(int irq, void *data)
+{
+	struct mtd_info *mtd = data;
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	prv->irq_stat = nfc_read(mtd, NFC_IRQ_STATUS);
+	nfc_clear(mtd, NFC_IRQ_STATUS, NFC_IRQ_ENABLE);
+	wake_up(&prv->irq_waitq);
+	/*mpc5125_nfc_clear(mtd);*/
+	prv->sync_flags |= 1;
+
+	return IRQ_HANDLED;
+}
+
+/* Do address cycle(s) */
+static void mpc5125_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
+{
+
+	if (column != -1) {
+		nfc_set_field(mtd, NFC_COL_ADDR,
+				COL_ADDR_MASK,
+				COL_ADDR_SHIFT, column);
+	}
+
+	if (page != -1) {
+		nfc_set_field(mtd, NFC_ROW_ADDR,
+				ROW_ADDR_MASK,
+				ROW_ADDR_SHIFT, page);
+	}
+	/* DMA Disable */
+#if (NFC_DMA_ENABLE<1)
+	nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_DMA_REQ_MASK);
+#endif
+	/* PAGE_CNT = 2 */
+	nfc_set_field(mtd, NFC_FLASH_CONFIG, CONFIG_PAGE_CNT_MASK,
+			CONFIG_PAGE_CNT_SHIFT, 0x2);
+}
+
+
+/* Control chips select signal on ADS5125 board */
+static void ads5125_select_chip(struct mtd_info *mtd, int chip)
+{
+
+	if ((chip < 0)||(chip > 3)) {
+		nfc_set_field(mtd, NFC_ROW_ADDR,
+			ROW_ADDR_CHIP_SEL_RB_MASK,
+			ROW_ADDR_CHIP_SEL_RB_SHIFT, 0);
+
+		nfc_set_field(mtd, NFC_ROW_ADDR,
+			ROW_ADDR_CHIP_SEL_MASK,
+			ROW_ADDR_CHIP_SEL_SHIFT, 0);
+		return;
+	}
+
+	nfc_set_field(mtd, NFC_ROW_ADDR,
+		ROW_ADDR_CHIP_SEL_RB_MASK,
+		ROW_ADDR_CHIP_SEL_RB_SHIFT, (1<<chip));
+
+	nfc_set_field(mtd, NFC_ROW_ADDR,
+		ROW_ADDR_CHIP_SEL_MASK,
+		ROW_ADDR_CHIP_SEL_SHIFT, (1<<chip));
+}
+
+/* Read NAND Ready/Busy signal */
+static int mpc5125_nfc_dev_ready(struct mtd_info *mtd)
+{
+	/*
+	 * NFC handles ready/busy signal internally. Therefore, this function
+	 * always returns status as ready.
+	 */
+	return 1;
+}
+
+/* Write command to NAND flash */
+static void mpc5125_nfc_command(struct mtd_info *mtd, unsigned command,
+						int column, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	prv->column = (column >= 0) ? column : 0;
+	prv->spareonly = 0;
+	get_id = 0;
+	get_status = 0;
+
+
+	switch (command) {
+	case NAND_CMD_PAGEPROG:
+#if (NFC_DMA_ENABLE)
+		mpc5125_nfc_send_cmd(mtd,
+				PROGRAM_PAGE_CMD_BYTE1,
+				PROGRAM_PAGE_CMD_BYTE2,
+				DMA_PROGRAM_PAGE_CMD_CODE);
+		/*
+		nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+			CMD_BYTE1_SHIFT, READ_STATUS_CMD_BYTE);
+			*/
+		mpc5125_dma_config(mtd, chip, 0);
+#else
+		mpc5125_nfc_send_cmd(mtd,
+				PROGRAM_PAGE_CMD_BYTE1,
+				PROGRAM_PAGE_CMD_BYTE2,
+				PROGRAM_PAGE_CMD_CODE);
+#endif
+		break;
+	/*
+	 * NFC does not support sub-page reads and writes,
+	 * so emulate them using full page transfers.
+	 */
+	case NAND_CMD_READ0:
+		column = 0;
+		goto read0;
+		break;
+
+	case NAND_CMD_READ1:
+		prv->column += 256;
+		command = NAND_CMD_READ0;
+		column = 0;
+		goto read0;
+		break;
+
+	case NAND_CMD_READOOB:
+		prv->spareonly = 1;
+		command = NAND_CMD_READ0;
+		column = 0;
+
+read0:
+		mpc5125_nfc_send_cmd(mtd,
+				PAGE_READ_CMD_BYTE1,
+				PAGE_READ_CMD_BYTE2,
+				READ_PAGE_CMD_CODE);
+#if NFC_DMA_ENABLE
+		mpc5125_dma_config(mtd, chip, 1);
+#endif
+		break;
+
+	case NAND_CMD_SEQIN:
+		mpc5125_nfc_command(mtd, NAND_CMD_READ0, column, page);
+		column = 0;
+		break;
+
+	case NAND_CMD_ERASE1:
+		mpc5125_nfc_send_cmd(mtd,
+				ERASE_CMD_BYTE1,
+				ERASE_CMD_BYTE2,
+				ERASE_CMD_CODE);
+		break;
+
+	case NAND_CMD_ERASE2:
+		return;
+
+	case NAND_CMD_READID:
+		get_id = 1;
+		mpc5125_nfc_send_one_byte(mtd, command, READ_ID_CMD_CODE);
+		break;
+
+	case NAND_CMD_STATUS:
+		get_status = 1;
+		mpc5125_nfc_send_one_byte(mtd, command, STATUS_READ_CMD_CODE);
+		break;
+
+	case NAND_CMD_RNDOUT:
+		mpc5125_nfc_send_cmd(mtd,
+				RANDOM_OUT_CMD_BYTE1,
+				RANDOM_OUT_CMD_BYTE2,
+				RANDOM_OUT_CMD_CODE);
+		break;
+
+	default:
+		return;
+	}
+
+	mpc5125_nfc_addr_cycle(mtd, column, page);
+	mpc5125_nfc_done(mtd);
+
+#if (NFC_DMA_ENABLE)
+	/* mpc5125_nand_dma_wait(mtd, chip); */
+	nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_DMA_REQ_MASK);
+#endif
+}
+
+/* Copy data from/to NFC spare buffers. */
+static void mpc5125_nfc_copy_spare(struct mtd_info *mtd, uint offset,
+						u8 *buffer, uint size, int wr)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct mpc5125_nfc_prv *prv = nand->priv;
+	u16 ooblen = mtd->oobsize;
+	u8 i, count;
+	uint  sbsize, blksize;
+
+	/*
+	 * NAND spare area is available through NFC spare buffers.
+	 * The NFC divides spare area into (page_size / 512) chunks.
+	 * Each chunk is placed into separate spare memory area, using
+	 * first (spare_size / num_of_chunks) bytes of the buffer.
+	 *
+	 * For NAND device in which the spare area is not divided fully
+	 * by the number of chunks, number of used bytes in each spare
+	 * buffer is rounded down to the nearest even number of bytes,
+	 * and all remaining bytes are added to the last used spare area.
+	 *
+	 * For more information read section 26.6.10 of MPC5121e
+	 * Microcontroller Reference Manual, Rev. 3.
+	 */
+
+	/* Calculate number of valid bytes in each spare buffer */
+	count = mtd->writesize >> 11;
+	count = (count > 0) ? count : 1;
+	sbsize = (ooblen / count >> 1) << 1;
+
+	for (i=0; (i < count) && size; i++) {
+		blksize = min(sbsize, size);
+		if (wr)
+			memcpy_toio(prv->regs + NFC_SPARE_AREA(i),
+							buffer, blksize);
+		else
+			memcpy_fromio(buffer,
+				prv->regs + NFC_SPARE_AREA(i), blksize);
+
+		buffer += blksize;
+		offset += blksize;
+		size -= blksize;
+	}
+}
+
+/* Copy data from/to NFC main and spare buffers */
+static void
+mpc5125_nfc_buf_copy(struct mtd_info *mtd, u8 *buf, int len, int wr)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	uint c = prv->column;
+	uint l;
+
+	/* Handle spare area access */
+	if (prv->spareonly || c >= mtd->writesize) {
+		/* Calculate offset from beginning of spare area */
+		if (c >= mtd->writesize)
+			c -= mtd->writesize;
+
+		prv->column += len;
+#if NFC_DMA_ENABLE
+		if (wr)
+			memcpy(prv->ops_buffer, buf, len);
+		else
+			memcpy(buf, prv->ops_buffer, len);
+#else
+		mpc5125_nfc_copy_spare(mtd, c, buf, len, wr);
+#endif
+		return;
+	}
+
+	/*
+	 * Handle main area access - limit copy length to prevent
+	 * crossing main/spare boundary.
+	 */
+	l = min((uint)len, mtd->writesize - c);
+	prv->column += l;
+
+	if (wr)	{
+#if NFC_DMA_ENABLE
+		memcpy(prv->data_buffers+c, buf, len);
+#else
+		unsigned int size, i;
+		for (i=(c/PAGE_2K); i < 4; i++) {
+			size = min(len, PAGE_2K);
+			memcpy_toio(prv->regs + NFC_MAIN_AREA(i) + c, buf, size);
+			buf += size;
+			len -= size;
+			if (!len)
+				break;
+		}
+#endif
+	} else {
+		if (get_status) {
+			get_status = 0;
+			*buf = mpc5125_nfc_get_status(mtd);
+		} else if (l == 1 && c <= 3 && get_id) {
+			*buf = mpc5125_nfc_get_id(mtd, c);
+		} else {
+			unsigned int size, i;
+#if NFC_DMA_ENABLE
+			if (len == mtd->writesize)
+				memcpy(buf, prv->data_buffers+c, len);
+			else
+#endif
+			for (i=(c/PAGE_2K); i < 4; i++) {
+				size = min(len, PAGE_2K);
+				memcpy_fromio(buf, prv->regs + NFC_MAIN_AREA(i) + c, size);
+				buf += size;
+				len -= size;
+				if (!len)
+					break;
+			}
+		}
+	}
+}
+
+/* Read data from NFC buffers */
+static void mpc5125_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	mpc5125_nfc_buf_copy(mtd, buf, len, 0);
+}
+
+/* Write data to NFC buffers */
+static void mpc5125_nfc_write_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	mpc5125_nfc_buf_copy(mtd, (u_char *)buf, len, 1);
+}
+
+/* Compare buffer with NAND flash */
+static int mpc5125_nfc_verify_buf(struct mtd_info *mtd,
+						const u_char *buf, int len)
+{
+	u_char tmp[256];
+	uint bsize;
+
+	while (len) {
+		bsize = min(len, 256);
+		mpc5125_nfc_read_buf(mtd, tmp, bsize);
+
+		if (memcmp(buf, tmp, bsize))
+			return 1;
+
+		buf += bsize;
+		len -= bsize;
+	}
+
+	return 0;
+}
+
+/* Read byte from NFC buffers */
+static u8 mpc5125_nfc_read_byte(struct mtd_info *mtd)
+{
+	u8 tmp;
+
+	mpc5125_nfc_read_buf(mtd, &tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/* Read word from NFC buffers */
+static u16 mpc5125_nfc_read_word(struct mtd_info *mtd)
+{
+	u16 tmp;
+
+	mpc5125_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+
+	return tmp;
+}
+
+/*
+ * Read NFC configuration from Reset Config Word
+ *
+ */
+static int mpc5125_nfc_read_hw_config(struct mtd_info *mtd)
+{
+	uint rcw_pagesize = 0;
+	uint rcw_sparesize = 0;
+
+	/* TODO */
+	rcw_pagesize = 4096;
+	rcw_sparesize = 128;
+	mtd->writesize = rcw_pagesize;
+	mtd->oobsize = rcw_sparesize;
+
+	return 0;
+}
+
+/* Free driver resources */
+static void mpc5125_nfc_free(struct device *dev, struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	if (prv->clk) {
+		clk_disable(prv->clk);
+		clk_put(prv->clk);
+	}
+
+	if (prv->csreg)
+		iounmap(prv->csreg);
+}
+
+static void mpc5125_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_ECC_MODE_MASK,
+			CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+	return;
+}
+
+/*
+ * Function to correct the detected errors. This NFC corrects all the errors
+ * detected. So this function is not required.
+ */
+static int mpc5125_nand_correct_data(struct mtd_info *mtd, u_char * dat,
+				 u_char * read_ecc, u_char * calc_ecc)
+{
+	panic("Shouldn't be called here: %d\n", __LINE__);
+	return 0;		/* FIXME */
+}
+
+/*
+ * Function to calculate the ECC for the data to be stored in the Nand device.
+ * This NFC has a hardware RS(511,503) ECC engine together with the RS ECC
+ * CONTROL blocks are responsible for detection  and correction of up to
+ * 4 symbols of 9 bits each in 528 byte page.
+ * So this function is not required.
+ */
+static int mpc5125_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
+				  u_char * ecc_code)
+{
+	panic(KERN_ERR "Shouldn't be called here %d \n", __LINE__);
+	return 0;		/* FIXME */
+}
+
+static int mpc5125_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			     int page, int sndcmd)
+{
+
+	if (sndcmd) {
+		mpc5125_nfc_command(mtd, NAND_CMD_READ0, 0, page);
+		sndcmd = 0;
+	}
+
+#if NFC_DMA_ENABLE
+{
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	memcpy(chip->oob_poi, prv->ops_buffer, mtd->oobsize);
+}
+#else
+	mpc5125_nfc_copy_spare(mtd, 0, chip->oob_poi, mtd->oobsize, 0);
+#endif
+	return sndcmd;
+}
+
+static int mpc5125_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			      int page)
+{
+//	unsigned int stat;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	mpc5125_nfc_command(mtd, NAND_CMD_READ0, 0, page);
+#if NFC_DMA_ENABLE
+	memcpy(prv->ops_buffer, chip->oob_poi, mtd->oobsize);
+#else
+	mpc5125_nfc_copy_spare(mtd, 0, chip->oob_poi, mtd->oobsize, 1);
+#endif
+	mpc5125_nfc_command(mtd, NAND_CMD_PAGEPROG, 0, page);
+
+	if (prv->wait_timeout) {
+		dev_err(prv->dev, "%s wait timeout.\n", __FUNCTION__);
+		return -EIO;
+	}
+	if (prv->irq_stat & WERR_IRQ_MASK) {
+		dev_err(prv->dev, "%s faield.\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mpc5125_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+			      uint8_t * buf, int page)
+{
+	unsigned int stat;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	u8 *erase_page_check, ecc_bytes = 0;
+	const u8 ecc_bytes_map[] = {0, 8, 12, 15, 23, 30, 45, 60};
+
+	stat = nfc_read(mtd, NFC_FLASH_CONFIG);
+	stat >>= 17;
+	stat &= 0x7;
+	ecc_bytes = ecc_bytes_map[stat];
+
+	erase_page_check = (u8 *)(PAGE_virtual_2K - ecc_bytes + prv->regs);
+	stat = nfc_read(mtd, MPC5125_NFC_ECC_STATUS_ADD + 4);
+
+	if (stat & 0x80) {
+		/*check the page is erased*/
+		if (stat & 0x3f) {
+			mtd->ecc_stats.failed++;
+			dev_warn(prv->dev, "Uncorrectable RS-ECC Error\n");
+		}
+
+	} else if (stat & 0x3f) {
+		/* dev_notice(prv->dev, "Correctable ECC %d\n", stat & 0x3f); */
+		mtd->ecc_stats.corrected += stat & 0x3f;
+	}
+
+#if NFC_DMA_ENABLE
+	memcpy(buf, prv->data_buffers, mtd->writesize);
+	memcpy(chip->oob_poi, prv->ops_buffer, mtd->oobsize);
+#else
+	mpc5125_nfc_buf_copy(mtd, buf, mtd->writesize, 0);
+	mpc5125_nfc_copy_spare(mtd, 0, chip->oob_poi, mtd->oobsize, 0);
+#endif
+
+	return 0;
+}
+
+static void mpc5125_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+				const uint8_t *buf)
+{
+#if NFC_DMA_ENABLE
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	memcpy(prv->data_buffers, buf, mtd->writesize);
+	memcpy(prv->ops_buffer, chip->oob_poi, mtd->oobsize);
+#else
+	mpc5125_nfc_buf_copy(mtd, buf, mtd->writesize, 1);
+	mpc5125_nfc_copy_spare(mtd, 0, chip->oob_poi, mtd->oobsize, 1);
+#endif
+}
+
+static int chip_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+			   const uint8_t *buf, int page, int cached, int raw)
+{
+	int status;
+#if (NFC_DMA_ENABLE<1)
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+#endif
+	if (unlikely(raw))
+		chip->ecc.write_page_raw(mtd, chip, buf);
+	else
+		chip->ecc.write_page(mtd, chip, buf);
+
+	/*
+	 * Cached progamming disabled for now, Not sure if its worth the
+	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+	 */
+	cached = 0;
+
+	if (!cached || !(chip->options & NAND_CACHEPRG)) {
+#if NFC_DMA_ENABLE
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, 0x00, page);
+#else
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+#endif
+
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available
+		 */
+		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+			status = chip->errstat(mtd, chip, FL_WRITING, status,
+					       page);
+
+		if (status & NAND_STATUS_FAIL)
+			return -EIO;
+	} else {
+#if NFC_DMA_ENABLE
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, 0x00, page);
+#else
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+#endif
+		status = chip->waitfunc(mtd, chip);
+	}
+	if (nfc_get_field(mtd, NFC_IRQ_STATUS, WERR_IRQ_MASK|WERR_STATUS_MASK)) {
+		printk(KERN_ERR "%s line:%d write page %d failed\n", __FUNCTION__, __LINE__, page);
+		nfc_set_field(mtd, NFC_IRQ_STATUS,
+			WERR_CLEAR_MASK,
+			WERR_CLEAR_SHIFT, 1);
+		return -EIO;
+	}
+	return 0;
+}
+
+#if NFC_DMA_ENABLE
+static void mpc5125_dma_config(struct mtd_info *mtd,
+		struct nand_chip *chip, unsigned isRead)
+{
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	nfc_write(mtd, NFC_DMA1_ADDR, prv->data_buffers_phyaddr);
+	nfc_write(mtd, NFC_DMA2_ADDR, prv->ops_buffer_phyaddr);
+
+	if (isRead)
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_DMA_REQ_MASK,
+				CONFIG_DMA_REQ_SHIFT, 1);
+	else
+		nfc_set_field(mtd, NFC_FLASH_CONFIG,
+				CONFIG_DMA_REQ_MASK,
+				CONFIG_DMA_REQ_SHIFT, 0);
+
+	nfc_set_field(mtd, NFC_FLASH_COMMAND_REPEAT,
+			COMMAND_REPEAT_MASK,
+			COMMAND_REPEAT_SHIFT, 0);
+	nfc_set_field(mtd, NFC_FLASH_CMD2, BUFNO_MASK,
+			BUFNO_SHIFT, 0);
+}
+
+static void mpc5125_nand_dma_wait(struct mtd_info *mtd,
+		struct nand_chip *chip)
+{
+	struct mpc5125_nfc_prv *prv = chip->priv;
+	int rv;
+
+	if ((DMA_BUSY_MASK|ECC_BUSY_MASK|RESIDUE_BUSY_MASK) &
+			nfc_read(mtd, NFC_IRQ_STATUS)) {
+		rv = wait_event_timeout(prv->irq_waitq,
+				(nfc_read(mtd, NFC_IRQ_STATUS) &
+				 (CMD_DONE_IRQ_MASK|IDLE_IRQ_MASK)) ==
+				(CMD_DONE_IRQ_MASK|IDLE_IRQ_MASK),
+				NFC_TIMEOUT * 4);
+		if (!rv) {
+			prv->irq_stat = nfc_read(mtd, NFC_IRQ_STATUS);
+			dev_err(prv->dev, "%s timeout status: %08x\n", __FUNCTION__, prv->irq_stat);
+			prv->wait_timeout = 1;
+		}
+	}
+}
+
+/**
+ * nand_read_page_raw - [Intern] read raw page data without ecc
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
+ */
+static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+			      uint8_t *buf, int page)
+{
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	memcpy(buf, prv->data_buffers, mtd->writesize);
+	memcpy(chip->oob_poi, prv->ops_buffer, mtd->oobsize);
+
+	return 0;
+}
+
+/**
+ * nand_write_page_raw - [Intern] raw page write function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	data buffer
+ */
+static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+				const uint8_t *buf)
+{
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	memcpy(prv->data_buffers, buf, mtd->writesize);
+	memcpy(prv->ops_buffer, chip->oob_poi, mtd->oobsize);
+	mpc5125_dma_config(mtd, chip, 0);
+}
+#endif
+
+static int __devinit mpc5125_nfc_probe(struct platform_device *op)
+{
+	struct device_node *dn = op->dev.of_node;
+	struct device *dev = &op->dev;
+	struct mpc5125_nfc_prv *prv;
+	struct resource res;
+	struct mtd_info *mtd;
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition *parts;
+#endif
+	struct nand_chip *chip;
+	unsigned long regs_paddr, regs_size;
+	const __be32 *chips_no;
+	int retval = 0;
+	int len;
+
+	prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL);
+	if (!prv) {
+		dev_err(dev, "Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	mtd = &prv->mtd;
+	chip = &prv->chip;
+
+	mtd->priv = chip;
+	chip->priv = prv;
+	prv->dev = dev;
+
+	/* Read NFC configuration from Reset Config Word */
+	retval = mpc5125_nfc_read_hw_config(mtd);
+	if (retval) {
+		dev_err(dev, "Unable to read NFC config!\n");
+		return retval;
+	}
+
+	/* speed up nand flash r/w add by cloudy */
+	{
+		volatile u32 *nfc_div = ioremap(0x80000f80, sizeof(u32));
+		if (!nfc_div)
+			dev_err(dev, "Unable to speed up nfc !\n");
+		else {
+#ifdef CONFIG_MTD_NAND_MPC5125_HWECC
+			*nfc_div = 0x1430 << 16;
+#else
+			*nfc_div = 0x2860 << 16;
+#endif
+			iounmap(nfc_div);
+		}
+	}
+
+	prv->irq = irq_of_parse_and_map(dn, 0);
+	if (prv->irq == NO_IRQ) {
+		dev_err(dev, "Error mapping IRQ!\n");
+		return -EINVAL;
+	}
+
+	retval = of_address_to_resource(dn, 0, &res);
+	if (retval) {
+		dev_err(dev, "Error parsing memory region!\n");
+		return retval;
+	}
+
+	chips_no = of_get_property(dn, "chips", &len);
+	if (!chips_no || len != sizeof(*chips_no)) {
+		dev_err(dev, "Invalid/missing 'chips' property!\n");
+		return -EINVAL;
+	}
+
+	regs_paddr = res.start;
+	regs_size = res.end - res.start + 1;
+
+	if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) {
+		dev_err(dev, "Error requesting memory region!\n");
+		return -EBUSY;
+	}
+
+	prv->regs = devm_ioremap(dev, regs_paddr, regs_size);
+	if (!prv->regs) {
+		dev_err(dev, "Error mapping memory region!\n");
+		return -ENOMEM;
+	}
+
+	prv->data_buffers = dma_alloc_coherent(dev, DATA_BUFFER_MAX_SIZE,
+                       &prv->data_buffers_phyaddr, GFP_KERNEL);
+	if (!prv->data_buffers) {
+		return -ENOMEM;
+	}
+
+	prv->ops_buffer = dma_alloc_coherent(dev, SPARE_BUFFER_MAX_SIZE,
+                       &prv->ops_buffer_phyaddr, GFP_KERNEL);
+	if (!prv->ops_buffer) {
+		dma_free_coherent(dev, DATA_BUFFER_MAX_SIZE,
+				prv->data_buffers, prv->data_buffers_phyaddr);
+		return -ENOMEM;
+	}
+
+	/* Enable NFC clock */
+	prv->clk = clk_get(dev, "nfc_clk");
+	if (!prv->clk) {
+		dev_err(dev, "Unable to acquire NFC clock!\n");
+		retval = -ENODEV;
+		goto error;
+	}
+
+	clk_enable(prv->clk);
+	init_waitqueue_head(&prv->irq_waitq);
+	retval = devm_request_irq(dev, prv->irq, &mpc5125_nfc_irq,
+			0, DRV_NAME, mtd);
+	if (retval) {
+		dev_err(dev, "Error requesting IRQ!\n");
+		goto error;
+	}
+
+	mtd->name = "MPC5125 NAND";
+	chip->write_page = chip_nand_write_page;
+	chip->dev_ready = mpc5125_nfc_dev_ready;
+	chip->cmdfunc = mpc5125_nfc_command;
+	chip->read_byte = mpc5125_nfc_read_byte;
+	chip->read_word = mpc5125_nfc_read_word;
+	chip->read_buf = mpc5125_nfc_read_buf;
+	chip->write_buf = mpc5125_nfc_write_buf;
+	chip->verify_buf = mpc5125_nfc_verify_buf;
+	chip->select_chip = ads5125_select_chip;
+	chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN;
+
+#ifdef CONFIG_MTD_NAND_MPC5125_HWECC
+	chip->ecc.read_page = mpc5125_nand_read_page;
+	chip->ecc.write_page = mpc5125_nand_write_page;
+	chip->ecc.read_oob = mpc5125_nand_read_oob;
+	chip->ecc.write_oob = mpc5125_nand_write_oob;
+	chip->ecc.calculate = mpc5125_nand_calculate_ecc;
+	chip->ecc.hwctl = mpc5125_nand_enable_hwecc;
+	chip->ecc.correct = mpc5125_nand_correct_data;
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = 512;	/* RS-ECC is applied for both MAIN+SPARE not MAIN alone */
+	chip->ecc.bytes = 9;	/* used for both main and spare area */
+	chip->ecc.layout = &nand_hw_eccoob_4k_128;
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_ECC_SRAM_ADDR_MASK,
+		CONFIG_ECC_SRAM_ADDR_SHIFT,
+		(MPC5125_NFC_ECC_STATUS_ADD>>3) & 0x00001ff);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_ECC_MODE_MASK,
+		CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_CMD_TIMEOUT_MASK,
+		CONFIG_CMD_TIMEOUT_SHIFT, 0xf);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_ECC_SRAM_REQ_MASK,
+		CONFIG_ECC_SRAM_REQ_SHIFT, 1);
+
+#else
+#if NFC_DMA_ENABLE
+	chip->ecc.read_page_raw = nand_read_page_raw;
+	chip->ecc.write_page_raw = nand_write_page_raw;
+#endif
+	chip->ecc.mode = NAND_ECC_SOFT;
+	chip->ecc.layout = &nand_hw_eccoob_4k_128;
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_ECC_MODE_MASK,
+		CONFIG_ECC_MODE_SHIFT, ECC_BYPASS);
+
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+		CONFIG_ECC_SRAM_REQ_MASK,
+		CONFIG_ECC_SRAM_REQ_SHIFT, 0);
+#endif /* CONFIG_MTD_NAND_MPC5125_HWECC */
+
+	/* SET SECTOR SIZE */
+	nfc_write(mtd, NFC_SECTOR_SIZE, PAGE_virtual_2K);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_PAGE_CNT_MASK,
+			CONFIG_PAGE_CNT_SHIFT, 2);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_ADDR_AUTO_INCR_MASK,
+			CONFIG_ADDR_AUTO_INCR_SHIFT, 0);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_BUFNO_AUTO_INCR_MASK,
+			CONFIG_BUFNO_AUTO_INCR_SHIFT, 1);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_16BIT_MASK,
+			CONFIG_16BIT_SHIFT, 0);
+
+#if NFC_DMA_ENABLE
+	nfc_set_field(mtd, NFC_DMA_CONFIG, DMA_CONFIG_DMA1_CNT_MASK,
+			DMA_CONFIG_DMA1_CNT_SHIFT, PAGE_2K);
+	nfc_set_field(mtd, NFC_DMA_CONFIG, DMA_CONFIG_DMA2_CNT_MASK,
+			DMA_CONFIG_DMA2_CNT_SHIFT, PAGE_64);
+	nfc_set_field(mtd, NFC_DMA_CONFIG, DMA_CONFIG_DMA1_ACT_MASK,
+			DMA_CONFIG_DMA1_ACT_SHIFT, 1);
+	nfc_set_field(mtd, NFC_DMA_CONFIG, DMA_CONFIG_DMA2_OFFSET_MASK,
+			DMA_CONFIG_DMA2_OFFSET_SHIFT, (PAGE_2K>>1));
+	nfc_set_field(mtd, NFC_DMA_CONFIG, DMA_CONFIG_DMA2_ACT_MASK,
+			DMA_CONFIG_DMA2_ACT_SHIFT, 1);
+#endif
+
+	/* SET FAST_FLASH = 1 */
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_FAST_FLASH_MASK,
+			CONFIG_FAST_FLASH_SHIFT, 1);
+	nfc_set_field(mtd, NFC_FLASH_CONFIG,
+			CONFIG_BOOT_MODE_MASK,
+			CONFIG_BOOT_MODE_SHIFT, 0);
+
+	/* Detect NAND chips */
+	if (nand_scan(mtd, be32_to_cpup(chips_no))) {
+		dev_err(dev, "NAND Flash not found !\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -ENXIO;
+		goto error;
+	}
+
+	dev_set_drvdata(dev, mtd);
+
+	/* Register device in MTD */
+#ifdef CONFIG_MTD_PARTITIONS
+	retval = parse_mtd_partitions(mtd, mpc5125_nfc_pprobes, &parts, 0);
+#ifdef CONFIG_MTD_OF_PARTS
+	if (retval == 0)
+		retval = of_mtd_parse_partitions(dev, dn, &parts);
+#endif
+	if (retval < 0) {
+		dev_err(dev, "Error parsing MTD partitions!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		retval = -EINVAL;
+		goto error;
+	}
+
+	if (retval > 0)
+		retval = add_mtd_partitions(mtd, parts, retval);
+	else
+#endif
+		retval = add_mtd_device(mtd);
+
+	if (retval) {
+		dev_err(dev, "Error adding MTD device!\n");
+		devm_free_irq(dev, prv->irq, mtd);
+		goto error;
+	}
+
+	return 0;
+error:
+	dma_free_coherent(dev, DATA_BUFFER_MAX_SIZE, prv->data_buffers, prv->data_buffers_phyaddr);
+	dma_free_coherent(dev, SPARE_BUFFER_MAX_SIZE, prv->ops_buffer, prv->ops_buffer_phyaddr);
+	mpc5125_nfc_free(dev, mtd);
+	return retval;
+}
+
+static int __exit mpc5125_nfc_remove(struct platform_device *op)
+{
+	struct device *dev = &op->dev;
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct nand_chip *chip = mtd->priv;
+	struct mpc5125_nfc_prv *prv = chip->priv;
+
+	nand_release(mtd);
+	devm_free_irq(dev, prv->irq, mtd);
+	dma_free_coherent(dev, DATA_BUFFER_MAX_SIZE, prv->data_buffers, prv->data_buffers_phyaddr);
+	dma_free_coherent(dev, SPARE_BUFFER_MAX_SIZE, prv->ops_buffer, prv->ops_buffer_phyaddr);
+	mpc5125_nfc_free(dev, mtd);
+
+	return 0;
+}
+
+static struct of_device_id mpc5125_nfc_match[] __devinitdata = {
+	{ .compatible = "fsl,mpc5125-nfc", },
+	{},
+};
+
+static struct platform_driver mpc5125_nfc_driver = {
+	.probe		= mpc5125_nfc_probe,
+	.remove		= __devexit_p(mpc5125_nfc_remove),
+	.driver		= {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = mpc5125_nfc_match,
+	},
+};
+
+static int __init mpc5125_nfc_init(void)
+{
+	return platform_driver_register(&mpc5125_nfc_driver);
+}
+
+module_init(mpc5125_nfc_init);
+
+static void __exit mpc5125_nfc_cleanup(void)
+{
+	platform_driver_unregister(&mpc5125_nfc_driver);
+}
+
+module_exit(mpc5125_nfc_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MPC5125 NAND MTD driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/mpc5125_nfc.h b/drivers/mtd/nand/mpc5125_nfc.h
new file mode 100644
index 0000000..5cb312c
--- /dev/null
+++ b/drivers/mtd/nand/mpc5125_nfc.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Shaohui Xie <b21989@freescale.com>
+ *
+ * Description:
+ * MPC5125 Nand driver.
+ *
+ * This 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.
+ */
+
+#ifndef MPC5125_NFC_H
+#define MPC5125_NFC_H
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n)	((n) *  0x1000)
+
+/* Addresses for NFC SPARE BUFFER areas */
+#define NFC_SPARE_BUFFERS		8
+#define NFC_SPARE_LEN			0x10
+#define NFC_SPARE_AREA(n)		(0x800 + NFC_MAIN_AREA(n))
+
+#define PAGE_2K                   	0x0800
+#define PAGE_virtual_2K          0x0840
+#define PAGE_64                   	0x0040
+
+/* MPC5125 NFC registers */
+/* Typical Flash Commands */
+#define READ_PAGE_CMD_CODE		0x7EE0
+#define DMA_READ_PAGE_CMD_CODE		0x7EE0
+#define PROGRAM_PAGE_CMD_CODE		0x7FC0
+#define ERASE_CMD_CODE			0x4EC0
+#define READ_ID_CMD_CODE		0x4804
+#define RESET_CMD_CODE			0x4040
+#define DMA_PROGRAM_PAGE_CMD_CODE	0xFFC0
+#define RANDOM_IN_CMD_CODE		0x7140
+#define RANDOM_OUT_CMD_CODE		0x70E0
+#define STATUS_READ_CMD_CODE		0x4068
+
+#define PAGE_READ_CMD_BYTE1		0x00
+#define PAGE_READ_CMD_BYTE2		0x30
+#define PROGRAM_PAGE_CMD_BYTE1		0x80
+#define PROGRAM_PAGE_CMD_BYTE2		0x10
+#define READ_STATUS_CMD_BYTE		0x70
+#define ERASE_CMD_BYTE1		0x60
+#define ERASE_CMD_BYTE2		0xD0
+#define READ_ID_CMD_BYTE		0x90
+#define RESET_CMD_BYTE			0xFF
+#define RANDOM_OUT_CMD_BYTE1		0x05
+#define RANDOM_OUT_CMD_BYTE2		0xE0
+
+/* NFC ECC mode define */
+#define ECC_BYPASS			0x0
+#define ECC_8_BYTE			0x1
+#define ECC_12_BYTE			0x2
+#define ECC_15_BYTE			0x3
+#define ECC_23_BYTE			0x4
+#define ECC_30_BYTE			0x5
+#define ECC_45_BYTE			0x6
+#define ECC_60_BYTE			0x7
+#define ECC_ERROR			1
+#define ECC_RIGHT			0
+
+/***************** Module-Relative Register Offsets *************************/
+#define NFC_SRAM_BUFFER                0x0000
+#define NFC_FLASH_CMD1 		0x3F00
+#define NFC_FLASH_CMD2			0x3F04
+#define NFC_COL_ADDR			0x3F08
+#define NFC_ROW_ADDR			0x3F0c
+#define NFC_FLASH_COMMAND_REPEAT	0x3F10
+#define NFC_ROW_ADDR_INC		0x3F14
+#define NFC_FLASH_STATUS1		0x3F18
+#define NFC_FLASH_STATUS2		0x3F1c
+#define NFC_DMA1_ADDR			0x3F20
+#define NFC_DMA2_ADDR			0x3F34
+#define NFC_DMA_CONFIG			0x3F24
+#define NFC_CACHE_SWAP			0x3F28
+#define NFC_SECTOR_SIZE		0x3F2c
+#define NFC_FLASH_CONFIG		0x3F30
+#define NFC_IRQ_STATUS			0x3F38
+
+/***************** Module-Relative Register Reset Value *********************/
+#define NFC_SRAM_BUFFER_RSTVAL                	0x00000000
+#define NFC_FLASH_CMD1_RSTVAL 			0x30FF0000
+#define NFC_FLASH_CMD2_RSTVAL			0x007EE000
+#define NFC_COL_ADDR_RSTVAL			0x00000000
+#define NFC_ROW_ADDR_RSTVAL			0x11000000
+#define NFC_FLASH_COMMAND_REPEAT_RSTVAL	0x00000000
+#define NFC_ROW_ADDR_INC_RSTVAL		0x00000001
+#define NFC_FLASH_STATUS1_RSTVAL		0x00000000
+#define NFC_FLASH_STATUS2_RSTVAL		0x00000000
+#define NFC_DMA1_ADDR_RSTVAL			0x00000000
+#define NFC_DMA2_ADDR_RSTVAL			0x00000000
+#define NFC_DMA_CONFIG_RSTVAL			0x00000000
+#define NFC_CACHE_SWAP_RSTVAL			0x0FFE0FFE
+#define NFC_SECTOR_SIZE_RSTVAL			0x00000420
+#define NFC_FLASH_CONFIG_RSTVAL		0x000EA631
+#define NFC_IRQ_STATUS_RSTVAL			0x04000000
+
+/***************** Module-Relative Register Mask *************************/
+
+/* NFC_FLASH_CMD1 Field */
+#define CMD1_MASK				0xFFFF0000
+#define CMD1_SHIFT				0
+#define CMD_BYTE2_MASK    			0xFF000000
+#define CMD_BYTE2_SHIFT   			24
+#define CMD_BYTE3_MASK    			0x00FF0000
+#define CMD_BYTE3_SHIFT   			16
+
+/* NFC_FLASH_CM2 Field */
+#define CMD2_MASK				0xFFFFFF07
+#define CMD2_SHIFT				0
+#define CMD_BYTE1_MASK			    	0xFF000000
+#define CMD_BYTE1_SHIFT   			24
+#define CMD_CODE_MASK				0x00FFFF00
+#define CMD_CODE_SHIFT				8
+#define BUFNO_MASK				0x00000006
+#define BUFNO_SHIFT				1
+#define BUSY_MASK				0x00000001
+#define BUSY_SHIFT				0
+#define START_MASK				0x00000001
+#define START_SHIFT				0
+
+/* NFC_COL_ADDR Field */
+#define COL_ADDR_MASK				0x0000FFFF
+#define COL_ADDR_SHIFT				0
+#define COL_ADDR_COL_ADDR2_MASK		0x0000FF00
+#define COL_ADDR_COL_ADDR2_SHIFT		8
+#define COL_ADDR_COL_ADDR1_MASK		0x000000FF
+#define COL_ADDR_COL_ADDR1_SHIFT		0
+
+/* NFC_ROW_ADDR Field */
+#define ROW_ADDR_MASK				0x00FFFFFF
+#define ROW_ADDR_SHIFT				0
+#define ROW_ADDR_CHIP_SEL_RB_MASK		0xF0000000
+#define ROW_ADDR_CHIP_SEL_RB_SHIFT		28
+#define ROW_ADDR_CHIP_SEL_MASK			0x0F000000
+#define ROW_ADDR_CHIP_SEL_SHIFT		24
+#define ROW_ADDR_ROW_ADDR3_MASK		0x00FF0000
+#define ROW_ADDR_ROW_ADDR3_SHIFT		16
+#define ROW_ADDR_ROW_ADDR2_MASK		0x0000FF00
+#define ROW_ADDR_ROW_ADDR2_SHIFT		8
+#define ROW_ADDR_ROW_ADDR1_MASK		0x000000FF
+#define ROW_ADDR_ROW_ADDR1_SHIFT		0
+
+/* NFC_FLASH_COMMAND_REPEAT Field */
+#define COMMAND_REPEAT_MASK			0x0000FFFF
+#define COMMAND_REPEAT_SHIFT			0
+#define COMMAND_REPEAT_REPEAT_COUNT_MASK	0x0000FFFF
+#define COMMAND_REPEAT_REPEAT_COUNT_SHIFT	0
+
+/* NFC_ROW_ADDR_INC Field */
+#define ROW_ADDR_INC_MASK			0x00FFFFFF
+#define ROW_ADDR_INC_SHIFT			0
+#define ROW_ADDR_INC_ROW_ADDR3_INC_MASK	0x00FF0000
+#define ROW_ADDR_INC_ROW_ADDR3_INC_SHIFT	16
+#define ROW_ADDR_INC_ROW_ADDR2_INC_MASK	0x0000FF00
+#define ROW_ADDR_INC_ROW_ADDR2_INC_SHIFT	8
+#define ROW_ADDR_INC_ROW_ADDR1_INC_MASK	0x000000FF
+#define ROW_ADDR_INC_ROW_ADDR1_INC_SHIFT	0
+
+/* NFC_FLASH_STATUS1 Field */
+#define STATUS1_MASK				0xFFFFFFFF
+#define STATUS1_SHIFT				0
+#define STATUS1_ID_BYTE1_MASK			0xFF000000
+#define STATUS1_ID_BYTE1_SHIFT			24
+#define STATUS1_ID_BYTE2_MASK			0x00FF0000
+#define STATUS1_ID_BYTE2_SHIFT			16
+#define STATUS1_ID_BYTE3_MASK			0x0000FF00
+#define STATUS1_ID_BYTE3_SHIFT			8
+#define STATUS1_ID_BYTE4_MASK			0x000000FF
+#define STATUS1_ID_BYTE4_SHIFT			0
+
+/* NFC_FLASH_STATUS2 Field */
+#define STATUS2_MASK				0xFF0000FF
+#define STATUS2_SHIFT				0
+#define STATUS2_ID_BYTE5_MASK			0xFF000000
+#define STATUS2_ID_BYTE5_SHIFT			24
+#define STATUS_BYTE1_MASK			0x000000FF
+#define STATUS2_STATUS_BYTE1_SHIFT		0
+
+/* NFC_DMA1_ADDR Field */
+#define DMA1_ADDR_MASK				0xFFFFFFFF
+#define DMA1_ADDR_SHIFT			0
+#define DMA1_ADDR_DMA1_ADDR_MASK		0xFFFFFFFF
+#define DMA1_ADDR_DMA1_ADDR_SHIFT		0
+
+/* DMA2_ADDR Field */
+#define DMA2_ADDR_MASK				0xFFFFFFFF
+#define DMA2_ADDR_SHIFT			0
+#define DMA2_ADDR_DMA2_ADDR_MASK		0xFFFFFFFF
+#define DMA2_ADDR_DMA2_ADDR_SHIFT		0
+
+/* DMA_CONFIG Field */
+#define DMA_CONFIG_MASK			0xFFFFFFFF
+#define DMA_CONFIG_SHIFT			0
+#define DMA_CONFIG_DMA1_CNT_MASK		0xFFF00000
+#define DMA_CONFIG_DMA1_CNT_SHIFT		20
+#define DMA_CONFIG_DMA2_CNT_MASK		0x000FE000
+#define DMA_CONFIG_DMA2_CNT_SHIFT		13
+#define DMA_CONFIG_DMA2_OFFSET_MASK		0x00001FC0
+#define DMA_CONFIG_DMA2_OFFSET_SHIFT		2
+#define DMA_CONFIG_DMA1_ACT_MASK		0x00000002
+#define DMA_CONFIG_DMA1_ACT_SHIFT		1
+#define DMA_CONFIG_DMA2_ACT_MASK		0x00000001
+#define DMA_CONFIG_DMA2_ACT_SHIFT		0
+
+/* NFC_CACHE_SWAP Field */
+#define CACHE_SWAP_MASK			0x0FFE0FFE
+#define CACHE_SWAP_SHIFT			1
+#define CACHE_SWAP_CACHE_SWAP_ADDR2_MASK	0x0FFE0000
+#define CACHE_SWAP_CACHE_SWAP_ADDR2_SHIFT	17
+#define CACHE_SWAP_CACHE_SWAP_ADDR1_MASK	0x00000FFE
+#define CACHE_SWAP_CACHE_SWAP_ADDR1_SHIFT	1
+
+/* NFC_SECTOR_SIZE Field */
+#define SECTOR_SIZE_MASK			0x00001FFF
+#define SECTOR_SIZE_SHIFT			0
+#define SECTOR_SIZE_SECTOR_SIZE_MASK		0x00001FFF
+#define SECTOR_SIZE_SECTOR_SIZE_SHIFT		0
+
+/* NFC_FLASH_CONFIG Field */
+#define CONFIG_MASK				0xFFFFFFFF
+#define CONFIG_SHIFT				0
+#define CONFIG_STOP_ON_WERR_MASK		0x80000000
+#define CONFIG_STOP_ON_WERR_SHIFT		31
+#define CONFIG_ECC_SRAM_ADDR_MASK		0x7FC00000
+#define CONFIG_ECC_SRAM_ADDR_SHIFT		22
+#define CONFIG_ECC_SRAM_REQ_MASK		0x00200000
+#define CONFIG_ECC_SRAM_REQ_SHIFT		21
+#define CONFIG_DMA_REQ_MASK			0x00100000
+#define CONFIG_DMA_REQ_SHIFT			20
+#define CONFIG_ECC_MODE_MASK			0x000E0000
+#define CONFIG_ECC_MODE_SHIFT			17
+#define CONFIG_FAST_FLASH_MASK			0x00010000
+#define CONFIG_FAST_FLASH_SHIFT		16
+#define CONFIG_ID_COUNT_MASK			0x0000E000
+#define CONFIG_ID_COUNT_SHIFT			13
+#define CONFIG_CMD_TIMEOUT_MASK		0x00001F00
+#define CONFIG_CMD_TIMEOUT_SHIFT		8
+#define CONFIG_16BIT_MASK			0x00000080
+#define CONFIG_16BIT_SHIFT			7
+#define CONFIG_BOOT_MODE_MASK			0x00000040
+#define CONFIG_BOOT_MODE_SHIFT			6
+#define CONFIG_ADDR_AUTO_INCR_MASK		0x00000020
+#define CONFIG_ADDR_AUTO_INCR_SHIFT		5
+#define CONFIG_BUFNO_AUTO_INCR_MASK		0x00000010
+#define CONFIG_BUFNO_AUTO_INCR_SHIFT		4
+#define CONFIG_PAGE_CNT_MASK			0x0000000F
+#define CONFIG_PAGE_CNT_SHIFT			0
+
+/* NFC_IRQ_STATUS Field */
+#define MASK					0xEFFC003F
+#define SHIFT					0
+#define WERR_IRQ_MASK				0x80000000
+#define WERR_IRQ_SHIFT				31
+#define CMD_DONE_IRQ_MASK			0x40000000
+#define CMD_DONE_IRQ_SHIFT			30
+#define IDLE_IRQ_MASK				0x20000000
+#define IDLE_IRQ_SHIFT				29
+#define WERR_STATUS_MASK			0x08000000
+#define WERR_STATUS_SHIFT			27
+#define FLASH_CMD_BUSY_MASK			0x04000000
+#define FLASH_CMD_BUSY_SHIFT			26
+#define RESIDUE_BUSY_MASK			0x02000000
+#define RESIDUE_BUSY_SHIFT			25
+#define ECC_BUSY_MASK				0x01000000
+#define ECC_BUSY_SHIFT				24
+#define DMA_BUSY_MASK				0x00800000
+#define DMA_BUSY_SHIFT				23
+#define WERR_EN_MASK				0x00400000
+#define WERR_EN_SHIFT				22
+#define CMD_DONE_EN_MASK			0x00200000
+#define CMD_DONE_EN_SHIFT			21
+#define IDLE_EN_MASK				0x00100000
+#define IDLE_EN_SHIFT				20
+#define WERR_CLEAR_MASK			0x00080000
+#define WERR_CLEAR_SHIFT			19
+#define CMD_DONE_CLEAR_MASK			0x00040000
+#define CMD_DONE_CLEAR_SHIFT			18
+#define IDLE_CLEAR_MASK			0x00020000
+#define IDLE_CLEAR_SHIFT			17
+#define RESIDUE_BUFF_NO_MASK			0x00000030
+#define RESIDUE_BUFF_NO_SHIFT			4
+#define ECC_BUFF_NO_MASK			0x000000C0
+#define ECC_BUFF_NO_SHIFT			2
+#define DMA_BUFF_NO_MASK			0x00000003
+
+#endif /* MPC5125_NFC_H */
+
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 00cf1b0..6755191 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -66,6 +66,8 @@ struct nand_flash_dev nand_flash_ids[] = {
 
 	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, 0},
 
+	{"NAND 4GiB 3,3V 8-bit",	0x68, 4096, 4096, 0x100000, 0},
+
 	/*
 	 * These are the new chips with large page size. The pagesize and the
 	 * erasesize is determined from the extended id bytes

^ permalink raw reply related

* [PATCH v2] gianfar: Fall back to software tcp/udp checksum on older controllers
From: Alex Dubov @ 2011-03-17  3:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, linuxppc-dev, davem, mlcreech

As specified by errata eTSEC49 of MPC8548 and errata eTSEC12 of MPC83xx,=0A=
older revisions of gianfar controllers will be unable to calculate a TCP/UD=
P=0Apacket checksum for some alignments of the appropriate FCB. This patch =
checks=0Afor FCB alignment on such controllers and falls back to software c=
hecksumming=0Aif the alignment is known to be bad.=0A=0ASigned-off-by: Alex=
 Dubov <oakad@yahoo.com>=0A---=0ACan we, please, proceed with this patch?=
=0AThe issue is badly annoying, breaking quite a few of the MPC8548 chips.=
=0A=0AChanges for v2:=0A   - Make indentation slightly more consistent.=0A =
  - Replace bizarre switch-based condition with plain boring one.=0A=0A dri=
vers/net/gianfar.c |   16 ++++++++++++++--=0A drivers/net/gianfar.h |    1 =
+=0A 2 files changed, 15 insertions(+), 2 deletions(-)=0A=0Adiff --git a/dr=
ivers/net/gianfar.c b/drivers/net/gianfar.c=0Aindex 5ed8f9f..3da19a5 100644=
=0A--- a/drivers/net/gianfar.c=0A+++ b/drivers/net/gianfar.c=0A@@ -950,6 +9=
50,11 @@ static void gfar_detect_errata(struct gfar_private *priv)=0A =09=
=09=09(pvr =3D=3D 0x80861010 && (mod & 0xfff9) =3D=3D 0x80c0))=0A =09=09pri=
v->errata |=3D GFAR_ERRATA_A002;=0A =0A+=09/* MPC8313 Rev < 2.0, MPC8548 re=
v 2.0 */=0A+=09if ((pvr =3D=3D 0x80850010 && mod =3D=3D 0x80b0 && rev < 0x0=
020) ||=0A+=09=09=09(pvr =3D=3D 0x80210020 && mod =3D=3D 0x8030 && rev =3D=
=3D 0x0020))=0A+=09=09priv->errata |=3D GFAR_ERRATA_12;=0A+=0A =09if (priv-=
>errata)=0A =09=09dev_info(dev, "enabled errata workarounds, flags: 0x%x\n"=
,=0A =09=09=09 priv->errata);=0A@@ -2156,8 +2161,15 @@ static int gfar_star=
t_xmit(struct sk_buff *skb, struct net_device *dev)=0A =09/* Set up checksu=
mming */=0A =09if (CHECKSUM_PARTIAL =3D=3D skb->ip_summed) {=0A =09=09fcb =
=3D gfar_add_fcb(skb);=0A-=09=09lstatus |=3D BD_LFLAG(TXBD_TOE);=0A-=09=09g=
far_tx_checksum(skb, fcb);=0A+=09=09/* as specified by errata */=0A+=09=09i=
f (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12)=0A+=09=09=09     && ((uns=
igned long)fcb % 0x20) > 0x18)) {=0A+=09=09=09__skb_pull(skb, GMAC_FCB_LEN)=
;=0A+=09=09=09skb_checksum_help(skb);=0A+=09=09} else {=0A+=09=09=09lstatus=
 |=3D BD_LFLAG(TXBD_TOE);=0A+=09=09=09gfar_tx_checksum(skb, fcb);=0A+=09=09=
}=0A =09}=0A =0A =09if (vlan_tx_tag_present(skb)) {=0Adiff --git a/drivers/=
net/gianfar.h b/drivers/net/gianfar.h=0Aindex 54de413..ec5d595 100644=0A---=
 a/drivers/net/gianfar.h=0A+++ b/drivers/net/gianfar.h=0A@@ -1039,6 +1039,7=
 @@ enum gfar_errata {=0A =09GFAR_ERRATA_74=09=09=3D 0x01,=0A =09GFAR_ERRAT=
A_76=09=09=3D 0x02,=0A =09GFAR_ERRATA_A002=09=3D 0x04,=0A+=09GFAR_ERRATA_12=
=09=09=3D 0x08, /* a.k.a errata eTSEC49 */=0A };=0A =0A /* Struct stolen al=
most completely (and shamelessly) from the FCC enet source=0A-- =0A1.7.3.2=
=0A=0A=0A=0A=0A      

^ permalink raw reply

* Re: [PATCH v2] powerpc/ptrace: remove BUG_ON when full register set not available
From: Paul Mackerras @ 2011-03-17  4:20 UTC (permalink / raw)
  To: mjw; +Cc: linuxppc-dev, mikey, anton
In-Reply-To: <1300282642.15145.2.camel@w500>

On Wed, Mar 16, 2011 at 08:37:22AM -0500, Michael Wolf wrote:

> In some cases during a threaded core dump not all 
> the threads will have a full register set.  This
> will cause problems when the sigkill is sent to
> the thread.  To solve this problem a poison value
> (0xdeadbeef) will be placed in the buffer in place 
> of the actual register values.  This will affect
> gpr14 to gpr31.

To be clear, this happens when the signal causing the core dump races
with a thread exiting.  The race happens when the exiting thread has
entered the kernel for the last time before the signal arrives, but
doesn't get far enough through the exit code to avoid being included
in the core dump.  So we get a thread included in the core dump which
is never going to go out to userspace again and only has a partial
register set recorded.  Normally we would catch each thread as it is
about to go into userspace and capture the full register set then.
However, this exiting thread is never going to go out to userspace
again, so we have no way to capture its full register set.  It doesn't
really matter, though, as this is a thread which is effectively
already dead.

Paul.

^ permalink raw reply

* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-03-17  6:12 UTC (permalink / raw)
  To: Paul Mundt
  Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
	linux-kernel, Ben Dooks, Randy Dunlap, linuxppc-dev,
	Wolfgang Denk
In-Reply-To: <20110316153601.GA13315@linux-sh.org>

Hello Paul,

Paul Mundt schrieb:
> On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
>>> 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
>>>
>>>  Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++
>>>  drivers/mfd/sm501.c                          |    9 +++++-
>>>  drivers/video/sm501fb.c                      |   42 ++++++++++++++++++++++++--
>>>  3 files changed, 81 insertions(+), 4 deletions(-)
>>>  create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>> This patchset is pending know for a while. I got Acked by from
>>
>> Samuel Ortiz for the mfd part, see here:
>>
>> http://www.spinics.net/lists/linux-fbdev/msg02550.html
>> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>>
>> and for the DTS part from Benjamin Herrenschmidt:
>>
>> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
>>
>> Are there some more issues?
>>
> Not that I remember off the top of my head, but I think they've been lost
> in my backlog. Could you re-send the current series with the appropriate
> acked-bys? If there's nothing else obvious outstanding I'll roll them in.

Ok, I resend them (I also rebase them to current tree, ok?)

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* [RFC/PATCH] powerpc: Rewrite XICS driver
From: Benjamin Herrenschmidt @ 2011-03-17  6:57 UTC (permalink / raw)
  To: linuxppc-dev

Hi Folks !

This is for comments at this stage. There are various reasons why I wanted
to rewrite (more than just refactor) the XICS driver. The main one is that
I want a better split between the various ICP (presentation) and ICS (source)
backends, especially with various new ones coming up soon.

Now one could argue that it would be generally easier to review if the
patch had been instead a long series of incremental move code / change
code, but that isn't how I did it as I basically wrote a new one from
scratch picking up code left & right and modifying it, and at this stage
I do not have the bandwidth to recreate the patch completely along this
process.

On the flip side, this is mostly for comments at this stage, and either
I may get to do the above patch splitting, or at least I will get it
thoroughly tested. This is eased by the fact that at this point, this
is only used on pSeries. (and yes, I did test old Power4 bare metal :-)

After that, I plan to drop in eventually new backends for native ICS
and at least one other variant not released yet, and bring in on some
code (reworked from our internal BML tree) that can configure the links
in the ICPs v2 and use them appropriately for interrupt distribution
when not using pHyp.

Not-signed-off-yet-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/xics.h                 |  139 ++++
 arch/powerpc/platforms/pseries/Kconfig          |    5 +-
 arch/powerpc/platforms/pseries/Makefile         |    1 -
 arch/powerpc/platforms/pseries/hotplug-cpu.c    |    3 +-
 arch/powerpc/platforms/pseries/kexec.c          |    5 +-
 arch/powerpc/platforms/pseries/plpar_wrappers.h |   27 -
 arch/powerpc/platforms/pseries/setup.c          |    8 +-
 arch/powerpc/platforms/pseries/smp.c            |   17 +-
 arch/powerpc/platforms/pseries/xics.c           |  943 -----------------------
 arch/powerpc/platforms/pseries/xics.h           |   23 -
 arch/powerpc/sysdev/Kconfig                     |    3 +
 arch/powerpc/sysdev/Makefile                    |    4 +
 arch/powerpc/sysdev/xics/Kconfig                |   12 +
 arch/powerpc/sysdev/xics/Makefile               |    6 +
 arch/powerpc/sysdev/xics/icp-hv.c               |  183 +++++
 arch/powerpc/sysdev/xics/icp-native.c           |  312 ++++++++
 arch/powerpc/sysdev/xics/ics-rtas.c             |  231 ++++++
 arch/powerpc/sysdev/xics/xics-common.c          |  458 +++++++++++
 18 files changed, 1369 insertions(+), 1011 deletions(-)
 create mode 100644 arch/powerpc/include/asm/xics.h
 delete mode 100644 arch/powerpc/platforms/pseries/xics.c
 delete mode 100644 arch/powerpc/platforms/pseries/xics.h
 create mode 100644 arch/powerpc/sysdev/xics/Kconfig
 create mode 100644 arch/powerpc/sysdev/xics/Makefile
 create mode 100644 arch/powerpc/sysdev/xics/icp-hv.c
 create mode 100644 arch/powerpc/sysdev/xics/icp-native.c
 create mode 100644 arch/powerpc/sysdev/xics/ics-rtas.c
 create mode 100644 arch/powerpc/sysdev/xics/xics-common.c

diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
new file mode 100644
index 0000000..faa0c60
--- /dev/null
+++ b/arch/powerpc/include/asm/xics.h
@@ -0,0 +1,139 @@
+/*
+ * Common definitions accross all variants of ICP and ICS interrupt
+ * controllers.
+ */
+
+#ifndef _XICS_H
+#define _XICS_H
+
+#define XICS_IPI		2
+#define XICS_IRQ_SPURIOUS	0
+
+/* Want a priority other than 0.  Various HW issues require this. */
+#define	DEFAULT_PRIORITY	5
+
+/*
+ * Mark IPIs as higher priority so we can take them inside interrupts that
+ * arent marked IRQF_DISABLED
+ */
+#define IPI_PRIORITY		4
+
+/* The least favored priority */
+#define LOWEST_PRIORITY		0xFF
+
+/* The number of priorities defined above */
+#define MAX_NUM_PRIORITIES	3
+
+/* Native ICP */
+extern int icp_native_init(void);
+
+/* PAPR ICP */
+extern int icp_hv_init(void);
+
+/* ICP ops */
+struct icp_ops {
+	unsigned int (*get_irq)(void);
+	void (*eoi)(unsigned int virq);
+	void (*set_priority)(unsigned char prio);
+	void (*teardown_cpu)(void);
+	void (*flush_ipi)(void);
+#ifdef CONFIG_SMP
+	void (*message_pass)(int target, int msg);
+	irq_handler_t ipi_action;
+#endif
+};
+
+extern const struct icp_ops *icp_ops;
+
+/* Native ICS */
+extern int ics_native_init(void);
+
+/* RTAS ICS */
+extern int ics_rtas_init(void);
+
+/* ICS instance, hooked up to chip_data of an irq */
+struct ics {
+	struct list_head link;
+	int (*map)(struct ics *ics, unsigned int virq);
+	void (*mask_unknown)(struct ics *ics, unsigned long vec);
+	long (*get_server)(struct ics *ics, unsigned long vec);
+	char data[];
+};
+
+/* Commons */
+extern unsigned int xics_default_server;
+extern unsigned int xics_default_distrib_server;
+extern unsigned int xics_interrupt_server_size;
+extern struct irq_host *xics_host;
+
+struct xics_cppr {
+	unsigned char stack[MAX_NUM_PRIORITIES];
+	int index;
+};
+
+DECLARE_PER_CPU(struct xics_cppr, xics_cppr);
+
+static inline void xics_push_cppr(unsigned int vec)
+{
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+
+	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
+		return;
+
+	if (vec == XICS_IPI)
+		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
+	else
+		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
+}
+
+static inline unsigned char xics_pop_cppr(void)
+{
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+
+	if (WARN_ON(os_cppr->index < 1))
+		return LOWEST_PRIORITY;
+
+	return os_cppr->stack[--os_cppr->index];
+}
+
+static inline void xics_set_base_cppr(unsigned char cppr)
+{
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+
+	/* we only really want to set the priority when there's
+	 * just one cppr value on the stack
+	 */
+	WARN_ON(os_cppr->index != 0);
+
+	os_cppr->stack[0] = cppr;
+}
+
+static inline unsigned char xics_cppr_top(void)
+{
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+	
+	return os_cppr->stack[os_cppr->index];
+}
+
+DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
+
+extern void xics_init(void);
+extern void xics_setup_cpu(void);
+extern void xics_update_irq_servers(void);
+extern void xics_set_cpu_giq(unsigned int gserver, unsigned int join);
+extern void xics_mask_unknown_vec(unsigned int vec);
+extern irqreturn_t xics_ipi_dispatch(int cpu);
+extern int xics_smp_probe(void);
+extern void xics_register_ics(struct ics *ics);
+extern void xics_teardown_cpu(void);
+extern void xics_kexec_teardown_cpu(int secondary);
+extern void xics_migrate_irqs_away(void);
+#ifdef CONFIG_SMP
+extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
+			       unsigned int strict_check);
+#else
+#define xics_get_irq_server(virq, cpumask, strict_check) (xics_default_server)
+#endif
+
+
+#endif /* _XICS_H */
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 5b3da4b..b044922 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -3,7 +3,10 @@ config PPC_PSERIES
 	bool "IBM pSeries & new (POWER5-based) iSeries"
 	select MPIC
 	select PCI_MSI
-	select XICS
+	select PPC_XICS
+	select PPC_ICP_NATIVE
+	select PPC_ICP_HV
+	select PPC_ICS_RTAS
 	select PPC_I8259
 	select PPC_RTAS
 	select PPC_RTAS_DAEMON
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index fc52378..4cfefba 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -5,7 +5,6 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o event_sources.o ras.o \
 			   firmware.o power.o dlpar.o mobility.o
 obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_KEXEC)	+= kexec.o
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index fd50ccd..b9b72f7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
 #include <asm/system.h>
@@ -28,7 +29,7 @@
 #include <asm/machdep.h>
 #include <asm/vdso_datapage.h>
 #include <asm/pSeries_reconfig.h>
-#include "xics.h"
+#include <asm/xics.h>
 #include "plpar_wrappers.h"
 #include "offline_states.h"
 
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index 77d38a5..54cf3a4 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -7,15 +7,18 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+
 #include <asm/machdep.h>
 #include <asm/page.h>
 #include <asm/firmware.h>
 #include <asm/kexec.h>
 #include <asm/mpic.h>
+#include <asm/xics.h>
 #include <asm/smp.h>
 
 #include "pseries.h"
-#include "xics.h"
 #include "plpar_wrappers.h"
 
 static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d980111..4bf2120 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -270,31 +270,4 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
 			lbuf[1]);
 }
 
-static inline long plpar_eoi(unsigned long xirr)
-{
-	return plpar_hcall_norets(H_EOI, xirr);
-}
-
-static inline long plpar_cppr(unsigned long cppr)
-{
-	return plpar_hcall_norets(H_CPPR, cppr);
-}
-
-static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
-{
-	return plpar_hcall_norets(H_IPI, servernum, mfrr);
-}
-
-static inline long plpar_xirr(unsigned long *xirr_ret, unsigned char cppr)
-{
-	long rc;
-	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
-
-	rc = plpar_hcall(H_XIRR, retbuf, cppr);
-
-	*xirr_ret = retbuf[0];
-
-	return rc;
-}
-
 #endif /* _PSERIES_PLPAR_WRAPPERS_H */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index d345bfd..82f632e 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -53,9 +53,9 @@
 #include <asm/irq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
-#include "xics.h"
 #include <asm/pmc.h>
 #include <asm/mpic.h>
+#include <asm/xics.h>
 #include <asm/ppc-pci.h>
 #include <asm/i8259.h>
 #include <asm/udbg.h>
@@ -202,6 +202,9 @@ static void __init pseries_mpic_init_IRQ(void)
 		mpic_assign_isu(mpic, n, isuaddr);
 	}
 
+	/* Setup top-level get_irq */
+	ppc_md.get_irq = mpic_get_irq;
+
 	/* All ISUs are setup, complete initialization */
 	mpic_init(mpic);
 
@@ -211,7 +214,7 @@ static void __init pseries_mpic_init_IRQ(void)
 
 static void __init pseries_xics_init_IRQ(void)
 {
-	xics_init_IRQ();
+	xics_init();
 	pseries_setup_i8259_cascade();
 }
 
@@ -235,7 +238,6 @@ static void __init pseries_discover_pic(void)
 		if (strstr(typep, "open-pic")) {
 			pSeries_mpic_node = of_node_get(np);
 			ppc_md.init_IRQ       = pseries_mpic_init_IRQ;
-			ppc_md.get_irq        = mpic_get_irq;
 			setup_kexec_cpu_down_mpic();
 			smp_init_pseries_mpic();
 			return;
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 5fe1ad6..dfc0789 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -44,10 +44,11 @@
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #include <asm/cputhreads.h>
+#include <asm/mpic.h>
+#include <asm/xics.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
-#include "xics.h"
 #include "offline_states.h"
 
 
@@ -136,7 +137,6 @@ out:
 	return 1;
 }
 
-#ifdef CONFIG_XICS
 static void __devinit smp_xics_setup_cpu(int cpu)
 {
 	if (cpu != boot_cpuid)
@@ -151,7 +151,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
 	set_default_offline_state(cpu);
 #endif
 }
-#endif /* CONFIG_XICS */
 
 static void __devinit smp_pSeries_kick_cpu(int nr)
 {
@@ -197,23 +196,21 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
 
 	return 1;
 }
-#ifdef CONFIG_MPIC
+
 static struct smp_ops_t pSeries_mpic_smp_ops = {
 	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_mpic_probe,
 	.kick_cpu	= smp_pSeries_kick_cpu,
 	.setup_cpu	= smp_mpic_setup_cpu,
 };
-#endif
-#ifdef CONFIG_XICS
+
 static struct smp_ops_t pSeries_xics_smp_ops = {
-	.message_pass	= smp_xics_message_pass,
-	.probe		= smp_xics_probe,
+	.message_pass	= NULL,	/* Filled at runtime by xics_smp_probe() */
+	.probe		= xics_smp_probe,
 	.kick_cpu	= smp_pSeries_kick_cpu,
 	.setup_cpu	= smp_xics_setup_cpu,
 	.cpu_bootable	= smp_pSeries_cpu_bootable,
 };
-#endif
 
 /* This is called very early */
 static void __init smp_init_pseries(void)
@@ -245,14 +242,12 @@ static void __init smp_init_pseries(void)
 	pr_debug(" <- smp_init_pSeries()\n");
 }
 
-#ifdef CONFIG_MPIC
 void __init smp_init_pseries_mpic(void)
 {
 	smp_ops = &pSeries_mpic_smp_ops;
 
 	smp_init_pseries();
 }
-#endif
 
 void __init smp_init_pseries_xics(void)
 {
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
deleted file mode 100644
index 7b96e5a..0000000
--- a/arch/powerpc/platforms/pseries/xics.c
+++ /dev/null
@@ -1,943 +0,0 @@
-/*
- * arch/powerpc/platforms/pseries/xics.c
- *
- * Copyright 2000 IBM Corporation.
- *
- *  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/types.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/radix-tree.h>
-#include <linux/cpu.h>
-#include <linux/msi.h>
-#include <linux/of.h>
-#include <linux/percpu.h>
-
-#include <asm/firmware.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/smp.h>
-#include <asm/rtas.h>
-#include <asm/hvcall.h>
-#include <asm/machdep.h>
-
-#include "xics.h"
-#include "plpar_wrappers.h"
-
-static struct irq_host *xics_host;
-
-#define XICS_IPI		2
-#define XICS_IRQ_SPURIOUS	0
-
-/* Want a priority other than 0.  Various HW issues require this. */
-#define	DEFAULT_PRIORITY	5
-
-/*
- * Mark IPIs as higher priority so we can take them inside interrupts that
- * arent marked IRQF_DISABLED
- */
-#define IPI_PRIORITY		4
-
-/* The least favored priority */
-#define LOWEST_PRIORITY		0xFF
-
-/* The number of priorities defined above */
-#define MAX_NUM_PRIORITIES	3
-
-static unsigned int default_server = 0xFF;
-static unsigned int default_distrib_server = 0;
-static unsigned int interrupt_server_size = 8;
-
-/* RTAS service tokens */
-static int ibm_get_xive;
-static int ibm_set_xive;
-static int ibm_int_on;
-static int ibm_int_off;
-
-struct xics_cppr {
-	unsigned char stack[MAX_NUM_PRIORITIES];
-	int index;
-};
-
-static DEFINE_PER_CPU(struct xics_cppr, xics_cppr);
-
-/* Direct hardware low level accessors */
-
-/* The part of the interrupt presentation layer that we care about */
-struct xics_ipl {
-	union {
-		u32 word;
-		u8 bytes[4];
-	} xirr_poll;
-	union {
-		u32 word;
-		u8 bytes[4];
-	} xirr;
-	u32 dummy;
-	union {
-		u32 word;
-		u8 bytes[4];
-	} qirr;
-};
-
-static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
-
-static inline unsigned int direct_xirr_info_get(void)
-{
-	int cpu = smp_processor_id();
-
-	return in_be32(&xics_per_cpu[cpu]->xirr.word);
-}
-
-static inline void direct_xirr_info_set(unsigned int value)
-{
-	int cpu = smp_processor_id();
-
-	out_be32(&xics_per_cpu[cpu]->xirr.word, value);
-}
-
-static inline void direct_cppr_info(u8 value)
-{
-	int cpu = smp_processor_id();
-
-	out_8(&xics_per_cpu[cpu]->xirr.bytes[0], value);
-}
-
-static inline void direct_qirr_info(int n_cpu, u8 value)
-{
-	out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
-}
-
-
-/* LPAR low level accessors */
-
-static inline unsigned int lpar_xirr_info_get(unsigned char cppr)
-{
-	unsigned long lpar_rc;
-	unsigned long return_value;
-
-	lpar_rc = plpar_xirr(&return_value, cppr);
-	if (lpar_rc != H_SUCCESS)
-		panic(" bad return code xirr - rc = %lx\n", lpar_rc);
-	return (unsigned int)return_value;
-}
-
-static inline void lpar_xirr_info_set(unsigned int value)
-{
-	unsigned long lpar_rc;
-
-	lpar_rc = plpar_eoi(value);
-	if (lpar_rc != H_SUCCESS)
-		panic("bad return code EOI - rc = %ld, value=%x\n", lpar_rc,
-		      value);
-}
-
-static inline void lpar_cppr_info(u8 value)
-{
-	unsigned long lpar_rc;
-
-	lpar_rc = plpar_cppr(value);
-	if (lpar_rc != H_SUCCESS)
-		panic("bad return code cppr - rc = %lx\n", lpar_rc);
-}
-
-static inline void lpar_qirr_info(int n_cpu , u8 value)
-{
-	unsigned long lpar_rc;
-
-	lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
-	if (lpar_rc != H_SUCCESS)
-		panic("bad return code qirr - rc = %lx\n", lpar_rc);
-}
-
-
-/* Interface to generic irq subsystem */
-
-#ifdef CONFIG_SMP
-/*
- * For the moment we only implement delivery to all cpus or one cpu.
- *
- * If the requested affinity is cpu_all_mask, we set global affinity.
- * If not we set it to the first cpu in the mask, even if multiple cpus
- * are set. This is so things like irqbalance (which set core and package
- * wide affinities) do the right thing.
- */
-static int get_irq_server(unsigned int virq, const struct cpumask *cpumask,
-			  unsigned int strict_check)
-{
-
-	if (!distribute_irqs)
-		return default_server;
-
-	if (!cpumask_subset(cpu_possible_mask, cpumask)) {
-		int server = cpumask_first_and(cpu_online_mask, cpumask);
-
-		if (server < nr_cpu_ids)
-			return get_hard_smp_processor_id(server);
-
-		if (strict_check)
-			return -1;
-	}
-
-	/*
-	 * Workaround issue with some versions of JS20 firmware that
-	 * deliver interrupts to cpus which haven't been started. This
-	 * happens when using the maxcpus= boot option.
-	 */
-	if (cpumask_equal(cpu_online_mask, cpu_present_mask))
-		return default_distrib_server;
-
-	return default_server;
-}
-#else
-#define get_irq_server(virq, cpumask, strict_check) (default_server)
-#endif
-
-static void xics_unmask_irq(unsigned int virq)
-{
-	unsigned int irq;
-	int call_status;
-	int server;
-
-	pr_devel("xics: unmask virq %d\n", virq);
-
-	irq = (unsigned int)irq_map[virq].hwirq;
-	pr_devel(" -> map to hwirq 0x%x\n", irq);
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-		return;
-
-	server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0);
-
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
-				DEFAULT_PRIORITY);
-	if (call_status != 0) {
-		printk(KERN_ERR
-			"%s: ibm_set_xive irq %u server %x returned %d\n",
-			__func__, irq, server, call_status);
-		return;
-	}
-
-	/* Now unmask the interrupt (often a no-op) */
-	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
-	if (call_status != 0) {
-		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
-			__func__, irq, call_status);
-		return;
-	}
-}
-
-static unsigned int xics_startup(unsigned int virq)
-{
-	/*
-	 * The generic MSI code returns with the interrupt disabled on the
-	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
-	 * at that level, so we do it here by hand.
-	 */
-	if (irq_to_desc(virq)->msi_desc)
-		unmask_msi_irq(irq_get_irq_data(virq));
-
-	/* unmask it */
-	xics_unmask_irq(virq);
-	return 0;
-}
-
-static void xics_mask_real_irq(unsigned int irq)
-{
-	int call_status;
-
-	if (irq == XICS_IPI)
-		return;
-
-	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
-	if (call_status != 0) {
-		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
-			__func__, irq, call_status);
-		return;
-	}
-
-	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
-				default_server, 0xff);
-	if (call_status != 0) {
-		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
-			__func__, irq, call_status);
-		return;
-	}
-}
-
-static void xics_mask_irq(unsigned int virq)
-{
-	unsigned int irq;
-
-	pr_devel("xics: mask virq %d\n", virq);
-
-	irq = (unsigned int)irq_map[virq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-		return;
-	xics_mask_real_irq(irq);
-}
-
-static void xics_mask_unknown_vec(unsigned int vec)
-{
-	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-	xics_mask_real_irq(vec);
-}
-
-static inline unsigned int xics_xirr_vector(unsigned int xirr)
-{
-	/*
-	 * The top byte is the old cppr, to be restored on EOI.
-	 * The remaining 24 bits are the vector.
-	 */
-	return xirr & 0x00ffffff;
-}
-
-static void push_cppr(unsigned int vec)
-{
-	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
-
-	if (WARN_ON(os_cppr->index >= MAX_NUM_PRIORITIES - 1))
-		return;
-
-	if (vec == XICS_IPI)
-		os_cppr->stack[++os_cppr->index] = IPI_PRIORITY;
-	else
-		os_cppr->stack[++os_cppr->index] = DEFAULT_PRIORITY;
-}
-
-static unsigned int xics_get_irq_direct(void)
-{
-	unsigned int xirr = direct_xirr_info_get();
-	unsigned int vec = xics_xirr_vector(xirr);
-	unsigned int irq;
-
-	if (vec == XICS_IRQ_SPURIOUS)
-		return NO_IRQ;
-
-	irq = irq_radix_revmap_lookup(xics_host, vec);
-	if (likely(irq != NO_IRQ)) {
-		push_cppr(vec);
-		return irq;
-	}
-
-	/* We don't have a linux mapping, so have rtas mask it. */
-	xics_mask_unknown_vec(vec);
-
-	/* We might learn about it later, so EOI it */
-	direct_xirr_info_set(xirr);
-	return NO_IRQ;
-}
-
-static unsigned int xics_get_irq_lpar(void)
-{
-	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
-	unsigned int xirr = lpar_xirr_info_get(os_cppr->stack[os_cppr->index]);
-	unsigned int vec = xics_xirr_vector(xirr);
-	unsigned int irq;
-
-	if (vec == XICS_IRQ_SPURIOUS)
-		return NO_IRQ;
-
-	irq = irq_radix_revmap_lookup(xics_host, vec);
-	if (likely(irq != NO_IRQ)) {
-		push_cppr(vec);
-		return irq;
-	}
-
-	/* We don't have a linux mapping, so have RTAS mask it. */
-	xics_mask_unknown_vec(vec);
-
-	/* We might learn about it later, so EOI it */
-	lpar_xirr_info_set(xirr);
-	return NO_IRQ;
-}
-
-static unsigned char pop_cppr(void)
-{
-	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
-
-	if (WARN_ON(os_cppr->index < 1))
-		return LOWEST_PRIORITY;
-
-	return os_cppr->stack[--os_cppr->index];
-}
-
-static void xics_eoi_direct(unsigned int virq)
-{
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-	iosync();
-	direct_xirr_info_set((pop_cppr() << 24) | irq);
-}
-
-static void xics_eoi_lpar(unsigned int virq)
-{
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-	iosync();
-	lpar_xirr_info_set((pop_cppr() << 24) | irq);
-}
-
-static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
-{
-	unsigned int irq;
-	int status;
-	int xics_status[2];
-	int irq_server;
-
-	irq = (unsigned int)irq_map[virq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-		return -1;
-
-	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
-
-	if (status) {
-		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-			__func__, irq, status);
-		return -1;
-	}
-
-	irq_server = get_irq_server(virq, cpumask, 1);
-	if (irq_server == -1) {
-		char cpulist[128];
-		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
-		printk(KERN_WARNING
-			"%s: No online cpus in the mask %s for irq %d\n",
-			__func__, cpulist, virq);
-		return -1;
-	}
-
-	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, irq_server, xics_status[1]);
-
-	if (status) {
-		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
-			__func__, irq, status);
-		return -1;
-	}
-
-	return 0;
-}
-
-static struct irq_chip xics_pic_direct = {
-	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_direct,
-	.set_affinity = xics_set_affinity
-};
-
-static struct irq_chip xics_pic_lpar = {
-	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_lpar,
-	.set_affinity = xics_set_affinity
-};
-
-
-/* Interface to arch irq controller subsystem layer */
-
-/* Points to the irq_chip we're actually using */
-static struct irq_chip *xics_irq_chip;
-
-static int xics_host_match(struct irq_host *h, struct device_node *node)
-{
-	/* IBM machines have interrupt parents of various funky types for things
-	 * like vdevices, events, etc... The trick we use here is to match
-	 * everything here except the legacy 8259 which is compatible "chrp,iic"
-	 */
-	return !of_device_is_compatible(node, "chrp,iic");
-}
-
-static int xics_host_map(struct irq_host *h, unsigned int virq,
-			 irq_hw_number_t hw)
-{
-	pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
-
-	/* Insert the interrupt mapping into the radix tree for fast lookup */
-	irq_radix_revmap_insert(xics_host, virq, hw);
-
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
-	return 0;
-}
-
-static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
-			   const u32 *intspec, unsigned int intsize,
-			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
-
-{
-	/* Current xics implementation translates everything
-	 * to level. It is not technically right for MSIs but this
-	 * is irrelevant at this point. We might get smarter in the future
-	 */
-	*out_hwirq = intspec[0];
-	*out_flags = IRQ_TYPE_LEVEL_LOW;
-
-	return 0;
-}
-
-static struct irq_host_ops xics_host_ops = {
-	.match = xics_host_match,
-	.map = xics_host_map,
-	.xlate = xics_host_xlate,
-};
-
-static void __init xics_init_host(void)
-{
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		xics_irq_chip = &xics_pic_lpar;
-	else
-		xics_irq_chip = &xics_pic_direct;
-
-	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
-				   XICS_IRQ_SPURIOUS);
-	BUG_ON(xics_host == NULL);
-	irq_set_default_host(xics_host);
-}
-
-
-/* Inter-processor interrupt support */
-
-#ifdef CONFIG_SMP
-/*
- * XICS only has a single IPI, so encode the messages per CPU
- */
-static DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
-
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
-
-	set_bit(msg, tgt);
-	mb();
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_qirr_info(cpu, IPI_PRIORITY);
-	else
-		direct_qirr_info(cpu, IPI_PRIORITY);
-}
-
-void smp_xics_message_pass(int target, int msg)
-{
-	unsigned int i;
-
-	if (target < NR_CPUS) {
-		smp_xics_do_message(target, msg);
-	} else {
-		for_each_online_cpu(i) {
-			if (target == MSG_ALL_BUT_SELF
-			    && i == smp_processor_id())
-				continue;
-			smp_xics_do_message(i, msg);
-		}
-	}
-}
-
-static irqreturn_t xics_ipi_dispatch(int cpu)
-{
-	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
-
-	mb();	/* order mmio clearing qirr */
-	while (*tgt) {
-		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) {
-			smp_message_recv(PPC_MSG_CALL_FUNCTION);
-		}
-		if (test_and_clear_bit(PPC_MSG_RESCHEDULE, tgt)) {
-			smp_message_recv(PPC_MSG_RESCHEDULE);
-		}
-		if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, tgt)) {
-			smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
-		}
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, tgt)) {
-			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
-		}
-#endif
-	}
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
-{
-	int cpu = smp_processor_id();
-
-	direct_qirr_info(cpu, 0xff);
-
-	return xics_ipi_dispatch(cpu);
-}
-
-static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
-{
-	int cpu = smp_processor_id();
-
-	lpar_qirr_info(cpu, 0xff);
-
-	return xics_ipi_dispatch(cpu);
-}
-
-static void xics_request_ipi(void)
-{
-	unsigned int ipi;
-	int rc;
-
-	ipi = irq_create_mapping(xics_host, XICS_IPI);
-	BUG_ON(ipi == NO_IRQ);
-
-	/*
-	 * IPIs are marked IRQF_DISABLED as they must run with irqs
-	 * disabled
-	 */
-	set_irq_handler(ipi, handle_percpu_irq);
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		rc = request_irq(ipi, xics_ipi_action_lpar,
-				IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
-	else
-		rc = request_irq(ipi, xics_ipi_action_direct,
-				IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
-	BUG_ON(rc);
-}
-
-int __init smp_xics_probe(void)
-{
-	xics_request_ipi();
-
-	return cpumask_weight(cpu_possible_mask);
-}
-
-#endif /* CONFIG_SMP */
-
-
-/* Initialization */
-
-static void xics_update_irq_servers(void)
-{
-	int i, j;
-	struct device_node *np;
-	u32 ilen;
-	const u32 *ireg;
-	u32 hcpuid;
-
-	/* Find the server numbers for the boot cpu. */
-	np = of_get_cpu_node(boot_cpuid, NULL);
-	BUG_ON(!np);
-
-	ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
-	if (!ireg) {
-		of_node_put(np);
-		return;
-	}
-
-	i = ilen / sizeof(int);
-	hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
-	/* Global interrupt distribution server is specified in the last
-	 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
-	 * entry fom this property for current boot cpu id and use it as
-	 * default distribution server
-	 */
-	for (j = 0; j < i; j += 2) {
-		if (ireg[j] == hcpuid) {
-			default_server = hcpuid;
-			default_distrib_server = ireg[j+1];
-		}
-	}
-
-	of_node_put(np);
-}
-
-static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
-				     unsigned long size)
-{
-	int i;
-
-	/* This may look gross but it's good enough for now, we don't quite
-	 * have a hard -> linux processor id matching.
-	 */
-	for_each_possible_cpu(i) {
-		if (!cpu_present(i))
-			continue;
-		if (hw_id == get_hard_smp_processor_id(i)) {
-			xics_per_cpu[i] = ioremap(addr, size);
-			return;
-		}
-	}
-}
-
-static void __init xics_init_one_node(struct device_node *np,
-				      unsigned int *indx)
-{
-	unsigned int ilen;
-	const u32 *ireg;
-
-	/* This code does the theorically broken assumption that the interrupt
-	 * server numbers are the same as the hard CPU numbers.
-	 * This happens to be the case so far but we are playing with fire...
-	 * should be fixed one of these days. -BenH.
-	 */
-	ireg = of_get_property(np, "ibm,interrupt-server-ranges", NULL);
-
-	/* Do that ever happen ? we'll know soon enough... but even good'old
-	 * f80 does have that property ..
-	 */
-	WARN_ON(ireg == NULL);
-	if (ireg) {
-		/*
-		 * set node starting index for this node
-		 */
-		*indx = *ireg;
-	}
-	ireg = of_get_property(np, "reg", &ilen);
-	if (!ireg)
-		panic("xics_init_IRQ: can't find interrupt reg property");
-
-	while (ilen >= (4 * sizeof(u32))) {
-		unsigned long addr, size;
-
-		/* XXX Use proper OF parsing code here !!! */
-		addr = (unsigned long)*ireg++ << 32;
-		ilen -= sizeof(u32);
-		addr |= *ireg++;
-		ilen -= sizeof(u32);
-		size = (unsigned long)*ireg++ << 32;
-		ilen -= sizeof(u32);
-		size |= *ireg++;
-		ilen -= sizeof(u32);
-		xics_map_one_cpu(*indx, addr, size);
-		(*indx)++;
-	}
-}
-
-void __init xics_init_IRQ(void)
-{
-	struct device_node *np;
-	u32 indx = 0;
-	int found = 0;
-	const u32 *isize;
-
-	ppc64_boot_msg(0x20, "XICS Init");
-
-	ibm_get_xive = rtas_token("ibm,get-xive");
-	ibm_set_xive = rtas_token("ibm,set-xive");
-	ibm_int_on  = rtas_token("ibm,int-on");
-	ibm_int_off = rtas_token("ibm,int-off");
-
-	for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
-		found = 1;
-		if (firmware_has_feature(FW_FEATURE_LPAR)) {
-			of_node_put(np);
-			break;
-			}
-		xics_init_one_node(np, &indx);
-	}
-	if (found == 0)
-		return;
-
-	/* get the bit size of server numbers */
-	found = 0;
-
-	for_each_compatible_node(np, NULL, "ibm,ppc-xics") {
-		isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
-
-		if (!isize)
-			continue;
-
-		if (!found) {
-			interrupt_server_size = *isize;
-			found = 1;
-		} else if (*isize != interrupt_server_size) {
-			printk(KERN_WARNING "XICS: "
-			       "mismatched ibm,interrupt-server#-size\n");
-			interrupt_server_size = max(*isize,
-						    interrupt_server_size);
-		}
-	}
-
-	xics_update_irq_servers();
-	xics_init_host();
-
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		ppc_md.get_irq = xics_get_irq_lpar;
-	else
-		ppc_md.get_irq = xics_get_irq_direct;
-
-	xics_setup_cpu();
-
-	ppc64_boot_msg(0x21, "XICS Done");
-}
-
-/* Cpu startup, shutdown, and hotplug */
-
-static void xics_set_cpu_priority(unsigned char cppr)
-{
-	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
-
-	/*
-	 * we only really want to set the priority when there's
-	 * just one cppr value on the stack
-	 */
-	WARN_ON(os_cppr->index != 0);
-
-	os_cppr->stack[0] = cppr;
-
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_cppr_info(cppr);
-	else
-		direct_cppr_info(cppr);
-	iosync();
-}
-
-/* Have the calling processor join or leave the specified global queue */
-static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
-{
-	int index;
-	int status;
-
-	if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL))
-		return;
-
-	index = (1UL << interrupt_server_size) - 1 - gserver;
-
-	status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
-
-	WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n",
-	     GLOBAL_INTERRUPT_QUEUE, index, join, status);
-}
-
-void xics_setup_cpu(void)
-{
-	xics_set_cpu_priority(LOWEST_PRIORITY);
-
-	xics_set_cpu_giq(default_distrib_server, 1);
-}
-
-void xics_teardown_cpu(void)
-{
-	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
-	int cpu = smp_processor_id();
-
-	/*
-	 * we have to reset the cppr index to 0 because we're
-	 * not going to return from the IPI
-	 */
-	os_cppr->index = 0;
-	xics_set_cpu_priority(0);
-
-	/* Clear any pending IPI request */
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_qirr_info(cpu, 0xff);
-	else
-		direct_qirr_info(cpu, 0xff);
-}
-
-void xics_kexec_teardown_cpu(int secondary)
-{
-	xics_teardown_cpu();
-
-	/*
-	 * we take the ipi irq but and never return so we
-	 * need to EOI the IPI, but want to leave our priority 0
-	 *
-	 * should we check all the other interrupts too?
-	 * should we be flagging idle loop instead?
-	 * or creating some task to be scheduled?
-	 */
-
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_xirr_info_set((0x00 << 24) | XICS_IPI);
-	else
-		direct_xirr_info_set((0x00 << 24) | XICS_IPI);
-
-	/*
-	 * Some machines need to have at least one cpu in the GIQ,
-	 * so leave the master cpu in the group.
-	 */
-	if (secondary)
-		xics_set_cpu_giq(default_distrib_server, 0);
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-/* Interrupts are disabled. */
-void xics_migrate_irqs_away(void)
-{
-	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
-	unsigned int irq, virq;
-
-	/* If we used to be the default server, move to the new "boot_cpuid" */
-	if (hw_cpu == default_server)
-		xics_update_irq_servers();
-
-	/* Reject any interrupt that was queued to us... */
-	xics_set_cpu_priority(0);
-
-	/* Remove ourselves from the global interrupt queue */
-	xics_set_cpu_giq(default_distrib_server, 0);
-
-	/* Allow IPIs again... */
-	xics_set_cpu_priority(DEFAULT_PRIORITY);
-
-	for_each_irq(virq) {
-		struct irq_desc *desc;
-		int xics_status[2];
-		int status;
-		unsigned long flags;
-
-		/* We cant set affinity on ISA interrupts */
-		if (virq < NUM_ISA_INTERRUPTS)
-			continue;
-		if (irq_map[virq].host != xics_host)
-			continue;
-		irq = (unsigned int)irq_map[virq].hwirq;
-		/* We need to get IPIs still. */
-		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
-			continue;
-		desc = irq_to_desc(virq);
-
-		/* We only need to migrate enabled IRQS */
-		if (desc == NULL || desc->chip == NULL
-		    || desc->action == NULL
-		    || desc->chip->set_affinity == NULL)
-			continue;
-
-		raw_spin_lock_irqsave(&desc->lock, flags);
-
-		status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
-		if (status) {
-			printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-					__func__, irq, status);
-			goto unlock;
-		}
-
-		/*
-		 * We only support delivery to all cpus or to one cpu.
-		 * The irq has to be migrated only in the single cpu
-		 * case.
-		 */
-		if (xics_status[0] != hw_cpu)
-			goto unlock;
-
-		/* This is expected during cpu offline. */
-		if (cpu_online(cpu))
-			printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
-			       virq, cpu);
-
-		/* Reset affinity to all cpus */
-		cpumask_setall(irq_to_desc(virq)->affinity);
-		desc->chip->set_affinity(virq, cpu_all_mask);
-unlock:
-		raw_spin_unlock_irqrestore(&desc->lock, flags);
-	}
-}
-#endif
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
deleted file mode 100644
index d1d5a83..0000000
--- a/arch/powerpc/platforms/pseries/xics.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/powerpc/platforms/pseries/xics.h
- *
- * Copyright 2000 IBM Corporation.
- *
- *  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.
- */
-
-#ifndef _POWERPC_KERNEL_XICS_H
-#define _POWERPC_KERNEL_XICS_H
-
-extern void xics_init_IRQ(void);
-extern void xics_setup_cpu(void);
-extern void xics_teardown_cpu(void);
-extern void xics_kexec_teardown_cpu(int secondary);
-extern void xics_migrate_irqs_away(void);
-extern int smp_xics_probe(void);
-extern void smp_xics_message_pass(int target, int msg);
-
-#endif /* _POWERPC_KERNEL_XICS_H */
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 3965828..cfc1877 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -12,3 +12,6 @@ config PPC_MSI_BITMAP
 	depends on PCI_MSI
 	default y if MPIC
 	default y if FSL_PCI
+
+source "arch/powerpc/sysdev/xics/Kconfig"
+
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 9c29734..2b82081 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -57,3 +57,7 @@ obj-$(CONFIG_PPC_MPC52xx)	+= mpc5xxx_clocks.o
 ifeq ($(CONFIG_SUSPEND),y)
 obj-$(CONFIG_6xx)		+= 6xx-suspend.o
 endif
+
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
+obj-$(CONFIG_PPC_XICS)		+= xics/
diff --git a/arch/powerpc/sysdev/xics/Kconfig b/arch/powerpc/sysdev/xics/Kconfig
new file mode 100644
index 0000000..123b8dd
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/Kconfig
@@ -0,0 +1,12 @@
+config PPC_XICS
+       def_bool n
+
+config PPC_ICP_NATIVE
+       def_bool n
+
+config PPC_ICP_HV
+       def_bool n
+
+config PPC_ICS_RTAS
+       def_bool n
+
diff --git a/arch/powerpc/sysdev/xics/Makefile b/arch/powerpc/sysdev/xics/Makefile
new file mode 100644
index 0000000..b75a605
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/Makefile
@@ -0,0 +1,6 @@
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
+obj-y				+= xics-common.o
+obj-$(CONFIG_PPC_ICP_NATIVE)	+= icp-native.o
+obj-$(CONFIG_PPC_ICP_HV)	+= icp-hv.o
+obj-$(CONFIG_PPC_ICS_RTAS)	+= ics-rtas.o
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
new file mode 100644
index 0000000..8633fa1
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2011 IBM Corporation.
+ *
+ *  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/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/io.h>
+
+static inline unsigned int icp_hv_get_xirr(unsigned char cppr)
+{
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+	long rc;
+
+	rc = plpar_hcall(H_XIRR, retbuf, cppr);
+	if (rc != H_SUCCESS)
+		panic(" bad return code xirr - rc = %lx\n", rc);
+	return (unsigned int)retbuf[0];
+}
+
+static inline void icp_hv_set_xirr(unsigned int value)
+{
+	long rc = plpar_hcall_norets(H_EOI, value);
+	if (rc != H_SUCCESS)
+		panic("bad return code EOI - rc = %ld, value=%x\n", rc, value);
+}
+
+static inline void icp_hv_set_cppr(u8 value)
+{
+	long rc = plpar_hcall_norets(H_CPPR, value);
+	if (rc != H_SUCCESS)
+		panic("bad return code cppr - rc = %lx\n", rc);
+}
+
+static inline void icp_hv_set_qirr(int n_cpu , u8 value)
+{
+	long rc = plpar_hcall_norets(H_IPI, get_hard_smp_processor_id(n_cpu),
+				     value);
+	if (rc != H_SUCCESS)
+		panic("bad return code qirr - rc = %lx\n", rc);
+}
+
+static void icp_hv_eoi(unsigned int virq)
+{
+	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+
+	iosync();
+	icp_hv_set_xirr((xics_pop_cppr() << 24) | irq);
+}
+
+static void icp_hv_teardown_cpu(void)
+{
+	int cpu = smp_processor_id();
+
+	/* Clear any pending IPI */
+	icp_hv_set_qirr(cpu, 0xff);
+}
+
+static void icp_hv_flush_ipi(void)
+{
+	/* We take the ipi irq but and never return so we
+	 * need to EOI the IPI, but want to leave our priority 0
+	 *
+	 * should we check all the other interrupts too?
+	 * should we be flagging idle loop instead?
+	 * or creating some task to be scheduled?
+	 */
+
+	icp_hv_set_xirr((0x00 << 24) | XICS_IPI);
+}
+
+static unsigned int icp_hv_get_irq(void)
+{
+	unsigned int xirr = icp_hv_get_xirr(xics_cppr_top());
+	unsigned int vec = xirr & 0x00ffffff;
+	unsigned int irq;
+
+	if (vec == XICS_IRQ_SPURIOUS)
+		return NO_IRQ;
+
+	irq = irq_radix_revmap_lookup(xics_host, vec);
+	if (likely(irq != NO_IRQ)) {
+		xics_push_cppr(vec);
+		return irq;
+	}
+
+	/* We don't have a linux mapping, so have rtas mask it. */
+	xics_mask_unknown_vec(vec);
+
+	/* We might learn about it later, so EOI it */
+	icp_hv_set_xirr(xirr);
+
+	return NO_IRQ;
+}
+
+static void icp_hv_set_cpu_priority(unsigned char cppr)
+{
+	xics_set_base_cppr(cppr);
+	icp_hv_set_cppr(cppr);
+	iosync();
+}
+
+#ifdef CONFIG_SMP
+
+static inline void icp_hv_do_message(int cpu, int msg)
+{
+	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
+
+	set_bit(msg, tgt);
+	mb();
+	icp_hv_set_qirr(cpu, IPI_PRIORITY);
+}
+
+static void icp_hv_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		icp_hv_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			icp_hv_do_message(i, msg);
+		}
+	}
+}
+
+static irqreturn_t icp_hv_ipi_action(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+
+	icp_hv_set_qirr(cpu, 0xff);
+
+	return xics_ipi_dispatch(cpu);
+}
+
+#endif /* CONFIG_SMP */
+
+static const struct icp_ops icp_hv_ops = {
+	.get_irq	= icp_hv_get_irq,
+	.eoi		= icp_hv_eoi,
+	.set_priority	= icp_hv_set_cpu_priority,
+	.teardown_cpu	= icp_hv_teardown_cpu,
+	.flush_ipi	= icp_hv_flush_ipi,
+#ifdef CONFIG_SMP
+	.ipi_action	= icp_hv_ipi_action,
+	.message_pass	= icp_hv_message_pass,
+#endif
+};
+
+int icp_hv_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xicp");
+	if (!np)
+		np = of_find_node_by_type(NULL,
+				    "PowerPC-External-Interrupt-Presentation");
+	if (!np)
+		return -ENODEV;
+	
+	icp_ops = &icp_hv_ops;	
+
+	return 0;
+}
+
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
new file mode 100644
index 0000000..a27239f
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2011 IBM Corporation.
+ *
+ *  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/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+
+struct icp_ipl {
+	union {
+		u32 word;
+		u8 bytes[4];
+	} xirr_poll;
+	union {
+		u32 word;
+		u8 bytes[4];
+	} xirr;
+	u32 dummy;
+	union {
+		u32 word;
+		u8 bytes[4];
+	} qirr;
+	u32 link_a;
+	u32 link_b;
+	u32 link_c;
+};
+
+static struct icp_ipl __iomem *icp_native_regs[NR_CPUS];
+
+static inline unsigned int icp_native_get_xirr(void)
+{
+	int cpu = smp_processor_id();
+
+	return in_be32(&icp_native_regs[cpu]->xirr.word);
+}
+
+static inline void icp_native_set_xirr(unsigned int value)
+{
+	int cpu = smp_processor_id();
+
+	out_be32(&icp_native_regs[cpu]->xirr.word, value);
+}
+
+static inline void icp_native_set_cppr(u8 value)
+{
+	int cpu = smp_processor_id();
+
+	out_8(&icp_native_regs[cpu]->xirr.bytes[0], value);
+}
+
+static inline void icp_native_set_qirr(int n_cpu, u8 value)
+{
+	out_8(&icp_native_regs[n_cpu]->qirr.bytes[0], value);
+}
+
+static void icp_native_set_cpu_priority(unsigned char cppr)
+{
+	xics_set_base_cppr(cppr);
+	icp_native_set_cppr(cppr);
+	iosync();
+}
+
+static void icp_native_eoi(unsigned int virq)
+{
+	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+
+	iosync();
+	icp_native_set_xirr((xics_pop_cppr() << 24) | irq);
+}
+
+static void icp_native_teardown_cpu(void)
+{
+	int cpu = smp_processor_id();
+
+	/* Clear any pending IPI */
+	icp_native_set_qirr(cpu, 0xff);
+}
+
+static void icp_native_flush_ipi(void)
+{
+	/* We take the ipi irq but and never return so we
+	 * need to EOI the IPI, but want to leave our priority 0
+	 *
+	 * should we check all the other interrupts too?
+	 * should we be flagging idle loop instead?
+	 * or creating some task to be scheduled?
+	 */
+
+	icp_native_set_xirr((0x00 << 24) | XICS_IPI);
+}
+
+static unsigned int icp_native_get_irq(void)
+{
+	unsigned int xirr = icp_native_get_xirr();
+	unsigned int vec = xirr & 0x00ffffff;
+	unsigned int irq;
+
+	if (vec == XICS_IRQ_SPURIOUS)
+		return NO_IRQ;
+
+	irq = irq_radix_revmap_lookup(xics_host, vec);
+	if (likely(irq != NO_IRQ)) {
+		xics_push_cppr(vec);
+		return irq;
+	}
+
+	/* We don't have a linux mapping, so have rtas mask it. */
+	xics_mask_unknown_vec(vec);
+
+	/* We might learn about it later, so EOI it */
+	icp_native_set_xirr(xirr);
+
+	return NO_IRQ;
+}
+
+#ifdef CONFIG_SMP
+
+static inline void icp_native_do_message(int cpu, int msg)
+{
+	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
+
+	set_bit(msg, tgt);
+	mb();
+	icp_native_set_qirr(cpu, IPI_PRIORITY);
+}
+
+static void icp_native_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		icp_native_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			icp_native_do_message(i, msg);
+		}
+	}
+}
+
+static irqreturn_t icp_native_ipi_action(int irq, void *dev_id)
+{
+	int cpu = smp_processor_id();
+
+	icp_native_set_qirr(cpu, 0xff);
+
+	return xics_ipi_dispatch(cpu);
+}
+
+#endif /* CONFIG_SMP */
+
+static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
+					 unsigned long size)
+{
+	char *rname;
+	int i, cpu = -1;
+
+	/* This may look gross but it's good enough for now, we don't quite
+	 * have a hard -> linux processor id matching.
+	 */
+	for_each_possible_cpu(i) {
+		if (!cpu_present(i))
+			continue;
+		if (hw_id == get_hard_smp_processor_id(i)) {
+			cpu = i;
+			break;
+		}
+	}
+
+	/* Fail, skip that CPU. Don't print, it's normal, some XICS come up
+	 * with way more entries in there than you have CPUs
+	 */
+	if (cpu == -1)
+		return 0;
+
+	rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
+			  cpu, hw_id);
+
+	if (!request_mem_region(addr, size, rname)) {
+		pr_warning("icp_native: Could not reserve ICP MMIO"
+			   " for CPU %d, interrupt server #0x%x\n",
+			   cpu, hw_id);
+		return -EBUSY;
+	}
+
+	icp_native_regs[cpu] = ioremap(addr, size);
+	if (!icp_native_regs[cpu]) {
+		pr_warning("icp_native: Failed ioremap for CPU %d, "
+			   "interrupt server #0x%x, addr %#lx\n",
+			   cpu, hw_id, addr);
+		release_mem_region(addr, size);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int __init icp_native_init_one_node(struct device_node *np,
+					   unsigned int *indx)
+{
+	unsigned int ilen;
+	const u32 *ireg;
+	int i;
+	int reg_tuple_size;
+	int num_servers = 0;
+
+	/* This code does the theorically broken assumption that the interrupt
+	 * server numbers are the same as the hard CPU numbers.
+	 * This happens to be the case so far but we are playing with fire...
+	 * should be fixed one of these days. -BenH.
+	 */
+	ireg = of_get_property(np, "ibm,interrupt-server-ranges", &ilen);
+
+	/* Do that ever happen ? we'll know soon enough... but even good'old
+	 * f80 does have that property ..
+	 */
+	WARN_ON((ireg == NULL) || (ilen != 2*sizeof(u32)));
+
+	if (ireg) {
+		*indx = of_read_number(ireg, 1);
+		if (ilen >= 2*sizeof(u32))
+			num_servers = of_read_number(ireg + 1, 1);
+	}
+
+	ireg = of_get_property(np, "reg", &ilen);
+	if (!ireg) {
+		pr_err("icp_native: Can't find interrupt reg property");
+		return -1;
+	}
+
+	reg_tuple_size = (of_n_addr_cells(np) + of_n_size_cells(np)) * 4;
+	if (((ilen % reg_tuple_size) != 0)
+	    || (num_servers && (num_servers != (ilen / reg_tuple_size)))) {
+		pr_err("icp_native: ICP reg len (%d) != num servers (%d)",
+		       ilen / reg_tuple_size, num_servers);
+		return -1;
+	}
+
+	for (i = 0; i < (ilen / reg_tuple_size); i++) {
+		struct resource r;
+		int err;
+
+		err = of_address_to_resource(np, i, &r);
+		if (err) {
+			pr_err("icp_native: Could not translate ICP MMIO"
+			       " for interrupt server 0x%x (%d)\n", *indx, err);
+			return -1;
+		}
+
+		if (icp_native_map_one_cpu(*indx, r.start, r.end - r.start))
+			return -1;
+
+		(*indx)++;
+	}
+	return 0;
+}
+
+static const struct icp_ops icp_native_ops = {
+	.get_irq	= icp_native_get_irq,
+	.eoi		= icp_native_eoi,
+	.set_priority	= icp_native_set_cpu_priority,
+	.teardown_cpu	= icp_native_teardown_cpu,
+	.flush_ipi	= icp_native_flush_ipi,
+#ifdef CONFIG_SMP
+	.ipi_action	= icp_native_ipi_action,
+	.message_pass	= icp_native_message_pass,
+#endif
+};
+
+int icp_native_init(void)
+{
+	struct device_node *np;
+	u32 indx = 0;
+	int found = 0;
+
+	for_each_compatible_node(np, NULL, "ibm,ppc-xicp")
+		if (icp_native_init_one_node(np, &indx) == 0)
+			found = 1;
+	if (!found) {
+		for_each_node_by_type(np,
+			"PowerPC-External-Interrupt-Presentation") {
+				if (icp_native_init_one_node(np, &indx) == 0)
+					found = 1;
+		}
+	}
+
+	if (found == 0)
+		return -ENODEV;
+
+	icp_ops = &icp_native_ops;
+
+	return 0;
+}
diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c
new file mode 100644
index 0000000..192d794
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/ics-rtas.c
@@ -0,0 +1,231 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/msi.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/xics.h>
+#include <asm/rtas.h>
+
+/* RTAS service tokens */
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
+
+static int ics_rtas_map(struct ics *ics, unsigned int virq);
+static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec);
+static long ics_rtas_get_server(struct ics *ics, unsigned long vec);
+
+/* Only one global & state struct ics */
+static struct ics ics_rtas = {
+	.map		= ics_rtas_map,
+	.mask_unknown	= ics_rtas_mask_unknown,
+	.get_server	= ics_rtas_get_server,
+};
+
+static void ics_rtas_unmask_irq(unsigned int virq)
+{
+	unsigned int irq;
+	int call_status;
+	int server;
+
+	pr_devel("xics: unmask virq %d\n", virq);
+
+	irq = (unsigned int)irq_map[virq].hwirq;
+	pr_devel(" -> map to hwirq 0x%x\n", irq);
+	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+		return;
+
+	server = xics_get_irq_server(virq, irq_to_desc(virq)->affinity, 0);
+
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
+				DEFAULT_PRIORITY);
+	if (call_status != 0) {
+		printk(KERN_ERR
+			"%s: ibm_set_xive irq %u server %x returned %d\n",
+			__func__, irq, server, call_status);
+		return;
+	}
+
+	/* Now unmask the interrupt (often a no-op) */
+	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
+	if (call_status != 0) {
+		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
+			__func__, irq, call_status);
+		return;
+	}
+}
+
+static unsigned int ics_rtas_startup(unsigned int virq)
+{
+	/*
+	 * The generic MSI code returns with the interrupt disabled on the
+	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
+	 * at that level, so we do it here by hand.
+	 */
+	if (irq_to_desc(virq)->msi_desc)
+		unmask_msi_irq(irq_get_irq_data(virq));
+
+	/* unmask it */
+	ics_rtas_unmask_irq(virq);
+	return 0;
+}
+
+static void ics_rtas_mask_real_irq(unsigned int irq)
+{
+	int call_status;
+
+	if (irq == XICS_IPI)
+		return;
+
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
+	if (call_status != 0) {
+		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
+			__func__, irq, call_status);
+		return;
+	}
+
+	/* Have to set XIVE to 0xff to be able to remove a slot */
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
+				xics_default_server, 0xff);
+	if (call_status != 0) {
+		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
+			__func__, irq, call_status);
+		return;
+	}
+}
+
+static void ics_rtas_mask_irq(unsigned int virq)
+{
+	unsigned int irq;
+
+	pr_devel("xics: mask virq %d\n", virq);
+
+	irq = (unsigned int)irq_map[virq].hwirq;
+	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+		return;
+	ics_rtas_mask_real_irq(irq);
+}
+
+static int ics_rtas_set_affinity(unsigned int virq,
+				 const struct cpumask *cpumask)
+{
+	unsigned int irq;
+	int status;
+	int xics_status[2];
+	int irq_server;
+
+	irq = (unsigned int)irq_map[virq].hwirq;
+	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+		return -1;
+
+	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+
+	if (status) {
+		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+			__func__, irq, status);
+		return -1;
+	}
+
+	irq_server = xics_get_irq_server(virq, cpumask, 1);
+	if (irq_server == -1) {
+		char cpulist[128];
+		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
+		printk(KERN_WARNING
+			"%s: No online cpus in the mask %s for irq %d\n",
+			__func__, cpulist, virq);
+		return -1;
+	}
+
+	status = rtas_call(ibm_set_xive, 3, 1, NULL,
+				irq, irq_server, xics_status[1]);
+
+	if (status) {
+		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
+			__func__, irq, status);
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct irq_chip ics_rtas_irq_chip = {
+	.name = "XICS",
+	.startup = ics_rtas_startup,
+	.mask = ics_rtas_mask_irq,
+	.unmask = ics_rtas_unmask_irq,
+	.eoi = NULL, /* Patched at init time */
+	.set_affinity = ics_rtas_set_affinity
+};
+
+static int ics_rtas_map(struct ics *ics, unsigned int virq)
+{
+	unsigned int hw_irq = (unsigned int)irq_map[virq].hwirq;
+	int status[2];
+	int rc;
+
+	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
+		return -EINVAL;
+
+	/* Check if RTAS knows about this interrupt */
+	rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq);
+	if (rc)
+		return -ENXIO;
+	
+	set_irq_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq);
+	set_irq_chip_data(virq, &ics_rtas);
+
+	return 0;
+}
+
+static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec)
+{
+	ics_rtas_mask_real_irq(vec);
+}
+
+static long ics_rtas_get_server(struct ics *ics, unsigned long vec)
+{
+	int rc, status[2];
+	
+	rc = rtas_call(ibm_get_xive, 1, 3, status, vec);
+	if (rc)
+		return -1;
+	return status[0];
+}
+
+int ics_rtas_init(void)
+{
+	ibm_get_xive = rtas_token("ibm,get-xive");
+	ibm_set_xive = rtas_token("ibm,set-xive");
+	ibm_int_on  = rtas_token("ibm,int-on");
+	ibm_int_off = rtas_token("ibm,int-off");
+
+	/* We enable the RTAS "ICS" if RTAS is present with the
+	 * appropriate tokens
+	 */
+	if (ibm_get_xive == RTAS_UNKNOWN_SERVICE ||
+	    ibm_set_xive == RTAS_UNKNOWN_SERVICE)
+		return -ENODEV;
+
+	/* We need to patch our irq chip's EOI to point to the
+	 * right ICP
+	 */
+	ics_rtas_irq_chip.eoi = icp_ops->eoi;
+
+	/* Register ourselves */
+	xics_register_ics(&ics_rtas);
+
+	return 0;
+}
+
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
new file mode 100644
index 0000000..fdf43c0
--- /dev/null
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2011 IBM Corporation.
+ *
+ *  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/types.h>
+#include <linux/threads.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+#include <asm/rtas.h>
+#include <asm/xics.h>
+#include <asm/firmware.h>
+
+/* Globals common to all ICP/ICS implementations */
+const struct icp_ops	*icp_ops;
+
+unsigned int xics_default_server		= 0xff;
+unsigned int xics_default_distrib_server	= 0;
+unsigned int xics_interrupt_server_size		= 8;
+
+DEFINE_PER_CPU(struct xics_cppr, xics_cppr);
+
+struct irq_host *xics_host;
+
+static LIST_HEAD(ics_list);
+
+void xics_update_irq_servers(void)
+{
+	int i, j;
+	struct device_node *np;
+	u32 ilen;
+	const u32 *ireg;
+	u32 hcpuid;
+
+	/* Find the server numbers for the boot cpu. */
+	np = of_get_cpu_node(boot_cpuid, NULL);
+	BUG_ON(!np);
+
+	hcpuid = get_hard_smp_processor_id(boot_cpuid);
+	xics_default_server = hcpuid;
+
+	ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+	if (!ireg) {
+		of_node_put(np);
+		return;
+	}
+
+	i = ilen / sizeof(int);
+
+	/* Global interrupt distribution server is specified in the last
+	 * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+	 * entry fom this property for current boot cpu id and use it as
+	 * default distribution server
+	 */
+	for (j = 0; j < i; j += 2) {
+		if (ireg[j] == hcpuid) {
+			xics_default_distrib_server = ireg[j+1];
+		}
+	}
+
+	of_node_put(np);
+}
+
+/* GIQ stuff, currently only supported on RTAS setups, will have
+ * to be sorted properly for bare metal
+ */
+void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
+{
+#ifdef CONFIG_PPC_RTAS
+	int index;
+	int status;
+
+	if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL))
+		return;
+
+	index = (1UL << xics_interrupt_server_size) - 1 - gserver;
+
+	status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
+
+	WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n",
+	     GLOBAL_INTERRUPT_QUEUE, index, join, status);
+#endif
+}
+
+void xics_setup_cpu(void)
+{
+	icp_ops->set_priority(LOWEST_PRIORITY);
+
+	xics_set_cpu_giq(xics_default_distrib_server, 1);
+}
+
+void xics_mask_unknown_vec(unsigned int vec)
+{
+	struct ics *ics;
+
+	pr_err("Interrupt %u (real) is invalid, disabling it.\n", vec);
+
+	list_for_each_entry(ics, &ics_list, link)
+		ics->mask_unknown(ics, vec);
+}
+
+
+#ifdef CONFIG_SMP
+
+DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, xics_ipi_message);
+
+irqreturn_t xics_ipi_dispatch(int cpu)
+{
+	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
+
+	mb();	/* order mmio clearing qirr */
+	while (*tgt) {
+		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) {
+			smp_message_recv(PPC_MSG_CALL_FUNCTION);
+		}
+		if (test_and_clear_bit(PPC_MSG_RESCHEDULE, tgt)) {
+			smp_message_recv(PPC_MSG_RESCHEDULE);
+		}
+		if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, tgt)) {
+			smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
+		}
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+		if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, tgt)) {
+			smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+		}
+#endif
+	}
+	return IRQ_HANDLED;
+}
+
+static void xics_request_ipi(void)
+{
+	unsigned int ipi;
+
+	ipi = irq_create_mapping(xics_host, XICS_IPI);
+	BUG_ON(ipi == NO_IRQ);
+
+	/*
+	 * IPIs are marked IRQF_DISABLED as they must run with irqs
+	 * disabled
+	 */
+	set_irq_handler(ipi, handle_percpu_irq);
+	BUG_ON(request_irq(ipi, icp_ops->ipi_action,
+			   IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL));
+}
+
+int __init xics_smp_probe(void)
+{
+	/* Setup message_pass callback  based on which ICP is used */
+	smp_ops->message_pass = icp_ops->message_pass;
+
+	/* Register all the IPIs */
+	xics_request_ipi();
+
+	return cpumask_weight(cpu_possible_mask);
+}
+
+#endif /* CONFIG_SMP */
+
+void xics_teardown_cpu(void)
+{
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+
+	/*
+	 * we have to reset the cppr index to 0 because we're
+	 * not going to return from the IPI
+	 */
+	os_cppr->index = 0;
+	icp_ops->set_priority(0);
+	icp_ops->teardown_cpu();
+}
+
+void xics_kexec_teardown_cpu(int secondary)
+{
+	xics_teardown_cpu();
+
+	icp_ops->flush_ipi();
+
+	/*
+	 * Some machines need to have at least one cpu in the GIQ,
+	 * so leave the master cpu in the group.
+	 */
+	if (secondary)
+		xics_set_cpu_giq(xics_default_distrib_server, 0);
+}
+
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/* Interrupts are disabled. */
+void xics_migrate_irqs_away(void)
+{
+	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
+	unsigned int irq, virq;
+
+	/* If we used to be the default server, move to the new "boot_cpuid" */
+	if (hw_cpu == xics_default_server)
+		xics_update_irq_servers();
+
+	/* Reject any interrupt that was queued to us... */
+	icp_ops->set_priority(0);
+
+	/* Remove ourselves from the global interrupt queue */
+	xics_set_cpu_giq(xics_default_distrib_server, 0);
+
+	/* Allow IPIs again... */
+	icp_ops->set_priority(DEFAULT_PRIORITY);
+
+	for_each_irq(virq) {
+		struct irq_desc *desc;
+		long server;
+		unsigned long flags;
+		struct ics *ics;
+
+		/* We cant set affinity on ISA interrupts */
+		if (virq < NUM_ISA_INTERRUPTS)
+			continue;
+		if (irq_map[virq].host != xics_host)
+			continue;
+		irq = (unsigned int)irq_map[virq].hwirq;
+		/* We need to get IPIs still. */
+		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+			continue;
+		desc = irq_to_desc(virq);
+
+		/* We only need to migrate enabled IRQS */
+		if (desc == NULL || desc->chip == NULL
+		    || desc->action == NULL
+		    || desc->chip->set_affinity == NULL)
+			continue;
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+
+		/* Locate interrupt server */
+		server = -1;
+		ics = get_irq_chip_data(virq);
+		if (ics)
+			server = ics->get_server(ics, irq);
+		if (server < 0) {
+			printk(KERN_ERR "%s: Can't find server for irq %d\n",
+			       __func__, irq);
+			goto unlock;
+		}
+
+		/* We only support delivery to all cpus or to one cpu.
+		 * The irq has to be migrated only in the single cpu
+		 * case.
+		 */
+		if (server != hw_cpu)
+			goto unlock;
+
+		/* This is expected during cpu offline. */
+		if (cpu_online(cpu))
+			printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
+			       virq, cpu);
+
+		/* Reset affinity to all cpus */
+		cpumask_setall(irq_to_desc(virq)->affinity);
+		desc->chip->set_affinity(virq, cpu_all_mask);
+unlock:
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
+	}
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#ifdef CONFIG_SMP
+/*
+ * For the moment we only implement delivery to all cpus or one cpu.
+ *
+ * If the requested affinity is cpu_all_mask, we set global affinity.
+ * If not we set it to the first cpu in the mask, even if multiple cpus
+ * are set. This is so things like irqbalance (which set core and package
+ * wide affinities) do the right thing.
+ */
+int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
+			unsigned int strict_check)
+{
+
+	if (!distribute_irqs)
+		return xics_default_server;
+
+	if (!cpumask_subset(cpu_possible_mask, cpumask)) {
+		int server = cpumask_first_and(cpu_online_mask, cpumask);
+
+		if (server < nr_cpu_ids)
+			return get_hard_smp_processor_id(server);
+
+		if (strict_check)
+			return -1;
+	}
+
+	/*
+	 * Workaround issue with some versions of JS20 firmware that
+	 * deliver interrupts to cpus which haven't been started. This
+	 * happens when using the maxcpus= boot option.
+	 */
+	if (cpumask_equal(cpu_online_mask, cpu_present_mask))
+		return xics_default_distrib_server;
+
+	return xics_default_server;
+}
+#endif /* CONFIG_SMP */
+
+static int xics_host_match(struct irq_host *h, struct device_node *node)
+{
+	/* IBM machines have interrupt parents of various funky types for things
+	 * like vdevices, events, etc... The trick we use here is to match
+	 * everything here except the legacy 8259 which is compatible "chrp,iic"
+	 */
+	return !of_device_is_compatible(node, "chrp,iic");
+}
+
+/* Dummies */
+static void xics_ipi_unmask(unsigned int virq) { }
+static void xics_ipi_mask(unsigned int virq) { }
+
+static struct irq_chip xics_ipi_chip = {	
+	.name = "XICS",
+	.eoi = NULL, /* Patched at init time */
+	.mask = xics_ipi_mask,
+	.unmask = xics_ipi_unmask,
+};
+
+static int xics_host_map(struct irq_host *h, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	struct ics *ics;
+
+	pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+
+	/* Insert the interrupt mapping into the radix tree for fast lookup */
+	irq_radix_revmap_insert(xics_host, virq, hw);
+
+	irq_to_desc(virq)->status |= IRQ_LEVEL;
+
+	/* Don't call into ICS for IPIs */
+	if (hw == XICS_IPI) {
+		set_irq_chip_and_handler(virq, &xics_ipi_chip,
+					 handle_fasteoi_irq);
+		return 0;
+	}
+
+	/* Let the ICS setup the chip data */
+	list_for_each_entry(ics, &ics_list, link)
+		if (ics->map(ics, virq) == 0)
+			break;
+	return 0;
+}
+
+static int xics_host_xlate(struct irq_host *h, struct device_node *ct,
+			   const u32 *intspec, unsigned int intsize,
+			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+	/* Current xics implementation translates everything
+	 * to level. It is not technically right for MSIs but this
+	 * is irrelevant at this point. We might get smarter in the future
+	 */
+	*out_hwirq = intspec[0];
+	*out_flags = IRQ_TYPE_LEVEL_LOW;
+
+	return 0;
+}
+
+static struct irq_host_ops xics_host_ops = {
+	.match = xics_host_match,
+	.map = xics_host_map,
+	.xlate = xics_host_xlate,
+};
+
+static void __init xics_init_host(void)
+{
+	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops,
+				   XICS_IRQ_SPURIOUS);
+	BUG_ON(xics_host == NULL);
+	irq_set_default_host(xics_host);
+}
+
+void __init xics_register_ics(struct ics *ics)
+{
+	list_add(&ics->link, &ics_list);
+}
+
+static void __init xics_get_server_size(void)
+{
+	struct device_node *np;
+	const u32 *isize;
+
+	/* We fetch the interrupt server size from the first ICS node
+	 * we find if any
+	 */
+	np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xics");
+	if (!np)
+		return;
+	isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
+	if (!isize)
+		return;
+	xics_interrupt_server_size = *isize;
+	of_node_put(np);
+}
+
+void __init xics_init(void)
+{
+	int rc = -1;
+
+	/* Fist locate ICP */
+#ifdef CONFIG_PPC_ICP_HV
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		rc = icp_hv_init();
+#endif
+#ifdef CONFIG_PPC_ICP_NATIVE
+	if (rc < 0)
+		rc = icp_native_init();
+#endif
+	if (rc < 0) {
+		pr_warning("XICS: Cannot find a Presentation Controller !\n");
+		return;
+	}
+
+	/* Copy get_irq callback over to ppc_md */
+	ppc_md.get_irq = icp_ops->get_irq;
+
+	/* Patch up IPI chip EOI */
+	xics_ipi_chip.eoi = icp_ops->eoi;
+
+	/* Now locate ICS */
+#ifdef CONFIG_PPC_ICS_RTAS
+	rc = ics_rtas_init();
+#endif
+	if (rc < 0)
+		pr_warning("XICS: Cannot find a Source Controller !\n");
+
+	/* Initialize common bits */
+	xics_get_server_size();
+	xics_update_irq_servers();
+	xics_init_host();
+	xics_setup_cpu();
+}
-- 
1.7.2.3

^ permalink raw reply related

* Re: [PATCH v3 1/6] powerpc: Move udbg_early_init() after early_init_devtree()
From: Benjamin Herrenschmidt @ 2011-03-17  7:01 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev, Dave Kleikamp
In-Reply-To: <20110315130546.GF3662@zod.rchland.ibm.com>

On Tue, 2011-03-15 at 09:05 -0400, Josh Boyer wrote:
> On Wed, Feb 09, 2011 at 05:08:08PM -0600, Dave Kleikamp wrote:
> >so that it can use information from the device tree.
> >
> >Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
> >Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>
> >Cc: linuxppc-dev@lists.ozlabs.org
> >---
> 
> Ben, you want this patch dropped, right?

Yes !

Cheers,
Ben.

> josh
> 
> > arch/powerpc/kernel/setup_32.c |    6 +++---
> > 1 files changed, 3 insertions(+), 3 deletions(-)
> >
> >diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> >index 1d2fbc9..d1ca976 100644
> >--- a/arch/powerpc/kernel/setup_32.c
> >+++ b/arch/powerpc/kernel/setup_32.c
> >@@ -120,12 +120,12 @@ notrace void __init machine_init(unsigned long dt_ptr)
> > {
> > 	lockdep_init();
> >
> >-	/* Enable early debugging if any specified (see udbg.h) */
> >-	udbg_early_init();
> >-
> > 	/* Do some early initialization based on the flat device tree */
> > 	early_init_devtree(__va(dt_ptr));
> >
> >+	/* Enable early debugging if any specified (see udbg.h) */
> >+	udbg_early_init();
> >+
> > 	probe_machine();
> >
> > 	setup_kdump_trampoline();
> >-- 
> >1.7.3.4
> >

^ permalink raw reply

* Re: [PATCH 1/1] fsl_qe_udc: send ZLP when zero flag and length % maxpacket == 0
From: Sergei Shtylyov @ 2011-03-17 12:47 UTC (permalink / raw)
  To: Valentin Longchamp
  Cc: dbrownell, stefan.bigler, linux-usb, linuxppc-dev, holger.brunck
In-Reply-To: <1300357858-1288-1-git-send-email-valentin.longchamp@keymile.com>

Hello.

On 17-03-2011 13:30, Valentin Longchamp wrote:

> The driver did not take the zero flag in the USB request. If the
> request length is the same as the endpoint's maxpacket, an additional
> ZLP with no data has to be transmitted.

> The method used here is inspired to what is done in fsl_udc_core.c
> (and pxa27x_udc.c and at91_udc.c) where this is supported.

> This is the first version of the patch, it may still contain mistakes,
> but I send it as a RFC since there already was a discussion about this
> topic with people from Keymile:

> http://thread.gmane.org/gmane.linux.usb.general/38951

> Signed-off-by: Valentin Longchamp<valentin.longchamp@keymile.com>
> ---
>   drivers/usb/gadget/fsl_qe_udc.c |   28 +++++++++++++++++++++++-----
>   1 files changed, 23 insertions(+), 5 deletions(-)

> diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
> index 8dc15da..08538f5 100644
> --- a/drivers/usb/gadget/fsl_qe_udc.c
> +++ b/drivers/usb/gadget/fsl_qe_udc.c
[...]
> @@ -1158,13 +1164,24 @@ static int txcomplete(struct qe_ep *ep, unsigned char restart)
>   			ep->last = 0;
>   		}
>
> +		/* zlp needed when req->re.zero is set */
> +		if (req->req.zero) {
> +			if (last_len == 0 ||
> +				(req->req.length % ep->ep.maxpacket) != 0)
> +				zlp = 0;
> +			else
> +				zlp = 1;
> +		} else
> +			zlp = 0;
> +
>   		/* a request already were transmitted completely */
>   		if ((ep->tx_req->req.length - ep->sent) <= 0) {
> -			ep->tx_req->req.actual = (unsigned int)ep->sent;
> -			done(ep, ep->tx_req, 0);
> -			ep->tx_req = NULL;
> -			ep->last = 0;
> -			ep->sent = 0;
> +			if (!zlp) {

    This *if* could be collapsed into previous *if*, and so the subsequest 
indentation level not changed.

> +				done(ep, ep->tx_req, 0);
> +				ep->tx_req = NULL;
> +				ep->last = 0;
> +				ep->sent = 0;
> +			}
>   		}
>   	}
>

WBR, Sergei

^ permalink raw reply

* Re: [PATCH V11 2/4] ptp: Added a clock that uses the eTSEC found on the MPC85xx.
From: Grant Likely @ 2011-03-17 19:21 UTC (permalink / raw)
  To: Richard Cochran
  Cc: John Stultz, Christoph Lameter, Russell King, Rodolfo Giometti,
	Arnd Bergmann, Peter Zijlstra, linux-api, devicetree-discuss,
	linux-kernel, Paul Mackerras, Alan Cox, netdev, Scott Wood,
	Mike Frysinger, Thomas Gleixner, linuxppc-dev, David Miller,
	linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <20110225075320.GA4032@riccoc20.at.omicron.at>

On Fri, Feb 25, 2011 at 08:53:20AM +0100, Richard Cochran wrote:
> On Thu, Feb 24, 2011 at 11:27:31AM -0600, Scott Wood wrote:
> 
> > My vote, if it goes in a separate node at all, is "fsl,etsec-ptp",
> 
> So, that is what the patch does.
> 
> > and let the driver use SVR.
> 
> What is SVR?

An on chip register that provides the exact version of the SoC.  (As
opposed to PVR which is the version of the cpu core).

g.

^ permalink raw reply

* Re: [PATCH 1/4] powerpc/mpc512x: Add initial support for TWR-MPC5125
From: Wolfram Sang @ 2011-03-17 21:25 UTC (permalink / raw)
  To: Vladimir Ermakov; +Cc: linuxppc-dev
In-Reply-To: <1300318163.12970.66.camel@desinto>

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

Hi Vladimir,

(if possible, please provide a diffstat with the patches)

> diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
> index 3dc2a8d..962c0ba 100644
> --- a/arch/powerpc/platforms/512x/clock.c
> +++ b/arch/powerpc/platforms/512x/clock.c
> @@ -669,6 +669,13 @@ static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
>  	clk->rate = mclk_src / mclk_div;
>  }
>  
> +
> +#ifdef CONFIG_PPC_MPC5125
> +#define PSC_PREFIX "mpc5125"
> +#else
> +#define PSC_PREFIX "mpc5121"
> +#endif
> +
>  /*
>   * Find all psc nodes in device tree and assign a clock
>   * with name "psc%d_mclk" and dev pointing at the device
> @@ -680,7 +687,7 @@ static void psc_clks_init(void)
>  	const u32 *cell_index;
>  	struct platform_device *ofdev;
>  
> -	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
> +	for_each_compatible_node(np, NULL, "fsl," PSC_PREFIX "-psc") {

Uh, that makes it impossible to have one kernel for mpc5121/5.

> -void __init mpc512x_psc_fifo_init(void)
> +void __init mpc512x_psc_fifo_init(char *psc_name)
>  {
>  	struct device_node *np;
>  	void __iomem *psc;
>  	unsigned int tx_fifo_size;
>  	unsigned int rx_fifo_size;
> +	char *default_psc = "fsl,mpc5121-psc";
>  	int fifobase = 0; /* current fifo address in 32 bit words */
>  
> -	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
> +	if (!psc_name)
> +		psc_name = default_psc;
> +
> +	for_each_compatible_node(np, NULL, psc_name) {

I think this goes more to the right direction, although you passed the
non-default string for mpc5125 in the board-config, which is the wrong place,
because it is a platform thing.

What about something like:

	if of_find_compatible_node(startpoint, NULL, "fsl,mpc5121-psc")
		psc_compat = "fsl,mpc5121-psc";
	else if of_find_compatible_node(startpoint, NULL, "fsl,mpc5125-psc")
		psc_compat = "fsl,mpc5125-psc";
	else if
		/* Problem handling */

Dunno, might be worth to put it into a function as it could be used here and in
the block above.

Also, I noticed quite a number of magic values (e.g. 0x76). I guess those are
register and bit names, which should be used instead.

Thanks,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* [git pull] Please pull powerpc.git next branch
From: Benjamin Herrenschmidt @ 2011-03-18  5:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list

Hi Linus !

Here are the changes for this merge window for powerpc. One highlight
is irq data conversion so we can get rid of the legacy stuff. The new
Dynamic DMA windows for pSeries should also improve performances for
some devices nicely on more recent machines/firmwares. Plus a little
pack of embedded things.

Cheers,
Ben.

The following changes since commit 08351fc6a75731226e1112fc7254542bd3a2912e:

  Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile (2011-03-17 19:34:12 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next

Anatolij Gustschin (1):
      powerpc/mpc8xxx_gpio: simplify searching for 'fsl, qoriq-gpio' compatiable

Anton Blanchard (1):
      powerpc: Add pgprot_writecombine

Benjamin Herrenschmidt (2):
      powerpc/pseries: Reduce HVCS driver insanity
      Merge remote branch 'jwb/next' into next

Dave Kleikamp (2):
      powerpc/476: define specific cpu table entry DD2 core
      powerpc/476: Workaround for PLB6 hang

Grant Likely (1):
      powerpc/macintosh: Fix __devexit annotation in rack-meter.c

Holger Brunck (3):
      powerpc/83xx: rename and update kmeter1
      powerpc/82xx: rename and update mgcoge board support
      powerpc/8xx: remove obsolete mgsuvd board

Jim Keniston (2):
      powerpc/nvram: Generalize code for OS partitions in NVRAM
      powerpc/pseries/nvram: Capture oops/panic reports in ibm, oops-log partition

Julia Lawall (1):
      drivers/serial/ucc_uart.c: Add of_node_put to avoid memory leak

Justin Mattock (1):
      powerpc/eeh: Remove one to many l's in the word.

Kumar Gala (1):
      powerpc/85xx: Fix writing to spin table 'cpu-release-addr' on ppc64e

Lennert Buytenhek (28):
      powerpc: mpic irq_data conversion.
      powerpc: platforms/512x irq_data conversion.
      powerpc: platforms/52xx irq_data conversion.
      powerpc: platforms/82xx irq_data conversion.
      powerpc: platforms/85xx irq_data conversion.
      powerpc: platforms/86xx irq_data conversion.
      powerpc: platforms/8xx irq_data conversion.
      powerpc: platforms/cell irq_data conversion.
      powerpc: platforms/chrp irq_data conversion.
      powerpc: platforms/embedded6xx irq_data conversion.
      powerpc: platforms/iseries irq_data conversion.
      powerpc: platforms/powermac irq_data conversion.
      powerpc: platforms/ps3 irq_data conversion.
      powerpc: platforms/pseries irq_data conversion.
      powerpc: sysdev/cpm1 irq_data conversion.
      powerpc: sysdev/cpm2_pic irq_data conversion.
      powerpc: sysdev/fsl_msi irq_data conversion.
      powerpc: sysdev/i8259 irq_data conversion.
      powerpc: sysdev/ipic irq_data conversion.
      powerpc: sysdev/mpc8xx_pic irq_data conversion.
      powerpc: sysdev/mpc8xxx_gpio irq_data conversion.
      powerpc: sysdev/mv64x60_pic irq_data conversion.
      powerpc: sysdev/qe_lib/qe_ic irq_data conversion.
      powerpc: sysdev/tsi108_pci irq_data conversion.
      powerpc: sysdev/uic irq_data conversion.
      powerpc: sysdev/xilinx_intc irq_data conversion.
      powerpc: core irq_data conversion.
      powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED.

Liu Yu (1):
      powerpc/85xx: Workaroudn e500 CPU erratum A005

Nicolas Kaiser (1):
      powerpc/mv64x60: Suspected typo in assignment

Nishanth Aravamudan (2):
      powerpc/pseries: Add support for dynamic dma windows
      powerpc/pseries: Disable MSI using new interface if possible

Paul E. McKenney (1):
      powerpc: Mask smp_processor_id() false positive

Prabhakar Kushwaha (1):
      powerpc/fsl_pci: Add support for FSL PCIe controllers v2.x

Prarit Bhargava (1):
      powerpc/pseries: Cleanup use of notifier_from_errno()

Rupjyoti Sarmah (1):
      powerpc/44x: PHY fixup for USB on canyonlands board

Scott Wood (2):
      powerpc: Fix memory limits when starting at a non-zero address
      powerpc/fsl_msi: Handle msi-available-ranges better

Shan Hai (1):
      powerpc/85xx: Fix SPE float to integer conversion failure

Stuart Yoder (1):
      powerpc/fsl: define binding for fsl mpic interrupt controllers

Thomas Gleixner (2):
      powerpc: Use ARCH_IRQ_INIT_FLAGS
      powerpc: Use new irq allocator

Tirumala Marri (1):
      powerpc/44x: Add USB DWC DTS entry to Canyonlands board

Tseng-Hui (Frank) Lin (1):
      powerpc: Cleanup definition of the PID register

Vasiliy Kulikov (1):
      powerpc/85xx: Fix signedness bug in cache-sram

Vivek Mahajan (1):
      powerpc/fsl: 85xx: document cache sram bindings

Xulei (2):
      ATA: Add FSL sata v2 controller support
      powerpc/85xx: Update sata controller compatible for p1022ds board

 .../devicetree/bindings/powerpc/fsl/cache_sram.txt |   20 +
 .../devicetree/bindings/powerpc/fsl/mpic.txt       |  253 +++++++--
 .../devicetree/bindings/powerpc/fsl/msi-pic.txt    |    9 +-
 Documentation/kernel-parameters.txt                |    4 +
 arch/powerpc/Kconfig                               |    1 +
 arch/powerpc/boot/dts/canyonlands.dts              |   24 +
 arch/powerpc/boot/dts/kmeter1.dts                  |   69 ++--
 arch/powerpc/boot/dts/mgcoge.dts                   |   47 +-
 arch/powerpc/boot/dts/mgsuvd.dts                   |  163 ------
 arch/powerpc/boot/dts/p1022ds.dts                  |    4 +-
 arch/powerpc/configs/83xx/kmeter1_defconfig        |    7 +-
 arch/powerpc/configs/mgcoge_defconfig              |    9 +-
 arch/powerpc/configs/mgsuvd_defconfig              |   81 ---
 arch/powerpc/include/asm/cputable.h                |    3 +-
 arch/powerpc/include/asm/hw_irq.h                  |    2 +
 arch/powerpc/include/asm/mpic.h                    |    6 +-
 arch/powerpc/include/asm/nvram.h                   |    3 +-
 arch/powerpc/include/asm/pgtable.h                 |    1 +
 arch/powerpc/include/asm/qe_ic.h                   |   19 +-
 arch/powerpc/include/asm/reg.h                     |   12 +
 arch/powerpc/include/asm/reg_booke.h               |    3 -
 arch/powerpc/kernel/cputable.c                     |   22 +-
 arch/powerpc/kernel/irq.c                          |   55 +-
 arch/powerpc/kernel/machine_kexec.c                |   21 +-
 arch/powerpc/kernel/nvram_64.c                     |   31 +-
 arch/powerpc/kernel/prom.c                         |    2 +-
 arch/powerpc/kernel/rtasd.c                        |    3 +-
 arch/powerpc/math-emu/math_efp.c                   |   65 ++-
 arch/powerpc/mm/init_32.c                          |    2 +-
 arch/powerpc/mm/tlb_nohash_low.S                   |   35 ++
 arch/powerpc/platforms/44x/44x.h                   |    4 +
 arch/powerpc/platforms/44x/Kconfig                 |    1 -
 arch/powerpc/platforms/44x/Makefile                |    1 +
 arch/powerpc/platforms/44x/canyonlands.c           |  134 +++++
 arch/powerpc/platforms/44x/ppc44x_simple.c         |    1 -
 arch/powerpc/platforms/512x/mpc5121_ads_cpld.c     |   14 +-
 arch/powerpc/platforms/52xx/media5200.c            |   21 +-
 arch/powerpc/platforms/52xx/mpc52xx_gpt.c          |   26 +-
 arch/powerpc/platforms/52xx/mpc52xx_pic.c          |   80 ++--
 arch/powerpc/platforms/82xx/Makefile               |    2 +-
 arch/powerpc/platforms/82xx/{mgcoge.c => km82xx.c} |   62 ++-
 arch/powerpc/platforms/82xx/pq2ads-pci-pic.c       |   27 +-
 arch/powerpc/platforms/83xx/Makefile               |    2 +-
 .../powerpc/platforms/83xx/{kmeter1.c => km83xx.c} |   46 +-
 arch/powerpc/platforms/85xx/ksi8560.c              |    3 +-
 arch/powerpc/platforms/85xx/mpc85xx_ads.c          |    3 +-
 arch/powerpc/platforms/85xx/mpc85xx_ds.c           |    3 +-
 arch/powerpc/platforms/85xx/sbc8560.c              |    3 +-
 arch/powerpc/platforms/85xx/smp.c                  |    6 +-
 arch/powerpc/platforms/85xx/socrates_fpga_pic.c    |   40 +-
 arch/powerpc/platforms/85xx/stx_gp3.c              |    3 +-
 arch/powerpc/platforms/85xx/tqm85xx.c              |    3 +-
 arch/powerpc/platforms/86xx/gef_pic.c              |   22 +-
 arch/powerpc/platforms/86xx/pic.c                  |    5 +-
 arch/powerpc/platforms/8xx/Kconfig                 |    6 -
 arch/powerpc/platforms/8xx/Makefile                |    1 -
 arch/powerpc/platforms/8xx/m8xx_setup.c            |    9 +-
 arch/powerpc/platforms/8xx/mgsuvd.c                |   92 ---
 arch/powerpc/platforms/cell/axon_msi.c             |    3 +-
 arch/powerpc/platforms/cell/beat_interrupt.c       |   36 +-
 arch/powerpc/platforms/cell/interrupt.c            |   30 +-
 arch/powerpc/platforms/cell/setup.c                |    6 +-
 arch/powerpc/platforms/cell/spider-pic.c           |   43 +-
 arch/powerpc/platforms/chrp/setup.c                |    5 +-
 arch/powerpc/platforms/embedded6xx/flipper-pic.c   |   32 +-
 arch/powerpc/platforms/embedded6xx/hlwd-pic.c      |   41 +-
 arch/powerpc/platforms/iseries/irq.c               |   43 +-
 arch/powerpc/platforms/pasemi/setup.c              |    4 +-
 arch/powerpc/platforms/powermac/pic.c              |   48 +-
 arch/powerpc/platforms/ps3/interrupt.c             |   40 +-
 arch/powerpc/platforms/pseries/cmm.c               |   14 +-
 arch/powerpc/platforms/pseries/eeh.c               |    2 +-
 arch/powerpc/platforms/pseries/iommu.c             |  587 ++++++++++++++++++++
 arch/powerpc/platforms/pseries/msi.c               |   14 +-
 arch/powerpc/platforms/pseries/nvram.c             |  255 +++++++--
 arch/powerpc/platforms/pseries/setup.c             |    5 +-
 arch/powerpc/platforms/pseries/xics.c              |   89 ++--
 arch/powerpc/sysdev/cpm1.c                         |   18 +-
 arch/powerpc/sysdev/cpm2_pic.c                     |   32 +-
 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c              |    4 +-
 arch/powerpc/sysdev/fsl_msi.c                      |  111 +++--
 arch/powerpc/sysdev/fsl_pci.c                      |   15 +-
 arch/powerpc/sysdev/fsl_pci.h                      |   17 +-
 arch/powerpc/sysdev/i8259.c                        |   42 +-
 arch/powerpc/sysdev/ipic.c                         |   54 +-
 arch/powerpc/sysdev/mpc8xx_pic.c                   |   32 +-
 arch/powerpc/sysdev/mpc8xxx_gpio.c                 |   46 +-
 arch/powerpc/sysdev/mpic.c                         |  137 +++---
 arch/powerpc/sysdev/mpic.h                         |    5 +-
 arch/powerpc/sysdev/mpic_pasemi_msi.c              |   18 +-
 arch/powerpc/sysdev/mpic_u3msi.c                   |   18 +-
 arch/powerpc/sysdev/mv64x60_dev.c                  |    2 +-
 arch/powerpc/sysdev/mv64x60_pic.c                  |   46 +-
 arch/powerpc/sysdev/qe_lib/qe_ic.c                 |   25 +-
 arch/powerpc/sysdev/tsi108_pci.c                   |   41 +-
 arch/powerpc/sysdev/uic.c                          |   59 +-
 arch/powerpc/sysdev/xilinx_intc.c                  |   48 +-
 drivers/ata/sata_fsl.c                             |   25 +-
 drivers/macintosh/rack-meter.c                     |    2 +-
 drivers/tty/hvc/hvcs.c                             |   74 ++-
 drivers/tty/serial/ucc_uart.c                      |   67 ++--
 101 files changed, 2437 insertions(+), 1394 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt
 delete mode 100644 arch/powerpc/boot/dts/mgsuvd.dts
 delete mode 100644 arch/powerpc/configs/mgsuvd_defconfig
 create mode 100644 arch/powerpc/platforms/44x/canyonlands.c
 rename arch/powerpc/platforms/82xx/{mgcoge.c => km82xx.c} (69%)
 rename arch/powerpc/platforms/83xx/{kmeter1.c => km83xx.c} (80%)
 delete mode 100644 arch/powerpc/platforms/8xx/mgsuvd.c

^ permalink raw reply

* [PATCH 1/1] SPI: dw_spi, fix PPC build
From: Jiri Slaby @ 2011-03-18  9:41 UTC (permalink / raw)
  To: dbrownell
  Cc: jirislaby, linux-kernel, Paul Mackerras, spi-devel-general,
	linuxppc-dev

Currently, build on PPC dies with:
In file included from drivers/spi/dw_spi_mmio.c:16:
include/linux/spi/dw_spi.h:147: error: field ‘tx_sgl’ has incomplete type
include/linux/spi/dw_spi.h:149: error: field ‘rx_sgl’ has incomplete type

Add linux/scatterlist.h include to dw_spi.h, because we need to know
the contents of the structure.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
---
 include/linux/spi/dw_spi.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
index 6cd10f6..fb0bce5 100644
--- a/include/linux/spi/dw_spi.h
+++ b/include/linux/spi/dw_spi.h
@@ -2,6 +2,7 @@
 #define DW_SPI_HEADER_H
 
 #include <linux/io.h>
+#include <linux/scatterlist.h>
 
 /* Bit fields in CTRLR0 */
 #define SPI_DFS_OFFSET			0
-- 
1.7.4.1

^ permalink raw reply related

* Re: [PATCH 1/4] powerpc/mpc512x: Add initial support for TWR-MPC5125
From: vooon341 @ 2011-03-18 11:35 UTC (permalink / raw)
  To: Wolfram Sang, linuxppc-dev
In-Reply-To: <20110317212542.GB29231@pengutronix.de>

Hi Wolfram.
I create function for select compat string and give name for registers.

commit fe8895542d537567f43f99af8234e7326451197e
Author: Ermakov Vladimir <ermakov@tecon.ru>
Date:   Thu Mar 17 11:10:49 2011 +0300

    Adds Freescale TWR-MPC5125 device tree and platform code.

    Currently following is supported:
     - NAND
     - FEC1 and FEC2
     - RTC
     - PSC UART

    Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
    ---
    v2:
     - add PSC compat string selection
     - add ioctl defines

diff --git a/arch/powerpc/boot/dts/mpc5125twr.dts
b/arch/powerpc/boot/dts/mpc5125twr.dts
new file mode 100644
index 0000000..54f568f
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc5125twr.dts
@@ -0,0 +1,394 @@
+/*
+ * STx/Freescale ADS5125 MPC5125 silicon
+ *
+ * Copyright (C) 2009 Freescale Semiconductor Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute  it and/or modify i=
t
+ * under  the terms of  the GNU General  Public License as published by th=
e
+ * Free Software Foundation;  either version 2 of the  License, or (at you=
r
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	model =3D "mpc5125ads";
+	compatible =3D "fsl,mpc5125ads";
+	#address-cells =3D <1>;
+	#size-cells =3D <1>;
+
+	cpus {
+		#address-cells =3D <1>;
+		#size-cells =3D <0>;
+
+		PowerPC,5125@0 {
+			device_type =3D "cpu";
+			reg =3D <0>;
+			d-cache-line-size =3D <0x20>;	// 32 bytes
+			i-cache-line-size =3D <0x20>;	// 32 bytes
+			d-cache-size =3D <0x8000>;	// L1, 32K
+			i-cache-size =3D <0x8000>;	// L1, 32K
+			timebase-frequency =3D <49500000>;// 49.5 MHz (csb/4)
+			bus-frequency =3D <198000000>;	// 198 MHz csb bus
+			clock-frequency =3D <396000000>;	// 396 MHz ppc core
+		};
+	};
+
+	memory {
+		device_type =3D "memory";
+		reg =3D <0x00000000 0x10000000>;	// 256MB at 0
+	};
+
+	sram@30000000 {
+		compatible =3D "fsl,mpc5121-sram";
+		reg =3D <0x30000000 0x08000>;		// 32K at 0x30000000
+	};
+
+	nfc@40000000 {
+		compatible =3D "fsl,mpc5125-nfc";
+		reg =3D <0x40000000 0x100000>;	// 1M at 0x40000000
+		interrupts =3D <6 0x8>;
+		interrupt-parent =3D < &ipic >;
+		#address-cells =3D <1>;
+		#size-cells =3D <1>;
+		bank-width =3D <1>;
+		write-size =3D <4096>;
+		spare-size =3D <128>;
+		chips =3D <1>;
+		// NOTE: partition map different than in BSP
+		nand-spl@0 {
+			label =3D "loader";
+			reg =3D <0x00000000 0x00100000>;
+			read-only;
+		};
+		uboot@100000 {
+			label =3D "uboot";
+			reg =3D <0x00100000 0x00100000>;
+			read-only;
+		};
+		uboot-env@200000 {
+			label =3D "uboot-env";
+			reg =3D <0x00200000 0x00100000>;
+			read-only;
+		};
+		kernel300000 {
+			label =3D "kernel";
+			reg =3D <0x00300000 0x00800000>;
+		};
+		device-tree00000 {
+			label =3D "device-tree";
+			reg =3D <0x00b00000 0x00100000>;
+		};
+		ramboot-rootfs@c00000 {
+			label =3D "ramboot-rootfs";
+			reg =3D <0x00c00000 0x00800000>;
+		};
+		rootfs@1400000 {
+			label =3D "rootfs";
+			reg =3D <0x01400000 0x01400000>;
+		};
+		user@2800000 {
+			label =3D "user";
+			reg =3D <0x02800000 0x01400000>;
+		};
+		SRAM@4200000 {
+			label =3D "SRAM"; // NVRAM emul
+			reg =3D <0x04200000 0x01400000>;
+		};
+		prom@5600000 {
+			label =3D "prom";
+			reg =3D <0x05600000 0x01400000>;
+		};
+		//data@2800000 {
+		//	label =3D "data";
+		//	reg =3D <0x28000000 0xeac00000>;
+		//};
+	};
+
+	soc@80000000 {
+		compatible =3D "fsl,mpc5121-immr";
+		device_type =3D "soc";
+		#address-cells =3D <1>;
+		#size-cells =3D <1>;
+		#interrupt-cells =3D <2>;
+		ranges =3D <0x0 0x80000000 0x400000>;
+		reg =3D <0x80000000 0x400000>;
+		bus-frequency =3D <66000000>;	// 66 MHz ips bus
+
+
+		// IPIC
+		// interrupts cell =3D <intr #, sense>
+		// sense values match linux IORESOURCE_IRQ_* defines:
+		// sense =3D=3D 8: Level, low assertion
+		// sense =3D=3D 2: Edge, high-to-low change
+		//
+		ipic: interrupt-controller@c00 {
+			compatible =3D "fsl,mpc5121-ipic", "fsl,ipic";
+			interrupt-controller;
+			#address-cells =3D <0>;
+			#interrupt-cells =3D <2>;
+			reg =3D <0xc00 0x100>;
+		};
+
+		rtc@a00 {	// Real time clock
+			compatible =3D "fsl,mpc5121-rtc";
+			reg =3D <0xa00 0x100>;
+			interrupts =3D <79 0x8 80 0x8>;
+			interrupt-parent =3D < &ipic >;
+		};
+
+		reset@e00 {	// Reset module
+			compatible =3D "fsl,mpc5121-reset";
+			reg =3D <0xe00 0x100>;
+		};
+
+		clock@f00 {	// Clock control
+			compatible =3D "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
+			reg =3D <0xf00 0x100>;
+		};
+
+		pmc@1000{  // Power Management Controller
+			compatible =3D "fsl,mpc5121-pmc";
+			reg =3D <0x1000 0x100>;
+			interrupts =3D <83 0x2>;
+			interrupt-parent =3D < &ipic >;
+		};
+
+		gpio@1100 {
+			compatible =3D "fsl,mpc5125-gpio";
+			cell-index =3D <0>;
+			reg =3D <0x1100 0x080>;
+			interrupts =3D <78 0x8>;
+			interrupt-parent =3D < &ipic >;
+		};
+
+		gpio@1180 {
+			compatible =3D "fsl,mpc5125-gpio1";
+			cell-index =3D <1>;
+			reg =3D <0x1180 0x080>;
+			interrupts =3D <78 0x8>;
+			interrupt-parent =3D < &ipic >;
+		};
+
+		can@1300 { // CAN rev.2
+			compatible =3D "fsl,mpc5121-mscan";
+			cell-index =3D <0>;
+			interrupts =3D <12 0x8>;
+			interrupt-parent =3D < &ipic >;
+			reg =3D <0x1300 0x80>;
+		};
+
+		can@1380 {
+			compatible =3D "fsl,mpc5121-mscan";
+			cell-index =3D <1>;
+			interrupts =3D <13 0x8>;
+			interrupt-parent =3D < &ipic >;
+			reg =3D <0x1380 0x80>;
+		};
+
+		sdhc@1500 {
+			compatible =3D "fsl,mpc5125-sdhc";
+			interrupts =3D <8 0x8>;
+			interrupt-parent =3D < &ipic >;
+			reg =3D <0x1500 0x100>;
+		};
+
+		i2c@1700 {
+			#address-cells =3D <1>;
+			#size-cells =3D <0>;
+			compatible =3D "fsl-i2c";
+			cell-index =3D <0>;
+			reg =3D <0x1700 0x20>;
+			interrupts =3D <0x9 0x8>;
+			interrupt-parent =3D < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2c@1720 {
+			#address-cells =3D <1>;
+			#size-cells =3D <0>;
+			compatible =3D "fsl-i2c";
+			cell-index =3D <1>;
+			reg =3D <0x1720 0x20>;
+			interrupts =3D <0xa 0x8>;
+			interrupt-parent =3D < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2c@1740 {
+			#address-cells =3D <1>;
+			#size-cells =3D <0>;
+			compatible =3D "fsl-i2c";
+			cell-index =3D <2>;
+			reg =3D <0x1740 0x20>;
+			interrupts =3D <0xb 0x8>;
+			interrupt-parent =3D < &ipic >;
+			fsl5200-clocking;
+		};
+
+		i2ccontrol@1760 {
+			compatible =3D "fsl,mpc5121-i2c-ctrl";
+			reg =3D <0x1760 0x8>;
+		};
+
+		//diu@2100 {
+		//	device_type =3D "display";
+		//	compatible =3D "fsl-diu";
+		//	reg =3D <0x2100 0x100>;
+		//	interrupts =3D <64 0x8>;
+		//	interrupt-parent =3D < &ipic >;
+		//};
+
+		// MPC5125e has two more CAN ports
+		// but they are not used on ADS5125
+		//can@2300 {
+		//	compatible =3D "fsl,mpc5121-mscan";
+		//	cell-index =3D <2>;
+		//	interrupts =3D <90 0x8>;
+		//	interrupt-parent =3D < &ipic >;
+		//	reg =3D <0x2300 0x80>;
+		//};
+
+		//can@2380 {
+		//	compatible =3D "fsl,mpc5121-mscan";
+		//	cell-index =3D <3>;
+		//	interrupts =3D <91 0x8>;
+		//	interrupt-parent =3D < &ipic >;
+		//	reg =3D <0x2380 0x80>;
+		//};
+
+		mdio@2800 {
+			device_type =3D "mdio";
+			compatible =3D "fsl,mpc5121-fec-mdio";
+			reg =3D <0x2800 0x800>;
+			#address-cells =3D <1>;
+			#size-cells =3D <0>;
+			phy0: ethernet-phy@0 {
+				reg =3D <1>;
+				device_type =3D "ethernet-phy";
+			};
+		};
+
+		ethernet@2800 {
+			device_type =3D "network";
+			compatible =3D "fsl,mpc5121-fec";
+			reg =3D <0x2800 0x800>;
+			local-mac-address =3D [ 00 00 00 00 00 00 ];
+			interrupts =3D <4 0x8>;
+			interrupt-parent =3D < &ipic >;
+			phy-handle =3D < &phy0 >;
+		};
+
+		// USB ULPI1
+		//usb@3000 {
+		//	device_type =3D "usb";
+		//	compatible =3D "fsl-usb2-dr";
+		//	reg =3D <0x3000 0x400>;
+		//	#address-cells =3D <1>;
+		//	#size-cells =3D <0>;
+		//	interrupt-parent =3D < &ipic >;
+		//	interrupts =3D <43 0x8>;
+		//	dr_mode =3D "host";
+		//	phy_type =3D "ulpi";
+		//	big-endian-regs;
+		//};
+
+		// USB ULPI2
+		//usb@4000 {
+		//	device_type =3D "usb";
+		//	compatible =3D "fsl-usb2-dr";
+		//	reg =3D <0x4000 0x400>;
+		//	#address-cells =3D <1>;
+		//	#size-cells =3D <0>;
+		//	interrupt-parent =3D < &ipic >;
+		//	interrupts =3D <44 0x8>;
+		//	dr_mode =3D "otg";
+		//	phy_type =3D "ulpi";
+		//	big-endian-regs;
+		//};
+
+		mdio@4800 {
+			device_type =3D "mdio";
+			compatible =3D "fsl,mpc5121-fec-mdio";
+			reg =3D <0x4800 0x800>;
+			#address-cells =3D <1>;
+			#size-cells =3D <0>;
+			phy1: ethernet-phy@0 {
+				reg =3D <1>;
+				device_type =3D "ethernet-phy";
+			};
+		};
+
+		ethernet@4800 {
+			device_type =3D "network";
+			compatible =3D "fsl,mpc5121-fec";
+			reg =3D <0x4800 0x800>;
+			local-mac-address =3D [ 00 00 00 00 00 00 ];
+			interrupts =3D <5 0x8>;
+			interrupt-parent =3D < &ipic >;
+			phy-handle =3D < &phy1 >;
+		};
+
+		// IO control
+		ioctl@a000 {
+			compatible =3D "fsl,mpc5125-ioctl";
+			reg =3D <0xA000 0x1000>;
+		};
+
+		// PSC0 in ac97 mode
+		//ac97@11000 {
+		//	device_type =3D "sound";
+		//	compatible =3D "fsl,mpc5125-psc-ac97", "fsl,mpc5125-psc";
+		//	cell-index =3D <0>;
+		//	reg =3D <0x11000 0x100>;
+		//	interrupts =3D <40 0x8>;
+		//	interrupt-parent =3D < &ipic >;
+		//	fsl,mode =3D "ac97-slave";
+		//	rx-fifo-size =3D <384>;
+		//	tx-fifo-size =3D <384>;
+		//};
+
+		// 5125 PSCs are not 52xx or 5121 PSC compatible
+		// PSC1 uart0 aka ttyPSC0
+		serial@11100 {
+			device_type =3D "serial";
+			compatible =3D "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number =3D <0>;
+			cell-index =3D <1>;
+			reg =3D <0x11100 0x100>;
+			interrupts =3D <40 0x8 71 0x8>;
+			interrupt-parent =3D < &ipic >;
+			fsl,rx-fifo-size =3D <16>;
+			fsl,tx-fifo-size =3D <16>;
+			nodcd;
+		};
+
+		// PSC9 uart1 aka ttyPSC1
+		serial@11900 {
+			device_type =3D "serial";
+			compatible =3D "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number =3D <1>;
+			cell-index =3D <9>;
+			reg =3D <0x11900 0x100>;
+			interrupts =3D <40 0x8 32 0x8>;
+			interrupt-parent =3D < &ipic >;
+			fsl,rx-fifo-size =3D <16>;
+			fsl,tx-fifo-size =3D <16>;
+			nodcd;
+		};
+
+		pscfifo@11f00 {
+			compatible =3D "fsl,mpc5121-psc-fifo";
+			reg =3D <0x11f00 0x100>;
+			interrupts =3D <40 0x8>;
+			interrupt-parent =3D < &ipic >;
+		};
+
+		dma@14000 {
+			compatible =3D "fsl,mpc5121-dma"; // old name: "mpc512x-dma2"
+			reg =3D <0x14000 0x1800>;
+			interrupts =3D <65 0x8>;
+			interrupt-parent =3D < &ipic >;
+		};
+	};
+};
diff --git a/arch/powerpc/platforms/512x/Kconfig
b/arch/powerpc/platforms/512x/Kconfig
index 27b0651..0dde4b0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -26,6 +26,20 @@ config MPC5121_GENERIC
 	  Compatible boards include:  Protonic LVT base boards (ZANMCU
 	  and VICVT2).

+config PPC_MPC5125
+	bool "Generic support for MPC5125 based boards"
+	depends on PPC_MPC512x
+	select DEFAULT_UIMAGE
+	select PPC_INDIRECT_PCI
+	default n
+
+config MPC5125_TWR
+	bool "Freescale MPC5125 Tower system"
+	depends on PPC_MPC512x
+	select PPC_MPC5125
+	help
+	  This option enables support for the MPC5125 TWR board.
+
 config PDM360NG
 	bool "ifm PDM360NG board"
 	depends on PPC_MPC512x
diff --git a/arch/powerpc/platforms/512x/Makefile
b/arch/powerpc/platforms/512x/Makefile
index 4efc1c4..5c17561 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -5,3 +5,4 @@ obj-y				+=3D clock.o mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+=3D mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC5121_GENERIC)	+=3D mpc5121_generic.o
 obj-$(CONFIG_PDM360NG)		+=3D pdm360ng.o
+obj-$(CONFIG_MPC5125_TWR)	+=3D mpc5125_twr.o
diff --git a/arch/powerpc/platforms/512x/clock.c
b/arch/powerpc/platforms/512x/clock.c
index 3dc2a8d..5cadf8e 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -606,6 +606,21 @@ static void rate_clks_init(void)
  */
 struct clk dev_clks[2][32];

+char *mpc512x_select_psc_compat(void)
+{
+	char *psc_compats[] =3D {
+		"fsl,mpc5121-psc",
+		"fsl,mpc5125-psc"
+	};
+	int i;
+
+	for (i =3D 0; i < ARRAY_SIZE(psc_compats); i++)
+		if (of_find_compatible_node(NULL, NULL, psc_compats[i]))
+			return psc_compats[i];
+
+	return NULL;
+}
+
 /*
  * Given a psc number return the dev_clk
  * associated with it
@@ -679,8 +694,13 @@ static void psc_clks_init(void)
 	struct device_node *np;
 	const u32 *cell_index;
 	struct platform_device *ofdev;
+	char *psc_compat;
+
+	psc_compat =3D mpc512x_select_psc_compat();
+	if (!psc_compat)
+		return;

-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	for_each_compatible_node(np, NULL, psc_compat) {
 		cell_index =3D of_get_property(np, "cell-index", NULL);
 		if (cell_index) {
 			int pscnum =3D *cell_index;
diff --git a/arch/powerpc/platforms/512x/mpc5125_twr.c
b/arch/powerpc/platforms/512x/mpc5125_twr.c
new file mode 100644
index 0000000..b4f931f
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc5125_twr.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010 LimePC Multimedia Technologies Co., Limited
+ * Copyright (C) 2011 Vladimir Ermakov <vooon341@gmail.com>
+ *
+ * Based on original Freescale Semiconductor BSP
+ * written by Cloudy Chen <chen_yunsong@mtcera.com>
+ *
+ * MPC5125 Tower board setup
+ *
+ * This 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/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include <linux/bootmem.h>
+#include <asm/rheap.h>
+
+#include "mpc512x.h"
+
+// IOCTL registers for USB1/FEC2
+#define IOCTL_USB1_DATA0	0x63
+#define IOCTL_USB1_DATA1	0x64
+#define IOCTL_USB1_DATA2	0x65
+#define IOCTL_USB1_DATA3	0x66
+#define IOCTL_USB1_DATA4	0x67
+#define IOCTL_USB1_DATA5	0x68
+#define IOCTL_USB1_DATA6	0x69
+#define IOCTL_USB1_DATA7	0x6A
+#define IOCTL_USB1_STOP		0x6B
+#define IOCTL_USB1_CLK		0x6C
+#define IOCTL_USB1_NEXT		0x6D
+#define IOCTL_USB1_DIR		0x6E
+
+// IOCTL for PSCx
+#define PSC_TO_IOCTL_OFFSET(psc)	(0x76 + 5 * psc)
+#define IOCTL_PSCx_0		0
+#define IOCTL_PSCx_1		1
+#define IOCTL_PSCx_2		2
+#define IOCTL_PSCx_3		3
+#define IOCTL_PSCx_4		4
+
+// MODES
+#define IOCTL_DEFAULT_MODE	0x03 // FUNCMUX=3D0, PUD=3D0, PUE=3D0, DS=3D3
+#define IOCTL_FEC2_MODE		0x43 // FUNCMUX=3D2, PUD=3D0, PUE=3D0, DS=3D3
+#define IOCTL_PSCx_0_MODE	0x07 // FUNCMUX=3D0, PUD=3D0, PUE=3D0, ST=3D1, D=
S=3D3
+
+static void mpc5125_psc_iopad_init(void __iomem *ioctl, char *name)
+{
+	struct device_node *np;
+	const u32 *cell_index;
+	char *default_psc =3D "fsl,mpc5125-psc";
+	char *psc_name;
+
+	if (name)
+		psc_name =3D name;
+	else
+		psc_name =3D default_psc;
+
+	for_each_compatible_node(np, NULL, psc_name) {
+		cell_index =3D of_get_property(np, "cell-index", NULL);
+		if (cell_index) {
+			u8 __iomem *pscioctl;
+			int psc_num =3D *cell_index;
+			if (psc_num > 1)
+				continue;
+
+			pscioctl =3D ioctl + PSC_TO_IOCTL_OFFSET(psc_num);
+			out_8(pscioctl + IOCTL_PSCx_0, IOCTL_PSCx_0_MODE); // NOTE maybe wrong
+			out_8(pscioctl + IOCTL_PSCx_1, IOCTL_DEFAULT_MODE);
+			out_8(pscioctl + IOCTL_PSCx_2, IOCTL_DEFAULT_MODE);
+			out_8(pscioctl + IOCTL_PSCx_3, IOCTL_DEFAULT_MODE);
+			out_8(pscioctl + IOCTL_PSCx_4, IOCTL_DEFAULT_MODE);
+		}
+	}
+}
+
+static void mpc5125_fec2_usb_io_init(void __iomem *ioctl, int isusb)
+{
+	int i;
+	const u8 offset[12] =3D {
+		IOCTL_USB1_DATA0, IOCTL_USB1_DATA1,
+		IOCTL_USB1_DATA2, IOCTL_USB1_DATA3,
+		IOCTL_USB1_DATA4, IOCTL_USB1_DATA5,
+		IOCTL_USB1_DATA6, IOCTL_USB1_DATA7,
+		IOCTL_USB1_STOP, IOCTL_USB1_CLK,
+		IOCTL_USB1_NEXT, IOCTL_USB1_DIR
+	};
+	u8 mode;
+
+	mode =3D (isusb) ? IOCTL_DEFAULT_MODE : IOCTL_FEC2_MODE;
+	for (i =3D 0; i < ARRAY_SIZE(offset); i++)
+		out_8(ioctl + offset[i], mode);
+}
+
+static void __init mpc5125_board_setup(void)
+{
+	struct device_node *np;
+
+	/*
+	 * io pad config
+	 */
+	np =3D of_find_compatible_node(NULL, NULL, "fsl,mpc5125-ioctl");
+	if (np) {
+		void __iomem *ioctl =3D of_iomap(np, 0);
+
+		mpc5125_psc_iopad_init(ioctl, NULL);
+		mpc5125_fec2_usb_io_init(ioctl, 0);
+
+		of_node_put(np);
+		iounmap(ioctl);
+	}
+}
+
+static void __init mpc5125_ads_setup_arch(void)
+{
+	printk(KERN_INFO "MPC5125 ADS board from Freescale Semiconductor\n");
+
+	mpc5125_board_setup();
+}
+
+static struct of_device_id __initdata of_bus_ids[] =3D {
+	{ .name =3D "soc", },
+	{},
+};
+
+static void __init mpc5125_ads_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
+		printk(KERN_ERR __FILE__ ": "
+			"Error while probing of_platform bus\n");
+
+	np =3D of_find_compatible_node(NULL, NULL, "fsl,mpc5125-nfc");
+	if (np) {
+		of_platform_device_create(np, NULL, NULL);
+		of_node_put(np);
+	}
+}
+
+static void __init mpc5125_ads_init(void)
+{
+	mpc5125_ads_declare_of_platform_devices();
+	mpc5121_clk_init();
+	mpc512x_restart_init();
+	mpc512x_psc_fifo_init();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc5125_ads_probe(void)
+{
+	unsigned long root =3D of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,mpc5125ads");
+}
+
+define_machine(mpc5125_ads) {
+	.name			=3D "MPC5125 ADS",
+	.probe			=3D mpc5125_ads_probe,
+	.setup_arch		=3D mpc5125_ads_setup_arch,
+	.init			=3D mpc5125_ads_init,
+	.init_IRQ		=3D mpc512x_init_IRQ,
+	.get_irq		=3D ipic_get_irq,
+	.calibrate_decr		=3D generic_calibrate_decr,
+	.restart		=3D mpc512x_restart,
+};
diff --git a/arch/powerpc/platforms/512x/mpc512x.h
b/arch/powerpc/platforms/512x/mpc512x.h
index 1ab6d11..91c903f 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -13,8 +13,11 @@
 #define __MPC512X_H__
 extern void __init mpc512x_init_IRQ(void);
 extern void __init mpc512x_init(void);
+extern void __init mpc512x_restart_init(void);
 extern int __init mpc5121_clk_init(void);
-void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_psc_fifo_init(void);
+extern char *mpc512x_select_psc_compat(void);
 extern void mpc512x_restart(char *cmd);
 extern void mpc512x_init_diu(void);
 extern void mpc512x_setup_diu(void);
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c
b/arch/powerpc/platforms/512x/mpc512x_shared.c
index e41ebbd..52283d6 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -32,7 +32,7 @@

 static struct mpc512x_reset_module __iomem *reset_module_base;

-static void __init mpc512x_restart_init(void)
+void __init mpc512x_restart_init(void)
 {
 	struct device_node *np;

@@ -407,9 +407,16 @@ void __init mpc512x_psc_fifo_init(void)
 	void __iomem *psc;
 	unsigned int tx_fifo_size;
 	unsigned int rx_fifo_size;
+	char *psc_compat;
 	int fifobase =3D 0; /* current fifo address in 32 bit words */

-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	psc_compat =3D mpc512x_select_psc_compat();
+	if (!psc_compat) {
+		pr_err("%s: no compatible devices found\n", __func__);
+		return;
+	}
+
+	for_each_compatible_node(np, NULL, psc_compat) {
 		tx_fifo_size =3D get_fifo_size(np, "fsl,tx-fifo-size");
 		rx_fifo_size =3D get_fifo_size(np, "fsl,rx-fifo-size");


2011/3/18 Wolfram Sang <w.sang@pengutronix.de>
>
> Hi Vladimir,
>
> (if possible, please provide a diffstat with the patches)
>
> > diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platfor=
ms/512x/clock.c
> > index 3dc2a8d..962c0ba 100644
> > --- a/arch/powerpc/platforms/512x/clock.c
> > +++ b/arch/powerpc/platforms/512x/clock.c
> > @@ -669,6 +669,13 @@ static void psc_calc_rate(struct clk *clk, int psc=
num, struct device_node *np)
> > =C2=A0 =C2=A0 =C2=A0 clk->rate =3D mclk_src / mclk_div;
> > =C2=A0}
> >
> > +
> > +#ifdef CONFIG_PPC_MPC5125
> > +#define PSC_PREFIX "mpc5125"
> > +#else
> > +#define PSC_PREFIX "mpc5121"
> > +#endif
> > +
> > =C2=A0/*
> > =C2=A0 * Find all psc nodes in device tree and assign a clock
> > =C2=A0 * with name "psc%d_mclk" and dev pointing at the device
> > @@ -680,7 +687,7 @@ static void psc_clks_init(void)
> > =C2=A0 =C2=A0 =C2=A0 const u32 *cell_index;
> > =C2=A0 =C2=A0 =C2=A0 struct platform_device *ofdev;
> >
> > - =C2=A0 =C2=A0 for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
> > + =C2=A0 =C2=A0 for_each_compatible_node(np, NULL, "fsl," PSC_PREFIX "-=
psc") {
>
> Uh, that makes it impossible to have one kernel for mpc5121/5.
>
> > -void __init mpc512x_psc_fifo_init(void)
> > +void __init mpc512x_psc_fifo_init(char *psc_name)
> > =C2=A0{
> > =C2=A0 =C2=A0 =C2=A0 struct device_node *np;
> > =C2=A0 =C2=A0 =C2=A0 void __iomem *psc;
> > =C2=A0 =C2=A0 =C2=A0 unsigned int tx_fifo_size;
> > =C2=A0 =C2=A0 =C2=A0 unsigned int rx_fifo_size;
> > + =C2=A0 =C2=A0 char *default_psc =3D "fsl,mpc5121-psc";
> > =C2=A0 =C2=A0 =C2=A0 int fifobase =3D 0; /* current fifo address in 32 =
bit words */
> >
> > - =C2=A0 =C2=A0 for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
> > + =C2=A0 =C2=A0 if (!psc_name)
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 psc_name =3D default_psc;
> > +
> > + =C2=A0 =C2=A0 for_each_compatible_node(np, NULL, psc_name) {
>
> I think this goes more to the right direction, although you passed the
> non-default string for mpc5125 in the board-config, which is the wrong pl=
ace,
> because it is a platform thing.
>
> What about something like:
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if of_find_compatible_node(startpoint, NULL, "=
fsl,mpc5121-psc")
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0psc_compat =3D "fs=
l,mpc5121-psc";
> =C2=A0 =C2=A0 =C2=A0 =C2=A0else if of_find_compatible_node(startpoint, NU=
LL, "fsl,mpc5125-psc")
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0psc_compat =3D "fs=
l,mpc5125-psc";
> =C2=A0 =C2=A0 =C2=A0 =C2=A0else if
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Problem handlin=
g */
>
> Dunno, might be worth to put it into a function as it could be used here =
and in
> the block above.
>
> Also, I noticed quite a number of magic values (e.g. 0x76). I guess those=
 are
> register and bit names, which should be used instead.
>
> Thanks,
>
> =C2=A0 Wolfram
>
> --
> Pengutronix e.K. =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | Wolfram Sang =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|
> Industrial Linux Solutions =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 | http://www.pengutronix.de/ =C2=A0|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAk2CfFYACgkQD27XaX1/VRsmcwCfdqwIn6V6VDwm7wZXm1PDHXmx
> 0mcAnirFHcCmZ4TqqNXbXfOOWsDPFauA
> =3DU2sn
> -----END PGP SIGNATURE-----
>

^ permalink raw reply related


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