2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2004-2007 Cavium Networks
8 #include <linux/console.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/platform_device.h>
12 #include <linux/serial.h>
13 #include <linux/serial_8250.h>
14 #include <linux/serial_reg.h>
15 #include <linux/tty.h>
16 #include <linux/irq.h>
20 #include <asm/octeon/octeon.h>
24 unsigned int octeon_serial_in(struct uart_port
*up
, int offset
)
26 int rv
= cvmx_read_csr((uint64_t)(up
->membase
+ (offset
<< 3)));
27 if (offset
== UART_IIR
&& (rv
& 0xf) == 7) {
28 /* Busy interrupt, read the USR (39) and try again. */
29 cvmx_read_csr((uint64_t)(up
->membase
+ (39 << 3)));
30 rv
= cvmx_read_csr((uint64_t)(up
->membase
+ (offset
<< 3)));
35 void octeon_serial_out(struct uart_port
*up
, int offset
, int value
)
38 * If bits 6 or 7 of the OCTEON UART's LCR are set, it quits
41 if (offset
== UART_LCR
)
43 cvmx_write_csr((uint64_t)(up
->membase
+ (offset
<< 3)), (u8
)value
);
46 static int __devinit
octeon_serial_probe(struct platform_device
*pdev
)
49 struct resource
*res_mem
;
50 struct uart_port port
;
52 /* All adaptors have an irq. */
53 irq
= platform_get_irq(pdev
, 0);
57 memset(&port
, 0, sizeof(port
));
59 port
.flags
= ASYNC_SKIP_TEST
| UPF_SHARE_IRQ
| UPF_FIXED_TYPE
;
60 port
.type
= PORT_OCTEON
;
61 port
.iotype
= UPIO_MEM
;
63 port
.dev
= &pdev
->dev
;
65 if (octeon_is_simulation())
66 /* Make simulator output fast*/
67 port
.uartclk
= 115200 * 16;
69 port
.uartclk
= octeon_get_io_clock_rate();
71 port
.serial_in
= octeon_serial_in
;
72 port
.serial_out
= octeon_serial_out
;
75 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
76 if (res_mem
== NULL
) {
77 dev_err(&pdev
->dev
, "found no memory resource\n");
80 port
.mapbase
= res_mem
->start
;
81 port
.membase
= ioremap(res_mem
->start
, resource_size(res_mem
));
83 res
= serial8250_register_port(&port
);
85 return res
>= 0 ? 0 : res
;
88 static struct of_device_id octeon_serial_match
[] = {
90 .compatible
= "cavium,octeon-3860-uart",
94 MODULE_DEVICE_TABLE(of
, octeon_serial_match
);
96 static struct platform_driver octeon_serial_driver
= {
97 .probe
= octeon_serial_probe
,
100 .name
= "octeon_serial",
101 .of_match_table
= octeon_serial_match
,
105 static int __init
octeon_serial_init(void)
107 return platform_driver_register(&octeon_serial_driver
);
109 late_initcall(octeon_serial_init
);