diff options
Diffstat (limited to 'arch/mips/cavium-octeon/serial.c')
-rw-r--r-- | arch/mips/cavium-octeon/serial.c | 134 |
1 files changed, 53 insertions, 81 deletions
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c index 057f0ae88c99..138b2216b4f8 100644 --- a/arch/mips/cavium-octeon/serial.c +++ b/arch/mips/cavium-octeon/serial.c | |||
@@ -43,95 +43,67 @@ void octeon_serial_out(struct uart_port *up, int offset, int value) | |||
43 | cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); | 43 | cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); |
44 | } | 44 | } |
45 | 45 | ||
46 | /* | 46 | static int __devinit octeon_serial_probe(struct platform_device *pdev) |
47 | * Allocated in .bss, so it is all zeroed. | ||
48 | */ | ||
49 | #define OCTEON_MAX_UARTS 3 | ||
50 | static struct plat_serial8250_port octeon_uart8250_data[OCTEON_MAX_UARTS + 1]; | ||
51 | static struct platform_device octeon_uart8250_device = { | ||
52 | .name = "serial8250", | ||
53 | .id = PLAT8250_DEV_PLATFORM, | ||
54 | .dev = { | ||
55 | .platform_data = octeon_uart8250_data, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static void __init octeon_uart_set_common(struct plat_serial8250_port *p) | ||
60 | { | 47 | { |
61 | p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | 48 | int irq, res; |
62 | p->type = PORT_OCTEON; | 49 | struct resource *res_mem; |
63 | p->iotype = UPIO_MEM; | 50 | struct uart_port port; |
64 | p->regshift = 3; /* I/O addresses are every 8 bytes */ | 51 | |
52 | /* All adaptors have an irq. */ | ||
53 | irq = platform_get_irq(pdev, 0); | ||
54 | if (irq < 0) | ||
55 | return irq; | ||
56 | |||
57 | memset(&port, 0, sizeof(port)); | ||
58 | |||
59 | port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | ||
60 | port.type = PORT_OCTEON; | ||
61 | port.iotype = UPIO_MEM; | ||
62 | port.regshift = 3; | ||
63 | port.dev = &pdev->dev; | ||
64 | |||
65 | if (octeon_is_simulation()) | 65 | if (octeon_is_simulation()) |
66 | /* Make simulator output fast*/ | 66 | /* Make simulator output fast*/ |
67 | p->uartclk = 115200 * 16; | 67 | port.uartclk = 115200 * 16; |
68 | else | 68 | else |
69 | p->uartclk = octeon_get_io_clock_rate(); | 69 | port.uartclk = octeon_get_io_clock_rate(); |
70 | p->serial_in = octeon_serial_in; | ||
71 | p->serial_out = octeon_serial_out; | ||
72 | } | ||
73 | 70 | ||
74 | static int __init octeon_serial_init(void) | 71 | port.serial_in = octeon_serial_in; |
75 | { | 72 | port.serial_out = octeon_serial_out; |
76 | int enable_uart0; | 73 | port.irq = irq; |
77 | int enable_uart1; | ||
78 | int enable_uart2; | ||
79 | struct plat_serial8250_port *p; | ||
80 | |||
81 | #ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL | ||
82 | /* | ||
83 | * If we are configured to run as the second of two kernels, | ||
84 | * disable uart0 and enable uart1. Uart0 is owned by the first | ||
85 | * kernel | ||
86 | */ | ||
87 | enable_uart0 = 0; | ||
88 | enable_uart1 = 1; | ||
89 | #else | ||
90 | /* | ||
91 | * We are configured for the first kernel. We'll enable uart0 | ||
92 | * if the bootloader told us to use 0, otherwise will enable | ||
93 | * uart 1. | ||
94 | */ | ||
95 | enable_uart0 = (octeon_get_boot_uart() == 0); | ||
96 | enable_uart1 = (octeon_get_boot_uart() == 1); | ||
97 | #ifdef CONFIG_KGDB | ||
98 | enable_uart1 = 1; | ||
99 | #endif | ||
100 | #endif | ||
101 | |||
102 | /* Right now CN52XX is the only chip with a third uart */ | ||
103 | enable_uart2 = OCTEON_IS_MODEL(OCTEON_CN52XX); | ||
104 | |||
105 | p = octeon_uart8250_data; | ||
106 | if (enable_uart0) { | ||
107 | /* Add a ttyS device for hardware uart 0 */ | ||
108 | octeon_uart_set_common(p); | ||
109 | p->membase = (void *) CVMX_MIO_UARTX_RBR(0); | ||
110 | p->mapbase = CVMX_MIO_UARTX_RBR(0) & ((1ull << 49) - 1); | ||
111 | p->irq = OCTEON_IRQ_UART0; | ||
112 | p++; | ||
113 | } | ||
114 | 74 | ||
115 | if (enable_uart1) { | 75 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
116 | /* Add a ttyS device for hardware uart 1 */ | 76 | if (res_mem == NULL) { |
117 | octeon_uart_set_common(p); | 77 | dev_err(&pdev->dev, "found no memory resource\n"); |
118 | p->membase = (void *) CVMX_MIO_UARTX_RBR(1); | 78 | return -ENXIO; |
119 | p->mapbase = CVMX_MIO_UARTX_RBR(1) & ((1ull << 49) - 1); | ||
120 | p->irq = OCTEON_IRQ_UART1; | ||
121 | p++; | ||
122 | } | ||
123 | if (enable_uart2) { | ||
124 | /* Add a ttyS device for hardware uart 2 */ | ||
125 | octeon_uart_set_common(p); | ||
126 | p->membase = (void *) CVMX_MIO_UART2_RBR; | ||
127 | p->mapbase = CVMX_MIO_UART2_RBR & ((1ull << 49) - 1); | ||
128 | p->irq = OCTEON_IRQ_UART2; | ||
129 | p++; | ||
130 | } | 79 | } |
80 | port.mapbase = res_mem->start; | ||
81 | port.membase = ioremap(res_mem->start, resource_size(res_mem)); | ||
131 | 82 | ||
132 | BUG_ON(p > &octeon_uart8250_data[OCTEON_MAX_UARTS]); | 83 | res = serial8250_register_port(&port); |
133 | 84 | ||
134 | return platform_device_register(&octeon_uart8250_device); | 85 | return res >= 0 ? 0 : res; |
135 | } | 86 | } |
136 | 87 | ||
137 | device_initcall(octeon_serial_init); | 88 | static struct of_device_id octeon_serial_match[] = { |
89 | { | ||
90 | .compatible = "cavium,octeon-3860-uart", | ||
91 | }, | ||
92 | {}, | ||
93 | }; | ||
94 | MODULE_DEVICE_TABLE(of, octeon_serial_match); | ||
95 | |||
96 | static struct platform_driver octeon_serial_driver = { | ||
97 | .probe = octeon_serial_probe, | ||
98 | .driver = { | ||
99 | .owner = THIS_MODULE, | ||
100 | .name = "octeon_serial", | ||
101 | .of_match_table = octeon_serial_match, | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | static int __init octeon_serial_init(void) | ||
106 | { | ||
107 | return platform_driver_register(&octeon_serial_driver); | ||
108 | } | ||
109 | late_initcall(octeon_serial_init); | ||