|
@@ -2403,6 +2403,109 @@ static struct platform_driver samsung_serial_driver = {
|
|
|
|
|
|
module_platform_driver(samsung_serial_driver);
|
|
|
|
|
|
+/*
|
|
|
+ * Early console.
|
|
|
+ */
|
|
|
+
|
|
|
+struct samsung_early_console_data {
|
|
|
+ u32 txfull_mask;
|
|
|
+};
|
|
|
+
|
|
|
+static void samsung_early_busyuart(struct uart_port *port)
|
|
|
+{
|
|
|
+ while (!(readl(port->membase + S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE))
|
|
|
+ ;
|
|
|
+}
|
|
|
+
|
|
|
+static void samsung_early_busyuart_fifo(struct uart_port *port)
|
|
|
+{
|
|
|
+ struct samsung_early_console_data *data = port->private_data;
|
|
|
+
|
|
|
+ while (readl(port->membase + S3C2410_UFSTAT) & data->txfull_mask)
|
|
|
+ ;
|
|
|
+}
|
|
|
+
|
|
|
+static void samsung_early_putc(struct uart_port *port, int c)
|
|
|
+{
|
|
|
+ if (readl(port->membase + S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE)
|
|
|
+ samsung_early_busyuart_fifo(port);
|
|
|
+ else
|
|
|
+ samsung_early_busyuart(port);
|
|
|
+
|
|
|
+ writeb(c, port->membase + S3C2410_UTXH);
|
|
|
+}
|
|
|
+
|
|
|
+static void samsung_early_write(struct console *con, const char *s, unsigned n)
|
|
|
+{
|
|
|
+ struct earlycon_device *dev = con->data;
|
|
|
+
|
|
|
+ uart_console_write(&dev->port, s, n, samsung_early_putc);
|
|
|
+}
|
|
|
+
|
|
|
+static int __init samsung_early_console_setup(struct earlycon_device *device,
|
|
|
+ const char *opt)
|
|
|
+{
|
|
|
+ if (!device->port.membase)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ device->con->write = samsung_early_write;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* S3C2410 */
|
|
|
+static struct samsung_early_console_data s3c2410_early_console_data = {
|
|
|
+ .txfull_mask = S3C2410_UFSTAT_TXFULL,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init s3c2410_early_console_setup(struct earlycon_device *device,
|
|
|
+ const char *opt)
|
|
|
+{
|
|
|
+ device->port.private_data = &s3c2410_early_console_data;
|
|
|
+ return samsung_early_console_setup(device, opt);
|
|
|
+}
|
|
|
+OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
|
|
|
+ s3c2410_early_console_setup);
|
|
|
+EARLYCON_DECLARE(s3c2410, s3c2410_early_console_setup);
|
|
|
+
|
|
|
+/* S3C2412, S3C2440, S3C64xx */
|
|
|
+static struct samsung_early_console_data s3c2440_early_console_data = {
|
|
|
+ .txfull_mask = S3C2440_UFSTAT_TXFULL,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init s3c2440_early_console_setup(struct earlycon_device *device,
|
|
|
+ const char *opt)
|
|
|
+{
|
|
|
+ device->port.private_data = &s3c2440_early_console_data;
|
|
|
+ return samsung_early_console_setup(device, opt);
|
|
|
+}
|
|
|
+OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
|
|
|
+ s3c2440_early_console_setup);
|
|
|
+OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
|
|
|
+ s3c2440_early_console_setup);
|
|
|
+OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
|
|
|
+ s3c2440_early_console_setup);
|
|
|
+EARLYCON_DECLARE(s3c2412, s3c2440_early_console_setup);
|
|
|
+EARLYCON_DECLARE(s3c2440, s3c2440_early_console_setup);
|
|
|
+EARLYCON_DECLARE(s3c6400, s3c2440_early_console_setup);
|
|
|
+
|
|
|
+/* S5PV210, EXYNOS */
|
|
|
+static struct samsung_early_console_data s5pv210_early_console_data = {
|
|
|
+ .txfull_mask = S5PV210_UFSTAT_TXFULL,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init s5pv210_early_console_setup(struct earlycon_device *device,
|
|
|
+ const char *opt)
|
|
|
+{
|
|
|
+ device->port.private_data = &s5pv210_early_console_data;
|
|
|
+ return samsung_early_console_setup(device, opt);
|
|
|
+}
|
|
|
+OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
|
|
|
+ s5pv210_early_console_setup);
|
|
|
+OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
|
|
|
+ s5pv210_early_console_setup);
|
|
|
+EARLYCON_DECLARE(s5pv210, s5pv210_early_console_setup);
|
|
|
+EARLYCON_DECLARE(exynos4210, s5pv210_early_console_setup);
|
|
|
+
|
|
|
MODULE_ALIAS("platform:samsung-uart");
|
|
|
MODULE_DESCRIPTION("Samsung SoC Serial port driver");
|
|
|
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|