diff options
author | David S. Miller <davem@davemloft.net> | 2010-04-03 18:49:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-03 18:49:14 -0400 |
commit | 87e8b821ed8db3dab03d96cd542e29666bf210aa (patch) | |
tree | 0027060473aafbbb125655ba027319c8a1a665fc /drivers/serial | |
parent | 33cd9dfa3a13e3d8e41aef225a9f98169816723b (diff) | |
parent | 5e11611a5d22252f3f9c169a3c9377eac0c32033 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/serial')
27 files changed, 1452 insertions, 408 deletions
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index d935b2d04f93..ae0251ef6f4e 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -153,8 +153,6 @@ static int baud_table[] = { | |||
153 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 153 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
154 | 9600, 19200, 38400, 57600, 115200, 0 }; | 154 | 9600, 19200, 38400, 57600, 115200, 0 }; |
155 | 155 | ||
156 | #define BAUD_TABLE_SIZE (sizeof(baud_table)/sizeof(baud_table[0])) | ||
157 | |||
158 | /* Sets or clears DTR/RTS on the requested line */ | 156 | /* Sets or clears DTR/RTS on the requested line */ |
159 | static inline void m68k_rtsdtr(struct m68k_serial *ss, int set) | 157 | static inline void m68k_rtsdtr(struct m68k_serial *ss, int set) |
160 | { | 158 | { |
@@ -1406,10 +1404,10 @@ static void m68328_set_baud(void) | |||
1406 | USTCNT = ustcnt & ~USTCNT_TXEN; | 1404 | USTCNT = ustcnt & ~USTCNT_TXEN; |
1407 | 1405 | ||
1408 | again: | 1406 | again: |
1409 | for (i = 0; i < sizeof(baud_table) / sizeof(baud_table[0]); i++) | 1407 | for (i = 0; i < ARRAY_SIZE(baud_table); i++) |
1410 | if (baud_table[i] == m68328_console_baud) | 1408 | if (baud_table[i] == m68328_console_baud) |
1411 | break; | 1409 | break; |
1412 | if (i >= sizeof(baud_table) / sizeof(baud_table[0])) { | 1410 | if (i >= ARRAY_SIZE(baud_table)) { |
1413 | m68328_console_baud = 9600; | 1411 | m68328_console_baud = 9600; |
1414 | goto again; | 1412 | goto again; |
1415 | } | 1413 | } |
@@ -1435,7 +1433,7 @@ int m68328_console_setup(struct console *cp, char *arg) | |||
1435 | if (arg) | 1433 | if (arg) |
1436 | n = simple_strtoul(arg,NULL,0); | 1434 | n = simple_strtoul(arg,NULL,0); |
1437 | 1435 | ||
1438 | for (i = 0; i < BAUD_TABLE_SIZE; i++) | 1436 | for (i = 0; i < ARRAY_SIZE(baud_table); i++) |
1439 | if (baud_table[i] == n) | 1437 | if (baud_table[i] == n) |
1440 | break; | 1438 | break; |
1441 | if (i < BAUD_TABLE_SIZE) { | 1439 | if (i < BAUD_TABLE_SIZE) { |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index a81ff7bc5fa1..c3db16b7afa1 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2408,6 +2408,21 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2408 | } | 2408 | } |
2409 | 2409 | ||
2410 | static void | 2410 | static void |
2411 | serial8250_set_ldisc(struct uart_port *port) | ||
2412 | { | ||
2413 | int line = port->line; | ||
2414 | |||
2415 | if (line >= port->state->port.tty->driver->num) | ||
2416 | return; | ||
2417 | |||
2418 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
2419 | port->flags |= UPF_HARDPPS_CD; | ||
2420 | serial8250_enable_ms(port); | ||
2421 | } else | ||
2422 | port->flags &= ~UPF_HARDPPS_CD; | ||
2423 | } | ||
2424 | |||
2425 | static void | ||
2411 | serial8250_pm(struct uart_port *port, unsigned int state, | 2426 | serial8250_pm(struct uart_port *port, unsigned int state, |
2412 | unsigned int oldstate) | 2427 | unsigned int oldstate) |
2413 | { | 2428 | { |
@@ -2628,6 +2643,7 @@ static struct uart_ops serial8250_pops = { | |||
2628 | .startup = serial8250_startup, | 2643 | .startup = serial8250_startup, |
2629 | .shutdown = serial8250_shutdown, | 2644 | .shutdown = serial8250_shutdown, |
2630 | .set_termios = serial8250_set_termios, | 2645 | .set_termios = serial8250_set_termios, |
2646 | .set_ldisc = serial8250_set_ldisc, | ||
2631 | .pm = serial8250_pm, | 2647 | .pm = serial8250_pm, |
2632 | .type = serial8250_type, | 2648 | .type = serial8250_type, |
2633 | .release_port = serial8250_release_port, | 2649 | .release_port = serial8250_release_port, |
@@ -2690,6 +2706,15 @@ static void __init serial8250_isa_init_ports(void) | |||
2690 | } | 2706 | } |
2691 | } | 2707 | } |
2692 | 2708 | ||
2709 | static void | ||
2710 | serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type) | ||
2711 | { | ||
2712 | up->port.type = type; | ||
2713 | up->port.fifosize = uart_config[type].fifo_size; | ||
2714 | up->capabilities = uart_config[type].flags; | ||
2715 | up->tx_loadsz = uart_config[type].tx_loadsz; | ||
2716 | } | ||
2717 | |||
2693 | static void __init | 2718 | static void __init |
2694 | serial8250_register_ports(struct uart_driver *drv, struct device *dev) | 2719 | serial8250_register_ports(struct uart_driver *drv, struct device *dev) |
2695 | { | 2720 | { |
@@ -2706,6 +2731,10 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) | |||
2706 | struct uart_8250_port *up = &serial8250_ports[i]; | 2731 | struct uart_8250_port *up = &serial8250_ports[i]; |
2707 | 2732 | ||
2708 | up->port.dev = dev; | 2733 | up->port.dev = dev; |
2734 | |||
2735 | if (up->port.flags & UPF_FIXED_TYPE) | ||
2736 | serial8250_init_fixed_type_port(up, up->port.type); | ||
2737 | |||
2709 | uart_add_one_port(drv, &up->port); | 2738 | uart_add_one_port(drv, &up->port); |
2710 | } | 2739 | } |
2711 | } | 2740 | } |
@@ -3118,12 +3147,8 @@ int serial8250_register_port(struct uart_port *port) | |||
3118 | if (port->dev) | 3147 | if (port->dev) |
3119 | uart->port.dev = port->dev; | 3148 | uart->port.dev = port->dev; |
3120 | 3149 | ||
3121 | if (port->flags & UPF_FIXED_TYPE) { | 3150 | if (port->flags & UPF_FIXED_TYPE) |
3122 | uart->port.type = port->type; | 3151 | serial8250_init_fixed_type_port(uart, port->type); |
3123 | uart->port.fifosize = uart_config[port->type].fifo_size; | ||
3124 | uart->capabilities = uart_config[port->type].flags; | ||
3125 | uart->tx_loadsz = uart_config[port->type].tx_loadsz; | ||
3126 | } | ||
3127 | 3152 | ||
3128 | set_io_from_upio(&uart->port); | 3153 | set_io_from_upio(&uart->port); |
3129 | /* Possibly override default I/O functions. */ | 3154 | /* Possibly override default I/O functions. */ |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index b28af13c45a1..01c012da4e26 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -760,7 +760,8 @@ static int pci_netmos_init(struct pci_dev *dev) | |||
760 | /* subdevice 0x00PS means <P> parallel, <S> serial */ | 760 | /* subdevice 0x00PS means <P> parallel, <S> serial */ |
761 | unsigned int num_serial = dev->subsystem_device & 0xf; | 761 | unsigned int num_serial = dev->subsystem_device & 0xf; |
762 | 762 | ||
763 | if (dev->device == PCI_DEVICE_ID_NETMOS_9901) | 763 | if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) || |
764 | (dev->device == PCI_DEVICE_ID_NETMOS_9865)) | ||
764 | return 0; | 765 | return 0; |
765 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && | 766 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && |
766 | dev->subsystem_device == 0x0299) | 767 | dev->subsystem_device == 0x0299) |
@@ -1479,6 +1480,7 @@ enum pci_board_num_t { | |||
1479 | 1480 | ||
1480 | pbn_b0_bt_1_115200, | 1481 | pbn_b0_bt_1_115200, |
1481 | pbn_b0_bt_2_115200, | 1482 | pbn_b0_bt_2_115200, |
1483 | pbn_b0_bt_4_115200, | ||
1482 | pbn_b0_bt_8_115200, | 1484 | pbn_b0_bt_8_115200, |
1483 | 1485 | ||
1484 | pbn_b0_bt_1_460800, | 1486 | pbn_b0_bt_1_460800, |
@@ -1703,6 +1705,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { | |||
1703 | .base_baud = 115200, | 1705 | .base_baud = 115200, |
1704 | .uart_offset = 8, | 1706 | .uart_offset = 8, |
1705 | }, | 1707 | }, |
1708 | [pbn_b0_bt_4_115200] = { | ||
1709 | .flags = FL_BASE0|FL_BASE_BARS, | ||
1710 | .num_ports = 4, | ||
1711 | .base_baud = 115200, | ||
1712 | .uart_offset = 8, | ||
1713 | }, | ||
1706 | [pbn_b0_bt_8_115200] = { | 1714 | [pbn_b0_bt_8_115200] = { |
1707 | .flags = FL_BASE0|FL_BASE_BARS, | 1715 | .flags = FL_BASE0|FL_BASE_BARS, |
1708 | .num_ports = 8, | 1716 | .num_ports = 8, |
@@ -3191,6 +3199,15 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3191 | 0x1208, 0x0004, 0, 0, | 3199 | 0x1208, 0x0004, 0, 0, |
3192 | pbn_b0_4_921600 }, | 3200 | pbn_b0_4_921600 }, |
3193 | 3201 | ||
3202 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, | ||
3203 | 0x1204, 0x0004, 0, 0, | ||
3204 | pbn_b0_4_921600 }, | ||
3205 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, | ||
3206 | 0x1208, 0x0004, 0, 0, | ||
3207 | pbn_b0_4_921600 }, | ||
3208 | { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3, | ||
3209 | 0x1208, 0x0004, 0, 0, | ||
3210 | pbn_b0_4_921600 }, | ||
3194 | /* | 3211 | /* |
3195 | * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com | 3212 | * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com |
3196 | */ | 3213 | */ |
@@ -3649,6 +3666,18 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3649 | 0, 0, pbn_b0_1_115200 }, | 3666 | 0, 0, pbn_b0_1_115200 }, |
3650 | 3667 | ||
3651 | /* | 3668 | /* |
3669 | * Best Connectivity PCI Multi I/O cards | ||
3670 | */ | ||
3671 | |||
3672 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
3673 | 0xA000, 0x1000, | ||
3674 | 0, 0, pbn_b0_1_115200 }, | ||
3675 | |||
3676 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, | ||
3677 | 0xA000, 0x3004, | ||
3678 | 0, 0, pbn_b0_bt_4_115200 }, | ||
3679 | |||
3680 | /* | ||
3652 | * These entries match devices with class COMMUNICATION_SERIAL, | 3681 | * These entries match devices with class COMMUNICATION_SERIAL, |
3653 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL | 3682 | * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL |
3654 | */ | 3683 | */ |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 888a0ce91c4b..f55c49475a8c 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -447,7 +447,7 @@ config SERIAL_CLPS711X_CONSOLE | |||
447 | 447 | ||
448 | config SERIAL_SAMSUNG | 448 | config SERIAL_SAMSUNG |
449 | tristate "Samsung SoC serial support" | 449 | tristate "Samsung SoC serial support" |
450 | depends on ARM && PLAT_S3C | 450 | depends on ARM && PLAT_SAMSUNG |
451 | select SERIAL_CORE | 451 | select SERIAL_CORE |
452 | help | 452 | help |
453 | Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, | 453 | Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, |
@@ -455,11 +455,18 @@ config SERIAL_SAMSUNG | |||
455 | provide all of these ports, depending on how the serial port | 455 | provide all of these ports, depending on how the serial port |
456 | pins are configured. | 456 | pins are configured. |
457 | 457 | ||
458 | config SERIAL_SAMSUNG_UARTS_4 | ||
459 | bool | ||
460 | depends on ARM && PLAT_SAMSUNG | ||
461 | default y if CPU_S3C2443 | ||
462 | help | ||
463 | Internal node for the common case of 4 Samsung compatible UARTs | ||
464 | |||
458 | config SERIAL_SAMSUNG_UARTS | 465 | config SERIAL_SAMSUNG_UARTS |
459 | int | 466 | int |
460 | depends on ARM && PLAT_S3C | 467 | depends on ARM && PLAT_SAMSUNG |
461 | default 2 if ARCH_S3C2400 | 468 | default 2 if ARCH_S3C2400 |
462 | default 4 if ARCH_S5PC1XX || ARCH_S3C64XX || CPU_S3C2443 | 469 | default 4 if SERIAL_SAMSUNG_UARTS_4 |
463 | default 3 | 470 | default 3 |
464 | help | 471 | help |
465 | Select the number of available UART ports for the Samsung S3C | 472 | Select the number of available UART ports for the Samsung S3C |
@@ -526,20 +533,30 @@ config SERIAL_S3C24A0 | |||
526 | Serial port support for the Samsung S3C24A0 SoC | 533 | Serial port support for the Samsung S3C24A0 SoC |
527 | 534 | ||
528 | config SERIAL_S3C6400 | 535 | config SERIAL_S3C6400 |
529 | tristate "Samsung S3C6400/S3C6410 Serial port support" | 536 | tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support" |
530 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410) | 537 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440) |
538 | select SERIAL_SAMSUNG_UARTS_4 | ||
531 | default y | 539 | default y |
532 | help | 540 | help |
533 | Serial port support for the Samsung S3C6400 and S3C6410 | 541 | Serial port support for the Samsung S3C6400, S3C6410 and S5P6440 |
534 | SoCs | 542 | SoCs |
535 | 543 | ||
536 | config SERIAL_S5PC100 | 544 | config SERIAL_S5PC100 |
537 | tristate "Samsung S5PC100 Serial port support" | 545 | tristate "Samsung S5PC100 Serial port support" |
538 | depends on SERIAL_SAMSUNG && CPU_S5PC100 | 546 | depends on SERIAL_SAMSUNG && CPU_S5PC100 |
547 | select SERIAL_SAMSUNG_UARTS_4 | ||
539 | default y | 548 | default y |
540 | help | 549 | help |
541 | Serial port support for the Samsung S5PC100 SoCs | 550 | Serial port support for the Samsung S5PC100 SoCs |
542 | 551 | ||
552 | config SERIAL_S5PV210 | ||
553 | tristate "Samsung S5PV210 Serial port support" | ||
554 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) | ||
555 | select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210 | ||
556 | default y | ||
557 | help | ||
558 | Serial port support for Samsung's S5P Family of SoC's | ||
559 | |||
543 | config SERIAL_MAX3100 | 560 | config SERIAL_MAX3100 |
544 | tristate "MAX3100 support" | 561 | tristate "MAX3100 support" |
545 | depends on SPI | 562 | depends on SPI |
@@ -996,7 +1013,7 @@ config SERIAL_IP22_ZILOG_CONSOLE | |||
996 | 1013 | ||
997 | config SERIAL_SH_SCI | 1014 | config SERIAL_SH_SCI |
998 | tristate "SuperH SCI(F) serial port support" | 1015 | tristate "SuperH SCI(F) serial port support" |
999 | depends on HAVE_CLK && (SUPERH || H8300) | 1016 | depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE) |
1000 | select SERIAL_CORE | 1017 | select SERIAL_CORE |
1001 | 1018 | ||
1002 | config SERIAL_SH_SCI_NR_UARTS | 1019 | config SERIAL_SH_SCI_NR_UARTS |
@@ -1009,6 +1026,10 @@ config SERIAL_SH_SCI_CONSOLE | |||
1009 | depends on SERIAL_SH_SCI=y | 1026 | depends on SERIAL_SH_SCI=y |
1010 | select SERIAL_CORE_CONSOLE | 1027 | select SERIAL_CORE_CONSOLE |
1011 | 1028 | ||
1029 | config SERIAL_SH_SCI_DMA | ||
1030 | bool "DMA support" | ||
1031 | depends on SERIAL_SH_SCI && SH_DMAE && EXPERIMENTAL | ||
1032 | |||
1012 | config SERIAL_PNX8XXX | 1033 | config SERIAL_PNX8XXX |
1013 | bool "Enable PNX8XXX SoCs' UART Support" | 1034 | bool "Enable PNX8XXX SoCs' UART Support" |
1014 | depends on MIPS && (SOC_PNX8550 || SOC_PNX833X) | 1035 | depends on MIPS && (SOC_PNX8550 || SOC_PNX833X) |
@@ -1418,42 +1439,37 @@ config SERIAL_BFIN_SPORT | |||
1418 | To compile this driver as a module, choose M here: the | 1439 | To compile this driver as a module, choose M here: the |
1419 | module will be called bfin_sport_uart. | 1440 | module will be called bfin_sport_uart. |
1420 | 1441 | ||
1421 | choice | 1442 | config SERIAL_BFIN_SPORT_CONSOLE |
1422 | prompt "Baud rate for Blackfin SPORT UART" | 1443 | bool "Console on Blackfin sport emulated uart" |
1423 | depends on SERIAL_BFIN_SPORT | 1444 | depends on SERIAL_BFIN_SPORT=y |
1424 | default SERIAL_SPORT_BAUD_RATE_57600 | 1445 | select SERIAL_CORE_CONSOLE |
1425 | help | ||
1426 | Choose a baud rate for the SPORT UART, other uart settings are | ||
1427 | 8 bit, 1 stop bit, no parity, no flow control. | ||
1428 | |||
1429 | config SERIAL_SPORT_BAUD_RATE_115200 | ||
1430 | bool "115200" | ||
1431 | |||
1432 | config SERIAL_SPORT_BAUD_RATE_57600 | ||
1433 | bool "57600" | ||
1434 | 1446 | ||
1435 | config SERIAL_SPORT_BAUD_RATE_38400 | 1447 | config SERIAL_BFIN_SPORT0_UART |
1436 | bool "38400" | 1448 | bool "Enable UART over SPORT0" |
1449 | depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M) | ||
1450 | help | ||
1451 | Enable UART over SPORT0 | ||
1437 | 1452 | ||
1438 | config SERIAL_SPORT_BAUD_RATE_19200 | 1453 | config SERIAL_BFIN_SPORT1_UART |
1439 | bool "19200" | 1454 | bool "Enable UART over SPORT1" |
1455 | depends on SERIAL_BFIN_SPORT | ||
1456 | help | ||
1457 | Enable UART over SPORT1 | ||
1440 | 1458 | ||
1441 | config SERIAL_SPORT_BAUD_RATE_9600 | 1459 | config SERIAL_BFIN_SPORT2_UART |
1442 | bool "9600" | 1460 | bool "Enable UART over SPORT2" |
1443 | endchoice | 1461 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
1462 | help | ||
1463 | Enable UART over SPORT2 | ||
1444 | 1464 | ||
1445 | config SPORT_BAUD_RATE | 1465 | config SERIAL_BFIN_SPORT3_UART |
1446 | int | 1466 | bool "Enable UART over SPORT3" |
1447 | depends on SERIAL_BFIN_SPORT | 1467 | depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) |
1448 | default 115200 if (SERIAL_SPORT_BAUD_RATE_115200) | 1468 | help |
1449 | default 57600 if (SERIAL_SPORT_BAUD_RATE_57600) | 1469 | Enable UART over SPORT3 |
1450 | default 38400 if (SERIAL_SPORT_BAUD_RATE_38400) | ||
1451 | default 19200 if (SERIAL_SPORT_BAUD_RATE_19200) | ||
1452 | default 9600 if (SERIAL_SPORT_BAUD_RATE_9600) | ||
1453 | 1470 | ||
1454 | config SERIAL_TIMBERDALE | 1471 | config SERIAL_TIMBERDALE |
1455 | tristate "Support for timberdale UART" | 1472 | tristate "Support for timberdale UART" |
1456 | depends on MFD_TIMBERDALE | ||
1457 | select SERIAL_CORE | 1473 | select SERIAL_CORE |
1458 | ---help--- | 1474 | ---help--- |
1459 | Add support for UART controller on timberdale. | 1475 | Add support for UART controller on timberdale. |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 5548fe7df61d..6aa4723b74ee 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o | |||
45 | obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o | 45 | obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o |
46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o | 46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o |
47 | obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o | 47 | obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o |
48 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o | ||
48 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o | 49 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o |
49 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o | 50 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
50 | obj-$(CONFIG_SERIAL_MUX) += mux.o | 51 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 429a8ae86933..e4b3c2c88bb6 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -471,6 +471,20 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, | |||
471 | spin_unlock_irqrestore(&uap->port.lock, flags); | 471 | spin_unlock_irqrestore(&uap->port.lock, flags); |
472 | } | 472 | } |
473 | 473 | ||
474 | static void pl010_set_ldisc(struct uart_port *port) | ||
475 | { | ||
476 | int line = port->line; | ||
477 | |||
478 | if (line >= port->state->port.tty->driver->num) | ||
479 | return; | ||
480 | |||
481 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
482 | port->flags |= UPF_HARDPPS_CD; | ||
483 | pl010_enable_ms(port); | ||
484 | } else | ||
485 | port->flags &= ~UPF_HARDPPS_CD; | ||
486 | } | ||
487 | |||
474 | static const char *pl010_type(struct uart_port *port) | 488 | static const char *pl010_type(struct uart_port *port) |
475 | { | 489 | { |
476 | return port->type == PORT_AMBA ? "AMBA" : NULL; | 490 | return port->type == PORT_AMBA ? "AMBA" : NULL; |
@@ -531,6 +545,7 @@ static struct uart_ops amba_pl010_pops = { | |||
531 | .startup = pl010_startup, | 545 | .startup = pl010_startup, |
532 | .shutdown = pl010_shutdown, | 546 | .shutdown = pl010_shutdown, |
533 | .set_termios = pl010_set_termios, | 547 | .set_termios = pl010_set_termios, |
548 | .set_ldisc = pl010_set_ldisc, | ||
534 | .type = pl010_type, | 549 | .type = pl010_type, |
535 | .release_port = pl010_release_port, | 550 | .release_port = pl010_release_port, |
536 | .request_port = pl010_request_port, | 551 | .request_port = pl010_request_port, |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 9d948bccafaf..2c9bf9b68327 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -1213,6 +1213,24 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
1213 | return ret; | 1213 | return ret; |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | #ifdef CONFIG_CONSOLE_POLL | ||
1217 | static int atmel_poll_get_char(struct uart_port *port) | ||
1218 | { | ||
1219 | while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY)) | ||
1220 | cpu_relax(); | ||
1221 | |||
1222 | return UART_GET_CHAR(port); | ||
1223 | } | ||
1224 | |||
1225 | static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) | ||
1226 | { | ||
1227 | while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY)) | ||
1228 | cpu_relax(); | ||
1229 | |||
1230 | UART_PUT_CHAR(port, ch); | ||
1231 | } | ||
1232 | #endif | ||
1233 | |||
1216 | static struct uart_ops atmel_pops = { | 1234 | static struct uart_ops atmel_pops = { |
1217 | .tx_empty = atmel_tx_empty, | 1235 | .tx_empty = atmel_tx_empty, |
1218 | .set_mctrl = atmel_set_mctrl, | 1236 | .set_mctrl = atmel_set_mctrl, |
@@ -1232,6 +1250,10 @@ static struct uart_ops atmel_pops = { | |||
1232 | .config_port = atmel_config_port, | 1250 | .config_port = atmel_config_port, |
1233 | .verify_port = atmel_verify_port, | 1251 | .verify_port = atmel_verify_port, |
1234 | .pm = atmel_serial_pm, | 1252 | .pm = atmel_serial_pm, |
1253 | #ifdef CONFIG_CONSOLE_POLL | ||
1254 | .poll_get_char = atmel_poll_get_char, | ||
1255 | .poll_put_char = atmel_poll_put_char, | ||
1256 | #endif | ||
1235 | }; | 1257 | }; |
1236 | 1258 | ||
1237 | /* | 1259 | /* |
diff --git a/drivers/serial/bcm63xx_uart.c b/drivers/serial/bcm63xx_uart.c index 37ad0c449937..a1a0e55d0807 100644 --- a/drivers/serial/bcm63xx_uart.c +++ b/drivers/serial/bcm63xx_uart.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <bcm63xx_regs.h> | 35 | #include <bcm63xx_regs.h> |
36 | #include <bcm63xx_io.h> | 36 | #include <bcm63xx_io.h> |
37 | 37 | ||
38 | #define BCM63XX_NR_UARTS 1 | 38 | #define BCM63XX_NR_UARTS 2 |
39 | 39 | ||
40 | static struct uart_port ports[BCM63XX_NR_UARTS]; | 40 | static struct uart_port ports[BCM63XX_NR_UARTS]; |
41 | 41 | ||
@@ -784,7 +784,7 @@ static struct uart_driver bcm_uart_driver = { | |||
784 | .dev_name = "ttyS", | 784 | .dev_name = "ttyS", |
785 | .major = TTY_MAJOR, | 785 | .major = TTY_MAJOR, |
786 | .minor = 64, | 786 | .minor = 64, |
787 | .nr = 1, | 787 | .nr = BCM63XX_NR_UARTS, |
788 | .cons = BCM63XX_CONSOLE, | 788 | .cons = BCM63XX_CONSOLE, |
789 | }; | 789 | }; |
790 | 790 | ||
@@ -826,11 +826,12 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev) | |||
826 | port->dev = &pdev->dev; | 826 | port->dev = &pdev->dev; |
827 | port->fifosize = 16; | 827 | port->fifosize = 16; |
828 | port->uartclk = clk_get_rate(clk) / 2; | 828 | port->uartclk = clk_get_rate(clk) / 2; |
829 | port->line = pdev->id; | ||
829 | clk_put(clk); | 830 | clk_put(clk); |
830 | 831 | ||
831 | ret = uart_add_one_port(&bcm_uart_driver, port); | 832 | ret = uart_add_one_port(&bcm_uart_driver, port); |
832 | if (ret) { | 833 | if (ret) { |
833 | kfree(port); | 834 | ports[pdev->id].membase = 0; |
834 | return ret; | 835 | return ret; |
835 | } | 836 | } |
836 | platform_set_drvdata(pdev, port); | 837 | platform_set_drvdata(pdev, port); |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 50abb7e557f4..fcf273e3f48c 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
17 | #include <linux/io.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/console.h> | 19 | #include <linux/console.h> |
19 | #include <linux/sysrq.h> | 20 | #include <linux/sysrq.h> |
@@ -237,7 +238,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
237 | 238 | ||
238 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | 239 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
239 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | 240 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
240 | if (kgdb_connected && kgdboc_port_line == uart->port.line) | 241 | if (kgdb_connected && kgdboc_port_line == uart->port.line |
242 | && kgdboc_break_enabled) | ||
241 | if (ch == 0x3) {/* Ctrl + C */ | 243 | if (ch == 0x3) {/* Ctrl + C */ |
242 | kgdb_breakpoint(); | 244 | kgdb_breakpoint(); |
243 | return; | 245 | return; |
@@ -488,6 +490,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
488 | { | 490 | { |
489 | int x_pos, pos; | 491 | int x_pos, pos; |
490 | 492 | ||
493 | dma_disable_irq(uart->tx_dma_channel); | ||
491 | dma_disable_irq(uart->rx_dma_channel); | 494 | dma_disable_irq(uart->rx_dma_channel); |
492 | spin_lock_bh(&uart->port.lock); | 495 | spin_lock_bh(&uart->port.lock); |
493 | 496 | ||
@@ -521,6 +524,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
521 | } | 524 | } |
522 | 525 | ||
523 | spin_unlock_bh(&uart->port.lock); | 526 | spin_unlock_bh(&uart->port.lock); |
527 | dma_enable_irq(uart->tx_dma_channel); | ||
524 | dma_enable_irq(uart->rx_dma_channel); | 528 | dma_enable_irq(uart->rx_dma_channel); |
525 | 529 | ||
526 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); | 530 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); |
@@ -746,15 +750,6 @@ static int bfin_serial_startup(struct uart_port *port) | |||
746 | Status interrupt.\n"); | 750 | Status interrupt.\n"); |
747 | } | 751 | } |
748 | 752 | ||
749 | if (uart->cts_pin >= 0) { | ||
750 | gpio_request(uart->cts_pin, DRIVER_NAME); | ||
751 | gpio_direction_output(uart->cts_pin, 1); | ||
752 | } | ||
753 | if (uart->rts_pin >= 0) { | ||
754 | gpio_request(uart->rts_pin, DRIVER_NAME); | ||
755 | gpio_direction_output(uart->rts_pin, 0); | ||
756 | } | ||
757 | |||
758 | /* CTS RTS PINs are negative assertive. */ | 753 | /* CTS RTS PINs are negative assertive. */ |
759 | UART_PUT_MCR(uart, ACTS); | 754 | UART_PUT_MCR(uart, ACTS); |
760 | UART_SET_IER(uart, EDSSI); | 755 | UART_SET_IER(uart, EDSSI); |
@@ -801,10 +796,6 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
801 | gpio_free(uart->rts_pin); | 796 | gpio_free(uart->rts_pin); |
802 | #endif | 797 | #endif |
803 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 798 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
804 | if (uart->cts_pin >= 0) | ||
805 | gpio_free(uart->cts_pin); | ||
806 | if (uart->rts_pin >= 0) | ||
807 | gpio_free(uart->rts_pin); | ||
808 | if (UART_GET_IER(uart) && EDSSI) | 799 | if (UART_GET_IER(uart) && EDSSI) |
809 | free_irq(uart->status_irq, uart); | 800 | free_irq(uart->status_irq, uart); |
810 | #endif | 801 | #endif |
@@ -1409,8 +1400,7 @@ static int bfin_serial_remove(struct platform_device *dev) | |||
1409 | continue; | 1400 | continue; |
1410 | uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | 1401 | uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); |
1411 | bfin_serial_ports[i].port.dev = NULL; | 1402 | bfin_serial_ports[i].port.dev = NULL; |
1412 | #if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \ | 1403 | #if defined(CONFIG_SERIAL_BFIN_CTSRTS) |
1413 | defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS) | ||
1414 | gpio_free(bfin_serial_ports[i].cts_pin); | 1404 | gpio_free(bfin_serial_ports[i].cts_pin); |
1415 | gpio_free(bfin_serial_ports[i].rts_pin); | 1405 | gpio_free(bfin_serial_ports[i].rts_pin); |
1416 | #endif | 1406 | #endif |
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 088bb35475f1..7c72888fbf94 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
@@ -1,27 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * File: linux/drivers/serial/bfin_sport_uart.c | 2 | * Blackfin On-Chip Sport Emulated UART Driver |
3 | * | 3 | * |
4 | * Based on: drivers/serial/bfin_5xx.c by Aubrey Li. | 4 | * Copyright 2006-2009 Analog Devices Inc. |
5 | * Author: Roy Huang <roy.huang@analog.com> | ||
6 | * | 5 | * |
7 | * Created: Nov 22, 2006 | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * Copyright: (c) 2006-2007 Analog Devices Inc. | ||
9 | * Description: this driver enable SPORTs on Blackfin emulate UART. | ||
10 | * | 7 | * |
11 | * This program is free software; you can redistribute it and/or modify | 8 | * Licensed under the GPL-2 or later. |
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, see the file COPYING, or write | ||
23 | * to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
25 | */ | 9 | */ |
26 | 10 | ||
27 | /* | 11 | /* |
@@ -29,39 +13,18 @@ | |||
29 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf | 13 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf |
30 | * This application note describe how to implement a UART on a Sharc DSP, | 14 | * This application note describe how to implement a UART on a Sharc DSP, |
31 | * but this driver is implemented on Blackfin Processor. | 15 | * but this driver is implemented on Blackfin Processor. |
16 | * Transmit Frame Sync is not used by this driver to transfer data out. | ||
32 | */ | 17 | */ |
33 | 18 | ||
34 | /* After reset, there is a prelude of low level pulse when transmit data first | 19 | /* #define DEBUG */ |
35 | * time. No addtional pulse in following transmit. | ||
36 | * According to document: | ||
37 | * The SPORTs are ready to start transmitting or receiving data no later than | ||
38 | * three serial clock cycles after they are enabled in the SPORTx_TCR1 or | ||
39 | * SPORTx_RCR1 register. No serial clock cycles are lost from this point on. | ||
40 | * The first internal frame sync will occur one frame sync delay after the | ||
41 | * SPORTs are ready. External frame syncs can occur as soon as the SPORT is | ||
42 | * ready. | ||
43 | */ | ||
44 | 20 | ||
45 | /* Thanks to Axel Alatalo <axel@rubico.se> for fixing sport rx bug. Sometimes | 21 | #define DRV_NAME "bfin-sport-uart" |
46 | * sport receives data incorrectly. The following is Axel's words. | 22 | #define DEVICE_NAME "ttySS" |
47 | * As EE-191, sport rx samples 3 times of the UART baudrate and takes the | 23 | #define pr_fmt(fmt) DRV_NAME ": " fmt |
48 | * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting, | ||
49 | * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short | ||
50 | * byte due to buadrate drift, then the 30th sample of a byte, this sample is | ||
51 | * also the third sample of the stop bit, will happens on the immediately | ||
52 | * following start bit which will be thrown away and missed. Thus since parts | ||
53 | * of the startbit will be missed and the receiver will begin to drift, the | ||
54 | * effect accumulates over time until synchronization is lost. | ||
55 | * If only require 2 samples of the stopbit (by sampling in total 29 samples), | ||
56 | * then a to short byte as in the case above will be tolerated. Then the 1/3 | ||
57 | * early startbit will trigger a framesync since the last read is complete | ||
58 | * after only 2/3 stopbit and framesync is active during the last 1/3 looking | ||
59 | * for a possible early startbit. */ | ||
60 | |||
61 | //#define DEBUG | ||
62 | 24 | ||
63 | #include <linux/module.h> | 25 | #include <linux/module.h> |
64 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/io.h> | ||
65 | #include <linux/init.h> | 28 | #include <linux/init.h> |
66 | #include <linux/console.h> | 29 | #include <linux/console.h> |
67 | #include <linux/sysrq.h> | 30 | #include <linux/sysrq.h> |
@@ -75,23 +38,36 @@ | |||
75 | 38 | ||
76 | #include "bfin_sport_uart.h" | 39 | #include "bfin_sport_uart.h" |
77 | 40 | ||
41 | #ifdef CONFIG_SERIAL_BFIN_SPORT0_UART | ||
78 | unsigned short bfin_uart_pin_req_sport0[] = | 42 | unsigned short bfin_uart_pin_req_sport0[] = |
79 | {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ | 43 | {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \ |
80 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0}; | 44 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0}; |
81 | 45 | #endif | |
46 | #ifdef CONFIG_SERIAL_BFIN_SPORT1_UART | ||
82 | unsigned short bfin_uart_pin_req_sport1[] = | 47 | unsigned short bfin_uart_pin_req_sport1[] = |
83 | {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ | 48 | {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \ |
84 | P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0}; | 49 | P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0}; |
85 | 50 | #endif | |
86 | #define DRV_NAME "bfin-sport-uart" | 51 | #ifdef CONFIG_SERIAL_BFIN_SPORT2_UART |
52 | unsigned short bfin_uart_pin_req_sport2[] = | ||
53 | {P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \ | ||
54 | P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0}; | ||
55 | #endif | ||
56 | #ifdef CONFIG_SERIAL_BFIN_SPORT3_UART | ||
57 | unsigned short bfin_uart_pin_req_sport3[] = | ||
58 | {P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \ | ||
59 | P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0}; | ||
60 | #endif | ||
87 | 61 | ||
88 | struct sport_uart_port { | 62 | struct sport_uart_port { |
89 | struct uart_port port; | 63 | struct uart_port port; |
90 | char *name; | ||
91 | |||
92 | int tx_irq; | ||
93 | int rx_irq; | ||
94 | int err_irq; | 64 | int err_irq; |
65 | unsigned short csize; | ||
66 | unsigned short rxmask; | ||
67 | unsigned short txmask1; | ||
68 | unsigned short txmask2; | ||
69 | unsigned char stopb; | ||
70 | /* unsigned char parib; */ | ||
95 | }; | 71 | }; |
96 | 72 | ||
97 | static void sport_uart_tx_chars(struct sport_uart_port *up); | 73 | static void sport_uart_tx_chars(struct sport_uart_port *up); |
@@ -99,36 +75,42 @@ static void sport_stop_tx(struct uart_port *port); | |||
99 | 75 | ||
100 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | 76 | static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) |
101 | { | 77 | { |
102 | pr_debug("%s value:%x\n", __func__, value); | 78 | pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value, |
103 | /* Place a Start and Stop bit */ | 79 | up->txmask1, up->txmask2); |
80 | |||
81 | /* Place Start and Stop bits */ | ||
104 | __asm__ __volatile__ ( | 82 | __asm__ __volatile__ ( |
105 | "R2 = b#01111111100;" | 83 | "%[val] <<= 1;" |
106 | "R3 = b#10000000001;" | 84 | "%[val] = %[val] & %[mask1];" |
107 | "%0 <<= 2;" | 85 | "%[val] = %[val] | %[mask2];" |
108 | "%0 = %0 & R2;" | 86 | : [val]"+d"(value) |
109 | "%0 = %0 | R3;" | 87 | : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2) |
110 | : "=d"(value) | 88 | : "ASTAT" |
111 | : "d"(value) | ||
112 | : "ASTAT", "R2", "R3" | ||
113 | ); | 89 | ); |
114 | pr_debug("%s value:%x\n", __func__, value); | 90 | pr_debug("%s value:%x\n", __func__, value); |
115 | 91 | ||
116 | SPORT_PUT_TX(up, value); | 92 | SPORT_PUT_TX(up, value); |
117 | } | 93 | } |
118 | 94 | ||
119 | static inline unsigned int rx_one_byte(struct sport_uart_port *up) | 95 | static inline unsigned char rx_one_byte(struct sport_uart_port *up) |
120 | { | 96 | { |
121 | unsigned int value, extract; | 97 | unsigned int value; |
98 | unsigned char extract; | ||
122 | u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; | 99 | u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; |
123 | 100 | ||
124 | value = SPORT_GET_RX32(up); | 101 | if ((up->csize + up->stopb) > 7) |
125 | pr_debug("%s value:%x\n", __func__, value); | 102 | value = SPORT_GET_RX32(up); |
103 | else | ||
104 | value = SPORT_GET_RX(up); | ||
105 | |||
106 | pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value, | ||
107 | up->csize, up->rxmask); | ||
126 | 108 | ||
127 | /* Extract 8 bits data */ | 109 | /* Extract data */ |
128 | __asm__ __volatile__ ( | 110 | __asm__ __volatile__ ( |
129 | "%[extr] = 0;" | 111 | "%[extr] = 0;" |
130 | "%[mask1] = 0x1801(Z);" | 112 | "%[mask1] = %[rxmask];" |
131 | "%[mask2] = 0x0300(Z);" | 113 | "%[mask2] = 0x0200(Z);" |
132 | "%[shift] = 0;" | 114 | "%[shift] = 0;" |
133 | "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" | 115 | "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" |
134 | ".Lloop_s:" | 116 | ".Lloop_s:" |
@@ -138,9 +120,9 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up) | |||
138 | "%[mask1] = %[mask1] - %[mask2];" | 120 | "%[mask1] = %[mask1] - %[mask2];" |
139 | ".Lloop_e:" | 121 | ".Lloop_e:" |
140 | "%[shift] += 1;" | 122 | "%[shift] += 1;" |
141 | : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp), | 123 | : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp), |
142 | [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2) | 124 | [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2) |
143 | : "d"(value), [lc]"a"(8) | 125 | : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize) |
144 | : "ASTAT", "LB0", "LC0", "LT0" | 126 | : "ASTAT", "LB0", "LC0", "LT0" |
145 | ); | 127 | ); |
146 | 128 | ||
@@ -148,29 +130,28 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up) | |||
148 | return extract; | 130 | return extract; |
149 | } | 131 | } |
150 | 132 | ||
151 | static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) | 133 | static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) |
152 | { | 134 | { |
153 | int tclkdiv, tfsdiv, rclkdiv; | 135 | int tclkdiv, rclkdiv; |
136 | unsigned int sclk = get_sclk(); | ||
154 | 137 | ||
155 | /* Set TCR1 and TCR2 */ | 138 | /* Set TCR1 and TCR2, TFSR is not enabled for uart */ |
156 | SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); | 139 | SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK)); |
157 | SPORT_PUT_TCR2(up, 10); | 140 | SPORT_PUT_TCR2(up, size + 1); |
158 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); | 141 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); |
159 | 142 | ||
160 | /* Set RCR1 and RCR2 */ | 143 | /* Set RCR1 and RCR2 */ |
161 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); | 144 | SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); |
162 | SPORT_PUT_RCR2(up, 28); | 145 | SPORT_PUT_RCR2(up, (size + 1) * 2 - 1); |
163 | pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); | 146 | pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); |
164 | 147 | ||
165 | tclkdiv = sclk/(2 * baud_rate) - 1; | 148 | tclkdiv = sclk / (2 * baud_rate) - 1; |
166 | tfsdiv = 12; | 149 | rclkdiv = sclk / (2 * baud_rate * 2) - 1; |
167 | rclkdiv = sclk/(2 * baud_rate * 3) - 1; | ||
168 | SPORT_PUT_TCLKDIV(up, tclkdiv); | 150 | SPORT_PUT_TCLKDIV(up, tclkdiv); |
169 | SPORT_PUT_TFSDIV(up, tfsdiv); | ||
170 | SPORT_PUT_RCLKDIV(up, rclkdiv); | 151 | SPORT_PUT_RCLKDIV(up, rclkdiv); |
171 | SSYNC(); | 152 | SSYNC(); |
172 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n", | 153 | pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n", |
173 | __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv); | 154 | __func__, sclk, baud_rate, tclkdiv, rclkdiv); |
174 | 155 | ||
175 | return 0; | 156 | return 0; |
176 | } | 157 | } |
@@ -181,23 +162,29 @@ static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id) | |||
181 | struct tty_struct *tty = up->port.state->port.tty; | 162 | struct tty_struct *tty = up->port.state->port.tty; |
182 | unsigned int ch; | 163 | unsigned int ch; |
183 | 164 | ||
184 | do { | 165 | spin_lock(&up->port.lock); |
166 | |||
167 | while (SPORT_GET_STAT(up) & RXNE) { | ||
185 | ch = rx_one_byte(up); | 168 | ch = rx_one_byte(up); |
186 | up->port.icount.rx++; | 169 | up->port.icount.rx++; |
187 | 170 | ||
188 | if (uart_handle_sysrq_char(&up->port, ch)) | 171 | if (!uart_handle_sysrq_char(&up->port, ch)) |
189 | ; | ||
190 | else | ||
191 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | 172 | tty_insert_flip_char(tty, ch, TTY_NORMAL); |
192 | } while (SPORT_GET_STAT(up) & RXNE); | 173 | } |
193 | tty_flip_buffer_push(tty); | 174 | tty_flip_buffer_push(tty); |
194 | 175 | ||
176 | spin_unlock(&up->port.lock); | ||
177 | |||
195 | return IRQ_HANDLED; | 178 | return IRQ_HANDLED; |
196 | } | 179 | } |
197 | 180 | ||
198 | static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) | 181 | static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) |
199 | { | 182 | { |
200 | sport_uart_tx_chars(dev_id); | 183 | struct sport_uart_port *up = dev_id; |
184 | |||
185 | spin_lock(&up->port.lock); | ||
186 | sport_uart_tx_chars(up); | ||
187 | spin_unlock(&up->port.lock); | ||
201 | 188 | ||
202 | return IRQ_HANDLED; | 189 | return IRQ_HANDLED; |
203 | } | 190 | } |
@@ -208,6 +195,8 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
208 | struct tty_struct *tty = up->port.state->port.tty; | 195 | struct tty_struct *tty = up->port.state->port.tty; |
209 | unsigned int stat = SPORT_GET_STAT(up); | 196 | unsigned int stat = SPORT_GET_STAT(up); |
210 | 197 | ||
198 | spin_lock(&up->port.lock); | ||
199 | |||
211 | /* Overflow in RX FIFO */ | 200 | /* Overflow in RX FIFO */ |
212 | if (stat & ROVF) { | 201 | if (stat & ROVF) { |
213 | up->port.icount.overrun++; | 202 | up->port.icount.overrun++; |
@@ -216,15 +205,16 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
216 | } | 205 | } |
217 | /* These should not happen */ | 206 | /* These should not happen */ |
218 | if (stat & (TOVF | TUVF | RUVF)) { | 207 | if (stat & (TOVF | TUVF | RUVF)) { |
219 | printk(KERN_ERR "SPORT Error:%s %s %s\n", | 208 | pr_err("SPORT Error:%s %s %s\n", |
220 | (stat & TOVF)?"TX overflow":"", | 209 | (stat & TOVF) ? "TX overflow" : "", |
221 | (stat & TUVF)?"TX underflow":"", | 210 | (stat & TUVF) ? "TX underflow" : "", |
222 | (stat & RUVF)?"RX underflow":""); | 211 | (stat & RUVF) ? "RX underflow" : ""); |
223 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | 212 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); |
224 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); | 213 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); |
225 | } | 214 | } |
226 | SSYNC(); | 215 | SSYNC(); |
227 | 216 | ||
217 | spin_unlock(&up->port.lock); | ||
228 | return IRQ_HANDLED; | 218 | return IRQ_HANDLED; |
229 | } | 219 | } |
230 | 220 | ||
@@ -232,60 +222,37 @@ static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) | |||
232 | static int sport_startup(struct uart_port *port) | 222 | static int sport_startup(struct uart_port *port) |
233 | { | 223 | { |
234 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 224 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
235 | char buffer[20]; | 225 | int ret; |
236 | int retval; | ||
237 | 226 | ||
238 | pr_debug("%s enter\n", __func__); | 227 | pr_debug("%s enter\n", __func__); |
239 | snprintf(buffer, 20, "%s rx", up->name); | 228 | ret = request_irq(up->port.irq, sport_uart_rx_irq, 0, |
240 | retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 229 | "SPORT_UART_RX", up); |
241 | if (retval) { | 230 | if (ret) { |
242 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 231 | dev_err(port->dev, "unable to request SPORT RX interrupt\n"); |
243 | return retval; | 232 | return ret; |
244 | } | 233 | } |
245 | 234 | ||
246 | snprintf(buffer, 20, "%s tx", up->name); | 235 | ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0, |
247 | retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 236 | "SPORT_UART_TX", up); |
248 | if (retval) { | 237 | if (ret) { |
249 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 238 | dev_err(port->dev, "unable to request SPORT TX interrupt\n"); |
250 | goto fail1; | 239 | goto fail1; |
251 | } | 240 | } |
252 | 241 | ||
253 | snprintf(buffer, 20, "%s err", up->name); | 242 | ret = request_irq(up->err_irq, sport_uart_err_irq, 0, |
254 | retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up); | 243 | "SPORT_UART_STATUS", up); |
255 | if (retval) { | 244 | if (ret) { |
256 | printk(KERN_ERR "Unable to request interrupt %s\n", buffer); | 245 | dev_err(port->dev, "unable to request SPORT status interrupt\n"); |
257 | goto fail2; | 246 | goto fail2; |
258 | } | 247 | } |
259 | 248 | ||
260 | if (port->line) { | ||
261 | if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME)) | ||
262 | goto fail3; | ||
263 | } else { | ||
264 | if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME)) | ||
265 | goto fail3; | ||
266 | } | ||
267 | |||
268 | sport_uart_setup(up, get_sclk(), port->uartclk); | ||
269 | |||
270 | /* Enable receive interrupt */ | ||
271 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN)); | ||
272 | SSYNC(); | ||
273 | |||
274 | return 0; | 249 | return 0; |
250 | fail2: | ||
251 | free_irq(up->port.irq+1, up); | ||
252 | fail1: | ||
253 | free_irq(up->port.irq, up); | ||
275 | 254 | ||
276 | 255 | return ret; | |
277 | fail3: | ||
278 | printk(KERN_ERR DRV_NAME | ||
279 | ": Requesting Peripherals failed\n"); | ||
280 | |||
281 | free_irq(up->err_irq, up); | ||
282 | fail2: | ||
283 | free_irq(up->tx_irq, up); | ||
284 | fail1: | ||
285 | free_irq(up->rx_irq, up); | ||
286 | |||
287 | return retval; | ||
288 | |||
289 | } | 256 | } |
290 | 257 | ||
291 | static void sport_uart_tx_chars(struct sport_uart_port *up) | 258 | static void sport_uart_tx_chars(struct sport_uart_port *up) |
@@ -344,20 +311,17 @@ static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
344 | static void sport_stop_tx(struct uart_port *port) | 311 | static void sport_stop_tx(struct uart_port *port) |
345 | { | 312 | { |
346 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 313 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
347 | unsigned int stat; | ||
348 | 314 | ||
349 | pr_debug("%s enter\n", __func__); | 315 | pr_debug("%s enter\n", __func__); |
350 | 316 | ||
351 | stat = SPORT_GET_STAT(up); | ||
352 | while(!(stat & TXHRE)) { | ||
353 | udelay(1); | ||
354 | stat = SPORT_GET_STAT(up); | ||
355 | } | ||
356 | /* Although the hold register is empty, last byte is still in shift | 317 | /* Although the hold register is empty, last byte is still in shift |
357 | * register and not sent out yet. If baud rate is lower than default, | 318 | * register and not sent out yet. So, put a dummy data into TX FIFO. |
358 | * delay should be longer. For example, if the baud rate is 9600, | 319 | * Then, sport tx stops when last byte is shift out and the dummy |
359 | * the delay must be at least 2ms by experience */ | 320 | * data is moved into the shift register. |
360 | udelay(500); | 321 | */ |
322 | SPORT_PUT_TX(up, 0xffff); | ||
323 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
324 | cpu_relax(); | ||
361 | 325 | ||
362 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | 326 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); |
363 | SSYNC(); | 327 | SSYNC(); |
@@ -370,6 +334,7 @@ static void sport_start_tx(struct uart_port *port) | |||
370 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 334 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
371 | 335 | ||
372 | pr_debug("%s enter\n", __func__); | 336 | pr_debug("%s enter\n", __func__); |
337 | |||
373 | /* Write data into SPORT FIFO before enable SPROT to transmit */ | 338 | /* Write data into SPORT FIFO before enable SPROT to transmit */ |
374 | sport_uart_tx_chars(up); | 339 | sport_uart_tx_chars(up); |
375 | 340 | ||
@@ -403,37 +368,24 @@ static void sport_shutdown(struct uart_port *port) | |||
403 | { | 368 | { |
404 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 369 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
405 | 370 | ||
406 | pr_debug("%s enter\n", __func__); | 371 | dev_dbg(port->dev, "%s enter\n", __func__); |
407 | 372 | ||
408 | /* Disable sport */ | 373 | /* Disable sport */ |
409 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | 374 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); |
410 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); | 375 | SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); |
411 | SSYNC(); | 376 | SSYNC(); |
412 | 377 | ||
413 | if (port->line) { | 378 | free_irq(up->port.irq, up); |
414 | peripheral_free_list(bfin_uart_pin_req_sport1); | 379 | free_irq(up->port.irq+1, up); |
415 | } else { | ||
416 | peripheral_free_list(bfin_uart_pin_req_sport0); | ||
417 | } | ||
418 | |||
419 | free_irq(up->rx_irq, up); | ||
420 | free_irq(up->tx_irq, up); | ||
421 | free_irq(up->err_irq, up); | 380 | free_irq(up->err_irq, up); |
422 | } | 381 | } |
423 | 382 | ||
424 | static void sport_set_termios(struct uart_port *port, | ||
425 | struct ktermios *termios, struct ktermios *old) | ||
426 | { | ||
427 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); | ||
428 | uart_update_timeout(port, CS8 ,port->uartclk); | ||
429 | } | ||
430 | |||
431 | static const char *sport_type(struct uart_port *port) | 383 | static const char *sport_type(struct uart_port *port) |
432 | { | 384 | { |
433 | struct sport_uart_port *up = (struct sport_uart_port *)port; | 385 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
434 | 386 | ||
435 | pr_debug("%s enter\n", __func__); | 387 | pr_debug("%s enter\n", __func__); |
436 | return up->name; | 388 | return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL; |
437 | } | 389 | } |
438 | 390 | ||
439 | static void sport_release_port(struct uart_port *port) | 391 | static void sport_release_port(struct uart_port *port) |
@@ -461,6 +413,110 @@ static int sport_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
461 | return 0; | 413 | return 0; |
462 | } | 414 | } |
463 | 415 | ||
416 | static void sport_set_termios(struct uart_port *port, | ||
417 | struct ktermios *termios, struct ktermios *old) | ||
418 | { | ||
419 | struct sport_uart_port *up = (struct sport_uart_port *)port; | ||
420 | unsigned long flags; | ||
421 | int i; | ||
422 | |||
423 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); | ||
424 | |||
425 | switch (termios->c_cflag & CSIZE) { | ||
426 | case CS8: | ||
427 | up->csize = 8; | ||
428 | break; | ||
429 | case CS7: | ||
430 | up->csize = 7; | ||
431 | break; | ||
432 | case CS6: | ||
433 | up->csize = 6; | ||
434 | break; | ||
435 | case CS5: | ||
436 | up->csize = 5; | ||
437 | break; | ||
438 | default: | ||
439 | pr_warning("requested word length not supported\n"); | ||
440 | } | ||
441 | |||
442 | if (termios->c_cflag & CSTOPB) { | ||
443 | up->stopb = 1; | ||
444 | } | ||
445 | if (termios->c_cflag & PARENB) { | ||
446 | pr_warning("PAREN bits is not supported yet\n"); | ||
447 | /* up->parib = 1; */ | ||
448 | } | ||
449 | |||
450 | port->read_status_mask = OE; | ||
451 | if (termios->c_iflag & INPCK) | ||
452 | port->read_status_mask |= (FE | PE); | ||
453 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
454 | port->read_status_mask |= BI; | ||
455 | |||
456 | /* | ||
457 | * Characters to ignore | ||
458 | */ | ||
459 | port->ignore_status_mask = 0; | ||
460 | if (termios->c_iflag & IGNPAR) | ||
461 | port->ignore_status_mask |= FE | PE; | ||
462 | if (termios->c_iflag & IGNBRK) { | ||
463 | port->ignore_status_mask |= BI; | ||
464 | /* | ||
465 | * If we're ignoring parity and break indicators, | ||
466 | * ignore overruns too (for real raw support). | ||
467 | */ | ||
468 | if (termios->c_iflag & IGNPAR) | ||
469 | port->ignore_status_mask |= OE; | ||
470 | } | ||
471 | |||
472 | /* RX extract mask */ | ||
473 | up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8); | ||
474 | /* TX masks, 8 bit data and 1 bit stop for example: | ||
475 | * mask1 = b#0111111110 | ||
476 | * mask2 = b#1000000000 | ||
477 | */ | ||
478 | for (i = 0, up->txmask1 = 0; i < up->csize; i++) | ||
479 | up->txmask1 |= (1<<i); | ||
480 | up->txmask2 = (1<<i); | ||
481 | if (up->stopb) { | ||
482 | ++i; | ||
483 | up->txmask2 |= (1<<i); | ||
484 | } | ||
485 | up->txmask1 <<= 1; | ||
486 | up->txmask2 <<= 1; | ||
487 | /* uart baud rate */ | ||
488 | port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16); | ||
489 | |||
490 | spin_lock_irqsave(&up->port.lock, flags); | ||
491 | |||
492 | /* Disable UART */ | ||
493 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | ||
494 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); | ||
495 | |||
496 | sport_uart_setup(up, up->csize + up->stopb, port->uartclk); | ||
497 | |||
498 | /* driver TX line high after config, one dummy data is | ||
499 | * necessary to stop sport after shift one byte | ||
500 | */ | ||
501 | SPORT_PUT_TX(up, 0xffff); | ||
502 | SPORT_PUT_TX(up, 0xffff); | ||
503 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
504 | SSYNC(); | ||
505 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
506 | cpu_relax(); | ||
507 | SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); | ||
508 | SSYNC(); | ||
509 | |||
510 | /* Port speed changed, update the per-port timeout. */ | ||
511 | uart_update_timeout(port, termios->c_cflag, port->uartclk); | ||
512 | |||
513 | /* Enable sport rx */ | ||
514 | SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN); | ||
515 | SSYNC(); | ||
516 | |||
517 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
518 | } | ||
519 | |||
464 | struct uart_ops sport_uart_ops = { | 520 | struct uart_ops sport_uart_ops = { |
465 | .tx_empty = sport_tx_empty, | 521 | .tx_empty = sport_tx_empty, |
466 | .set_mctrl = sport_set_mctrl, | 522 | .set_mctrl = sport_set_mctrl, |
@@ -480,138 +536,319 @@ struct uart_ops sport_uart_ops = { | |||
480 | .verify_port = sport_verify_port, | 536 | .verify_port = sport_verify_port, |
481 | }; | 537 | }; |
482 | 538 | ||
483 | static struct sport_uart_port sport_uart_ports[] = { | 539 | #define BFIN_SPORT_UART_MAX_PORTS 4 |
484 | { /* SPORT 0 */ | 540 | |
485 | .name = "SPORT0", | 541 | static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS]; |
486 | .tx_irq = IRQ_SPORT0_TX, | 542 | |
487 | .rx_irq = IRQ_SPORT0_RX, | 543 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE |
488 | .err_irq= IRQ_SPORT0_ERROR, | 544 | static int __init |
489 | .port = { | 545 | sport_uart_console_setup(struct console *co, char *options) |
490 | .type = PORT_BFIN_SPORT, | 546 | { |
491 | .iotype = UPIO_MEM, | 547 | struct sport_uart_port *up; |
492 | .membase = (void __iomem *)SPORT0_TCR1, | 548 | int baud = 57600; |
493 | .mapbase = SPORT0_TCR1, | 549 | int bits = 8; |
494 | .irq = IRQ_SPORT0_RX, | 550 | int parity = 'n'; |
495 | .uartclk = CONFIG_SPORT_BAUD_RATE, | 551 | int flow = 'n'; |
496 | .fifosize = 8, | 552 | |
497 | .ops = &sport_uart_ops, | 553 | /* Check whether an invalid uart number has been specified */ |
498 | .line = 0, | 554 | if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS) |
499 | }, | 555 | return -ENODEV; |
500 | }, { /* SPORT 1 */ | 556 | |
501 | .name = "SPORT1", | 557 | up = bfin_sport_uart_ports[co->index]; |
502 | .tx_irq = IRQ_SPORT1_TX, | 558 | if (!up) |
503 | .rx_irq = IRQ_SPORT1_RX, | 559 | return -ENODEV; |
504 | .err_irq= IRQ_SPORT1_ERROR, | 560 | |
505 | .port = { | 561 | if (options) |
506 | .type = PORT_BFIN_SPORT, | 562 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
507 | .iotype = UPIO_MEM, | 563 | |
508 | .membase = (void __iomem *)SPORT1_TCR1, | 564 | return uart_set_options(&up->port, co, baud, parity, bits, flow); |
509 | .mapbase = SPORT1_TCR1, | 565 | } |
510 | .irq = IRQ_SPORT1_RX, | 566 | |
511 | .uartclk = CONFIG_SPORT_BAUD_RATE, | 567 | static void sport_uart_console_putchar(struct uart_port *port, int ch) |
512 | .fifosize = 8, | 568 | { |
513 | .ops = &sport_uart_ops, | 569 | struct sport_uart_port *up = (struct sport_uart_port *)port; |
514 | .line = 1, | 570 | |
515 | }, | 571 | while (SPORT_GET_STAT(up) & TXF) |
572 | barrier(); | ||
573 | |||
574 | tx_one_byte(up, ch); | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | * Interrupts are disabled on entering | ||
579 | */ | ||
580 | static void | ||
581 | sport_uart_console_write(struct console *co, const char *s, unsigned int count) | ||
582 | { | ||
583 | struct sport_uart_port *up = bfin_sport_uart_ports[co->index]; | ||
584 | unsigned long flags; | ||
585 | |||
586 | spin_lock_irqsave(&up->port.lock, flags); | ||
587 | |||
588 | if (SPORT_GET_TCR1(up) & TSPEN) | ||
589 | uart_console_write(&up->port, s, count, sport_uart_console_putchar); | ||
590 | else { | ||
591 | /* dummy data to start sport */ | ||
592 | while (SPORT_GET_STAT(up) & TXF) | ||
593 | barrier(); | ||
594 | SPORT_PUT_TX(up, 0xffff); | ||
595 | /* Enable transmit, then an interrupt will generated */ | ||
596 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); | ||
597 | SSYNC(); | ||
598 | |||
599 | uart_console_write(&up->port, s, count, sport_uart_console_putchar); | ||
600 | |||
601 | /* Although the hold register is empty, last byte is still in shift | ||
602 | * register and not sent out yet. So, put a dummy data into TX FIFO. | ||
603 | * Then, sport tx stops when last byte is shift out and the dummy | ||
604 | * data is moved into the shift register. | ||
605 | */ | ||
606 | while (SPORT_GET_STAT(up) & TXF) | ||
607 | barrier(); | ||
608 | SPORT_PUT_TX(up, 0xffff); | ||
609 | while (!(SPORT_GET_STAT(up) & TXHRE)) | ||
610 | barrier(); | ||
611 | |||
612 | /* Stop sport tx transfer */ | ||
613 | SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); | ||
614 | SSYNC(); | ||
516 | } | 615 | } |
616 | |||
617 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
618 | } | ||
619 | |||
620 | static struct uart_driver sport_uart_reg; | ||
621 | |||
622 | static struct console sport_uart_console = { | ||
623 | .name = DEVICE_NAME, | ||
624 | .write = sport_uart_console_write, | ||
625 | .device = uart_console_device, | ||
626 | .setup = sport_uart_console_setup, | ||
627 | .flags = CON_PRINTBUFFER, | ||
628 | .index = -1, | ||
629 | .data = &sport_uart_reg, | ||
517 | }; | 630 | }; |
518 | 631 | ||
632 | #define SPORT_UART_CONSOLE (&sport_uart_console) | ||
633 | #else | ||
634 | #define SPORT_UART_CONSOLE NULL | ||
635 | #endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */ | ||
636 | |||
637 | |||
519 | static struct uart_driver sport_uart_reg = { | 638 | static struct uart_driver sport_uart_reg = { |
520 | .owner = THIS_MODULE, | 639 | .owner = THIS_MODULE, |
521 | .driver_name = "SPORT-UART", | 640 | .driver_name = DRV_NAME, |
522 | .dev_name = "ttySS", | 641 | .dev_name = DEVICE_NAME, |
523 | .major = 204, | 642 | .major = 204, |
524 | .minor = 84, | 643 | .minor = 84, |
525 | .nr = ARRAY_SIZE(sport_uart_ports), | 644 | .nr = BFIN_SPORT_UART_MAX_PORTS, |
526 | .cons = NULL, | 645 | .cons = SPORT_UART_CONSOLE, |
527 | }; | 646 | }; |
528 | 647 | ||
529 | static int sport_uart_suspend(struct platform_device *dev, pm_message_t state) | 648 | #ifdef CONFIG_PM |
649 | static int sport_uart_suspend(struct device *dev) | ||
530 | { | 650 | { |
531 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 651 | struct sport_uart_port *sport = dev_get_drvdata(dev); |
532 | 652 | ||
533 | pr_debug("%s enter\n", __func__); | 653 | dev_dbg(dev, "%s enter\n", __func__); |
534 | if (sport) | 654 | if (sport) |
535 | uart_suspend_port(&sport_uart_reg, &sport->port); | 655 | uart_suspend_port(&sport_uart_reg, &sport->port); |
536 | 656 | ||
537 | return 0; | 657 | return 0; |
538 | } | 658 | } |
539 | 659 | ||
540 | static int sport_uart_resume(struct platform_device *dev) | 660 | static int sport_uart_resume(struct device *dev) |
541 | { | 661 | { |
542 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 662 | struct sport_uart_port *sport = dev_get_drvdata(dev); |
543 | 663 | ||
544 | pr_debug("%s enter\n", __func__); | 664 | dev_dbg(dev, "%s enter\n", __func__); |
545 | if (sport) | 665 | if (sport) |
546 | uart_resume_port(&sport_uart_reg, &sport->port); | 666 | uart_resume_port(&sport_uart_reg, &sport->port); |
547 | 667 | ||
548 | return 0; | 668 | return 0; |
549 | } | 669 | } |
550 | 670 | ||
551 | static int sport_uart_probe(struct platform_device *dev) | 671 | static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = { |
672 | .suspend = sport_uart_suspend, | ||
673 | .resume = sport_uart_resume, | ||
674 | }; | ||
675 | #endif | ||
676 | |||
677 | static int __devinit sport_uart_probe(struct platform_device *pdev) | ||
552 | { | 678 | { |
553 | pr_debug("%s enter\n", __func__); | 679 | struct resource *res; |
554 | sport_uart_ports[dev->id].port.dev = &dev->dev; | 680 | struct sport_uart_port *sport; |
555 | uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port); | 681 | int ret = 0; |
556 | platform_set_drvdata(dev, &sport_uart_ports[dev->id]); | ||
557 | 682 | ||
558 | return 0; | 683 | dev_dbg(&pdev->dev, "%s enter\n", __func__); |
684 | |||
685 | if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) { | ||
686 | dev_err(&pdev->dev, "Wrong sport uart platform device id.\n"); | ||
687 | return -ENOENT; | ||
688 | } | ||
689 | |||
690 | if (bfin_sport_uart_ports[pdev->id] == NULL) { | ||
691 | bfin_sport_uart_ports[pdev->id] = | ||
692 | kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL); | ||
693 | sport = bfin_sport_uart_ports[pdev->id]; | ||
694 | if (!sport) { | ||
695 | dev_err(&pdev->dev, | ||
696 | "Fail to kmalloc sport_uart_port\n"); | ||
697 | return -ENOMEM; | ||
698 | } | ||
699 | |||
700 | ret = peripheral_request_list( | ||
701 | (unsigned short *)pdev->dev.platform_data, DRV_NAME); | ||
702 | if (ret) { | ||
703 | dev_err(&pdev->dev, | ||
704 | "Fail to request SPORT peripherals\n"); | ||
705 | goto out_error_free_mem; | ||
706 | } | ||
707 | |||
708 | spin_lock_init(&sport->port.lock); | ||
709 | sport->port.fifosize = SPORT_TX_FIFO_SIZE, | ||
710 | sport->port.ops = &sport_uart_ops; | ||
711 | sport->port.line = pdev->id; | ||
712 | sport->port.iotype = UPIO_MEM; | ||
713 | sport->port.flags = UPF_BOOT_AUTOCONF; | ||
714 | |||
715 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
716 | if (res == NULL) { | ||
717 | dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); | ||
718 | ret = -ENOENT; | ||
719 | goto out_error_free_peripherals; | ||
720 | } | ||
721 | |||
722 | sport->port.membase = ioremap(res->start, | ||
723 | res->end - res->start); | ||
724 | if (!sport->port.membase) { | ||
725 | dev_err(&pdev->dev, "Cannot map sport IO\n"); | ||
726 | ret = -ENXIO; | ||
727 | goto out_error_free_peripherals; | ||
728 | } | ||
729 | |||
730 | sport->port.irq = platform_get_irq(pdev, 0); | ||
731 | if (sport->port.irq < 0) { | ||
732 | dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n"); | ||
733 | ret = -ENOENT; | ||
734 | goto out_error_unmap; | ||
735 | } | ||
736 | |||
737 | sport->err_irq = platform_get_irq(pdev, 1); | ||
738 | if (sport->err_irq < 0) { | ||
739 | dev_err(&pdev->dev, "No sport status IRQ specified\n"); | ||
740 | ret = -ENOENT; | ||
741 | goto out_error_unmap; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
746 | if (!is_early_platform_device(pdev)) { | ||
747 | #endif | ||
748 | sport = bfin_sport_uart_ports[pdev->id]; | ||
749 | sport->port.dev = &pdev->dev; | ||
750 | dev_set_drvdata(&pdev->dev, sport); | ||
751 | ret = uart_add_one_port(&sport_uart_reg, &sport->port); | ||
752 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
753 | } | ||
754 | #endif | ||
755 | if (!ret) | ||
756 | return 0; | ||
757 | |||
758 | if (sport) { | ||
759 | out_error_unmap: | ||
760 | iounmap(sport->port.membase); | ||
761 | out_error_free_peripherals: | ||
762 | peripheral_free_list( | ||
763 | (unsigned short *)pdev->dev.platform_data); | ||
764 | out_error_free_mem: | ||
765 | kfree(sport); | ||
766 | bfin_sport_uart_ports[pdev->id] = NULL; | ||
767 | } | ||
768 | |||
769 | return ret; | ||
559 | } | 770 | } |
560 | 771 | ||
561 | static int sport_uart_remove(struct platform_device *dev) | 772 | static int __devexit sport_uart_remove(struct platform_device *pdev) |
562 | { | 773 | { |
563 | struct sport_uart_port *sport = platform_get_drvdata(dev); | 774 | struct sport_uart_port *sport = platform_get_drvdata(pdev); |
564 | 775 | ||
565 | pr_debug("%s enter\n", __func__); | 776 | dev_dbg(&pdev->dev, "%s enter\n", __func__); |
566 | platform_set_drvdata(dev, NULL); | 777 | dev_set_drvdata(&pdev->dev, NULL); |
567 | 778 | ||
568 | if (sport) | 779 | if (sport) { |
569 | uart_remove_one_port(&sport_uart_reg, &sport->port); | 780 | uart_remove_one_port(&sport_uart_reg, &sport->port); |
781 | iounmap(sport->port.membase); | ||
782 | peripheral_free_list( | ||
783 | (unsigned short *)pdev->dev.platform_data); | ||
784 | kfree(sport); | ||
785 | bfin_sport_uart_ports[pdev->id] = NULL; | ||
786 | } | ||
570 | 787 | ||
571 | return 0; | 788 | return 0; |
572 | } | 789 | } |
573 | 790 | ||
574 | static struct platform_driver sport_uart_driver = { | 791 | static struct platform_driver sport_uart_driver = { |
575 | .probe = sport_uart_probe, | 792 | .probe = sport_uart_probe, |
576 | .remove = sport_uart_remove, | 793 | .remove = __devexit_p(sport_uart_remove), |
577 | .suspend = sport_uart_suspend, | ||
578 | .resume = sport_uart_resume, | ||
579 | .driver = { | 794 | .driver = { |
580 | .name = DRV_NAME, | 795 | .name = DRV_NAME, |
796 | #ifdef CONFIG_PM | ||
797 | .pm = &bfin_sport_uart_dev_pm_ops, | ||
798 | #endif | ||
581 | }, | 799 | }, |
582 | }; | 800 | }; |
583 | 801 | ||
802 | #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE | ||
803 | static __initdata struct early_platform_driver early_sport_uart_driver = { | ||
804 | .class_str = DRV_NAME, | ||
805 | .pdrv = &sport_uart_driver, | ||
806 | .requested_id = EARLY_PLATFORM_ID_UNSET, | ||
807 | }; | ||
808 | |||
809 | static int __init sport_uart_rs_console_init(void) | ||
810 | { | ||
811 | early_platform_driver_register(&early_sport_uart_driver, DRV_NAME); | ||
812 | |||
813 | early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0); | ||
814 | |||
815 | register_console(&sport_uart_console); | ||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | console_initcall(sport_uart_rs_console_init); | ||
820 | #endif | ||
821 | |||
584 | static int __init sport_uart_init(void) | 822 | static int __init sport_uart_init(void) |
585 | { | 823 | { |
586 | int ret; | 824 | int ret; |
587 | 825 | ||
588 | pr_debug("%s enter\n", __func__); | 826 | pr_info("Serial: Blackfin uart over sport driver\n"); |
827 | |||
589 | ret = uart_register_driver(&sport_uart_reg); | 828 | ret = uart_register_driver(&sport_uart_reg); |
590 | if (ret != 0) { | 829 | if (ret) { |
591 | printk(KERN_ERR "Failed to register %s:%d\n", | 830 | pr_err("failed to register %s:%d\n", |
592 | sport_uart_reg.driver_name, ret); | 831 | sport_uart_reg.driver_name, ret); |
593 | return ret; | 832 | return ret; |
594 | } | 833 | } |
595 | 834 | ||
596 | ret = platform_driver_register(&sport_uart_driver); | 835 | ret = platform_driver_register(&sport_uart_driver); |
597 | if (ret != 0) { | 836 | if (ret) { |
598 | printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret); | 837 | pr_err("failed to register sport uart driver:%d\n", ret); |
599 | uart_unregister_driver(&sport_uart_reg); | 838 | uart_unregister_driver(&sport_uart_reg); |
600 | } | 839 | } |
601 | 840 | ||
602 | |||
603 | pr_debug("%s exit\n", __func__); | ||
604 | return ret; | 841 | return ret; |
605 | } | 842 | } |
843 | module_init(sport_uart_init); | ||
606 | 844 | ||
607 | static void __exit sport_uart_exit(void) | 845 | static void __exit sport_uart_exit(void) |
608 | { | 846 | { |
609 | pr_debug("%s enter\n", __func__); | ||
610 | platform_driver_unregister(&sport_uart_driver); | 847 | platform_driver_unregister(&sport_uart_driver); |
611 | uart_unregister_driver(&sport_uart_reg); | 848 | uart_unregister_driver(&sport_uart_reg); |
612 | } | 849 | } |
613 | |||
614 | module_init(sport_uart_init); | ||
615 | module_exit(sport_uart_exit); | 850 | module_exit(sport_uart_exit); |
616 | 851 | ||
852 | MODULE_AUTHOR("Sonic Zhang, Roy Huang"); | ||
853 | MODULE_DESCRIPTION("Blackfin serial over SPORT driver"); | ||
617 | MODULE_LICENSE("GPL"); | 854 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h index 671d41cc1a3f..abe03614e4df 100644 --- a/drivers/serial/bfin_sport_uart.h +++ b/drivers/serial/bfin_sport_uart.h | |||
@@ -1,29 +1,23 @@ | |||
1 | /* | 1 | /* |
2 | * File: linux/drivers/serial/bfin_sport_uart.h | 2 | * Blackfin On-Chip Sport Emulated UART Driver |
3 | * | 3 | * |
4 | * Based on: include/asm-blackfin/mach-533/bfin_serial_5xx.h | 4 | * Copyright 2006-2008 Analog Devices Inc. |
5 | * Author: Roy Huang <roy.huang>analog.com> | ||
6 | * | 5 | * |
7 | * Created: Nov 22, 2006 | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
8 | * Copyright: (C) Analog Device Inc. | ||
9 | * Description: this driver enable SPORTs on Blackfin emulate UART. | ||
10 | * | 7 | * |
11 | * This program is free software; you can redistribute it and/or modify | 8 | * Licensed under the GPL-2 or later. |
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, see the file COPYING, or write | ||
23 | * to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
25 | */ | 9 | */ |
26 | 10 | ||
11 | /* | ||
12 | * This driver and the hardware supported are in term of EE-191 of ADI. | ||
13 | * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf | ||
14 | * This application note describe how to implement a UART on a Sharc DSP, | ||
15 | * but this driver is implemented on Blackfin Processor. | ||
16 | * Transmit Frame Sync is not used by this driver to transfer data out. | ||
17 | */ | ||
18 | |||
19 | #ifndef _BFIN_SPORT_UART_H | ||
20 | #define _BFIN_SPORT_UART_H | ||
27 | 21 | ||
28 | #define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */ | 22 | #define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */ |
29 | #define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */ | 23 | #define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */ |
@@ -61,3 +55,7 @@ | |||
61 | #define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v) | 55 | #define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v) |
62 | #define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v) | 56 | #define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v) |
63 | #define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v) | 57 | #define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v) |
58 | |||
59 | #define SPORT_TX_FIFO_SIZE 8 | ||
60 | |||
61 | #endif /* _BFIN_SPORT_UART_H */ | ||
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index a9802e76b5fa..722eac18f382 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -61,7 +61,7 @@ void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | |||
61 | void __iomem *pram; | 61 | void __iomem *pram; |
62 | unsigned long offset; | 62 | unsigned long offset; |
63 | struct resource res; | 63 | struct resource res; |
64 | unsigned long len; | 64 | resource_size_t len; |
65 | 65 | ||
66 | /* Don't remap parameter RAM if it has already been initialized | 66 | /* Don't remap parameter RAM if it has already been initialized |
67 | * during console setup. | 67 | * during console setup. |
@@ -74,7 +74,7 @@ void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | |||
74 | if (of_address_to_resource(np, 1, &res)) | 74 | if (of_address_to_resource(np, 1, &res)) |
75 | return NULL; | 75 | return NULL; |
76 | 76 | ||
77 | len = 1 + res.end - res.start; | 77 | len = resource_size(&res); |
78 | pram = ioremap(res.start, len); | 78 | pram = ioremap(res.start, len); |
79 | if (!pram) | 79 | if (!pram) |
80 | return NULL; | 80 | return NULL; |
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 0028b6f89ce6..53a468227056 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
@@ -751,7 +751,6 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port) | |||
751 | trace(icom_port, "FID_STATUS", status); | 751 | trace(icom_port, "FID_STATUS", status); |
752 | count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); | 752 | count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength); |
753 | 753 | ||
754 | count = tty_buffer_request_room(tty, count); | ||
755 | trace(icom_port, "RCV_COUNT", count); | 754 | trace(icom_port, "RCV_COUNT", count); |
756 | 755 | ||
757 | trace(icom_port, "REAL_COUNT", count); | 756 | trace(icom_port, "REAL_COUNT", count); |
@@ -1654,4 +1653,6 @@ MODULE_DESCRIPTION("IBM iSeries Serial IOA driver"); | |||
1654 | MODULE_SUPPORTED_DEVICE | 1653 | MODULE_SUPPORTED_DEVICE |
1655 | ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters"); | 1654 | ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters"); |
1656 | MODULE_LICENSE("GPL"); | 1655 | MODULE_LICENSE("GPL"); |
1657 | 1656 | MODULE_FIRMWARE("icom_call_setup.bin"); | |
1657 | MODULE_FIRMWARE("icom_res_dce.bin"); | ||
1658 | MODULE_FIRMWARE("icom_asc.bin"); | ||
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 60d665a17a88..e579d7a1807a 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -440,7 +440,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) | |||
440 | 440 | ||
441 | temp = readl(sport->port.membase + USR2); | 441 | temp = readl(sport->port.membase + USR2); |
442 | if (temp & USR2_BRCD) { | 442 | if (temp & USR2_BRCD) { |
443 | writel(temp | USR2_BRCD, sport->port.membase + USR2); | 443 | writel(USR2_BRCD, sport->port.membase + USR2); |
444 | if (uart_handle_break(&sport->port)) | 444 | if (uart_handle_break(&sport->port)) |
445 | continue; | 445 | continue; |
446 | } | 446 | } |
@@ -1279,7 +1279,7 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1279 | sport->use_irda = 1; | 1279 | sport->use_irda = 1; |
1280 | #endif | 1280 | #endif |
1281 | 1281 | ||
1282 | if (pdata->init) { | 1282 | if (pdata && pdata->init) { |
1283 | ret = pdata->init(pdev); | 1283 | ret = pdata->init(pdev); |
1284 | if (ret) | 1284 | if (ret) |
1285 | goto clkput; | 1285 | goto clkput; |
@@ -1292,7 +1292,7 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1292 | 1292 | ||
1293 | return 0; | 1293 | return 0; |
1294 | deinit: | 1294 | deinit: |
1295 | if (pdata->exit) | 1295 | if (pdata && pdata->exit) |
1296 | pdata->exit(pdev); | 1296 | pdata->exit(pdev); |
1297 | clkput: | 1297 | clkput: |
1298 | clk_put(sport->clk); | 1298 | clk_put(sport->clk); |
@@ -1321,7 +1321,7 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
1321 | 1321 | ||
1322 | clk_disable(sport->clk); | 1322 | clk_disable(sport->clk); |
1323 | 1323 | ||
1324 | if (pdata->exit) | 1324 | if (pdata && pdata->exit) |
1325 | pdata->exit(pdev); | 1325 | pdata->exit(pdev); |
1326 | 1326 | ||
1327 | iounmap(sport->port.membase); | 1327 | iounmap(sport->port.membase); |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 85dc0410ac1a..23ba6b40b3ac 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -1411,8 +1411,7 @@ static int receive_chars(struct uart_port *the_port) | |||
1411 | read_count = do_read(the_port, ch, MAX_CHARS); | 1411 | read_count = do_read(the_port, ch, MAX_CHARS); |
1412 | if (read_count > 0) { | 1412 | if (read_count > 0) { |
1413 | flip = 1; | 1413 | flip = 1; |
1414 | read_room = tty_buffer_request_room(tty, read_count); | 1414 | read_room = tty_insert_flip_string(tty, ch, read_count); |
1415 | tty_insert_flip_string(tty, ch, read_room); | ||
1416 | the_port->icount.rx += read_count; | 1415 | the_port->icount.rx += read_count; |
1417 | } | 1416 | } |
1418 | spin_unlock_irqrestore(&the_port->lock, pflags); | 1417 | spin_unlock_irqrestore(&the_port->lock, pflags); |
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 108c3e0471fd..12cb5e446a4f 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -179,6 +179,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
179 | 179 | ||
180 | return 0; | 180 | return 0; |
181 | out_free_irq: | 181 | out_free_irq: |
182 | jsm_remove_uart_port(brd); | ||
182 | free_irq(brd->irq, brd); | 183 | free_irq(brd->irq, brd); |
183 | out_iounmap: | 184 | out_iounmap: |
184 | iounmap(brd->re_map_membase); | 185 | iounmap(brd->re_map_membase); |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index cd95e215550d..5673ca9dfdc8 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -432,7 +432,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
432 | 432 | ||
433 | int jsm_uart_port_init(struct jsm_board *brd) | 433 | int jsm_uart_port_init(struct jsm_board *brd) |
434 | { | 434 | { |
435 | int i; | 435 | int i, rc; |
436 | unsigned int line; | 436 | unsigned int line; |
437 | struct jsm_channel *ch; | 437 | struct jsm_channel *ch; |
438 | 438 | ||
@@ -467,8 +467,11 @@ int jsm_uart_port_init(struct jsm_board *brd) | |||
467 | } else | 467 | } else |
468 | set_bit(line, linemap); | 468 | set_bit(line, linemap); |
469 | brd->channels[i]->uart_port.line = line; | 469 | brd->channels[i]->uart_port.line = line; |
470 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 470 | rc = uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port); |
471 | printk(KERN_INFO "jsm: add device failed\n"); | 471 | if (rc){ |
472 | printk(KERN_INFO "jsm: Port %d failed. Aborting...\n", i); | ||
473 | return rc; | ||
474 | } | ||
472 | else | 475 | else |
473 | printk(KERN_INFO "jsm: Port %d added\n", i); | 476 | printk(KERN_INFO "jsm: Port %d added\n", i); |
474 | } | 477 | } |
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c index b05c5aa02cb4..ecdc0facf7ee 100644 --- a/drivers/serial/msm_serial.c +++ b/drivers/serial/msm_serial.c | |||
@@ -691,6 +691,7 @@ static int __init msm_serial_probe(struct platform_device *pdev) | |||
691 | struct msm_port *msm_port; | 691 | struct msm_port *msm_port; |
692 | struct resource *resource; | 692 | struct resource *resource; |
693 | struct uart_port *port; | 693 | struct uart_port *port; |
694 | int irq; | ||
694 | 695 | ||
695 | if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) | 696 | if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) |
696 | return -ENXIO; | 697 | return -ENXIO; |
@@ -711,9 +712,10 @@ static int __init msm_serial_probe(struct platform_device *pdev) | |||
711 | return -ENXIO; | 712 | return -ENXIO; |
712 | port->mapbase = resource->start; | 713 | port->mapbase = resource->start; |
713 | 714 | ||
714 | port->irq = platform_get_irq(pdev, 0); | 715 | irq = platform_get_irq(pdev, 0); |
715 | if (unlikely(port->irq < 0)) | 716 | if (unlikely(irq < 0)) |
716 | return -ENXIO; | 717 | return -ENXIO; |
718 | port->irq = irq; | ||
717 | 719 | ||
718 | platform_set_drvdata(pdev, port); | 720 | platform_set_drvdata(pdev, port); |
719 | 721 | ||
diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c index ce75e28e36ef..1700b1a2fb7e 100644 --- a/drivers/serial/s3c2412.c +++ b/drivers/serial/s3c2412.c | |||
@@ -102,6 +102,7 @@ static struct s3c24xx_uart_info s3c2412_uart_inf = { | |||
102 | .name = "Samsung S3C2412 UART", | 102 | .name = "Samsung S3C2412 UART", |
103 | .type = PORT_S3C2412, | 103 | .type = PORT_S3C2412, |
104 | .fifosize = 64, | 104 | .fifosize = 64, |
105 | .has_divslot = 1, | ||
105 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, | 106 | .rx_fifomask = S3C2440_UFSTAT_RXMASK, |
106 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, | 107 | .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, |
107 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, | 108 | .rx_fifofull = S3C2440_UFSTAT_RXFULL, |
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c new file mode 100644 index 000000000000..8dc03837617b --- /dev/null +++ b/drivers/serial/s5pv210.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* linux/drivers/serial/s5pv210.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * Based on drivers/serial/s3c6400.c | ||
7 | * | ||
8 | * Driver for Samsung S5PV210 SoC UARTs. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/serial_core.h> | ||
21 | #include <linux/serial.h> | ||
22 | |||
23 | #include <asm/irq.h> | ||
24 | #include <mach/hardware.h> | ||
25 | #include <plat/regs-serial.h> | ||
26 | #include "samsung.h" | ||
27 | |||
28 | static int s5pv210_serial_setsource(struct uart_port *port, | ||
29 | struct s3c24xx_uart_clksrc *clk) | ||
30 | { | ||
31 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
32 | |||
33 | if (strcmp(clk->name, "pclk") == 0) | ||
34 | ucon &= ~S5PV210_UCON_CLKMASK; | ||
35 | else if (strcmp(clk->name, "uclk1") == 0) | ||
36 | ucon |= S5PV210_UCON_CLKMASK; | ||
37 | else { | ||
38 | printk(KERN_ERR "unknown clock source %s\n", clk->name); | ||
39 | return -EINVAL; | ||
40 | } | ||
41 | |||
42 | wr_regl(port, S3C2410_UCON, ucon); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | |||
47 | static int s5pv210_serial_getsource(struct uart_port *port, | ||
48 | struct s3c24xx_uart_clksrc *clk) | ||
49 | { | ||
50 | u32 ucon = rd_regl(port, S3C2410_UCON); | ||
51 | |||
52 | clk->divisor = 1; | ||
53 | |||
54 | switch (ucon & S5PV210_UCON_CLKMASK) { | ||
55 | case S5PV210_UCON_PCLK: | ||
56 | clk->name = "pclk"; | ||
57 | break; | ||
58 | case S5PV210_UCON_UCLK: | ||
59 | clk->name = "uclk1"; | ||
60 | break; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int s5pv210_serial_resetport(struct uart_port *port, | ||
67 | struct s3c2410_uartcfg *cfg) | ||
68 | { | ||
69 | unsigned long ucon = rd_regl(port, S3C2410_UCON); | ||
70 | |||
71 | ucon &= S5PV210_UCON_CLKMASK; | ||
72 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | ||
73 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
74 | |||
75 | /* reset both fifos */ | ||
76 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | ||
77 | wr_regl(port, S3C2410_UFCON, cfg->ufcon); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | #define S5PV210_UART_DEFAULT_INFO(fifo_size) \ | ||
83 | .name = "Samsung S5PV210 UART0", \ | ||
84 | .type = PORT_S3C6400, \ | ||
85 | .fifosize = fifo_size, \ | ||
86 | .has_divslot = 1, \ | ||
87 | .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ | ||
88 | .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ | ||
89 | .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ | ||
90 | .tx_fifofull = S5PV210_UFSTAT_TXFULL, \ | ||
91 | .tx_fifomask = S5PV210_UFSTAT_TXMASK, \ | ||
92 | .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \ | ||
93 | .get_clksrc = s5pv210_serial_getsource, \ | ||
94 | .set_clksrc = s5pv210_serial_setsource, \ | ||
95 | .reset_port = s5pv210_serial_resetport | ||
96 | |||
97 | static struct s3c24xx_uart_info s5p_port_fifo256 = { | ||
98 | S5PV210_UART_DEFAULT_INFO(256), | ||
99 | }; | ||
100 | |||
101 | static struct s3c24xx_uart_info s5p_port_fifo64 = { | ||
102 | S5PV210_UART_DEFAULT_INFO(64), | ||
103 | }; | ||
104 | |||
105 | static struct s3c24xx_uart_info s5p_port_fifo16 = { | ||
106 | S5PV210_UART_DEFAULT_INFO(16), | ||
107 | }; | ||
108 | |||
109 | static struct s3c24xx_uart_info *s5p_uart_inf[] = { | ||
110 | [0] = &s5p_port_fifo256, | ||
111 | [1] = &s5p_port_fifo64, | ||
112 | [2] = &s5p_port_fifo16, | ||
113 | [3] = &s5p_port_fifo16, | ||
114 | }; | ||
115 | |||
116 | /* device management */ | ||
117 | static int s5p_serial_probe(struct platform_device *pdev) | ||
118 | { | ||
119 | return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); | ||
120 | } | ||
121 | |||
122 | static struct platform_driver s5p_serial_drv = { | ||
123 | .probe = s5p_serial_probe, | ||
124 | .remove = __devexit_p(s3c24xx_serial_remove), | ||
125 | .driver = { | ||
126 | .name = "s5pv210-uart", | ||
127 | .owner = THIS_MODULE, | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | static int __init s5pv210_serial_console_init(void) | ||
132 | { | ||
133 | return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf); | ||
134 | } | ||
135 | |||
136 | console_initcall(s5pv210_serial_console_init); | ||
137 | |||
138 | static int __init s5p_serial_init(void) | ||
139 | { | ||
140 | return s3c24xx_serial_init(&s5p_serial_drv, *s5p_uart_inf); | ||
141 | } | ||
142 | |||
143 | static void __exit s5p_serial_exit(void) | ||
144 | { | ||
145 | platform_driver_unregister(&s5p_serial_drv); | ||
146 | } | ||
147 | |||
148 | module_init(s5p_serial_init); | ||
149 | module_exit(s5p_serial_exit); | ||
150 | |||
151 | MODULE_LICENSE("GPL"); | ||
152 | MODULE_ALIAS("platform:s5pv210-uart"); | ||
153 | MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support"); | ||
154 | MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); | ||
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index 52e3df113ec0..a9d6c5626a0a 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -1271,7 +1271,7 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) | |||
1271 | unsigned long ufstat, utrstat; | 1271 | unsigned long ufstat, utrstat; |
1272 | 1272 | ||
1273 | if (ufcon & S3C2410_UFCON_FIFOMODE) { | 1273 | if (ufcon & S3C2410_UFCON_FIFOMODE) { |
1274 | /* fifo mode - check ammount of data in fifo registers... */ | 1274 | /* fifo mode - check amount of data in fifo registers... */ |
1275 | 1275 | ||
1276 | ufstat = rd_regl(port, S3C2410_UFSTAT); | 1276 | ufstat = rd_regl(port, S3C2410_UFSTAT); |
1277 | return (ufstat & info->tx_fifofull) ? 0 : 1; | 1277 | return (ufstat & info->tx_fifofull) ? 0 : 1; |
@@ -1374,7 +1374,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, | |||
1374 | * data. | 1374 | * data. |
1375 | */ | 1375 | */ |
1376 | 1376 | ||
1377 | static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) | 1377 | static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info) |
1378 | { | 1378 | { |
1379 | struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; | 1379 | struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; |
1380 | struct platform_device **platdev_ptr; | 1380 | struct platform_device **platdev_ptr; |
@@ -1385,7 +1385,7 @@ static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info) | |||
1385 | platdev_ptr = s3c24xx_uart_devs; | 1385 | platdev_ptr = s3c24xx_uart_devs; |
1386 | 1386 | ||
1387 | for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { | 1387 | for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { |
1388 | s3c24xx_serial_init_port(ptr, info, *platdev_ptr); | 1388 | s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr); |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | return 0; | 1391 | return 0; |
@@ -1451,7 +1451,7 @@ static struct console s3c24xx_serial_console = { | |||
1451 | }; | 1451 | }; |
1452 | 1452 | ||
1453 | int s3c24xx_serial_initconsole(struct platform_driver *drv, | 1453 | int s3c24xx_serial_initconsole(struct platform_driver *drv, |
1454 | struct s3c24xx_uart_info *info) | 1454 | struct s3c24xx_uart_info **info) |
1455 | 1455 | ||
1456 | { | 1456 | { |
1457 | struct platform_device *dev = s3c24xx_uart_devs[0]; | 1457 | struct platform_device *dev = s3c24xx_uart_devs[0]; |
diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index 1fb22343df42..0ac06a07d25f 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h | |||
@@ -75,19 +75,24 @@ extern int s3c24xx_serial_probe(struct platform_device *dev, | |||
75 | extern int __devexit s3c24xx_serial_remove(struct platform_device *dev); | 75 | extern int __devexit s3c24xx_serial_remove(struct platform_device *dev); |
76 | 76 | ||
77 | extern int s3c24xx_serial_initconsole(struct platform_driver *drv, | 77 | extern int s3c24xx_serial_initconsole(struct platform_driver *drv, |
78 | struct s3c24xx_uart_info *uart); | 78 | struct s3c24xx_uart_info **uart); |
79 | 79 | ||
80 | extern int s3c24xx_serial_init(struct platform_driver *drv, | 80 | extern int s3c24xx_serial_init(struct platform_driver *drv, |
81 | struct s3c24xx_uart_info *info); | 81 | struct s3c24xx_uart_info *info); |
82 | 82 | ||
83 | #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE | 83 | #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE |
84 | 84 | ||
85 | #define s3c24xx_console_init(__drv, __inf) \ | 85 | #define s3c24xx_console_init(__drv, __inf) \ |
86 | static int __init s3c_serial_console_init(void) \ | 86 | static int __init s3c_serial_console_init(void) \ |
87 | { \ | 87 | { \ |
88 | return s3c24xx_serial_initconsole(__drv, __inf); \ | 88 | struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS]; \ |
89 | } \ | 89 | int i; \ |
90 | \ | 90 | \ |
91 | for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) \ | ||
92 | uinfo[i] = __inf; \ | ||
93 | return s3c24xx_serial_initconsole(__drv, uinfo); \ | ||
94 | } \ | ||
95 | \ | ||
91 | console_initcall(s3c_serial_console_init) | 96 | console_initcall(s3c_serial_console_init) |
92 | 97 | ||
93 | #else | 98 | #else |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index e91db4b38012..175d202ab37e 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -745,6 +745,7 @@ static struct pcmcia_device_id serial_ids[] = { | |||
745 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), | 745 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), |
746 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), | 746 | PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), |
747 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4), | 747 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4), |
748 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e), | ||
748 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), | 749 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), |
749 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), | 750 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), |
750 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), | 751 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 42f3333c4ad0..309de6be8204 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/ctype.h> | 48 | #include <linux/ctype.h> |
49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
51 | #include <linux/dmaengine.h> | ||
52 | #include <linux/scatterlist.h> | ||
51 | 53 | ||
52 | #ifdef CONFIG_SUPERH | 54 | #ifdef CONFIG_SUPERH |
53 | #include <asm/sh_bios.h> | 55 | #include <asm/sh_bios.h> |
@@ -84,6 +86,27 @@ struct sci_port { | |||
84 | struct clk *dclk; | 86 | struct clk *dclk; |
85 | 87 | ||
86 | struct list_head node; | 88 | struct list_head node; |
89 | struct dma_chan *chan_tx; | ||
90 | struct dma_chan *chan_rx; | ||
91 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
92 | struct device *dma_dev; | ||
93 | enum sh_dmae_slave_chan_id slave_tx; | ||
94 | enum sh_dmae_slave_chan_id slave_rx; | ||
95 | struct dma_async_tx_descriptor *desc_tx; | ||
96 | struct dma_async_tx_descriptor *desc_rx[2]; | ||
97 | dma_cookie_t cookie_tx; | ||
98 | dma_cookie_t cookie_rx[2]; | ||
99 | dma_cookie_t active_rx; | ||
100 | struct scatterlist sg_tx; | ||
101 | unsigned int sg_len_tx; | ||
102 | struct scatterlist sg_rx[2]; | ||
103 | size_t buf_len_rx; | ||
104 | struct sh_dmae_slave param_tx; | ||
105 | struct sh_dmae_slave param_rx; | ||
106 | struct work_struct work_tx; | ||
107 | struct work_struct work_rx; | ||
108 | struct timer_list rx_timer; | ||
109 | #endif | ||
87 | }; | 110 | }; |
88 | 111 | ||
89 | struct sh_sci_priv { | 112 | struct sh_sci_priv { |
@@ -269,29 +292,44 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) | |||
269 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | 292 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ |
270 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | 293 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ |
271 | defined(CONFIG_CPU_SUBTYPE_SH7786) | 294 | defined(CONFIG_CPU_SUBTYPE_SH7786) |
272 | static inline int scif_txroom(struct uart_port *port) | 295 | static int scif_txfill(struct uart_port *port) |
296 | { | ||
297 | return sci_in(port, SCTFDR) & 0xff; | ||
298 | } | ||
299 | |||
300 | static int scif_txroom(struct uart_port *port) | ||
273 | { | 301 | { |
274 | return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff); | 302 | return SCIF_TXROOM_MAX - scif_txfill(port); |
275 | } | 303 | } |
276 | 304 | ||
277 | static inline int scif_rxroom(struct uart_port *port) | 305 | static int scif_rxfill(struct uart_port *port) |
278 | { | 306 | { |
279 | return sci_in(port, SCRFDR) & 0xff; | 307 | return sci_in(port, SCRFDR) & 0xff; |
280 | } | 308 | } |
281 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) | 309 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) |
282 | static inline int scif_txroom(struct uart_port *port) | 310 | static int scif_txfill(struct uart_port *port) |
283 | { | 311 | { |
284 | if ((port->mapbase == 0xffe00000) || | 312 | if (port->mapbase == 0xffe00000 || |
285 | (port->mapbase == 0xffe08000)) { | 313 | port->mapbase == 0xffe08000) |
286 | /* SCIF0/1*/ | 314 | /* SCIF0/1*/ |
287 | return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff); | 315 | return sci_in(port, SCTFDR) & 0xff; |
288 | } else { | 316 | else |
289 | /* SCIF2 */ | 317 | /* SCIF2 */ |
290 | return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8); | 318 | return sci_in(port, SCFDR) >> 8; |
291 | } | ||
292 | } | 319 | } |
293 | 320 | ||
294 | static inline int scif_rxroom(struct uart_port *port) | 321 | static int scif_txroom(struct uart_port *port) |
322 | { | ||
323 | if (port->mapbase == 0xffe00000 || | ||
324 | port->mapbase == 0xffe08000) | ||
325 | /* SCIF0/1*/ | ||
326 | return SCIF_TXROOM_MAX - scif_txfill(port); | ||
327 | else | ||
328 | /* SCIF2 */ | ||
329 | return SCIF2_TXROOM_MAX - scif_txfill(port); | ||
330 | } | ||
331 | |||
332 | static int scif_rxfill(struct uart_port *port) | ||
295 | { | 333 | { |
296 | if ((port->mapbase == 0xffe00000) || | 334 | if ((port->mapbase == 0xffe00000) || |
297 | (port->mapbase == 0xffe08000)) { | 335 | (port->mapbase == 0xffe08000)) { |
@@ -303,23 +341,33 @@ static inline int scif_rxroom(struct uart_port *port) | |||
303 | } | 341 | } |
304 | } | 342 | } |
305 | #else | 343 | #else |
306 | static inline int scif_txroom(struct uart_port *port) | 344 | static int scif_txfill(struct uart_port *port) |
345 | { | ||
346 | return sci_in(port, SCFDR) >> 8; | ||
347 | } | ||
348 | |||
349 | static int scif_txroom(struct uart_port *port) | ||
307 | { | 350 | { |
308 | return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8); | 351 | return SCIF_TXROOM_MAX - scif_txfill(port); |
309 | } | 352 | } |
310 | 353 | ||
311 | static inline int scif_rxroom(struct uart_port *port) | 354 | static int scif_rxfill(struct uart_port *port) |
312 | { | 355 | { |
313 | return sci_in(port, SCFDR) & SCIF_RFDC_MASK; | 356 | return sci_in(port, SCFDR) & SCIF_RFDC_MASK; |
314 | } | 357 | } |
315 | #endif | 358 | #endif |
316 | 359 | ||
317 | static inline int sci_txroom(struct uart_port *port) | 360 | static int sci_txfill(struct uart_port *port) |
361 | { | ||
362 | return !(sci_in(port, SCxSR) & SCI_TDRE); | ||
363 | } | ||
364 | |||
365 | static int sci_txroom(struct uart_port *port) | ||
318 | { | 366 | { |
319 | return (sci_in(port, SCxSR) & SCI_TDRE) != 0; | 367 | return !sci_txfill(port); |
320 | } | 368 | } |
321 | 369 | ||
322 | static inline int sci_rxroom(struct uart_port *port) | 370 | static int sci_rxfill(struct uart_port *port) |
323 | { | 371 | { |
324 | return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; | 372 | return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0; |
325 | } | 373 | } |
@@ -406,9 +454,9 @@ static inline void sci_receive_chars(struct uart_port *port) | |||
406 | 454 | ||
407 | while (1) { | 455 | while (1) { |
408 | if (port->type == PORT_SCI) | 456 | if (port->type == PORT_SCI) |
409 | count = sci_rxroom(port); | 457 | count = sci_rxfill(port); |
410 | else | 458 | else |
411 | count = scif_rxroom(port); | 459 | count = scif_rxfill(port); |
412 | 460 | ||
413 | /* Don't copy more bytes than there is room for in the buffer */ | 461 | /* Don't copy more bytes than there is room for in the buffer */ |
414 | count = tty_buffer_request_room(tty, count); | 462 | count = tty_buffer_request_room(tty, count); |
@@ -453,10 +501,10 @@ static inline void sci_receive_chars(struct uart_port *port) | |||
453 | } | 501 | } |
454 | 502 | ||
455 | /* Store data and status */ | 503 | /* Store data and status */ |
456 | if (status&SCxSR_FER(port)) { | 504 | if (status & SCxSR_FER(port)) { |
457 | flag = TTY_FRAME; | 505 | flag = TTY_FRAME; |
458 | dev_notice(port->dev, "frame error\n"); | 506 | dev_notice(port->dev, "frame error\n"); |
459 | } else if (status&SCxSR_PER(port)) { | 507 | } else if (status & SCxSR_PER(port)) { |
460 | flag = TTY_PARITY; | 508 | flag = TTY_PARITY; |
461 | dev_notice(port->dev, "parity error\n"); | 509 | dev_notice(port->dev, "parity error\n"); |
462 | } else | 510 | } else |
@@ -618,13 +666,39 @@ static inline int sci_handle_breaks(struct uart_port *port) | |||
618 | return copied; | 666 | return copied; |
619 | } | 667 | } |
620 | 668 | ||
621 | static irqreturn_t sci_rx_interrupt(int irq, void *port) | 669 | static irqreturn_t sci_rx_interrupt(int irq, void *ptr) |
622 | { | 670 | { |
671 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
672 | struct uart_port *port = ptr; | ||
673 | struct sci_port *s = to_sci_port(port); | ||
674 | |||
675 | if (s->chan_rx) { | ||
676 | unsigned long tout; | ||
677 | u16 scr = sci_in(port, SCSCR); | ||
678 | u16 ssr = sci_in(port, SCxSR); | ||
679 | |||
680 | /* Disable future Rx interrupts */ | ||
681 | sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE); | ||
682 | /* Clear current interrupt */ | ||
683 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); | ||
684 | /* Calculate delay for 1.5 DMA buffers */ | ||
685 | tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | ||
686 | port->fifosize / 2; | ||
687 | dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n", | ||
688 | tout * 1000 / HZ); | ||
689 | if (tout < 2) | ||
690 | tout = 2; | ||
691 | mod_timer(&s->rx_timer, jiffies + tout); | ||
692 | |||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | #endif | ||
696 | |||
623 | /* I think sci_receive_chars has to be called irrespective | 697 | /* I think sci_receive_chars has to be called irrespective |
624 | * of whether the I_IXOFF is set, otherwise, how is the interrupt | 698 | * of whether the I_IXOFF is set, otherwise, how is the interrupt |
625 | * to be disabled? | 699 | * to be disabled? |
626 | */ | 700 | */ |
627 | sci_receive_chars(port); | 701 | sci_receive_chars(ptr); |
628 | 702 | ||
629 | return IRQ_HANDLED; | 703 | return IRQ_HANDLED; |
630 | } | 704 | } |
@@ -680,6 +754,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
680 | { | 754 | { |
681 | unsigned short ssr_status, scr_status, err_enabled; | 755 | unsigned short ssr_status, scr_status, err_enabled; |
682 | struct uart_port *port = ptr; | 756 | struct uart_port *port = ptr; |
757 | struct sci_port *s = to_sci_port(port); | ||
683 | irqreturn_t ret = IRQ_NONE; | 758 | irqreturn_t ret = IRQ_NONE; |
684 | 759 | ||
685 | ssr_status = sci_in(port, SCxSR); | 760 | ssr_status = sci_in(port, SCxSR); |
@@ -687,10 +762,15 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
687 | err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); | 762 | err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); |
688 | 763 | ||
689 | /* Tx Interrupt */ | 764 | /* Tx Interrupt */ |
690 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE)) | 765 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) && |
766 | !s->chan_tx) | ||
691 | ret = sci_tx_interrupt(irq, ptr); | 767 | ret = sci_tx_interrupt(irq, ptr); |
692 | /* Rx Interrupt */ | 768 | /* |
693 | if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE)) | 769 | * Rx Interrupt: if we're using DMA, the DMA controller clears RDF / |
770 | * DR flags | ||
771 | */ | ||
772 | if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) && | ||
773 | (scr_status & SCI_CTRL_FLAGS_RIE)) | ||
694 | ret = sci_rx_interrupt(irq, ptr); | 774 | ret = sci_rx_interrupt(irq, ptr); |
695 | /* Error Interrupt */ | 775 | /* Error Interrupt */ |
696 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) | 776 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) |
@@ -800,7 +880,9 @@ static void sci_free_irq(struct sci_port *port) | |||
800 | static unsigned int sci_tx_empty(struct uart_port *port) | 880 | static unsigned int sci_tx_empty(struct uart_port *port) |
801 | { | 881 | { |
802 | unsigned short status = sci_in(port, SCxSR); | 882 | unsigned short status = sci_in(port, SCxSR); |
803 | return status & SCxSR_TEND(port) ? TIOCSER_TEMT : 0; | 883 | unsigned short in_tx_fifo = scif_txfill(port); |
884 | |||
885 | return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; | ||
804 | } | 886 | } |
805 | 887 | ||
806 | static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) | 888 | static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) |
@@ -812,16 +894,297 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
812 | 894 | ||
813 | static unsigned int sci_get_mctrl(struct uart_port *port) | 895 | static unsigned int sci_get_mctrl(struct uart_port *port) |
814 | { | 896 | { |
815 | /* This routine is used for geting signals of: DTR, DCD, DSR, RI, | 897 | /* This routine is used for getting signals of: DTR, DCD, DSR, RI, |
816 | and CTS/RTS */ | 898 | and CTS/RTS */ |
817 | 899 | ||
818 | return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; | 900 | return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; |
819 | } | 901 | } |
820 | 902 | ||
903 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
904 | static void sci_dma_tx_complete(void *arg) | ||
905 | { | ||
906 | struct sci_port *s = arg; | ||
907 | struct uart_port *port = &s->port; | ||
908 | struct circ_buf *xmit = &port->state->xmit; | ||
909 | unsigned long flags; | ||
910 | |||
911 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | ||
912 | |||
913 | spin_lock_irqsave(&port->lock, flags); | ||
914 | |||
915 | xmit->tail += s->sg_tx.length; | ||
916 | xmit->tail &= UART_XMIT_SIZE - 1; | ||
917 | |||
918 | port->icount.tx += s->sg_tx.length; | ||
919 | |||
920 | async_tx_ack(s->desc_tx); | ||
921 | s->cookie_tx = -EINVAL; | ||
922 | s->desc_tx = NULL; | ||
923 | |||
924 | spin_unlock_irqrestore(&port->lock, flags); | ||
925 | |||
926 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
927 | uart_write_wakeup(port); | ||
928 | |||
929 | if (uart_circ_chars_pending(xmit)) | ||
930 | schedule_work(&s->work_tx); | ||
931 | } | ||
932 | |||
933 | /* Locking: called with port lock held */ | ||
934 | static int sci_dma_rx_push(struct sci_port *s, struct tty_struct *tty, | ||
935 | size_t count) | ||
936 | { | ||
937 | struct uart_port *port = &s->port; | ||
938 | int i, active, room; | ||
939 | |||
940 | room = tty_buffer_request_room(tty, count); | ||
941 | |||
942 | if (s->active_rx == s->cookie_rx[0]) { | ||
943 | active = 0; | ||
944 | } else if (s->active_rx == s->cookie_rx[1]) { | ||
945 | active = 1; | ||
946 | } else { | ||
947 | dev_err(port->dev, "cookie %d not found!\n", s->active_rx); | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | if (room < count) | ||
952 | dev_warn(port->dev, "Rx overrun: dropping %u bytes\n", | ||
953 | count - room); | ||
954 | if (!room) | ||
955 | return room; | ||
956 | |||
957 | for (i = 0; i < room; i++) | ||
958 | tty_insert_flip_char(tty, ((u8 *)sg_virt(&s->sg_rx[active]))[i], | ||
959 | TTY_NORMAL); | ||
960 | |||
961 | port->icount.rx += room; | ||
962 | |||
963 | return room; | ||
964 | } | ||
965 | |||
966 | static void sci_dma_rx_complete(void *arg) | ||
967 | { | ||
968 | struct sci_port *s = arg; | ||
969 | struct uart_port *port = &s->port; | ||
970 | struct tty_struct *tty = port->state->port.tty; | ||
971 | unsigned long flags; | ||
972 | int count; | ||
973 | |||
974 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | ||
975 | |||
976 | spin_lock_irqsave(&port->lock, flags); | ||
977 | |||
978 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); | ||
979 | |||
980 | mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5)); | ||
981 | |||
982 | spin_unlock_irqrestore(&port->lock, flags); | ||
983 | |||
984 | if (count) | ||
985 | tty_flip_buffer_push(tty); | ||
986 | |||
987 | schedule_work(&s->work_rx); | ||
988 | } | ||
989 | |||
990 | static void sci_start_rx(struct uart_port *port); | ||
991 | static void sci_start_tx(struct uart_port *port); | ||
992 | |||
993 | static void sci_rx_dma_release(struct sci_port *s, bool enable_pio) | ||
994 | { | ||
995 | struct dma_chan *chan = s->chan_rx; | ||
996 | struct uart_port *port = &s->port; | ||
997 | |||
998 | s->chan_rx = NULL; | ||
999 | s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL; | ||
1000 | dma_release_channel(chan); | ||
1001 | dma_free_coherent(port->dev, s->buf_len_rx * 2, | ||
1002 | sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0])); | ||
1003 | if (enable_pio) | ||
1004 | sci_start_rx(port); | ||
1005 | } | ||
1006 | |||
1007 | static void sci_tx_dma_release(struct sci_port *s, bool enable_pio) | ||
1008 | { | ||
1009 | struct dma_chan *chan = s->chan_tx; | ||
1010 | struct uart_port *port = &s->port; | ||
1011 | |||
1012 | s->chan_tx = NULL; | ||
1013 | s->cookie_tx = -EINVAL; | ||
1014 | dma_release_channel(chan); | ||
1015 | if (enable_pio) | ||
1016 | sci_start_tx(port); | ||
1017 | } | ||
1018 | |||
1019 | static void sci_submit_rx(struct sci_port *s) | ||
1020 | { | ||
1021 | struct dma_chan *chan = s->chan_rx; | ||
1022 | int i; | ||
1023 | |||
1024 | for (i = 0; i < 2; i++) { | ||
1025 | struct scatterlist *sg = &s->sg_rx[i]; | ||
1026 | struct dma_async_tx_descriptor *desc; | ||
1027 | |||
1028 | desc = chan->device->device_prep_slave_sg(chan, | ||
1029 | sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT); | ||
1030 | |||
1031 | if (desc) { | ||
1032 | s->desc_rx[i] = desc; | ||
1033 | desc->callback = sci_dma_rx_complete; | ||
1034 | desc->callback_param = s; | ||
1035 | s->cookie_rx[i] = desc->tx_submit(desc); | ||
1036 | } | ||
1037 | |||
1038 | if (!desc || s->cookie_rx[i] < 0) { | ||
1039 | if (i) { | ||
1040 | async_tx_ack(s->desc_rx[0]); | ||
1041 | s->cookie_rx[0] = -EINVAL; | ||
1042 | } | ||
1043 | if (desc) { | ||
1044 | async_tx_ack(desc); | ||
1045 | s->cookie_rx[i] = -EINVAL; | ||
1046 | } | ||
1047 | dev_warn(s->port.dev, | ||
1048 | "failed to re-start DMA, using PIO\n"); | ||
1049 | sci_rx_dma_release(s, true); | ||
1050 | return; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | s->active_rx = s->cookie_rx[0]; | ||
1055 | |||
1056 | dma_async_issue_pending(chan); | ||
1057 | } | ||
1058 | |||
1059 | static void work_fn_rx(struct work_struct *work) | ||
1060 | { | ||
1061 | struct sci_port *s = container_of(work, struct sci_port, work_rx); | ||
1062 | struct uart_port *port = &s->port; | ||
1063 | struct dma_async_tx_descriptor *desc; | ||
1064 | int new; | ||
1065 | |||
1066 | if (s->active_rx == s->cookie_rx[0]) { | ||
1067 | new = 0; | ||
1068 | } else if (s->active_rx == s->cookie_rx[1]) { | ||
1069 | new = 1; | ||
1070 | } else { | ||
1071 | dev_err(port->dev, "cookie %d not found!\n", s->active_rx); | ||
1072 | return; | ||
1073 | } | ||
1074 | desc = s->desc_rx[new]; | ||
1075 | |||
1076 | if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) != | ||
1077 | DMA_SUCCESS) { | ||
1078 | /* Handle incomplete DMA receive */ | ||
1079 | struct tty_struct *tty = port->state->port.tty; | ||
1080 | struct dma_chan *chan = s->chan_rx; | ||
1081 | struct sh_desc *sh_desc = container_of(desc, struct sh_desc, | ||
1082 | async_tx); | ||
1083 | unsigned long flags; | ||
1084 | int count; | ||
1085 | |||
1086 | chan->device->device_terminate_all(chan); | ||
1087 | dev_dbg(port->dev, "Read %u bytes with cookie %d\n", | ||
1088 | sh_desc->partial, sh_desc->cookie); | ||
1089 | |||
1090 | spin_lock_irqsave(&port->lock, flags); | ||
1091 | count = sci_dma_rx_push(s, tty, sh_desc->partial); | ||
1092 | spin_unlock_irqrestore(&port->lock, flags); | ||
1093 | |||
1094 | if (count) | ||
1095 | tty_flip_buffer_push(tty); | ||
1096 | |||
1097 | sci_submit_rx(s); | ||
1098 | |||
1099 | return; | ||
1100 | } | ||
1101 | |||
1102 | s->cookie_rx[new] = desc->tx_submit(desc); | ||
1103 | if (s->cookie_rx[new] < 0) { | ||
1104 | dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n"); | ||
1105 | sci_rx_dma_release(s, true); | ||
1106 | return; | ||
1107 | } | ||
1108 | |||
1109 | dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__, | ||
1110 | s->cookie_rx[new], new); | ||
1111 | |||
1112 | s->active_rx = s->cookie_rx[!new]; | ||
1113 | } | ||
1114 | |||
1115 | static void work_fn_tx(struct work_struct *work) | ||
1116 | { | ||
1117 | struct sci_port *s = container_of(work, struct sci_port, work_tx); | ||
1118 | struct dma_async_tx_descriptor *desc; | ||
1119 | struct dma_chan *chan = s->chan_tx; | ||
1120 | struct uart_port *port = &s->port; | ||
1121 | struct circ_buf *xmit = &port->state->xmit; | ||
1122 | struct scatterlist *sg = &s->sg_tx; | ||
1123 | |||
1124 | /* | ||
1125 | * DMA is idle now. | ||
1126 | * Port xmit buffer is already mapped, and it is one page... Just adjust | ||
1127 | * offsets and lengths. Since it is a circular buffer, we have to | ||
1128 | * transmit till the end, and then the rest. Take the port lock to get a | ||
1129 | * consistent xmit buffer state. | ||
1130 | */ | ||
1131 | spin_lock_irq(&port->lock); | ||
1132 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); | ||
1133 | sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + | ||
1134 | sg->offset; | ||
1135 | sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), | ||
1136 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); | ||
1137 | sg->dma_length = sg->length; | ||
1138 | spin_unlock_irq(&port->lock); | ||
1139 | |||
1140 | BUG_ON(!sg->length); | ||
1141 | |||
1142 | desc = chan->device->device_prep_slave_sg(chan, | ||
1143 | sg, s->sg_len_tx, DMA_TO_DEVICE, | ||
1144 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
1145 | if (!desc) { | ||
1146 | /* switch to PIO */ | ||
1147 | sci_tx_dma_release(s, true); | ||
1148 | return; | ||
1149 | } | ||
1150 | |||
1151 | dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE); | ||
1152 | |||
1153 | spin_lock_irq(&port->lock); | ||
1154 | s->desc_tx = desc; | ||
1155 | desc->callback = sci_dma_tx_complete; | ||
1156 | desc->callback_param = s; | ||
1157 | spin_unlock_irq(&port->lock); | ||
1158 | s->cookie_tx = desc->tx_submit(desc); | ||
1159 | if (s->cookie_tx < 0) { | ||
1160 | dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n"); | ||
1161 | /* switch to PIO */ | ||
1162 | sci_tx_dma_release(s, true); | ||
1163 | return; | ||
1164 | } | ||
1165 | |||
1166 | dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__, | ||
1167 | xmit->buf, xmit->tail, xmit->head, s->cookie_tx); | ||
1168 | |||
1169 | dma_async_issue_pending(chan); | ||
1170 | } | ||
1171 | #endif | ||
1172 | |||
821 | static void sci_start_tx(struct uart_port *port) | 1173 | static void sci_start_tx(struct uart_port *port) |
822 | { | 1174 | { |
823 | unsigned short ctrl; | 1175 | unsigned short ctrl; |
824 | 1176 | ||
1177 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1178 | struct sci_port *s = to_sci_port(port); | ||
1179 | |||
1180 | if (s->chan_tx) { | ||
1181 | if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0) | ||
1182 | schedule_work(&s->work_tx); | ||
1183 | |||
1184 | return; | ||
1185 | } | ||
1186 | #endif | ||
1187 | |||
825 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1188 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
826 | ctrl = sci_in(port, SCSCR); | 1189 | ctrl = sci_in(port, SCSCR); |
827 | ctrl |= SCI_CTRL_FLAGS_TIE; | 1190 | ctrl |= SCI_CTRL_FLAGS_TIE; |
@@ -838,13 +1201,12 @@ static void sci_stop_tx(struct uart_port *port) | |||
838 | sci_out(port, SCSCR, ctrl); | 1201 | sci_out(port, SCSCR, ctrl); |
839 | } | 1202 | } |
840 | 1203 | ||
841 | static void sci_start_rx(struct uart_port *port, unsigned int tty_start) | 1204 | static void sci_start_rx(struct uart_port *port) |
842 | { | 1205 | { |
843 | unsigned short ctrl; | 1206 | unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE; |
844 | 1207 | ||
845 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1208 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
846 | ctrl = sci_in(port, SCSCR); | 1209 | ctrl |= sci_in(port, SCSCR); |
847 | ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE; | ||
848 | sci_out(port, SCSCR, ctrl); | 1210 | sci_out(port, SCSCR, ctrl); |
849 | } | 1211 | } |
850 | 1212 | ||
@@ -868,16 +1230,154 @@ static void sci_break_ctl(struct uart_port *port, int break_state) | |||
868 | /* Nothing here yet .. */ | 1230 | /* Nothing here yet .. */ |
869 | } | 1231 | } |
870 | 1232 | ||
1233 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1234 | static bool filter(struct dma_chan *chan, void *slave) | ||
1235 | { | ||
1236 | struct sh_dmae_slave *param = slave; | ||
1237 | |||
1238 | dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__, | ||
1239 | param->slave_id); | ||
1240 | |||
1241 | if (param->dma_dev == chan->device->dev) { | ||
1242 | chan->private = param; | ||
1243 | return true; | ||
1244 | } else { | ||
1245 | return false; | ||
1246 | } | ||
1247 | } | ||
1248 | |||
1249 | static void rx_timer_fn(unsigned long arg) | ||
1250 | { | ||
1251 | struct sci_port *s = (struct sci_port *)arg; | ||
1252 | struct uart_port *port = &s->port; | ||
1253 | |||
1254 | u16 scr = sci_in(port, SCSCR); | ||
1255 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | ||
1256 | dev_dbg(port->dev, "DMA Rx timed out\n"); | ||
1257 | schedule_work(&s->work_rx); | ||
1258 | } | ||
1259 | |||
1260 | static void sci_request_dma(struct uart_port *port) | ||
1261 | { | ||
1262 | struct sci_port *s = to_sci_port(port); | ||
1263 | struct sh_dmae_slave *param; | ||
1264 | struct dma_chan *chan; | ||
1265 | dma_cap_mask_t mask; | ||
1266 | int nent; | ||
1267 | |||
1268 | dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__, | ||
1269 | port->line, s->dma_dev); | ||
1270 | |||
1271 | if (!s->dma_dev) | ||
1272 | return; | ||
1273 | |||
1274 | dma_cap_zero(mask); | ||
1275 | dma_cap_set(DMA_SLAVE, mask); | ||
1276 | |||
1277 | param = &s->param_tx; | ||
1278 | |||
1279 | /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */ | ||
1280 | param->slave_id = s->slave_tx; | ||
1281 | param->dma_dev = s->dma_dev; | ||
1282 | |||
1283 | s->cookie_tx = -EINVAL; | ||
1284 | chan = dma_request_channel(mask, filter, param); | ||
1285 | dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan); | ||
1286 | if (chan) { | ||
1287 | s->chan_tx = chan; | ||
1288 | sg_init_table(&s->sg_tx, 1); | ||
1289 | /* UART circular tx buffer is an aligned page. */ | ||
1290 | BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); | ||
1291 | sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf), | ||
1292 | UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK); | ||
1293 | nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE); | ||
1294 | if (!nent) | ||
1295 | sci_tx_dma_release(s, false); | ||
1296 | else | ||
1297 | dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, | ||
1298 | sg_dma_len(&s->sg_tx), | ||
1299 | port->state->xmit.buf, sg_dma_address(&s->sg_tx)); | ||
1300 | |||
1301 | s->sg_len_tx = nent; | ||
1302 | |||
1303 | INIT_WORK(&s->work_tx, work_fn_tx); | ||
1304 | } | ||
1305 | |||
1306 | param = &s->param_rx; | ||
1307 | |||
1308 | /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */ | ||
1309 | param->slave_id = s->slave_rx; | ||
1310 | param->dma_dev = s->dma_dev; | ||
1311 | |||
1312 | chan = dma_request_channel(mask, filter, param); | ||
1313 | dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan); | ||
1314 | if (chan) { | ||
1315 | dma_addr_t dma[2]; | ||
1316 | void *buf[2]; | ||
1317 | int i; | ||
1318 | |||
1319 | s->chan_rx = chan; | ||
1320 | |||
1321 | s->buf_len_rx = 2 * max(16, (int)port->fifosize); | ||
1322 | buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2, | ||
1323 | &dma[0], GFP_KERNEL); | ||
1324 | |||
1325 | if (!buf[0]) { | ||
1326 | dev_warn(port->dev, | ||
1327 | "failed to allocate dma buffer, using PIO\n"); | ||
1328 | sci_rx_dma_release(s, true); | ||
1329 | return; | ||
1330 | } | ||
1331 | |||
1332 | buf[1] = buf[0] + s->buf_len_rx; | ||
1333 | dma[1] = dma[0] + s->buf_len_rx; | ||
1334 | |||
1335 | for (i = 0; i < 2; i++) { | ||
1336 | struct scatterlist *sg = &s->sg_rx[i]; | ||
1337 | |||
1338 | sg_init_table(sg, 1); | ||
1339 | sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, | ||
1340 | (int)buf[i] & ~PAGE_MASK); | ||
1341 | sg->dma_address = dma[i]; | ||
1342 | sg->dma_length = sg->length; | ||
1343 | } | ||
1344 | |||
1345 | INIT_WORK(&s->work_rx, work_fn_rx); | ||
1346 | setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s); | ||
1347 | |||
1348 | sci_submit_rx(s); | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | static void sci_free_dma(struct uart_port *port) | ||
1353 | { | ||
1354 | struct sci_port *s = to_sci_port(port); | ||
1355 | |||
1356 | if (!s->dma_dev) | ||
1357 | return; | ||
1358 | |||
1359 | if (s->chan_tx) | ||
1360 | sci_tx_dma_release(s, false); | ||
1361 | if (s->chan_rx) | ||
1362 | sci_rx_dma_release(s, false); | ||
1363 | } | ||
1364 | #endif | ||
1365 | |||
871 | static int sci_startup(struct uart_port *port) | 1366 | static int sci_startup(struct uart_port *port) |
872 | { | 1367 | { |
873 | struct sci_port *s = to_sci_port(port); | 1368 | struct sci_port *s = to_sci_port(port); |
874 | 1369 | ||
1370 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | ||
1371 | |||
875 | if (s->enable) | 1372 | if (s->enable) |
876 | s->enable(port); | 1373 | s->enable(port); |
877 | 1374 | ||
878 | sci_request_irq(s); | 1375 | sci_request_irq(s); |
1376 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1377 | sci_request_dma(port); | ||
1378 | #endif | ||
879 | sci_start_tx(port); | 1379 | sci_start_tx(port); |
880 | sci_start_rx(port, 1); | 1380 | sci_start_rx(port); |
881 | 1381 | ||
882 | return 0; | 1382 | return 0; |
883 | } | 1383 | } |
@@ -886,8 +1386,13 @@ static void sci_shutdown(struct uart_port *port) | |||
886 | { | 1386 | { |
887 | struct sci_port *s = to_sci_port(port); | 1387 | struct sci_port *s = to_sci_port(port); |
888 | 1388 | ||
1389 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | ||
1390 | |||
889 | sci_stop_rx(port); | 1391 | sci_stop_rx(port); |
890 | sci_stop_tx(port); | 1392 | sci_stop_tx(port); |
1393 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1394 | sci_free_dma(port); | ||
1395 | #endif | ||
891 | sci_free_irq(s); | 1396 | sci_free_irq(s); |
892 | 1397 | ||
893 | if (s->disable) | 1398 | if (s->disable) |
@@ -937,6 +1442,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
937 | 1442 | ||
938 | sci_out(port, SCSMR, smr_val); | 1443 | sci_out(port, SCSMR, smr_val); |
939 | 1444 | ||
1445 | dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, | ||
1446 | SCSCR_INIT(port)); | ||
1447 | |||
940 | if (t > 0) { | 1448 | if (t > 0) { |
941 | if (t >= 256) { | 1449 | if (t >= 256) { |
942 | sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); | 1450 | sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1); |
@@ -954,7 +1462,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
954 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1462 | sci_out(port, SCSCR, SCSCR_INIT(port)); |
955 | 1463 | ||
956 | if ((termios->c_cflag & CREAD) != 0) | 1464 | if ((termios->c_cflag & CREAD) != 0) |
957 | sci_start_rx(port, 0); | 1465 | sci_start_rx(port); |
958 | } | 1466 | } |
959 | 1467 | ||
960 | static const char *sci_type(struct uart_port *port) | 1468 | static const char *sci_type(struct uart_port *port) |
@@ -1049,19 +1557,21 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
1049 | unsigned int index, | 1557 | unsigned int index, |
1050 | struct plat_sci_port *p) | 1558 | struct plat_sci_port *p) |
1051 | { | 1559 | { |
1052 | sci_port->port.ops = &sci_uart_ops; | 1560 | struct uart_port *port = &sci_port->port; |
1053 | sci_port->port.iotype = UPIO_MEM; | 1561 | |
1054 | sci_port->port.line = index; | 1562 | port->ops = &sci_uart_ops; |
1563 | port->iotype = UPIO_MEM; | ||
1564 | port->line = index; | ||
1055 | 1565 | ||
1056 | switch (p->type) { | 1566 | switch (p->type) { |
1057 | case PORT_SCIFA: | 1567 | case PORT_SCIFA: |
1058 | sci_port->port.fifosize = 64; | 1568 | port->fifosize = 64; |
1059 | break; | 1569 | break; |
1060 | case PORT_SCIF: | 1570 | case PORT_SCIF: |
1061 | sci_port->port.fifosize = 16; | 1571 | port->fifosize = 16; |
1062 | break; | 1572 | break; |
1063 | default: | 1573 | default: |
1064 | sci_port->port.fifosize = 1; | 1574 | port->fifosize = 1; |
1065 | break; | 1575 | break; |
1066 | } | 1576 | } |
1067 | 1577 | ||
@@ -1070,19 +1580,28 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
1070 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); | 1580 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); |
1071 | sci_port->enable = sci_clk_enable; | 1581 | sci_port->enable = sci_clk_enable; |
1072 | sci_port->disable = sci_clk_disable; | 1582 | sci_port->disable = sci_clk_disable; |
1073 | sci_port->port.dev = &dev->dev; | 1583 | port->dev = &dev->dev; |
1074 | } | 1584 | } |
1075 | 1585 | ||
1076 | sci_port->break_timer.data = (unsigned long)sci_port; | 1586 | sci_port->break_timer.data = (unsigned long)sci_port; |
1077 | sci_port->break_timer.function = sci_break_timer; | 1587 | sci_port->break_timer.function = sci_break_timer; |
1078 | init_timer(&sci_port->break_timer); | 1588 | init_timer(&sci_port->break_timer); |
1079 | 1589 | ||
1080 | sci_port->port.mapbase = p->mapbase; | 1590 | port->mapbase = p->mapbase; |
1081 | sci_port->port.membase = p->membase; | 1591 | port->membase = p->membase; |
1082 | 1592 | ||
1083 | sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; | 1593 | port->irq = p->irqs[SCIx_TXI_IRQ]; |
1084 | sci_port->port.flags = p->flags; | 1594 | port->flags = p->flags; |
1085 | sci_port->type = sci_port->port.type = p->type; | 1595 | sci_port->type = port->type = p->type; |
1596 | |||
1597 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1598 | sci_port->dma_dev = p->dma_dev; | ||
1599 | sci_port->slave_tx = p->dma_slave_tx; | ||
1600 | sci_port->slave_rx = p->dma_slave_rx; | ||
1601 | |||
1602 | dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__, | ||
1603 | p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); | ||
1604 | #endif | ||
1086 | 1605 | ||
1087 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); | 1606 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
1088 | } | 1607 | } |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f7d2589926d2..f70c49f915fa 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -30,7 +30,10 @@ | |||
30 | */ | 30 | */ |
31 | # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 | 31 | # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 |
32 | #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 32 | #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
33 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 33 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
34 | defined(CONFIG_ARCH_SH7367) || \ | ||
35 | defined(CONFIG_ARCH_SH7377) || \ | ||
36 | defined(CONFIG_ARCH_SH7372) | ||
34 | # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ | 37 | # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ |
35 | # define PORT_PTCR 0xA405011EUL | 38 | # define PORT_PTCR 0xA405011EUL |
36 | # define PORT_PVCR 0xA4050122UL | 39 | # define PORT_PVCR 0xA4050122UL |
@@ -93,7 +96,9 @@ | |||
93 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 96 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
94 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | 97 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) |
95 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 98 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
96 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 99 | # define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \ |
100 | 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ | ||
101 | 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) | ||
97 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 102 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
98 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 103 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
99 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 104 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
@@ -196,6 +201,8 @@ | |||
196 | defined(CONFIG_CPU_SUBTYPE_SH7786) || \ | 201 | defined(CONFIG_CPU_SUBTYPE_SH7786) || \ |
197 | defined(CONFIG_CPU_SUBTYPE_SHX3) | 202 | defined(CONFIG_CPU_SUBTYPE_SHX3) |
198 | #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ | 203 | #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ |
204 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
205 | #define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8) | ||
199 | #else | 206 | #else |
200 | #define SCI_CTRL_FLAGS_REIE 0 | 207 | #define SCI_CTRL_FLAGS_REIE 0 |
201 | #endif | 208 | #endif |
@@ -228,7 +235,10 @@ | |||
228 | 235 | ||
229 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 236 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
230 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 237 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
231 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 238 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
239 | defined(CONFIG_ARCH_SH7367) || \ | ||
240 | defined(CONFIG_ARCH_SH7377) || \ | ||
241 | defined(CONFIG_ARCH_SH7372) | ||
232 | # define SCIF_ORER 0x0200 | 242 | # define SCIF_ORER 0x0200 |
233 | # define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) | 243 | # define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) |
234 | # define SCIF_RFDC_MASK 0x007f | 244 | # define SCIF_RFDC_MASK 0x007f |
@@ -261,7 +271,10 @@ | |||
261 | 271 | ||
262 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 272 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
263 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 273 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
264 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 274 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
275 | defined(CONFIG_ARCH_SH7367) || \ | ||
276 | defined(CONFIG_ARCH_SH7377) || \ | ||
277 | defined(CONFIG_ARCH_SH7372) | ||
265 | # define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) | 278 | # define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) |
266 | # define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) | 279 | # define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) |
267 | # define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) | 280 | # define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) |
@@ -356,7 +369,10 @@ | |||
356 | SCI_OUT(sci_size, sci_offset, value); \ | 369 | SCI_OUT(sci_size, sci_offset, value); \ |
357 | } | 370 | } |
358 | 371 | ||
359 | #ifdef CONFIG_CPU_SH3 | 372 | #if defined(CONFIG_CPU_SH3) || \ |
373 | defined(CONFIG_ARCH_SH7367) || \ | ||
374 | defined(CONFIG_ARCH_SH7377) || \ | ||
375 | defined(CONFIG_ARCH_SH7372) | ||
360 | #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) | 376 | #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) |
361 | #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ | 377 | #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ |
362 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ | 378 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ |
@@ -366,7 +382,10 @@ | |||
366 | CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) | 382 | CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) |
367 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 383 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
368 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 384 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
369 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 385 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
386 | defined(CONFIG_ARCH_SH7367) || \ | ||
387 | defined(CONFIG_ARCH_SH7377) || \ | ||
388 | defined(CONFIG_ARCH_SH7372) | ||
370 | #define SCIF_FNS(name, scif_offset, scif_size) \ | 389 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
371 | CPU_SCIF_FNS(name, scif_offset, scif_size) | 390 | CPU_SCIF_FNS(name, scif_offset, scif_size) |
372 | #else | 391 | #else |
@@ -401,7 +420,10 @@ | |||
401 | 420 | ||
402 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 421 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
403 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 422 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
404 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 423 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
424 | defined(CONFIG_ARCH_SH7367) || \ | ||
425 | defined(CONFIG_ARCH_SH7377) || \ | ||
426 | defined(CONFIG_ARCH_SH7372) | ||
405 | 427 | ||
406 | SCIF_FNS(SCSMR, 0x00, 16) | 428 | SCIF_FNS(SCSMR, 0x00, 16) |
407 | SCIF_FNS(SCBRR, 0x04, 8) | 429 | SCIF_FNS(SCBRR, 0x04, 8) |
@@ -413,7 +435,7 @@ SCIF_FNS(SCFCR, 0x18, 16) | |||
413 | SCIF_FNS(SCFDR, 0x1c, 16) | 435 | SCIF_FNS(SCFDR, 0x1c, 16) |
414 | SCIF_FNS(SCxTDR, 0x20, 8) | 436 | SCIF_FNS(SCxTDR, 0x20, 8) |
415 | SCIF_FNS(SCxRDR, 0x24, 8) | 437 | SCIF_FNS(SCxRDR, 0x24, 8) |
416 | SCIF_FNS(SCLSR, 0x24, 16) | 438 | SCIF_FNS(SCLSR, 0x00, 0) |
417 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | 439 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
418 | defined(CONFIG_CPU_SUBTYPE_SH7724) | 440 | defined(CONFIG_CPU_SUBTYPE_SH7724) |
419 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | 441 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) |
@@ -583,7 +605,10 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
583 | #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) | 605 | #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) |
584 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 606 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
585 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 607 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
586 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 608 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
609 | defined(CONFIG_ARCH_SH7367) || \ | ||
610 | defined(CONFIG_ARCH_SH7377) || \ | ||
611 | defined(CONFIG_ARCH_SH7372) | ||
587 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) | 612 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
588 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | 613 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
589 | defined(CONFIG_CPU_SUBTYPE_SH7724) | 614 | defined(CONFIG_CPU_SUBTYPE_SH7724) |
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 34b31da01d09..7bf10264a6ac 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c | |||
@@ -421,7 +421,7 @@ static struct uart_driver timbuart_driver = { | |||
421 | 421 | ||
422 | static int timbuart_probe(struct platform_device *dev) | 422 | static int timbuart_probe(struct platform_device *dev) |
423 | { | 423 | { |
424 | int err; | 424 | int err, irq; |
425 | struct timbuart_port *uart; | 425 | struct timbuart_port *uart; |
426 | struct resource *iomem; | 426 | struct resource *iomem; |
427 | 427 | ||
@@ -453,11 +453,12 @@ static int timbuart_probe(struct platform_device *dev) | |||
453 | uart->port.mapbase = iomem->start; | 453 | uart->port.mapbase = iomem->start; |
454 | uart->port.membase = NULL; | 454 | uart->port.membase = NULL; |
455 | 455 | ||
456 | uart->port.irq = platform_get_irq(dev, 0); | 456 | irq = platform_get_irq(dev, 0); |
457 | if (uart->port.irq < 0) { | 457 | if (irq < 0) { |
458 | err = -EINVAL; | 458 | err = -EINVAL; |
459 | goto err_register; | 459 | goto err_register; |
460 | } | 460 | } |
461 | uart->port.irq = irq; | ||
461 | 462 | ||
462 | tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); | 463 | tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); |
463 | 464 | ||
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index ab2ab3c81834..f0a6c61b17f7 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <asm/io.h> | 21 | #include <asm/io.h> |
22 | #if defined(CONFIG_OF) | 22 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) |
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
25 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
@@ -581,7 +581,7 @@ static struct platform_driver ulite_platform_driver = { | |||
581 | /* --------------------------------------------------------------------- | 581 | /* --------------------------------------------------------------------- |
582 | * OF bus bindings | 582 | * OF bus bindings |
583 | */ | 583 | */ |
584 | #if defined(CONFIG_OF) | 584 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) |
585 | static int __devinit | 585 | static int __devinit |
586 | ulite_of_probe(struct of_device *op, const struct of_device_id *match) | 586 | ulite_of_probe(struct of_device *op, const struct of_device_id *match) |
587 | { | 587 | { |
@@ -631,11 +631,11 @@ static inline void __exit ulite_of_unregister(void) | |||
631 | { | 631 | { |
632 | of_unregister_platform_driver(&ulite_of_driver); | 632 | of_unregister_platform_driver(&ulite_of_driver); |
633 | } | 633 | } |
634 | #else /* CONFIG_OF */ | 634 | #else /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ |
635 | /* CONFIG_OF not enabled; do nothing helpers */ | 635 | /* Appropriate config not enabled; do nothing helpers */ |
636 | static inline int __init ulite_of_register(void) { return 0; } | 636 | static inline int __init ulite_of_register(void) { return 0; } |
637 | static inline void __exit ulite_of_unregister(void) { } | 637 | static inline void __exit ulite_of_unregister(void) { } |
638 | #endif /* CONFIG_OF */ | 638 | #endif /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ |
639 | 639 | ||
640 | /* --------------------------------------------------------------------- | 640 | /* --------------------------------------------------------------------- |
641 | * Module setup/teardown | 641 | * Module setup/teardown |