diff options
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r-- | drivers/serial/8250.c | 225 |
1 files changed, 165 insertions, 60 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 303272af386e..daa00567bc44 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -279,6 +279,13 @@ static const struct serial8250_config uart_config[] = { | |||
279 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 279 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
280 | .flags = UART_CAP_FIFO, | 280 | .flags = UART_CAP_FIFO, |
281 | }, | 281 | }, |
282 | [PORT_OCTEON] = { | ||
283 | .name = "OCTEON", | ||
284 | .fifo_size = 64, | ||
285 | .tx_loadsz = 64, | ||
286 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
287 | .flags = UART_CAP_FIFO, | ||
288 | }, | ||
282 | }; | 289 | }; |
283 | 290 | ||
284 | #if defined (CONFIG_SERIAL_8250_AU1X00) | 291 | #if defined (CONFIG_SERIAL_8250_AU1X00) |
@@ -303,16 +310,16 @@ static const u8 au_io_out_map[] = { | |||
303 | }; | 310 | }; |
304 | 311 | ||
305 | /* sane hardware needs no mapping */ | 312 | /* sane hardware needs no mapping */ |
306 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | 313 | static inline int map_8250_in_reg(struct uart_port *p, int offset) |
307 | { | 314 | { |
308 | if (up->port.iotype != UPIO_AU) | 315 | if (p->iotype != UPIO_AU) |
309 | return offset; | 316 | return offset; |
310 | return au_io_in_map[offset]; | 317 | return au_io_in_map[offset]; |
311 | } | 318 | } |
312 | 319 | ||
313 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | 320 | static inline int map_8250_out_reg(struct uart_port *p, int offset) |
314 | { | 321 | { |
315 | if (up->port.iotype != UPIO_AU) | 322 | if (p->iotype != UPIO_AU) |
316 | return offset; | 323 | return offset; |
317 | return au_io_out_map[offset]; | 324 | return au_io_out_map[offset]; |
318 | } | 325 | } |
@@ -341,16 +348,16 @@ static const u8 | |||
341 | [UART_SCR] = 0x2c | 348 | [UART_SCR] = 0x2c |
342 | }; | 349 | }; |
343 | 350 | ||
344 | static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) | 351 | static inline int map_8250_in_reg(struct uart_port *p, int offset) |
345 | { | 352 | { |
346 | if (up->port.iotype != UPIO_RM9000) | 353 | if (p->iotype != UPIO_RM9000) |
347 | return offset; | 354 | return offset; |
348 | return regmap_in[offset]; | 355 | return regmap_in[offset]; |
349 | } | 356 | } |
350 | 357 | ||
351 | static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | 358 | static inline int map_8250_out_reg(struct uart_port *p, int offset) |
352 | { | 359 | { |
353 | if (up->port.iotype != UPIO_RM9000) | 360 | if (p->iotype != UPIO_RM9000) |
354 | return offset; | 361 | return offset; |
355 | return regmap_out[offset]; | 362 | return regmap_out[offset]; |
356 | } | 363 | } |
@@ -363,108 +370,170 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) | |||
363 | 370 | ||
364 | #endif | 371 | #endif |
365 | 372 | ||
366 | static unsigned int serial_in(struct uart_8250_port *up, int offset) | 373 | static unsigned int hub6_serial_in(struct uart_port *p, int offset) |
367 | { | 374 | { |
368 | unsigned int tmp; | 375 | offset = map_8250_in_reg(p, offset) << p->regshift; |
369 | offset = map_8250_in_reg(up, offset) << up->port.regshift; | 376 | outb(p->hub6 - 1 + offset, p->iobase); |
377 | return inb(p->iobase + 1); | ||
378 | } | ||
370 | 379 | ||
371 | switch (up->port.iotype) { | 380 | static void hub6_serial_out(struct uart_port *p, int offset, int value) |
372 | case UPIO_HUB6: | 381 | { |
373 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 382 | offset = map_8250_out_reg(p, offset) << p->regshift; |
374 | return inb(up->port.iobase + 1); | 383 | outb(p->hub6 - 1 + offset, p->iobase); |
384 | outb(value, p->iobase + 1); | ||
385 | } | ||
375 | 386 | ||
376 | case UPIO_MEM: | 387 | static unsigned int mem_serial_in(struct uart_port *p, int offset) |
377 | case UPIO_DWAPB: | 388 | { |
378 | return readb(up->port.membase + offset); | 389 | offset = map_8250_in_reg(p, offset) << p->regshift; |
390 | return readb(p->membase + offset); | ||
391 | } | ||
379 | 392 | ||
380 | case UPIO_RM9000: | 393 | static void mem_serial_out(struct uart_port *p, int offset, int value) |
381 | case UPIO_MEM32: | 394 | { |
382 | return readl(up->port.membase + offset); | 395 | offset = map_8250_out_reg(p, offset) << p->regshift; |
396 | writeb(value, p->membase + offset); | ||
397 | } | ||
398 | |||
399 | static void mem32_serial_out(struct uart_port *p, int offset, int value) | ||
400 | { | ||
401 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
402 | writel(value, p->membase + offset); | ||
403 | } | ||
404 | |||
405 | static unsigned int mem32_serial_in(struct uart_port *p, int offset) | ||
406 | { | ||
407 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
408 | return readl(p->membase + offset); | ||
409 | } | ||
383 | 410 | ||
384 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 411 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
385 | case UPIO_AU: | 412 | static unsigned int au_serial_in(struct uart_port *p, int offset) |
386 | return __raw_readl(up->port.membase + offset); | 413 | { |
414 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
415 | return __raw_readl(p->membase + offset); | ||
416 | } | ||
417 | |||
418 | static void au_serial_out(struct uart_port *p, int offset, int value) | ||
419 | { | ||
420 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
421 | __raw_writel(value, p->membase + offset); | ||
422 | } | ||
387 | #endif | 423 | #endif |
388 | 424 | ||
389 | case UPIO_TSI: | 425 | static unsigned int tsi_serial_in(struct uart_port *p, int offset) |
390 | if (offset == UART_IIR) { | 426 | { |
391 | tmp = readl(up->port.membase + (UART_IIR & ~3)); | 427 | unsigned int tmp; |
392 | return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ | 428 | offset = map_8250_in_reg(p, offset) << p->regshift; |
393 | } else | 429 | if (offset == UART_IIR) { |
394 | return readb(up->port.membase + offset); | 430 | tmp = readl(p->membase + (UART_IIR & ~3)); |
431 | return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ | ||
432 | } else | ||
433 | return readb(p->membase + offset); | ||
434 | } | ||
395 | 435 | ||
396 | default: | 436 | static void tsi_serial_out(struct uart_port *p, int offset, int value) |
397 | return inb(up->port.iobase + offset); | 437 | { |
398 | } | 438 | offset = map_8250_out_reg(p, offset) << p->regshift; |
439 | if (!((offset == UART_IER) && (value & UART_IER_UUE))) | ||
440 | writeb(value, p->membase + offset); | ||
399 | } | 441 | } |
400 | 442 | ||
401 | static void | 443 | static void dwapb_serial_out(struct uart_port *p, int offset, int value) |
402 | serial_out(struct uart_8250_port *up, int offset, int value) | ||
403 | { | 444 | { |
404 | /* Save the offset before it's remapped */ | ||
405 | int save_offset = offset; | 445 | int save_offset = offset; |
406 | offset = map_8250_out_reg(up, offset) << up->port.regshift; | 446 | offset = map_8250_out_reg(p, offset) << p->regshift; |
447 | /* Save the LCR value so it can be re-written when a | ||
448 | * Busy Detect interrupt occurs. */ | ||
449 | if (save_offset == UART_LCR) { | ||
450 | struct uart_8250_port *up = (struct uart_8250_port *)p; | ||
451 | up->lcr = value; | ||
452 | } | ||
453 | writeb(value, p->membase + offset); | ||
454 | /* Read the IER to ensure any interrupt is cleared before | ||
455 | * returning from ISR. */ | ||
456 | if (save_offset == UART_TX || save_offset == UART_IER) | ||
457 | value = p->serial_in(p, UART_IER); | ||
458 | } | ||
407 | 459 | ||
408 | switch (up->port.iotype) { | 460 | static unsigned int io_serial_in(struct uart_port *p, int offset) |
461 | { | ||
462 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
463 | return inb(p->iobase + offset); | ||
464 | } | ||
465 | |||
466 | static void io_serial_out(struct uart_port *p, int offset, int value) | ||
467 | { | ||
468 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
469 | outb(value, p->iobase + offset); | ||
470 | } | ||
471 | |||
472 | static void set_io_from_upio(struct uart_port *p) | ||
473 | { | ||
474 | switch (p->iotype) { | ||
409 | case UPIO_HUB6: | 475 | case UPIO_HUB6: |
410 | outb(up->port.hub6 - 1 + offset, up->port.iobase); | 476 | p->serial_in = hub6_serial_in; |
411 | outb(value, up->port.iobase + 1); | 477 | p->serial_out = hub6_serial_out; |
412 | break; | 478 | break; |
413 | 479 | ||
414 | case UPIO_MEM: | 480 | case UPIO_MEM: |
415 | writeb(value, up->port.membase + offset); | 481 | p->serial_in = mem_serial_in; |
482 | p->serial_out = mem_serial_out; | ||
416 | break; | 483 | break; |
417 | 484 | ||
418 | case UPIO_RM9000: | 485 | case UPIO_RM9000: |
419 | case UPIO_MEM32: | 486 | case UPIO_MEM32: |
420 | writel(value, up->port.membase + offset); | 487 | p->serial_in = mem32_serial_in; |
488 | p->serial_out = mem32_serial_out; | ||
421 | break; | 489 | break; |
422 | 490 | ||
423 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 491 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
424 | case UPIO_AU: | 492 | case UPIO_AU: |
425 | __raw_writel(value, up->port.membase + offset); | 493 | p->serial_in = au_serial_in; |
494 | p->serial_out = au_serial_out; | ||
426 | break; | 495 | break; |
427 | #endif | 496 | #endif |
428 | case UPIO_TSI: | 497 | case UPIO_TSI: |
429 | if (!((offset == UART_IER) && (value & UART_IER_UUE))) | 498 | p->serial_in = tsi_serial_in; |
430 | writeb(value, up->port.membase + offset); | 499 | p->serial_out = tsi_serial_out; |
431 | break; | 500 | break; |
432 | 501 | ||
433 | case UPIO_DWAPB: | 502 | case UPIO_DWAPB: |
434 | /* Save the LCR value so it can be re-written when a | 503 | p->serial_in = mem_serial_in; |
435 | * Busy Detect interrupt occurs. */ | 504 | p->serial_out = dwapb_serial_out; |
436 | if (save_offset == UART_LCR) | ||
437 | up->lcr = value; | ||
438 | writeb(value, up->port.membase + offset); | ||
439 | /* Read the IER to ensure any interrupt is cleared before | ||
440 | * returning from ISR. */ | ||
441 | if (save_offset == UART_TX || save_offset == UART_IER) | ||
442 | value = serial_in(up, UART_IER); | ||
443 | break; | 505 | break; |
444 | 506 | ||
445 | default: | 507 | default: |
446 | outb(value, up->port.iobase + offset); | 508 | p->serial_in = io_serial_in; |
509 | p->serial_out = io_serial_out; | ||
510 | break; | ||
447 | } | 511 | } |
448 | } | 512 | } |
449 | 513 | ||
450 | static void | 514 | static void |
451 | serial_out_sync(struct uart_8250_port *up, int offset, int value) | 515 | serial_out_sync(struct uart_8250_port *up, int offset, int value) |
452 | { | 516 | { |
453 | switch (up->port.iotype) { | 517 | struct uart_port *p = &up->port; |
518 | switch (p->iotype) { | ||
454 | case UPIO_MEM: | 519 | case UPIO_MEM: |
455 | case UPIO_MEM32: | 520 | case UPIO_MEM32: |
456 | #ifdef CONFIG_SERIAL_8250_AU1X00 | 521 | #ifdef CONFIG_SERIAL_8250_AU1X00 |
457 | case UPIO_AU: | 522 | case UPIO_AU: |
458 | #endif | 523 | #endif |
459 | case UPIO_DWAPB: | 524 | case UPIO_DWAPB: |
460 | serial_out(up, offset, value); | 525 | p->serial_out(p, offset, value); |
461 | serial_in(up, UART_LCR); /* safe, no side-effects */ | 526 | p->serial_in(p, UART_LCR); /* safe, no side-effects */ |
462 | break; | 527 | break; |
463 | default: | 528 | default: |
464 | serial_out(up, offset, value); | 529 | p->serial_out(p, offset, value); |
465 | } | 530 | } |
466 | } | 531 | } |
467 | 532 | ||
533 | #define serial_in(up, offset) \ | ||
534 | (up->port.serial_in(&(up)->port, (offset))) | ||
535 | #define serial_out(up, offset, value) \ | ||
536 | (up->port.serial_out(&(up)->port, (offset), (value))) | ||
468 | /* | 537 | /* |
469 | * We used to support using pause I/O for certain machines. We | 538 | * We used to support using pause I/O for certain machines. We |
470 | * haven't supported this for a while, but just in case it's badly | 539 | * haven't supported this for a while, but just in case it's badly |
@@ -2576,6 +2645,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2576 | up->port.membase = old_serial_port[i].iomem_base; | 2645 | up->port.membase = old_serial_port[i].iomem_base; |
2577 | up->port.iotype = old_serial_port[i].io_type; | 2646 | up->port.iotype = old_serial_port[i].io_type; |
2578 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 2647 | up->port.regshift = old_serial_port[i].iomem_reg_shift; |
2648 | set_io_from_upio(&up->port); | ||
2579 | if (share_irqs) | 2649 | if (share_irqs) |
2580 | up->port.flags |= UPF_SHARE_IRQ; | 2650 | up->port.flags |= UPF_SHARE_IRQ; |
2581 | } | 2651 | } |
@@ -2752,12 +2822,30 @@ static struct uart_driver serial8250_reg = { | |||
2752 | */ | 2822 | */ |
2753 | int __init early_serial_setup(struct uart_port *port) | 2823 | int __init early_serial_setup(struct uart_port *port) |
2754 | { | 2824 | { |
2825 | struct uart_port *p; | ||
2826 | |||
2755 | if (port->line >= ARRAY_SIZE(serial8250_ports)) | 2827 | if (port->line >= ARRAY_SIZE(serial8250_ports)) |
2756 | return -ENODEV; | 2828 | return -ENODEV; |
2757 | 2829 | ||
2758 | serial8250_isa_init_ports(); | 2830 | serial8250_isa_init_ports(); |
2759 | serial8250_ports[port->line].port = *port; | 2831 | p = &serial8250_ports[port->line].port; |
2760 | serial8250_ports[port->line].port.ops = &serial8250_pops; | 2832 | p->iobase = port->iobase; |
2833 | p->membase = port->membase; | ||
2834 | p->irq = port->irq; | ||
2835 | p->uartclk = port->uartclk; | ||
2836 | p->fifosize = port->fifosize; | ||
2837 | p->regshift = port->regshift; | ||
2838 | p->iotype = port->iotype; | ||
2839 | p->flags = port->flags; | ||
2840 | p->mapbase = port->mapbase; | ||
2841 | p->private_data = port->private_data; | ||
2842 | |||
2843 | set_io_from_upio(p); | ||
2844 | if (port->serial_in) | ||
2845 | p->serial_in = port->serial_in; | ||
2846 | if (port->serial_out) | ||
2847 | p->serial_out = port->serial_out; | ||
2848 | |||
2761 | return 0; | 2849 | return 0; |
2762 | } | 2850 | } |
2763 | 2851 | ||
@@ -2822,6 +2910,9 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2822 | port.mapbase = p->mapbase; | 2910 | port.mapbase = p->mapbase; |
2823 | port.hub6 = p->hub6; | 2911 | port.hub6 = p->hub6; |
2824 | port.private_data = p->private_data; | 2912 | port.private_data = p->private_data; |
2913 | port.type = p->type; | ||
2914 | port.serial_in = p->serial_in; | ||
2915 | port.serial_out = p->serial_out; | ||
2825 | port.dev = &dev->dev; | 2916 | port.dev = &dev->dev; |
2826 | if (share_irqs) | 2917 | if (share_irqs) |
2827 | port.flags |= UPF_SHARE_IRQ; | 2918 | port.flags |= UPF_SHARE_IRQ; |
@@ -2976,6 +3067,20 @@ int serial8250_register_port(struct uart_port *port) | |||
2976 | if (port->dev) | 3067 | if (port->dev) |
2977 | uart->port.dev = port->dev; | 3068 | uart->port.dev = port->dev; |
2978 | 3069 | ||
3070 | if (port->flags & UPF_FIXED_TYPE) { | ||
3071 | uart->port.type = port->type; | ||
3072 | uart->port.fifosize = uart_config[port->type].fifo_size; | ||
3073 | uart->capabilities = uart_config[port->type].flags; | ||
3074 | uart->tx_loadsz = uart_config[port->type].tx_loadsz; | ||
3075 | } | ||
3076 | |||
3077 | set_io_from_upio(&uart->port); | ||
3078 | /* Possibly override default I/O functions. */ | ||
3079 | if (port->serial_in) | ||
3080 | uart->port.serial_in = port->serial_in; | ||
3081 | if (port->serial_out) | ||
3082 | uart->port.serial_out = port->serial_out; | ||
3083 | |||
2979 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 3084 | ret = uart_add_one_port(&serial8250_reg, &uart->port); |
2980 | if (ret == 0) | 3085 | if (ret == 0) |
2981 | ret = uart->port.line; | 3086 | ret = uart->port.line; |