ia64/linux-2.6.18-xen.hg

annotate drivers/serial/8250_hp300.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

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