serial: 8250_pci: add Intel Penwell ports
[firefly-linux-kernel-4.4.55.git] / arch / x86 / platform / intel-mid / early_printk_intel_mid.c
1 /*
2  * early_printk_intel_mid.c - early consoles for Intel MID platforms
3  *
4  * Copyright (c) 2008-2010, Intel Corporation
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; version 2
9  * of the License.
10  */
11
12 /*
13  * This file implements early console named hsu.
14  * hsu is based on a High Speed UART device which only exists in the Medfield
15  * platform
16  */
17
18 #include <linux/serial_reg.h>
19 #include <linux/serial_mfd.h>
20 #include <linux/console.h>
21 #include <linux/kernel.h>
22 #include <linux/delay.h>
23 #include <linux/io.h>
24
25 #include <asm/fixmap.h>
26 #include <asm/pgtable.h>
27 #include <asm/intel-mid.h>
28
29 /*
30  * Following is the early console based on Medfield HSU (High
31  * Speed UART) device.
32  */
33 #define HSU_PORT_BASE           0xffa28080
34
35 static void __iomem *phsu;
36
37 void hsu_early_console_init(const char *s)
38 {
39         unsigned long paddr, port = 0;
40         u8 lcr;
41
42         /*
43          * Select the early HSU console port if specified by user in the
44          * kernel command line.
45          */
46         if (*s && !kstrtoul(s, 10, &port))
47                 port = clamp_val(port, 0, 2);
48
49         paddr = HSU_PORT_BASE + port * 0x80;
50         phsu = (void __iomem *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, paddr);
51
52         /* Disable FIFO */
53         writeb(0x0, phsu + UART_FCR);
54
55         /* Set to default 115200 bps, 8n1 */
56         lcr = readb(phsu + UART_LCR);
57         writeb((0x80 | lcr), phsu + UART_LCR);
58         writeb(0x18, phsu + UART_DLL);
59         writeb(lcr,  phsu + UART_LCR);
60         writel(0x3600, phsu + UART_MUL*4);
61
62         writeb(0x8, phsu + UART_MCR);
63         writeb(0x7, phsu + UART_FCR);
64         writeb(0x3, phsu + UART_LCR);
65
66         /* Clear IRQ status */
67         readb(phsu + UART_LSR);
68         readb(phsu + UART_RX);
69         readb(phsu + UART_IIR);
70         readb(phsu + UART_MSR);
71
72         /* Enable FIFO */
73         writeb(0x7, phsu + UART_FCR);
74 }
75
76 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
77
78 static void early_hsu_putc(char ch)
79 {
80         unsigned int timeout = 10000; /* 10ms */
81         u8 status;
82
83         while (--timeout) {
84                 status = readb(phsu + UART_LSR);
85                 if (status & BOTH_EMPTY)
86                         break;
87                 udelay(1);
88         }
89
90         /* Only write the char when there was no timeout */
91         if (timeout)
92                 writeb(ch, phsu + UART_TX);
93 }
94
95 static void early_hsu_write(struct console *con, const char *str, unsigned n)
96 {
97         int i;
98
99         for (i = 0; i < n && *str; i++) {
100                 if (*str == '\n')
101                         early_hsu_putc('\r');
102                 early_hsu_putc(*str);
103                 str++;
104         }
105 }
106
107 struct console early_hsu_console = {
108         .name =         "earlyhsu",
109         .write =        early_hsu_write,
110         .flags =        CON_PRINTBUFFER,
111         .index =        -1,
112 };