LCOV - code coverage report
Current view: top level - drivers/tty/serial/8250 - 8250_early.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 56 0.0 %
Date: 2020-10-17 15:46:43 Functions: 0 6 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       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                 :          0 : static unsigned int serial8250_early_in(struct uart_port *port, int offset)
      38                 :            : {
      39                 :            :         int reg_offset = offset;
      40                 :          0 :         offset <<= port->regshift;
      41                 :            : 
      42                 :          0 :         switch (port->iotype) {
      43                 :            :         case UPIO_MEM:
      44                 :          0 :                 return readb(port->membase + offset);
      45                 :            :         case UPIO_MEM16:
      46                 :          0 :                 return readw(port->membase + offset);
      47                 :            :         case UPIO_MEM32:
      48                 :          0 :                 return readl(port->membase + offset);
      49                 :            :         case UPIO_MEM32BE:
      50                 :          0 :                 return ioread32be(port->membase + offset);
      51                 :            :         case UPIO_PORT:
      52                 :          0 :                 return inb(port->iobase + offset);
      53                 :            :         case UPIO_AU:
      54                 :          0 :                 return port->serial_in(port, reg_offset);
      55                 :            :         default:
      56                 :            :                 return 0;
      57                 :            :         }
      58                 :            : }
      59                 :            : 
      60                 :          0 : static void serial8250_early_out(struct uart_port *port, int offset, int value)
      61                 :            : {
      62                 :            :         int reg_offset = offset;
      63                 :          0 :         offset <<= port->regshift;
      64                 :            : 
      65                 :          0 :         switch (port->iotype) {
      66                 :            :         case UPIO_MEM:
      67                 :          0 :                 writeb(value, port->membase + offset);
      68                 :            :                 break;
      69                 :            :         case UPIO_MEM16:
      70                 :          0 :                 writew(value, port->membase + offset);
      71                 :            :                 break;
      72                 :            :         case UPIO_MEM32:
      73                 :          0 :                 writel(value, port->membase + offset);
      74                 :            :                 break;
      75                 :            :         case UPIO_MEM32BE:
      76                 :          0 :                 iowrite32be(value, port->membase + offset);
      77                 :            :                 break;
      78                 :            :         case UPIO_PORT:
      79                 :          0 :                 outb(value, port->iobase + offset);
      80                 :            :                 break;
      81                 :            :         case UPIO_AU:
      82                 :          0 :                 port->serial_out(port, reg_offset, value);
      83                 :          0 :                 break;
      84                 :            :         }
      85                 :          0 : }
      86                 :            : 
      87                 :            : #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
      88                 :            : 
      89                 :          0 : static void serial_putc(struct uart_port *port, int c)
      90                 :            : {
      91                 :            :         unsigned int status;
      92                 :            : 
      93                 :          0 :         serial8250_early_out(port, UART_TX, c);
      94                 :            : 
      95                 :            :         for (;;) {
      96                 :          0 :                 status = serial8250_early_in(port, UART_LSR);
      97                 :          0 :                 if ((status & BOTH_EMPTY) == BOTH_EMPTY)
      98                 :            :                         break;
      99                 :          0 :                 cpu_relax();
     100                 :          0 :         }
     101                 :          0 : }
     102                 :            : 
     103                 :          0 : static void early_serial8250_write(struct console *console,
     104                 :            :                                         const char *s, unsigned int count)
     105                 :            : {
     106                 :          0 :         struct earlycon_device *device = console->data;
     107                 :          0 :         struct uart_port *port = &device->port;
     108                 :            : 
     109                 :          0 :         uart_console_write(port, s, count, serial_putc);
     110                 :          0 : }
     111                 :            : 
     112                 :          0 : static void __init init_port(struct earlycon_device *device)
     113                 :            : {
     114                 :          0 :         struct uart_port *port = &device->port;
     115                 :            :         unsigned int divisor;
     116                 :            :         unsigned char c;
     117                 :            :         unsigned int ier;
     118                 :            : 
     119                 :          0 :         serial8250_early_out(port, UART_LCR, 0x3);      /* 8n1 */
     120                 :          0 :         ier = serial8250_early_in(port, UART_IER);
     121                 :          0 :         serial8250_early_out(port, UART_IER, ier & UART_IER_UUE); /* no interrupt */
     122                 :          0 :         serial8250_early_out(port, UART_FCR, 0);        /* no fifo */
     123                 :          0 :         serial8250_early_out(port, UART_MCR, 0x3);      /* DTR + RTS */
     124                 :            : 
     125                 :          0 :         if (port->uartclk) {
     126                 :          0 :                 divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
     127                 :          0 :                 c = serial8250_early_in(port, UART_LCR);
     128                 :          0 :                 serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
     129                 :          0 :                 serial8250_early_out(port, UART_DLL, divisor & 0xff);
     130                 :          0 :                 serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
     131                 :          0 :                 serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
     132                 :            :         }
     133                 :          0 : }
     134                 :            : 
     135                 :          0 : int __init early_serial8250_setup(struct earlycon_device *device,
     136                 :            :                                          const char *options)
     137                 :            : {
     138                 :          0 :         if (!(device->port.membase || device->port.iobase))
     139                 :            :                 return -ENODEV;
     140                 :            : 
     141                 :          0 :         if (!device->baud) {
     142                 :          0 :                 struct uart_port *port = &device->port;
     143                 :            :                 unsigned int ier;
     144                 :            : 
     145                 :            :                 /* assume the device was initialized, only mask interrupts */
     146                 :          0 :                 ier = serial8250_early_in(port, UART_IER);
     147                 :          0 :                 serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
     148                 :            :         } else
     149                 :          0 :                 init_port(device);
     150                 :            : 
     151                 :          0 :         device->con->write = early_serial8250_write;
     152                 :          0 :         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
    

Generated by: LCOV version 1.14