===================================================================
@@ -26,7 +26,7 @@ obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
-obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
+obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o samsung-decomp.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
===================================================================
@@ -0,0 +1,140 @@
+/*
+ * Decompressor support for Samsung UARTs
+ *
+ * Copyright (C) 2012 Domenico Andreoli <domenico.andreoli@linux.com>
+ *
+ * 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/decompress/console.h>
+
+typedef unsigned int upf_t; /* cannot include linux/serial_core.h */
+
+#include <mach/map.h>
+#include <mach/regs-gpio.h>
+#include <plat/regs-serial.h>
+
+static const char samsung_drvname[] __decomp_archdata = "samsung-uart";
+
+#define DECOMP_CONSOLE_SAMSUNG(_soc, _data) \
+ DECOMP_CONSOLE_DATA(decomp_console_soc_##_soc, samsung_drvname, _data);
+
+struct samsung_decomp_console {
+ unsigned long base;
+ unsigned int fifo_mask;
+ unsigned int fifo_max;
+};
+
+/* s5p6450 serial ports */
+static const struct samsung_decomp_console
+ __decomp_console_data_s5p6450[] __decomp_archdata = {
+ { 0xec800000, },
+ { 0xec800400, },
+ { 0xec800800, },
+ { 0xec800c00, },
+};
+DECOMP_CONSOLE_SAMSUNG(s5p6450, __decomp_console_data_s5p6450);
+
+static inline unsigned int uart_rd(unsigned long base, unsigned int reg)
+{
+ volatile unsigned int *p = (volatile unsigned int *) (base + reg);
+ return *p;
+}
+
+static inline void uart_wr(unsigned long base, unsigned int reg, unsigned int val)
+{
+ volatile unsigned int *p = (volatile unsigned int *) (base + reg);
+ *p = val;
+}
+
+#define samsung_decomp_console(_drv) ((struct samsung_decomp_console *) (_drv)->devdata)
+
+static int __decomp_arch samsung_decomp_probe(struct decomp_console_drv *drv)
+{
+ struct samsung_decomp_console *console = samsung_decomp_console(drv);
+ u32 fifocon;
+ int retries = 1000;
+
+ /* this driver doesn't support probing of the base address */
+ if (!console->base)
+ return -EINVAL;
+
+ /* Enable the UART FIFOs if they are not enabled and our
+ * configuration says we should turn them on.
+ */
+ if (console->fifo_mask && console->fifo_max &&
+ IS_ENABLED(CONFIG_S3C_BOOT_UART_FORCE_FIFO)) {
+ fifocon = uart_rd(console->base, S3C2410_UFCON);
+
+ if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
+ fifocon |= S3C2410_UFCON_RESETBOTH;
+ uart_wr(console->base, S3C2410_UFCON, fifocon);
+
+ /* wait for fifo reset to complete */
+ while (retries--) {
+ fifocon = uart_rd(console->base, S3C2410_UFCON);
+ if (!(fifocon & S3C2410_UFCON_RESETBOTH))
+ break;
+ barrier();
+ }
+ }
+ }
+
+ return retries ? 0 : -EBUSY;
+}
+
+/* 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 samsung_decomp_putc(struct decomp_console_drv *drv, int ch)
+{
+ struct samsung_decomp_console *console = samsung_decomp_console(drv);
+
+ if (console->fifo_mask && console->fifo_max &&
+ uart_rd(console->base, S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+ while (1) {
+ int level = uart_rd(console->base, S3C2410_UFSTAT);
+ level &= console->fifo_mask;
+
+ if (level < console->fifo_max)
+ break;
+ }
+ } else {
+ /* not using fifos */
+ while ((uart_rd(console->base, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+ barrier();
+ }
+
+ /* write byte to transmission register */
+ uart_wr(console->base, S3C2410_UTXH, ch);
+}
+
+static void __decomp_arch samsung_decomp_flush(struct decomp_console_drv *drv)
+{
+ struct samsung_decomp_console *console = samsung_decomp_console(drv);
+
+ /* FIXME: not using fifos */
+ while ((uart_rd(console->base, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+ barrier();
+}
+
+static const char samsung_dt_compat[][16] __decomp_archdata = {
+ "samsung-uart",
+ "",
+};
+
+DECOMP_CONSOLE_START("ttySAC")
+ .probe = samsung_decomp_probe,
+ .putc = samsung_decomp_putc,
+ .flush = samsung_decomp_flush,
+ .dt_compat = samsung_dt_compat,
+DECOMP_CONSOLE_END
===================================================================
@@ -26,6 +26,8 @@
#include <linux/fb.h>
#include <linux/mmc/host.h>
+#include <linux/decompress/console.h>
+
#include <video/platform_lcd.h>
#include <asm/hardware/vic.h>
@@ -287,6 +289,8 @@ static void __init smdk6450_machine_init
platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
}
+DECOMP_CONSOLE_SOC(SMDK6450, decomp_console_soc_s5p6450);
+
MACHINE_START(SMDK6450, "SMDK6450")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.atag_offset = 0x100,