]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/tty/serial/8250/8250_hp300.c
Merge branch 'depends/tty-omap-serial' into next/cleanup
[karo-tx-linux.git] / drivers / tty / serial / 8250 / 8250_hp300.c
1 /*
2  * Driver for the 98626/98644/internal serial interface on hp300/hp400
3  * (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
4  *
5  * Ported from 2.2 and modified to use the normal 8250 driver
6  * by Kars de Jong <jongk@linux-m68k.org>, May 2004.
7  */
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/string.h>
11 #include <linux/kernel.h>
12 #include <linux/serial.h>
13 #include <linux/serial_core.h>
14 #include <linux/serial_8250.h>
15 #include <linux/delay.h>
16 #include <linux/dio.h>
17 #include <linux/console.h>
18 #include <linux/slab.h>
19 #include <asm/io.h>
20
21 #include "8250.h"
22
23 #if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
24 #warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
25 #endif
26
27 #ifdef CONFIG_HPAPCI
28 struct hp300_port
29 {
30         struct hp300_port *next;        /* next port */
31         int line;                       /* line (tty) number */
32 };
33
34 static struct hp300_port *hp300_ports;
35 #endif
36
37 #ifdef CONFIG_HPDCA
38
39 static int __devinit hpdca_init_one(struct dio_dev *d,
40                                         const struct dio_device_id *ent);
41 static void __devexit hpdca_remove_one(struct dio_dev *d);
42
43 static struct dio_device_id hpdca_dio_tbl[] = {
44         { DIO_ID_DCA0 },
45         { DIO_ID_DCA0REM },
46         { DIO_ID_DCA1 },
47         { DIO_ID_DCA1REM },
48         { 0 }
49 };
50
51 static struct dio_driver hpdca_driver = {
52         .name      = "hpdca",
53         .id_table  = hpdca_dio_tbl,
54         .probe     = hpdca_init_one,
55         .remove    = __devexit_p(hpdca_remove_one),
56 };
57
58 #endif
59
60 static unsigned int num_ports;
61
62 extern int hp300_uart_scode;
63
64 /* Offset to UART registers from base of DCA */
65 #define UART_OFFSET     17
66
67 #define DCA_ID          0x01    /* ID (read), reset (write) */
68 #define DCA_IC          0x03    /* Interrupt control        */
69
70 /* Interrupt control */
71 #define DCA_IC_IE       0x80    /* Master interrupt enable  */
72
73 #define HPDCA_BAUD_BASE 153600
74
75 /* Base address of the Frodo part */
76 #define FRODO_BASE      (0x41c000)
77
78 /*
79  * Where we find the 8250-like APCI ports, and how far apart they are.
80  */
81 #define FRODO_APCIBASE          0x0
82 #define FRODO_APCISPACE         0x20
83 #define FRODO_APCI_OFFSET(x)    (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
84
85 #define HPAPCI_BAUD_BASE 500400
86
87 #ifdef CONFIG_SERIAL_8250_CONSOLE
88 /*
89  * Parse the bootinfo to find descriptions for headless console and
90  * debug serial ports and register them with the 8250 driver.
91  * This function should be called before serial_console_init() is called
92  * to make sure the serial console will be available for use. IA-64 kernel
93  * calls this function from setup_arch() after the EFI and ACPI tables have
94  * been parsed.
95  */
96 int __init hp300_setup_serial_console(void)
97 {
98         int scode;
99         struct uart_port port;
100
101         memset(&port, 0, sizeof(port));
102
103         if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
104                 return 0;
105
106         if (DIO_SCINHOLE(hp300_uart_scode))
107                 return 0;
108
109         scode = hp300_uart_scode;
110
111         /* Memory mapped I/O */
112         port.iotype = UPIO_MEM;
113         port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
114         port.type = PORT_UNKNOWN;
115
116         /* Check for APCI console */
117         if (scode == 256) {
118 #ifdef CONFIG_HPAPCI
119                 printk(KERN_INFO "Serial console is HP APCI 1\n");
120
121                 port.uartclk = HPAPCI_BAUD_BASE * 16;
122                 port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
123                 port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
124                 port.regshift = 2;
125                 add_preferred_console("ttyS", port.line, "9600n8");
126 #else
127                 printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
128                 return 0;
129 #endif
130         } else {
131 #ifdef CONFIG_HPDCA
132                 unsigned long pa = dio_scodetophysaddr(scode);
133                 if (!pa)
134                         return 0;
135
136                 printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
137
138                 port.uartclk = HPDCA_BAUD_BASE * 16;
139                 port.mapbase = (pa + UART_OFFSET);
140                 port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
141                 port.regshift = 1;
142                 port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
143
144                 /* Enable board-interrupts */
145                 out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
146
147                 if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80)
148                         add_preferred_console("ttyS", port.line, "9600n8");
149 #else
150                 printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
151                 return 0;
152 #endif
153         }
154
155         if (early_serial_setup(&port) < 0)
156                 printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
157         return 0;
158 }
159 #endif /* CONFIG_SERIAL_8250_CONSOLE */
160
161 #ifdef CONFIG_HPDCA
162 static int __devinit hpdca_init_one(struct dio_dev *d,
163                                 const struct dio_device_id *ent)
164 {
165         struct uart_port port;
166         int line;
167
168 #ifdef CONFIG_SERIAL_8250_CONSOLE
169         if (hp300_uart_scode == d->scode) {
170                 /* Already got it. */
171                 return 0;
172         }
173 #endif
174         memset(&uart, 0, sizeof(uart));
175
176         /* Memory mapped I/O */
177         port.iotype = UPIO_MEM;
178         port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
179         port.irq = d->ipl;
180         port.uartclk = HPDCA_BAUD_BASE * 16;
181         port.mapbase = (d->resource.start + UART_OFFSET);
182         port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
183         port.regshift = 1;
184         port.dev = &d->dev;
185         line = serial8250_register_8250_port(&uart);
186
187         if (line < 0) {
188                 printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
189                        " irq %d failed\n", d->scode, port.irq);
190                 return -ENOMEM;
191         }
192
193         /* Enable board-interrupts */
194         out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
195         dio_set_drvdata(d, (void *)line);
196
197         /* Reset the DCA */
198         out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
199         udelay(100);
200
201         num_ports++;
202
203         return 0;
204 }
205 #endif
206
207 static int __init hp300_8250_init(void)
208 {
209         static int called;
210 #ifdef CONFIG_HPAPCI
211         int line;
212         unsigned long base;
213         struct uart_8250_port uart;
214         struct hp300_port *port;
215         int i;
216 #endif
217         if (called)
218                 return -ENODEV;
219         called = 1;
220
221         if (!MACH_IS_HP300)
222                 return -ENODEV;
223
224 #ifdef CONFIG_HPDCA
225         dio_register_driver(&hpdca_driver);
226 #endif
227 #ifdef CONFIG_HPAPCI
228         if (hp300_model < HP_400) {
229                 if (!num_ports)
230                         return -ENODEV;
231                 return 0;
232         }
233         /* These models have the Frodo chip.
234          * Port 0 is reserved for the Apollo Domain keyboard.
235          * Port 1 is either the console or the DCA.
236          */
237         for (i = 1; i < 4; i++) {
238                 /* Port 1 is the console on a 425e, on other machines it's
239                  * mapped to DCA.
240                  */
241 #ifdef CONFIG_SERIAL_8250_CONSOLE
242                 if (i == 1)
243                         continue;
244 #endif
245
246                 /* Create new serial device */
247                 port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
248                 if (!port)
249                         return -ENOMEM;
250
251                 memset(&uart, 0, sizeof(uart));
252
253                 base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
254
255                 /* Memory mapped I/O */
256                 uart.port.iotype = UPIO_MEM;
257                 uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \
258                               | UPF_BOOT_AUTOCONF;
259                 /* XXX - no interrupt support yet */
260                 uart.port.irq = 0;
261                 uart.port.uartclk = HPAPCI_BAUD_BASE * 16;
262                 uart.port.mapbase = base;
263                 uart.port.membase = (char *)(base + DIO_VIRADDRBASE);
264                 uart.port.regshift = 2;
265
266                 line = serial8250_register_8250_port(&uart);
267
268                 if (line < 0) {
269                         printk(KERN_NOTICE "8250_hp300: register_serial() APCI"
270                                " %d irq %d failed\n", i, uart.port.irq);
271                         kfree(port);
272                         continue;
273                 }
274
275                 port->line = line;
276                 port->next = hp300_ports;
277                 hp300_ports = port;
278
279                 num_ports++;
280         }
281 #endif
282
283         /* Any boards found? */
284         if (!num_ports)
285                 return -ENODEV;
286
287         return 0;
288 }
289
290 #ifdef CONFIG_HPDCA
291 static void __devexit hpdca_remove_one(struct dio_dev *d)
292 {
293         int line;
294
295         line = (int) dio_get_drvdata(d);
296         if (d->resource.start) {
297                 /* Disable board-interrupts */
298                 out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
299         }
300         serial8250_unregister_port(line);
301 }
302 #endif
303
304 static void __exit hp300_8250_exit(void)
305 {
306 #ifdef CONFIG_HPAPCI
307         struct hp300_port *port, *to_free;
308
309         for (port = hp300_ports; port; ) {
310                 serial8250_unregister_port(port->line);
311                 to_free = port;
312                 port = port->next;
313                 kfree(to_free);
314         }
315
316         hp300_ports = NULL;
317 #endif
318 #ifdef CONFIG_HPDCA
319         dio_unregister_driver(&hpdca_driver);
320 #endif
321 }
322
323 module_init(hp300_8250_init);
324 module_exit(hp300_8250_exit);
325 MODULE_DESCRIPTION("HP DCA/APCI serial driver");
326 MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
327 MODULE_LICENSE("GPL");