1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Early serial console for 8250/16550 devices 4 * 5 * (c) Copyright 2004 Hewlett-Packard Development Company, L.P. 6 * Bjorn Helgaas <bjorn.helgaas@hp.com> 7 * 8 * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King, 9 * and on early_printk.c by Andi Kleen. 10 * 11 * This is for use before the serial driver has initialized, in 12 * particular, before the UARTs have been discovered and named. 13 * Instead of specifying the console device as, e.g., "ttyS0", 14 * we locate the device directly by its MMIO or I/O port address. 15 * 16 * The user can specify the device directly, e.g., 17 * earlycon=uart8250,io,0x3f8,9600n8 18 * earlycon=uart8250,mmio,0xff5e0000,115200n8 19 * earlycon=uart8250,mmio32,0xff5e0000,115200n8 20 * or 21 * console=uart8250,io,0x3f8,9600n8 22 * console=uart8250,mmio,0xff5e0000,115200n8 23 * console=uart8250,mmio32,0xff5e0000,115200n8 24 */ 25 26 #include <linux/tty.h> 27 #include <linux/init.h> 28 #include <linux/console.h> 29 #include <linux/of.h> 30 #include <linux/of_device.h> 31 #include <linux/serial_reg.h> 32 #include <linux/serial.h> 33 #include <linux/serial_8250.h> 34 #include <asm/io.h> 35 #include <asm/serial.h> 36 37 static unsigned int serial8250_early_in(struct uart_port *port, int offset) 38 { 39 offset <<= port->regshift; 40 41 switch (port->iotype) { 42 case UPIO_MEM: 43 return readb(port->membase + offset); 44 case UPIO_MEM16: 45 return readw(port->membase + offset); 46 case UPIO_MEM32: 47 return readl(port->membase + offset); 48 case UPIO_MEM32BE: 49 return ioread32be(port->membase + offset); 50 case UPIO_PORT: 51 return inb(port->iobase + offset); 52 default: 53 return 0; 54 } 55 } 56 57 static void serial8250_early_out(struct uart_port *port, int offset, int value) 58 { 59 offset <<= port->regshift; 60 61 switch (port->iotype) { 62 case UPIO_MEM: 63 writeb(value, port->membase + offset); 64 break; 65 case UPIO_MEM16: 66 writew(value, port->membase + offset); 67 break; 68 case UPIO_MEM32: 69 writel(value, port->membase + offset); 70 break; 71 case UPIO_MEM32BE: 72 iowrite32be(value, port->membase + offset); 73 break; 74 case UPIO_PORT: 75 outb(value, port->iobase + offset); 76 break; 77 } 78 } 79 80 static void serial_putc(struct uart_port *port, unsigned char c) 81 { 82 unsigned int status; 83 84 serial8250_early_out(port, UART_TX, c); 85 86 for (;;) { 87 status = serial8250_early_in(port, UART_LSR); 88 if (uart_lsr_tx_empty(status)) 89 break; 90 cpu_relax(); 91 } 92 } 93 94 static void early_serial8250_write(struct console *console, 95 const char *s, unsigned int count) 96 { 97 struct earlycon_device *device = console->data; 98 struct uart_port *port = &device->port; 99 100 uart_console_write(port, s, count, serial_putc); 101 } 102 103 #ifdef CONFIG_CONSOLE_POLL 104 static int early_serial8250_read(struct console *console, 105 char *s, unsigned int count) 106 { 107 struct earlycon_device *device = console->data; 108 struct uart_port *port = &device->port; 109 unsigned int status; 110 int num_read = 0; 111 112 while (num_read < count) { 113 status = serial8250_early_in(port, UART_LSR); 114 if (!(status & UART_LSR_DR)) 115 break; 116 s[num_read++] = serial8250_early_in(port, UART_RX); 117 } 118 119 return num_read; 120 } 121 #else 122 #define early_serial8250_read NULL 123 #endif 124 125 static void __init init_port(struct earlycon_device *device) 126 { 127 struct uart_port *port = &device->port; 128 unsigned int divisor; 129 unsigned char c; 130 unsigned int ier; 131 132 serial8250_early_out(port, UART_LCR, UART_LCR_WLEN8); /* 8n1 */ 133 ier = serial8250_early_in(port, UART_IER); 134 serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); /* no interrupt */ 135 serial8250_early_out(port, UART_FCR, 0); /* no fifo */ 136 serial8250_early_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); 137 138 if (port->uartclk) { 139 divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud); 140 c = serial8250_early_in(port, UART_LCR); 141 serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB); 142 serial8250_early_out(port, UART_DLL, divisor & 0xff); 143 serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff); 144 serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB); 145 } 146 } 147 148 int __init early_serial8250_setup(struct earlycon_device *device, 149 const char *options) 150 { 151 if (!(device->port.membase || device->port.iobase)) 152 return -ENODEV; 153 154 if (!device->baud) { 155 struct uart_port *port = &device->port; 156 unsigned int ier; 157 158 /* assume the device was initialized, only mask interrupts */ 159 ier = serial8250_early_in(port, UART_IER); 160 serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); 161 } else 162 init_port(device); 163 164 device->con->write = early_serial8250_write; 165 device->con->read = early_serial8250_read; 166 return 0; 167 } 168 EARLYCON_DECLARE(uart8250, early_serial8250_setup); 169 EARLYCON_DECLARE(uart, early_serial8250_setup); 170 OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); 171 OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); 172 OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup); 173 OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup); 174 175 #ifdef CONFIG_SERIAL_8250_OMAP 176 177 static int __init early_omap8250_setup(struct earlycon_device *device, 178 const char *options) 179 { 180 struct uart_port *port = &device->port; 181 182 if (!(device->port.membase || device->port.iobase)) 183 return -ENODEV; 184 185 port->regshift = 2; 186 device->con->write = early_serial8250_write; 187 return 0; 188 } 189 190 OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup); 191 OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); 192 OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); 193 194 #endif 195