OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [drivers/] [serial/] [8250_early.c] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Early serial console for 8250/16550 devices
3
 *
4
 * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
5
 *      Bjorn Helgaas <bjorn.helgaas@hp.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 *
11
 * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
12
 * and on early_printk.c by Andi Kleen.
13
 *
14
 * This is for use before the serial driver has initialized, in
15
 * particular, before the UARTs have been discovered and named.
16
 * Instead of specifying the console device as, e.g., "ttyS0",
17
 * we locate the device directly by its MMIO or I/O port address.
18
 *
19
 * The user can specify the device directly, e.g.,
20
 *      earlycon=uart8250,io,0x3f8,9600n8
21
 *      earlycon=uart8250,mmio,0xff5e0000,115200n8
22
 * or
23
 *      console=uart8250,io,0x3f8,9600n8
24
 *      console=uart8250,mmio,0xff5e0000,115200n8
25
 */
26
 
27
#include <linux/tty.h>
28
#include <linux/init.h>
29
#include <linux/console.h>
30
#include <linux/serial_core.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
#ifdef CONFIG_FIX_EARLYCON_MEM
37
#include <asm/pgtable.h>
38
#include <asm/fixmap.h>
39
#endif
40
 
41
struct early_serial8250_device {
42
        struct uart_port port;
43
        char options[16];               /* e.g., 115200n8 */
44
        unsigned int baud;
45
};
46
 
47
static struct early_serial8250_device early_device;
48
 
49
static unsigned int __init serial_in(struct uart_port *port, int offset)
50
{
51
        if (port->iotype == UPIO_MEM)
52
                return readb(port->membase + offset);
53
        else
54
                return inb(port->iobase + offset);
55
}
56
 
57
static void __init serial_out(struct uart_port *port, int offset, int value)
58
{
59
        if (port->iotype == UPIO_MEM)
60
                writeb(value, port->membase + offset);
61
        else
62
                outb(value, port->iobase + offset);
63
}
64
 
65
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
66
 
67
static void __init wait_for_xmitr(struct uart_port *port)
68
{
69
        unsigned int status;
70
 
71
        for (;;) {
72
                status = serial_in(port, UART_LSR);
73
                if ((status & BOTH_EMPTY) == BOTH_EMPTY)
74
                        return;
75
                cpu_relax();
76
        }
77
}
78
 
79
static void __init serial_putc(struct uart_port *port, int c)
80
{
81
        wait_for_xmitr(port);
82
        serial_out(port, UART_TX, c);
83
}
84
 
85
static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
86
{
87
        struct uart_port *port = &early_device.port;
88
        unsigned int ier;
89
 
90
        /* Save the IER and disable interrupts */
91
        ier = serial_in(port, UART_IER);
92
        serial_out(port, UART_IER, 0);
93
 
94
        uart_console_write(port, s, count, serial_putc);
95
 
96
        /* Wait for transmitter to become empty and restore the IER */
97
        wait_for_xmitr(port);
98
        serial_out(port, UART_IER, ier);
99
}
100
 
101
static unsigned int __init probe_baud(struct uart_port *port)
102
{
103
        unsigned char lcr, dll, dlm;
104
        unsigned int quot;
105
 
106
        lcr = serial_in(port, UART_LCR);
107
        serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
108
        dll = serial_in(port, UART_DLL);
109
        dlm = serial_in(port, UART_DLM);
110
        serial_out(port, UART_LCR, lcr);
111
 
112
        quot = (dlm << 8) | dll;
113
        return (port->uartclk / 16) / quot;
114
}
115
 
116
static void __init init_port(struct early_serial8250_device *device)
117
{
118
        struct uart_port *port = &device->port;
119
        unsigned int divisor;
120
        unsigned char c;
121
 
122
        serial_out(port, UART_LCR, 0x3);        /* 8n1 */
123
        serial_out(port, UART_IER, 0);           /* no interrupt */
124
        serial_out(port, UART_FCR, 0);           /* no fifo */
125
        serial_out(port, UART_MCR, 0x3);        /* DTR + RTS */
126
 
127
        divisor = port->uartclk / (16 * device->baud);
128
        c = serial_in(port, UART_LCR);
129 7 xianfeng
 
130 3 xianfeng
        serial_out(port, UART_LCR, c | UART_LCR_DLAB);
131
        serial_out(port, UART_DLL, divisor & 0xff);
132
        serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
133
        serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
134
}
135
 
136
static int __init parse_options(struct early_serial8250_device *device, char *options)
137
{
138
        struct uart_port *port = &device->port;
139
        int mmio, length;
140
 
141
        if (!options)
142
                return -ENODEV;
143
 
144 7 xianfeng
        /* port->uartclk = BASE_BAUD * 16; */
145
        port->uartclk = SYS_CLK; /* changed */
146
 
147 3 xianfeng
        if (!strncmp(options, "mmio,", 5)) {
148
                port->iotype = UPIO_MEM;
149
                port->mapbase = simple_strtoul(options + 5, &options, 0);
150
#ifdef CONFIG_FIX_EARLYCON_MEM
151
                set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
152
                port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
153
                port->membase += port->mapbase & ~PAGE_MASK;
154
#else
155
                port->membase = ioremap(port->mapbase, 64);
156
                if (!port->membase) {
157
                        printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
158
                                __FUNCTION__,
159
                               (unsigned long long)port->mapbase);
160
                        return -ENOMEM;
161
                }
162
#endif
163
                mmio = 1;
164
        } else if (!strncmp(options, "io,", 3)) {
165
                port->iotype = UPIO_PORT;
166
                port->iobase = simple_strtoul(options + 3, &options, 0);
167
                mmio = 0;
168
        } else
169
                return -EINVAL;
170
 
171
        if ((options = strchr(options, ','))) {
172
                options++;
173
                device->baud = simple_strtoul(options, NULL, 0);
174
                length = min(strcspn(options, " "), sizeof(device->options));
175
                strncpy(device->options, options, length);
176
        } else {
177
                device->baud = probe_baud(port);
178
                snprintf(device->options, sizeof(device->options), "%u",
179
                        device->baud);
180
        }
181
 
182
        printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n",
183
                mmio ? "MMIO" : "I/O port",
184
                mmio ? (unsigned long long) port->mapbase
185
                     : (unsigned long long) port->iobase,
186
                device->options);
187
        return 0;
188
}
189
 
190
static struct console early_serial8250_console __initdata = {
191
        .name   = "uart",
192
        .write  = early_serial8250_write,
193
        .flags  = CON_PRINTBUFFER | CON_BOOT,
194
        .index  = -1,
195
};
196
 
197
static int __init early_serial8250_setup(char *options)
198
{
199
        struct early_serial8250_device *device = &early_device;
200
        int err;
201
 
202
        if (device->port.membase || device->port.iobase)
203
                return 0;
204
 
205
        if ((err = parse_options(device, options)) < 0)
206
                return err;
207
 
208
        init_port(device);
209
        return 0;
210
}
211
 
212
int __init setup_early_serial8250_console(char *cmdline)
213
{
214
        char *options;
215
        int err;
216
 
217
        options = strstr(cmdline, "uart8250,");
218
        if (!options) {
219
                options = strstr(cmdline, "uart,");
220
                if (!options)
221
                        return 0;
222
        }
223
 
224
        options = strchr(cmdline, ',') + 1;
225
        if ((err = early_serial8250_setup(options)) < 0)
226
                return err;
227
 
228
        register_console(&early_serial8250_console);
229
 
230
        return 0;
231
}
232
 
233
int serial8250_find_port_for_earlycon(void)
234
{
235
        struct early_serial8250_device *device = &early_device;
236
        struct uart_port *port = &device->port;
237
        int line;
238
        int ret;
239
 
240
        if (!device->port.membase && !device->port.iobase)
241
                return -ENODEV;
242
 
243
        line = serial8250_find_port(port);
244
        if (line < 0)
245
                return -ENODEV;
246
 
247
        ret = update_console_cmdline("uart", 8250,
248
                             "ttyS", line, device->options);
249
        if (ret < 0)
250
                ret = update_console_cmdline("uart", 0,
251
                                     "ttyS", line, device->options);
252
 
253
        return ret;
254
}
255
 
256
early_param("earlycon", setup_early_serial8250_console);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.