diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4d175c751246..a57c1f216b21 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -35,6 +35,7 @@ parameter is applicable:
 	APIC	APIC support is enabled.
 	APM	Advanced Power Management support is enabled.
 	AX25	Appropriate AX.25 support is enabled.
+	BLACKFIN Blackfin architecture is enabled.
 	DRM	Direct Rendering Management support is enabled.
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
@@ -550,7 +551,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
 	dtc3181e=	[HW,SCSI]
 
-	earlyprintk=	[X86-32,X86-64,SH]
+	earlyprintk=	[X86-32,X86-64,SH,BLACKFIN]
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
 
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 26ebb0e8c431..cc789b988f3a 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -1164,6 +1164,20 @@ config DEBUG_BFIN_NO_KERN_HWTRACE
 	  Say Y here to disable hardware tracing in some known "jumpy" pieces
 	  of code so that the trace buffer will extend further back.
 
+config EARLY_PRINTK
+	bool "Early printk" 
+	default n
+	help
+	  This option enables special console drivers which allow the kernel
+	  to print messages very early in the bootup process.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. After enabling this
+	  feature, you must add "earlyprintk=serial,uart0,57600" to the
+	  command line (bootargs). It is safe to say Y here in all cases, as
+	  all of this lives in the init section and is thrown away after the
+	  kernel boots completely.
+
 config DUAL_CORE_TEST_MODULE
 	tristate "Dual Core Test Module"
 	depends on (BF561)
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 243883ec6de1..8aeb6066b19b 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_MODULES)                += module.o
 obj-$(CONFIG_BFIN_DMA_5XX)           += bfin_dma_5xx.o
 obj-$(CONFIG_DUAL_CORE_TEST_MODULE)  += dualcore_test.o
 obj-$(CONFIG_KGDB)                   += kgdb.o
+obj-$(CONFIG_EARLY_PRINTK)           += early_printk.o
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c
new file mode 100644
index 000000000000..9bf61706694f
--- /dev/null
+++ b/arch/blackfin/kernel/early_printk.c
@@ -0,0 +1,161 @@
+/*
+ * File:         arch/blackfin/kernel/early_printk.c
+ * Based on:     arch/x86_64/kernel/early_printk.c
+ * Author:       Robin Getz <rgetz@blackfin.uclinux.org
+ *
+ * Created:      14Aug2007
+ * Description:  allow a console to be used for early printk
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <asm/blackfin.h>
+#include <asm/irq_handler.h>
+#include <asm/early_printk.h>
+
+#ifdef CONFIG_SERIAL_BFIN
+extern struct console *bfin_earlyserial_init(unsigned int port,
+						unsigned int cflag);
+#endif
+
+static struct console *early_console;
+
+/* Default console
+ * Port n == ttyBFn
+ * cflags == UART output modes
+ */
+#define DEFAULT_PORT 0
+#define DEFAULT_CFLAG CS8|B57600
+
+#ifdef CONFIG_SERIAL_CORE
+/* What should get here is "0,57600" */
+static struct console * __init earlyserial_init(char *buf)
+{
+	int baud, bit;
+	char parity;
+	unsigned int serial_port = DEFAULT_PORT;
+	unsigned int cflag = DEFAULT_CFLAG;
+
+	serial_port = simple_strtoul(buf, &buf, 10);
+	buf++;
+
+	cflag = 0;
+	baud = simple_strtoul(buf, &buf, 10);
+	switch (baud) {
+	case 1200:
+		cflag |= B1200;
+		break;
+	case 2400:
+		cflag |= B2400;
+		break;
+	case 4800:
+		cflag |= B4800;
+		break;
+	case 9600:
+		cflag |= B9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 115200:
+		cflag |= B115200;
+		break;
+	default:
+		cflag |= B57600;
+	}
+
+	parity = buf[0];
+	buf++;
+	switch (parity) {
+	case 'e':
+		cflag |= PARENB;
+		break;
+	case 'o':
+		cflag |= PARODD;
+		break;
+	}
+
+	bit = simple_strtoul(buf, &buf, 10);
+	switch (bit) {
+	case 5:
+		cflag |= CS5;
+		break;
+	case 6:
+		cflag |= CS5;
+		break;
+	case 7:
+		cflag |= CS5;
+		break;
+	default:
+		cflag |= CS8;
+	}
+
+#ifdef CONFIG_SERIAL_BFIN
+	return bfin_earlyserial_init(serial_port, cflag);
+#else
+	return NULL;
+#endif
+
+}
+#endif
+
+int __init setup_early_printk(char *buf)
+{
+
+	/* Crashing in here would be really bad, so check both the var
+	   and the pointer before we start using it
+	 */
+	if (!buf)
+		return 0;
+
+	if (!*buf)
+		return 0;
+
+	if (early_console != NULL)
+		return 0;
+
+#ifdef CONFIG_SERIAL_BFIN
+	/* Check for Blackfin Serial */
+	if (!strncmp(buf, "serial,uart", 11)) {
+		buf += 11;
+		early_console = earlyserial_init(buf);
+	}
+#endif
+#ifdef CONFIG_FB
+		/* TODO: add framebuffer console support */
+#endif
+
+	if (likely(early_console)) {
+		early_console->flags |= CON_BOOT;
+
+		register_console(early_console);
+		printk(KERN_INFO "early printk enabled on %s%d\n",
+			early_console->name,
+			early_console->index);
+	}
+
+	return 0;
+}
+
+early_param("earlyprintk", setup_early_printk);
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 1e79ee605d93..5039e2675abc 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -962,30 +962,6 @@ static void __init bfin_serial_init_ports(void)
 }
 
 #ifdef CONFIG_SERIAL_BFIN_CONSOLE
-static void bfin_serial_console_putchar(struct uart_port *port, int ch)
-{
-	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-	while (!(UART_GET_LSR(uart) & THRE))
-		barrier();
-	UART_PUT_CHAR(uart, ch);
-	SSYNC();
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void
-bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct bfin_serial_port *uart = &bfin_serial_ports[co->index];
-	int flags = 0;
-
-	spin_lock_irqsave(&uart->port.lock, flags);
-	uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
-	spin_unlock_irqrestore(&uart->port.lock, flags);
-
-}
-
 /*
  * If the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
@@ -1038,19 +1014,25 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
 	}
 	pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
 }
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+static struct uart_driver bfin_serial_reg;
 
 static int __init
 bfin_serial_console_setup(struct console *co, char *options)
 {
 	struct bfin_serial_port *uart;
+# ifdef CONFIG_SERIAL_BFIN_CONSOLE
 	int baud = 57600;
 	int bits = 8;
 	int parity = 'n';
-#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+#  ifdef CONFIG_SERIAL_BFIN_CTSRTS
 	int flow = 'r';
-#else
+#  else
 	int flow = 'n';
-#endif
+#  endif
+# endif
 
 	/*
 	 * Check whether an invalid uart number has been specified, and
@@ -1061,15 +1043,45 @@ bfin_serial_console_setup(struct console *co, char *options)
 		co->index = 0;
 	uart = &bfin_serial_ports[co->index];
 
+# ifdef CONFIG_SERIAL_BFIN_CONSOLE
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	else
 		bfin_serial_console_get_options(uart, &baud, &parity, &bits);
 
 	return uart_set_options(&uart->port, co, baud, parity, bits, flow);
+# else
+	return 0;
+# endif
+}
+#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) ||
+				 defined (CONFIG_EARLY_PRINTK) */
+
+#ifdef CONFIG_SERIAL_BFIN_CONSOLE
+static void bfin_serial_console_putchar(struct uart_port *port, int ch)
+{
+	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+	while (!(UART_GET_LSR(uart) & THRE))
+		barrier();
+	UART_PUT_CHAR(uart, ch);
+	SSYNC();
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void
+bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct bfin_serial_port *uart = &bfin_serial_ports[co->index];
+	int flags = 0;
+
+	spin_lock_irqsave(&uart->port.lock, flags);
+	uart_console_write(&uart->port, s, count, bfin_serial_console_putchar);
+	spin_unlock_irqrestore(&uart->port.lock, flags);
+
 }
 
-static struct uart_driver bfin_serial_reg;
 static struct console bfin_serial_console = {
 	.name		= BFIN_SERIAL_NAME,
 	.write		= bfin_serial_console_write,
@@ -1095,7 +1107,68 @@ console_initcall(bfin_serial_rs_console_init);
 #define BFIN_SERIAL_CONSOLE	&bfin_serial_console
 #else
 #define BFIN_SERIAL_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
+
+
+#ifdef CONFIG_EARLY_PRINTK
+static __init void early_serial_putc(struct uart_port *port, int ch)
+{
+	unsigned timeout = 0xffff;
+	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+	while ((!(UART_GET_LSR(uart) & THRE)) && --timeout)
+		cpu_relax();
+	UART_PUT_CHAR(uart, ch);
+}
+
+static __init void early_serial_write(struct console *con, const char *s,
+					unsigned int n)
+{
+	struct bfin_serial_port *uart = &bfin_serial_ports[con->index];
+	unsigned int i;
+
+	for (i = 0; i < n; i++, s++) {
+		if (*s == '\n')
+			early_serial_putc(&uart->port, '\r');
+		early_serial_putc(&uart->port, *s);
+	}
+}
+
+static struct __init console bfin_early_serial_console = {
+	.name = "early_BFuart",
+	.write = early_serial_write,
+	.device = uart_console_device,
+	.flags = CON_PRINTBUFFER,
+	.setup = bfin_serial_console_setup,
+	.index = -1,
+	.data  = &bfin_serial_reg,
+};
+
+struct console __init *bfin_earlyserial_init(unsigned int port,
+						unsigned int cflag)
+{
+	struct bfin_serial_port *uart;
+	struct ktermios t;
+
+	if (port == -1 || port >= nr_ports)
+		port = 0;
+	bfin_serial_init_ports();
+	bfin_early_serial_console.index = port;
+#ifdef CONFIG_KGDB_UART
+	kgdb_entry_state = 0;
+	init_kgdb_uart();
 #endif
+	uart = &bfin_serial_ports[port];
+	t.c_cflag = cflag;
+	t.c_iflag = 0;
+	t.c_oflag = 0;
+	t.c_lflag = ICANON;
+	t.c_line = port;
+	bfin_serial_set_termios(&uart->port, &t, &t);
+	return &bfin_early_serial_console;
+}
+
+#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
 
 static struct uart_driver bfin_serial_reg = {
 	.owner			= THIS_MODULE,
diff --git a/include/asm-blackfin/early_printk.h b/include/asm-blackfin/early_printk.h
new file mode 100644
index 000000000000..110f1c1f845c
--- /dev/null
+++ b/include/asm-blackfin/early_printk.h
@@ -0,0 +1,28 @@
+/*
+ * File:         include/asm-blackfin/early_printk.h
+ * Author:       Robin Getz <rgetz@blackfin.uclinux.org
+ *
+ * Created:      14Aug2007
+ * Description:  function prototpyes for early printk
+ *
+ * Modified:
+ *               Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifdef CONFIG_EARLY_PRINTK
+extern int setup_early_printk(char *);
+#else
+#define setup_early_printk(fmt) do { } while (0)
+#endif /* CONFIG_EARLY_PRINTK */