Add support for CONFIG_SERIAL_MULTI on MPC5xxx
Patch by Martin Krause, 8 Jun 2006

This patch supports two serial consoles on boards with a MPC5xxx CPU.
The console could be switchd during runtime by setting stdin, stdout
and stderr to the desired serial interface (serial0 or serial1).
Which PSCs are used for the console is definded by CONFIG_PSC_CONSOLE
and CONFIG_PSC_CONSOLE2. For further Information see README.serial_multi

Signed-of-by: Martin Krause <martin.krause@tqs.de>

---
commit 8a42513ef78a73c721d87933831b8d61601999a3
tree 15647df7c028987ba6d21615f54e99f22a5af9cd
parent 445ba78ece0c857baed2256095f73451cfee1045
author Martin Krause <mkr@tq-sewsrv-4.tq-net.de> Thu, 08 Jun 2006 12:01:04 +0200
committer Martin Krause <mkr@tq-sewsrv-4.tq-net.de> Thu, 08 Jun 2006 12:01:04 +0200

 common/serial.c         |    4 +
 cpu/mpc5xxx/serial.c    |  181 ++++++++++++++++++++++++++++++++++++++++++++---
 doc/README.serial_multi |   26 +++++++
 include/serial.h        |    2 -
 4 files changed, 200 insertions(+), 13 deletions(-)

diff --git a/common/serial.c b/common/serial.c
old mode 100644
new mode 100755
index 2acbd08..7b29951
--- a/common/serial.c
+++ b/common/serial.c
@@ -41,7 +41,7 @@ #elif defined(CONFIG_8xx_CONS_SCC1) || d
    || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
 	return &serial_scc_device;
 #elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) \
-   || defined(CONFIG_405EP)
+   || defined(CONFIG_405EP) || defined(CONFIG_MPC5xxx)
 	return &serial0_device;
 #else
 #error No default console
@@ -75,7 +75,7 @@ #if defined(CONFIG_8xx_CONS_SCC1) || def
 #endif
 
 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) \
- || defined(CONFIG_405EP)
+ || defined(CONFIG_405EP) || defined(CONFIG_MPC5xxx)
 	serial_register(&serial0_device);
 	serial_register(&serial1_device);
 #endif
diff --git a/cpu/mpc5xxx/serial.c b/cpu/mpc5xxx/serial.c
old mode 100644
new mode 100755
index cacb9f0..6cb523d
--- a/cpu/mpc5xxx/serial.c
+++ b/cpu/mpc5xxx/serial.c
@@ -23,6 +23,9 @@
  * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
  * changes based on the file arch/ppc/mbxboot/m8260_tty.c from the
  * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ *
+ * Martin Krause, 8 Jun 2006
+ * Added CONFIG_SERIAL_MULTI support
  */
 
 /*
@@ -33,6 +36,10 @@
 #include <common.h>
 #include <mpc5xxx.h>
 
+#if defined (CONFIG_SERIAL_MULTI)
+#include <serial.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #if defined(CONFIG_PSC_CONSOLE)
@@ -55,9 +62,41 @@ #else
 #error CONFIG_PSC_CONSOLE must be in 1 ... 6
 #endif
 
+#if defined(CONFIG_SERIAL_MULTI) && !defined(CONFIG_PSC_CONSOLE2)
+#error you must define CONFIG_PSC_CONSOLE2 if CONFIG_SERIAL_MULTI is set
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+#if CONFIG_PSC_CONSOLE2 == 1
+#define PSC_BASE2 MPC5XXX_PSC1
+#elif CONFIG_PSC_CONSOLE2 == 2
+#define PSC_BASE2 MPC5XXX_PSC2
+#elif CONFIG_PSC_CONSOLE2 == 3
+#define PSC_BASE2 MPC5XXX_PSC3
+#elif defined(CONFIG_MGT5100)
+#error CONFIG_PSC_CONSOLE2 must be in 1, 2 or 3
+#elif CONFIG_PSC_CONSOLE2 == 4
+#define PSC_BASE2 MPC5XXX_PSC4
+#elif CONFIG_PSC_CONSOLE2 == 5
+#define PSC_BASE2 MPC5XXX_PSC5
+#elif CONFIG_PSC_CONSOLE2 == 6
+#define PSC_BASE2 MPC5XXX_PSC6
+#else
+#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
+#endif
+#endif /* CONFIG_SERIAL_MULTI */
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_init_dev (unsigned long dev_base)
+#else
 int serial_init (void)
+#endif
 {
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
 	unsigned long baseclk;
 	int div;
 
@@ -100,13 +139,24 @@ #endif
 	return (0);
 }
 
-void
-serial_putc(const char c)
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_putc_dev (unsigned long dev_base, const char c)
+#else
+void serial_putc(const char c)
+#endif
 {
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
 
 	if (c == '\n')
+#if defined(CONFIG_SERIAL_MULTI)
+		serial_putc_dev (dev_base, '\r');
+#else
 		serial_putc('\r');
+#endif
 
 	/* Wait for last character to go. */
 	while (!(psc->psc_status & PSC_SR_TXEMP))
@@ -115,18 +165,32 @@ serial_putc(const char c)
 	psc->psc_buffer_8 = c;
 }
 
-void
-serial_puts (const char *s)
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_puts_dev (unsigned long dev_base, const char *s)
+#else
+void serial_puts (const char *s)
+#endif
 {
 	while (*s) {
+#if defined(CONFIG_SERIAL_MULTI)
+		serial_putc_dev (dev_base, *s++);
+#else
 		serial_putc (*s++);
+#endif
 	}
 }
 
-int
-serial_getc(void)
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_getc_dev (unsigned long dev_base)
+#else
+int serial_getc(void)
+#endif
 {
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
 
 	/* Wait for a character to arrive. */
 	while (!(psc->psc_status & PSC_SR_RXRDY))
@@ -135,18 +199,32 @@ serial_getc(void)
 	return psc->psc_buffer_8;
 }
 
-int
-serial_tstc(void)
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_tstc_dev (unsigned long dev_base)
+#else
+int serial_tstc(void)
+#endif
 {
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
 
 	return (psc->psc_status & PSC_SR_RXRDY);
 }
 
-void
-serial_setbrg(void)
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_setbrg_dev (unsigned long dev_base)
+#else
+void serial_setbrg(void)
+#endif
 {
+#if defined(CONFIG_SERIAL_MULTI)
+	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+#else
 	volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
+#endif
 	unsigned long baseclk, div;
 
 #if defined(CONFIG_MGT5100)
@@ -160,4 +238,87 @@ #endif
 	psc->ctur = (div >> 8) & 0xFF;
 	psc->ctlr =  div & 0xff;
 }
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial0_init(void)
+{
+	return (serial_init_dev(PSC_BASE));
+}
+
+int serial1_init(void)
+{
+	return (serial_init_dev(PSC_BASE2));
+}
+void serial0_setbrg (void)
+{
+	serial_setbrg_dev(PSC_BASE);
+}
+void serial1_setbrg (void)
+{
+	serial_setbrg_dev(PSC_BASE2);
+}
+
+void serial0_putc(const char c)
+{
+	serial_putc_dev(PSC_BASE,c);
+}
+
+void serial1_putc(const char c)
+{
+	serial_putc_dev(PSC_BASE2, c);
+}
+void serial0_puts(const char *s)
+{
+	serial_puts_dev(PSC_BASE, s);
+}
+
+void serial1_puts(const char *s)
+{
+	serial_puts_dev(PSC_BASE2, s);
+}
+
+int serial0_getc(void)
+{
+	return(serial_getc_dev(PSC_BASE));
+}
+
+int serial1_getc(void)
+{
+	return(serial_getc_dev(PSC_BASE2));
+}
+int serial0_tstc(void)
+{
+	return (serial_tstc_dev(PSC_BASE));
+}
+
+int serial1_tstc(void)
+{
+	return (serial_tstc_dev(PSC_BASE2));
+}
+
+struct serial_device serial0_device =
+{
+	"serial0",
+	"UART0",
+	serial0_init,
+	serial0_setbrg,
+	serial0_getc,
+	serial0_tstc,
+	serial0_putc,
+	serial0_puts,
+};
+
+struct serial_device serial1_device =
+{
+	"serial1",
+	"UART1",
+	serial1_init,
+	serial1_setbrg,
+	serial1_getc,
+	serial1_tstc,
+	serial1_putc,
+	serial1_puts,
+};
+#endif /* CONFIG_SERIAL_MULTI */
+
 #endif /* CONFIG_PSC_CONSOLE */
diff --git a/doc/README.serial_multi b/doc/README.serial_multi
old mode 100644
new mode 100755
index a8d48fc..b41f920
--- a/doc/README.serial_multi
+++ b/doc/README.serial_multi
@@ -52,3 +52,29 @@ PPC4XX Specific
 	setenv stdout serial0
 	setenv stderr serial0
 	setenv stdin serial0
+
+MPC5xxx Specific
+================
+
+At the moment up to two PSCs could be used as console.
+
+Support for hardware handshake has not been implemented yet.
+
+*) The first (default) console is defined by:
+	#define CONFIG_PSC_CONSOLE <PSC number>
+
+*) The second console is defined by:
+	#define CONFIG_PSC_CONSOLE2 <PSC number>
+
+*) Commands to switch to the second console:
+	setenv stdout serial1
+	setenv stderr serial1
+	setenv stdin serial1
+
+*) Commands to switch to the first console:
+	setenv stdout serial0
+	setenv stderr serial0
+	setenv stdin serial0
+
+*) If a file descriptor is set to "serial" then the current serial device
+   will be used which, in turn, can be switched by above commands.
diff --git a/include/serial.h b/include/serial.h
old mode 100644
new mode 100755
index c8abb72..8c7b1c2
--- a/include/serial.h
+++ b/include/serial.h
@@ -23,7 +23,7 @@ extern struct serial_device serial_scc_d
 extern struct serial_device * default_serial_console (void);
 
 #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) \
-   || defined(CONFIG_405EP)
+   || defined(CONFIG_405EP) || defined(CONFIG_MPC5xxx)
 extern struct serial_device serial0_device;
 extern struct serial_device serial1_device;
 #endif
