bk://bkbits.246tNt.com/linux-2.5-mpc52xx-pending
tnt@246tNt-laptop.lan.ayanami.246tNt.com|ChangeSet|20040708141802|18700 tnt

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/11 13:37:25-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mpc52xx
# 
# drivers/serial/Kconfig
#   2004/07/11 13:37:22-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/07/08 16:18:02+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com 
#   Add support for MPC52xx PSCs.
#   
#   Can be used as serial port and console. Compliant with the OCP driver model.
#   
#   Signed-off-by: Sylvain Munaut <tnt@246tNt.com> 
# 
# drivers/serial/mpc52xx_uart.c
#   2004/07/08 16:17:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +869 -0
# 
# include/linux/serial_core.h
#   2004/07/08 16:17:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +3 -0
#   Add port number for MPC52xx PSCs
# 
# drivers/serial/mpc52xx_uart.c
#   2004/07/08 16:17:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/drivers/serial/mpc52xx_uart.c
# 
# drivers/serial/Makefile
#   2004/07/08 16:17:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +1 -0
#   Add options for MPC52xx PSCs to be used as UART (serial port & console)
# 
# drivers/serial/Kconfig
#   2004/07/08 16:17:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +27 -0
#   Add options for MPC52xx PSCs to be used as UART (serial port & console)
# 
# ChangeSet
#   2004/07/08 16:11:09+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com 
#   Add basic support for the Freescale MPC52xx embedded CPU and the LITE5200 platform. 
#   
#   Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
# 
# include/asm-ppc/mpc52xx_psc.h
#   2004/07/08 16:10:56+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +191 -0
# 
# include/asm-ppc/mpc52xx.h
#   2004/07/08 16:10:56+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +380 -0
# 
# include/asm-ppc/mpc52xx_psc.h
#   2004/07/08 16:10:56+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/include/asm-ppc/mpc52xx_psc.h
# 
# include/asm-ppc/mpc52xx.h
#   2004/07/08 16:10:56+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/include/asm-ppc/mpc52xx.h
# 
# arch/ppc/syslib/mpc52xx_setup.c
#   2004/07/08 16:10:55+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +228 -0
# 
# arch/ppc/syslib/mpc52xx_setup.c
#   2004/07/08 16:10:55+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/syslib/mpc52xx_setup.c
# 
# arch/ppc/syslib/mpc52xx_pic.c
#   2004/07/08 16:10:54+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +252 -0
# 
# arch/ppc/syslib/mpc52xx_pic.c
#   2004/07/08 16:10:54+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/syslib/mpc52xx_pic.c
# 
# arch/ppc/platforms/mpc5200.c
#   2004/07/08 16:10:53+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +29 -0
# 
# arch/ppc/platforms/mpc5200.c
#   2004/07/08 16:10:53+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/platforms/mpc5200.c
# 
# arch/ppc/platforms/lite5200.h
#   2004/07/08 16:10:52+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +23 -0
# 
# arch/ppc/platforms/lite5200.h
#   2004/07/08 16:10:52+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/platforms/lite5200.h
# 
# arch/ppc/platforms/lite5200.c
#   2004/07/08 16:10:51+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +152 -0
# 
# arch/ppc/platforms/lite5200.c
#   2004/07/08 16:10:51+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/platforms/lite5200.c
# 
# arch/ppc/configs/lite5200_defconfig
#   2004/07/08 16:10:50+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +436 -0
# 
# arch/ppc/configs/lite5200_defconfig
#   2004/07/08 16:10:50+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/configs/lite5200_defconfig
# 
# arch/ppc/boot/simple/mpc52xx_tty.c
#   2004/07/08 16:10:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +138 -0
# 
# arch/ppc/boot/simple/mpc52xx_tty.c
#   2004/07/08 16:10:49+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/arch/ppc/boot/simple/mpc52xx_tty.c
# 
# Documentation/powerpc/mpc52xx.txt
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +48 -0
# 
# include/asm-ppc/ppcboot.h
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +7 -0
#   Add MPC52xx specific fields
# 
# include/asm-ppc/ocp_ids.h
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +1 -0
#   Add OCP ID for the MPC52xx Programmable Serial Controler (PSC) working as an UART
# 
# arch/ppc/syslib/Makefile
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +1 -0
#   Add options for Freescale MPC52xx and it's LITE5200 board
# 
# arch/ppc/platforms/Makefile
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +1 -0
#   Add options for Freescale MPC52xx and it's LITE5200 board
# 
# arch/ppc/kernel/cputable.c
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +2 -2
#   Add MPC52xx entry with the 8280 entry, they are both G2_LE core
# 
# arch/ppc/boot/simple/Makefile
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +7 -0
#   Add options for Freescale MPC52xx and it's LITE5200 board
# 
# arch/ppc/boot/common/misc-common.c
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +5 -5
#   Add options for Freescale MPC52xx and it's LITE5200 board
# 
# arch/ppc/Kconfig
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +20 -8
#   Add options for Freescale MPC52xx and it's LITE5200 board
# 
# Documentation/powerpc/mpc52xx.txt
#   2004/07/08 16:10:48+02:00 tnt@246tNt-laptop.lan.ayanami.246tNt.com +0 -0
#   BitKeeper file /home/tnt/musicbox/kernel/linux-2.5-mpc52xx/Documentation/powerpc/mpc52xx.txt
# 
diff -Nru a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/powerpc/mpc52xx.txt	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,48 @@
+Linux 2.6.x on MPC52xx family
+-----------------------------
+
+For the latest info, go to http://www.246tNt.com/mpc52xx/state.txt
+ 
+To compile/use :
+
+  - U-Boot:
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # make uImage
+    
+     then, on U-boot:
+     => tftpboot 200000 uImage
+     => tftpboot 400000 pRamdisk
+     => bootm 200000 400000
+    
+  - DBug:
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
+     # make zImage.initrd 
+     # make 
+
+     then in DBug:
+     DBug> dn -i zImage.initrd.lite5200
+     
+
+Some remarks :
+ - The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100
+   is not supported, and I'm not sure anyone is interesting in working on it
+   so. I didn't took 5xxx because there's apparently a lot of 5xxx that have
+   nothing to do with the MPC5200. I also included the 'MPC' for the same
+   reason.
+ - Of course, I inspired myself from the 2.4 port. If you think I forgot to
+   mention you/your company in the copyright of some code, I'll correct it
+   ASAP.
+ - The codes wants the MBAR to be set at 0xf0000000 by the bootloader. It's
+   mapped 1:1 with the MMU. If for whatever reason, you want to change this,
+   beware that some code depends on the 0xf0000000 address and other depends
+   on the 1:1 mapping.
+ - Most of the code assumes that port multiplexing, frequency selection, ...
+   has already been done. IMHO this should be done as early as possible, in
+   the bootloader. If for whatever reason you can't do it there, do it in the
+   platform setup code (if U-Boot) or in the arch/ppc/boot/simple/... (if
+   DBug)
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/Kconfig	2004-07-13 12:45:03 -07:00
@@ -44,18 +44,18 @@
 	default 6xx
 
 config 6xx
-	bool "6xx/7xx/74xx/8260"
+	bool "6xx/7xx/74xx/52xx/8260"
 	help
 	  There are four types of PowerPC chips supported.  The more common
 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-	  versions (821, 823, 850, 855, 860, 8260), the IBM embedded versions
-	  (403 and 405) and the high end 64 bit Power processors (POWER 3,
-	  POWER4, and IBM 970 also known as G5)
+	  versions (821, 823, 850, 855, 860, 52xx, 8260), the IBM embedded
+	  versions (403 and 405) and the high end 64 bit Power processors 
+	  (POWER 3, POWER4, and IBM 970 also known as G5)
 	  Unless you are building a kernel for one of the embedded processor
 	  systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
 	  Note that the kernel runs in 32-bit mode even on 64-bit chips.
-	  Also note that because the 82xx family has a 603e core, specific
-	  support for that chipset is asked later on.
+	  Also note that because the 52xx & 82xx family has a 603e core,
+	  specific support for that chipset is asked later on.
 
 config 40x
 	bool "40x"
@@ -601,6 +601,15 @@
 config ADS8272
 	bool "ADS8272"
 
+config LITE5200
+	bool "Freescale LITE5200 / (IceCube)"
+	select PPC_MPC52xx
+	help
+	  Support for the LITE5200 dev board for the MPC5200 from Freescale.
+	  This is for the LITE5200 version 2.0 board. Don't know if it changes
+	  much but it's only been tested on this board version. I think this
+	  board is also known as IceCube.
+
 endchoice
 
 config PQ2ADS
@@ -617,6 +626,9 @@
 	bool
 	depends on 8xx || 8260
 	default y
+	
+config PPC_MPC52xx
+	bool
 
 config 8260
 	bool "CPM2 Support" if WILLOW
@@ -707,7 +719,7 @@
 
 config FSL_OCP
 	bool
-	depends on MPC10X_BRIDGE
+	depends on MPC10X_BRIDGE || PPC_MPC52xx
 	default y
 
 config MPC10X_OPENPIC
@@ -1363,7 +1375,7 @@
 
 config SERIAL_TEXT_DEBUG
 	bool "Support for early boot texts over serial port"
-	depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550
+	depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
 
 config PPC_OCP
 	bool
diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
--- a/arch/ppc/boot/common/misc-common.c	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/boot/common/misc-common.c	2004-07-13 12:45:03 -07:00
@@ -59,7 +59,7 @@
 void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
 unsigned char *ISA_io = NULL;
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)
 extern unsigned long com_port;
 
 extern int serial_tstc(unsigned long com_port);
@@ -80,7 +80,7 @@
 
 int tstc(void)
 {
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)
 	if(keyb_present)
 		return (CRT_tstc() || serial_tstc(com_port));
 	else
@@ -93,7 +93,7 @@
 int getc(void)
 {
 	while (1) {
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)
 		if (serial_tstc(com_port))
 			return (serial_getc(com_port));
 #endif /* serial console */
@@ -108,7 +108,7 @@
 {
 	int x,y;
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)
 	serial_putc(com_port, c);
 	if ( c == '\n' )
 		serial_putc(com_port, '\r');
@@ -155,7 +155,7 @@
 	y = orig_y;
 
 	while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_SERIAL_MPC52xx_CONSOLE)
 	        serial_putc(com_port, c);
 	        if ( c == '\n' ) serial_putc(com_port, '\r');
 #endif /* serial console */
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/boot/simple/Makefile	2004-07-13 12:45:03 -07:00
@@ -113,6 +113,12 @@
   entrypoint-$(CONFIG_SPRUCE)		:= 0x00800000
         misc-$(CONFIG_SPRUCE)		+= misc-spruce.o
 
+      zimage-$(CONFIG_LITE5200)		:= zImage-STRIPELF
+zimageinitrd-$(CONFIG_LITE5200)		:= zImage.initrd-STRIPELF
+         end-$(CONFIG_LITE5200)		:= lite5200
+   cacheflag-$(CONFIG_LITE5200)		:= -include $(clear_L2_L3)
+
+
 # SMP images should have a '.smp' suffix.
          end-$(CONFIG_SMP)             := $(end-y).smp
 
@@ -144,6 +150,7 @@
 boot-$(CONFIG_8260)		+= m8260_tty.o
 boot-$(CONFIG_GT64260_CONSOLE)	+= gt64260_tty.o
 endif
+boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o
 
 LIBS				:= $(common)/lib.a $(bootlib)/lib.a
 ifeq ($(CONFIG_PPC_PREP),y)
diff -Nru a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/mpc52xx_tty.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,138 @@
+/*
+ * arch/ppc/boot/simple/mpc52xx_tty.c
+ *
+ * Minimal serial functions needed to send messages out a MPC52xx
+ * Programmable Serial Controller (PSC).
+ *
+ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc.  This file is licensed under the
+ * terms of the GNU General Public License version 2.  This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+#include <asm/serial.h>
+#include <asm/time.h>
+
+#if MPC52xx_PF_CONSOLE_PORT == 0
+#define MPC52xx_CONSOLE		MPC52xx_PSC1
+#define MPC52xx_PSC_CONFIG_SHIFT	0
+#elif MPC52xx_PF_CONSOLE_PORT == 1
+#define MPC52xx_CONSOLE		MPC52xx_PSC2
+#define MPC52xx_PSC_CONFIG_SHIFT	4
+#elif MPC52xx_PF_CONSOLE_PORT == 2
+#define MPC52xx_CONSOLE		MPC52xx_PSC3
+#define MPC52xx_PSC_CONFIG_SHIFT	8
+#else
+#error "MPC52xx_PF_CONSOLE_PORT not defined"
+#endif
+
+static struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
+
+/* The decrementer counts at the system bus clock frequency
+ * divided by four.  The most accurate time base is connected to the
+ * rtc.  We read the decrementer change during one rtc tick (one second)
+ * and multiply by 4 to get the system bus clock frequency.
+ */
+int
+mpc52xx_ipbfreq(void)
+{
+	struct mpc52xx_rtc *rtc = (struct mpc52xx_rtc*)MPC52xx_RTC;
+	struct mpc52xx_cdm *cdm = (struct mpc52xx_cdm*)MPC52xx_CDM;
+	int current_time, previous_time;
+	int tbl_start, tbl_end;
+	int xlbfreq, ipbfreq;
+
+	out_be32(&rtc->dividers, 0x8f1f0000);	/* Set RTC 64x faster */
+	previous_time = in_be32(&rtc->time);
+	while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+	tbl_start = get_tbl();
+	previous_time = current_time;
+	while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+	tbl_end = get_tbl();
+	out_be32(&rtc->dividers, 0xffff0000);   /* Restore RTC */
+
+	xlbfreq = (tbl_end - tbl_start) << 8;
+	ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq;
+
+	return ipbfreq;
+}
+
+unsigned long
+serial_init(int ignored, void *ignored2)
+{
+	struct mpc52xx_gpio *gpio = (struct mpc52xx_gpio *)MPC52xx_GPIO;
+	int divisor;
+	int mode1;
+	int mode2;
+	u32 val32;
+
+	static int been_here = 0;
+
+	if (been_here)
+		return 0;
+
+	been_here = 1;
+
+	val32 = in_be32(&gpio->port_config);
+	val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT);
+	val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD
+				<< MPC52xx_PSC_CONFIG_SHIFT;
+	out_be32(&gpio->port_config, val32);
+
+	out_8(&psc->command, MPC52xx_PSC_RST_TX
+			| MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE);
+	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+
+	out_be32(&psc->sicr, 0x0);
+	out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00);
+	out_be16(&psc->tfalarm, 0xf8);
+
+	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1
+			| MPC52xx_PSC_RX_ENABLE
+			| MPC52xx_PSC_TX_ENABLE);
+
+	divisor = ((mpc52xx_ipbfreq()
+			/ (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1;
+
+	mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE
+			| MPC52xx_PSC_MODE_ERR;
+	mode2 = MPC52xx_PSC_MODE_ONE_STOP;
+
+	out_8(&psc->ctur, divisor>>8);
+	out_8(&psc->ctlr, divisor);
+	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+	out_8(&psc->mode, mode1);
+	out_8(&psc->mode, mode2);
+
+	return 0;	/* ignored */
+}
+
+void
+serial_putc(void *ignored, const char c)
+{
+	serial_init(0, 0);
+
+	while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
+	out_8(&psc->mpc52xx_psc_buffer_8, c);
+	while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
+}
+
+char
+serial_getc(void *ignored)
+{
+	while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY)) ;
+
+	return in_8(&psc->mpc52xx_psc_buffer_8);
+}
+
+int
+serial_tstc(void *ignored)
+{
+	return (in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY) != 0;
+}
diff -Nru a/arch/ppc/configs/lite5200_defconfig b/arch/ppc/configs/lite5200_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/configs/lite5200_defconfig	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,436 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_ALTIVEC is not set
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_FSL_OCP=y
+CONFIG_PPC_STD_MMU=y
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+CONFIG_LITE5200=y
+CONFIG_PPC_MPC52xx=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0 root=/dev/ram0 rw"
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+#
+# Device Drivers
+#
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+#
+# Plug and Play support
+#
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+#
+# Fusion MPT device support
+#
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+#
+# Macintosh device drivers
+#
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+#
+# ISDN subsystem
+#
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+#
+# Input device support
+#
+CONFIG_INPUT=y
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+#
+# Misc devices
+#
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+#
+# Digital Video Broadcasting Devices
+#
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+#
+# USB support
+#
+# CONFIG_USB is not set
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+#
+# Library routines
+#
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_SERIAL_TEXT_DEBUG=y
+CONFIG_PPC_OCP=y
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/kernel/cputable.c	2004-07-13 12:45:03 -07:00
@@ -351,8 +351,8 @@
 	32, 32,
 	__setup_cpu_603
     },
-    {	/* 8280 is a G2_LE (603e core, plus some) */
-	0x7fff0000, 0x00820000, "8280",
+    {	/* 8280 is a G2_LE (603e core, plus some), MPC52xx is a G2_LE too */
+	0x7fff0000, 0x00820000, "8280/MPC52xx",
 	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
 	CPU_FTR_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
 	COMMON_PPC,
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/platforms/Makefile	2004-07-13 12:45:03 -07:00
@@ -48,6 +48,7 @@
 obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
 obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
 obj-$(CONFIG_SPRUCE)		+= spruce.o
+obj-$(CONFIG_LITE5200)		+= lite5200.o mpc5200.o
 
 ifeq ($(CONFIG_SMP),y)
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o
diff -Nru a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/lite5200.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,152 @@
+/*
+ * arch/ppc/platforms/lite5200.c
+ *
+ * Platform support file for the Freescale LITE5200 based on MPC52xx.
+ * A maximum of this file should be moved to syslib/mpc52xx_?????
+ * so that new platform based on MPC52xx need a minimal platform file
+ * ( avoid code duplication )
+ *
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based on the 2.4 code written by Kent Borg,
+ * Dale Farnsworth <dale.farnsworth@mvista.com> and
+ * Wolfgang Denk <wd@denx.de>
+ * 
+ * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2003 Motorola Inc.
+ * Copyright 2003 MontaVista Software Inc.
+ * Copyright 2003 DENX Software Engineering (wd@denx.de)
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <asm/mpc52xx.h>
+
+
+/* Board data given by U-Boot */
+bd_t __res;
+EXPORT_SYMBOL(__res);	/* For modules */
+
+
+/* ======================================================================== */
+/* OCP device definition                                                    */
+/* For board/shared resources like PSCs                                     */
+/* ======================================================================== */
+/* Be sure not to load conficting devices : e.g. loading the UART drivers for
+ * PSC1 and then also loading a AC97 for this same PSC.
+ * For details about how to create an entry, look in the doc of the concerned
+ * driver ( eg drivers/serial/mpc52xx_uart.c for the PSC in uart mode )
+ */
+
+struct ocp_def board_ocp[] = {
+	{
+		.vendor		= OCP_VENDOR_FREESCALE,
+		.function	= OCP_FUNC_PSC_UART,
+		.index		= 0,
+		.paddr		= MPC52xx_PSC1,
+		.irq		= MPC52xx_PSC1_IRQ,
+		.pm		= OCP_CPM_NA,
+	},
+	{	/* Terminating entry */
+		.vendor		= OCP_VENDOR_INVALID
+	}
+};
+	
+
+/* ======================================================================== */
+/* Platform specific code                                                   */
+/* ======================================================================== */
+
+static int
+icecube_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "machine\t\t: Freescale LITE5200\n");
+	return 0;
+}
+
+static void __init
+icecube_setup_arch(void)
+{
+
+	/* Add board OCP definitions */
+	mpc52xx_add_board_devices(board_ocp);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+              unsigned long r6, unsigned long r7)
+{
+	/* Generic MPC52xx platform initialization */
+	/* TODO Create one and move a max of stuff in it.
+	   Put this init in the syslib */
+
+	struct bi_record *bootinfo = find_bootinfo();
+
+	if (bootinfo)
+		parse_bootinfo(bootinfo);
+	else {
+		/* Load the bd_t board info structure */
+		if (r3)
+			memcpy((void*)&__res,(void*)(r3+KERNELBASE),
+					sizeof(bd_t));
+
+#ifdef CONFIG_BLK_DEV_INITRD
+		/* Load the initrd */
+		if (r4) {
+			initrd_start = r4 + KERNELBASE;
+			initrd_end = r5 + KERNELBASE;
+		}
+#endif
+	
+		/* Load the command line */
+		if (r6) {
+			*(char *)(r7+KERNELBASE) = 0;
+			strcpy(cmd_line, (char *)(r6+KERNELBASE));
+		}
+	}
+
+	/* BAT setup */
+	mpc52xx_set_bat();
+	
+	/* No ISA bus AFAIK */
+	isa_io_base		= 0;
+	isa_mem_base		= 0;
+
+	/* Setup the ppc_md struct */
+	ppc_md.setup_arch	= icecube_setup_arch;
+	ppc_md.show_cpuinfo	= icecube_show_cpuinfo;
+	ppc_md.show_percpuinfo	= NULL;
+	ppc_md.init_IRQ		= mpc52xx_init_irq;
+	ppc_md.get_irq		= mpc52xx_get_irq;
+
+	ppc_md.find_end_of_memory = mpc52xx_find_end_of_memory;
+	ppc_md.setup_io_mappings  = mpc52xx_map_io;
+
+	ppc_md.restart		= mpc52xx_restart;
+	ppc_md.power_off	= mpc52xx_power_off;
+	ppc_md.halt		= mpc52xx_halt;
+	
+		/* No time keeper on the IceCube */
+	ppc_md.time_init	= NULL;
+	ppc_md.get_rtc_time	= NULL;
+	ppc_md.set_rtc_time	= NULL;
+	
+	ppc_md.calibrate_decr	= mpc52xx_calibrate_decr;
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress		= mpc52xx_progress;
+#endif
+}
+
diff -Nru a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/lite5200.h	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,23 @@
+/*
+ * arch/ppc/platforms/lite5200.h
+ * 
+ * Definitions for Freescale LITE5200 : MPC52xx Standard Development
+ * Platform board support
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __PLATFORMS_LITE5200_H__
+#define __PLATFORMS_LITE5200_H__
+
+/* Serial port used for low-level debug */
+#define MPC52xx_PF_CONSOLE_PORT 0	/* PSC1 */
+
+
+#endif /* __PLATFORMS_LITE5200_H__ */
diff -Nru a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/mpc5200.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,29 @@
+/*
+ * arch/ppc/platforms/mpc5200.c
+ *
+ * OCP Definitions for the boards based on MPC5200 processor. Contains
+ * definitions for every common peripherals. (Mostly all but PSCs)
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <asm/ocp.h>
+#include <asm/mpc52xx.h>
+
+/* Here is the core_ocp struct.
+ * With all the devices common to all board. Even if port multiplexing is
+ * not setup for them (if the user don't want them, just don't select the
+ * config option). The potentially conflicting devices (like PSCs) goes in
+ * board specific file.
+ */
+struct ocp_def core_ocp[] = {
+	{	/* Terminating entry */
+		.vendor		= OCP_VENDOR_INVALID
+	}
+};
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	2004-07-13 12:45:03 -07:00
+++ b/arch/ppc/syslib/Makefile	2004-07-13 12:45:03 -07:00
@@ -86,3 +86,4 @@
 ifeq ($(CONFIG_85xx),y)
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o
 endif
+obj-$(CONFIG_PPC_MPC52xx)	+= mpc52xx_setup.o mpc52xx_pic.o
diff -Nru a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/mpc52xx_pic.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,252 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ *
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ * 
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/mpc52xx.h>
+
+
+static struct mpc52xx_intr *intr;
+static struct mpc52xx_sdma *sdma;
+
+static void
+mpc52xx_ic_disable(unsigned int irq)
+{
+	u32 val;
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+	}
+	else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	}
+	else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+		out_be32(&intr->ctrl, val);
+	}
+	else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+		out_be32(&intr->main_mask, val);
+	}
+	else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+		out_be32(&sdma->IntMask, val);
+	}
+	else {
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void
+mpc52xx_ic_enable(unsigned int irq)
+{
+	u32 val;
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+	}
+	else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	}
+	else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+		out_be32(&intr->ctrl, val);
+	}
+	else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+		out_be32(&intr->main_mask, val);
+	}
+	else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		out_be32(&sdma->IntMask, val);
+	}
+	else {
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void
+mpc52xx_ic_ack(unsigned int irq)
+{
+	u32 val;
+
+	/*
+	 * Only some irqs are reset here, others in interrupting hardware.
+	 */
+			
+	switch (irq) {
+	case MPC52xx_IRQ0:
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_CCS_IRQ:
+		val = in_be32(&intr->enc_status);
+		val |= 0x00000400;
+		out_be32(&intr->enc_status, val);
+		break;
+	case MPC52xx_IRQ1:
+		val = in_be32(&intr->ctrl);
+		val |= 0x04000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ2:
+		val = in_be32(&intr->ctrl);
+		val |= 0x02000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ3:
+		val = in_be32(&intr->ctrl);
+		val |= 0x01000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	default:
+		if (irq >= MPC52xx_SDMA_IRQ_BASE
+		    && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+			out_be32(&sdma->IntPend,
+				 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		}
+		break;
+	}
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+	mpc52xx_ic_disable(irq);
+	mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		mpc52xx_ic_enable(irq);
+}
+
+static struct hw_interrupt_type mpc52xx_ic = {
+	"MPC52xx",
+	NULL,				/* startup(irq) */
+	NULL,				/* shutdown(irq) */
+	mpc52xx_ic_enable,		/* enable(irq) */
+	mpc52xx_ic_disable,		/* disable(irq) */
+	mpc52xx_ic_disable_and_ack,	/* disable_and_ack(irq) */
+	mpc52xx_ic_end,			/* end(irq) */
+	0				/* set_affinity(irq, cpumask) SMP. */
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+
+	/* Remap the necessary zones */
+	intr = (struct mpc52xx_intr *)
+		ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
+	sdma = (struct mpc52xx_sdma *)
+		ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
+	
+	if ((intr==NULL) || (sdma==NULL))
+		panic("Can't ioremap PIC/SDMA register for init_irq !");
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	out_be32(&intr->ctrl,
+			0x0f000000 |	/* clear IRQ 0-3 */
+			0x00c00000 |	/* IRQ0: level-sensitive, active low */
+			0x00001000 |	/* MEE master external enable */
+			0x00000000 |	/* 0 means disable IRQ 0-3 */
+			0x00000001);	/* CEb route critical normally */
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+
+	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].handler = &mpc52xx_ic;
+		irq_desc[i].status = IRQ_LEVEL;
+	}
+}
+
+int
+mpc52xx_get_irq(struct pt_regs *regs)
+{
+	u32 status;
+	int irq = -1;
+
+	status = in_be32(&intr->enc_status);
+
+	if (status & 0x00000400) {		/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)			/* high priority peripheral */
+			goto peripheral;
+		irq += MPC52xx_CRIT_IRQ_BASE;
+	}
+	else if (status & 0x00200000) {		/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)			/* low priority peripheral */
+			goto peripheral;
+		irq += MPC52xx_MAIN_IRQ_BASE;
+	}
+	else if (status & 0x20000000) {		/* peripheral */
+peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {			/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+		}
+		else
+			irq += MPC52xx_PERP_IRQ_BASE;
+	}
+
+	return irq;
+}
+
diff -Nru a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/mpc52xx_setup.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,228 @@
+/*
+ * arch/ppc/syslib/mpc52xx_common.c
+ *
+ * Common code for the boards based on Freescale MPC52xx embedded CPU.
+ *
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Support for other bootloaders than UBoot by Dale Farnsworth 
+ * <dfarnsworth@mvista.com>
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ * 
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+
+#include <asm/time.h>
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+#include <asm/ocp.h>
+#include <asm/ppcboot.h>
+
+extern bd_t __res;
+
+static int cpu_52xx[] = {
+	0,  0,  0,  10, 20, 20, 25, 45,
+	30, 55, 40, 50, 0,  60, 35, 0,
+	30, 25, 65, 10, 70, 20, 75, 45,
+	0,  55, 40, 50, 80, 60, 35, 0
+};
+
+void
+mpc52xx_restart(char *cmd)
+{
+	struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
+	
+	local_irq_disable();
+	
+	/* Turn on the watchdog and wait for it to expire. It effectively
+	  does a reset */
+	if (gpt0 != NULL) {
+		out_be32(&gpt0->count, 0x000000ff);
+		out_be32(&gpt0->mode, 0x00009004);
+	} else
+		printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
+
+	while (1);
+}
+
+void
+mpc52xx_halt(void)
+{
+	local_irq_disable();
+
+	while (1);
+}
+
+void
+mpc52xx_power_off(void)
+{
+	/* By default we don't have any way of shut down.
+	   If a specific board wants to, it can set the power down
+	   code to any hardware implementation dependent code */
+	mpc52xx_halt();
+}
+
+
+void __init
+mpc52xx_set_bat(void)
+{
+	/* Set BAT 2 to map the 0xf0000000 area */
+	/* This mapping is used during mpc52xx_progress,
+	 * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
+	 */
+	mb();
+	mtspr(DBAT2U, 0xf0001ffe);
+	mtspr(DBAT2L, 0xf000002a);
+	mb();
+}
+
+void __init
+mpc52xx_map_io(void)
+{
+	/* Here we only map the MBAR */
+	io_block_mapping(
+		MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO);
+}
+
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#ifdef MPC52xx_PF_CONSOLE_PORT
+#define MPC52xx_CONSOLE MPC52xx_PSCx(MPC52xx_PF_CONSOLE_PORT)
+#else
+#error "mpc52xx PSC for console not selected"
+#endif
+
+void
+mpc52xx_progress(char *s, unsigned short hex)
+{
+	struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
+	char c;
+
+		/* Don't we need to disable serial interrupts ? */
+	
+	while ((c = *s++) != 0) {
+		if (c == '\n') {
+			while (!(in_be16(&psc->mpc52xx_psc_status) &
+			         MPC52xx_PSC_SR_TXRDY)) ;
+			out_8(&psc->mpc52xx_psc_buffer_8, '\r');
+		}
+		while (!(in_be16(&psc->mpc52xx_psc_status) &
+		         MPC52xx_PSC_SR_TXRDY)) ;
+		out_8(&psc->mpc52xx_psc_buffer_8, c);
+	}
+}
+
+#endif  /* CONFIG_SERIAL_TEXT_DEBUG */
+
+
+unsigned long __init
+mpc52xx_find_end_of_memory(void)
+{
+	u32 ramsize = __res.bi_memsize;
+
+	/*
+	 * if bootloader passed a memsize, just use it
+	 * else get size from sdram config registers
+	 */
+	if (ramsize == 0) {
+		struct mpc52xx_mmap_ctl *mmap_ctl;
+		u32 sdram_config_0, sdram_config_1;
+
+		/* Temp BAT2 mapping active when this is called ! */
+		mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
+			
+		sdram_config_0 = in_be32(&mmap_ctl->sdram0);
+		sdram_config_1 = in_be32(&mmap_ctl->sdram1);
+
+		if ((sdram_config_0 & 0x1f) >= 0x13)
+			ramsize = 1 << ((sdram_config_0 & 0xf) + 17);
+
+		if (((sdram_config_1 & 0x1f) >= 0x13) &&
+				((sdram_config_1 & 0xfff00000) == ramsize))
+			ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
+
+		iounmap(mmap_ctl);
+	}
+	
+	return ramsize;
+}
+
+void __init
+mpc52xx_calibrate_decr(void)
+{
+	int current_time, previous_time;
+	int tbl_start, tbl_end;
+	unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
+
+	xlbfreq = __res.bi_busfreq;
+	/* if bootloader didn't pass bus frequencies, calculate them */
+	if (xlbfreq == 0) {
+		/* Get RTC & Clock manager modules */
+		struct mpc52xx_rtc *rtc;
+		struct mpc52xx_cdm *cdm;
+		
+		rtc = (struct mpc52xx_rtc*)
+			ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
+		cdm = (struct mpc52xx_cdm*)
+			ioremap(MPC52xx_CDM, sizeof(struct mpc52xx_cdm));
+
+		if ((rtc==NULL) || (cdm==NULL))
+			panic("Can't ioremap RTC/CDM while computing bus freq");
+
+		/* Count bus clock during 1/64 sec */
+		out_be32(&rtc->dividers, 0x8f1f0000);	/* Set RTC 64x faster */
+		previous_time = in_be32(&rtc->time);
+		while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+		tbl_start = get_tbl();
+		previous_time = current_time;
+		while ((current_time = in_be32(&rtc->time)) == previous_time) ;
+		tbl_end = get_tbl();
+		out_be32(&rtc->dividers, 0xffff0000);	/* Restore RTC */
+
+		/* Compute all frequency from that & CDM settings */
+		xlbfreq = (tbl_end - tbl_start) << 8;
+		cpufreq = (xlbfreq * cpu_52xx[in_be32(&cdm->rstcfg) & 0x1f])/10;
+		ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
+					xlbfreq / 2 : xlbfreq;
+		switch (in_8(&cdm->pci_clk_sel) & 3) {
+		case 0:
+			pcifreq = ipbfreq;
+			break;
+		case 1:
+			pcifreq = ipbfreq / 2;
+			break;
+		default:
+			pcifreq = xlbfreq / 4;
+			break;
+		}
+		__res.bi_busfreq = xlbfreq;
+		__res.bi_intfreq = cpufreq;
+		__res.bi_ipbfreq = ipbfreq;
+		__res.bi_pcifreq = pcifreq;
+	
+		/* Release mapping */
+		iounmap((void*)rtc);
+		iounmap((void*)cdm);
+	}
+
+	divisor = 4;
+
+	tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
+}
+
+
+void __init
+mpc52xx_add_board_devices(struct ocp_def board_ocp[]) {
+	while (board_ocp->vendor != OCP_VENDOR_INVALID)
+		if(ocp_add_one_device(board_ocp++))
+			printk("mpc5200-ocp: Failed to add board device !\n");
+}
+
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	2004-07-13 12:45:03 -07:00
+++ b/drivers/serial/Kconfig	2004-07-13 12:45:03 -07:00
@@ -677,5 +677,32 @@
 	help
 	  Select the is option to use SMC2 as a serial port
 
+config SERIAL_MPC52xx
+	tristate "Freescale MPC52xx family PSC serial support"
+	depends on PPC_MPC52xx
+	select SERIAL_CORE
+	help
+	  This drivers support the MPC52xx PSC serial ports. If you would
+	  like to use them, you must answer Y or M to this option. Not that
+	  for use as console, it must be included in kernel and not as a
+	  module.
+
+config SERIAL_MPC52xx_CONSOLE
+	bool "Console on a Freescale MPC52xx family PSC serial port"
+	depends on SERIAL_MPC52xx=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Select this options if you'd like to use one of the PSC serial port
+	  of the Freescale MPC52xx family as a console.
+
+config SERIAL_MPC52xx_CONSOLE_BAUD
+	int "Freescale MPC52xx family PSC serial port baud"
+	depends on SERIAL_MPC52xx_CONSOLE=y
+	default "9600"
+	help
+	  Select the MPC52xx console baud rate.
+	  This value is only used if the bootloader doesn't pass in the
+	  console baudrate
+
 endmenu
 
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	2004-07-13 12:45:03 -07:00
+++ b/drivers/serial/Makefile	2004-07-13 12:45:03 -07:00
@@ -39,3 +39,4 @@
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
 obj-$(CONFIG_SERIAL_BAST_SIO) += bast_sio.o
 obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
+obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
diff -Nru a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/mpc52xx_uart.c	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,869 @@
+/*
+ * drivers/serial/mpc52xx_uart.c
+ *
+ * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
+ *
+ * FIXME According to the usermanual the status bits in the status register
+ * are only updated when the peripherals access the FIFO and not when the
+ * CPU access them. So since we use this bits to know when we stop writing
+ * and reading, they may not be updated in-time and a race condition may
+ * exists. But I haven't be able to prove this and I don't care. But if
+ * any problem arises, it might worth checking. The TX/RX FIFO Stats
+ * registers should be used in addition.
+ * Update: Actually, they seem updated ... At least the bits we use.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ * 
+ * Some of the code has been inspired/copied from the 2.4 code written
+ * by Dale Farnsworth <dfarnsworth@mvista.com>.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ * 
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+ 
+/* OCP Usage :
+ *
+ * This drivers uses the OCP model. To load the serial driver for one of the
+ * PSCs, just add this to the core_ocp table :
+ *
+ * {
+ * 	.vendor         = OCP_VENDOR_FREESCALE,
+ * 	.function       = OCP_FUNC_PSC_UART,
+ * 	.index          = 0,
+ * 	.paddr          = MPC52xx_PSC1,
+ * 	.irq            = MPC52xx_PSC1_IRQ,
+ * 	.pm             = OCP_CPM_NA,
+ * },
+ *
+ * This is for PSC1, replace the paddr and irq according to the PSC you want to
+ * use. The driver all necessary registers to place the PSC in uart mode without
+ * DCD. However, the pin multiplexing aren't changed and should be set either
+ * by the bootloader or in the platform init code.
+ * The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
+ * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
+ * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
+ * the console code : without this 1:1 mapping, at early boot time, when we are
+ * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
+ * mapped to because OCP stuff is not yet initialized.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/sysrq.h>
+#include <linux/console.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+
+#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+
+
+#define ISR_PASS_LIMIT 256	/* Max number of iteration in the interrupt */
+
+
+static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
+	/* Rem: - We use the read_status_mask as a shadow of
+	 *        psc->mpc52xx_psc_imr
+	 *      - It's important that is array is all zero on start as we
+	 *        use it to know if it's initialized or not ! If it's not sure
+	 *        it's cleared, then a memset(...,0,...) should be added to
+	 *        the console_init
+	 */
+
+#define PSC(port) ((struct mpc52xx_psc *)((port)->membase))
+
+
+/* Forward declaration of the interruption handling routine */
+static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id,struct pt_regs *regs);
+
+
+/* Simple macro to test if a port is console or not. This one is taken
+ * for serial_core.c and maybe should be moved to serial_core.h ? */
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+#define uart_console(port)	((port)->cons && (port)->cons->index == (port)->line)
+#else
+#define uart_console(port)	(0)
+#endif
+
+
+/* ======================================================================== */
+/* UART operations                                                          */
+/* ======================================================================== */
+
+static unsigned int 
+mpc52xx_uart_tx_empty(struct uart_port *port)
+{
+	int status = in_be16(&PSC(port)->mpc52xx_psc_status);
+	return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
+}
+
+static void 
+mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* Not implemented */
+}
+
+static unsigned int 
+mpc52xx_uart_get_mctrl(struct uart_port *port)
+{
+	/* Not implemented */
+	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void 
+mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	/* port->lock taken by caller */
+	port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
+	out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
+}
+
+static void 
+mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	/* port->lock taken by caller */
+	port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
+	out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
+}
+
+static void 
+mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&port->lock, flags);
+	
+	port->x_char = ch;
+	if (ch) {
+		/* Make sure tx interrupts are on */
+		/* Truly necessary ??? They should be anyway */
+		port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
+		out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
+	}
+	
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void
+mpc52xx_uart_stop_rx(struct uart_port *port)
+{
+	/* port->lock taken by caller */
+	port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
+	out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
+}
+
+static void
+mpc52xx_uart_enable_ms(struct uart_port *port)
+{
+	/* Not implemented */
+}
+
+static void
+mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&port->lock, flags);
+
+	if ( ctl == -1 )
+		out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK);
+	else
+		out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK);
+	
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int
+mpc52xx_uart_startup(struct uart_port *port)
+{
+	struct mpc52xx_psc *psc = PSC(port);
+
+	/* Reset/activate the port, clear and enable interrupts */
+	out_8(&psc->command,MPC52xx_PSC_RST_RX);
+	out_8(&psc->command,MPC52xx_PSC_RST_TX);
+	
+	out_be32(&psc->sicr,0);	/* UART mode DCD ignored */
+
+	out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */
+	
+	out_8(&psc->rfcntl, 0x00);
+	out_be16(&psc->rfalarm, 0x1ff);
+	out_8(&psc->tfcntl, 0x07);
+	out_be16(&psc->tfalarm, 0x80);
+
+	port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
+	out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
+	
+	out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
+	out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
+		
+	return 0;
+}
+
+static void
+mpc52xx_uart_shutdown(struct uart_port *port)
+{
+	struct mpc52xx_psc *psc = PSC(port);
+	
+	/* Shut down the port, interrupt and all */
+	out_8(&psc->command,MPC52xx_PSC_RST_RX);
+	out_8(&psc->command,MPC52xx_PSC_RST_TX);
+	
+	port->read_status_mask = 0; 
+	out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
+}
+
+static void 
+mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
+                         struct termios *old)
+{
+	struct mpc52xx_psc *psc = PSC(port);
+	unsigned long flags;
+	unsigned char mr1, mr2;
+	unsigned short ctr;
+	unsigned int j, baud, quot;
+	
+	/* Prepare what we're gonna write */
+	mr1 = 0;
+	
+	switch (new->c_cflag & CSIZE) {
+		case CS5:	mr1 |= MPC52xx_PSC_MODE_5_BITS;
+				break;
+		case CS6:	mr1 |= MPC52xx_PSC_MODE_6_BITS;
+				break;
+		case CS7:	mr1 |= MPC52xx_PSC_MODE_7_BITS;
+				break;
+		case CS8:
+		default:	mr1 |= MPC52xx_PSC_MODE_8_BITS;
+	}
+
+	if (new->c_cflag & PARENB) {
+		mr1 |= (new->c_cflag & PARODD) ?
+			MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
+	} else
+		mr1 |= MPC52xx_PSC_MODE_PARNONE;
+	
+	
+	mr2 = 0;
+
+	if (new->c_cflag & CSTOPB)
+		mr2 |= MPC52xx_PSC_MODE_TWO_STOP;
+	else
+		mr2 |= ((new->c_cflag & CSIZE) == CS5) ?
+			MPC52xx_PSC_MODE_ONE_STOP_5_BITS :
+			MPC52xx_PSC_MODE_ONE_STOP;
+
+
+	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+	ctr = quot & 0xffff;
+	
+	/* Get the lock */
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Update the per-port timeout */
+	uart_update_timeout(port, new->c_cflag, baud);
+
+	/* Do our best to flush TX & RX, so we don't loose anything */
+	/* But we don't wait indefinitly ! */
+	j = 5000000;	/* Maximum wait */
+	/* FIXME Can't receive chars since set_termios might be called at early
+	 * boot for the console, all stuff is not yet ready to receive at that
+	 * time and that just makes the kernel oops */
+	/* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
+	while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && 
+	       --j)
+		udelay(1);
+
+	if (!j)
+		printk(	KERN_ERR "mpc52xx_uart.c: "
+			"Unable to flush RX & TX fifos in-time in set_termios."
+			"Some chars may have been lost.\n" ); 
+
+	/* Reset the TX & RX */
+	out_8(&psc->command,MPC52xx_PSC_RST_RX);
+	out_8(&psc->command,MPC52xx_PSC_RST_TX);
+
+	/* Send new mode settings */
+	out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);
+	out_8(&psc->mode,mr1);
+	out_8(&psc->mode,mr2);
+	out_8(&psc->ctur,ctr >> 8);
+	out_8(&psc->ctlr,ctr & 0xff);
+	
+	/* Reenable TX & RX */
+	out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
+	out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
+
+	/* We're all set, release the lock */
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *
+mpc52xx_uart_type(struct uart_port *port)
+{
+	return port->type == PORT_MPC52xx ? "MPC52xx PSC" : NULL;
+}
+
+static void
+mpc52xx_uart_release_port(struct uart_port *port)
+{
+	if (port->flags & UPF_IOREMAP) { /* remapped by us ? */
+		iounmap(port->membase);
+		port->membase = NULL;
+	}
+}
+
+static int
+mpc52xx_uart_request_port(struct uart_port *port)
+{
+	if (port->flags & UPF_IOREMAP) /* Need to remap ? */
+		port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
+	
+	return port->membase != NULL ? 0 : -EBUSY;
+}
+
+static void
+mpc52xx_uart_config_port(struct uart_port *port, int flags)
+{
+	if ( (flags & UART_CONFIG_TYPE) &&
+	     (mpc52xx_uart_request_port(port) == 0) )
+	     	port->type = PORT_MPC52xx;
+}
+
+static int
+mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if ( ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx )
+		return -EINVAL;
+
+	if ( (ser->irq != port->irq) ||
+	     (ser->io_type != SERIAL_IO_MEM) ||
+	     (ser->baud_base != port->uartclk)  || 
+	     // FIXME Should check addresses/irq as well ?
+	     (ser->hub6 != 0 ) )
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static struct uart_ops mpc52xx_uart_ops = {
+	.tx_empty	= mpc52xx_uart_tx_empty,
+	.set_mctrl	= mpc52xx_uart_set_mctrl,
+	.get_mctrl	= mpc52xx_uart_get_mctrl,
+	.stop_tx	= mpc52xx_uart_stop_tx,
+	.start_tx	= mpc52xx_uart_start_tx,
+	.send_xchar	= mpc52xx_uart_send_xchar,
+	.stop_rx	= mpc52xx_uart_stop_rx,
+	.enable_ms	= mpc52xx_uart_enable_ms,
+	.break_ctl	= mpc52xx_uart_break_ctl,
+	.startup	= mpc52xx_uart_startup,
+	.shutdown	= mpc52xx_uart_shutdown,
+	.set_termios	= mpc52xx_uart_set_termios,
+/*	.pm		= mpc52xx_uart_pm,		Not supported yet */
+/*	.set_wake	= mpc52xx_uart_set_wake,	Not supported yet */
+	.type		= mpc52xx_uart_type,
+	.release_port	= mpc52xx_uart_release_port,
+	.request_port	= mpc52xx_uart_request_port,
+	.config_port	= mpc52xx_uart_config_port,
+	.verify_port	= mpc52xx_uart_verify_port
+};
+
+	
+/* ======================================================================== */
+/* Interrupt handling                                                       */
+/* ======================================================================== */
+	
+static inline int
+mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
+{
+	struct tty_struct *tty = port->info->tty;
+	unsigned char ch;
+	unsigned short status;
+
+	/* While we can read, do so ! */
+	while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
+	        MPC52xx_PSC_SR_RXRDY) {
+
+		/* If we are full, just stop reading */
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			break;
+		
+		/* Get the char */
+		ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
+
+		/* Handle sysreq char */
+#ifdef SUPPORT_SYSRQ
+		if (uart_handle_sysrq_char(port, ch, regs)) {
+			port->sysrq = 0;
+			continue;
+		}
+#endif
+
+		/* Store it */
+		*tty->flip.char_buf_ptr = ch;
+		*tty->flip.flag_buf_ptr = 0;
+		port->icount.rx++;
+	
+		if ( status & (MPC52xx_PSC_SR_PE |
+		               MPC52xx_PSC_SR_FE |
+		               MPC52xx_PSC_SR_RB |
+		               MPC52xx_PSC_SR_OE) ) {
+			
+			if (status & MPC52xx_PSC_SR_RB) {
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				uart_handle_break(port);
+			} else if (status & MPC52xx_PSC_SR_PE)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (status & MPC52xx_PSC_SR_FE)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+			if (status & MPC52xx_PSC_SR_OE) {
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
+					tty->flip.flag_buf_ptr++;
+					tty->flip.char_buf_ptr++;
+					tty->flip.count++;
+				}
+				*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			}
+
+			/* Clear error condition */
+			out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
+
+		}
+
+		tty->flip.char_buf_ptr++;
+		tty->flip.flag_buf_ptr++;
+		tty->flip.count++;
+
+	}
+
+	tty_flip_buffer_push(tty);
+	
+	return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;
+}
+
+static inline int
+mpc52xx_uart_int_tx_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+
+	/* Process out of band chars */
+	if (port->x_char) {
+		out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		return 1;
+	}
+
+	/* Nothing to do ? */
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		mpc52xx_uart_stop_tx(port,0);
+		return 0;
+	}
+
+	/* Send chars */
+	while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) {
+		out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	}
+
+	/* Wake up */
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	/* Maybe we're done after all */
+	if (uart_circ_empty(xmit)) {
+		mpc52xx_uart_stop_tx(port,0);
+		return 0;
+	}
+
+	return 1;
+}
+
+static irqreturn_t 
+mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = (struct uart_port *) dev_id;
+	unsigned long pass = ISR_PASS_LIMIT;
+	unsigned int keepgoing;
+	unsigned short status;
+	
+	if ( irq != port->irq ) {
+		printk( KERN_WARNING
+		        "mpc52xx_uart_int : " \
+		        "Received wrong int %d. Waiting for %d\n",
+		       irq, port->irq);
+		return IRQ_NONE;
+	}
+	
+	spin_lock(&port->lock);
+	
+	/* While we have stuff to do, we continue */
+	do {
+		/* If we don't find anything to do, we stop */
+		keepgoing = 0; 
+		
+		/* Read status */
+		status = in_be16(&PSC(port)->mpc52xx_psc_isr);
+		status &= port->read_status_mask;
+			
+		/* Do we need to receive chars ? */
+		/* For this RX interrupts must be on and some chars waiting */
+		if ( status & MPC52xx_PSC_IMR_RXRDY )
+			keepgoing |= mpc52xx_uart_int_rx_chars(port, regs);
+
+		/* Do we need to send chars ? */
+		/* For this, TX must be ready and TX interrupt enabled */
+		if ( status & MPC52xx_PSC_IMR_TXRDY )
+			keepgoing |= mpc52xx_uart_int_tx_chars(port);
+		
+		/* Limit number of iteration */
+		if ( !(--pass) )
+			keepgoing = 0;
+
+	} while (keepgoing);
+	
+	spin_unlock(&port->lock);
+	
+	return IRQ_HANDLED;
+}
+
+
+/* ======================================================================== */
+/* Console ( if applicable )                                                */
+/* ======================================================================== */
+
+#ifdef CONFIG_SERIAL_MPC52xx_CONSOLE
+
+static void __init
+mpc52xx_console_get_options(struct uart_port *port,
+                            int *baud, int *parity, int *bits, int *flow)
+{
+	struct mpc52xx_psc *psc = PSC(port);
+	unsigned char mr1;
+
+	/* Read the mode registers */
+	out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);
+	mr1 = in_8(&psc->mode);
+	
+	/* CT{U,L}R are write-only ! */
+	*baud = __res.bi_baudrate ?
+		__res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
+
+	/* Parse them */
+	switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
+		case MPC52xx_PSC_MODE_5_BITS:	*bits = 5; break;
+		case MPC52xx_PSC_MODE_6_BITS:	*bits = 6; break;
+		case MPC52xx_PSC_MODE_7_BITS:	*bits = 7; break;
+		case MPC52xx_PSC_MODE_8_BITS:
+		default:			*bits = 8;
+	}
+	
+	if (mr1 & MPC52xx_PSC_MODE_PARNONE)
+		*parity = 'n';
+	else
+		*parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';
+}
+
+static void  
+mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *port = &mpc52xx_uart_ports[co->index];
+	struct mpc52xx_psc *psc = PSC(port);
+	unsigned int i, j;
+	
+	/* Disable interrupts */
+	out_be16(&psc->mpc52xx_psc_imr, 0);
+
+	/* Wait the TX buffer to be empty */
+	j = 5000000;	/* Maximum wait */	
+	while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && 
+	       --j)
+		udelay(1);
+
+	/* Write all the chars */
+	for ( i=0 ; i<count ; i++ ) {
+	
+		/* Send the char */
+		out_8(&psc->mpc52xx_psc_buffer_8, *s);
+
+		/* Line return handling */
+		if ( *s++ == '\n' )
+			out_8(&psc->mpc52xx_psc_buffer_8, '\r');
+		
+		/* Wait the TX buffer to be empty */
+		j = 20000;	/* Maximum wait */	
+		while (!(in_be16(&psc->mpc52xx_psc_status) & 
+		         MPC52xx_PSC_SR_TXEMP) && --j)
+			udelay(1);
+	}
+
+	/* Restore interrupt state */
+	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
+}
+
+static int __init
+mpc52xx_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port = &mpc52xx_uart_ports[co->index];
+
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
+		return -EINVAL;
+	
+	/* Basic port init. Needed since we use some uart_??? func before
+	 * real init for early access */
+	port->lock	= SPIN_LOCK_UNLOCKED;
+	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */
+	port->ops	= &mpc52xx_uart_ops;
+	port->mapbase	= MPC52xx_PSCx(co->index);
+
+		/* We ioremap ourself */
+	port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
+	if (port->membase == NULL) {
+		release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+		return -EBUSY;
+	}
+
+	/* Setup the port parameters accoding to options */
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+
+extern struct uart_driver mpc52xx_uart_driver;
+
+static struct console mpc52xx_console = {
+	.name	= "ttyS",
+	.write	= mpc52xx_console_write,
+	.device	= uart_console_device,
+	.setup	= mpc52xx_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,	/* Specified on the cmdline (e.g. console=ttyS0 ) */
+	.data	= &mpc52xx_uart_driver,
+};
+
+	
+static int __init 
+mpc52xx_console_init(void)
+{
+	register_console(&mpc52xx_console);
+	return 0;
+}
+
+console_initcall(mpc52xx_console_init);
+
+#define MPC52xx_PSC_CONSOLE &mpc52xx_console
+#else
+#define MPC52xx_PSC_CONSOLE NULL
+#endif
+
+
+/* ======================================================================== */
+/* UART Driver                                                              */
+/* ======================================================================== */
+
+static struct uart_driver mpc52xx_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "mpc52xx_psc_uart",
+	.dev_name	= "ttyS",
+	.devfs_name	= "ttyS",
+	.major		= TTY_MAJOR,
+	.minor		= 64,
+	.nr		= MPC52xx_PSC_MAXNUM,
+	.cons		= MPC52xx_PSC_CONSOLE,
+};
+
+
+/* ======================================================================== */
+/* OCP Driver                                                               */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_uart_probe(struct ocp_device *ocp)
+{
+	struct uart_port *port = NULL;
+	int idx, ret;
+
+	/* Get the corresponding port struct */
+	idx = ocp->def->index;
+	if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
+		return -EINVAL;
+	
+	port = &mpc52xx_uart_ports[idx];
+
+	/* Init the port structure */
+	port->lock	= SPIN_LOCK_UNLOCKED;
+	port->mapbase	= ocp->def->paddr;
+	port->irq	= ocp->def->irq;
+	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */
+	port->fifosize	= 255; /* Should be 512 ! But it can't be */
+	                       /* stored in a unsigned char       */
+	port->iotype	= UPIO_MEM;
+	port->flags	= UPF_BOOT_AUTOCONF |
+			  ( uart_console(port) ? 0 : UPF_IOREMAP );
+	port->line	= idx;
+	port->ops	= &mpc52xx_uart_ops;
+	port->read_status_mask = 0;
+	
+	/* Requests the mem & irqs */
+	/* Unlike other serial drivers, we reserve the resources here, so we
+	 * can detect early if multiple drivers uses the same PSC. Special
+	 * care must be taken with the console PSC
+	 */
+	ret = request_irq(
+		port->irq, mpc52xx_uart_int,
+		SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
+	if (ret)
+		goto error;
+
+	ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
+	                         "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
+	if (ret)
+		goto free_irq;
+
+	/* Add the port to the uart sub-system */
+	ret = uart_add_one_port(&mpc52xx_uart_driver, port);
+	if (ret)
+		goto release_mem;
+
+	ocp_set_drvdata(ocp, (void*)port);
+
+	return 0;
+
+
+free_irq:
+	free_irq(port->irq, mpc52xx_uart_int);
+
+release_mem:
+	release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+
+error:
+	if (uart_console(port))
+		printk(	"mpc52xx_uart.c: Error during resource alloction for "
+			"the console port !!! Check that the console PSC is "
+			"not used by another OCP driver !!!\n" );
+
+	return ret;
+}
+
+static void
+mpc52xx_uart_remove(struct ocp_device *ocp)
+{
+	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+
+	ocp_set_drvdata(ocp, NULL);
+
+	if (port) {
+		uart_remove_one_port(&mpc52xx_uart_driver, port);
+		release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
+		free_irq(port->irq, mpc52xx_uart_int);
+	}
+}
+
+#ifdef CONFIG_PM
+static int
+mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state)
+{
+	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+
+	uart_suspend_port(&mpc52xx_uart_driver, port);
+
+	return 0;
+}
+
+static int
+mpc52xx_uart_resume(struct ocp_device *ocp)
+{
+	struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+
+	uart_resume_port(&mpc52xx_uart_driver, port);
+
+	return 0;
+}
+#endif
+
+static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {
+	{ .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },
+	{ .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }
+};
+
+MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);
+
+static struct ocp_driver mpc52xx_uart_ocp_driver = {
+	.name		= "mpc52xx_psc_uart",
+	.id_table	= mpc52xx_uart_ids,
+	.probe		= mpc52xx_uart_probe,
+	.remove		= mpc52xx_uart_remove,
+#ifdef CONFIG_PM
+	.suspend	= mpc52xx_uart_suspend,
+	.resume		= mpc52xx_uart_resume,
+#endif
+};
+
+
+/* ======================================================================== */
+/* Module                                                                   */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_uart_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
+
+	ret = uart_register_driver(&mpc52xx_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);
+
+	return ret;
+}
+
+static void __exit
+mpc52xx_uart_exit(void)
+{
+	ocp_unregister_driver(&mpc52xx_uart_ocp_driver);
+	uart_unregister_driver(&mpc52xx_uart_driver);
+}
+
+
+module_init(mpc52xx_uart_init);
+module_exit(mpc52xx_uart_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");
+MODULE_LICENSE("GPL");
diff -Nru a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/mpc52xx.h	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,380 @@
+/*
+ * include/asm-ppc/mpc52xx.h
+ * 
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> 
+ * for the 2.4 kernel.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_MPC52xx_H__
+#define __ASM_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/ppcboot.h>
+#include <asm/types.h>
+
+struct pt_regs;
+struct ocp_def;
+#endif /* __ASSEMBLY__ */
+
+
+/* ======================================================================== */
+/* Main registers/struct addresses                                          */
+/* ======================================================================== */
+/* Theses are PHYSICAL addresses !                                          */
+/* TODO : There should be no static mapping, but it's not yet the case, so  */
+/*        we require a 1:1 mapping                                          */
+
+#define MPC52xx_MBAR		0xf0000000	/* Phys address */
+#define MPC52xx_MBAR_SIZE	0x00010000
+#define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
+
+#define MPC52xx_MMAP_CTL	(MPC52xx_MBAR + 0x0000)
+#define MPC52xx_CDM		(MPC52xx_MBAR + 0x0200)
+#define MPC52xx_SFTRST		(MPC52xx_MBAR + 0x0220)
+#define MPC52xx_SFTRST_BIT	0x01000000
+#define MPC52xx_INTR		(MPC52xx_MBAR + 0x0500)
+#define MPC52xx_GPTx(x)		(MPC52xx_MBAR + 0x0600 + ((x)<<4))
+#define MPC52xx_RTC		(MPC52xx_MBAR + 0x0800)
+#define MPC52xx_MSCAN1		(MPC52xx_MBAR + 0x0900)
+#define MPC52xx_MSCAN2		(MPC52xx_MBAR + 0x0980)
+#define MPC52xx_GPIO		(MPC52xx_MBAR + 0x0b00)
+#define MPC52xx_PCI		(MPC52xx_MBAR + 0x0d00)
+#define MPC52xx_USB_OHCI	(MPC52xx_MBAR + 0x1000)
+#define MPC52xx_SDMA		(MPC52xx_MBAR + 0x1200)
+#define MPC52xx_XLB		(MPC52xx_MBAR + 0x1f00)
+#define MPC52xx_PSCx(x)		(MPC52xx_MBAR + 0x2000 + ((x)<<9))
+#define MPC52xx_PSC1		(MPC52xx_MBAR + 0x2000)
+#define MPC52xx_PSC2		(MPC52xx_MBAR + 0x2200)
+#define MPC52xx_PSC3		(MPC52xx_MBAR + 0x2400)
+#define MPC52xx_PSC4		(MPC52xx_MBAR + 0x2600)
+#define MPC52xx_PSC5		(MPC52xx_MBAR + 0x2800)
+#define MPC52xx_PSC6		(MPC52xx_MBAR + 0x2C00)
+#define MPC52xx_FEC		(MPC52xx_MBAR + 0x3000)
+#define MPC52xx_ATA		(MPC52xx_MBAR + 0x3a00)
+#define MPC52xx_I2C1		(MPC52xx_MBAR + 0x3d00)
+#define MPC52xx_I2C_MICR	(MPC52xx_MBAR + 0x3d20)
+#define MPC52xx_I2C2		(MPC52xx_MBAR + 0x3d40)
+
+/* SRAM used for SDMA */
+#define MPC52xx_SRAM		(MPC52xx_MBAR + 0x8000)
+#define MPC52xx_SRAM_SIZE	(16*1024)
+#define MPC52xx_SDMA_MAX_TASKS	16
+
+	/* Memory allocation block size */
+#define MPC52xx_SDRAM_UNIT	0x8000		/* 32K byte */
+
+
+/* ======================================================================== */
+/* IRQ mapping                                                              */
+/* ======================================================================== */
+/* Be sure to look at mpc52xx_pic.h if you wish for whatever reason to change
+ * this
+ */
+
+#define MPC52xx_CRIT_IRQ_NUM	4
+#define MPC52xx_MAIN_IRQ_NUM	17
+#define MPC52xx_SDMA_IRQ_NUM	17
+#define MPC52xx_PERP_IRQ_NUM	23
+
+#define MPC52xx_CRIT_IRQ_BASE	0
+#define MPC52xx_MAIN_IRQ_BASE	(MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
+#define MPC52xx_SDMA_IRQ_BASE	(MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
+#define MPC52xx_PERP_IRQ_BASE	(MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
+
+#define MPC52xx_IRQ0			(MPC52xx_CRIT_IRQ_BASE + 0)
+#define MPC52xx_SLICE_TIMER_0_IRQ	(MPC52xx_CRIT_IRQ_BASE + 1)
+#define MPC52xx_HI_INT_IRQ		(MPC52xx_CRIT_IRQ_BASE + 2)
+#define MPC52xx_CCS_IRQ			(MPC52xx_CRIT_IRQ_BASE + 3)
+
+#define MPC52xx_IRQ1			(MPC52xx_MAIN_IRQ_BASE + 1)
+#define MPC52xx_IRQ2			(MPC52xx_MAIN_IRQ_BASE + 2)
+#define MPC52xx_IRQ3			(MPC52xx_MAIN_IRQ_BASE + 3)
+
+#define MPC52xx_SDMA_IRQ		(MPC52xx_PERP_IRQ_BASE + 0)
+#define MPC52xx_PSC1_IRQ		(MPC52xx_PERP_IRQ_BASE + 1)
+#define MPC52xx_PSC2_IRQ		(MPC52xx_PERP_IRQ_BASE + 2)
+#define MPC52xx_PSC3_IRQ		(MPC52xx_PERP_IRQ_BASE + 3)
+#define MPC52xx_PSC6_IRQ		(MPC52xx_PERP_IRQ_BASE + 4)
+#define MPC52xx_IRDA_IRQ		(MPC52xx_PERP_IRQ_BASE + 4)
+#define MPC52xx_FEC_IRQ			(MPC52xx_PERP_IRQ_BASE + 5)
+#define MPC52xx_USB_IRQ			(MPC52xx_PERP_IRQ_BASE + 6)
+#define MPC52xx_ATA_IRQ			(MPC52xx_PERP_IRQ_BASE + 7)
+#define MPC52xx_PCI_CNTRL_IRQ		(MPC52xx_PERP_IRQ_BASE + 8)
+#define MPC52xx_PCI_SCIRX_IRQ		(MPC52xx_PERP_IRQ_BASE + 9)
+#define MPC52xx_PCI_SCITX_IRQ		(MPC52xx_PERP_IRQ_BASE + 10)
+#define MPC52xx_PSC4_IRQ		(MPC52xx_PERP_IRQ_BASE + 11)
+#define MPC52xx_PSC5_IRQ		(MPC52xx_PERP_IRQ_BASE + 12)
+#define MPC52xx_SPI_MODF_IRQ		(MPC52xx_PERP_IRQ_BASE + 13)
+#define MPC52xx_SPI_SPIF_IRQ		(MPC52xx_PERP_IRQ_BASE + 14)
+#define MPC52xx_I2C1_IRQ		(MPC52xx_PERP_IRQ_BASE + 15)
+#define MPC52xx_I2C2_IRQ		(MPC52xx_PERP_IRQ_BASE + 16)
+#define MPC52xx_CAN1_IRQ		(MPC52xx_PERP_IRQ_BASE + 17)
+#define MPC52xx_CAN2_IRQ		(MPC52xx_PERP_IRQ_BASE + 18)
+#define MPC52xx_IR_RX_IRQ		(MPC52xx_PERP_IRQ_BASE + 19)
+#define MPC52xx_IR_TX_IRQ		(MPC52xx_PERP_IRQ_BASE + 20)
+#define MPC52xx_XLB_ARB_IRQ		(MPC52xx_PERP_IRQ_BASE + 21)
+
+
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set                             */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+	volatile u32	mbar;		/* MMAP_CTRL + 0x00 */
+
+	volatile u32	cs0_start;	/* MMAP_CTRL + 0x04 */
+	volatile u32	cs0_stop;	/* MMAP_CTRL + 0x08 */
+	volatile u32	cs1_start;	/* MMAP_CTRL + 0x0c */
+	volatile u32	cs1_stop;	/* MMAP_CTRL + 0x10 */
+	volatile u32	cs2_start;	/* MMAP_CTRL + 0x14 */
+	volatile u32	cs2_stop;	/* MMAP_CTRL + 0x18 */
+	volatile u32	cs3_start;	/* MMAP_CTRL + 0x1c */
+	volatile u32	cs3_stop;	/* MMAP_CTRL + 0x20 */
+	volatile u32	cs4_start;	/* MMAP_CTRL + 0x24 */
+	volatile u32	cs4_stop;	/* MMAP_CTRL + 0x28 */
+	volatile u32	cs5_start;	/* MMAP_CTRL + 0x2c */
+	volatile u32	cs5_stop;	/* MMAP_CTRL + 0x30 */
+
+	volatile u32	sdram0;		/* MMAP_CTRL + 0x34 */
+	volatile u32	sdram1;		/* MMAP_CTRL + 0X38 */
+
+	volatile u32	reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	volatile u32	boot_start;	/* MMAP_CTRL + 0x4c */
+	volatile u32	boot_stop;	/* MMAP_CTRL + 0x50 */
+	
+	volatile u32	ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+	
+	volatile u32	cs6_start;	/* MMAP_CTRL + 0x58 */
+	volatile u32	cs6_stop;	/* MMAP_CTRL + 0x5c */
+	volatile u32	cs7_start;	/* MMAP_CTRL + 0x60 */
+	volatile u32	cs7_stop;	/* MMAP_CTRL + 0x60 */
+};
+
+/* Interrupt controller */
+struct mpc52xx_intr {
+	volatile u32	per_mask;	/* INTR + 0x00 */
+	volatile u32	per_pri1;	/* INTR + 0x04 */
+	volatile u32	per_pri2;	/* INTR + 0x08 */
+	volatile u32	per_pri3;	/* INTR + 0x0c */
+	volatile u32	ctrl;		/* INTR + 0x10 */
+	volatile u32	main_mask;	/* INTR + 0x14 */
+	volatile u32	main_pri1;	/* INTR + 0x18 */
+	volatile u32	main_pri2;	/* INTR + 0x1c */
+	volatile u32	reserved1;	/* INTR + 0x20 */
+	volatile u32	enc_status;	/* INTR + 0x24 */
+	volatile u32	crit_status;	/* INTR + 0x28 */
+	volatile u32	main_status;	/* INTR + 0x2c */
+	volatile u32	per_status;	/* INTR + 0x30 */
+	volatile u32	reserved2;	/* INTR + 0x34 */
+	volatile u32	per_error;	/* INTR + 0x38 */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+	volatile u32	taskBar;	/* SDMA + 0x00 */
+	volatile u32	currentPointer;	/* SDMA + 0x04 */
+	volatile u32	endPointer;	/* SDMA + 0x08 */
+	volatile u32	variablePointer;/* SDMA + 0x0c */
+
+	volatile u8	IntVect1;	/* SDMA + 0x10 */
+	volatile u8	IntVect2;	/* SDMA + 0x11 */
+	volatile u16	PtdCntrl;	/* SDMA + 0x12 */
+
+	volatile u32	IntPend;	/* SDMA + 0x14 */
+	volatile u32	IntMask;	/* SDMA + 0x18 */
+	
+	volatile u16	tcr[16];	/* SDMA + 0x1c .. 0x3a */
+
+	volatile u8	ipr[31];	/* SDMA + 0x3c .. 5b */
+
+	volatile u32	res1;		/* SDMA + 0x5c */
+	volatile u32	task_size0;	/* SDMA + 0x60 */
+	volatile u32	task_size1;	/* SDMA + 0x64 */
+	volatile u32	MDEDebug;	/* SDMA + 0x68 */
+	volatile u32	ADSDebug;	/* SDMA + 0x6c */
+	volatile u32	Value1;		/* SDMA + 0x70 */
+	volatile u32	Value2;		/* SDMA + 0x74 */
+	volatile u32	Control;	/* SDMA + 0x78 */
+	volatile u32	Status;		/* SDMA + 0x7c */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+	volatile u32	mode;		/* GPTx + 0x00 */
+	volatile u32	count;		/* GPTx + 0x04 */
+	volatile u32	pwm;		/* GPTx + 0x08 */
+	volatile u32	status;		/* GPTx + 0X0c */
+};
+
+/* RTC */
+struct mpc52xx_rtc {
+	volatile u32	time_set;	/* RTC + 0x00 */
+	volatile u32	date_set;	/* RTC + 0x04 */
+	volatile u32	stopwatch;	/* RTC + 0x08 */
+	volatile u32	int_enable;	/* RTC + 0x0c */
+	volatile u32	time;		/* RTC + 0x10 */
+	volatile u32	date;		/* RTC + 0x14 */
+	volatile u32	stopwatch_intr;	/* RTC + 0x18 */
+	volatile u32	bus_error;	/* RTC + 0x1c */
+	volatile u32	dividers;	/* RTC + 0x20 */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+	volatile u32	port_config;	/* GPIO + 0x00 */
+	volatile u32	simple_gpioe;	/* GPIO + 0x04 */
+	volatile u32	simple_ode;	/* GPIO + 0x08 */
+	volatile u32	simple_ddr;	/* GPIO + 0x0c */
+	volatile u32	simple_dvo;	/* GPIO + 0x10 */
+	volatile u32	simple_ival;	/* GPIO + 0x14 */
+	volatile u8	outo_gpioe;	/* GPIO + 0x18 */
+	volatile u8	reserved1[3];	/* GPIO + 0x19 */
+	volatile u8	outo_dvo;	/* GPIO + 0x1c */
+	volatile u8	reserved2[3];	/* GPIO + 0x1d */
+	volatile u8	sint_gpioe;	/* GPIO + 0x20 */
+	volatile u8	reserved3[3];	/* GPIO + 0x21 */
+	volatile u8	sint_ode;	/* GPIO + 0x24 */
+	volatile u8	reserved4[3];	/* GPIO + 0x25 */
+	volatile u8	sint_ddr;	/* GPIO + 0x28 */
+	volatile u8	reserved5[3];	/* GPIO + 0x29 */
+	volatile u8	sint_dvo;	/* GPIO + 0x2c */
+	volatile u8	reserved6[3];	/* GPIO + 0x2d */
+	volatile u8	sint_inten;	/* GPIO + 0x30 */
+	volatile u8	reserved7[3];	/* GPIO + 0x31 */
+	volatile u16	sint_itype;	/* GPIO + 0x34 */
+	volatile u16	reserved8;	/* GPIO + 0x36 */
+	volatile u8	gpio_control;	/* GPIO + 0x38 */
+	volatile u8	reserved9[3];	/* GPIO + 0x39 */
+	volatile u8	sint_istat;	/* GPIO + 0x3c */
+	volatile u8	sint_ival;	/* GPIO + 0x3d */
+	volatile u8	bus_errs;	/* GPIO + 0x3e */
+	volatile u8	reserved10;	/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
+#define MPC52xx_GPIO_PCI_DIS			(1<<15)
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+	volatile u8 reserved[0x40];
+	volatile u32 config;		/* XLB + 0x40 */
+	volatile u32 version;		/* XLB + 0x44 */
+	volatile u32 status;		/* XLB + 0x48 */
+	volatile u32 int_enable;	/* XLB + 0x4c */
+	volatile u32 addr_capture;	/* XLB + 0x50 */
+	volatile u32 bus_sig_capture;	/* XLB + 0x54 */
+	volatile u32 addr_timeout;	/* XLB + 0x58 */
+	volatile u32 data_timeout;	/* XLB + 0x5c */
+	volatile u32 bus_act_timeout;	/* XLB + 0x60 */
+	volatile u32 master_pri_enable;	/* XLB + 0x64 */
+	volatile u32 master_priority;	/* XLB + 0x68 */
+	volatile u32 base_address;	/* XLB + 0x6c */
+	volatile u32 snoop_window;	/* XLB + 0x70 */
+};
+
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+	volatile u32	jtag_id;	/* MBAR_CDM + 0x00  reg0 read only */
+	volatile u32	rstcfg;		/* MBAR_CDM + 0x04  reg1 read only */
+	volatile u32	breadcrumb;	/* MBAR_CDM + 0x08  reg2 */
+
+	volatile u8	mem_clk_sel;	/* MBAR_CDM + 0x0c  reg3 byte0 */
+	volatile u8	xlb_clk_sel;	/* MBAR_CDM + 0x0d  reg3 byte1 read only */
+	volatile u8	ipb_clk_sel;	/* MBAR_CDM + 0x0e  reg3 byte2 */
+	volatile u8	pci_clk_sel;	/* MBAR_CDM + 0x0f  reg3 byte3 */
+
+	volatile u8	ext_48mhz_en;	/* MBAR_CDM + 0x10  reg4 byte0 */
+	volatile u8	fd_enable;	/* MBAR_CDM + 0x11  reg4 byte1 */
+	volatile u16	fd_counters;	/* MBAR_CDM + 0x12  reg4 byte2,3 */
+
+	volatile u32	clk_enables;	/* MBAR_CDM + 0x14  reg5 */
+
+	volatile u8	osc_disable;	/* MBAR_CDM + 0x18  reg6 byte0 */
+	volatile u8	reserved0[3];	/* MBAR_CDM + 0x19  reg6 byte1,2,3 */
+
+	volatile u8	ccs_sleep_enable;/* MBAR_CDM + 0x1c  reg7 byte0 */
+	volatile u8	osc_sleep_enable;/* MBAR_CDM + 0x1d  reg7 byte1 */
+	volatile u8	reserved1;	/* MBAR_CDM + 0x1e  reg7 byte2 */
+	volatile u8	ccs_qreq_test;	/* MBAR_CDM + 0x1f  reg7 byte3 */
+
+	volatile u8	soft_reset;	/* MBAR_CDM + 0x20  u8 byte0 */
+	volatile u8	no_ckstp;	/* MBAR_CDM + 0x21  u8 byte0 */
+	volatile u8	reserved2[2];	/* MBAR_CDM + 0x22  u8 byte1,2,3 */
+
+	volatile u8	pll_lock;	/* MBAR_CDM + 0x24  reg9 byte0 */
+	volatile u8	pll_looselock;	/* MBAR_CDM + 0x25  reg9 byte1 */
+	volatile u8	pll_sm_lockwin;	/* MBAR_CDM + 0x26  reg9 byte2 */
+	volatile u8	reserved3;	/* MBAR_CDM + 0x27  reg9 byte3 */
+
+	volatile u16	reserved4;	/* MBAR_CDM + 0x28  reg10 byte0,1 */
+	volatile u16	mclken_div_psc1;/* MBAR_CDM + 0x2a  reg10 byte2,3 */
+    
+	volatile u16	reserved5;	/* MBAR_CDM + 0x2c  reg11 byte0,1 */
+	volatile u16	mclken_div_psc2;/* MBAR_CDM + 0x2e  reg11 byte2,3 */
+		
+	volatile u16	reserved6;	/* MBAR_CDM + 0x30  reg12 byte0,1 */
+	volatile u16	mclken_div_psc3;/* MBAR_CDM + 0x32  reg12 byte2,3 */
+    
+	volatile u16	reserved7;	/* MBAR_CDM + 0x34  reg13 byte0,1 */
+	volatile u16	mclken_div_psc6;/* MBAR_CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx syslib                                             */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern int mpc52xx_get_irq(struct pt_regs *regs);
+
+extern unsigned long mpc52xx_find_end_of_memory(void);
+extern void mpc52xx_set_bat(void);
+extern void mpc52xx_map_io(void);
+extern void mpc52xx_restart(char *cmd);
+extern void mpc52xx_halt(void);
+extern void mpc52xx_power_off(void);
+extern void mpc52xx_progress(char *s, unsigned short hex);
+extern void mpc52xx_calibrate_decr(void);
+extern void mpc52xx_add_board_devices(struct ocp_def board_ocp[]);
+
+#endif /* __ASSEMBLY__ */
+
+
+/* ========================================================================= */
+/* Platform configuration                                                    */
+/* ========================================================================= */
+
+/* The U-Boot platform information struct */
+extern bd_t __res;
+
+/* Platform options */
+#if defined(CONFIG_LITE5200)
+#include <platforms/lite5200.h>
+#endif
+
+
+#endif /* __ASM_MPC52xx_H__ */
diff -Nru a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/mpc52xx_psc.h	2004-07-13 12:45:03 -07:00
@@ -0,0 +1,191 @@
+/*
+ * include/asm-ppc/mpc52xx_psc.h
+ * 
+ * Definitions of consts/structs to drive the Freescale MPC52xx OnChip
+ * PSCs. Theses are shared between multiple drivers since a PSC can be
+ * UART, AC97, IR, I2S, ... So this header is in asm-ppc.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Based/Extracted from some header of the 2.4 originally written by 
+ * Dale Farnsworth <dfarnsworth@mvista.com> 
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __MPC52xx_PSC_H__
+#define __MPC52xx_PSC_H__
+
+#include <asm/types.h>
+
+/* Max number of PSCs */
+#define MPC52xx_PSC_MAXNUM	6
+
+/* Programmable Serial Controller (PSC) status register bits */
+#define MPC52xx_PSC_SR_CDE	0x0080
+#define MPC52xx_PSC_SR_RXRDY	0x0100
+#define MPC52xx_PSC_SR_RXFULL	0x0200
+#define MPC52xx_PSC_SR_TXRDY	0x0400
+#define MPC52xx_PSC_SR_TXEMP	0x0800
+#define MPC52xx_PSC_SR_OE	0x1000
+#define MPC52xx_PSC_SR_PE	0x2000
+#define MPC52xx_PSC_SR_FE	0x4000
+#define MPC52xx_PSC_SR_RB	0x8000
+
+/* PSC Command values */
+#define MPC52xx_PSC_RX_ENABLE		0x0001
+#define MPC52xx_PSC_RX_DISABLE		0x0002
+#define MPC52xx_PSC_TX_ENABLE		0x0004
+#define MPC52xx_PSC_TX_DISABLE		0x0008
+#define MPC52xx_PSC_SEL_MODE_REG_1	0x0010
+#define MPC52xx_PSC_RST_RX		0x0020
+#define MPC52xx_PSC_RST_TX		0x0030
+#define MPC52xx_PSC_RST_ERR_STAT	0x0040
+#define MPC52xx_PSC_RST_BRK_CHG_INT	0x0050
+#define MPC52xx_PSC_START_BRK		0x0060
+#define MPC52xx_PSC_STOP_BRK		0x0070
+
+/* PSC TxRx FIFO status bits */
+#define MPC52xx_PSC_RXTX_FIFO_ERR	0x0040
+#define MPC52xx_PSC_RXTX_FIFO_UF	0x0020
+#define MPC52xx_PSC_RXTX_FIFO_OF	0x0010
+#define MPC52xx_PSC_RXTX_FIFO_FR	0x0008
+#define MPC52xx_PSC_RXTX_FIFO_FULL	0x0004
+#define MPC52xx_PSC_RXTX_FIFO_ALARM	0x0002
+#define MPC52xx_PSC_RXTX_FIFO_EMPTY	0x0001
+
+/* PSC interrupt mask bits */
+#define MPC52xx_PSC_IMR_TXRDY		0x0100
+#define MPC52xx_PSC_IMR_RXRDY		0x0200
+#define MPC52xx_PSC_IMR_DB		0x0400
+#define MPC52xx_PSC_IMR_IPC		0x8000
+
+/* PSC input port change bit */
+#define MPC52xx_PSC_CTS			0x01
+#define MPC52xx_PSC_DCD			0x02
+#define MPC52xx_PSC_D_CTS		0x10
+#define MPC52xx_PSC_D_DCD		0x20
+
+/* PSC mode fields */
+#define MPC52xx_PSC_MODE_5_BITS			0x00
+#define MPC52xx_PSC_MODE_6_BITS			0x01
+#define MPC52xx_PSC_MODE_7_BITS			0x02
+#define MPC52xx_PSC_MODE_8_BITS			0x03
+#define MPC52xx_PSC_MODE_BITS_MASK		0x03
+#define MPC52xx_PSC_MODE_PAREVEN		0x00
+#define MPC52xx_PSC_MODE_PARODD			0x04
+#define MPC52xx_PSC_MODE_PARFORCE		0x08
+#define MPC52xx_PSC_MODE_PARNONE		0x10
+#define MPC52xx_PSC_MODE_ERR			0x20
+#define MPC52xx_PSC_MODE_FFULL			0x40
+#define MPC52xx_PSC_MODE_RXRTS			0x80
+
+#define MPC52xx_PSC_MODE_ONE_STOP_5_BITS	0x00
+#define MPC52xx_PSC_MODE_ONE_STOP		0x07
+#define MPC52xx_PSC_MODE_TWO_STOP		0x0f
+
+#define MPC52xx_PSC_RFNUM_MASK	0x01ff
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_psc {
+	volatile u8		mode;		/* PSC + 0x00 */
+	volatile u8		reserved0[3];
+	union {					/* PSC + 0x04 */
+		volatile u16	status;
+		volatile u16	clock_select;
+	} sr_csr;
+#define mpc52xx_psc_status	sr_csr.status
+#define mpc52xx_psc_clock_select	sr_csr.clock_select
+	volatile u16		reserved1;
+	volatile u8		command;	/* PSC + 0x08 */
+volatile u8		reserved2[3];
+	union {					/* PSC + 0x0c */
+		volatile u8	buffer_8;
+		volatile u16	buffer_16;
+		volatile 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
+	union {					/* PSC + 0x10 */
+		volatile u8	ipcr;
+		volatile u8	acr;
+	} ipcr_acr;
+#define mpc52xx_psc_ipcr	ipcr_acr.ipcr
+#define mpc52xx_psc_acr		ipcr_acr.acr
+	volatile u8		reserved3[3];
+	union {					/* PSC + 0x14 */
+		volatile u16	isr;
+		volatile u16	imr;
+	} isr_imr;
+#define mpc52xx_psc_isr		isr_imr.isr
+#define mpc52xx_psc_imr		isr_imr.imr
+	volatile u16		reserved4;
+	volatile u8		ctur;		/* PSC + 0x18 */
+	volatile u8		reserved5[3];
+	volatile u8		ctlr;		/* PSC + 0x1c */
+	volatile u8		reserved6[3];
+	volatile u16		ccr;		/* PSC + 0x20 */
+	volatile u8		reserved7[14];
+	volatile u8		ivr;		/* PSC + 0x30 */
+	volatile u8		reserved8[3];
+	volatile u8		ip;		/* PSC + 0x34 */
+	volatile u8		reserved9[3];
+	volatile u8		op1;		/* PSC + 0x38 */
+	volatile u8		reserved10[3];
+	volatile u8		op0;		/* PSC + 0x3c */
+	volatile u8		reserved11[3];
+	volatile u32		sicr;		/* PSC + 0x40 */
+	volatile u8		ircr1;		/* PSC + 0x44 */
+	volatile u8		reserved13[3];
+	volatile u8		ircr2;		/* PSC + 0x44 */
+	volatile u8		reserved14[3];
+	volatile u8		irsdr;		/* PSC + 0x4c */
+	volatile u8		reserved15[3];
+	volatile u8		irmdr;		/* PSC + 0x50 */
+	volatile u8		reserved16[3];
+	volatile u8		irfdr;		/* PSC + 0x54 */
+	volatile u8		reserved17[3];
+	volatile u16		rfnum;		/* PSC + 0x58 */
+	volatile u16		reserved18;
+	volatile u16		tfnum;		/* PSC + 0x5c */
+	volatile u16		reserved19;
+	volatile u32		rfdata;		/* PSC + 0x60 */
+	volatile u16		rfstat;		/* PSC + 0x64 */
+	volatile u16		reserved20;
+	volatile u8		rfcntl;		/* PSC + 0x68 */
+	volatile u8		reserved21[5];
+	volatile u16		rfalarm;	/* PSC + 0x6e */
+	volatile u16		reserved22;
+	volatile u16		rfrptr;		/* PSC + 0x72 */
+	volatile u16		reserved23;
+	volatile u16		rfwptr;		/* PSC + 0x76 */
+	volatile u16		reserved24;
+	volatile u16		rflrfptr;	/* PSC + 0x7a */
+	volatile u16		reserved25;
+	volatile u16		rflwfptr;	/* PSC + 0x7e */
+	volatile u32		tfdata;		/* PSC + 0x80 */
+	volatile u16		tfstat;		/* PSC + 0x84 */
+	volatile u16		reserved26;
+	volatile u8		tfcntl;		/* PSC + 0x88 */
+	volatile u8		reserved27[5];
+	volatile u16		tfalarm;	/* PSC + 0x8e */
+	volatile u16		reserved28;
+	volatile u16		tfrptr;		/* PSC + 0x92 */
+	volatile u16		reserved29;
+	volatile u16		tfwptr;		/* PSC + 0x96 */
+	volatile u16		reserved30;
+	volatile u16		tflrfptr;	/* PSC + 0x9a */
+	volatile u16		reserved31;
+	volatile u16		tflwfptr;	/* PSC + 0x9e */
+};
+
+
+#endif  /* __MPC52xx_PSC_H__ */
diff -Nru a/include/asm-ppc/ocp_ids.h b/include/asm-ppc/ocp_ids.h
--- a/include/asm-ppc/ocp_ids.h	2004-07-13 12:45:03 -07:00
+++ b/include/asm-ppc/ocp_ids.h	2004-07-13 12:45:03 -07:00
@@ -42,6 +42,7 @@
 #define OCP_FUNC_16550		0x0031
 #define OCP_FUNC_IIC		0x0032
 #define OCP_FUNC_USB		0x0033
+#define OCP_FUNC_PSC_UART	0x0034
 
 /* Memory devices 0x0090 - 0x009F */
 #define OCP_FUNC_MAL		0x0090
diff -Nru a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
--- a/include/asm-ppc/ppcboot.h	2004-07-13 12:45:03 -07:00
+++ b/include/asm-ppc/ppcboot.h	2004-07-13 12:45:03 -07:00
@@ -55,6 +55,9 @@
 #if defined(CONFIG_8xx) || defined(CONFIG_CPM2) || defined(CONFIG_85xx)
 	unsigned long	bi_immr_base;	/* base of IMMR register */
 #endif
+#if defined(CONFIG_PPC_MPC52xx)
+	unsigned long   bi_mbar_base;   /* base of internal registers */
+#endif
 	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
 	unsigned long	bi_ip_addr;	/* IP Address */
 	unsigned char	bi_enetaddr[6];	/* Ethernet address */
@@ -66,6 +69,10 @@
 	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
 	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
 	unsigned long	bi_vco;		/* VCO Out from PLL, in MHz */
+#endif
+#if defined(CONFIG_PPC_MPC52xx)
+	unsigned long   bi_ipbfreq;     /* IPB Bus Freq, in MHz */
+	unsigned long   bi_pcifreq;     /* PCI Bus Freq, in MHz */
 #endif
 	unsigned long	bi_baudrate;	/* Console Baudrate */
 #if defined(CONFIG_405GP)
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	2004-07-13 12:45:03 -07:00
+++ b/include/linux/serial_core.h	2004-07-13 12:45:03 -07:00
@@ -86,6 +86,9 @@
 /* PPC CPM type number */
 #define PORT_CPM        58
 
+/* MPC52xx type numbers */
+#define PORT_MPC52xx	59
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>