root/drivers/tty/serial/8250/8250_early.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. serial8250_early_in
  2. serial8250_early_out
  3. serial_putc
  4. early_serial8250_write
  5. init_port
  6. early_serial8250_setup
  7. early_omap8250_setup
  8. early_au_setup

   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         int reg_offset = offset;
  40         offset <<= port->regshift;
  41 
  42         switch (port->iotype) {
  43         case UPIO_MEM:
  44                 return readb(port->membase + offset);
  45         case UPIO_MEM16:
  46                 return readw(port->membase + offset);
  47         case UPIO_MEM32:
  48                 return readl(port->membase + offset);
  49         case UPIO_MEM32BE:
  50                 return ioread32be(port->membase + offset);
  51         case UPIO_PORT:
  52                 return inb(port->iobase + offset);
  53         case UPIO_AU:
  54                 return port->serial_in(port, reg_offset);
  55         default:
  56                 return 0;
  57         }
  58 }
  59 
  60 static void serial8250_early_out(struct uart_port *port, int offset, int value)
  61 {
  62         int reg_offset = offset;
  63         offset <<= port->regshift;
  64 
  65         switch (port->iotype) {
  66         case UPIO_MEM:
  67                 writeb(value, port->membase + offset);
  68                 break;
  69         case UPIO_MEM16:
  70                 writew(value, port->membase + offset);
  71                 break;
  72         case UPIO_MEM32:
  73                 writel(value, port->membase + offset);
  74                 break;
  75         case UPIO_MEM32BE:
  76                 iowrite32be(value, port->membase + offset);
  77                 break;
  78         case UPIO_PORT:
  79                 outb(value, port->iobase + offset);
  80                 break;
  81         case UPIO_AU:
  82                 port->serial_out(port, reg_offset, value);
  83                 break;
  84         }
  85 }
  86 
  87 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
  88 
  89 static void serial_putc(struct uart_port *port, int c)
  90 {
  91         unsigned int status;
  92 
  93         serial8250_early_out(port, UART_TX, c);
  94 
  95         for (;;) {
  96                 status = serial8250_early_in(port, UART_LSR);
  97                 if ((status & BOTH_EMPTY) == BOTH_EMPTY)
  98                         break;
  99                 cpu_relax();
 100         }
 101 }
 102 
 103 static void early_serial8250_write(struct console *console,
 104                                         const char *s, unsigned int count)
 105 {
 106         struct earlycon_device *device = console->data;
 107         struct uart_port *port = &device->port;
 108 
 109         uart_console_write(port, s, count, serial_putc);
 110 }
 111 
 112 static void __init init_port(struct earlycon_device *device)
 113 {
 114         struct uart_port *port = &device->port;
 115         unsigned int divisor;
 116         unsigned char c;
 117         unsigned int ier;
 118 
 119         serial8250_early_out(port, UART_LCR, 0x3);      /* 8n1 */
 120         ier = serial8250_early_in(port, UART_IER);
 121         serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); /* no interrupt */
 122         serial8250_early_out(port, UART_FCR, 0);        /* no fifo */
 123         serial8250_early_out(port, UART_MCR, 0x3);      /* DTR + RTS */
 124 
 125         if (port->uartclk) {
 126                 divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
 127                 c = serial8250_early_in(port, UART_LCR);
 128                 serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
 129                 serial8250_early_out(port, UART_DLL, divisor & 0xff);
 130                 serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
 131                 serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 132         }
 133 }
 134 
 135 int __init early_serial8250_setup(struct earlycon_device *device,
 136                                          const char *options)
 137 {
 138         if (!(device->port.membase || device->port.iobase))
 139                 return -ENODEV;
 140 
 141         if (!device->baud) {
 142                 struct uart_port *port = &device->port;
 143                 unsigned int ier;
 144 
 145                 /* assume the device was initialized, only mask interrupts */
 146                 ier = serial8250_early_in(port, UART_IER);
 147                 serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
 148         } else
 149                 init_port(device);
 150 
 151         device->con->write = early_serial8250_write;
 152         return 0;
 153 }
 154 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 155 EARLYCON_DECLARE(uart, early_serial8250_setup);
 156 OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
 157 OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
 158 OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
 159 OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
 160 
 161 #ifdef CONFIG_SERIAL_8250_OMAP
 162 
 163 static int __init early_omap8250_setup(struct earlycon_device *device,
 164                                        const char *options)
 165 {
 166         struct uart_port *port = &device->port;
 167 
 168         if (!(device->port.membase || device->port.iobase))
 169                 return -ENODEV;
 170 
 171         port->regshift = 2;
 172         device->con->write = early_serial8250_write;
 173         return 0;
 174 }
 175 
 176 OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup);
 177 OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
 178 OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
 179 
 180 #endif
 181 
 182 #ifdef CONFIG_SERIAL_8250_RT288X
 183 
 184 unsigned int au_serial_in(struct uart_port *p, int offset);
 185 void au_serial_out(struct uart_port *p, int offset, int value);
 186 
 187 static int __init early_au_setup(struct earlycon_device *dev, const char *opt)
 188 {
 189         dev->port.serial_in = au_serial_in;
 190         dev->port.serial_out = au_serial_out;
 191         dev->port.iotype = UPIO_AU;
 192         dev->con->write = early_serial8250_write;
 193         return 0;
 194 }
 195 OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup);
 196 
 197 #endif

/* [<][>][^][v][top][bottom][index][help] */