From: Domenico Andreoli <[email-masked]>

Also OMAP get its decompressor console support with this driver, which
already sports a nice number of SoC's console data and its own struct
omap_decomp_console.

Signed-off-by: Domenico Andreoli <[email-masked]>

---
 drivers/tty/serial/Makefile      |    2 
 drivers/tty/serial/omap-decomp.c |  192 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+), 1 deletion(-)

Index: b/drivers/tty/serial/Makefile
===================================================================
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -60,7 +60,7 @@ obj-$(CONFIG_SERIAL_NETX) += netx-serial
 obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
 obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
-obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o omap-decomp.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
Index: b/drivers/tty/serial/omap-decomp.c
===================================================================
--- /dev/null
+++ b/drivers/tty/serial/omap-decomp.c
@@ -0,0 +1,192 @@
+/*
+ * Decompressor support for OMAP UARTs
+ *
+ * Copyright (C) 2012 Domenico Andreoli <[email-masked]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/errno.h>
+#include <linux/types.h>
+#include <linux/decompress/console.h>
+#include <linux/serial_reg.h>
+
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+
+#include <plat/serial.h>
+
+#define MDR1_MODE_MASK			0x07
+
+static const char omap_drvname[] __decomp_archdata = "omap-uart";
+
+#define DECOMP_CONSOLE_OMAP(_soc, _data) \
+	DECOMP_CONSOLE_DATA(decomp_console_soc_##_soc, omap_drvname, _data);
+
+struct omap_decomp_console {
+	unsigned long base;
+	unsigned short shift;
+	unsigned char port;
+};
+
+/* OMAP1 serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_omap1[]
+  __decomp_archdata = {
+	{ OMAP1_UART1_BASE, OMAP_PORT_SHIFT, OMAP1UART1, },
+	{ OMAP1_UART2_BASE, OMAP_PORT_SHIFT, OMAP1UART2, },
+	{ OMAP1_UART3_BASE, OMAP_PORT_SHIFT, OMAP1UART3, },
+};
+DECOMP_CONSOLE_OMAP(omap1, __decomp_console_data_omap1);
+
+/* OMAP7XX serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_omap7xx[]
+  __decomp_archdata = {
+	{ OMAP1_UART1_BASE, OMAP7XX_PORT_SHIFT, OMAP1UART1, },
+	{ OMAP1_UART2_BASE, OMAP7XX_PORT_SHIFT, OMAP1UART2, },
+	{ OMAP1_UART3_BASE, OMAP7XX_PORT_SHIFT, OMAP1UART3, },
+};
+DECOMP_CONSOLE_OMAP(omap7xx, __decomp_console_data_omap7xx);
+
+/* OMAP2 serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_omap2[]
+  __decomp_archdata = {
+	{ OMAP2_UART1_BASE, OMAP_PORT_SHIFT, OMAP2UART1, },
+	{ OMAP2_UART2_BASE, OMAP_PORT_SHIFT, OMAP2UART2, },
+	{ OMAP2_UART3_BASE, OMAP_PORT_SHIFT, OMAP2UART3, },
+};
+DECOMP_CONSOLE_OMAP(omap2, __decomp_console_data_omap2);
+
+/* OMAP3 serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_omap3[]
+  __decomp_archdata = {
+	{ OMAP3_UART1_BASE, OMAP_PORT_SHIFT, OMAP3UART1, },
+	{ OMAP3_UART2_BASE, OMAP_PORT_SHIFT, OMAP3UART2, },
+	{ OMAP3_UART3_BASE, OMAP_PORT_SHIFT, OMAP3UART3, },
+	{ OMAP3_UART4_BASE, OMAP_PORT_SHIFT, OMAP3UART4, },
+};
+DECOMP_CONSOLE_OMAP(omap3, __decomp_console_data_omap3);
+
+/* OMAP4 serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_omap4[]
+  __decomp_archdata = {
+	{ OMAP4_UART1_BASE, OMAP_PORT_SHIFT, OMAP4UART1, },
+	{ OMAP4_UART2_BASE, OMAP_PORT_SHIFT, OMAP4UART2, },
+	{ OMAP4_UART3_BASE, OMAP_PORT_SHIFT, OMAP4UART3, },
+	{ OMAP4_UART4_BASE, OMAP_PORT_SHIFT, OMAP4UART4, },
+};
+DECOMP_CONSOLE_OMAP(omap4, __decomp_console_data_omap4);
+
+/* TI81XX serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_ti81xx[]
+  __decomp_archdata = {
+	{ TI81XX_UART1_BASE, OMAP_PORT_SHIFT, TI81XXUART1, },
+	{ TI81XX_UART2_BASE, OMAP_PORT_SHIFT, TI81XXUART2, },
+	{ TI81XX_UART3_BASE, OMAP_PORT_SHIFT, TI81XXUART3, },
+};
+DECOMP_CONSOLE_OMAP(ti81xx, __decomp_console_data_ti81xx);
+
+/* AM33XX serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_am33xx[]
+  __decomp_archdata = {
+//	{ AM33XX_UART1_BASE, OMAP_PORT_SHIFT, AM33XXUART1, },
+	{ 0x44e09000, OMAP_PORT_SHIFT, 82, },
+};
+DECOMP_CONSOLE_OMAP(am33xx, __decomp_console_data_am33xx);
+
+/* AM35XX serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_am35xx[]
+  __decomp_archdata = {
+	{ OMAP3_UART1_BASE, OMAP_PORT_SHIFT, OMAP3UART1, },
+	{ OMAP3_UART2_BASE, OMAP_PORT_SHIFT, OMAP3UART2, },
+	{ OMAP3_UART3_BASE, OMAP_PORT_SHIFT, OMAP3UART3, },
+	{ OMAP3_UART4_AM35XX_BASE, OMAP_PORT_SHIFT, OMAP3UART4, },
+};
+DECOMP_CONSOLE_OMAP(am35xx, __decomp_console_data_am35xx);
+
+/* ZOOM serial ports */
+static const
+struct omap_decomp_console __decomp_console_data_zoom[]
+  __decomp_archdata = {
+	{ ZOOM_UART_BASE, OMAP_PORT_SHIFT, ZOOM_UART, },
+};
+DECOMP_CONSOLE_OMAP(zoom, __decomp_console_data_zoom);
+
+/*
+ * Store the DEBUG_LL uart number into memory.
+ * See also debug-macro.S, and serial.c for related code.
+ */
+static inline void set_omap_uart_info(struct omap_decomp_console *console)
+{
+	/*
+	 * Get address of some.bss variable and round it down
+	 * a la CONFIG_AUTO_ZRELADDR.
+	 */
+	u32 ram_start = (u32) console->shift & 0xf8000000;
+	u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);
+	*uart_info = console->port;
+}
+
+#define omap_decomp_console(_drv) ((struct omap_decomp_console *) (_drv)->devdata)
+
+static int __decomp_arch omap_decomp_probe(struct decomp_console_drv *drv)
+{
+	struct omap_decomp_console *console = omap_decomp_console(drv);
+
+	/* this driver doesn't support probing of the base address */
+	if (!console->base)
+		return -EINVAL;
+
+	set_omap_uart_info(console);
+	return 0;
+}
+
+/* we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+ */
+static void __decomp_arch omap_decomp_putc(struct decomp_console_drv *drv, int ch)
+{
+	struct omap_decomp_console *console = omap_decomp_console(drv);
+	volatile u8 *uart_base = (volatile u8 *) console->base;
+
+	/* Check for UART 16x mode */
+	if ((uart_base[UART_OMAP_MDR1 << console->shift] & MDR1_MODE_MASK) != 0)
+		return;
+
+	while (!(uart_base[UART_LSR << console->shift] & UART_LSR_THRE))
+		barrier();
+
+	uart_base[UART_TX << console->shift] = ch;
+}
+
+static void __decomp_arch omap_decomp_flush(struct decomp_console_drv *drv)
+{
+	/* TODO */
+}
+
+static const char omap_dt_compat[][16] __decomp_archdata = {
+	"omap-uart",
+	"",
+};
+
+DECOMP_CONSOLE_START("ttyO")
+	.probe = omap_decomp_probe,
+	.putc = omap_decomp_putc,
+	.flush = omap_decomp_flush,
+	.dt_compat = omap_dt_compat,
+DECOMP_CONSOLE_END