diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-03-17 03:44:08 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-03-17 03:44:08 -0400 |
commit | 1d2a1959fe534279cf37aba20b08c24c20840e52 (patch) | |
tree | 67c0b9aa7fe22a44bf0b4af88947799203eb8f67 /drivers/tty/serial | |
parent | 5a79ce76e9bb8f4b2cd8106ee36d15ee05013bcf (diff) | |
parent | 054cfaacf88865bff1dd58d305443d5d6c068a08 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into sh-latest
Diffstat (limited to 'drivers/tty/serial')
34 files changed, 2713 insertions, 1157 deletions
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index be0ebce36e54..d5bfd41707e7 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c | |||
@@ -262,7 +262,7 @@ static void status_handle(struct m68k_serial *info, unsigned short status) | |||
262 | 262 | ||
263 | static void receive_chars(struct m68k_serial *info, unsigned short rx) | 263 | static void receive_chars(struct m68k_serial *info, unsigned short rx) |
264 | { | 264 | { |
265 | struct tty_struct *tty = info->port.tty; | 265 | struct tty_struct *tty = info->tty; |
266 | m68328_uart *uart = &uart_addr[info->line]; | 266 | m68328_uart *uart = &uart_addr[info->line]; |
267 | unsigned char ch, flag; | 267 | unsigned char ch, flag; |
268 | 268 | ||
@@ -329,7 +329,7 @@ static void transmit_chars(struct m68k_serial *info) | |||
329 | goto clear_and_return; | 329 | goto clear_and_return; |
330 | } | 330 | } |
331 | 331 | ||
332 | if((info->xmit_cnt <= 0) || info->port.tty->stopped) { | 332 | if((info->xmit_cnt <= 0) || info->tty->stopped) { |
333 | /* That's peculiar... TX ints off */ | 333 | /* That's peculiar... TX ints off */ |
334 | uart->ustcnt &= ~USTCNT_TX_INTR_MASK; | 334 | uart->ustcnt &= ~USTCNT_TX_INTR_MASK; |
335 | goto clear_and_return; | 335 | goto clear_and_return; |
@@ -383,7 +383,7 @@ static void do_softint(struct work_struct *work) | |||
383 | struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); | 383 | struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); |
384 | struct tty_struct *tty; | 384 | struct tty_struct *tty; |
385 | 385 | ||
386 | tty = info->port.tty; | 386 | tty = info->tty; |
387 | if (!tty) | 387 | if (!tty) |
388 | return; | 388 | return; |
389 | #if 0 | 389 | #if 0 |
@@ -393,28 +393,6 @@ static void do_softint(struct work_struct *work) | |||
393 | #endif | 393 | #endif |
394 | } | 394 | } |
395 | 395 | ||
396 | /* | ||
397 | * This routine is called from the scheduler tqueue when the interrupt | ||
398 | * routine has signalled that a hangup has occurred. The path of | ||
399 | * hangup processing is: | ||
400 | * | ||
401 | * serial interrupt routine -> (scheduler tqueue) -> | ||
402 | * do_serial_hangup() -> tty->hangup() -> rs_hangup() | ||
403 | * | ||
404 | */ | ||
405 | static void do_serial_hangup(struct work_struct *work) | ||
406 | { | ||
407 | struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue_hangup); | ||
408 | struct tty_struct *tty; | ||
409 | |||
410 | tty = info->port.tty; | ||
411 | if (!tty) | ||
412 | return; | ||
413 | |||
414 | tty_hangup(tty); | ||
415 | } | ||
416 | |||
417 | |||
418 | static int startup(struct m68k_serial * info) | 396 | static int startup(struct m68k_serial * info) |
419 | { | 397 | { |
420 | m68328_uart *uart = &uart_addr[info->line]; | 398 | m68328_uart *uart = &uart_addr[info->line]; |
@@ -451,8 +429,8 @@ static int startup(struct m68k_serial * info) | |||
451 | uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; | 429 | uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; |
452 | #endif | 430 | #endif |
453 | 431 | ||
454 | if (info->port.tty) | 432 | if (info->tty) |
455 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); | 433 | clear_bit(TTY_IO_ERROR, &info->tty->flags); |
456 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 434 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
457 | 435 | ||
458 | /* | 436 | /* |
@@ -486,8 +464,8 @@ static void shutdown(struct m68k_serial * info) | |||
486 | info->xmit_buf = 0; | 464 | info->xmit_buf = 0; |
487 | } | 465 | } |
488 | 466 | ||
489 | if (info->port.tty) | 467 | if (info->tty) |
490 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | 468 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
491 | 469 | ||
492 | info->flags &= ~S_INITIALIZED; | 470 | info->flags &= ~S_INITIALIZED; |
493 | local_irq_restore(flags); | 471 | local_irq_restore(flags); |
@@ -553,9 +531,9 @@ static void change_speed(struct m68k_serial *info) | |||
553 | unsigned cflag; | 531 | unsigned cflag; |
554 | int i; | 532 | int i; |
555 | 533 | ||
556 | if (!info->port.tty || !info->port.tty->termios) | 534 | if (!info->tty || !info->tty->termios) |
557 | return; | 535 | return; |
558 | cflag = info->port.tty->termios->c_cflag; | 536 | cflag = info->tty->termios->c_cflag; |
559 | if (!(port = info->port)) | 537 | if (!(port = info->port)) |
560 | return; | 538 | return; |
561 | 539 | ||
@@ -967,10 +945,9 @@ static void send_break(struct m68k_serial * info, unsigned int duration) | |||
967 | local_irq_restore(flags); | 945 | local_irq_restore(flags); |
968 | } | 946 | } |
969 | 947 | ||
970 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 948 | static int rs_ioctl(struct tty_struct *tty, |
971 | unsigned int cmd, unsigned long arg) | 949 | unsigned int cmd, unsigned long arg) |
972 | { | 950 | { |
973 | int error; | ||
974 | struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; | 951 | struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; |
975 | int retval; | 952 | int retval; |
976 | 953 | ||
@@ -1104,7 +1081,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1104 | tty_ldisc_flush(tty); | 1081 | tty_ldisc_flush(tty); |
1105 | tty->closing = 0; | 1082 | tty->closing = 0; |
1106 | info->event = 0; | 1083 | info->event = 0; |
1107 | info->port.tty = NULL; | 1084 | info->tty = NULL; |
1108 | #warning "This is not and has never been valid so fix it" | 1085 | #warning "This is not and has never been valid so fix it" |
1109 | #if 0 | 1086 | #if 0 |
1110 | if (tty->ldisc.num != ldiscs[N_TTY].num) { | 1087 | if (tty->ldisc.num != ldiscs[N_TTY].num) { |
@@ -1142,7 +1119,7 @@ void rs_hangup(struct tty_struct *tty) | |||
1142 | info->event = 0; | 1119 | info->event = 0; |
1143 | info->count = 0; | 1120 | info->count = 0; |
1144 | info->flags &= ~S_NORMAL_ACTIVE; | 1121 | info->flags &= ~S_NORMAL_ACTIVE; |
1145 | info->port.tty = NULL; | 1122 | info->tty = NULL; |
1146 | wake_up_interruptible(&info->open_wait); | 1123 | wake_up_interruptible(&info->open_wait); |
1147 | } | 1124 | } |
1148 | 1125 | ||
@@ -1261,7 +1238,7 @@ int rs_open(struct tty_struct *tty, struct file * filp) | |||
1261 | 1238 | ||
1262 | info->count++; | 1239 | info->count++; |
1263 | tty->driver_data = info; | 1240 | tty->driver_data = info; |
1264 | info->port.tty = tty; | 1241 | info->tty = tty; |
1265 | 1242 | ||
1266 | /* | 1243 | /* |
1267 | * Start up serial port | 1244 | * Start up serial port |
@@ -1338,7 +1315,7 @@ rs68328_init(void) | |||
1338 | info = &m68k_soft[i]; | 1315 | info = &m68k_soft[i]; |
1339 | info->magic = SERIAL_MAGIC; | 1316 | info->magic = SERIAL_MAGIC; |
1340 | info->port = (int) &uart_addr[i]; | 1317 | info->port = (int) &uart_addr[i]; |
1341 | info->port.tty = NULL; | 1318 | info->tty = NULL; |
1342 | info->irq = uart_irqs[i]; | 1319 | info->irq = uart_irqs[i]; |
1343 | info->custom_divisor = 16; | 1320 | info->custom_divisor = 16; |
1344 | info->close_delay = 50; | 1321 | info->close_delay = 50; |
@@ -1348,7 +1325,6 @@ rs68328_init(void) | |||
1348 | info->count = 0; | 1325 | info->count = 0; |
1349 | info->blocked_open = 0; | 1326 | info->blocked_open = 0; |
1350 | INIT_WORK(&info->tqueue, do_softint); | 1327 | INIT_WORK(&info->tqueue, do_softint); |
1351 | INIT_WORK(&info->tqueue_hangup, do_serial_hangup); | ||
1352 | init_waitqueue_head(&info->open_wait); | 1328 | init_waitqueue_head(&info->open_wait); |
1353 | init_waitqueue_head(&info->close_wait); | 1329 | init_waitqueue_head(&info->close_wait); |
1354 | info->line = i; | 1330 | info->line = i; |
diff --git a/drivers/tty/serial/68328serial.h b/drivers/tty/serial/68328serial.h index 664ceb0a158c..8c9c3c0745db 100644 --- a/drivers/tty/serial/68328serial.h +++ b/drivers/tty/serial/68328serial.h | |||
@@ -159,7 +159,6 @@ struct m68k_serial { | |||
159 | int xmit_tail; | 159 | int xmit_tail; |
160 | int xmit_cnt; | 160 | int xmit_cnt; |
161 | struct work_struct tqueue; | 161 | struct work_struct tqueue; |
162 | struct work_struct tqueue_hangup; | ||
163 | wait_queue_head_t open_wait; | 162 | wait_queue_head_t open_wait; |
164 | wait_queue_head_t close_wait; | 163 | wait_queue_head_t close_wait; |
165 | }; | 164 | }; |
diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c index bc21eeae8fde..0a3e8787ed50 100644 --- a/drivers/tty/serial/68360serial.c +++ b/drivers/tty/serial/68360serial.c | |||
@@ -1240,7 +1240,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value) | |||
1240 | } | 1240 | } |
1241 | #endif | 1241 | #endif |
1242 | 1242 | ||
1243 | static int rs_360_tiocmget(struct tty_struct *tty, struct file *file) | 1243 | static int rs_360_tiocmget(struct tty_struct *tty) |
1244 | { | 1244 | { |
1245 | ser_info_t *info = (ser_info_t *)tty->driver_data; | 1245 | ser_info_t *info = (ser_info_t *)tty->driver_data; |
1246 | unsigned int result = 0; | 1246 | unsigned int result = 0; |
@@ -1271,7 +1271,7 @@ static int rs_360_tiocmget(struct tty_struct *tty, struct file *file) | |||
1271 | return result; | 1271 | return result; |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | static int rs_360_tiocmset(struct tty_struct *tty, struct file *file, | 1274 | static int rs_360_tiocmset(struct tty_struct *tty, |
1275 | unsigned int set, unsigned int clear) | 1275 | unsigned int set, unsigned int clear) |
1276 | { | 1276 | { |
1277 | #ifdef modem_control | 1277 | #ifdef modem_control |
@@ -1405,7 +1405,7 @@ static int rs_360_get_icount(struct tty_struct *tty, | |||
1405 | return 0; | 1405 | return 0; |
1406 | } | 1406 | } |
1407 | 1407 | ||
1408 | static int rs_360_ioctl(struct tty_struct *tty, struct file * file, | 1408 | static int rs_360_ioctl(struct tty_struct *tty, |
1409 | unsigned int cmd, unsigned long arg) | 1409 | unsigned int cmd, unsigned long arg) |
1410 | { | 1410 | { |
1411 | int error; | 1411 | int error; |
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 3975df6f7fdb..b3b881bc4712 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c | |||
@@ -954,6 +954,23 @@ static int broken_efr(struct uart_8250_port *up) | |||
954 | return 0; | 954 | return 0; |
955 | } | 955 | } |
956 | 956 | ||
957 | static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) | ||
958 | { | ||
959 | unsigned char status; | ||
960 | |||
961 | status = serial_in(up, 0x04); /* EXCR2 */ | ||
962 | #define PRESL(x) ((x) & 0x30) | ||
963 | if (PRESL(status) == 0x10) { | ||
964 | /* already in high speed mode */ | ||
965 | return 0; | ||
966 | } else { | ||
967 | status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||
968 | status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | ||
969 | serial_outp(up, 0x04, status); | ||
970 | } | ||
971 | return 1; | ||
972 | } | ||
973 | |||
957 | /* | 974 | /* |
958 | * We know that the chip has FIFOs. Does it have an EFR? The | 975 | * We know that the chip has FIFOs. Does it have an EFR? The |
959 | * EFR is located in the same register position as the IIR and | 976 | * EFR is located in the same register position as the IIR and |
@@ -1025,12 +1042,8 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
1025 | quot = serial_dl_read(up); | 1042 | quot = serial_dl_read(up); |
1026 | quot <<= 3; | 1043 | quot <<= 3; |
1027 | 1044 | ||
1028 | status1 = serial_in(up, 0x04); /* EXCR2 */ | 1045 | if (ns16550a_goto_highspeed(up)) |
1029 | status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | 1046 | serial_dl_write(up, quot); |
1030 | status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | ||
1031 | serial_outp(up, 0x04, status1); | ||
1032 | |||
1033 | serial_dl_write(up, quot); | ||
1034 | 1047 | ||
1035 | serial_outp(up, UART_LCR, 0); | 1048 | serial_outp(up, UART_LCR, 0); |
1036 | 1049 | ||
@@ -3025,17 +3038,13 @@ void serial8250_resume_port(int line) | |||
3025 | struct uart_8250_port *up = &serial8250_ports[line]; | 3038 | struct uart_8250_port *up = &serial8250_ports[line]; |
3026 | 3039 | ||
3027 | if (up->capabilities & UART_NATSEMI) { | 3040 | if (up->capabilities & UART_NATSEMI) { |
3028 | unsigned char tmp; | ||
3029 | |||
3030 | /* Ensure it's still in high speed mode */ | 3041 | /* Ensure it's still in high speed mode */ |
3031 | serial_outp(up, UART_LCR, 0xE0); | 3042 | serial_outp(up, UART_LCR, 0xE0); |
3032 | 3043 | ||
3033 | tmp = serial_in(up, 0x04); /* EXCR2 */ | 3044 | ns16550a_goto_highspeed(up); |
3034 | tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||
3035 | tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | ||
3036 | serial_outp(up, 0x04, tmp); | ||
3037 | 3045 | ||
3038 | serial_outp(up, UART_LCR, 0); | 3046 | serial_outp(up, UART_LCR, 0); |
3047 | up->port.uartclk = 921600*16; | ||
3039 | } | 3048 | } |
3040 | uart_resume_port(&serial8250_reg, &up->port); | 3049 | uart_resume_port(&serial8250_reg, &up->port); |
3041 | } | 3050 | } |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2b8334601c8b..e461be164f67 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -1110,29 +1110,6 @@ config SERIAL_PMACZILOG_CONSOLE | |||
1110 | on your (Power)Mac as the console, you can do so by answering | 1110 | on your (Power)Mac as the console, you can do so by answering |
1111 | Y to this option. | 1111 | Y to this option. |
1112 | 1112 | ||
1113 | config SERIAL_LH7A40X | ||
1114 | tristate "Sharp LH7A40X embedded UART support" | ||
1115 | depends on ARM && ARCH_LH7A40X | ||
1116 | select SERIAL_CORE | ||
1117 | help | ||
1118 | This enables support for the three on-board UARTs of the | ||
1119 | Sharp LH7A40X series CPUs. Choose Y or M. | ||
1120 | |||
1121 | config SERIAL_LH7A40X_CONSOLE | ||
1122 | bool "Support for console on Sharp LH7A40X serial port" | ||
1123 | depends on SERIAL_LH7A40X=y | ||
1124 | select SERIAL_CORE_CONSOLE | ||
1125 | help | ||
1126 | Say Y here if you wish to use one of the serial ports as the | ||
1127 | system console--the system console is the device which | ||
1128 | receives all kernel messages and warnings and which allows | ||
1129 | logins in single user mode. | ||
1130 | |||
1131 | Even if you say Y here, the currently visible framebuffer console | ||
1132 | (/dev/tty0) will still be used as the default system console, but | ||
1133 | you can alter that using a kernel command line, for example | ||
1134 | "console=ttyAM1". | ||
1135 | |||
1136 | config SERIAL_CPM | 1113 | config SERIAL_CPM |
1137 | tristate "CPM SCC/SMC serial port support" | 1114 | tristate "CPM SCC/SMC serial port support" |
1138 | depends on CPM2 || 8xx | 1115 | depends on CPM2 || 8xx |
@@ -1319,6 +1296,18 @@ config SERIAL_MSM_CONSOLE | |||
1319 | depends on SERIAL_MSM=y | 1296 | depends on SERIAL_MSM=y |
1320 | select SERIAL_CORE_CONSOLE | 1297 | select SERIAL_CORE_CONSOLE |
1321 | 1298 | ||
1299 | config SERIAL_MSM_HS | ||
1300 | tristate "MSM UART High Speed: Serial Driver" | ||
1301 | depends on ARCH_MSM | ||
1302 | select SERIAL_CORE | ||
1303 | help | ||
1304 | If you have a machine based on MSM family of SoCs, you | ||
1305 | can enable its onboard high speed serial port by enabling | ||
1306 | this option. | ||
1307 | |||
1308 | Choose M here to compile it as a module. The module will be | ||
1309 | called msm_serial_hs. | ||
1310 | |||
1322 | config SERIAL_VT8500 | 1311 | config SERIAL_VT8500 |
1323 | bool "VIA VT8500 on-chip serial port support" | 1312 | bool "VIA VT8500 on-chip serial port support" |
1324 | depends on ARM && ARCH_VT8500 | 1313 | depends on ARM && ARCH_VT8500 |
@@ -1588,12 +1577,25 @@ config SERIAL_IFX6X60 | |||
1588 | Support for the IFX6x60 modem devices on Intel MID platforms. | 1577 | Support for the IFX6x60 modem devices on Intel MID platforms. |
1589 | 1578 | ||
1590 | config SERIAL_PCH_UART | 1579 | config SERIAL_PCH_UART |
1591 | tristate "Intel EG20T PCH UART" | 1580 | tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH" |
1592 | depends on PCI && DMADEVICES | 1581 | depends on PCI |
1593 | select SERIAL_CORE | 1582 | select SERIAL_CORE |
1594 | select PCH_DMA | ||
1595 | help | 1583 | help |
1596 | This driver is for PCH(Platform controller Hub) UART of Intel EG20T | 1584 | This driver is for PCH(Platform controller Hub) UART of Intel EG20T |
1597 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 1585 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
1598 | Enabling PCH_DMA, this PCH UART works as DMA mode. | 1586 | Enabling PCH_DMA, this PCH UART works as DMA mode. |
1587 | |||
1588 | This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/ | ||
1589 | Output Hub) which is for IVI(In-Vehicle Infotainment) use. | ||
1590 | ML7213 is companion chip for Intel Atom E6xx series. | ||
1591 | ML7213 is completely compatible for Intel EG20T PCH. | ||
1592 | |||
1593 | config SERIAL_MSM_SMD | ||
1594 | bool "Enable tty device interface for some SMD ports" | ||
1595 | default n | ||
1596 | depends on MSM_SMD | ||
1597 | help | ||
1598 | Enables userspace clients to read and write to some streaming SMD | ||
1599 | ports via tty device interface for MSM chipset. | ||
1600 | |||
1599 | endmenu | 1601 | endmenu |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 8ea92e9c73b0..31e868cb49b2 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -54,7 +54,6 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o | |||
54 | obj-$(CONFIG_SERIAL_68360) += 68360serial.o | 54 | obj-$(CONFIG_SERIAL_68360) += 68360serial.o |
55 | obj-$(CONFIG_SERIAL_MCF) += mcf.o | 55 | obj-$(CONFIG_SERIAL_MCF) += mcf.o |
56 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o | 56 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o |
57 | obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o | ||
58 | obj-$(CONFIG_SERIAL_DZ) += dz.o | 57 | obj-$(CONFIG_SERIAL_DZ) += dz.o |
59 | obj-$(CONFIG_SERIAL_ZS) += zs.o | 58 | obj-$(CONFIG_SERIAL_ZS) += zs.o |
60 | obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o | 59 | obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o |
@@ -76,6 +75,7 @@ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o | |||
76 | obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o | 75 | obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o |
77 | obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o | 76 | obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o |
78 | obj-$(CONFIG_SERIAL_MSM) += msm_serial.o | 77 | obj-$(CONFIG_SERIAL_MSM) += msm_serial.o |
78 | obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o | ||
79 | obj-$(CONFIG_SERIAL_NETX) += netx-serial.o | 79 | obj-$(CONFIG_SERIAL_NETX) += netx-serial.o |
80 | obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o | 80 | obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o |
81 | obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o | 81 | obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o |
@@ -92,3 +92,4 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o | |||
92 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o | 92 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o |
93 | obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o | 93 | obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o |
94 | obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o | 94 | obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o |
95 | obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o | ||
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index f9b49b5ff5e1..60e049b041a7 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c | |||
@@ -305,28 +305,6 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS]; | |||
305 | 305 | ||
306 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) | 306 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) |
307 | 307 | ||
308 | int __init early_altera_jtaguart_setup(struct altera_jtaguart_platform_uart | ||
309 | *platp) | ||
310 | { | ||
311 | struct uart_port *port; | ||
312 | int i; | ||
313 | |||
314 | for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) { | ||
315 | port = &altera_jtaguart_ports[i].port; | ||
316 | |||
317 | port->line = i; | ||
318 | port->type = PORT_ALTERA_JTAGUART; | ||
319 | port->mapbase = platp[i].mapbase; | ||
320 | port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE); | ||
321 | port->iotype = SERIAL_IO_MEM; | ||
322 | port->irq = platp[i].irq; | ||
323 | port->flags = ASYNC_BOOT_AUTOCONF; | ||
324 | port->ops = &altera_jtaguart_ops; | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | 308 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) |
331 | static void altera_jtaguart_console_putc(struct console *co, const char c) | 309 | static void altera_jtaguart_console_putc(struct console *co, const char c) |
332 | { | 310 | { |
@@ -384,7 +362,7 @@ static int __init altera_jtaguart_console_setup(struct console *co, | |||
384 | if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS) | 362 | if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS) |
385 | return -EINVAL; | 363 | return -EINVAL; |
386 | port = &altera_jtaguart_ports[co->index].port; | 364 | port = &altera_jtaguart_ports[co->index].port; |
387 | if (port->membase == 0) | 365 | if (port->membase == NULL) |
388 | return -ENODEV; | 366 | return -ENODEV; |
389 | return 0; | 367 | return 0; |
390 | } | 368 | } |
@@ -431,22 +409,45 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev) | |||
431 | { | 409 | { |
432 | struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data; | 410 | struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data; |
433 | struct uart_port *port; | 411 | struct uart_port *port; |
434 | int i; | 412 | struct resource *res_irq, *res_mem; |
413 | int i = pdev->id; | ||
435 | 414 | ||
436 | for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) { | 415 | /* -1 emphasizes that the platform must have one port, no .N suffix */ |
437 | port = &altera_jtaguart_ports[i].port; | 416 | if (i == -1) |
417 | i = 0; | ||
438 | 418 | ||
439 | port->line = i; | 419 | if (i >= ALTERA_JTAGUART_MAXPORTS) |
440 | port->type = PORT_ALTERA_JTAGUART; | 420 | return -EINVAL; |
441 | port->mapbase = platp[i].mapbase; | ||
442 | port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE); | ||
443 | port->iotype = SERIAL_IO_MEM; | ||
444 | port->irq = platp[i].irq; | ||
445 | port->ops = &altera_jtaguart_ops; | ||
446 | port->flags = ASYNC_BOOT_AUTOCONF; | ||
447 | 421 | ||
448 | uart_add_one_port(&altera_jtaguart_driver, port); | 422 | port = &altera_jtaguart_ports[i].port; |
449 | } | 423 | |
424 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
425 | if (res_mem) | ||
426 | port->mapbase = res_mem->start; | ||
427 | else if (platp) | ||
428 | port->mapbase = platp->mapbase; | ||
429 | else | ||
430 | return -ENODEV; | ||
431 | |||
432 | res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
433 | if (res_irq) | ||
434 | port->irq = res_irq->start; | ||
435 | else if (platp) | ||
436 | port->irq = platp->irq; | ||
437 | else | ||
438 | return -ENODEV; | ||
439 | |||
440 | port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE); | ||
441 | if (!port->membase) | ||
442 | return -ENOMEM; | ||
443 | |||
444 | port->line = i; | ||
445 | port->type = PORT_ALTERA_JTAGUART; | ||
446 | port->iotype = SERIAL_IO_MEM; | ||
447 | port->ops = &altera_jtaguart_ops; | ||
448 | port->flags = UPF_BOOT_AUTOCONF; | ||
449 | |||
450 | uart_add_one_port(&altera_jtaguart_driver, port); | ||
450 | 451 | ||
451 | return 0; | 452 | return 0; |
452 | } | 453 | } |
@@ -454,23 +455,34 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev) | |||
454 | static int __devexit altera_jtaguart_remove(struct platform_device *pdev) | 455 | static int __devexit altera_jtaguart_remove(struct platform_device *pdev) |
455 | { | 456 | { |
456 | struct uart_port *port; | 457 | struct uart_port *port; |
457 | int i; | 458 | int i = pdev->id; |
458 | 459 | ||
459 | for (i = 0; i < ALTERA_JTAGUART_MAXPORTS; i++) { | 460 | if (i == -1) |
460 | port = &altera_jtaguart_ports[i].port; | 461 | i = 0; |
461 | if (port) | 462 | |
462 | uart_remove_one_port(&altera_jtaguart_driver, port); | 463 | port = &altera_jtaguart_ports[i].port; |
463 | } | 464 | uart_remove_one_port(&altera_jtaguart_driver, port); |
464 | 465 | ||
465 | return 0; | 466 | return 0; |
466 | } | 467 | } |
467 | 468 | ||
469 | #ifdef CONFIG_OF | ||
470 | static struct of_device_id altera_jtaguart_match[] = { | ||
471 | { .compatible = "ALTR,juart-1.0", }, | ||
472 | {}, | ||
473 | }; | ||
474 | MODULE_DEVICE_TABLE(of, altera_jtaguart_match); | ||
475 | #else | ||
476 | #define altera_jtaguart_match NULL | ||
477 | #endif /* CONFIG_OF */ | ||
478 | |||
468 | static struct platform_driver altera_jtaguart_platform_driver = { | 479 | static struct platform_driver altera_jtaguart_platform_driver = { |
469 | .probe = altera_jtaguart_probe, | 480 | .probe = altera_jtaguart_probe, |
470 | .remove = __devexit_p(altera_jtaguart_remove), | 481 | .remove = __devexit_p(altera_jtaguart_remove), |
471 | .driver = { | 482 | .driver = { |
472 | .name = DRV_NAME, | 483 | .name = DRV_NAME, |
473 | .owner = THIS_MODULE, | 484 | .owner = THIS_MODULE, |
485 | .of_match_table = altera_jtaguart_match, | ||
474 | }, | 486 | }, |
475 | }; | 487 | }; |
476 | 488 | ||
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 721216292a50..6d5b036ac783 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/serial.h> | 24 | #include <linux/serial.h> |
25 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/of.h> | ||
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
28 | #include <linux/altera_uart.h> | 29 | #include <linux/altera_uart.h> |
29 | 30 | ||
@@ -86,16 +87,12 @@ struct altera_uart { | |||
86 | 87 | ||
87 | static u32 altera_uart_readl(struct uart_port *port, int reg) | 88 | static u32 altera_uart_readl(struct uart_port *port, int reg) |
88 | { | 89 | { |
89 | struct altera_uart_platform_uart *platp = port->private_data; | 90 | return readl(port->membase + (reg << port->regshift)); |
90 | |||
91 | return readl(port->membase + (reg << platp->bus_shift)); | ||
92 | } | 91 | } |
93 | 92 | ||
94 | static void altera_uart_writel(struct uart_port *port, u32 dat, int reg) | 93 | static void altera_uart_writel(struct uart_port *port, u32 dat, int reg) |
95 | { | 94 | { |
96 | struct altera_uart_platform_uart *platp = port->private_data; | 95 | writel(dat, port->membase + (reg << port->regshift)); |
97 | |||
98 | writel(dat, port->membase + (reg << platp->bus_shift)); | ||
99 | } | 96 | } |
100 | 97 | ||
101 | static unsigned int altera_uart_tx_empty(struct uart_port *port) | 98 | static unsigned int altera_uart_tx_empty(struct uart_port *port) |
@@ -511,6 +508,29 @@ static struct uart_driver altera_uart_driver = { | |||
511 | .cons = ALTERA_UART_CONSOLE, | 508 | .cons = ALTERA_UART_CONSOLE, |
512 | }; | 509 | }; |
513 | 510 | ||
511 | #ifdef CONFIG_OF | ||
512 | static int altera_uart_get_of_uartclk(struct platform_device *pdev, | ||
513 | struct uart_port *port) | ||
514 | { | ||
515 | int len; | ||
516 | const __be32 *clk; | ||
517 | |||
518 | clk = of_get_property(pdev->dev.of_node, "clock-frequency", &len); | ||
519 | if (!clk || len < sizeof(__be32)) | ||
520 | return -ENODEV; | ||
521 | |||
522 | port->uartclk = be32_to_cpup(clk); | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | #else | ||
527 | static int altera_uart_get_of_uartclk(struct platform_device *pdev, | ||
528 | struct uart_port *port) | ||
529 | { | ||
530 | return -ENODEV; | ||
531 | } | ||
532 | #endif /* CONFIG_OF */ | ||
533 | |||
514 | static int __devinit altera_uart_probe(struct platform_device *pdev) | 534 | static int __devinit altera_uart_probe(struct platform_device *pdev) |
515 | { | 535 | { |
516 | struct altera_uart_platform_uart *platp = pdev->dev.platform_data; | 536 | struct altera_uart_platform_uart *platp = pdev->dev.platform_data; |
@@ -518,6 +538,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
518 | struct resource *res_mem; | 538 | struct resource *res_mem; |
519 | struct resource *res_irq; | 539 | struct resource *res_irq; |
520 | int i = pdev->id; | 540 | int i = pdev->id; |
541 | int ret; | ||
521 | 542 | ||
522 | /* -1 emphasizes that the platform must have one port, no .N suffix */ | 543 | /* -1 emphasizes that the platform must have one port, no .N suffix */ |
523 | if (i == -1) | 544 | if (i == -1) |
@@ -542,17 +563,29 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
542 | else if (platp->irq) | 563 | else if (platp->irq) |
543 | port->irq = platp->irq; | 564 | port->irq = platp->irq; |
544 | 565 | ||
566 | /* Check platform data first so we can override device node data */ | ||
567 | if (platp) | ||
568 | port->uartclk = platp->uartclk; | ||
569 | else { | ||
570 | ret = altera_uart_get_of_uartclk(pdev, port); | ||
571 | if (ret) | ||
572 | return ret; | ||
573 | } | ||
574 | |||
545 | port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); | 575 | port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE); |
546 | if (!port->membase) | 576 | if (!port->membase) |
547 | return -ENOMEM; | 577 | return -ENOMEM; |
548 | 578 | ||
579 | if (platp) | ||
580 | port->regshift = platp->bus_shift; | ||
581 | else | ||
582 | port->regshift = 0; | ||
583 | |||
549 | port->line = i; | 584 | port->line = i; |
550 | port->type = PORT_ALTERA_UART; | 585 | port->type = PORT_ALTERA_UART; |
551 | port->iotype = SERIAL_IO_MEM; | 586 | port->iotype = SERIAL_IO_MEM; |
552 | port->uartclk = platp->uartclk; | ||
553 | port->ops = &altera_uart_ops; | 587 | port->ops = &altera_uart_ops; |
554 | port->flags = UPF_BOOT_AUTOCONF; | 588 | port->flags = UPF_BOOT_AUTOCONF; |
555 | port->private_data = platp; | ||
556 | 589 | ||
557 | uart_add_one_port(&altera_uart_driver, port); | 590 | uart_add_one_port(&altera_uart_driver, port); |
558 | 591 | ||
@@ -561,19 +594,35 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
561 | 594 | ||
562 | static int __devexit altera_uart_remove(struct platform_device *pdev) | 595 | static int __devexit altera_uart_remove(struct platform_device *pdev) |
563 | { | 596 | { |
564 | struct uart_port *port = &altera_uart_ports[pdev->id].port; | 597 | struct uart_port *port; |
598 | int i = pdev->id; | ||
599 | |||
600 | if (i == -1) | ||
601 | i = 0; | ||
565 | 602 | ||
603 | port = &altera_uart_ports[i].port; | ||
566 | uart_remove_one_port(&altera_uart_driver, port); | 604 | uart_remove_one_port(&altera_uart_driver, port); |
605 | |||
567 | return 0; | 606 | return 0; |
568 | } | 607 | } |
569 | 608 | ||
609 | #ifdef CONFIG_OF | ||
610 | static struct of_device_id altera_uart_match[] = { | ||
611 | { .compatible = "ALTR,uart-1.0", }, | ||
612 | {}, | ||
613 | }; | ||
614 | MODULE_DEVICE_TABLE(of, altera_uart_match); | ||
615 | #else | ||
616 | #define altera_uart_match NULL | ||
617 | #endif /* CONFIG_OF */ | ||
618 | |||
570 | static struct platform_driver altera_uart_platform_driver = { | 619 | static struct platform_driver altera_uart_platform_driver = { |
571 | .probe = altera_uart_probe, | 620 | .probe = altera_uart_probe, |
572 | .remove = __devexit_p(altera_uart_remove), | 621 | .remove = __devexit_p(altera_uart_remove), |
573 | .driver = { | 622 | .driver = { |
574 | .name = DRV_NAME, | 623 | .name = DRV_NAME, |
575 | .owner = THIS_MODULE, | 624 | .owner = THIS_MODULE, |
576 | .pm = NULL, | 625 | .of_match_table = altera_uart_match, |
577 | }, | 626 | }, |
578 | }; | 627 | }; |
579 | 628 | ||
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 095a5d562618..1ab999b04ef3 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c | |||
@@ -553,8 +553,7 @@ static struct uart_driver grlib_apbuart_driver = { | |||
553 | /* OF Platform Driver */ | 553 | /* OF Platform Driver */ |
554 | /* ======================================================================== */ | 554 | /* ======================================================================== */ |
555 | 555 | ||
556 | static int __devinit apbuart_probe(struct platform_device *op, | 556 | static int __devinit apbuart_probe(struct platform_device *op) |
557 | const struct of_device_id *match) | ||
558 | { | 557 | { |
559 | int i = -1; | 558 | int i = -1; |
560 | struct uart_port *port = NULL; | 559 | struct uart_port *port = NULL; |
@@ -587,7 +586,7 @@ static struct of_device_id __initdata apbuart_match[] = { | |||
587 | {}, | 586 | {}, |
588 | }; | 587 | }; |
589 | 588 | ||
590 | static struct of_platform_driver grlib_apbuart_of_driver = { | 589 | static struct platform_driver grlib_apbuart_of_driver = { |
591 | .probe = apbuart_probe, | 590 | .probe = apbuart_probe, |
592 | .driver = { | 591 | .driver = { |
593 | .owner = THIS_MODULE, | 592 | .owner = THIS_MODULE, |
@@ -676,10 +675,10 @@ static int __init grlib_apbuart_init(void) | |||
676 | return ret; | 675 | return ret; |
677 | } | 676 | } |
678 | 677 | ||
679 | ret = of_register_platform_driver(&grlib_apbuart_of_driver); | 678 | ret = platform_driver_register(&grlib_apbuart_of_driver); |
680 | if (ret) { | 679 | if (ret) { |
681 | printk(KERN_ERR | 680 | printk(KERN_ERR |
682 | "%s: of_register_platform_driver failed (%i)\n", | 681 | "%s: platform_driver_register failed (%i)\n", |
683 | __FILE__, ret); | 682 | __FILE__, ret); |
684 | uart_unregister_driver(&grlib_apbuart_driver); | 683 | uart_unregister_driver(&grlib_apbuart_driver); |
685 | return ret; | 684 | return ret; |
@@ -697,7 +696,7 @@ static void __exit grlib_apbuart_exit(void) | |||
697 | &grlib_apbuart_ports[i]); | 696 | &grlib_apbuart_ports[i]); |
698 | 697 | ||
699 | uart_unregister_driver(&grlib_apbuart_driver); | 698 | uart_unregister_driver(&grlib_apbuart_driver); |
700 | of_unregister_platform_driver(&grlib_apbuart_of_driver); | 699 | platform_driver_unregister(&grlib_apbuart_of_driver); |
701 | } | 700 | } |
702 | 701 | ||
703 | module_init(grlib_apbuart_init); | 702 | module_init(grlib_apbuart_init); |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 2a1d52fb4936..f119d1761106 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -1240,6 +1240,21 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1240 | spin_unlock_irqrestore(&port->lock, flags); | 1240 | spin_unlock_irqrestore(&port->lock, flags); |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | static void atmel_set_ldisc(struct uart_port *port, int new) | ||
1244 | { | ||
1245 | int line = port->line; | ||
1246 | |||
1247 | if (line >= port->state->port.tty->driver->num) | ||
1248 | return; | ||
1249 | |||
1250 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
1251 | port->flags |= UPF_HARDPPS_CD; | ||
1252 | atmel_enable_ms(port); | ||
1253 | } else { | ||
1254 | port->flags &= ~UPF_HARDPPS_CD; | ||
1255 | } | ||
1256 | } | ||
1257 | |||
1243 | /* | 1258 | /* |
1244 | * Return string describing the specified port | 1259 | * Return string describing the specified port |
1245 | */ | 1260 | */ |
@@ -1380,6 +1395,7 @@ static struct uart_ops atmel_pops = { | |||
1380 | .shutdown = atmel_shutdown, | 1395 | .shutdown = atmel_shutdown, |
1381 | .flush_buffer = atmel_flush_buffer, | 1396 | .flush_buffer = atmel_flush_buffer, |
1382 | .set_termios = atmel_set_termios, | 1397 | .set_termios = atmel_set_termios, |
1398 | .set_ldisc = atmel_set_ldisc, | ||
1383 | .type = atmel_type, | 1399 | .type = atmel_type, |
1384 | .release_port = atmel_release_port, | 1400 | .release_port = atmel_release_port, |
1385 | .request_port = atmel_request_port, | 1401 | .request_port = atmel_request_port, |
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index e95c524d9d18..c3ec0a61d859 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c | |||
@@ -788,7 +788,7 @@ static int __devinit sport_uart_probe(struct platform_device *pdev) | |||
788 | sport->port.mapbase = res->start; | 788 | sport->port.mapbase = res->start; |
789 | 789 | ||
790 | sport->port.irq = platform_get_irq(pdev, 0); | 790 | sport->port.irq = platform_get_irq(pdev, 0); |
791 | if (sport->port.irq < 0) { | 791 | if ((int)sport->port.irq < 0) { |
792 | dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n"); | 792 | dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n"); |
793 | ret = -ENOENT; | 793 | ret = -ENOENT; |
794 | goto out_error_unmap; | 794 | goto out_error_unmap; |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 8692ff98fc07..a9a6a5fd169e 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1359,8 +1359,7 @@ static struct uart_driver cpm_reg = { | |||
1359 | 1359 | ||
1360 | static int probe_index; | 1360 | static int probe_index; |
1361 | 1361 | ||
1362 | static int __devinit cpm_uart_probe(struct platform_device *ofdev, | 1362 | static int __devinit cpm_uart_probe(struct platform_device *ofdev) |
1363 | const struct of_device_id *match) | ||
1364 | { | 1363 | { |
1365 | int index = probe_index++; | 1364 | int index = probe_index++; |
1366 | struct uart_cpm_port *pinfo = &cpm_uart_ports[index]; | 1365 | struct uart_cpm_port *pinfo = &cpm_uart_ports[index]; |
@@ -1405,7 +1404,7 @@ static struct of_device_id cpm_uart_match[] = { | |||
1405 | {} | 1404 | {} |
1406 | }; | 1405 | }; |
1407 | 1406 | ||
1408 | static struct of_platform_driver cpm_uart_driver = { | 1407 | static struct platform_driver cpm_uart_driver = { |
1409 | .driver = { | 1408 | .driver = { |
1410 | .name = "cpm_uart", | 1409 | .name = "cpm_uart", |
1411 | .owner = THIS_MODULE, | 1410 | .owner = THIS_MODULE, |
@@ -1421,7 +1420,7 @@ static int __init cpm_uart_init(void) | |||
1421 | if (ret) | 1420 | if (ret) |
1422 | return ret; | 1421 | return ret; |
1423 | 1422 | ||
1424 | ret = of_register_platform_driver(&cpm_uart_driver); | 1423 | ret = platform_driver_register(&cpm_uart_driver); |
1425 | if (ret) | 1424 | if (ret) |
1426 | uart_unregister_driver(&cpm_reg); | 1425 | uart_unregister_driver(&cpm_reg); |
1427 | 1426 | ||
@@ -1430,7 +1429,7 @@ static int __init cpm_uart_init(void) | |||
1430 | 1429 | ||
1431 | static void __exit cpm_uart_exit(void) | 1430 | static void __exit cpm_uart_exit(void) |
1432 | { | 1431 | { |
1433 | of_unregister_platform_driver(&cpm_uart_driver); | 1432 | platform_driver_unregister(&cpm_uart_driver); |
1434 | uart_unregister_driver(&cpm_reg); | 1433 | uart_unregister_driver(&cpm_reg); |
1435 | } | 1434 | } |
1436 | 1435 | ||
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index bcc31f2140ac..225123b37f19 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c | |||
@@ -3581,8 +3581,7 @@ rs_break(struct tty_struct *tty, int break_state) | |||
3581 | } | 3581 | } |
3582 | 3582 | ||
3583 | static int | 3583 | static int |
3584 | rs_tiocmset(struct tty_struct *tty, struct file *file, | 3584 | rs_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) |
3585 | unsigned int set, unsigned int clear) | ||
3586 | { | 3585 | { |
3587 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | 3586 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
3588 | unsigned long flags; | 3587 | unsigned long flags; |
@@ -3614,7 +3613,7 @@ rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
3614 | } | 3613 | } |
3615 | 3614 | ||
3616 | static int | 3615 | static int |
3617 | rs_tiocmget(struct tty_struct *tty, struct file *file) | 3616 | rs_tiocmget(struct tty_struct *tty) |
3618 | { | 3617 | { |
3619 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; | 3618 | struct e100_serial *info = (struct e100_serial *)tty->driver_data; |
3620 | unsigned int result; | 3619 | unsigned int result; |
@@ -3648,7 +3647,7 @@ rs_tiocmget(struct tty_struct *tty, struct file *file) | |||
3648 | 3647 | ||
3649 | 3648 | ||
3650 | static int | 3649 | static int |
3651 | rs_ioctl(struct tty_struct *tty, struct file * file, | 3650 | rs_ioctl(struct tty_struct *tty, |
3652 | unsigned int cmd, unsigned long arg) | 3651 | unsigned int cmd, unsigned long arg) |
3653 | { | 3652 | { |
3654 | struct e100_serial * info = (struct e100_serial *)tty->driver_data; | 3653 | struct e100_serial * info = (struct e100_serial *)tty->driver_data; |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index ab93763862d5..8ee5a41d340d 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Jan Dumon <j.dumon@option.com> | 8 | * Jan Dumon <j.dumon@option.com> |
9 | * | 9 | * |
10 | * Copyright (C) 2009, 2010 Intel Corp | 10 | * Copyright (C) 2009, 2010 Intel Corp |
11 | * Russ Gorby <richardx.r.gorby@intel.com> | 11 | * Russ Gorby <russ.gorby@intel.com> |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
@@ -67,6 +67,7 @@ | |||
67 | #define IFX_SPI_MORE_MASK 0x10 | 67 | #define IFX_SPI_MORE_MASK 0x10 |
68 | #define IFX_SPI_MORE_BIT 12 /* bit position in u16 */ | 68 | #define IFX_SPI_MORE_BIT 12 /* bit position in u16 */ |
69 | #define IFX_SPI_CTS_BIT 13 /* bit position in u16 */ | 69 | #define IFX_SPI_CTS_BIT 13 /* bit position in u16 */ |
70 | #define IFX_SPI_MODE SPI_MODE_1 | ||
70 | #define IFX_SPI_TTY_ID 0 | 71 | #define IFX_SPI_TTY_ID 0 |
71 | #define IFX_SPI_TIMEOUT_SEC 2 | 72 | #define IFX_SPI_TIMEOUT_SEC 2 |
72 | #define IFX_SPI_HEADER_0 (-1) | 73 | #define IFX_SPI_HEADER_0 (-1) |
@@ -76,7 +77,7 @@ | |||
76 | static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); | 77 | static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); |
77 | 78 | ||
78 | /* local variables */ | 79 | /* local variables */ |
79 | static int spi_b16 = 1; /* 8 or 16 bit word length */ | 80 | static int spi_bpw = 16; /* 8, 16 or 32 bit word length */ |
80 | static struct tty_driver *tty_drv; | 81 | static struct tty_driver *tty_drv; |
81 | static struct ifx_spi_device *saved_ifx_dev; | 82 | static struct ifx_spi_device *saved_ifx_dev; |
82 | static struct lock_class_key ifx_spi_key; | 83 | static struct lock_class_key ifx_spi_key; |
@@ -244,7 +245,7 @@ static void ifx_spi_timeout(unsigned long arg) | |||
244 | * Map the signal state into Linux modem flags and report the value | 245 | * Map the signal state into Linux modem flags and report the value |
245 | * in Linux terms | 246 | * in Linux terms |
246 | */ | 247 | */ |
247 | static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp) | 248 | static int ifx_spi_tiocmget(struct tty_struct *tty) |
248 | { | 249 | { |
249 | unsigned int value; | 250 | unsigned int value; |
250 | struct ifx_spi_device *ifx_dev = tty->driver_data; | 251 | struct ifx_spi_device *ifx_dev = tty->driver_data; |
@@ -262,7 +263,6 @@ static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp) | |||
262 | /** | 263 | /** |
263 | * ifx_spi_tiocmset - set modem bits | 264 | * ifx_spi_tiocmset - set modem bits |
264 | * @tty: the tty structure | 265 | * @tty: the tty structure |
265 | * @filp: file handle issuing the request | ||
266 | * @set: bits to set | 266 | * @set: bits to set |
267 | * @clear: bits to clear | 267 | * @clear: bits to clear |
268 | * | 268 | * |
@@ -271,7 +271,7 @@ static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp) | |||
271 | * | 271 | * |
272 | * FIXME: do we need to kick the tranfers when we do this ? | 272 | * FIXME: do we need to kick the tranfers when we do this ? |
273 | */ | 273 | */ |
274 | static int ifx_spi_tiocmset(struct tty_struct *tty, struct file *filp, | 274 | static int ifx_spi_tiocmset(struct tty_struct *tty, |
275 | unsigned int set, unsigned int clear) | 275 | unsigned int set, unsigned int clear) |
276 | { | 276 | { |
277 | struct ifx_spi_device *ifx_dev = tty->driver_data; | 277 | struct ifx_spi_device *ifx_dev = tty->driver_data; |
@@ -722,9 +722,9 @@ static void ifx_spi_io(unsigned long data) | |||
722 | /* note len is BYTES, not transfers */ | 722 | /* note len is BYTES, not transfers */ |
723 | ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE; | 723 | ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE; |
724 | ifx_dev->spi_xfer.cs_change = 0; | 724 | ifx_dev->spi_xfer.cs_change = 0; |
725 | ifx_dev->spi_xfer.speed_hz = 12500000; | 725 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; |
726 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ | 726 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ |
727 | ifx_dev->spi_xfer.bits_per_word = spi_b16 ? 16 : 8; | 727 | ifx_dev->spi_xfer.bits_per_word = spi_bpw; |
728 | 728 | ||
729 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; | 729 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; |
730 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; | 730 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; |
@@ -732,7 +732,7 @@ static void ifx_spi_io(unsigned long data) | |||
732 | /* | 732 | /* |
733 | * setup dma pointers | 733 | * setup dma pointers |
734 | */ | 734 | */ |
735 | if (ifx_dev->is_6160) { | 735 | if (ifx_dev->use_dma) { |
736 | ifx_dev->spi_msg.is_dma_mapped = 1; | 736 | ifx_dev->spi_msg.is_dma_mapped = 1; |
737 | ifx_dev->tx_dma = ifx_dev->tx_bus; | 737 | ifx_dev->tx_dma = ifx_dev->tx_bus; |
738 | ifx_dev->rx_dma = ifx_dev->rx_bus; | 738 | ifx_dev->rx_dma = ifx_dev->rx_bus; |
@@ -798,8 +798,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev) | |||
798 | goto error_ret; | 798 | goto error_ret; |
799 | } | 799 | } |
800 | 800 | ||
801 | pport->ops = &ifx_tty_port_ops; | ||
802 | tty_port_init(pport); | 801 | tty_port_init(pport); |
802 | pport->ops = &ifx_tty_port_ops; | ||
803 | ifx_dev->minor = IFX_SPI_TTY_ID; | 803 | ifx_dev->minor = IFX_SPI_TTY_ID; |
804 | ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor, | 804 | ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor, |
805 | &ifx_dev->spi_dev->dev); | 805 | &ifx_dev->spi_dev->dev); |
@@ -960,7 +960,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) | |||
960 | { | 960 | { |
961 | int ret; | 961 | int ret; |
962 | int srdy; | 962 | int srdy; |
963 | struct ifx_modem_platform_data *pl_data = NULL; | 963 | struct ifx_modem_platform_data *pl_data; |
964 | struct ifx_spi_device *ifx_dev; | 964 | struct ifx_spi_device *ifx_dev; |
965 | 965 | ||
966 | if (saved_ifx_dev) { | 966 | if (saved_ifx_dev) { |
@@ -968,6 +968,12 @@ static int ifx_spi_spi_probe(struct spi_device *spi) | |||
968 | return -ENODEV; | 968 | return -ENODEV; |
969 | } | 969 | } |
970 | 970 | ||
971 | pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data; | ||
972 | if (!pl_data) { | ||
973 | dev_err(&spi->dev, "missing platform data!"); | ||
974 | return -ENODEV; | ||
975 | } | ||
976 | |||
971 | /* initialize structure to hold our device variables */ | 977 | /* initialize structure to hold our device variables */ |
972 | ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL); | 978 | ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL); |
973 | if (!ifx_dev) { | 979 | if (!ifx_dev) { |
@@ -983,14 +989,25 @@ static int ifx_spi_spi_probe(struct spi_device *spi) | |||
983 | init_timer(&ifx_dev->spi_timer); | 989 | init_timer(&ifx_dev->spi_timer); |
984 | ifx_dev->spi_timer.function = ifx_spi_timeout; | 990 | ifx_dev->spi_timer.function = ifx_spi_timeout; |
985 | ifx_dev->spi_timer.data = (unsigned long)ifx_dev; | 991 | ifx_dev->spi_timer.data = (unsigned long)ifx_dev; |
986 | ifx_dev->is_6160 = pl_data->is_6160; | 992 | ifx_dev->modem = pl_data->modem_type; |
993 | ifx_dev->use_dma = pl_data->use_dma; | ||
994 | ifx_dev->max_hz = pl_data->max_hz; | ||
995 | /* initialize spi mode, etc */ | ||
996 | spi->max_speed_hz = ifx_dev->max_hz; | ||
997 | spi->mode = IFX_SPI_MODE | (SPI_LOOP & spi->mode); | ||
998 | spi->bits_per_word = spi_bpw; | ||
999 | ret = spi_setup(spi); | ||
1000 | if (ret) { | ||
1001 | dev_err(&spi->dev, "SPI setup wasn't successful %d", ret); | ||
1002 | return -ENODEV; | ||
1003 | } | ||
987 | 1004 | ||
988 | /* ensure SPI protocol flags are initialized to enable transfer */ | 1005 | /* ensure SPI protocol flags are initialized to enable transfer */ |
989 | ifx_dev->spi_more = 0; | 1006 | ifx_dev->spi_more = 0; |
990 | ifx_dev->spi_slave_cts = 0; | 1007 | ifx_dev->spi_slave_cts = 0; |
991 | 1008 | ||
992 | /*initialize transfer and dma buffers */ | 1009 | /*initialize transfer and dma buffers */ |
993 | ifx_dev->tx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev, | 1010 | ifx_dev->tx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, |
994 | IFX_SPI_TRANSFER_SIZE, | 1011 | IFX_SPI_TRANSFER_SIZE, |
995 | &ifx_dev->tx_bus, | 1012 | &ifx_dev->tx_bus, |
996 | GFP_KERNEL); | 1013 | GFP_KERNEL); |
@@ -999,7 +1016,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) | |||
999 | ret = -ENOMEM; | 1016 | ret = -ENOMEM; |
1000 | goto error_ret; | 1017 | goto error_ret; |
1001 | } | 1018 | } |
1002 | ifx_dev->rx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev, | 1019 | ifx_dev->rx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, |
1003 | IFX_SPI_TRANSFER_SIZE, | 1020 | IFX_SPI_TRANSFER_SIZE, |
1004 | &ifx_dev->rx_bus, | 1021 | &ifx_dev->rx_bus, |
1005 | GFP_KERNEL); | 1022 | GFP_KERNEL); |
@@ -1025,18 +1042,11 @@ static int ifx_spi_spi_probe(struct spi_device *spi) | |||
1025 | goto error_ret; | 1042 | goto error_ret; |
1026 | } | 1043 | } |
1027 | 1044 | ||
1028 | pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data; | 1045 | ifx_dev->gpio.reset = pl_data->rst_pmu; |
1029 | if (pl_data) { | 1046 | ifx_dev->gpio.po = pl_data->pwr_on; |
1030 | ifx_dev->gpio.reset = pl_data->rst_pmu; | 1047 | ifx_dev->gpio.mrdy = pl_data->mrdy; |
1031 | ifx_dev->gpio.po = pl_data->pwr_on; | 1048 | ifx_dev->gpio.srdy = pl_data->srdy; |
1032 | ifx_dev->gpio.mrdy = pl_data->mrdy; | 1049 | ifx_dev->gpio.reset_out = pl_data->rst_out; |
1033 | ifx_dev->gpio.srdy = pl_data->srdy; | ||
1034 | ifx_dev->gpio.reset_out = pl_data->rst_out; | ||
1035 | } else { | ||
1036 | dev_err(&spi->dev, "missing platform data!"); | ||
1037 | ret = -ENODEV; | ||
1038 | goto error_ret; | ||
1039 | } | ||
1040 | 1050 | ||
1041 | dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d", | 1051 | dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d", |
1042 | ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy, | 1052 | ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy, |
@@ -1322,9 +1332,9 @@ static const struct spi_device_id ifx_id_table[] = { | |||
1322 | MODULE_DEVICE_TABLE(spi, ifx_id_table); | 1332 | MODULE_DEVICE_TABLE(spi, ifx_id_table); |
1323 | 1333 | ||
1324 | /* spi operations */ | 1334 | /* spi operations */ |
1325 | static const struct spi_driver ifx_spi_driver_6160 = { | 1335 | static const struct spi_driver ifx_spi_driver = { |
1326 | .driver = { | 1336 | .driver = { |
1327 | .name = "ifx6160", | 1337 | .name = DRVNAME, |
1328 | .bus = &spi_bus_type, | 1338 | .bus = &spi_bus_type, |
1329 | .pm = &ifx_spi_pm, | 1339 | .pm = &ifx_spi_pm, |
1330 | .owner = THIS_MODULE}, | 1340 | .owner = THIS_MODULE}, |
@@ -1346,7 +1356,7 @@ static void __exit ifx_spi_exit(void) | |||
1346 | { | 1356 | { |
1347 | /* unregister */ | 1357 | /* unregister */ |
1348 | tty_unregister_driver(tty_drv); | 1358 | tty_unregister_driver(tty_drv); |
1349 | spi_unregister_driver((void *)&ifx_spi_driver_6160); | 1359 | spi_unregister_driver((void *)&ifx_spi_driver); |
1350 | } | 1360 | } |
1351 | 1361 | ||
1352 | /** | 1362 | /** |
@@ -1388,7 +1398,7 @@ static int __init ifx_spi_init(void) | |||
1388 | return result; | 1398 | return result; |
1389 | } | 1399 | } |
1390 | 1400 | ||
1391 | result = spi_register_driver((void *)&ifx_spi_driver_6160); | 1401 | result = spi_register_driver((void *)&ifx_spi_driver); |
1392 | if (result) { | 1402 | if (result) { |
1393 | pr_err("%s: spi_register_driver failed(%d)", | 1403 | pr_err("%s: spi_register_driver failed(%d)", |
1394 | DRVNAME, result); | 1404 | DRVNAME, result); |
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h index deb7b8d977dc..e8464baf9e75 100644 --- a/drivers/tty/serial/ifx6x60.h +++ b/drivers/tty/serial/ifx6x60.h | |||
@@ -29,8 +29,6 @@ | |||
29 | #define DRVNAME "ifx6x60" | 29 | #define DRVNAME "ifx6x60" |
30 | #define TTYNAME "ttyIFX" | 30 | #define TTYNAME "ttyIFX" |
31 | 31 | ||
32 | /* #define IFX_THROTTLE_CODE */ | ||
33 | |||
34 | #define IFX_SPI_MAX_MINORS 1 | 32 | #define IFX_SPI_MAX_MINORS 1 |
35 | #define IFX_SPI_TRANSFER_SIZE 2048 | 33 | #define IFX_SPI_TRANSFER_SIZE 2048 |
36 | #define IFX_SPI_FIFO_SIZE 4096 | 34 | #define IFX_SPI_FIFO_SIZE 4096 |
@@ -88,7 +86,9 @@ struct ifx_spi_device { | |||
88 | dma_addr_t rx_dma; | 86 | dma_addr_t rx_dma; |
89 | dma_addr_t tx_dma; | 87 | dma_addr_t tx_dma; |
90 | 88 | ||
91 | int is_6160; /* Modem type */ | 89 | int modem; /* Modem type */ |
90 | int use_dma; /* provide dma-able addrs in SPI msg */ | ||
91 | long max_hz; /* max SPI frequency */ | ||
92 | 92 | ||
93 | spinlock_t write_lock; | 93 | spinlock_t write_lock; |
94 | int write_pending; | 94 | int write_pending; |
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index beb1afa27d8d..7b951adac54b 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c | |||
@@ -601,7 +601,7 @@ static int max3100_startup(struct uart_port *port) | |||
601 | s->rts = 0; | 601 | s->rts = 0; |
602 | 602 | ||
603 | sprintf(b, "max3100-%d", s->minor); | 603 | sprintf(b, "max3100-%d", s->minor); |
604 | s->workqueue = create_freezeable_workqueue(b); | 604 | s->workqueue = create_freezable_workqueue(b); |
605 | if (!s->workqueue) { | 605 | if (!s->workqueue) { |
606 | dev_warn(&s->spi->dev, "cannot create workqueue\n"); | 606 | dev_warn(&s->spi->dev, "cannot create workqueue\n"); |
607 | return -EBUSY; | 607 | return -EBUSY; |
diff --git a/drivers/tty/serial/max3107.c b/drivers/tty/serial/max3107.c index 910870edf708..750b4f627315 100644 --- a/drivers/tty/serial/max3107.c +++ b/drivers/tty/serial/max3107.c | |||
@@ -833,7 +833,7 @@ static int max3107_startup(struct uart_port *port) | |||
833 | struct max3107_port *s = container_of(port, struct max3107_port, port); | 833 | struct max3107_port *s = container_of(port, struct max3107_port, port); |
834 | 834 | ||
835 | /* Initialize work queue */ | 835 | /* Initialize work queue */ |
836 | s->workqueue = create_freezeable_workqueue("max3107"); | 836 | s->workqueue = create_freezable_workqueue("max3107"); |
837 | if (!s->workqueue) { | 837 | if (!s->workqueue) { |
838 | dev_err(&s->spi->dev, "Workqueue creation failed\n"); | 838 | dev_err(&s->spi->dev, "Workqueue creation failed\n"); |
839 | return -EBUSY; | 839 | return -EBUSY; |
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index d40010a22ecd..c111f36f5d21 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -16,9 +16,7 @@ | |||
16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans | 16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans |
17 | * are used for RX, odd chans for TX | 17 | * are used for RX, odd chans for TX |
18 | * | 18 | * |
19 | * 2. In A0 stepping, UART will not support TX half empty flag | 19 | * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always |
20 | * | ||
21 | * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always | ||
22 | * asserted, only when the HW is reset the DDCD and DDSR will | 20 | * asserted, only when the HW is reset the DDCD and DDSR will |
23 | * be triggered | 21 | * be triggered |
24 | */ | 22 | */ |
@@ -41,8 +39,6 @@ | |||
41 | #include <linux/io.h> | 39 | #include <linux/io.h> |
42 | #include <linux/debugfs.h> | 40 | #include <linux/debugfs.h> |
43 | 41 | ||
44 | #define MFD_HSU_A0_STEPPING 1 | ||
45 | |||
46 | #define HSU_DMA_BUF_SIZE 2048 | 42 | #define HSU_DMA_BUF_SIZE 2048 |
47 | 43 | ||
48 | #define chan_readl(chan, offset) readl(chan->reg + offset) | 44 | #define chan_readl(chan, offset) readl(chan->reg + offset) |
@@ -51,7 +47,10 @@ | |||
51 | #define mfd_readl(obj, offset) readl(obj->reg + offset) | 47 | #define mfd_readl(obj, offset) readl(obj->reg + offset) |
52 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) | 48 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) |
53 | 49 | ||
54 | #define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) | 50 | static int hsu_dma_enable; |
51 | module_param(hsu_dma_enable, int, 0); | ||
52 | MODULE_PARM_DESC(hsu_dma_enable, "It is a bitmap to set working mode, if \ | ||
53 | bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode."); | ||
55 | 54 | ||
56 | struct hsu_dma_buffer { | 55 | struct hsu_dma_buffer { |
57 | u8 *buf; | 56 | u8 *buf; |
@@ -65,7 +64,6 @@ struct hsu_dma_chan { | |||
65 | enum dma_data_direction dirt; | 64 | enum dma_data_direction dirt; |
66 | struct uart_hsu_port *uport; | 65 | struct uart_hsu_port *uport; |
67 | void __iomem *reg; | 66 | void __iomem *reg; |
68 | struct timer_list rx_timer; /* only needed by RX channel */ | ||
69 | }; | 67 | }; |
70 | 68 | ||
71 | struct uart_hsu_port { | 69 | struct uart_hsu_port { |
@@ -355,8 +353,6 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf | |||
355 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | 353 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ |
356 | ); | 354 | ); |
357 | chan_writel(rxc, HSU_CH_CR, 0x3); | 355 | chan_writel(rxc, HSU_CH_CR, 0x3); |
358 | |||
359 | mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
360 | } | 356 | } |
361 | 357 | ||
362 | /* Protected by spin_lock_irqsave(port->lock) */ | 358 | /* Protected by spin_lock_irqsave(port->lock) */ |
@@ -420,7 +416,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | |||
420 | chan_writel(chan, HSU_CH_CR, 0x3); | 416 | chan_writel(chan, HSU_CH_CR, 0x3); |
421 | return; | 417 | return; |
422 | } | 418 | } |
423 | del_timer(&chan->rx_timer); | ||
424 | 419 | ||
425 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, | 420 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, |
426 | dbuf->dma_size, DMA_FROM_DEVICE); | 421 | dbuf->dma_size, DMA_FROM_DEVICE); |
@@ -448,8 +443,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | |||
448 | tty_flip_buffer_push(tty); | 443 | tty_flip_buffer_push(tty); |
449 | 444 | ||
450 | chan_writel(chan, HSU_CH_CR, 0x3); | 445 | chan_writel(chan, HSU_CH_CR, 0x3); |
451 | chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; | ||
452 | add_timer(&chan->rx_timer); | ||
453 | 446 | ||
454 | } | 447 | } |
455 | 448 | ||
@@ -551,16 +544,9 @@ static void transmit_chars(struct uart_hsu_port *up) | |||
551 | return; | 544 | return; |
552 | } | 545 | } |
553 | 546 | ||
554 | #ifndef MFD_HSU_A0_STEPPING | 547 | /* The IRQ is for TX FIFO half-empty */ |
555 | count = up->port.fifosize / 2; | 548 | count = up->port.fifosize / 2; |
556 | #else | 549 | |
557 | /* | ||
558 | * A0 only supports fully empty IRQ, and the first char written | ||
559 | * into it won't clear the EMPT bit, so we may need be cautious | ||
560 | * by useing a shorter buffer | ||
561 | */ | ||
562 | count = up->port.fifosize - 4; | ||
563 | #endif | ||
564 | do { | 550 | do { |
565 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | 551 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); |
566 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 552 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
@@ -769,9 +755,8 @@ static void serial_hsu_break_ctl(struct uart_port *port, int break_state) | |||
769 | /* | 755 | /* |
770 | * What special to do: | 756 | * What special to do: |
771 | * 1. chose the 64B fifo mode | 757 | * 1. chose the 64B fifo mode |
772 | * 2. make sure not to select half empty mode for A0 stepping | 758 | * 2. start dma or pio depends on configuration |
773 | * 3. start dma or pio depends on configuration | 759 | * 3. we only allocate dma memory when needed |
774 | * 4. we only allocate dma memory when needed | ||
775 | */ | 760 | */ |
776 | static int serial_hsu_startup(struct uart_port *port) | 761 | static int serial_hsu_startup(struct uart_port *port) |
777 | { | 762 | { |
@@ -870,8 +855,6 @@ static void serial_hsu_shutdown(struct uart_port *port) | |||
870 | container_of(port, struct uart_hsu_port, port); | 855 | container_of(port, struct uart_hsu_port, port); |
871 | unsigned long flags; | 856 | unsigned long flags; |
872 | 857 | ||
873 | del_timer_sync(&up->rxc->rx_timer); | ||
874 | |||
875 | /* Disable interrupts from this port */ | 858 | /* Disable interrupts from this port */ |
876 | up->ier = 0; | 859 | up->ier = 0; |
877 | serial_out(up, UART_IER, 0); | 860 | serial_out(up, UART_IER, 0); |
@@ -977,10 +960,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | |||
977 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; | 960 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; |
978 | 961 | ||
979 | fcr |= UART_FCR_HSU_64B_FIFO; | 962 | fcr |= UART_FCR_HSU_64B_FIFO; |
980 | #ifdef MFD_HSU_A0_STEPPING | ||
981 | /* A0 doesn't support half empty IRQ */ | ||
982 | fcr |= UART_FCR_FULL_EMPT_TXI; | ||
983 | #endif | ||
984 | 963 | ||
985 | /* | 964 | /* |
986 | * Ok, we're now changing the port state. Do it with | 965 | * Ok, we're now changing the port state. Do it with |
@@ -1343,28 +1322,6 @@ err_disable: | |||
1343 | return ret; | 1322 | return ret; |
1344 | } | 1323 | } |
1345 | 1324 | ||
1346 | static void hsu_dma_rx_timeout(unsigned long data) | ||
1347 | { | ||
1348 | struct hsu_dma_chan *chan = (void *)data; | ||
1349 | struct uart_hsu_port *up = chan->uport; | ||
1350 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
1351 | int count = 0; | ||
1352 | unsigned long flags; | ||
1353 | |||
1354 | spin_lock_irqsave(&up->port.lock, flags); | ||
1355 | |||
1356 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
1357 | |||
1358 | if (!count) { | ||
1359 | mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
1360 | goto exit; | ||
1361 | } | ||
1362 | |||
1363 | hsu_dma_rx(up, 0); | ||
1364 | exit: | ||
1365 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1366 | } | ||
1367 | |||
1368 | static void hsu_global_init(void) | 1325 | static void hsu_global_init(void) |
1369 | { | 1326 | { |
1370 | struct hsu_port *hsu; | 1327 | struct hsu_port *hsu; |
@@ -1415,6 +1372,12 @@ static void hsu_global_init(void) | |||
1415 | 1372 | ||
1416 | serial_hsu_ports[i] = uport; | 1373 | serial_hsu_ports[i] = uport; |
1417 | uport->index = i; | 1374 | uport->index = i; |
1375 | |||
1376 | if (hsu_dma_enable & (1<<i)) | ||
1377 | uport->use_dma = 1; | ||
1378 | else | ||
1379 | uport->use_dma = 0; | ||
1380 | |||
1418 | uport++; | 1381 | uport++; |
1419 | } | 1382 | } |
1420 | 1383 | ||
@@ -1427,12 +1390,6 @@ static void hsu_global_init(void) | |||
1427 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + | 1390 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + |
1428 | i * HSU_DMA_CHANS_REG_LENGTH; | 1391 | i * HSU_DMA_CHANS_REG_LENGTH; |
1429 | 1392 | ||
1430 | /* Work around for RX */ | ||
1431 | if (dchan->dirt == DMA_FROM_DEVICE) { | ||
1432 | init_timer(&dchan->rx_timer); | ||
1433 | dchan->rx_timer.function = hsu_dma_rx_timeout; | ||
1434 | dchan->rx_timer.data = (unsigned long)dchan; | ||
1435 | } | ||
1436 | dchan++; | 1393 | dchan++; |
1437 | } | 1394 | } |
1438 | 1395 | ||
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 126ec7f568ec..a0bcd8a3758d 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -1302,8 +1302,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
1302 | {}, | 1302 | {}, |
1303 | }; | 1303 | }; |
1304 | 1304 | ||
1305 | static int __devinit | 1305 | static int __devinit mpc52xx_uart_of_probe(struct platform_device *op) |
1306 | mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) | ||
1307 | { | 1306 | { |
1308 | int idx = -1; | 1307 | int idx = -1; |
1309 | unsigned int uartclk; | 1308 | unsigned int uartclk; |
@@ -1311,8 +1310,6 @@ mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *mat | |||
1311 | struct resource res; | 1310 | struct resource res; |
1312 | int ret; | 1311 | int ret; |
1313 | 1312 | ||
1314 | dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); | ||
1315 | |||
1316 | /* Check validity & presence */ | 1313 | /* Check validity & presence */ |
1317 | for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) | 1314 | for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) |
1318 | if (mpc52xx_uart_nodes[idx] == op->dev.of_node) | 1315 | if (mpc52xx_uart_nodes[idx] == op->dev.of_node) |
@@ -1453,7 +1450,7 @@ mpc52xx_uart_of_enumerate(void) | |||
1453 | 1450 | ||
1454 | MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); | 1451 | MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); |
1455 | 1452 | ||
1456 | static struct of_platform_driver mpc52xx_uart_of_driver = { | 1453 | static struct platform_driver mpc52xx_uart_of_driver = { |
1457 | .probe = mpc52xx_uart_of_probe, | 1454 | .probe = mpc52xx_uart_of_probe, |
1458 | .remove = mpc52xx_uart_of_remove, | 1455 | .remove = mpc52xx_uart_of_remove, |
1459 | #ifdef CONFIG_PM | 1456 | #ifdef CONFIG_PM |
@@ -1497,9 +1494,9 @@ mpc52xx_uart_init(void) | |||
1497 | return ret; | 1494 | return ret; |
1498 | } | 1495 | } |
1499 | 1496 | ||
1500 | ret = of_register_platform_driver(&mpc52xx_uart_of_driver); | 1497 | ret = platform_driver_register(&mpc52xx_uart_of_driver); |
1501 | if (ret) { | 1498 | if (ret) { |
1502 | printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", | 1499 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", |
1503 | __FILE__, ret); | 1500 | __FILE__, ret); |
1504 | uart_unregister_driver(&mpc52xx_uart_driver); | 1501 | uart_unregister_driver(&mpc52xx_uart_driver); |
1505 | return ret; | 1502 | return ret; |
@@ -1514,7 +1511,7 @@ mpc52xx_uart_exit(void) | |||
1514 | if (psc_ops->fifoc_uninit) | 1511 | if (psc_ops->fifoc_uninit) |
1515 | psc_ops->fifoc_uninit(); | 1512 | psc_ops->fifoc_uninit(); |
1516 | 1513 | ||
1517 | of_unregister_platform_driver(&mpc52xx_uart_of_driver); | 1514 | platform_driver_unregister(&mpc52xx_uart_of_driver); |
1518 | uart_unregister_driver(&mpc52xx_uart_driver); | 1515 | uart_unregister_driver(&mpc52xx_uart_driver); |
1519 | } | 1516 | } |
1520 | 1517 | ||
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index b62857bf2fdb..37e13c3d91d9 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c | |||
@@ -51,7 +51,7 @@ | |||
51 | struct uart_max3110 { | 51 | struct uart_max3110 { |
52 | struct uart_port port; | 52 | struct uart_port port; |
53 | struct spi_device *spi; | 53 | struct spi_device *spi; |
54 | char name[24]; | 54 | char name[SPI_NAME_SIZE]; |
55 | 55 | ||
56 | wait_queue_head_t wq; | 56 | wait_queue_head_t wq; |
57 | struct task_struct *main_thread; | 57 | struct task_struct *main_thread; |
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c new file mode 100644 index 000000000000..2e7fc9cee9cc --- /dev/null +++ b/drivers/tty/serial/msm_serial_hs.c | |||
@@ -0,0 +1,1880 @@ | |||
1 | /* | ||
2 | * MSM 7k/8k High speed uart driver | ||
3 | * | ||
4 | * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved. | ||
5 | * Copyright (c) 2008 Google Inc. | ||
6 | * Modified: Nick Pelly <npelly@google.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
15 | * See the GNU General Public License for more details. | ||
16 | * | ||
17 | * Has optional support for uart power management independent of linux | ||
18 | * suspend/resume: | ||
19 | * | ||
20 | * RX wakeup. | ||
21 | * UART wakeup can be triggered by RX activity (using a wakeup GPIO on the | ||
22 | * UART RX pin). This should only be used if there is not a wakeup | ||
23 | * GPIO on the UART CTS, and the first RX byte is known (for example, with the | ||
24 | * Bluetooth Texas Instruments HCILL protocol), since the first RX byte will | ||
25 | * always be lost. RTS will be asserted even while the UART is off in this mode | ||
26 | * of operation. See msm_serial_hs_platform_data.rx_wakeup_irq. | ||
27 | */ | ||
28 | |||
29 | #include <linux/module.h> | ||
30 | |||
31 | #include <linux/serial.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/irq.h> | ||
37 | #include <linux/io.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <linux/clk.h> | ||
42 | #include <linux/platform_device.h> | ||
43 | #include <linux/pm_runtime.h> | ||
44 | #include <linux/dma-mapping.h> | ||
45 | #include <linux/dmapool.h> | ||
46 | #include <linux/wait.h> | ||
47 | #include <linux/workqueue.h> | ||
48 | |||
49 | #include <linux/atomic.h> | ||
50 | #include <asm/irq.h> | ||
51 | #include <asm/system.h> | ||
52 | |||
53 | #include <mach/hardware.h> | ||
54 | #include <mach/dma.h> | ||
55 | #include <linux/platform_data/msm_serial_hs.h> | ||
56 | |||
57 | /* HSUART Registers */ | ||
58 | #define UARTDM_MR1_ADDR 0x0 | ||
59 | #define UARTDM_MR2_ADDR 0x4 | ||
60 | |||
61 | /* Data Mover result codes */ | ||
62 | #define RSLT_FIFO_CNTR_BMSK (0xE << 28) | ||
63 | #define RSLT_VLD BIT(1) | ||
64 | |||
65 | /* write only register */ | ||
66 | #define UARTDM_CSR_ADDR 0x8 | ||
67 | #define UARTDM_CSR_115200 0xFF | ||
68 | #define UARTDM_CSR_57600 0xEE | ||
69 | #define UARTDM_CSR_38400 0xDD | ||
70 | #define UARTDM_CSR_28800 0xCC | ||
71 | #define UARTDM_CSR_19200 0xBB | ||
72 | #define UARTDM_CSR_14400 0xAA | ||
73 | #define UARTDM_CSR_9600 0x99 | ||
74 | #define UARTDM_CSR_7200 0x88 | ||
75 | #define UARTDM_CSR_4800 0x77 | ||
76 | #define UARTDM_CSR_3600 0x66 | ||
77 | #define UARTDM_CSR_2400 0x55 | ||
78 | #define UARTDM_CSR_1200 0x44 | ||
79 | #define UARTDM_CSR_600 0x33 | ||
80 | #define UARTDM_CSR_300 0x22 | ||
81 | #define UARTDM_CSR_150 0x11 | ||
82 | #define UARTDM_CSR_75 0x00 | ||
83 | |||
84 | /* write only register */ | ||
85 | #define UARTDM_TF_ADDR 0x70 | ||
86 | #define UARTDM_TF2_ADDR 0x74 | ||
87 | #define UARTDM_TF3_ADDR 0x78 | ||
88 | #define UARTDM_TF4_ADDR 0x7C | ||
89 | |||
90 | /* write only register */ | ||
91 | #define UARTDM_CR_ADDR 0x10 | ||
92 | #define UARTDM_IMR_ADDR 0x14 | ||
93 | |||
94 | #define UARTDM_IPR_ADDR 0x18 | ||
95 | #define UARTDM_TFWR_ADDR 0x1c | ||
96 | #define UARTDM_RFWR_ADDR 0x20 | ||
97 | #define UARTDM_HCR_ADDR 0x24 | ||
98 | #define UARTDM_DMRX_ADDR 0x34 | ||
99 | #define UARTDM_IRDA_ADDR 0x38 | ||
100 | #define UARTDM_DMEN_ADDR 0x3c | ||
101 | |||
102 | /* UART_DM_NO_CHARS_FOR_TX */ | ||
103 | #define UARTDM_NCF_TX_ADDR 0x40 | ||
104 | |||
105 | #define UARTDM_BADR_ADDR 0x44 | ||
106 | |||
107 | #define UARTDM_SIM_CFG_ADDR 0x80 | ||
108 | /* Read Only register */ | ||
109 | #define UARTDM_SR_ADDR 0x8 | ||
110 | |||
111 | /* Read Only register */ | ||
112 | #define UARTDM_RF_ADDR 0x70 | ||
113 | #define UARTDM_RF2_ADDR 0x74 | ||
114 | #define UARTDM_RF3_ADDR 0x78 | ||
115 | #define UARTDM_RF4_ADDR 0x7C | ||
116 | |||
117 | /* Read Only register */ | ||
118 | #define UARTDM_MISR_ADDR 0x10 | ||
119 | |||
120 | /* Read Only register */ | ||
121 | #define UARTDM_ISR_ADDR 0x14 | ||
122 | #define UARTDM_RX_TOTAL_SNAP_ADDR 0x38 | ||
123 | |||
124 | #define UARTDM_RXFS_ADDR 0x50 | ||
125 | |||
126 | /* Register field Mask Mapping */ | ||
127 | #define UARTDM_SR_PAR_FRAME_BMSK BIT(5) | ||
128 | #define UARTDM_SR_OVERRUN_BMSK BIT(4) | ||
129 | #define UARTDM_SR_TXEMT_BMSK BIT(3) | ||
130 | #define UARTDM_SR_TXRDY_BMSK BIT(2) | ||
131 | #define UARTDM_SR_RXRDY_BMSK BIT(0) | ||
132 | |||
133 | #define UARTDM_CR_TX_DISABLE_BMSK BIT(3) | ||
134 | #define UARTDM_CR_RX_DISABLE_BMSK BIT(1) | ||
135 | #define UARTDM_CR_TX_EN_BMSK BIT(2) | ||
136 | #define UARTDM_CR_RX_EN_BMSK BIT(0) | ||
137 | |||
138 | /* UARTDM_CR channel_comman bit value (register field is bits 8:4) */ | ||
139 | #define RESET_RX 0x10 | ||
140 | #define RESET_TX 0x20 | ||
141 | #define RESET_ERROR_STATUS 0x30 | ||
142 | #define RESET_BREAK_INT 0x40 | ||
143 | #define START_BREAK 0x50 | ||
144 | #define STOP_BREAK 0x60 | ||
145 | #define RESET_CTS 0x70 | ||
146 | #define RESET_STALE_INT 0x80 | ||
147 | #define RFR_LOW 0xD0 | ||
148 | #define RFR_HIGH 0xE0 | ||
149 | #define CR_PROTECTION_EN 0x100 | ||
150 | #define STALE_EVENT_ENABLE 0x500 | ||
151 | #define STALE_EVENT_DISABLE 0x600 | ||
152 | #define FORCE_STALE_EVENT 0x400 | ||
153 | #define CLEAR_TX_READY 0x300 | ||
154 | #define RESET_TX_ERROR 0x800 | ||
155 | #define RESET_TX_DONE 0x810 | ||
156 | |||
157 | #define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00 | ||
158 | #define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f | ||
159 | #define UARTDM_MR1_CTS_CTL_BMSK 0x40 | ||
160 | #define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80 | ||
161 | |||
162 | #define UARTDM_MR2_ERROR_MODE_BMSK 0x40 | ||
163 | #define UARTDM_MR2_BITS_PER_CHAR_BMSK 0x30 | ||
164 | |||
165 | /* bits per character configuration */ | ||
166 | #define FIVE_BPC (0 << 4) | ||
167 | #define SIX_BPC (1 << 4) | ||
168 | #define SEVEN_BPC (2 << 4) | ||
169 | #define EIGHT_BPC (3 << 4) | ||
170 | |||
171 | #define UARTDM_MR2_STOP_BIT_LEN_BMSK 0xc | ||
172 | #define STOP_BIT_ONE (1 << 2) | ||
173 | #define STOP_BIT_TWO (3 << 2) | ||
174 | |||
175 | #define UARTDM_MR2_PARITY_MODE_BMSK 0x3 | ||
176 | |||
177 | /* Parity configuration */ | ||
178 | #define NO_PARITY 0x0 | ||
179 | #define EVEN_PARITY 0x1 | ||
180 | #define ODD_PARITY 0x2 | ||
181 | #define SPACE_PARITY 0x3 | ||
182 | |||
183 | #define UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80 | ||
184 | #define UARTDM_IPR_STALE_LSB_BMSK 0x1f | ||
185 | |||
186 | /* These can be used for both ISR and IMR register */ | ||
187 | #define UARTDM_ISR_TX_READY_BMSK BIT(7) | ||
188 | #define UARTDM_ISR_CURRENT_CTS_BMSK BIT(6) | ||
189 | #define UARTDM_ISR_DELTA_CTS_BMSK BIT(5) | ||
190 | #define UARTDM_ISR_RXLEV_BMSK BIT(4) | ||
191 | #define UARTDM_ISR_RXSTALE_BMSK BIT(3) | ||
192 | #define UARTDM_ISR_RXBREAK_BMSK BIT(2) | ||
193 | #define UARTDM_ISR_RXHUNT_BMSK BIT(1) | ||
194 | #define UARTDM_ISR_TXLEV_BMSK BIT(0) | ||
195 | |||
196 | /* Field definitions for UART_DM_DMEN*/ | ||
197 | #define UARTDM_TX_DM_EN_BMSK 0x1 | ||
198 | #define UARTDM_RX_DM_EN_BMSK 0x2 | ||
199 | |||
200 | #define UART_FIFOSIZE 64 | ||
201 | #define UARTCLK 7372800 | ||
202 | |||
203 | /* Rx DMA request states */ | ||
204 | enum flush_reason { | ||
205 | FLUSH_NONE, | ||
206 | FLUSH_DATA_READY, | ||
207 | FLUSH_DATA_INVALID, /* values after this indicate invalid data */ | ||
208 | FLUSH_IGNORE = FLUSH_DATA_INVALID, | ||
209 | FLUSH_STOP, | ||
210 | FLUSH_SHUTDOWN, | ||
211 | }; | ||
212 | |||
213 | /* UART clock states */ | ||
214 | enum msm_hs_clk_states_e { | ||
215 | MSM_HS_CLK_PORT_OFF, /* port not in use */ | ||
216 | MSM_HS_CLK_OFF, /* clock disabled */ | ||
217 | MSM_HS_CLK_REQUEST_OFF, /* disable after TX and RX flushed */ | ||
218 | MSM_HS_CLK_ON, /* clock enabled */ | ||
219 | }; | ||
220 | |||
221 | /* Track the forced RXSTALE flush during clock off sequence. | ||
222 | * These states are only valid during MSM_HS_CLK_REQUEST_OFF */ | ||
223 | enum msm_hs_clk_req_off_state_e { | ||
224 | CLK_REQ_OFF_START, | ||
225 | CLK_REQ_OFF_RXSTALE_ISSUED, | ||
226 | CLK_REQ_OFF_FLUSH_ISSUED, | ||
227 | CLK_REQ_OFF_RXSTALE_FLUSHED, | ||
228 | }; | ||
229 | |||
230 | /** | ||
231 | * struct msm_hs_tx | ||
232 | * @tx_ready_int_en: ok to dma more tx? | ||
233 | * @dma_in_flight: tx dma in progress | ||
234 | * @xfer: top level DMA command pointer structure | ||
235 | * @command_ptr: third level command struct pointer | ||
236 | * @command_ptr_ptr: second level command list struct pointer | ||
237 | * @mapped_cmd_ptr: DMA view of third level command struct | ||
238 | * @mapped_cmd_ptr_ptr: DMA view of second level command list struct | ||
239 | * @tx_count: number of bytes to transfer in DMA transfer | ||
240 | * @dma_base: DMA view of UART xmit buffer | ||
241 | * | ||
242 | * This structure describes a single Tx DMA transaction. MSM DMA | ||
243 | * commands have two levels of indirection. The top level command | ||
244 | * ptr points to a list of command ptr which in turn points to a | ||
245 | * single DMA 'command'. In our case each Tx transaction consists | ||
246 | * of a single second level pointer pointing to a 'box type' command. | ||
247 | */ | ||
248 | struct msm_hs_tx { | ||
249 | unsigned int tx_ready_int_en; | ||
250 | unsigned int dma_in_flight; | ||
251 | struct msm_dmov_cmd xfer; | ||
252 | dmov_box *command_ptr; | ||
253 | u32 *command_ptr_ptr; | ||
254 | dma_addr_t mapped_cmd_ptr; | ||
255 | dma_addr_t mapped_cmd_ptr_ptr; | ||
256 | int tx_count; | ||
257 | dma_addr_t dma_base; | ||
258 | }; | ||
259 | |||
260 | /** | ||
261 | * struct msm_hs_rx | ||
262 | * @flush: Rx DMA request state | ||
263 | * @xfer: top level DMA command pointer structure | ||
264 | * @cmdptr_dmaaddr: DMA view of second level command structure | ||
265 | * @command_ptr: third level DMA command pointer structure | ||
266 | * @command_ptr_ptr: second level DMA command list pointer | ||
267 | * @mapped_cmd_ptr: DMA view of the third level command structure | ||
268 | * @wait: wait for DMA completion before shutdown | ||
269 | * @buffer: destination buffer for RX DMA | ||
270 | * @rbuffer: DMA view of buffer | ||
271 | * @pool: dma pool out of which coherent rx buffer is allocated | ||
272 | * @tty_work: private work-queue for tty flip buffer push task | ||
273 | * | ||
274 | * This structure describes a single Rx DMA transaction. Rx DMA | ||
275 | * transactions use box mode DMA commands. | ||
276 | */ | ||
277 | struct msm_hs_rx { | ||
278 | enum flush_reason flush; | ||
279 | struct msm_dmov_cmd xfer; | ||
280 | dma_addr_t cmdptr_dmaaddr; | ||
281 | dmov_box *command_ptr; | ||
282 | u32 *command_ptr_ptr; | ||
283 | dma_addr_t mapped_cmd_ptr; | ||
284 | wait_queue_head_t wait; | ||
285 | dma_addr_t rbuffer; | ||
286 | unsigned char *buffer; | ||
287 | struct dma_pool *pool; | ||
288 | struct work_struct tty_work; | ||
289 | }; | ||
290 | |||
291 | /** | ||
292 | * struct msm_hs_rx_wakeup | ||
293 | * @irq: IRQ line to be configured as interrupt source on Rx activity | ||
294 | * @ignore: boolean value. 1 = ignore the wakeup interrupt | ||
295 | * @rx_to_inject: extra character to be inserted to Rx tty on wakeup | ||
296 | * @inject_rx: 1 = insert rx_to_inject. 0 = do not insert extra character | ||
297 | * | ||
298 | * This is an optional structure required for UART Rx GPIO IRQ based | ||
299 | * wakeup from low power state. UART wakeup can be triggered by RX activity | ||
300 | * (using a wakeup GPIO on the UART RX pin). This should only be used if | ||
301 | * there is not a wakeup GPIO on the UART CTS, and the first RX byte is | ||
302 | * known (eg., with the Bluetooth Texas Instruments HCILL protocol), | ||
303 | * since the first RX byte will always be lost. RTS will be asserted even | ||
304 | * while the UART is clocked off in this mode of operation. | ||
305 | */ | ||
306 | struct msm_hs_rx_wakeup { | ||
307 | int irq; /* < 0 indicates low power wakeup disabled */ | ||
308 | unsigned char ignore; | ||
309 | unsigned char inject_rx; | ||
310 | char rx_to_inject; | ||
311 | }; | ||
312 | |||
313 | /** | ||
314 | * struct msm_hs_port | ||
315 | * @uport: embedded uart port structure | ||
316 | * @imr_reg: shadow value of UARTDM_IMR | ||
317 | * @clk: uart input clock handle | ||
318 | * @tx: Tx transaction related data structure | ||
319 | * @rx: Rx transaction related data structure | ||
320 | * @dma_tx_channel: Tx DMA command channel | ||
321 | * @dma_rx_channel Rx DMA command channel | ||
322 | * @dma_tx_crci: Tx channel rate control interface number | ||
323 | * @dma_rx_crci: Rx channel rate control interface number | ||
324 | * @clk_off_timer: Timer to poll DMA event completion before clock off | ||
325 | * @clk_off_delay: clk_off_timer poll interval | ||
326 | * @clk_state: overall clock state | ||
327 | * @clk_req_off_state: post flush clock states | ||
328 | * @rx_wakeup: optional rx_wakeup feature related data | ||
329 | * @exit_lpm_cb: optional callback to exit low power mode | ||
330 | * | ||
331 | * Low level serial port structure. | ||
332 | */ | ||
333 | struct msm_hs_port { | ||
334 | struct uart_port uport; | ||
335 | unsigned long imr_reg; | ||
336 | struct clk *clk; | ||
337 | struct msm_hs_tx tx; | ||
338 | struct msm_hs_rx rx; | ||
339 | |||
340 | int dma_tx_channel; | ||
341 | int dma_rx_channel; | ||
342 | int dma_tx_crci; | ||
343 | int dma_rx_crci; | ||
344 | |||
345 | struct hrtimer clk_off_timer; | ||
346 | ktime_t clk_off_delay; | ||
347 | enum msm_hs_clk_states_e clk_state; | ||
348 | enum msm_hs_clk_req_off_state_e clk_req_off_state; | ||
349 | |||
350 | struct msm_hs_rx_wakeup rx_wakeup; | ||
351 | void (*exit_lpm_cb)(struct uart_port *); | ||
352 | }; | ||
353 | |||
354 | #define MSM_UARTDM_BURST_SIZE 16 /* DM burst size (in bytes) */ | ||
355 | #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE | ||
356 | #define UARTDM_RX_BUF_SIZE 512 | ||
357 | |||
358 | #define UARTDM_NR 2 | ||
359 | |||
360 | static struct msm_hs_port q_uart_port[UARTDM_NR]; | ||
361 | static struct platform_driver msm_serial_hs_platform_driver; | ||
362 | static struct uart_driver msm_hs_driver; | ||
363 | static struct uart_ops msm_hs_ops; | ||
364 | static struct workqueue_struct *msm_hs_workqueue; | ||
365 | |||
366 | #define UARTDM_TO_MSM(uart_port) \ | ||
367 | container_of((uart_port), struct msm_hs_port, uport) | ||
368 | |||
369 | static unsigned int use_low_power_rx_wakeup(struct msm_hs_port | ||
370 | *msm_uport) | ||
371 | { | ||
372 | return (msm_uport->rx_wakeup.irq >= 0); | ||
373 | } | ||
374 | |||
375 | static unsigned int msm_hs_read(struct uart_port *uport, | ||
376 | unsigned int offset) | ||
377 | { | ||
378 | return ioread32(uport->membase + offset); | ||
379 | } | ||
380 | |||
381 | static void msm_hs_write(struct uart_port *uport, unsigned int offset, | ||
382 | unsigned int value) | ||
383 | { | ||
384 | iowrite32(value, uport->membase + offset); | ||
385 | } | ||
386 | |||
387 | static void msm_hs_release_port(struct uart_port *port) | ||
388 | { | ||
389 | iounmap(port->membase); | ||
390 | } | ||
391 | |||
392 | static int msm_hs_request_port(struct uart_port *port) | ||
393 | { | ||
394 | port->membase = ioremap(port->mapbase, PAGE_SIZE); | ||
395 | if (unlikely(!port->membase)) | ||
396 | return -ENOMEM; | ||
397 | |||
398 | /* configure the CR Protection to Enable */ | ||
399 | msm_hs_write(port, UARTDM_CR_ADDR, CR_PROTECTION_EN); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int __devexit msm_hs_remove(struct platform_device *pdev) | ||
404 | { | ||
405 | |||
406 | struct msm_hs_port *msm_uport; | ||
407 | struct device *dev; | ||
408 | |||
409 | if (pdev->id < 0 || pdev->id >= UARTDM_NR) { | ||
410 | printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id); | ||
411 | return -EINVAL; | ||
412 | } | ||
413 | |||
414 | msm_uport = &q_uart_port[pdev->id]; | ||
415 | dev = msm_uport->uport.dev; | ||
416 | |||
417 | dma_unmap_single(dev, msm_uport->rx.mapped_cmd_ptr, sizeof(dmov_box), | ||
418 | DMA_TO_DEVICE); | ||
419 | dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer, | ||
420 | msm_uport->rx.rbuffer); | ||
421 | dma_pool_destroy(msm_uport->rx.pool); | ||
422 | |||
423 | dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32 *), | ||
424 | DMA_TO_DEVICE); | ||
425 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32 *), | ||
426 | DMA_TO_DEVICE); | ||
427 | dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box), | ||
428 | DMA_TO_DEVICE); | ||
429 | |||
430 | uart_remove_one_port(&msm_hs_driver, &msm_uport->uport); | ||
431 | clk_put(msm_uport->clk); | ||
432 | |||
433 | /* Free the tx resources */ | ||
434 | kfree(msm_uport->tx.command_ptr); | ||
435 | kfree(msm_uport->tx.command_ptr_ptr); | ||
436 | |||
437 | /* Free the rx resources */ | ||
438 | kfree(msm_uport->rx.command_ptr); | ||
439 | kfree(msm_uport->rx.command_ptr_ptr); | ||
440 | |||
441 | iounmap(msm_uport->uport.membase); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int msm_hs_init_clk_locked(struct uart_port *uport) | ||
447 | { | ||
448 | int ret; | ||
449 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
450 | |||
451 | ret = clk_enable(msm_uport->clk); | ||
452 | if (ret) { | ||
453 | printk(KERN_ERR "Error could not turn on UART clk\n"); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | /* Set up the MREG/NREG/DREG/MNDREG */ | ||
458 | ret = clk_set_rate(msm_uport->clk, uport->uartclk); | ||
459 | if (ret) { | ||
460 | printk(KERN_WARNING "Error setting clock rate on UART\n"); | ||
461 | clk_disable(msm_uport->clk); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | msm_uport->clk_state = MSM_HS_CLK_ON; | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | /* Enable and Disable clocks (Used for power management) */ | ||
470 | static void msm_hs_pm(struct uart_port *uport, unsigned int state, | ||
471 | unsigned int oldstate) | ||
472 | { | ||
473 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
474 | |||
475 | if (use_low_power_rx_wakeup(msm_uport) || | ||
476 | msm_uport->exit_lpm_cb) | ||
477 | return; /* ignore linux PM states, | ||
478 | use msm_hs_request_clock API */ | ||
479 | |||
480 | switch (state) { | ||
481 | case 0: | ||
482 | clk_enable(msm_uport->clk); | ||
483 | break; | ||
484 | case 3: | ||
485 | clk_disable(msm_uport->clk); | ||
486 | break; | ||
487 | default: | ||
488 | dev_err(uport->dev, "msm_serial: Unknown PM state %d\n", | ||
489 | state); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * programs the UARTDM_CSR register with correct bit rates | ||
495 | * | ||
496 | * Interrupts should be disabled before we are called, as | ||
497 | * we modify Set Baud rate | ||
498 | * Set receive stale interrupt level, dependant on Bit Rate | ||
499 | * Goal is to have around 8 ms before indicate stale. | ||
500 | * roundup (((Bit Rate * .008) / 10) + 1 | ||
501 | */ | ||
502 | static void msm_hs_set_bps_locked(struct uart_port *uport, | ||
503 | unsigned int bps) | ||
504 | { | ||
505 | unsigned long rxstale; | ||
506 | unsigned long data; | ||
507 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
508 | |||
509 | switch (bps) { | ||
510 | case 300: | ||
511 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_75); | ||
512 | rxstale = 1; | ||
513 | break; | ||
514 | case 600: | ||
515 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_150); | ||
516 | rxstale = 1; | ||
517 | break; | ||
518 | case 1200: | ||
519 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_300); | ||
520 | rxstale = 1; | ||
521 | break; | ||
522 | case 2400: | ||
523 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_600); | ||
524 | rxstale = 1; | ||
525 | break; | ||
526 | case 4800: | ||
527 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_1200); | ||
528 | rxstale = 1; | ||
529 | break; | ||
530 | case 9600: | ||
531 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400); | ||
532 | rxstale = 2; | ||
533 | break; | ||
534 | case 14400: | ||
535 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_3600); | ||
536 | rxstale = 3; | ||
537 | break; | ||
538 | case 19200: | ||
539 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_4800); | ||
540 | rxstale = 4; | ||
541 | break; | ||
542 | case 28800: | ||
543 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_7200); | ||
544 | rxstale = 6; | ||
545 | break; | ||
546 | case 38400: | ||
547 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_9600); | ||
548 | rxstale = 8; | ||
549 | break; | ||
550 | case 57600: | ||
551 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_14400); | ||
552 | rxstale = 16; | ||
553 | break; | ||
554 | case 76800: | ||
555 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_19200); | ||
556 | rxstale = 16; | ||
557 | break; | ||
558 | case 115200: | ||
559 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_28800); | ||
560 | rxstale = 31; | ||
561 | break; | ||
562 | case 230400: | ||
563 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_57600); | ||
564 | rxstale = 31; | ||
565 | break; | ||
566 | case 460800: | ||
567 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200); | ||
568 | rxstale = 31; | ||
569 | break; | ||
570 | case 4000000: | ||
571 | case 3686400: | ||
572 | case 3200000: | ||
573 | case 3500000: | ||
574 | case 3000000: | ||
575 | case 2500000: | ||
576 | case 1500000: | ||
577 | case 1152000: | ||
578 | case 1000000: | ||
579 | case 921600: | ||
580 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200); | ||
581 | rxstale = 31; | ||
582 | break; | ||
583 | default: | ||
584 | msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400); | ||
585 | /* default to 9600 */ | ||
586 | bps = 9600; | ||
587 | rxstale = 2; | ||
588 | break; | ||
589 | } | ||
590 | if (bps > 460800) | ||
591 | uport->uartclk = bps * 16; | ||
592 | else | ||
593 | uport->uartclk = UARTCLK; | ||
594 | |||
595 | if (clk_set_rate(msm_uport->clk, uport->uartclk)) { | ||
596 | printk(KERN_WARNING "Error setting clock rate on UART\n"); | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | data = rxstale & UARTDM_IPR_STALE_LSB_BMSK; | ||
601 | data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2); | ||
602 | |||
603 | msm_hs_write(uport, UARTDM_IPR_ADDR, data); | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * termios : new ktermios | ||
608 | * oldtermios: old ktermios previous setting | ||
609 | * | ||
610 | * Configure the serial port | ||
611 | */ | ||
612 | static void msm_hs_set_termios(struct uart_port *uport, | ||
613 | struct ktermios *termios, | ||
614 | struct ktermios *oldtermios) | ||
615 | { | ||
616 | unsigned int bps; | ||
617 | unsigned long data; | ||
618 | unsigned long flags; | ||
619 | unsigned int c_cflag = termios->c_cflag; | ||
620 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
621 | |||
622 | spin_lock_irqsave(&uport->lock, flags); | ||
623 | clk_enable(msm_uport->clk); | ||
624 | |||
625 | /* 300 is the minimum baud support by the driver */ | ||
626 | bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000); | ||
627 | |||
628 | /* Temporary remapping 200 BAUD to 3.2 mbps */ | ||
629 | if (bps == 200) | ||
630 | bps = 3200000; | ||
631 | |||
632 | msm_hs_set_bps_locked(uport, bps); | ||
633 | |||
634 | data = msm_hs_read(uport, UARTDM_MR2_ADDR); | ||
635 | data &= ~UARTDM_MR2_PARITY_MODE_BMSK; | ||
636 | /* set parity */ | ||
637 | if (PARENB == (c_cflag & PARENB)) { | ||
638 | if (PARODD == (c_cflag & PARODD)) | ||
639 | data |= ODD_PARITY; | ||
640 | else if (CMSPAR == (c_cflag & CMSPAR)) | ||
641 | data |= SPACE_PARITY; | ||
642 | else | ||
643 | data |= EVEN_PARITY; | ||
644 | } | ||
645 | |||
646 | /* Set bits per char */ | ||
647 | data &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK; | ||
648 | |||
649 | switch (c_cflag & CSIZE) { | ||
650 | case CS5: | ||
651 | data |= FIVE_BPC; | ||
652 | break; | ||
653 | case CS6: | ||
654 | data |= SIX_BPC; | ||
655 | break; | ||
656 | case CS7: | ||
657 | data |= SEVEN_BPC; | ||
658 | break; | ||
659 | default: | ||
660 | data |= EIGHT_BPC; | ||
661 | break; | ||
662 | } | ||
663 | /* stop bits */ | ||
664 | if (c_cflag & CSTOPB) { | ||
665 | data |= STOP_BIT_TWO; | ||
666 | } else { | ||
667 | /* otherwise 1 stop bit */ | ||
668 | data |= STOP_BIT_ONE; | ||
669 | } | ||
670 | data |= UARTDM_MR2_ERROR_MODE_BMSK; | ||
671 | /* write parity/bits per char/stop bit configuration */ | ||
672 | msm_hs_write(uport, UARTDM_MR2_ADDR, data); | ||
673 | |||
674 | /* Configure HW flow control */ | ||
675 | data = msm_hs_read(uport, UARTDM_MR1_ADDR); | ||
676 | |||
677 | data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK); | ||
678 | |||
679 | if (c_cflag & CRTSCTS) { | ||
680 | data |= UARTDM_MR1_CTS_CTL_BMSK; | ||
681 | data |= UARTDM_MR1_RX_RDY_CTL_BMSK; | ||
682 | } | ||
683 | |||
684 | msm_hs_write(uport, UARTDM_MR1_ADDR, data); | ||
685 | |||
686 | uport->ignore_status_mask = termios->c_iflag & INPCK; | ||
687 | uport->ignore_status_mask |= termios->c_iflag & IGNPAR; | ||
688 | uport->read_status_mask = (termios->c_cflag & CREAD); | ||
689 | |||
690 | msm_hs_write(uport, UARTDM_IMR_ADDR, 0); | ||
691 | |||
692 | /* Set Transmit software time out */ | ||
693 | uart_update_timeout(uport, c_cflag, bps); | ||
694 | |||
695 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX); | ||
696 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX); | ||
697 | |||
698 | if (msm_uport->rx.flush == FLUSH_NONE) { | ||
699 | msm_uport->rx.flush = FLUSH_IGNORE; | ||
700 | msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1); | ||
701 | } | ||
702 | |||
703 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
704 | |||
705 | clk_disable(msm_uport->clk); | ||
706 | spin_unlock_irqrestore(&uport->lock, flags); | ||
707 | } | ||
708 | |||
709 | /* | ||
710 | * Standard API, Transmitter | ||
711 | * Any character in the transmit shift register is sent | ||
712 | */ | ||
713 | static unsigned int msm_hs_tx_empty(struct uart_port *uport) | ||
714 | { | ||
715 | unsigned int data; | ||
716 | unsigned int ret = 0; | ||
717 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
718 | |||
719 | clk_enable(msm_uport->clk); | ||
720 | |||
721 | data = msm_hs_read(uport, UARTDM_SR_ADDR); | ||
722 | if (data & UARTDM_SR_TXEMT_BMSK) | ||
723 | ret = TIOCSER_TEMT; | ||
724 | |||
725 | clk_disable(msm_uport->clk); | ||
726 | |||
727 | return ret; | ||
728 | } | ||
729 | |||
730 | /* | ||
731 | * Standard API, Stop transmitter. | ||
732 | * Any character in the transmit shift register is sent as | ||
733 | * well as the current data mover transfer . | ||
734 | */ | ||
735 | static void msm_hs_stop_tx_locked(struct uart_port *uport) | ||
736 | { | ||
737 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
738 | |||
739 | msm_uport->tx.tx_ready_int_en = 0; | ||
740 | } | ||
741 | |||
742 | /* | ||
743 | * Standard API, Stop receiver as soon as possible. | ||
744 | * | ||
745 | * Function immediately terminates the operation of the | ||
746 | * channel receiver and any incoming characters are lost. None | ||
747 | * of the receiver status bits are affected by this command and | ||
748 | * characters that are already in the receive FIFO there. | ||
749 | */ | ||
750 | static void msm_hs_stop_rx_locked(struct uart_port *uport) | ||
751 | { | ||
752 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
753 | unsigned int data; | ||
754 | |||
755 | clk_enable(msm_uport->clk); | ||
756 | |||
757 | /* disable dlink */ | ||
758 | data = msm_hs_read(uport, UARTDM_DMEN_ADDR); | ||
759 | data &= ~UARTDM_RX_DM_EN_BMSK; | ||
760 | msm_hs_write(uport, UARTDM_DMEN_ADDR, data); | ||
761 | |||
762 | /* Disable the receiver */ | ||
763 | if (msm_uport->rx.flush == FLUSH_NONE) | ||
764 | msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1); | ||
765 | |||
766 | if (msm_uport->rx.flush != FLUSH_SHUTDOWN) | ||
767 | msm_uport->rx.flush = FLUSH_STOP; | ||
768 | |||
769 | clk_disable(msm_uport->clk); | ||
770 | } | ||
771 | |||
772 | /* Transmit the next chunk of data */ | ||
773 | static void msm_hs_submit_tx_locked(struct uart_port *uport) | ||
774 | { | ||
775 | int left; | ||
776 | int tx_count; | ||
777 | dma_addr_t src_addr; | ||
778 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
779 | struct msm_hs_tx *tx = &msm_uport->tx; | ||
780 | struct circ_buf *tx_buf = &msm_uport->uport.state->xmit; | ||
781 | |||
782 | if (uart_circ_empty(tx_buf) || uport->state->port.tty->stopped) { | ||
783 | msm_hs_stop_tx_locked(uport); | ||
784 | return; | ||
785 | } | ||
786 | |||
787 | tx->dma_in_flight = 1; | ||
788 | |||
789 | tx_count = uart_circ_chars_pending(tx_buf); | ||
790 | |||
791 | if (UARTDM_TX_BUF_SIZE < tx_count) | ||
792 | tx_count = UARTDM_TX_BUF_SIZE; | ||
793 | |||
794 | left = UART_XMIT_SIZE - tx_buf->tail; | ||
795 | |||
796 | if (tx_count > left) | ||
797 | tx_count = left; | ||
798 | |||
799 | src_addr = tx->dma_base + tx_buf->tail; | ||
800 | dma_sync_single_for_device(uport->dev, src_addr, tx_count, | ||
801 | DMA_TO_DEVICE); | ||
802 | |||
803 | tx->command_ptr->num_rows = (((tx_count + 15) >> 4) << 16) | | ||
804 | ((tx_count + 15) >> 4); | ||
805 | tx->command_ptr->src_row_addr = src_addr; | ||
806 | |||
807 | dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr, | ||
808 | sizeof(dmov_box), DMA_TO_DEVICE); | ||
809 | |||
810 | *tx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(tx->mapped_cmd_ptr); | ||
811 | |||
812 | dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr, | ||
813 | sizeof(u32 *), DMA_TO_DEVICE); | ||
814 | |||
815 | /* Save tx_count to use in Callback */ | ||
816 | tx->tx_count = tx_count; | ||
817 | msm_hs_write(uport, UARTDM_NCF_TX_ADDR, tx_count); | ||
818 | |||
819 | /* Disable the tx_ready interrupt */ | ||
820 | msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK; | ||
821 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
822 | msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer); | ||
823 | } | ||
824 | |||
825 | /* Start to receive the next chunk of data */ | ||
826 | static void msm_hs_start_rx_locked(struct uart_port *uport) | ||
827 | { | ||
828 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
829 | |||
830 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT); | ||
831 | msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE); | ||
832 | msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE); | ||
833 | msm_uport->imr_reg |= UARTDM_ISR_RXLEV_BMSK; | ||
834 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
835 | |||
836 | msm_uport->rx.flush = FLUSH_NONE; | ||
837 | msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel, &msm_uport->rx.xfer); | ||
838 | |||
839 | /* might have finished RX and be ready to clock off */ | ||
840 | hrtimer_start(&msm_uport->clk_off_timer, msm_uport->clk_off_delay, | ||
841 | HRTIMER_MODE_REL); | ||
842 | } | ||
843 | |||
844 | /* Enable the transmitter Interrupt */ | ||
845 | static void msm_hs_start_tx_locked(struct uart_port *uport) | ||
846 | { | ||
847 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
848 | |||
849 | clk_enable(msm_uport->clk); | ||
850 | |||
851 | if (msm_uport->exit_lpm_cb) | ||
852 | msm_uport->exit_lpm_cb(uport); | ||
853 | |||
854 | if (msm_uport->tx.tx_ready_int_en == 0) { | ||
855 | msm_uport->tx.tx_ready_int_en = 1; | ||
856 | msm_hs_submit_tx_locked(uport); | ||
857 | } | ||
858 | |||
859 | clk_disable(msm_uport->clk); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * This routine is called when we are done with a DMA transfer | ||
864 | * | ||
865 | * This routine is registered with Data mover when we set | ||
866 | * up a Data Mover transfer. It is called from Data mover ISR | ||
867 | * when the DMA transfer is done. | ||
868 | */ | ||
869 | static void msm_hs_dmov_tx_callback(struct msm_dmov_cmd *cmd_ptr, | ||
870 | unsigned int result, | ||
871 | struct msm_dmov_errdata *err) | ||
872 | { | ||
873 | unsigned long flags; | ||
874 | struct msm_hs_port *msm_uport; | ||
875 | |||
876 | /* DMA did not finish properly */ | ||
877 | WARN_ON((((result & RSLT_FIFO_CNTR_BMSK) >> 28) == 1) && | ||
878 | !(result & RSLT_VLD)); | ||
879 | |||
880 | msm_uport = container_of(cmd_ptr, struct msm_hs_port, tx.xfer); | ||
881 | |||
882 | spin_lock_irqsave(&msm_uport->uport.lock, flags); | ||
883 | clk_enable(msm_uport->clk); | ||
884 | |||
885 | msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK; | ||
886 | msm_hs_write(&msm_uport->uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
887 | |||
888 | clk_disable(msm_uport->clk); | ||
889 | spin_unlock_irqrestore(&msm_uport->uport.lock, flags); | ||
890 | } | ||
891 | |||
892 | /* | ||
893 | * This routine is called when we are done with a DMA transfer or the | ||
894 | * a flush has been sent to the data mover driver. | ||
895 | * | ||
896 | * This routine is registered with Data mover when we set up a Data Mover | ||
897 | * transfer. It is called from Data mover ISR when the DMA transfer is done. | ||
898 | */ | ||
899 | static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr, | ||
900 | unsigned int result, | ||
901 | struct msm_dmov_errdata *err) | ||
902 | { | ||
903 | int retval; | ||
904 | int rx_count; | ||
905 | unsigned long status; | ||
906 | unsigned int error_f = 0; | ||
907 | unsigned long flags; | ||
908 | unsigned int flush; | ||
909 | struct tty_struct *tty; | ||
910 | struct uart_port *uport; | ||
911 | struct msm_hs_port *msm_uport; | ||
912 | |||
913 | msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer); | ||
914 | uport = &msm_uport->uport; | ||
915 | |||
916 | spin_lock_irqsave(&uport->lock, flags); | ||
917 | clk_enable(msm_uport->clk); | ||
918 | |||
919 | tty = uport->state->port.tty; | ||
920 | |||
921 | msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE); | ||
922 | |||
923 | status = msm_hs_read(uport, UARTDM_SR_ADDR); | ||
924 | |||
925 | /* overflow is not connect to data in a FIFO */ | ||
926 | if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) && | ||
927 | (uport->read_status_mask & CREAD))) { | ||
928 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
929 | uport->icount.buf_overrun++; | ||
930 | error_f = 1; | ||
931 | } | ||
932 | |||
933 | if (!(uport->ignore_status_mask & INPCK)) | ||
934 | status = status & ~(UARTDM_SR_PAR_FRAME_BMSK); | ||
935 | |||
936 | if (unlikely(status & UARTDM_SR_PAR_FRAME_BMSK)) { | ||
937 | /* Can not tell difference between parity & frame error */ | ||
938 | uport->icount.parity++; | ||
939 | error_f = 1; | ||
940 | if (uport->ignore_status_mask & IGNPAR) | ||
941 | tty_insert_flip_char(tty, 0, TTY_PARITY); | ||
942 | } | ||
943 | |||
944 | if (error_f) | ||
945 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS); | ||
946 | |||
947 | if (msm_uport->clk_req_off_state == CLK_REQ_OFF_FLUSH_ISSUED) | ||
948 | msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_FLUSHED; | ||
949 | |||
950 | flush = msm_uport->rx.flush; | ||
951 | if (flush == FLUSH_IGNORE) | ||
952 | msm_hs_start_rx_locked(uport); | ||
953 | if (flush == FLUSH_STOP) | ||
954 | msm_uport->rx.flush = FLUSH_SHUTDOWN; | ||
955 | if (flush >= FLUSH_DATA_INVALID) | ||
956 | goto out; | ||
957 | |||
958 | rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR); | ||
959 | |||
960 | if (0 != (uport->read_status_mask & CREAD)) { | ||
961 | retval = tty_insert_flip_string(tty, msm_uport->rx.buffer, | ||
962 | rx_count); | ||
963 | BUG_ON(retval != rx_count); | ||
964 | } | ||
965 | |||
966 | msm_hs_start_rx_locked(uport); | ||
967 | |||
968 | out: | ||
969 | clk_disable(msm_uport->clk); | ||
970 | |||
971 | spin_unlock_irqrestore(&uport->lock, flags); | ||
972 | |||
973 | if (flush < FLUSH_DATA_INVALID) | ||
974 | queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work); | ||
975 | } | ||
976 | |||
977 | static void msm_hs_tty_flip_buffer_work(struct work_struct *work) | ||
978 | { | ||
979 | struct msm_hs_port *msm_uport = | ||
980 | container_of(work, struct msm_hs_port, rx.tty_work); | ||
981 | struct tty_struct *tty = msm_uport->uport.state->port.tty; | ||
982 | |||
983 | tty_flip_buffer_push(tty); | ||
984 | } | ||
985 | |||
986 | /* | ||
987 | * Standard API, Current states of modem control inputs | ||
988 | * | ||
989 | * Since CTS can be handled entirely by HARDWARE we always | ||
990 | * indicate clear to send and count on the TX FIFO to block when | ||
991 | * it fills up. | ||
992 | * | ||
993 | * - TIOCM_DCD | ||
994 | * - TIOCM_CTS | ||
995 | * - TIOCM_DSR | ||
996 | * - TIOCM_RI | ||
997 | * (Unsupported) DCD and DSR will return them high. RI will return low. | ||
998 | */ | ||
999 | static unsigned int msm_hs_get_mctrl_locked(struct uart_port *uport) | ||
1000 | { | ||
1001 | return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * True enables UART auto RFR, which indicates we are ready for data if the RX | ||
1006 | * buffer is not full. False disables auto RFR, and deasserts RFR to indicate | ||
1007 | * we are not ready for data. Must be called with UART clock on. | ||
1008 | */ | ||
1009 | static void set_rfr_locked(struct uart_port *uport, int auto_rfr) | ||
1010 | { | ||
1011 | unsigned int data; | ||
1012 | |||
1013 | data = msm_hs_read(uport, UARTDM_MR1_ADDR); | ||
1014 | |||
1015 | if (auto_rfr) { | ||
1016 | /* enable auto ready-for-receiving */ | ||
1017 | data |= UARTDM_MR1_RX_RDY_CTL_BMSK; | ||
1018 | msm_hs_write(uport, UARTDM_MR1_ADDR, data); | ||
1019 | } else { | ||
1020 | /* disable auto ready-for-receiving */ | ||
1021 | data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK; | ||
1022 | msm_hs_write(uport, UARTDM_MR1_ADDR, data); | ||
1023 | /* RFR is active low, set high */ | ||
1024 | msm_hs_write(uport, UARTDM_CR_ADDR, RFR_HIGH); | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | /* | ||
1029 | * Standard API, used to set or clear RFR | ||
1030 | */ | ||
1031 | static void msm_hs_set_mctrl_locked(struct uart_port *uport, | ||
1032 | unsigned int mctrl) | ||
1033 | { | ||
1034 | unsigned int auto_rfr; | ||
1035 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1036 | |||
1037 | clk_enable(msm_uport->clk); | ||
1038 | |||
1039 | auto_rfr = TIOCM_RTS & mctrl ? 1 : 0; | ||
1040 | set_rfr_locked(uport, auto_rfr); | ||
1041 | |||
1042 | clk_disable(msm_uport->clk); | ||
1043 | } | ||
1044 | |||
1045 | /* Standard API, Enable modem status (CTS) interrupt */ | ||
1046 | static void msm_hs_enable_ms_locked(struct uart_port *uport) | ||
1047 | { | ||
1048 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1049 | |||
1050 | clk_enable(msm_uport->clk); | ||
1051 | |||
1052 | /* Enable DELTA_CTS Interrupt */ | ||
1053 | msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK; | ||
1054 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
1055 | |||
1056 | clk_disable(msm_uport->clk); | ||
1057 | |||
1058 | } | ||
1059 | |||
1060 | /* | ||
1061 | * Standard API, Break Signal | ||
1062 | * | ||
1063 | * Control the transmission of a break signal. ctl eq 0 => break | ||
1064 | * signal terminate ctl ne 0 => start break signal | ||
1065 | */ | ||
1066 | static void msm_hs_break_ctl(struct uart_port *uport, int ctl) | ||
1067 | { | ||
1068 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1069 | |||
1070 | clk_enable(msm_uport->clk); | ||
1071 | msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK); | ||
1072 | clk_disable(msm_uport->clk); | ||
1073 | } | ||
1074 | |||
1075 | static void msm_hs_config_port(struct uart_port *uport, int cfg_flags) | ||
1076 | { | ||
1077 | unsigned long flags; | ||
1078 | |||
1079 | spin_lock_irqsave(&uport->lock, flags); | ||
1080 | if (cfg_flags & UART_CONFIG_TYPE) { | ||
1081 | uport->type = PORT_MSM; | ||
1082 | msm_hs_request_port(uport); | ||
1083 | } | ||
1084 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1085 | } | ||
1086 | |||
1087 | /* Handle CTS changes (Called from interrupt handler) */ | ||
1088 | static void msm_hs_handle_delta_cts(struct uart_port *uport) | ||
1089 | { | ||
1090 | unsigned long flags; | ||
1091 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1092 | |||
1093 | spin_lock_irqsave(&uport->lock, flags); | ||
1094 | clk_enable(msm_uport->clk); | ||
1095 | |||
1096 | /* clear interrupt */ | ||
1097 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS); | ||
1098 | uport->icount.cts++; | ||
1099 | |||
1100 | clk_disable(msm_uport->clk); | ||
1101 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1102 | |||
1103 | /* clear the IOCTL TIOCMIWAIT if called */ | ||
1104 | wake_up_interruptible(&uport->state->port.delta_msr_wait); | ||
1105 | } | ||
1106 | |||
1107 | /* check if the TX path is flushed, and if so clock off | ||
1108 | * returns 0 did not clock off, need to retry (still sending final byte) | ||
1109 | * -1 did not clock off, do not retry | ||
1110 | * 1 if we clocked off | ||
1111 | */ | ||
1112 | static int msm_hs_check_clock_off_locked(struct uart_port *uport) | ||
1113 | { | ||
1114 | unsigned long sr_status; | ||
1115 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1116 | struct circ_buf *tx_buf = &uport->state->xmit; | ||
1117 | |||
1118 | /* Cancel if tx tty buffer is not empty, dma is in flight, | ||
1119 | * or tx fifo is not empty, or rx fifo is not empty */ | ||
1120 | if (msm_uport->clk_state != MSM_HS_CLK_REQUEST_OFF || | ||
1121 | !uart_circ_empty(tx_buf) || msm_uport->tx.dma_in_flight || | ||
1122 | (msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) || | ||
1123 | !(msm_uport->imr_reg & UARTDM_ISR_RXLEV_BMSK)) { | ||
1124 | return -1; | ||
1125 | } | ||
1126 | |||
1127 | /* Make sure the uart is finished with the last byte */ | ||
1128 | sr_status = msm_hs_read(uport, UARTDM_SR_ADDR); | ||
1129 | if (!(sr_status & UARTDM_SR_TXEMT_BMSK)) | ||
1130 | return 0; /* retry */ | ||
1131 | |||
1132 | /* Make sure forced RXSTALE flush complete */ | ||
1133 | switch (msm_uport->clk_req_off_state) { | ||
1134 | case CLK_REQ_OFF_START: | ||
1135 | msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED; | ||
1136 | msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT); | ||
1137 | return 0; /* RXSTALE flush not complete - retry */ | ||
1138 | case CLK_REQ_OFF_RXSTALE_ISSUED: | ||
1139 | case CLK_REQ_OFF_FLUSH_ISSUED: | ||
1140 | return 0; /* RXSTALE flush not complete - retry */ | ||
1141 | case CLK_REQ_OFF_RXSTALE_FLUSHED: | ||
1142 | break; /* continue */ | ||
1143 | } | ||
1144 | |||
1145 | if (msm_uport->rx.flush != FLUSH_SHUTDOWN) { | ||
1146 | if (msm_uport->rx.flush == FLUSH_NONE) | ||
1147 | msm_hs_stop_rx_locked(uport); | ||
1148 | return 0; /* come back later to really clock off */ | ||
1149 | } | ||
1150 | |||
1151 | /* we really want to clock off */ | ||
1152 | clk_disable(msm_uport->clk); | ||
1153 | msm_uport->clk_state = MSM_HS_CLK_OFF; | ||
1154 | |||
1155 | if (use_low_power_rx_wakeup(msm_uport)) { | ||
1156 | msm_uport->rx_wakeup.ignore = 1; | ||
1157 | enable_irq(msm_uport->rx_wakeup.irq); | ||
1158 | } | ||
1159 | return 1; | ||
1160 | } | ||
1161 | |||
1162 | static enum hrtimer_restart msm_hs_clk_off_retry(struct hrtimer *timer) | ||
1163 | { | ||
1164 | unsigned long flags; | ||
1165 | int ret = HRTIMER_NORESTART; | ||
1166 | struct msm_hs_port *msm_uport = container_of(timer, struct msm_hs_port, | ||
1167 | clk_off_timer); | ||
1168 | struct uart_port *uport = &msm_uport->uport; | ||
1169 | |||
1170 | spin_lock_irqsave(&uport->lock, flags); | ||
1171 | |||
1172 | if (!msm_hs_check_clock_off_locked(uport)) { | ||
1173 | hrtimer_forward_now(timer, msm_uport->clk_off_delay); | ||
1174 | ret = HRTIMER_RESTART; | ||
1175 | } | ||
1176 | |||
1177 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1178 | |||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | static irqreturn_t msm_hs_isr(int irq, void *dev) | ||
1183 | { | ||
1184 | unsigned long flags; | ||
1185 | unsigned long isr_status; | ||
1186 | struct msm_hs_port *msm_uport = dev; | ||
1187 | struct uart_port *uport = &msm_uport->uport; | ||
1188 | struct circ_buf *tx_buf = &uport->state->xmit; | ||
1189 | struct msm_hs_tx *tx = &msm_uport->tx; | ||
1190 | struct msm_hs_rx *rx = &msm_uport->rx; | ||
1191 | |||
1192 | spin_lock_irqsave(&uport->lock, flags); | ||
1193 | |||
1194 | isr_status = msm_hs_read(uport, UARTDM_MISR_ADDR); | ||
1195 | |||
1196 | /* Uart RX starting */ | ||
1197 | if (isr_status & UARTDM_ISR_RXLEV_BMSK) { | ||
1198 | msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK; | ||
1199 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
1200 | } | ||
1201 | /* Stale rx interrupt */ | ||
1202 | if (isr_status & UARTDM_ISR_RXSTALE_BMSK) { | ||
1203 | msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE); | ||
1204 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT); | ||
1205 | |||
1206 | if (msm_uport->clk_req_off_state == CLK_REQ_OFF_RXSTALE_ISSUED) | ||
1207 | msm_uport->clk_req_off_state = | ||
1208 | CLK_REQ_OFF_FLUSH_ISSUED; | ||
1209 | if (rx->flush == FLUSH_NONE) { | ||
1210 | rx->flush = FLUSH_DATA_READY; | ||
1211 | msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1); | ||
1212 | } | ||
1213 | } | ||
1214 | /* tx ready interrupt */ | ||
1215 | if (isr_status & UARTDM_ISR_TX_READY_BMSK) { | ||
1216 | /* Clear TX Ready */ | ||
1217 | msm_hs_write(uport, UARTDM_CR_ADDR, CLEAR_TX_READY); | ||
1218 | |||
1219 | if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) { | ||
1220 | msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK; | ||
1221 | msm_hs_write(uport, UARTDM_IMR_ADDR, | ||
1222 | msm_uport->imr_reg); | ||
1223 | } | ||
1224 | |||
1225 | /* Complete DMA TX transactions and submit new transactions */ | ||
1226 | tx_buf->tail = (tx_buf->tail + tx->tx_count) & ~UART_XMIT_SIZE; | ||
1227 | |||
1228 | tx->dma_in_flight = 0; | ||
1229 | |||
1230 | uport->icount.tx += tx->tx_count; | ||
1231 | if (tx->tx_ready_int_en) | ||
1232 | msm_hs_submit_tx_locked(uport); | ||
1233 | |||
1234 | if (uart_circ_chars_pending(tx_buf) < WAKEUP_CHARS) | ||
1235 | uart_write_wakeup(uport); | ||
1236 | } | ||
1237 | if (isr_status & UARTDM_ISR_TXLEV_BMSK) { | ||
1238 | /* TX FIFO is empty */ | ||
1239 | msm_uport->imr_reg &= ~UARTDM_ISR_TXLEV_BMSK; | ||
1240 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
1241 | if (!msm_hs_check_clock_off_locked(uport)) | ||
1242 | hrtimer_start(&msm_uport->clk_off_timer, | ||
1243 | msm_uport->clk_off_delay, | ||
1244 | HRTIMER_MODE_REL); | ||
1245 | } | ||
1246 | |||
1247 | /* Change in CTS interrupt */ | ||
1248 | if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK) | ||
1249 | msm_hs_handle_delta_cts(uport); | ||
1250 | |||
1251 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1252 | |||
1253 | return IRQ_HANDLED; | ||
1254 | } | ||
1255 | |||
1256 | void msm_hs_request_clock_off_locked(struct uart_port *uport) | ||
1257 | { | ||
1258 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1259 | |||
1260 | if (msm_uport->clk_state == MSM_HS_CLK_ON) { | ||
1261 | msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF; | ||
1262 | msm_uport->clk_req_off_state = CLK_REQ_OFF_START; | ||
1263 | if (!use_low_power_rx_wakeup(msm_uport)) | ||
1264 | set_rfr_locked(uport, 0); | ||
1265 | msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK; | ||
1266 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
1267 | } | ||
1268 | } | ||
1269 | |||
1270 | /** | ||
1271 | * msm_hs_request_clock_off - request to (i.e. asynchronously) turn off uart | ||
1272 | * clock once pending TX is flushed and Rx DMA command is terminated. | ||
1273 | * @uport: uart_port structure for the device instance. | ||
1274 | * | ||
1275 | * This functions puts the device into a partially active low power mode. It | ||
1276 | * waits to complete all pending tx transactions, flushes ongoing Rx DMA | ||
1277 | * command and terminates UART side Rx transaction, puts UART HW in non DMA | ||
1278 | * mode and then clocks off the device. A client calls this when no UART | ||
1279 | * data is expected. msm_request_clock_on() must be called before any further | ||
1280 | * UART can be sent or received. | ||
1281 | */ | ||
1282 | void msm_hs_request_clock_off(struct uart_port *uport) | ||
1283 | { | ||
1284 | unsigned long flags; | ||
1285 | |||
1286 | spin_lock_irqsave(&uport->lock, flags); | ||
1287 | msm_hs_request_clock_off_locked(uport); | ||
1288 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1289 | } | ||
1290 | |||
1291 | void msm_hs_request_clock_on_locked(struct uart_port *uport) | ||
1292 | { | ||
1293 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1294 | unsigned int data; | ||
1295 | |||
1296 | switch (msm_uport->clk_state) { | ||
1297 | case MSM_HS_CLK_OFF: | ||
1298 | clk_enable(msm_uport->clk); | ||
1299 | disable_irq_nosync(msm_uport->rx_wakeup.irq); | ||
1300 | /* fall-through */ | ||
1301 | case MSM_HS_CLK_REQUEST_OFF: | ||
1302 | if (msm_uport->rx.flush == FLUSH_STOP || | ||
1303 | msm_uport->rx.flush == FLUSH_SHUTDOWN) { | ||
1304 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX); | ||
1305 | data = msm_hs_read(uport, UARTDM_DMEN_ADDR); | ||
1306 | data |= UARTDM_RX_DM_EN_BMSK; | ||
1307 | msm_hs_write(uport, UARTDM_DMEN_ADDR, data); | ||
1308 | } | ||
1309 | hrtimer_try_to_cancel(&msm_uport->clk_off_timer); | ||
1310 | if (msm_uport->rx.flush == FLUSH_SHUTDOWN) | ||
1311 | msm_hs_start_rx_locked(uport); | ||
1312 | if (!use_low_power_rx_wakeup(msm_uport)) | ||
1313 | set_rfr_locked(uport, 1); | ||
1314 | if (msm_uport->rx.flush == FLUSH_STOP) | ||
1315 | msm_uport->rx.flush = FLUSH_IGNORE; | ||
1316 | msm_uport->clk_state = MSM_HS_CLK_ON; | ||
1317 | break; | ||
1318 | case MSM_HS_CLK_ON: | ||
1319 | break; | ||
1320 | case MSM_HS_CLK_PORT_OFF: | ||
1321 | break; | ||
1322 | } | ||
1323 | } | ||
1324 | |||
1325 | /** | ||
1326 | * msm_hs_request_clock_on - Switch the device from partially active low | ||
1327 | * power mode to fully active (i.e. clock on) mode. | ||
1328 | * @uport: uart_port structure for the device. | ||
1329 | * | ||
1330 | * This function switches on the input clock, puts UART HW into DMA mode | ||
1331 | * and enqueues an Rx DMA command if the device was in partially active | ||
1332 | * mode. It has no effect if called with the device in inactive state. | ||
1333 | */ | ||
1334 | void msm_hs_request_clock_on(struct uart_port *uport) | ||
1335 | { | ||
1336 | unsigned long flags; | ||
1337 | |||
1338 | spin_lock_irqsave(&uport->lock, flags); | ||
1339 | msm_hs_request_clock_on_locked(uport); | ||
1340 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1341 | } | ||
1342 | |||
1343 | static irqreturn_t msm_hs_rx_wakeup_isr(int irq, void *dev) | ||
1344 | { | ||
1345 | unsigned int wakeup = 0; | ||
1346 | unsigned long flags; | ||
1347 | struct msm_hs_port *msm_uport = dev; | ||
1348 | struct uart_port *uport = &msm_uport->uport; | ||
1349 | struct tty_struct *tty = NULL; | ||
1350 | |||
1351 | spin_lock_irqsave(&uport->lock, flags); | ||
1352 | if (msm_uport->clk_state == MSM_HS_CLK_OFF) { | ||
1353 | /* ignore the first irq - it is a pending irq that occured | ||
1354 | * before enable_irq() */ | ||
1355 | if (msm_uport->rx_wakeup.ignore) | ||
1356 | msm_uport->rx_wakeup.ignore = 0; | ||
1357 | else | ||
1358 | wakeup = 1; | ||
1359 | } | ||
1360 | |||
1361 | if (wakeup) { | ||
1362 | /* the uart was clocked off during an rx, wake up and | ||
1363 | * optionally inject char into tty rx */ | ||
1364 | msm_hs_request_clock_on_locked(uport); | ||
1365 | if (msm_uport->rx_wakeup.inject_rx) { | ||
1366 | tty = uport->state->port.tty; | ||
1367 | tty_insert_flip_char(tty, | ||
1368 | msm_uport->rx_wakeup.rx_to_inject, | ||
1369 | TTY_NORMAL); | ||
1370 | queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work); | ||
1371 | } | ||
1372 | } | ||
1373 | |||
1374 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1375 | |||
1376 | return IRQ_HANDLED; | ||
1377 | } | ||
1378 | |||
1379 | static const char *msm_hs_type(struct uart_port *port) | ||
1380 | { | ||
1381 | return (port->type == PORT_MSM) ? "MSM_HS_UART" : NULL; | ||
1382 | } | ||
1383 | |||
1384 | /* Called when port is opened */ | ||
1385 | static int msm_hs_startup(struct uart_port *uport) | ||
1386 | { | ||
1387 | int ret; | ||
1388 | int rfr_level; | ||
1389 | unsigned long flags; | ||
1390 | unsigned int data; | ||
1391 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1392 | struct circ_buf *tx_buf = &uport->state->xmit; | ||
1393 | struct msm_hs_tx *tx = &msm_uport->tx; | ||
1394 | struct msm_hs_rx *rx = &msm_uport->rx; | ||
1395 | |||
1396 | rfr_level = uport->fifosize; | ||
1397 | if (rfr_level > 16) | ||
1398 | rfr_level -= 16; | ||
1399 | |||
1400 | tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE, | ||
1401 | DMA_TO_DEVICE); | ||
1402 | |||
1403 | /* do not let tty layer execute RX in global workqueue, use a | ||
1404 | * dedicated workqueue managed by this driver */ | ||
1405 | uport->state->port.tty->low_latency = 1; | ||
1406 | |||
1407 | /* turn on uart clk */ | ||
1408 | ret = msm_hs_init_clk_locked(uport); | ||
1409 | if (unlikely(ret)) { | ||
1410 | printk(KERN_ERR "Turning uartclk failed!\n"); | ||
1411 | goto err_msm_hs_init_clk; | ||
1412 | } | ||
1413 | |||
1414 | /* Set auto RFR Level */ | ||
1415 | data = msm_hs_read(uport, UARTDM_MR1_ADDR); | ||
1416 | data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK; | ||
1417 | data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK; | ||
1418 | data |= (UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2)); | ||
1419 | data |= (UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level); | ||
1420 | msm_hs_write(uport, UARTDM_MR1_ADDR, data); | ||
1421 | |||
1422 | /* Make sure RXSTALE count is non-zero */ | ||
1423 | data = msm_hs_read(uport, UARTDM_IPR_ADDR); | ||
1424 | if (!data) { | ||
1425 | data |= 0x1f & UARTDM_IPR_STALE_LSB_BMSK; | ||
1426 | msm_hs_write(uport, UARTDM_IPR_ADDR, data); | ||
1427 | } | ||
1428 | |||
1429 | /* Enable Data Mover Mode */ | ||
1430 | data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK; | ||
1431 | msm_hs_write(uport, UARTDM_DMEN_ADDR, data); | ||
1432 | |||
1433 | /* Reset TX */ | ||
1434 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX); | ||
1435 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX); | ||
1436 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS); | ||
1437 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_BREAK_INT); | ||
1438 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT); | ||
1439 | msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS); | ||
1440 | msm_hs_write(uport, UARTDM_CR_ADDR, RFR_LOW); | ||
1441 | /* Turn on Uart Receiver */ | ||
1442 | msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_EN_BMSK); | ||
1443 | |||
1444 | /* Turn on Uart Transmitter */ | ||
1445 | msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_EN_BMSK); | ||
1446 | |||
1447 | /* Initialize the tx */ | ||
1448 | tx->tx_ready_int_en = 0; | ||
1449 | tx->dma_in_flight = 0; | ||
1450 | |||
1451 | tx->xfer.complete_func = msm_hs_dmov_tx_callback; | ||
1452 | tx->xfer.execute_func = NULL; | ||
1453 | |||
1454 | tx->command_ptr->cmd = CMD_LC | | ||
1455 | CMD_DST_CRCI(msm_uport->dma_tx_crci) | CMD_MODE_BOX; | ||
1456 | |||
1457 | tx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16) | ||
1458 | | (MSM_UARTDM_BURST_SIZE); | ||
1459 | |||
1460 | tx->command_ptr->row_offset = (MSM_UARTDM_BURST_SIZE << 16); | ||
1461 | |||
1462 | tx->command_ptr->dst_row_addr = | ||
1463 | msm_uport->uport.mapbase + UARTDM_TF_ADDR; | ||
1464 | |||
1465 | |||
1466 | /* Turn on Uart Receive */ | ||
1467 | rx->xfer.complete_func = msm_hs_dmov_rx_callback; | ||
1468 | rx->xfer.execute_func = NULL; | ||
1469 | |||
1470 | rx->command_ptr->cmd = CMD_LC | | ||
1471 | CMD_SRC_CRCI(msm_uport->dma_rx_crci) | CMD_MODE_BOX; | ||
1472 | |||
1473 | rx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16) | ||
1474 | | (MSM_UARTDM_BURST_SIZE); | ||
1475 | rx->command_ptr->row_offset = MSM_UARTDM_BURST_SIZE; | ||
1476 | rx->command_ptr->src_row_addr = uport->mapbase + UARTDM_RF_ADDR; | ||
1477 | |||
1478 | |||
1479 | msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK; | ||
1480 | /* Enable reading the current CTS, no harm even if CTS is ignored */ | ||
1481 | msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK; | ||
1482 | |||
1483 | msm_hs_write(uport, UARTDM_TFWR_ADDR, 0); /* TXLEV on empty TX fifo */ | ||
1484 | |||
1485 | |||
1486 | ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH, | ||
1487 | "msm_hs_uart", msm_uport); | ||
1488 | if (unlikely(ret)) { | ||
1489 | printk(KERN_ERR "Request msm_hs_uart IRQ failed!\n"); | ||
1490 | goto err_request_irq; | ||
1491 | } | ||
1492 | if (use_low_power_rx_wakeup(msm_uport)) { | ||
1493 | ret = request_irq(msm_uport->rx_wakeup.irq, | ||
1494 | msm_hs_rx_wakeup_isr, | ||
1495 | IRQF_TRIGGER_FALLING, | ||
1496 | "msm_hs_rx_wakeup", msm_uport); | ||
1497 | if (unlikely(ret)) { | ||
1498 | printk(KERN_ERR "Request msm_hs_rx_wakeup IRQ failed!\n"); | ||
1499 | free_irq(uport->irq, msm_uport); | ||
1500 | goto err_request_irq; | ||
1501 | } | ||
1502 | disable_irq(msm_uport->rx_wakeup.irq); | ||
1503 | } | ||
1504 | |||
1505 | spin_lock_irqsave(&uport->lock, flags); | ||
1506 | |||
1507 | msm_hs_write(uport, UARTDM_RFWR_ADDR, 0); | ||
1508 | msm_hs_start_rx_locked(uport); | ||
1509 | |||
1510 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1511 | ret = pm_runtime_set_active(uport->dev); | ||
1512 | if (ret) | ||
1513 | dev_err(uport->dev, "set active error:%d\n", ret); | ||
1514 | pm_runtime_enable(uport->dev); | ||
1515 | |||
1516 | return 0; | ||
1517 | |||
1518 | err_request_irq: | ||
1519 | err_msm_hs_init_clk: | ||
1520 | dma_unmap_single(uport->dev, tx->dma_base, | ||
1521 | UART_XMIT_SIZE, DMA_TO_DEVICE); | ||
1522 | return ret; | ||
1523 | } | ||
1524 | |||
1525 | /* Initialize tx and rx data structures */ | ||
1526 | static int __devinit uartdm_init_port(struct uart_port *uport) | ||
1527 | { | ||
1528 | int ret = 0; | ||
1529 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1530 | struct msm_hs_tx *tx = &msm_uport->tx; | ||
1531 | struct msm_hs_rx *rx = &msm_uport->rx; | ||
1532 | |||
1533 | /* Allocate the command pointer. Needs to be 64 bit aligned */ | ||
1534 | tx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA); | ||
1535 | if (!tx->command_ptr) | ||
1536 | return -ENOMEM; | ||
1537 | |||
1538 | tx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA); | ||
1539 | if (!tx->command_ptr_ptr) { | ||
1540 | ret = -ENOMEM; | ||
1541 | goto err_tx_command_ptr_ptr; | ||
1542 | } | ||
1543 | |||
1544 | tx->mapped_cmd_ptr = dma_map_single(uport->dev, tx->command_ptr, | ||
1545 | sizeof(dmov_box), DMA_TO_DEVICE); | ||
1546 | tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev, | ||
1547 | tx->command_ptr_ptr, | ||
1548 | sizeof(u32 *), DMA_TO_DEVICE); | ||
1549 | tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr); | ||
1550 | |||
1551 | init_waitqueue_head(&rx->wait); | ||
1552 | |||
1553 | rx->pool = dma_pool_create("rx_buffer_pool", uport->dev, | ||
1554 | UARTDM_RX_BUF_SIZE, 16, 0); | ||
1555 | if (!rx->pool) { | ||
1556 | pr_err("%s(): cannot allocate rx_buffer_pool", __func__); | ||
1557 | ret = -ENOMEM; | ||
1558 | goto err_dma_pool_create; | ||
1559 | } | ||
1560 | |||
1561 | rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer); | ||
1562 | if (!rx->buffer) { | ||
1563 | pr_err("%s(): cannot allocate rx->buffer", __func__); | ||
1564 | ret = -ENOMEM; | ||
1565 | goto err_dma_pool_alloc; | ||
1566 | } | ||
1567 | |||
1568 | /* Allocate the command pointer. Needs to be 64 bit aligned */ | ||
1569 | rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA); | ||
1570 | if (!rx->command_ptr) { | ||
1571 | pr_err("%s(): cannot allocate rx->command_ptr", __func__); | ||
1572 | ret = -ENOMEM; | ||
1573 | goto err_rx_command_ptr; | ||
1574 | } | ||
1575 | |||
1576 | rx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA); | ||
1577 | if (!rx->command_ptr_ptr) { | ||
1578 | pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__); | ||
1579 | ret = -ENOMEM; | ||
1580 | goto err_rx_command_ptr_ptr; | ||
1581 | } | ||
1582 | |||
1583 | rx->command_ptr->num_rows = ((UARTDM_RX_BUF_SIZE >> 4) << 16) | | ||
1584 | (UARTDM_RX_BUF_SIZE >> 4); | ||
1585 | |||
1586 | rx->command_ptr->dst_row_addr = rx->rbuffer; | ||
1587 | |||
1588 | rx->mapped_cmd_ptr = dma_map_single(uport->dev, rx->command_ptr, | ||
1589 | sizeof(dmov_box), DMA_TO_DEVICE); | ||
1590 | |||
1591 | *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr); | ||
1592 | |||
1593 | rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr, | ||
1594 | sizeof(u32 *), DMA_TO_DEVICE); | ||
1595 | rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr); | ||
1596 | |||
1597 | INIT_WORK(&rx->tty_work, msm_hs_tty_flip_buffer_work); | ||
1598 | |||
1599 | return ret; | ||
1600 | |||
1601 | err_rx_command_ptr_ptr: | ||
1602 | kfree(rx->command_ptr); | ||
1603 | err_rx_command_ptr: | ||
1604 | dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer, | ||
1605 | msm_uport->rx.rbuffer); | ||
1606 | err_dma_pool_alloc: | ||
1607 | dma_pool_destroy(msm_uport->rx.pool); | ||
1608 | err_dma_pool_create: | ||
1609 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr, | ||
1610 | sizeof(u32 *), DMA_TO_DEVICE); | ||
1611 | dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr, | ||
1612 | sizeof(dmov_box), DMA_TO_DEVICE); | ||
1613 | kfree(msm_uport->tx.command_ptr_ptr); | ||
1614 | err_tx_command_ptr_ptr: | ||
1615 | kfree(msm_uport->tx.command_ptr); | ||
1616 | return ret; | ||
1617 | } | ||
1618 | |||
1619 | static int __devinit msm_hs_probe(struct platform_device *pdev) | ||
1620 | { | ||
1621 | int ret; | ||
1622 | struct uart_port *uport; | ||
1623 | struct msm_hs_port *msm_uport; | ||
1624 | struct resource *resource; | ||
1625 | const struct msm_serial_hs_platform_data *pdata = | ||
1626 | pdev->dev.platform_data; | ||
1627 | |||
1628 | if (pdev->id < 0 || pdev->id >= UARTDM_NR) { | ||
1629 | printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id); | ||
1630 | return -EINVAL; | ||
1631 | } | ||
1632 | |||
1633 | msm_uport = &q_uart_port[pdev->id]; | ||
1634 | uport = &msm_uport->uport; | ||
1635 | |||
1636 | uport->dev = &pdev->dev; | ||
1637 | |||
1638 | resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1639 | if (unlikely(!resource)) | ||
1640 | return -ENXIO; | ||
1641 | |||
1642 | uport->mapbase = resource->start; | ||
1643 | uport->irq = platform_get_irq(pdev, 0); | ||
1644 | if (unlikely(uport->irq < 0)) | ||
1645 | return -ENXIO; | ||
1646 | |||
1647 | if (unlikely(set_irq_wake(uport->irq, 1))) | ||
1648 | return -ENXIO; | ||
1649 | |||
1650 | if (pdata == NULL || pdata->rx_wakeup_irq < 0) | ||
1651 | msm_uport->rx_wakeup.irq = -1; | ||
1652 | else { | ||
1653 | msm_uport->rx_wakeup.irq = pdata->rx_wakeup_irq; | ||
1654 | msm_uport->rx_wakeup.ignore = 1; | ||
1655 | msm_uport->rx_wakeup.inject_rx = pdata->inject_rx_on_wakeup; | ||
1656 | msm_uport->rx_wakeup.rx_to_inject = pdata->rx_to_inject; | ||
1657 | |||
1658 | if (unlikely(msm_uport->rx_wakeup.irq < 0)) | ||
1659 | return -ENXIO; | ||
1660 | |||
1661 | if (unlikely(set_irq_wake(msm_uport->rx_wakeup.irq, 1))) | ||
1662 | return -ENXIO; | ||
1663 | } | ||
1664 | |||
1665 | if (pdata == NULL) | ||
1666 | msm_uport->exit_lpm_cb = NULL; | ||
1667 | else | ||
1668 | msm_uport->exit_lpm_cb = pdata->exit_lpm_cb; | ||
1669 | |||
1670 | resource = platform_get_resource_byname(pdev, IORESOURCE_DMA, | ||
1671 | "uartdm_channels"); | ||
1672 | if (unlikely(!resource)) | ||
1673 | return -ENXIO; | ||
1674 | |||
1675 | msm_uport->dma_tx_channel = resource->start; | ||
1676 | msm_uport->dma_rx_channel = resource->end; | ||
1677 | |||
1678 | resource = platform_get_resource_byname(pdev, IORESOURCE_DMA, | ||
1679 | "uartdm_crci"); | ||
1680 | if (unlikely(!resource)) | ||
1681 | return -ENXIO; | ||
1682 | |||
1683 | msm_uport->dma_tx_crci = resource->start; | ||
1684 | msm_uport->dma_rx_crci = resource->end; | ||
1685 | |||
1686 | uport->iotype = UPIO_MEM; | ||
1687 | uport->fifosize = UART_FIFOSIZE; | ||
1688 | uport->ops = &msm_hs_ops; | ||
1689 | uport->flags = UPF_BOOT_AUTOCONF; | ||
1690 | uport->uartclk = UARTCLK; | ||
1691 | msm_uport->imr_reg = 0x0; | ||
1692 | msm_uport->clk = clk_get(&pdev->dev, "uartdm_clk"); | ||
1693 | if (IS_ERR(msm_uport->clk)) | ||
1694 | return PTR_ERR(msm_uport->clk); | ||
1695 | |||
1696 | ret = uartdm_init_port(uport); | ||
1697 | if (unlikely(ret)) | ||
1698 | return ret; | ||
1699 | |||
1700 | msm_uport->clk_state = MSM_HS_CLK_PORT_OFF; | ||
1701 | hrtimer_init(&msm_uport->clk_off_timer, CLOCK_MONOTONIC, | ||
1702 | HRTIMER_MODE_REL); | ||
1703 | msm_uport->clk_off_timer.function = msm_hs_clk_off_retry; | ||
1704 | msm_uport->clk_off_delay = ktime_set(0, 1000000); /* 1ms */ | ||
1705 | |||
1706 | uport->line = pdev->id; | ||
1707 | return uart_add_one_port(&msm_hs_driver, uport); | ||
1708 | } | ||
1709 | |||
1710 | static int __init msm_serial_hs_init(void) | ||
1711 | { | ||
1712 | int ret, i; | ||
1713 | |||
1714 | /* Init all UARTS as non-configured */ | ||
1715 | for (i = 0; i < UARTDM_NR; i++) | ||
1716 | q_uart_port[i].uport.type = PORT_UNKNOWN; | ||
1717 | |||
1718 | msm_hs_workqueue = create_singlethread_workqueue("msm_serial_hs"); | ||
1719 | if (unlikely(!msm_hs_workqueue)) | ||
1720 | return -ENOMEM; | ||
1721 | |||
1722 | ret = uart_register_driver(&msm_hs_driver); | ||
1723 | if (unlikely(ret)) { | ||
1724 | printk(KERN_ERR "%s failed to load\n", __func__); | ||
1725 | goto err_uart_register_driver; | ||
1726 | } | ||
1727 | |||
1728 | ret = platform_driver_register(&msm_serial_hs_platform_driver); | ||
1729 | if (ret) { | ||
1730 | printk(KERN_ERR "%s failed to load\n", __func__); | ||
1731 | goto err_platform_driver_register; | ||
1732 | } | ||
1733 | |||
1734 | return ret; | ||
1735 | |||
1736 | err_platform_driver_register: | ||
1737 | uart_unregister_driver(&msm_hs_driver); | ||
1738 | err_uart_register_driver: | ||
1739 | destroy_workqueue(msm_hs_workqueue); | ||
1740 | return ret; | ||
1741 | } | ||
1742 | module_init(msm_serial_hs_init); | ||
1743 | |||
1744 | /* | ||
1745 | * Called by the upper layer when port is closed. | ||
1746 | * - Disables the port | ||
1747 | * - Unhook the ISR | ||
1748 | */ | ||
1749 | static void msm_hs_shutdown(struct uart_port *uport) | ||
1750 | { | ||
1751 | unsigned long flags; | ||
1752 | struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport); | ||
1753 | |||
1754 | BUG_ON(msm_uport->rx.flush < FLUSH_STOP); | ||
1755 | |||
1756 | spin_lock_irqsave(&uport->lock, flags); | ||
1757 | clk_enable(msm_uport->clk); | ||
1758 | |||
1759 | /* Disable the transmitter */ | ||
1760 | msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK); | ||
1761 | /* Disable the receiver */ | ||
1762 | msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_DISABLE_BMSK); | ||
1763 | |||
1764 | pm_runtime_disable(uport->dev); | ||
1765 | pm_runtime_set_suspended(uport->dev); | ||
1766 | |||
1767 | /* Free the interrupt */ | ||
1768 | free_irq(uport->irq, msm_uport); | ||
1769 | if (use_low_power_rx_wakeup(msm_uport)) | ||
1770 | free_irq(msm_uport->rx_wakeup.irq, msm_uport); | ||
1771 | |||
1772 | msm_uport->imr_reg = 0; | ||
1773 | msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg); | ||
1774 | |||
1775 | wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN); | ||
1776 | |||
1777 | clk_disable(msm_uport->clk); /* to balance local clk_enable() */ | ||
1778 | if (msm_uport->clk_state != MSM_HS_CLK_OFF) | ||
1779 | clk_disable(msm_uport->clk); /* to balance clk_state */ | ||
1780 | msm_uport->clk_state = MSM_HS_CLK_PORT_OFF; | ||
1781 | |||
1782 | dma_unmap_single(uport->dev, msm_uport->tx.dma_base, | ||
1783 | UART_XMIT_SIZE, DMA_TO_DEVICE); | ||
1784 | |||
1785 | spin_unlock_irqrestore(&uport->lock, flags); | ||
1786 | |||
1787 | if (cancel_work_sync(&msm_uport->rx.tty_work)) | ||
1788 | msm_hs_tty_flip_buffer_work(&msm_uport->rx.tty_work); | ||
1789 | } | ||
1790 | |||
1791 | static void __exit msm_serial_hs_exit(void) | ||
1792 | { | ||
1793 | flush_workqueue(msm_hs_workqueue); | ||
1794 | destroy_workqueue(msm_hs_workqueue); | ||
1795 | platform_driver_unregister(&msm_serial_hs_platform_driver); | ||
1796 | uart_unregister_driver(&msm_hs_driver); | ||
1797 | } | ||
1798 | module_exit(msm_serial_hs_exit); | ||
1799 | |||
1800 | #ifdef CONFIG_PM_RUNTIME | ||
1801 | static int msm_hs_runtime_idle(struct device *dev) | ||
1802 | { | ||
1803 | /* | ||
1804 | * returning success from idle results in runtime suspend to be | ||
1805 | * called | ||
1806 | */ | ||
1807 | return 0; | ||
1808 | } | ||
1809 | |||
1810 | static int msm_hs_runtime_resume(struct device *dev) | ||
1811 | { | ||
1812 | struct platform_device *pdev = container_of(dev, struct | ||
1813 | platform_device, dev); | ||
1814 | struct msm_hs_port *msm_uport = &q_uart_port[pdev->id]; | ||
1815 | |||
1816 | msm_hs_request_clock_on(&msm_uport->uport); | ||
1817 | return 0; | ||
1818 | } | ||
1819 | |||
1820 | static int msm_hs_runtime_suspend(struct device *dev) | ||
1821 | { | ||
1822 | struct platform_device *pdev = container_of(dev, struct | ||
1823 | platform_device, dev); | ||
1824 | struct msm_hs_port *msm_uport = &q_uart_port[pdev->id]; | ||
1825 | |||
1826 | msm_hs_request_clock_off(&msm_uport->uport); | ||
1827 | return 0; | ||
1828 | } | ||
1829 | #else | ||
1830 | #define msm_hs_runtime_idle NULL | ||
1831 | #define msm_hs_runtime_resume NULL | ||
1832 | #define msm_hs_runtime_suspend NULL | ||
1833 | #endif | ||
1834 | |||
1835 | static const struct dev_pm_ops msm_hs_dev_pm_ops = { | ||
1836 | .runtime_suspend = msm_hs_runtime_suspend, | ||
1837 | .runtime_resume = msm_hs_runtime_resume, | ||
1838 | .runtime_idle = msm_hs_runtime_idle, | ||
1839 | }; | ||
1840 | |||
1841 | static struct platform_driver msm_serial_hs_platform_driver = { | ||
1842 | .probe = msm_hs_probe, | ||
1843 | .remove = __devexit_p(msm_hs_remove), | ||
1844 | .driver = { | ||
1845 | .name = "msm_serial_hs", | ||
1846 | .owner = THIS_MODULE, | ||
1847 | .pm = &msm_hs_dev_pm_ops, | ||
1848 | }, | ||
1849 | }; | ||
1850 | |||
1851 | static struct uart_driver msm_hs_driver = { | ||
1852 | .owner = THIS_MODULE, | ||
1853 | .driver_name = "msm_serial_hs", | ||
1854 | .dev_name = "ttyHS", | ||
1855 | .nr = UARTDM_NR, | ||
1856 | .cons = 0, | ||
1857 | }; | ||
1858 | |||
1859 | static struct uart_ops msm_hs_ops = { | ||
1860 | .tx_empty = msm_hs_tx_empty, | ||
1861 | .set_mctrl = msm_hs_set_mctrl_locked, | ||
1862 | .get_mctrl = msm_hs_get_mctrl_locked, | ||
1863 | .stop_tx = msm_hs_stop_tx_locked, | ||
1864 | .start_tx = msm_hs_start_tx_locked, | ||
1865 | .stop_rx = msm_hs_stop_rx_locked, | ||
1866 | .enable_ms = msm_hs_enable_ms_locked, | ||
1867 | .break_ctl = msm_hs_break_ctl, | ||
1868 | .startup = msm_hs_startup, | ||
1869 | .shutdown = msm_hs_shutdown, | ||
1870 | .set_termios = msm_hs_set_termios, | ||
1871 | .pm = msm_hs_pm, | ||
1872 | .type = msm_hs_type, | ||
1873 | .config_port = msm_hs_config_port, | ||
1874 | .release_port = msm_hs_release_port, | ||
1875 | .request_port = msm_hs_request_port, | ||
1876 | }; | ||
1877 | |||
1878 | MODULE_DESCRIPTION("High Speed UART Driver for the MSM chipset"); | ||
1879 | MODULE_VERSION("1.2"); | ||
1880 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c new file mode 100644 index 000000000000..beeff1e86093 --- /dev/null +++ b/drivers/tty/serial/msm_smd_tty.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* drivers/tty/serial/msm_smd_tty.c | ||
2 | * | ||
3 | * Copyright (C) 2007 Google, Inc. | ||
4 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | ||
5 | * Author: Brian Swetland <swetland@google.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/cdev.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/wait.h> | ||
23 | |||
24 | #include <linux/tty.h> | ||
25 | #include <linux/tty_driver.h> | ||
26 | #include <linux/tty_flip.h> | ||
27 | |||
28 | #include <mach/msm_smd.h> | ||
29 | |||
30 | #define MAX_SMD_TTYS 32 | ||
31 | |||
32 | struct smd_tty_info { | ||
33 | struct tty_port port; | ||
34 | smd_channel_t *ch; | ||
35 | }; | ||
36 | |||
37 | struct smd_tty_channel_desc { | ||
38 | int id; | ||
39 | const char *name; | ||
40 | }; | ||
41 | |||
42 | static struct smd_tty_info smd_tty[MAX_SMD_TTYS]; | ||
43 | |||
44 | static const struct smd_tty_channel_desc smd_default_tty_channels[] = { | ||
45 | { .id = 0, .name = "SMD_DS" }, | ||
46 | { .id = 27, .name = "SMD_GPSNMEA" }, | ||
47 | }; | ||
48 | |||
49 | static const struct smd_tty_channel_desc *smd_tty_channels = | ||
50 | smd_default_tty_channels; | ||
51 | static int smd_tty_channels_len = ARRAY_SIZE(smd_default_tty_channels); | ||
52 | |||
53 | static void smd_tty_notify(void *priv, unsigned event) | ||
54 | { | ||
55 | unsigned char *ptr; | ||
56 | int avail; | ||
57 | struct smd_tty_info *info = priv; | ||
58 | struct tty_struct *tty; | ||
59 | |||
60 | if (event != SMD_EVENT_DATA) | ||
61 | return; | ||
62 | |||
63 | tty = tty_port_tty_get(&info->port); | ||
64 | if (!tty) | ||
65 | return; | ||
66 | |||
67 | for (;;) { | ||
68 | if (test_bit(TTY_THROTTLED, &tty->flags)) | ||
69 | break; | ||
70 | avail = smd_read_avail(info->ch); | ||
71 | if (avail == 0) | ||
72 | break; | ||
73 | |||
74 | avail = tty_prepare_flip_string(tty, &ptr, avail); | ||
75 | |||
76 | if (smd_read(info->ch, ptr, avail) != avail) { | ||
77 | /* shouldn't be possible since we're in interrupt | ||
78 | ** context here and nobody else could 'steal' our | ||
79 | ** characters. | ||
80 | */ | ||
81 | pr_err("OOPS - smd_tty_buffer mismatch?!"); | ||
82 | } | ||
83 | |||
84 | tty_flip_buffer_push(tty); | ||
85 | } | ||
86 | |||
87 | /* XXX only when writable and necessary */ | ||
88 | tty_wakeup(tty); | ||
89 | tty_kref_put(tty); | ||
90 | } | ||
91 | |||
92 | static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty) | ||
93 | { | ||
94 | int i, res = 0; | ||
95 | int n = tty->index; | ||
96 | const char *name = NULL; | ||
97 | struct smd_tty_info *info = smd_tty + n; | ||
98 | |||
99 | for (i = 0; i < smd_tty_channels_len; i++) { | ||
100 | if (smd_tty_channels[i].id == n) { | ||
101 | name = smd_tty_channels[i].name; | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | if (!name) | ||
106 | return -ENODEV; | ||
107 | |||
108 | if (info->ch) | ||
109 | smd_kick(info->ch); | ||
110 | else | ||
111 | res = smd_open(name, &info->ch, info, smd_tty_notify); | ||
112 | |||
113 | if (!res) | ||
114 | tty->driver_data = info; | ||
115 | |||
116 | return res; | ||
117 | } | ||
118 | |||
119 | static void smd_tty_port_shutdown(struct tty_port *tport) | ||
120 | { | ||
121 | struct smd_tty_info *info; | ||
122 | struct tty_struct *tty = tty_port_tty_get(tport); | ||
123 | |||
124 | info = tty->driver_data; | ||
125 | if (info->ch) { | ||
126 | smd_close(info->ch); | ||
127 | info->ch = 0; | ||
128 | } | ||
129 | |||
130 | tty->driver_data = 0; | ||
131 | tty_kref_put(tty); | ||
132 | } | ||
133 | |||
134 | static int smd_tty_open(struct tty_struct *tty, struct file *f) | ||
135 | { | ||
136 | struct smd_tty_info *info = smd_tty + tty->index; | ||
137 | |||
138 | return tty_port_open(&info->port, tty, f); | ||
139 | } | ||
140 | |||
141 | static void smd_tty_close(struct tty_struct *tty, struct file *f) | ||
142 | { | ||
143 | struct smd_tty_info *info = tty->driver_data; | ||
144 | |||
145 | tty_port_close(&info->port, tty, f); | ||
146 | } | ||
147 | |||
148 | static int smd_tty_write(struct tty_struct *tty, | ||
149 | const unsigned char *buf, int len) | ||
150 | { | ||
151 | struct smd_tty_info *info = tty->driver_data; | ||
152 | int avail; | ||
153 | |||
154 | /* if we're writing to a packet channel we will | ||
155 | ** never be able to write more data than there | ||
156 | ** is currently space for | ||
157 | */ | ||
158 | avail = smd_write_avail(info->ch); | ||
159 | if (len > avail) | ||
160 | len = avail; | ||
161 | |||
162 | return smd_write(info->ch, buf, len); | ||
163 | } | ||
164 | |||
165 | static int smd_tty_write_room(struct tty_struct *tty) | ||
166 | { | ||
167 | struct smd_tty_info *info = tty->driver_data; | ||
168 | return smd_write_avail(info->ch); | ||
169 | } | ||
170 | |||
171 | static int smd_tty_chars_in_buffer(struct tty_struct *tty) | ||
172 | { | ||
173 | struct smd_tty_info *info = tty->driver_data; | ||
174 | return smd_read_avail(info->ch); | ||
175 | } | ||
176 | |||
177 | static void smd_tty_unthrottle(struct tty_struct *tty) | ||
178 | { | ||
179 | struct smd_tty_info *info = tty->driver_data; | ||
180 | smd_kick(info->ch); | ||
181 | } | ||
182 | |||
183 | static const struct tty_port_operations smd_tty_port_ops = { | ||
184 | .shutdown = smd_tty_port_shutdown, | ||
185 | .activate = smd_tty_port_activate, | ||
186 | }; | ||
187 | |||
188 | static const struct tty_operations smd_tty_ops = { | ||
189 | .open = smd_tty_open, | ||
190 | .close = smd_tty_close, | ||
191 | .write = smd_tty_write, | ||
192 | .write_room = smd_tty_write_room, | ||
193 | .chars_in_buffer = smd_tty_chars_in_buffer, | ||
194 | .unthrottle = smd_tty_unthrottle, | ||
195 | }; | ||
196 | |||
197 | static struct tty_driver *smd_tty_driver; | ||
198 | |||
199 | static int __init smd_tty_init(void) | ||
200 | { | ||
201 | int ret, i; | ||
202 | |||
203 | smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS); | ||
204 | if (smd_tty_driver == 0) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | smd_tty_driver->owner = THIS_MODULE; | ||
208 | smd_tty_driver->driver_name = "smd_tty_driver"; | ||
209 | smd_tty_driver->name = "smd"; | ||
210 | smd_tty_driver->major = 0; | ||
211 | smd_tty_driver->minor_start = 0; | ||
212 | smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
213 | smd_tty_driver->subtype = SERIAL_TYPE_NORMAL; | ||
214 | smd_tty_driver->init_termios = tty_std_termios; | ||
215 | smd_tty_driver->init_termios.c_iflag = 0; | ||
216 | smd_tty_driver->init_termios.c_oflag = 0; | ||
217 | smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; | ||
218 | smd_tty_driver->init_termios.c_lflag = 0; | ||
219 | smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | | ||
220 | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
221 | tty_set_operations(smd_tty_driver, &smd_tty_ops); | ||
222 | |||
223 | ret = tty_register_driver(smd_tty_driver); | ||
224 | if (ret) | ||
225 | return ret; | ||
226 | |||
227 | for (i = 0; i < smd_tty_channels_len; i++) { | ||
228 | tty_port_init(&smd_tty[smd_tty_channels[i].id].port); | ||
229 | smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops; | ||
230 | tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0); | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | module_init(smd_tty_init); | ||
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 5c7abe4c94dd..0e8eec516df4 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -80,14 +80,16 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, | |||
80 | /* | 80 | /* |
81 | * Try to register a serial port | 81 | * Try to register a serial port |
82 | */ | 82 | */ |
83 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev, | 83 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev) |
84 | const struct of_device_id *id) | ||
85 | { | 84 | { |
86 | struct of_serial_info *info; | 85 | struct of_serial_info *info; |
87 | struct uart_port port; | 86 | struct uart_port port; |
88 | int port_type; | 87 | int port_type; |
89 | int ret; | 88 | int ret; |
90 | 89 | ||
90 | if (!ofdev->dev.of_match) | ||
91 | return -EINVAL; | ||
92 | |||
91 | if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) | 93 | if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) |
92 | return -EBUSY; | 94 | return -EBUSY; |
93 | 95 | ||
@@ -95,7 +97,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev, | |||
95 | if (info == NULL) | 97 | if (info == NULL) |
96 | return -ENOMEM; | 98 | return -ENOMEM; |
97 | 99 | ||
98 | port_type = (unsigned long)id->data; | 100 | port_type = (unsigned long)ofdev->dev.of_match->data; |
99 | ret = of_platform_serial_setup(ofdev, port_type, &port); | 101 | ret = of_platform_serial_setup(ofdev, port_type, &port); |
100 | if (ret) | 102 | if (ret) |
101 | goto out; | 103 | goto out; |
@@ -160,21 +162,21 @@ static int of_platform_serial_remove(struct platform_device *ofdev) | |||
160 | * A few common types, add more as needed. | 162 | * A few common types, add more as needed. |
161 | */ | 163 | */ |
162 | static struct of_device_id __devinitdata of_platform_serial_table[] = { | 164 | static struct of_device_id __devinitdata of_platform_serial_table[] = { |
163 | { .type = "serial", .compatible = "ns8250", .data = (void *)PORT_8250, }, | 165 | { .compatible = "ns8250", .data = (void *)PORT_8250, }, |
164 | { .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, }, | 166 | { .compatible = "ns16450", .data = (void *)PORT_16450, }, |
165 | { .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, }, | 167 | { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, |
166 | { .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, }, | 168 | { .compatible = "ns16550", .data = (void *)PORT_16550, }, |
167 | { .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, }, | 169 | { .compatible = "ns16750", .data = (void *)PORT_16750, }, |
168 | { .type = "serial", .compatible = "ns16850", .data = (void *)PORT_16850, }, | 170 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, |
169 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | 171 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL |
170 | { .type = "serial", .compatible = "ibm,qpace-nwp-serial", | 172 | { .compatible = "ibm,qpace-nwp-serial", |
171 | .data = (void *)PORT_NWPSERIAL, }, | 173 | .data = (void *)PORT_NWPSERIAL, }, |
172 | #endif | 174 | #endif |
173 | { .type = "serial", .data = (void *)PORT_UNKNOWN, }, | 175 | { .type = "serial", .data = (void *)PORT_UNKNOWN, }, |
174 | { /* end of list */ }, | 176 | { /* end of list */ }, |
175 | }; | 177 | }; |
176 | 178 | ||
177 | static struct of_platform_driver of_platform_serial_driver = { | 179 | static struct platform_driver of_platform_serial_driver = { |
178 | .driver = { | 180 | .driver = { |
179 | .name = "of_serial", | 181 | .name = "of_serial", |
180 | .owner = THIS_MODULE, | 182 | .owner = THIS_MODULE, |
@@ -186,13 +188,13 @@ static struct of_platform_driver of_platform_serial_driver = { | |||
186 | 188 | ||
187 | static int __init of_platform_serial_init(void) | 189 | static int __init of_platform_serial_init(void) |
188 | { | 190 | { |
189 | return of_register_platform_driver(&of_platform_serial_driver); | 191 | return platform_driver_register(&of_platform_serial_driver); |
190 | } | 192 | } |
191 | module_init(of_platform_serial_init); | 193 | module_init(of_platform_serial_init); |
192 | 194 | ||
193 | static void __exit of_platform_serial_exit(void) | 195 | static void __exit of_platform_serial_exit(void) |
194 | { | 196 | { |
195 | return of_unregister_platform_driver(&of_platform_serial_driver); | 197 | return platform_driver_unregister(&of_platform_serial_driver); |
196 | }; | 198 | }; |
197 | module_exit(of_platform_serial_exit); | 199 | module_exit(of_platform_serial_exit); |
198 | 200 | ||
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 7f2f01058789..763537943a53 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
@@ -20,6 +20,10 @@ | |||
20 | * this driver as required for the omap-platform. | 20 | * this driver as required for the omap-platform. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #if defined(CONFIG_SERIAL_OMAP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
24 | #define SUPPORT_SYSRQ | ||
25 | #endif | ||
26 | |||
23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
24 | #include <linux/init.h> | 28 | #include <linux/init.h> |
25 | #include <linux/console.h> | 29 | #include <linux/console.h> |
@@ -190,7 +194,6 @@ static inline void receive_chars(struct uart_omap_port *up, int *status) | |||
190 | if (up->port.line == up->port.cons->index) { | 194 | if (up->port.line == up->port.cons->index) { |
191 | /* Recover the break flag from console xmit */ | 195 | /* Recover the break flag from console xmit */ |
192 | lsr |= up->lsr_break_flag; | 196 | lsr |= up->lsr_break_flag; |
193 | up->lsr_break_flag = 0; | ||
194 | } | 197 | } |
195 | #endif | 198 | #endif |
196 | if (lsr & UART_LSR_BI) | 199 | if (lsr & UART_LSR_BI) |
@@ -517,6 +520,9 @@ static int serial_omap_startup(struct uart_port *port) | |||
517 | up->ier = UART_IER_RLSI | UART_IER_RDI; | 520 | up->ier = UART_IER_RLSI | UART_IER_RDI; |
518 | serial_out(up, UART_IER, up->ier); | 521 | serial_out(up, UART_IER, up->ier); |
519 | 522 | ||
523 | /* Enable module level wake up */ | ||
524 | serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); | ||
525 | |||
520 | up->port_activity = jiffies; | 526 | up->port_activity = jiffies; |
521 | return 0; | 527 | return 0; |
522 | } | 528 | } |
@@ -824,9 +830,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state, | |||
824 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); | 830 | serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
825 | serial_out(up, UART_EFR, efr); | 831 | serial_out(up, UART_EFR, efr); |
826 | serial_out(up, UART_LCR, 0); | 832 | serial_out(up, UART_LCR, 0); |
827 | /* Enable module level wake up */ | ||
828 | serial_out(up, UART_OMAP_WER, | ||
829 | (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0); | ||
830 | } | 833 | } |
831 | 834 | ||
832 | static void serial_omap_release_port(struct uart_port *port) | 835 | static void serial_omap_release_port(struct uart_port *port) |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 70a61458ec42..a9ad7f33526d 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/serial_core.h> | 21 | #include <linux/serial_core.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/dmi.h> | ||
24 | 25 | ||
25 | #include <linux/dmaengine.h> | 26 | #include <linux/dmaengine.h> |
26 | #include <linux/pch_dma.h> | 27 | #include <linux/pch_dma.h> |
@@ -40,10 +41,11 @@ enum { | |||
40 | 41 | ||
41 | #define PCH_UART_DRIVER_DEVICE "ttyPCH" | 42 | #define PCH_UART_DRIVER_DEVICE "ttyPCH" |
42 | 43 | ||
43 | #define PCH_UART_NR_GE_256FIFO 1 | 44 | /* Set the max number of UART port |
44 | #define PCH_UART_NR_GE_64FIFO 3 | 45 | * Intel EG20T PCH: 4 port |
45 | #define PCH_UART_NR_GE (PCH_UART_NR_GE_256FIFO+PCH_UART_NR_GE_64FIFO) | 46 | * OKI SEMICONDUCTOR ML7213 IOH: 3 port |
46 | #define PCH_UART_NR PCH_UART_NR_GE | 47 | */ |
48 | #define PCH_UART_NR 4 | ||
47 | 49 | ||
48 | #define PCH_UART_HANDLED_RX_INT (1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1)) | 50 | #define PCH_UART_HANDLED_RX_INT (1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1)) |
49 | #define PCH_UART_HANDLED_TX_INT (1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1)) | 51 | #define PCH_UART_HANDLED_TX_INT (1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1)) |
@@ -192,6 +194,8 @@ enum { | |||
192 | #define PCH_UART_HAL_LOOP (PCH_UART_MCR_LOOP) | 194 | #define PCH_UART_HAL_LOOP (PCH_UART_MCR_LOOP) |
193 | #define PCH_UART_HAL_AFE (PCH_UART_MCR_AFE) | 195 | #define PCH_UART_HAL_AFE (PCH_UART_MCR_AFE) |
194 | 196 | ||
197 | #define PCI_VENDOR_ID_ROHM 0x10DB | ||
198 | |||
195 | struct pch_uart_buffer { | 199 | struct pch_uart_buffer { |
196 | unsigned char *buf; | 200 | unsigned char *buf; |
197 | int size; | 201 | int size; |
@@ -215,6 +219,7 @@ struct eg20t_port { | |||
215 | struct pch_uart_buffer rxbuf; | 219 | struct pch_uart_buffer rxbuf; |
216 | unsigned int dmsr; | 220 | unsigned int dmsr; |
217 | unsigned int fcr; | 221 | unsigned int fcr; |
222 | unsigned int mcr; | ||
218 | unsigned int use_dma; | 223 | unsigned int use_dma; |
219 | unsigned int use_dma_flag; | 224 | unsigned int use_dma_flag; |
220 | struct dma_async_tx_descriptor *desc_tx; | 225 | struct dma_async_tx_descriptor *desc_tx; |
@@ -223,13 +228,44 @@ struct eg20t_port { | |||
223 | struct pch_dma_slave param_rx; | 228 | struct pch_dma_slave param_rx; |
224 | struct dma_chan *chan_tx; | 229 | struct dma_chan *chan_tx; |
225 | struct dma_chan *chan_rx; | 230 | struct dma_chan *chan_rx; |
226 | struct scatterlist sg_tx; | 231 | struct scatterlist *sg_tx_p; |
232 | int nent; | ||
227 | struct scatterlist sg_rx; | 233 | struct scatterlist sg_rx; |
228 | int tx_dma_use; | 234 | int tx_dma_use; |
229 | void *rx_buf_virt; | 235 | void *rx_buf_virt; |
230 | dma_addr_t rx_buf_dma; | 236 | dma_addr_t rx_buf_dma; |
231 | }; | 237 | }; |
232 | 238 | ||
239 | /** | ||
240 | * struct pch_uart_driver_data - private data structure for UART-DMA | ||
241 | * @port_type: The number of DMA channel | ||
242 | * @line_no: UART port line number (0, 1, 2...) | ||
243 | */ | ||
244 | struct pch_uart_driver_data { | ||
245 | int port_type; | ||
246 | int line_no; | ||
247 | }; | ||
248 | |||
249 | enum pch_uart_num_t { | ||
250 | pch_et20t_uart0 = 0, | ||
251 | pch_et20t_uart1, | ||
252 | pch_et20t_uart2, | ||
253 | pch_et20t_uart3, | ||
254 | pch_ml7213_uart0, | ||
255 | pch_ml7213_uart1, | ||
256 | pch_ml7213_uart2, | ||
257 | }; | ||
258 | |||
259 | static struct pch_uart_driver_data drv_dat[] = { | ||
260 | [pch_et20t_uart0] = {PCH_UART_8LINE, 0}, | ||
261 | [pch_et20t_uart1] = {PCH_UART_2LINE, 1}, | ||
262 | [pch_et20t_uart2] = {PCH_UART_2LINE, 2}, | ||
263 | [pch_et20t_uart3] = {PCH_UART_2LINE, 3}, | ||
264 | [pch_ml7213_uart0] = {PCH_UART_8LINE, 0}, | ||
265 | [pch_ml7213_uart1] = {PCH_UART_2LINE, 1}, | ||
266 | [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, | ||
267 | }; | ||
268 | |||
233 | static unsigned int default_baud = 9600; | 269 | static unsigned int default_baud = 9600; |
234 | static const int trigger_level_256[4] = { 1, 64, 128, 224 }; | 270 | static const int trigger_level_256[4] = { 1, 64, 128, 224 }; |
235 | static const int trigger_level_64[4] = { 1, 16, 32, 56 }; | 271 | static const int trigger_level_64[4] = { 1, 16, 32, 56 }; |
@@ -278,7 +314,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, | |||
278 | 314 | ||
279 | div = DIV_ROUND(priv->base_baud / 16, baud); | 315 | div = DIV_ROUND(priv->base_baud / 16, baud); |
280 | if (div < 0 || USHRT_MAX <= div) { | 316 | if (div < 0 || USHRT_MAX <= div) { |
281 | pr_err("Invalid Baud(div=0x%x)\n", div); | 317 | dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div); |
282 | return -EINVAL; | 318 | return -EINVAL; |
283 | } | 319 | } |
284 | 320 | ||
@@ -286,17 +322,17 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, | |||
286 | dlm = ((unsigned int)div >> 8) & 0x00FFU; | 322 | dlm = ((unsigned int)div >> 8) & 0x00FFU; |
287 | 323 | ||
288 | if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) { | 324 | if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) { |
289 | pr_err("Invalid parity(0x%x)\n", parity); | 325 | dev_err(priv->port.dev, "Invalid parity(0x%x)\n", parity); |
290 | return -EINVAL; | 326 | return -EINVAL; |
291 | } | 327 | } |
292 | 328 | ||
293 | if (bits & ~PCH_UART_LCR_WLS) { | 329 | if (bits & ~PCH_UART_LCR_WLS) { |
294 | pr_err("Invalid bits(0x%x)\n", bits); | 330 | dev_err(priv->port.dev, "Invalid bits(0x%x)\n", bits); |
295 | return -EINVAL; | 331 | return -EINVAL; |
296 | } | 332 | } |
297 | 333 | ||
298 | if (stb & ~PCH_UART_LCR_STB) { | 334 | if (stb & ~PCH_UART_LCR_STB) { |
299 | pr_err("Invalid STB(0x%x)\n", stb); | 335 | dev_err(priv->port.dev, "Invalid STB(0x%x)\n", stb); |
300 | return -EINVAL; | 336 | return -EINVAL; |
301 | } | 337 | } |
302 | 338 | ||
@@ -304,7 +340,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, | |||
304 | lcr |= bits; | 340 | lcr |= bits; |
305 | lcr |= stb; | 341 | lcr |= stb; |
306 | 342 | ||
307 | pr_debug("%s:baud = %d, div = %04x, lcr = %02x (%lu)\n", | 343 | dev_dbg(priv->port.dev, "%s:baud = %d, div = %04x, lcr = %02x (%lu)\n", |
308 | __func__, baud, div, lcr, jiffies); | 344 | __func__, baud, div, lcr, jiffies); |
309 | iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); | 345 | iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); |
310 | iowrite8(dll, priv->membase + PCH_UART_DLL); | 346 | iowrite8(dll, priv->membase + PCH_UART_DLL); |
@@ -318,7 +354,8 @@ static int pch_uart_hal_fifo_reset(struct eg20t_port *priv, | |||
318 | unsigned int flag) | 354 | unsigned int flag) |
319 | { | 355 | { |
320 | if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) { | 356 | if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) { |
321 | pr_err("%s:Invalid flag(0x%x)\n", __func__, flag); | 357 | dev_err(priv->port.dev, "%s:Invalid flag(0x%x)\n", |
358 | __func__, flag); | ||
322 | return -EINVAL; | 359 | return -EINVAL; |
323 | } | 360 | } |
324 | 361 | ||
@@ -337,17 +374,20 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv, | |||
337 | u8 fcr; | 374 | u8 fcr; |
338 | 375 | ||
339 | if (dmamode & ~PCH_UART_FCR_DMS) { | 376 | if (dmamode & ~PCH_UART_FCR_DMS) { |
340 | pr_err("%s:Invalid DMA Mode(0x%x)\n", __func__, dmamode); | 377 | dev_err(priv->port.dev, "%s:Invalid DMA Mode(0x%x)\n", |
378 | __func__, dmamode); | ||
341 | return -EINVAL; | 379 | return -EINVAL; |
342 | } | 380 | } |
343 | 381 | ||
344 | if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) { | 382 | if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) { |
345 | pr_err("%s:Invalid FIFO SIZE(0x%x)\n", __func__, fifo_size); | 383 | dev_err(priv->port.dev, "%s:Invalid FIFO SIZE(0x%x)\n", |
384 | __func__, fifo_size); | ||
346 | return -EINVAL; | 385 | return -EINVAL; |
347 | } | 386 | } |
348 | 387 | ||
349 | if (trigger & ~PCH_UART_FCR_RFTL) { | 388 | if (trigger & ~PCH_UART_FCR_RFTL) { |
350 | pr_err("%s:Invalid TRIGGER(0x%x)\n", __func__, trigger); | 389 | dev_err(priv->port.dev, "%s:Invalid TRIGGER(0x%x)\n", |
390 | __func__, trigger); | ||
351 | return -EINVAL; | 391 | return -EINVAL; |
352 | } | 392 | } |
353 | 393 | ||
@@ -386,7 +426,7 @@ static u8 pch_uart_hal_get_modem(struct eg20t_port *priv) | |||
386 | return get_msr(priv, priv->membase); | 426 | return get_msr(priv, priv->membase); |
387 | } | 427 | } |
388 | 428 | ||
389 | static int pch_uart_hal_write(struct eg20t_port *priv, | 429 | static void pch_uart_hal_write(struct eg20t_port *priv, |
390 | const unsigned char *buf, int tx_size) | 430 | const unsigned char *buf, int tx_size) |
391 | { | 431 | { |
392 | int i; | 432 | int i; |
@@ -396,7 +436,6 @@ static int pch_uart_hal_write(struct eg20t_port *priv, | |||
396 | thr = buf[i++]; | 436 | thr = buf[i++]; |
397 | iowrite8(thr, priv->membase + PCH_UART_THR); | 437 | iowrite8(thr, priv->membase + PCH_UART_THR); |
398 | } | 438 | } |
399 | return i; | ||
400 | } | 439 | } |
401 | 440 | ||
402 | static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf, | 441 | static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf, |
@@ -452,7 +491,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf, | |||
452 | port = &priv->port; | 491 | port = &priv->port; |
453 | tty = tty_port_tty_get(&port->state->port); | 492 | tty = tty_port_tty_get(&port->state->port); |
454 | if (!tty) { | 493 | if (!tty) { |
455 | pr_debug("%s:tty is busy now", __func__); | 494 | dev_dbg(priv->port.dev, "%s:tty is busy now", __func__); |
456 | return -EBUSY; | 495 | return -EBUSY; |
457 | } | 496 | } |
458 | 497 | ||
@@ -469,8 +508,8 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf) | |||
469 | struct uart_port *port = &priv->port; | 508 | struct uart_port *port = &priv->port; |
470 | 509 | ||
471 | if (port->x_char) { | 510 | if (port->x_char) { |
472 | pr_debug("%s:X character send %02x (%lu)\n", __func__, | 511 | dev_dbg(priv->port.dev, "%s:X character send %02x (%lu)\n", |
473 | port->x_char, jiffies); | 512 | __func__, port->x_char, jiffies); |
474 | buf[0] = port->x_char; | 513 | buf[0] = port->x_char; |
475 | port->x_char = 0; | 514 | port->x_char = 0; |
476 | ret = 1; | 515 | ret = 1; |
@@ -490,7 +529,7 @@ static int dma_push_rx(struct eg20t_port *priv, int size) | |||
490 | port = &priv->port; | 529 | port = &priv->port; |
491 | tty = tty_port_tty_get(&port->state->port); | 530 | tty = tty_port_tty_get(&port->state->port); |
492 | if (!tty) { | 531 | if (!tty) { |
493 | pr_debug("%s:tty is busy now", __func__); | 532 | dev_dbg(priv->port.dev, "%s:tty is busy now", __func__); |
494 | return 0; | 533 | return 0; |
495 | } | 534 | } |
496 | 535 | ||
@@ -560,11 +599,13 @@ static void pch_request_dma(struct uart_port *port) | |||
560 | /* Set Tx DMA */ | 599 | /* Set Tx DMA */ |
561 | param = &priv->param_tx; | 600 | param = &priv->param_tx; |
562 | param->dma_dev = &dma_dev->dev; | 601 | param->dma_dev = &dma_dev->dev; |
563 | param->chan_id = priv->port.line; | 602 | param->chan_id = priv->port.line * 2; /* Tx = 0, 2, 4, ... */ |
603 | |||
564 | param->tx_reg = port->mapbase + UART_TX; | 604 | param->tx_reg = port->mapbase + UART_TX; |
565 | chan = dma_request_channel(mask, filter, param); | 605 | chan = dma_request_channel(mask, filter, param); |
566 | if (!chan) { | 606 | if (!chan) { |
567 | pr_err("%s:dma_request_channel FAILS(Tx)\n", __func__); | 607 | dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n", |
608 | __func__); | ||
568 | return; | 609 | return; |
569 | } | 610 | } |
570 | priv->chan_tx = chan; | 611 | priv->chan_tx = chan; |
@@ -572,11 +613,13 @@ static void pch_request_dma(struct uart_port *port) | |||
572 | /* Set Rx DMA */ | 613 | /* Set Rx DMA */ |
573 | param = &priv->param_rx; | 614 | param = &priv->param_rx; |
574 | param->dma_dev = &dma_dev->dev; | 615 | param->dma_dev = &dma_dev->dev; |
575 | param->chan_id = priv->port.line + 1; /* Rx = Tx + 1 */ | 616 | param->chan_id = priv->port.line * 2 + 1; /* Rx = Tx + 1 */ |
617 | |||
576 | param->rx_reg = port->mapbase + UART_RX; | 618 | param->rx_reg = port->mapbase + UART_RX; |
577 | chan = dma_request_channel(mask, filter, param); | 619 | chan = dma_request_channel(mask, filter, param); |
578 | if (!chan) { | 620 | if (!chan) { |
579 | pr_err("%s:dma_request_channel FAILS(Rx)\n", __func__); | 621 | dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n", |
622 | __func__); | ||
580 | dma_release_channel(priv->chan_tx); | 623 | dma_release_channel(priv->chan_tx); |
581 | return; | 624 | return; |
582 | } | 625 | } |
@@ -592,16 +635,20 @@ static void pch_dma_rx_complete(void *arg) | |||
592 | struct eg20t_port *priv = arg; | 635 | struct eg20t_port *priv = arg; |
593 | struct uart_port *port = &priv->port; | 636 | struct uart_port *port = &priv->port; |
594 | struct tty_struct *tty = tty_port_tty_get(&port->state->port); | 637 | struct tty_struct *tty = tty_port_tty_get(&port->state->port); |
638 | int count; | ||
595 | 639 | ||
596 | if (!tty) { | 640 | if (!tty) { |
597 | pr_debug("%s:tty is busy now", __func__); | 641 | dev_dbg(priv->port.dev, "%s:tty is busy now", __func__); |
598 | return; | 642 | return; |
599 | } | 643 | } |
600 | 644 | ||
601 | if (dma_push_rx(priv, priv->trigger_level)) | 645 | dma_sync_sg_for_cpu(port->dev, &priv->sg_rx, 1, DMA_FROM_DEVICE); |
646 | count = dma_push_rx(priv, priv->trigger_level); | ||
647 | if (count) | ||
602 | tty_flip_buffer_push(tty); | 648 | tty_flip_buffer_push(tty); |
603 | |||
604 | tty_kref_put(tty); | 649 | tty_kref_put(tty); |
650 | async_tx_ack(priv->desc_rx); | ||
651 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); | ||
605 | } | 652 | } |
606 | 653 | ||
607 | static void pch_dma_tx_complete(void *arg) | 654 | static void pch_dma_tx_complete(void *arg) |
@@ -609,16 +656,23 @@ static void pch_dma_tx_complete(void *arg) | |||
609 | struct eg20t_port *priv = arg; | 656 | struct eg20t_port *priv = arg; |
610 | struct uart_port *port = &priv->port; | 657 | struct uart_port *port = &priv->port; |
611 | struct circ_buf *xmit = &port->state->xmit; | 658 | struct circ_buf *xmit = &port->state->xmit; |
659 | struct scatterlist *sg = priv->sg_tx_p; | ||
660 | int i; | ||
612 | 661 | ||
613 | xmit->tail += sg_dma_len(&priv->sg_tx); | 662 | for (i = 0; i < priv->nent; i++, sg++) { |
663 | xmit->tail += sg_dma_len(sg); | ||
664 | port->icount.tx += sg_dma_len(sg); | ||
665 | } | ||
614 | xmit->tail &= UART_XMIT_SIZE - 1; | 666 | xmit->tail &= UART_XMIT_SIZE - 1; |
615 | port->icount.tx += sg_dma_len(&priv->sg_tx); | ||
616 | |||
617 | async_tx_ack(priv->desc_tx); | 667 | async_tx_ack(priv->desc_tx); |
668 | dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE); | ||
618 | priv->tx_dma_use = 0; | 669 | priv->tx_dma_use = 0; |
670 | priv->nent = 0; | ||
671 | kfree(priv->sg_tx_p); | ||
672 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT); | ||
619 | } | 673 | } |
620 | 674 | ||
621 | static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size) | 675 | static int pop_tx(struct eg20t_port *priv, int size) |
622 | { | 676 | { |
623 | int count = 0; | 677 | int count = 0; |
624 | struct uart_port *port = &priv->port; | 678 | struct uart_port *port = &priv->port; |
@@ -631,13 +685,13 @@ static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size) | |||
631 | int cnt_to_end = | 685 | int cnt_to_end = |
632 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); | 686 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); |
633 | int sz = min(size - count, cnt_to_end); | 687 | int sz = min(size - count, cnt_to_end); |
634 | memcpy(&buf[count], &xmit->buf[xmit->tail], sz); | 688 | pch_uart_hal_write(priv, &xmit->buf[xmit->tail], sz); |
635 | xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1); | 689 | xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1); |
636 | count += sz; | 690 | count += sz; |
637 | } while (!uart_circ_empty(xmit) && count < size); | 691 | } while (!uart_circ_empty(xmit) && count < size); |
638 | 692 | ||
639 | pop_tx_end: | 693 | pop_tx_end: |
640 | pr_debug("%d characters. Remained %d characters. (%lu)\n", | 694 | dev_dbg(priv->port.dev, "%d characters. Remained %d characters.(%lu)\n", |
641 | count, size - count, jiffies); | 695 | count, size - count, jiffies); |
642 | 696 | ||
643 | return count; | 697 | return count; |
@@ -679,7 +733,7 @@ static int dma_handle_rx(struct eg20t_port *priv) | |||
679 | 733 | ||
680 | sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */ | 734 | sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */ |
681 | 735 | ||
682 | sg_dma_len(sg) = priv->fifo_size; | 736 | sg_dma_len(sg) = priv->trigger_level; |
683 | 737 | ||
684 | sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt), | 738 | sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt), |
685 | sg_dma_len(sg), (unsigned long)priv->rx_buf_virt & | 739 | sg_dma_len(sg), (unsigned long)priv->rx_buf_virt & |
@@ -689,7 +743,8 @@ static int dma_handle_rx(struct eg20t_port *priv) | |||
689 | 743 | ||
690 | desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, | 744 | desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx, |
691 | sg, 1, DMA_FROM_DEVICE, | 745 | sg, 1, DMA_FROM_DEVICE, |
692 | DMA_PREP_INTERRUPT); | 746 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
747 | |||
693 | if (!desc) | 748 | if (!desc) |
694 | return 0; | 749 | return 0; |
695 | 750 | ||
@@ -706,14 +761,14 @@ static unsigned int handle_tx(struct eg20t_port *priv) | |||
706 | { | 761 | { |
707 | struct uart_port *port = &priv->port; | 762 | struct uart_port *port = &priv->port; |
708 | struct circ_buf *xmit = &port->state->xmit; | 763 | struct circ_buf *xmit = &port->state->xmit; |
709 | int ret; | ||
710 | int fifo_size; | 764 | int fifo_size; |
711 | int tx_size; | 765 | int tx_size; |
712 | int size; | 766 | int size; |
713 | int tx_empty; | 767 | int tx_empty; |
714 | 768 | ||
715 | if (!priv->start_tx) { | 769 | if (!priv->start_tx) { |
716 | pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies); | 770 | dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n", |
771 | __func__, jiffies); | ||
717 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | 772 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); |
718 | priv->tx_empty = 1; | 773 | priv->tx_empty = 1; |
719 | return 0; | 774 | return 0; |
@@ -728,17 +783,21 @@ static unsigned int handle_tx(struct eg20t_port *priv) | |||
728 | fifo_size--; | 783 | fifo_size--; |
729 | } | 784 | } |
730 | size = min(xmit->head - xmit->tail, fifo_size); | 785 | size = min(xmit->head - xmit->tail, fifo_size); |
731 | tx_size = pop_tx(priv, xmit->buf, size); | 786 | if (size < 0) |
787 | size = fifo_size; | ||
788 | |||
789 | tx_size = pop_tx(priv, size); | ||
732 | if (tx_size > 0) { | 790 | if (tx_size > 0) { |
733 | ret = pch_uart_hal_write(priv, xmit->buf, tx_size); | 791 | port->icount.tx += tx_size; |
734 | port->icount.tx += ret; | ||
735 | tx_empty = 0; | 792 | tx_empty = 0; |
736 | } | 793 | } |
737 | 794 | ||
738 | priv->tx_empty = tx_empty; | 795 | priv->tx_empty = tx_empty; |
739 | 796 | ||
740 | if (tx_empty) | 797 | if (tx_empty) { |
741 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | 798 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); |
799 | uart_write_wakeup(port); | ||
800 | } | ||
742 | 801 | ||
743 | return PCH_UART_HANDLED_TX_INT; | 802 | return PCH_UART_HANDLED_TX_INT; |
744 | } | 803 | } |
@@ -747,14 +806,28 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) | |||
747 | { | 806 | { |
748 | struct uart_port *port = &priv->port; | 807 | struct uart_port *port = &priv->port; |
749 | struct circ_buf *xmit = &port->state->xmit; | 808 | struct circ_buf *xmit = &port->state->xmit; |
750 | struct scatterlist *sg = &priv->sg_tx; | 809 | struct scatterlist *sg; |
751 | int nent; | 810 | int nent; |
752 | int fifo_size; | 811 | int fifo_size; |
753 | int tx_empty; | 812 | int tx_empty; |
754 | struct dma_async_tx_descriptor *desc; | 813 | struct dma_async_tx_descriptor *desc; |
814 | int num; | ||
815 | int i; | ||
816 | int bytes; | ||
817 | int size; | ||
818 | int rem; | ||
755 | 819 | ||
756 | if (!priv->start_tx) { | 820 | if (!priv->start_tx) { |
757 | pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies); | 821 | dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n", |
822 | __func__, jiffies); | ||
823 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | ||
824 | priv->tx_empty = 1; | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | if (priv->tx_dma_use) { | ||
829 | dev_dbg(priv->port.dev, "%s:Tx is not completed. (%lu)\n", | ||
830 | __func__, jiffies); | ||
758 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | 831 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); |
759 | priv->tx_empty = 1; | 832 | priv->tx_empty = 1; |
760 | return 0; | 833 | return 0; |
@@ -769,37 +842,73 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) | |||
769 | fifo_size--; | 842 | fifo_size--; |
770 | } | 843 | } |
771 | 844 | ||
772 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | 845 | bytes = min((int)CIRC_CNT(xmit->head, xmit->tail, |
846 | UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head, | ||
847 | xmit->tail, UART_XMIT_SIZE)); | ||
848 | if (!bytes) { | ||
849 | dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__); | ||
850 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT); | ||
851 | uart_write_wakeup(port); | ||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | if (bytes > fifo_size) { | ||
856 | num = bytes / fifo_size + 1; | ||
857 | size = fifo_size; | ||
858 | rem = bytes % fifo_size; | ||
859 | } else { | ||
860 | num = 1; | ||
861 | size = bytes; | ||
862 | rem = bytes; | ||
863 | } | ||
864 | |||
865 | dev_dbg(priv->port.dev, "%s num=%d size=%d rem=%d\n", | ||
866 | __func__, num, size, rem); | ||
773 | 867 | ||
774 | priv->tx_dma_use = 1; | 868 | priv->tx_dma_use = 1; |
775 | 869 | ||
776 | sg_init_table(&priv->sg_tx, 1); /* Initialize SG table */ | 870 | priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); |
777 | 871 | ||
778 | sg_set_page(&priv->sg_tx, virt_to_page(xmit->buf), | 872 | sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */ |
779 | UART_XMIT_SIZE, (int)xmit->buf & ~PAGE_MASK); | 873 | sg = priv->sg_tx_p; |
780 | 874 | ||
781 | nent = dma_map_sg(port->dev, &priv->sg_tx, 1, DMA_TO_DEVICE); | 875 | for (i = 0; i < num; i++, sg++) { |
876 | if (i == (num - 1)) | ||
877 | sg_set_page(sg, virt_to_page(xmit->buf), | ||
878 | rem, fifo_size * i); | ||
879 | else | ||
880 | sg_set_page(sg, virt_to_page(xmit->buf), | ||
881 | size, fifo_size * i); | ||
882 | } | ||
883 | |||
884 | sg = priv->sg_tx_p; | ||
885 | nent = dma_map_sg(port->dev, sg, num, DMA_TO_DEVICE); | ||
782 | if (!nent) { | 886 | if (!nent) { |
783 | pr_err("%s:dma_map_sg Failed\n", __func__); | 887 | dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__); |
784 | return 0; | 888 | return 0; |
785 | } | 889 | } |
786 | 890 | priv->nent = nent; | |
787 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); | 891 | |
788 | sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + | 892 | for (i = 0; i < nent; i++, sg++) { |
789 | sg->offset; | 893 | sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) + |
790 | sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, | 894 | fifo_size * i; |
791 | UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head, | 895 | sg_dma_address(sg) = (sg_dma_address(sg) & |
792 | xmit->tail, UART_XMIT_SIZE)); | 896 | ~(UART_XMIT_SIZE - 1)) + sg->offset; |
897 | if (i == (nent - 1)) | ||
898 | sg_dma_len(sg) = rem; | ||
899 | else | ||
900 | sg_dma_len(sg) = size; | ||
901 | } | ||
793 | 902 | ||
794 | desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, | 903 | desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx, |
795 | sg, nent, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 904 | priv->sg_tx_p, nent, DMA_TO_DEVICE, |
905 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
796 | if (!desc) { | 906 | if (!desc) { |
797 | pr_err("%s:device_prep_slave_sg Failed\n", __func__); | 907 | dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n", |
908 | __func__); | ||
798 | return 0; | 909 | return 0; |
799 | } | 910 | } |
800 | 911 | dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE); | |
801 | dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE); | ||
802 | |||
803 | priv->desc_tx = desc; | 912 | priv->desc_tx = desc; |
804 | desc->callback = pch_dma_tx_complete; | 913 | desc->callback = pch_dma_tx_complete; |
805 | desc->callback_param = priv; | 914 | desc->callback_param = priv; |
@@ -854,10 +963,16 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
854 | } | 963 | } |
855 | break; | 964 | break; |
856 | case PCH_UART_IID_RDR: /* Received Data Ready */ | 965 | case PCH_UART_IID_RDR: /* Received Data Ready */ |
857 | if (priv->use_dma) | 966 | if (priv->use_dma) { |
967 | pch_uart_hal_disable_interrupt(priv, | ||
968 | PCH_UART_HAL_RX_INT); | ||
858 | ret = dma_handle_rx(priv); | 969 | ret = dma_handle_rx(priv); |
859 | else | 970 | if (!ret) |
971 | pch_uart_hal_enable_interrupt(priv, | ||
972 | PCH_UART_HAL_RX_INT); | ||
973 | } else { | ||
860 | ret = handle_rx(priv); | 974 | ret = handle_rx(priv); |
975 | } | ||
861 | break; | 976 | break; |
862 | case PCH_UART_IID_RDR_TO: /* Received Data Ready | 977 | case PCH_UART_IID_RDR_TO: /* Received Data Ready |
863 | (FIFO Timeout) */ | 978 | (FIFO Timeout) */ |
@@ -874,7 +989,8 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) | |||
874 | ret = PCH_UART_HANDLED_MS_INT; | 989 | ret = PCH_UART_HANDLED_MS_INT; |
875 | break; | 990 | break; |
876 | default: /* Never junp to this label */ | 991 | default: /* Never junp to this label */ |
877 | pr_err("%s:iid=%d (%lu)\n", __func__, iid, jiffies); | 992 | dev_err(priv->port.dev, "%s:iid=%d (%lu)\n", __func__, |
993 | iid, jiffies); | ||
878 | ret = -1; | 994 | ret = -1; |
879 | break; | 995 | break; |
880 | } | 996 | } |
@@ -932,7 +1048,6 @@ static unsigned int pch_uart_get_mctrl(struct uart_port *port) | |||
932 | static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 1048 | static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
933 | { | 1049 | { |
934 | u32 mcr = 0; | 1050 | u32 mcr = 0; |
935 | unsigned int dat; | ||
936 | struct eg20t_port *priv = container_of(port, struct eg20t_port, port); | 1051 | struct eg20t_port *priv = container_of(port, struct eg20t_port, port); |
937 | 1052 | ||
938 | if (mctrl & TIOCM_DTR) | 1053 | if (mctrl & TIOCM_DTR) |
@@ -942,11 +1057,11 @@ static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
942 | if (mctrl & TIOCM_LOOP) | 1057 | if (mctrl & TIOCM_LOOP) |
943 | mcr |= UART_MCR_LOOP; | 1058 | mcr |= UART_MCR_LOOP; |
944 | 1059 | ||
945 | if (mctrl) { | 1060 | if (priv->mcr & UART_MCR_AFE) |
946 | dat = pch_uart_get_mctrl(port); | 1061 | mcr |= UART_MCR_AFE; |
947 | dat |= mcr; | 1062 | |
948 | iowrite8(dat, priv->membase + UART_MCR); | 1063 | if (mctrl) |
949 | } | 1064 | iowrite8(mcr, priv->membase + UART_MCR); |
950 | } | 1065 | } |
951 | 1066 | ||
952 | static void pch_uart_stop_tx(struct uart_port *port) | 1067 | static void pch_uart_stop_tx(struct uart_port *port) |
@@ -963,9 +1078,13 @@ static void pch_uart_start_tx(struct uart_port *port) | |||
963 | 1078 | ||
964 | priv = container_of(port, struct eg20t_port, port); | 1079 | priv = container_of(port, struct eg20t_port, port); |
965 | 1080 | ||
966 | if (priv->use_dma) | 1081 | if (priv->use_dma) { |
967 | if (priv->tx_dma_use) | 1082 | if (priv->tx_dma_use) { |
1083 | dev_dbg(priv->port.dev, "%s : Tx DMA is NOT empty.\n", | ||
1084 | __func__); | ||
968 | return; | 1085 | return; |
1086 | } | ||
1087 | } | ||
969 | 1088 | ||
970 | priv->start_tx = 1; | 1089 | priv->start_tx = 1; |
971 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT); | 1090 | pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT); |
@@ -1010,7 +1129,12 @@ static int pch_uart_startup(struct uart_port *port) | |||
1010 | 1129 | ||
1011 | priv = container_of(port, struct eg20t_port, port); | 1130 | priv = container_of(port, struct eg20t_port, port); |
1012 | priv->tx_empty = 1; | 1131 | priv->tx_empty = 1; |
1013 | port->uartclk = priv->base_baud; | 1132 | |
1133 | if (port->uartclk) | ||
1134 | priv->base_baud = port->uartclk; | ||
1135 | else | ||
1136 | port->uartclk = priv->base_baud; | ||
1137 | |||
1014 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); | 1138 | pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); |
1015 | ret = pch_uart_hal_set_line(priv, default_baud, | 1139 | ret = pch_uart_hal_set_line(priv, default_baud, |
1016 | PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT, | 1140 | PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT, |
@@ -1081,7 +1205,8 @@ static void pch_uart_shutdown(struct uart_port *port) | |||
1081 | ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0, | 1205 | ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0, |
1082 | PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1); | 1206 | PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1); |
1083 | if (ret) | 1207 | if (ret) |
1084 | pr_err("pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); | 1208 | dev_err(priv->port.dev, |
1209 | "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); | ||
1085 | 1210 | ||
1086 | if (priv->use_dma_flag) | 1211 | if (priv->use_dma_flag) |
1087 | pch_free_dma(port); | 1212 | pch_free_dma(port); |
@@ -1130,6 +1255,13 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
1130 | } else { | 1255 | } else { |
1131 | parity = PCH_UART_HAL_PARITY_NONE; | 1256 | parity = PCH_UART_HAL_PARITY_NONE; |
1132 | } | 1257 | } |
1258 | |||
1259 | /* Only UART0 has auto hardware flow function */ | ||
1260 | if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256)) | ||
1261 | priv->mcr |= UART_MCR_AFE; | ||
1262 | else | ||
1263 | priv->mcr &= ~UART_MCR_AFE; | ||
1264 | |||
1133 | termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */ | 1265 | termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */ |
1134 | 1266 | ||
1135 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | 1267 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); |
@@ -1202,17 +1334,19 @@ static int pch_uart_verify_port(struct uart_port *port, | |||
1202 | 1334 | ||
1203 | priv = container_of(port, struct eg20t_port, port); | 1335 | priv = container_of(port, struct eg20t_port, port); |
1204 | if (serinfo->flags & UPF_LOW_LATENCY) { | 1336 | if (serinfo->flags & UPF_LOW_LATENCY) { |
1205 | pr_info("PCH UART : Use PIO Mode (without DMA)\n"); | 1337 | dev_info(priv->port.dev, |
1338 | "PCH UART : Use PIO Mode (without DMA)\n"); | ||
1206 | priv->use_dma = 0; | 1339 | priv->use_dma = 0; |
1207 | serinfo->flags &= ~UPF_LOW_LATENCY; | 1340 | serinfo->flags &= ~UPF_LOW_LATENCY; |
1208 | } else { | 1341 | } else { |
1209 | #ifndef CONFIG_PCH_DMA | 1342 | #ifndef CONFIG_PCH_DMA |
1210 | pr_err("%s : PCH DMA is not Loaded.\n", __func__); | 1343 | dev_err(priv->port.dev, "%s : PCH DMA is not Loaded.\n", |
1344 | __func__); | ||
1211 | return -EOPNOTSUPP; | 1345 | return -EOPNOTSUPP; |
1212 | #endif | 1346 | #endif |
1213 | priv->use_dma = 1; | 1347 | priv->use_dma = 1; |
1214 | priv->use_dma_flag = 1; | 1348 | priv->use_dma_flag = 1; |
1215 | pr_info("PCH UART : Use DMA Mode\n"); | 1349 | dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n"); |
1216 | } | 1350 | } |
1217 | 1351 | ||
1218 | return 0; | 1352 | return 0; |
@@ -1249,7 +1383,7 @@ static struct uart_driver pch_uart_driver = { | |||
1249 | }; | 1383 | }; |
1250 | 1384 | ||
1251 | static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | 1385 | static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, |
1252 | int port_type) | 1386 | const struct pci_device_id *id) |
1253 | { | 1387 | { |
1254 | struct eg20t_port *priv; | 1388 | struct eg20t_port *priv; |
1255 | int ret; | 1389 | int ret; |
@@ -1257,7 +1391,11 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1257 | unsigned int mapbase; | 1391 | unsigned int mapbase; |
1258 | unsigned char *rxbuf; | 1392 | unsigned char *rxbuf; |
1259 | int fifosize, base_baud; | 1393 | int fifosize, base_baud; |
1260 | static int num; | 1394 | int port_type; |
1395 | struct pch_uart_driver_data *board; | ||
1396 | |||
1397 | board = &drv_dat[id->driver_data]; | ||
1398 | port_type = board->port_type; | ||
1261 | 1399 | ||
1262 | priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL); | 1400 | priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL); |
1263 | if (priv == NULL) | 1401 | if (priv == NULL) |
@@ -1267,14 +1405,18 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1267 | if (!rxbuf) | 1405 | if (!rxbuf) |
1268 | goto init_port_free_txbuf; | 1406 | goto init_port_free_txbuf; |
1269 | 1407 | ||
1408 | base_baud = 1843200; /* 1.8432MHz */ | ||
1409 | |||
1410 | /* quirk for CM-iTC board */ | ||
1411 | if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC")) | ||
1412 | base_baud = 192000000; /* 192.0MHz */ | ||
1413 | |||
1270 | switch (port_type) { | 1414 | switch (port_type) { |
1271 | case PORT_UNKNOWN: | 1415 | case PORT_UNKNOWN: |
1272 | fifosize = 256; /* UART0 */ | 1416 | fifosize = 256; /* EG20T/ML7213: UART0 */ |
1273 | base_baud = 1843200; /* 1.8432MHz */ | ||
1274 | break; | 1417 | break; |
1275 | case PORT_8250: | 1418 | case PORT_8250: |
1276 | fifosize = 64; /* UART1~3 */ | 1419 | fifosize = 64; /* EG20T:UART1~3 ML7213: UART1~2*/ |
1277 | base_baud = 1843200; /* 1.8432MHz */ | ||
1278 | break; | 1420 | break; |
1279 | default: | 1421 | default: |
1280 | dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type); | 1422 | dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type); |
@@ -1302,11 +1444,14 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, | |||
1302 | priv->port.ops = &pch_uart_ops; | 1444 | priv->port.ops = &pch_uart_ops; |
1303 | priv->port.flags = UPF_BOOT_AUTOCONF; | 1445 | priv->port.flags = UPF_BOOT_AUTOCONF; |
1304 | priv->port.fifosize = fifosize; | 1446 | priv->port.fifosize = fifosize; |
1305 | priv->port.line = num++; | 1447 | priv->port.line = board->line_no; |
1306 | priv->trigger = PCH_UART_HAL_TRIGGER_M; | 1448 | priv->trigger = PCH_UART_HAL_TRIGGER_M; |
1307 | 1449 | ||
1450 | spin_lock_init(&priv->port.lock); | ||
1451 | |||
1308 | pci_set_drvdata(pdev, priv); | 1452 | pci_set_drvdata(pdev, priv); |
1309 | pch_uart_hal_request(pdev, fifosize, base_baud); | 1453 | pch_uart_hal_request(pdev, fifosize, base_baud); |
1454 | |||
1310 | ret = uart_add_one_port(&pch_uart_driver, &priv->port); | 1455 | ret = uart_add_one_port(&pch_uart_driver, &priv->port); |
1311 | if (ret < 0) | 1456 | if (ret < 0) |
1312 | goto init_port_hal_free; | 1457 | goto init_port_hal_free; |
@@ -1377,13 +1522,19 @@ static int pch_uart_pci_resume(struct pci_dev *pdev) | |||
1377 | 1522 | ||
1378 | static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { | 1523 | static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { |
1379 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), | 1524 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), |
1380 | .driver_data = PCH_UART_8LINE}, | 1525 | .driver_data = pch_et20t_uart0}, |
1381 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812), | 1526 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812), |
1382 | .driver_data = PCH_UART_2LINE}, | 1527 | .driver_data = pch_et20t_uart1}, |
1383 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813), | 1528 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813), |
1384 | .driver_data = PCH_UART_2LINE}, | 1529 | .driver_data = pch_et20t_uart2}, |
1385 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814), | 1530 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814), |
1386 | .driver_data = PCH_UART_2LINE}, | 1531 | .driver_data = pch_et20t_uart3}, |
1532 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8027), | ||
1533 | .driver_data = pch_ml7213_uart0}, | ||
1534 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8028), | ||
1535 | .driver_data = pch_ml7213_uart1}, | ||
1536 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029), | ||
1537 | .driver_data = pch_ml7213_uart2}, | ||
1387 | {0,}, | 1538 | {0,}, |
1388 | }; | 1539 | }; |
1389 | 1540 | ||
@@ -1397,7 +1548,7 @@ static int __devinit pch_uart_pci_probe(struct pci_dev *pdev, | |||
1397 | if (ret < 0) | 1548 | if (ret < 0) |
1398 | goto probe_error; | 1549 | goto probe_error; |
1399 | 1550 | ||
1400 | priv = pch_uart_init_port(pdev, id->driver_data); | 1551 | priv = pch_uart_init_port(pdev, id); |
1401 | if (!priv) { | 1552 | if (!priv) { |
1402 | ret = -EBUSY; | 1553 | ret = -EBUSY; |
1403 | goto probe_disable_device; | 1554 | goto probe_disable_device; |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 460a72d91bb7..733fe8e73f0f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -905,7 +905,7 @@ static int uart_get_lsr_info(struct tty_struct *tty, | |||
905 | return put_user(result, value); | 905 | return put_user(result, value); |
906 | } | 906 | } |
907 | 907 | ||
908 | static int uart_tiocmget(struct tty_struct *tty, struct file *file) | 908 | static int uart_tiocmget(struct tty_struct *tty) |
909 | { | 909 | { |
910 | struct uart_state *state = tty->driver_data; | 910 | struct uart_state *state = tty->driver_data; |
911 | struct tty_port *port = &state->port; | 911 | struct tty_port *port = &state->port; |
@@ -913,10 +913,8 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) | |||
913 | int result = -EIO; | 913 | int result = -EIO; |
914 | 914 | ||
915 | mutex_lock(&port->mutex); | 915 | mutex_lock(&port->mutex); |
916 | if ((!file || !tty_hung_up_p(file)) && | 916 | if (!(tty->flags & (1 << TTY_IO_ERROR))) { |
917 | !(tty->flags & (1 << TTY_IO_ERROR))) { | ||
918 | result = uport->mctrl; | 917 | result = uport->mctrl; |
919 | |||
920 | spin_lock_irq(&uport->lock); | 918 | spin_lock_irq(&uport->lock); |
921 | result |= uport->ops->get_mctrl(uport); | 919 | result |= uport->ops->get_mctrl(uport); |
922 | spin_unlock_irq(&uport->lock); | 920 | spin_unlock_irq(&uport->lock); |
@@ -927,8 +925,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file) | |||
927 | } | 925 | } |
928 | 926 | ||
929 | static int | 927 | static int |
930 | uart_tiocmset(struct tty_struct *tty, struct file *file, | 928 | uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) |
931 | unsigned int set, unsigned int clear) | ||
932 | { | 929 | { |
933 | struct uart_state *state = tty->driver_data; | 930 | struct uart_state *state = tty->driver_data; |
934 | struct uart_port *uport = state->uart_port; | 931 | struct uart_port *uport = state->uart_port; |
@@ -936,8 +933,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
936 | int ret = -EIO; | 933 | int ret = -EIO; |
937 | 934 | ||
938 | mutex_lock(&port->mutex); | 935 | mutex_lock(&port->mutex); |
939 | if ((!file || !tty_hung_up_p(file)) && | 936 | if (!(tty->flags & (1 << TTY_IO_ERROR))) { |
940 | !(tty->flags & (1 << TTY_IO_ERROR))) { | ||
941 | uart_update_mctrl(uport, set, clear); | 937 | uart_update_mctrl(uport, set, clear); |
942 | ret = 0; | 938 | ret = 0; |
943 | } | 939 | } |
@@ -1103,7 +1099,7 @@ static int uart_get_icount(struct tty_struct *tty, | |||
1103 | * Called via sys_ioctl. We can use spin_lock_irq() here. | 1099 | * Called via sys_ioctl. We can use spin_lock_irq() here. |
1104 | */ | 1100 | */ |
1105 | static int | 1101 | static int |
1106 | uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | 1102 | uart_ioctl(struct tty_struct *tty, unsigned int cmd, |
1107 | unsigned long arg) | 1103 | unsigned long arg) |
1108 | { | 1104 | { |
1109 | struct uart_state *state = tty->driver_data; | 1105 | struct uart_state *state = tty->driver_data; |
@@ -1156,7 +1152,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1156 | 1152 | ||
1157 | mutex_lock(&port->mutex); | 1153 | mutex_lock(&port->mutex); |
1158 | 1154 | ||
1159 | if (tty_hung_up_p(filp)) { | 1155 | if (tty->flags & (1 << TTY_IO_ERROR)) { |
1160 | ret = -EIO; | 1156 | ret = -EIO; |
1161 | goto out_up; | 1157 | goto out_up; |
1162 | } | 1158 | } |
@@ -2064,7 +2060,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2064 | /* | 2060 | /* |
2065 | * Re-enable the console device after suspending. | 2061 | * Re-enable the console device after suspending. |
2066 | */ | 2062 | */ |
2067 | if (console_suspend_enabled && uart_console(uport)) { | 2063 | if (uart_console(uport)) { |
2068 | /* | 2064 | /* |
2069 | * First try to use the console cflag setting. | 2065 | * First try to use the console cflag setting. |
2070 | */ | 2066 | */ |
@@ -2077,9 +2073,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2077 | if (port->tty && port->tty->termios && termios.c_cflag == 0) | 2073 | if (port->tty && port->tty->termios && termios.c_cflag == 0) |
2078 | termios = *(port->tty->termios); | 2074 | termios = *(port->tty->termios); |
2079 | 2075 | ||
2080 | uart_change_pm(state, 0); | ||
2081 | uport->ops->set_termios(uport, &termios, NULL); | 2076 | uport->ops->set_termios(uport, &termios, NULL); |
2082 | console_start(uport->cons); | 2077 | if (console_suspend_enabled) |
2078 | console_start(uport->cons); | ||
2083 | } | 2079 | } |
2084 | 2080 | ||
2085 | if (port->flags & ASYNC_SUSPENDED) { | 2081 | if (port->flags & ASYNC_SUSPENDED) { |
diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/serial_cs.c index 93760b2ea172..1ef4df9bf7e4 100644 --- a/drivers/tty/serial/serial_cs.c +++ b/drivers/tty/serial/serial_cs.c | |||
@@ -712,6 +712,7 @@ static struct pcmcia_device_id serial_ids[] = { | |||
712 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), | 712 | PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), |
713 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01), | 713 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0e01), |
714 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05), | 714 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05), |
715 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0b05), | ||
715 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101), | 716 | PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101), |
716 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), | 717 | PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), |
717 | PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562), | 718 | PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562), |
diff --git a/drivers/tty/serial/serial_lh7a40x.c b/drivers/tty/serial/serial_lh7a40x.c deleted file mode 100644 index ea744707c4d6..000000000000 --- a/drivers/tty/serial/serial_lh7a40x.c +++ /dev/null | |||
@@ -1,682 +0,0 @@ | |||
1 | /* drivers/serial/serial_lh7a40x.c | ||
2 | * | ||
3 | * Copyright (C) 2004 Coastal Environmental Systems | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | /* Driver for Sharp LH7A40X embedded serial ports | ||
12 | * | ||
13 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | ||
14 | * Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd. | ||
15 | * | ||
16 | * --- | ||
17 | * | ||
18 | * This driver supports the embedded UARTs of the Sharp LH7A40X series | ||
19 | * CPUs. While similar to the 16550 and other UART chips, there is | ||
20 | * nothing close to register compatibility. Moreover, some of the | ||
21 | * modem control lines are not available, either in the chip or they | ||
22 | * are lacking in the board-level implementation. | ||
23 | * | ||
24 | * - Use of SIRDIS | ||
25 | * For simplicity, we disable the IR functions of any UART whenever | ||
26 | * we enable it. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | |||
31 | #if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
32 | #define SUPPORT_SYSRQ | ||
33 | #endif | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <linux/ioport.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/console.h> | ||
39 | #include <linux/sysrq.h> | ||
40 | #include <linux/tty.h> | ||
41 | #include <linux/tty_flip.h> | ||
42 | #include <linux/serial_core.h> | ||
43 | #include <linux/serial.h> | ||
44 | #include <linux/io.h> | ||
45 | |||
46 | #include <asm/irq.h> | ||
47 | #include <mach/hardware.h> | ||
48 | |||
49 | #define DEV_MAJOR 204 | ||
50 | #define DEV_MINOR 16 | ||
51 | #define DEV_NR 3 | ||
52 | |||
53 | #define ISR_LOOP_LIMIT 256 | ||
54 | |||
55 | #define UR(p,o) _UR ((p)->membase, o) | ||
56 | #define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o)))) | ||
57 | #define BIT_CLR(p,o,m) UR(p,o) = UR(p,o) & (~(unsigned int)m) | ||
58 | #define BIT_SET(p,o,m) UR(p,o) = UR(p,o) | ( (unsigned int)m) | ||
59 | |||
60 | #define UART_REG_SIZE 32 | ||
61 | |||
62 | #define UART_R_DATA (0x00) | ||
63 | #define UART_R_FCON (0x04) | ||
64 | #define UART_R_BRCON (0x08) | ||
65 | #define UART_R_CON (0x0c) | ||
66 | #define UART_R_STATUS (0x10) | ||
67 | #define UART_R_RAWISR (0x14) | ||
68 | #define UART_R_INTEN (0x18) | ||
69 | #define UART_R_ISR (0x1c) | ||
70 | |||
71 | #define UARTEN (0x01) /* UART enable */ | ||
72 | #define SIRDIS (0x02) /* Serial IR disable (UART1 only) */ | ||
73 | |||
74 | #define RxEmpty (0x10) | ||
75 | #define TxEmpty (0x80) | ||
76 | #define TxFull (0x20) | ||
77 | #define nRxRdy RxEmpty | ||
78 | #define nTxRdy TxFull | ||
79 | #define TxBusy (0x08) | ||
80 | |||
81 | #define RxBreak (0x0800) | ||
82 | #define RxOverrunError (0x0400) | ||
83 | #define RxParityError (0x0200) | ||
84 | #define RxFramingError (0x0100) | ||
85 | #define RxError (RxBreak | RxOverrunError | RxParityError | RxFramingError) | ||
86 | |||
87 | #define DCD (0x04) | ||
88 | #define DSR (0x02) | ||
89 | #define CTS (0x01) | ||
90 | |||
91 | #define RxInt (0x01) | ||
92 | #define TxInt (0x02) | ||
93 | #define ModemInt (0x04) | ||
94 | #define RxTimeoutInt (0x08) | ||
95 | |||
96 | #define MSEOI (0x10) | ||
97 | |||
98 | #define WLEN_8 (0x60) | ||
99 | #define WLEN_7 (0x40) | ||
100 | #define WLEN_6 (0x20) | ||
101 | #define WLEN_5 (0x00) | ||
102 | #define WLEN (0x60) /* Mask for all word-length bits */ | ||
103 | #define STP2 (0x08) | ||
104 | #define PEN (0x02) /* Parity Enable */ | ||
105 | #define EPS (0x04) /* Even Parity Set */ | ||
106 | #define FEN (0x10) /* FIFO Enable */ | ||
107 | #define BRK (0x01) /* Send Break */ | ||
108 | |||
109 | |||
110 | struct uart_port_lh7a40x { | ||
111 | struct uart_port port; | ||
112 | unsigned int statusPrev; /* Most recently read modem status */ | ||
113 | }; | ||
114 | |||
115 | static void lh7a40xuart_stop_tx (struct uart_port* port) | ||
116 | { | ||
117 | BIT_CLR (port, UART_R_INTEN, TxInt); | ||
118 | } | ||
119 | |||
120 | static void lh7a40xuart_start_tx (struct uart_port* port) | ||
121 | { | ||
122 | BIT_SET (port, UART_R_INTEN, TxInt); | ||
123 | |||
124 | /* *** FIXME: do I need to check for startup of the | ||
125 | transmitter? The old driver did, but AMBA | ||
126 | doesn't . */ | ||
127 | } | ||
128 | |||
129 | static void lh7a40xuart_stop_rx (struct uart_port* port) | ||
130 | { | ||
131 | BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); | ||
132 | } | ||
133 | |||
134 | static void lh7a40xuart_enable_ms (struct uart_port* port) | ||
135 | { | ||
136 | BIT_SET (port, UART_R_INTEN, ModemInt); | ||
137 | } | ||
138 | |||
139 | static void lh7a40xuart_rx_chars (struct uart_port* port) | ||
140 | { | ||
141 | struct tty_struct* tty = port->state->port.tty; | ||
142 | int cbRxMax = 256; /* (Gross) limit on receive */ | ||
143 | unsigned int data; /* Received data and status */ | ||
144 | unsigned int flag; | ||
145 | |||
146 | while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) { | ||
147 | data = UR (port, UART_R_DATA); | ||
148 | flag = TTY_NORMAL; | ||
149 | ++port->icount.rx; | ||
150 | |||
151 | if (unlikely(data & RxError)) { | ||
152 | if (data & RxBreak) { | ||
153 | data &= ~(RxFramingError | RxParityError); | ||
154 | ++port->icount.brk; | ||
155 | if (uart_handle_break (port)) | ||
156 | continue; | ||
157 | } | ||
158 | else if (data & RxParityError) | ||
159 | ++port->icount.parity; | ||
160 | else if (data & RxFramingError) | ||
161 | ++port->icount.frame; | ||
162 | if (data & RxOverrunError) | ||
163 | ++port->icount.overrun; | ||
164 | |||
165 | /* Mask by termios, leave Rx'd byte */ | ||
166 | data &= port->read_status_mask | 0xff; | ||
167 | |||
168 | if (data & RxBreak) | ||
169 | flag = TTY_BREAK; | ||
170 | else if (data & RxParityError) | ||
171 | flag = TTY_PARITY; | ||
172 | else if (data & RxFramingError) | ||
173 | flag = TTY_FRAME; | ||
174 | } | ||
175 | |||
176 | if (uart_handle_sysrq_char (port, (unsigned char) data)) | ||
177 | continue; | ||
178 | |||
179 | uart_insert_char(port, data, RxOverrunError, data, flag); | ||
180 | } | ||
181 | tty_flip_buffer_push (tty); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | static void lh7a40xuart_tx_chars (struct uart_port* port) | ||
186 | { | ||
187 | struct circ_buf* xmit = &port->state->xmit; | ||
188 | int cbTxMax = port->fifosize; | ||
189 | |||
190 | if (port->x_char) { | ||
191 | UR (port, UART_R_DATA) = port->x_char; | ||
192 | ++port->icount.tx; | ||
193 | port->x_char = 0; | ||
194 | return; | ||
195 | } | ||
196 | if (uart_circ_empty (xmit) || uart_tx_stopped (port)) { | ||
197 | lh7a40xuart_stop_tx (port); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | /* Unlike the AMBA UART, the lh7a40x UART does not guarantee | ||
202 | that at least half of the FIFO is empty. Instead, we check | ||
203 | status for every character. Using the AMBA method causes | ||
204 | the transmitter to drop characters. */ | ||
205 | |||
206 | do { | ||
207 | UR (port, UART_R_DATA) = xmit->buf[xmit->tail]; | ||
208 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
209 | ++port->icount.tx; | ||
210 | if (uart_circ_empty(xmit)) | ||
211 | break; | ||
212 | } while (!(UR (port, UART_R_STATUS) & nTxRdy) | ||
213 | && cbTxMax--); | ||
214 | |||
215 | if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) | ||
216 | uart_write_wakeup (port); | ||
217 | |||
218 | if (uart_circ_empty (xmit)) | ||
219 | lh7a40xuart_stop_tx (port); | ||
220 | } | ||
221 | |||
222 | static void lh7a40xuart_modem_status (struct uart_port* port) | ||
223 | { | ||
224 | unsigned int status = UR (port, UART_R_STATUS); | ||
225 | unsigned int delta | ||
226 | = status ^ ((struct uart_port_lh7a40x*) port)->statusPrev; | ||
227 | |||
228 | BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */ | ||
229 | |||
230 | if (!delta) /* Only happens if we missed 2 transitions */ | ||
231 | return; | ||
232 | |||
233 | ((struct uart_port_lh7a40x*) port)->statusPrev = status; | ||
234 | |||
235 | if (delta & DCD) | ||
236 | uart_handle_dcd_change (port, status & DCD); | ||
237 | |||
238 | if (delta & DSR) | ||
239 | ++port->icount.dsr; | ||
240 | |||
241 | if (delta & CTS) | ||
242 | uart_handle_cts_change (port, status & CTS); | ||
243 | |||
244 | wake_up_interruptible (&port->state->port.delta_msr_wait); | ||
245 | } | ||
246 | |||
247 | static irqreturn_t lh7a40xuart_int (int irq, void* dev_id) | ||
248 | { | ||
249 | struct uart_port* port = dev_id; | ||
250 | unsigned int cLoopLimit = ISR_LOOP_LIMIT; | ||
251 | unsigned int isr = UR (port, UART_R_ISR); | ||
252 | |||
253 | |||
254 | do { | ||
255 | if (isr & (RxInt | RxTimeoutInt)) | ||
256 | lh7a40xuart_rx_chars(port); | ||
257 | if (isr & ModemInt) | ||
258 | lh7a40xuart_modem_status (port); | ||
259 | if (isr & TxInt) | ||
260 | lh7a40xuart_tx_chars (port); | ||
261 | |||
262 | if (--cLoopLimit == 0) | ||
263 | break; | ||
264 | |||
265 | isr = UR (port, UART_R_ISR); | ||
266 | } while (isr & (RxInt | TxInt | RxTimeoutInt)); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static unsigned int lh7a40xuart_tx_empty (struct uart_port* port) | ||
272 | { | ||
273 | return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0; | ||
274 | } | ||
275 | |||
276 | static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port) | ||
277 | { | ||
278 | unsigned int result = 0; | ||
279 | unsigned int status = UR (port, UART_R_STATUS); | ||
280 | |||
281 | if (status & DCD) | ||
282 | result |= TIOCM_CAR; | ||
283 | if (status & DSR) | ||
284 | result |= TIOCM_DSR; | ||
285 | if (status & CTS) | ||
286 | result |= TIOCM_CTS; | ||
287 | |||
288 | return result; | ||
289 | } | ||
290 | |||
291 | static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl) | ||
292 | { | ||
293 | /* None of the ports supports DTR. UART1 supports RTS through GPIO. */ | ||
294 | /* Note, kernel appears to be setting DTR and RTS on console. */ | ||
295 | |||
296 | /* *** FIXME: this deserves more work. There's some work in | ||
297 | tracing all of the IO pins. */ | ||
298 | #if 0 | ||
299 | if( port->mapbase == UART1_PHYS) { | ||
300 | gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS); | ||
301 | |||
302 | if (mctrl & TIOCM_RTS) | ||
303 | gpio->pbdr &= ~GPIOB_UART1_RTS; | ||
304 | else | ||
305 | gpio->pbdr |= GPIOB_UART1_RTS; | ||
306 | } | ||
307 | #endif | ||
308 | } | ||
309 | |||
310 | static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state) | ||
311 | { | ||
312 | unsigned long flags; | ||
313 | |||
314 | spin_lock_irqsave(&port->lock, flags); | ||
315 | if (break_state == -1) | ||
316 | BIT_SET (port, UART_R_FCON, BRK); /* Assert break */ | ||
317 | else | ||
318 | BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */ | ||
319 | spin_unlock_irqrestore(&port->lock, flags); | ||
320 | } | ||
321 | |||
322 | static int lh7a40xuart_startup (struct uart_port* port) | ||
323 | { | ||
324 | int retval; | ||
325 | |||
326 | retval = request_irq (port->irq, lh7a40xuart_int, 0, | ||
327 | "serial_lh7a40x", port); | ||
328 | if (retval) | ||
329 | return retval; | ||
330 | |||
331 | /* Initial modem control-line settings */ | ||
332 | ((struct uart_port_lh7a40x*) port)->statusPrev | ||
333 | = UR (port, UART_R_STATUS); | ||
334 | |||
335 | /* There is presently no configuration option to enable IR. | ||
336 | Thus, we always disable it. */ | ||
337 | |||
338 | BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); | ||
339 | BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static void lh7a40xuart_shutdown (struct uart_port* port) | ||
345 | { | ||
346 | free_irq (port->irq, port); | ||
347 | BIT_CLR (port, UART_R_FCON, BRK | FEN); | ||
348 | BIT_CLR (port, UART_R_CON, UARTEN); | ||
349 | } | ||
350 | |||
351 | static void lh7a40xuart_set_termios (struct uart_port* port, | ||
352 | struct ktermios* termios, | ||
353 | struct ktermios* old) | ||
354 | { | ||
355 | unsigned int con; | ||
356 | unsigned int inten; | ||
357 | unsigned int fcon; | ||
358 | unsigned long flags; | ||
359 | unsigned int baud; | ||
360 | unsigned int quot; | ||
361 | |||
362 | baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16); | ||
363 | quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */ | ||
364 | |||
365 | switch (termios->c_cflag & CSIZE) { | ||
366 | case CS5: | ||
367 | fcon = WLEN_5; | ||
368 | break; | ||
369 | case CS6: | ||
370 | fcon = WLEN_6; | ||
371 | break; | ||
372 | case CS7: | ||
373 | fcon = WLEN_7; | ||
374 | break; | ||
375 | case CS8: | ||
376 | default: | ||
377 | fcon = WLEN_8; | ||
378 | break; | ||
379 | } | ||
380 | if (termios->c_cflag & CSTOPB) | ||
381 | fcon |= STP2; | ||
382 | if (termios->c_cflag & PARENB) { | ||
383 | fcon |= PEN; | ||
384 | if (!(termios->c_cflag & PARODD)) | ||
385 | fcon |= EPS; | ||
386 | } | ||
387 | if (port->fifosize > 1) | ||
388 | fcon |= FEN; | ||
389 | |||
390 | spin_lock_irqsave (&port->lock, flags); | ||
391 | |||
392 | uart_update_timeout (port, termios->c_cflag, baud); | ||
393 | |||
394 | port->read_status_mask = RxOverrunError; | ||
395 | if (termios->c_iflag & INPCK) | ||
396 | port->read_status_mask |= RxFramingError | RxParityError; | ||
397 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
398 | port->read_status_mask |= RxBreak; | ||
399 | |||
400 | /* Figure mask for status we ignore */ | ||
401 | port->ignore_status_mask = 0; | ||
402 | if (termios->c_iflag & IGNPAR) | ||
403 | port->ignore_status_mask |= RxFramingError | RxParityError; | ||
404 | if (termios->c_iflag & IGNBRK) { | ||
405 | port->ignore_status_mask |= RxBreak; | ||
406 | /* Ignore overrun when ignorning parity */ | ||
407 | /* *** FIXME: is this in the right place? */ | ||
408 | if (termios->c_iflag & IGNPAR) | ||
409 | port->ignore_status_mask |= RxOverrunError; | ||
410 | } | ||
411 | |||
412 | /* Ignore all receive errors when receive disabled */ | ||
413 | if ((termios->c_cflag & CREAD) == 0) | ||
414 | port->ignore_status_mask |= RxError; | ||
415 | |||
416 | con = UR (port, UART_R_CON); | ||
417 | inten = (UR (port, UART_R_INTEN) & ~ModemInt); | ||
418 | |||
419 | if (UART_ENABLE_MS (port, termios->c_cflag)) | ||
420 | inten |= ModemInt; | ||
421 | |||
422 | BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */ | ||
423 | UR (port, UART_R_INTEN) = 0; /* Disable interrupts */ | ||
424 | UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */ | ||
425 | UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */ | ||
426 | UR (port, UART_R_INTEN) = inten; /* Enable interrupts */ | ||
427 | UR (port, UART_R_CON) = con; /* Restore UART mode */ | ||
428 | |||
429 | spin_unlock_irqrestore(&port->lock, flags); | ||
430 | } | ||
431 | |||
432 | static const char* lh7a40xuart_type (struct uart_port* port) | ||
433 | { | ||
434 | return port->type == PORT_LH7A40X ? "LH7A40X" : NULL; | ||
435 | } | ||
436 | |||
437 | static void lh7a40xuart_release_port (struct uart_port* port) | ||
438 | { | ||
439 | release_mem_region (port->mapbase, UART_REG_SIZE); | ||
440 | } | ||
441 | |||
442 | static int lh7a40xuart_request_port (struct uart_port* port) | ||
443 | { | ||
444 | return request_mem_region (port->mapbase, UART_REG_SIZE, | ||
445 | "serial_lh7a40x") != NULL | ||
446 | ? 0 : -EBUSY; | ||
447 | } | ||
448 | |||
449 | static void lh7a40xuart_config_port (struct uart_port* port, int flags) | ||
450 | { | ||
451 | if (flags & UART_CONFIG_TYPE) { | ||
452 | port->type = PORT_LH7A40X; | ||
453 | lh7a40xuart_request_port (port); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static int lh7a40xuart_verify_port (struct uart_port* port, | ||
458 | struct serial_struct* ser) | ||
459 | { | ||
460 | int ret = 0; | ||
461 | |||
462 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X) | ||
463 | ret = -EINVAL; | ||
464 | if (ser->irq < 0 || ser->irq >= nr_irqs) | ||
465 | ret = -EINVAL; | ||
466 | if (ser->baud_base < 9600) /* *** FIXME: is this true? */ | ||
467 | ret = -EINVAL; | ||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | static struct uart_ops lh7a40x_uart_ops = { | ||
472 | .tx_empty = lh7a40xuart_tx_empty, | ||
473 | .set_mctrl = lh7a40xuart_set_mctrl, | ||
474 | .get_mctrl = lh7a40xuart_get_mctrl, | ||
475 | .stop_tx = lh7a40xuart_stop_tx, | ||
476 | .start_tx = lh7a40xuart_start_tx, | ||
477 | .stop_rx = lh7a40xuart_stop_rx, | ||
478 | .enable_ms = lh7a40xuart_enable_ms, | ||
479 | .break_ctl = lh7a40xuart_break_ctl, | ||
480 | .startup = lh7a40xuart_startup, | ||
481 | .shutdown = lh7a40xuart_shutdown, | ||
482 | .set_termios = lh7a40xuart_set_termios, | ||
483 | .type = lh7a40xuart_type, | ||
484 | .release_port = lh7a40xuart_release_port, | ||
485 | .request_port = lh7a40xuart_request_port, | ||
486 | .config_port = lh7a40xuart_config_port, | ||
487 | .verify_port = lh7a40xuart_verify_port, | ||
488 | }; | ||
489 | |||
490 | static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { | ||
491 | { | ||
492 | .port = { | ||
493 | .membase = (void*) io_p2v (UART1_PHYS), | ||
494 | .mapbase = UART1_PHYS, | ||
495 | .iotype = UPIO_MEM, | ||
496 | .irq = IRQ_UART1INTR, | ||
497 | .uartclk = 14745600/2, | ||
498 | .fifosize = 16, | ||
499 | .ops = &lh7a40x_uart_ops, | ||
500 | .flags = UPF_BOOT_AUTOCONF, | ||
501 | .line = 0, | ||
502 | }, | ||
503 | }, | ||
504 | { | ||
505 | .port = { | ||
506 | .membase = (void*) io_p2v (UART2_PHYS), | ||
507 | .mapbase = UART2_PHYS, | ||
508 | .iotype = UPIO_MEM, | ||
509 | .irq = IRQ_UART2INTR, | ||
510 | .uartclk = 14745600/2, | ||
511 | .fifosize = 16, | ||
512 | .ops = &lh7a40x_uart_ops, | ||
513 | .flags = UPF_BOOT_AUTOCONF, | ||
514 | .line = 1, | ||
515 | }, | ||
516 | }, | ||
517 | { | ||
518 | .port = { | ||
519 | .membase = (void*) io_p2v (UART3_PHYS), | ||
520 | .mapbase = UART3_PHYS, | ||
521 | .iotype = UPIO_MEM, | ||
522 | .irq = IRQ_UART3INTR, | ||
523 | .uartclk = 14745600/2, | ||
524 | .fifosize = 16, | ||
525 | .ops = &lh7a40x_uart_ops, | ||
526 | .flags = UPF_BOOT_AUTOCONF, | ||
527 | .line = 2, | ||
528 | }, | ||
529 | }, | ||
530 | }; | ||
531 | |||
532 | #ifndef CONFIG_SERIAL_LH7A40X_CONSOLE | ||
533 | # define LH7A40X_CONSOLE NULL | ||
534 | #else | ||
535 | # define LH7A40X_CONSOLE &lh7a40x_console | ||
536 | |||
537 | static void lh7a40xuart_console_putchar(struct uart_port *port, int ch) | ||
538 | { | ||
539 | while (UR(port, UART_R_STATUS) & nTxRdy) | ||
540 | ; | ||
541 | UR(port, UART_R_DATA) = ch; | ||
542 | } | ||
543 | |||
544 | static void lh7a40xuart_console_write (struct console* co, | ||
545 | const char* s, | ||
546 | unsigned int count) | ||
547 | { | ||
548 | struct uart_port* port = &lh7a40x_ports[co->index].port; | ||
549 | unsigned int con = UR (port, UART_R_CON); | ||
550 | unsigned int inten = UR (port, UART_R_INTEN); | ||
551 | |||
552 | |||
553 | UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ | ||
554 | BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ | ||
555 | |||
556 | uart_console_write(port, s, count, lh7a40xuart_console_putchar); | ||
557 | |||
558 | /* Wait until all characters are sent */ | ||
559 | while (UR (port, UART_R_STATUS) & TxBusy) | ||
560 | ; | ||
561 | |||
562 | /* Restore control and interrupt mask */ | ||
563 | UR (port, UART_R_CON) = con; | ||
564 | UR (port, UART_R_INTEN) = inten; | ||
565 | } | ||
566 | |||
567 | static void __init lh7a40xuart_console_get_options (struct uart_port* port, | ||
568 | int* baud, | ||
569 | int* parity, | ||
570 | int* bits) | ||
571 | { | ||
572 | if (UR (port, UART_R_CON) & UARTEN) { | ||
573 | unsigned int fcon = UR (port, UART_R_FCON); | ||
574 | unsigned int quot = UR (port, UART_R_BRCON) + 1; | ||
575 | |||
576 | switch (fcon & (PEN | EPS)) { | ||
577 | default: *parity = 'n'; break; | ||
578 | case PEN: *parity = 'o'; break; | ||
579 | case PEN | EPS: *parity = 'e'; break; | ||
580 | } | ||
581 | |||
582 | switch (fcon & WLEN) { | ||
583 | default: | ||
584 | case WLEN_8: *bits = 8; break; | ||
585 | case WLEN_7: *bits = 7; break; | ||
586 | case WLEN_6: *bits = 6; break; | ||
587 | case WLEN_5: *bits = 5; break; | ||
588 | } | ||
589 | |||
590 | *baud = port->uartclk/(16*quot); | ||
591 | } | ||
592 | } | ||
593 | |||
594 | static int __init lh7a40xuart_console_setup (struct console* co, char* options) | ||
595 | { | ||
596 | struct uart_port* port; | ||
597 | int baud = 38400; | ||
598 | int bits = 8; | ||
599 | int parity = 'n'; | ||
600 | int flow = 'n'; | ||
601 | |||
602 | if (co->index >= DEV_NR) /* Bounds check on device number */ | ||
603 | co->index = 0; | ||
604 | port = &lh7a40x_ports[co->index].port; | ||
605 | |||
606 | if (options) | ||
607 | uart_parse_options (options, &baud, &parity, &bits, &flow); | ||
608 | else | ||
609 | lh7a40xuart_console_get_options (port, &baud, &parity, &bits); | ||
610 | |||
611 | return uart_set_options (port, co, baud, parity, bits, flow); | ||
612 | } | ||
613 | |||
614 | static struct uart_driver lh7a40x_reg; | ||
615 | static struct console lh7a40x_console = { | ||
616 | .name = "ttyAM", | ||
617 | .write = lh7a40xuart_console_write, | ||
618 | .device = uart_console_device, | ||
619 | .setup = lh7a40xuart_console_setup, | ||
620 | .flags = CON_PRINTBUFFER, | ||
621 | .index = -1, | ||
622 | .data = &lh7a40x_reg, | ||
623 | }; | ||
624 | |||
625 | static int __init lh7a40xuart_console_init(void) | ||
626 | { | ||
627 | register_console (&lh7a40x_console); | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | console_initcall (lh7a40xuart_console_init); | ||
632 | |||
633 | #endif | ||
634 | |||
635 | static struct uart_driver lh7a40x_reg = { | ||
636 | .owner = THIS_MODULE, | ||
637 | .driver_name = "ttyAM", | ||
638 | .dev_name = "ttyAM", | ||
639 | .major = DEV_MAJOR, | ||
640 | .minor = DEV_MINOR, | ||
641 | .nr = DEV_NR, | ||
642 | .cons = LH7A40X_CONSOLE, | ||
643 | }; | ||
644 | |||
645 | static int __init lh7a40xuart_init(void) | ||
646 | { | ||
647 | int ret; | ||
648 | |||
649 | printk (KERN_INFO "serial: LH7A40X serial driver\n"); | ||
650 | |||
651 | ret = uart_register_driver (&lh7a40x_reg); | ||
652 | |||
653 | if (ret == 0) { | ||
654 | int i; | ||
655 | |||
656 | for (i = 0; i < DEV_NR; i++) { | ||
657 | /* UART3, when used, requires GPIO pin reallocation */ | ||
658 | if (lh7a40x_ports[i].port.mapbase == UART3_PHYS) | ||
659 | GPIO_PINMUX |= 1<<3; | ||
660 | uart_add_one_port (&lh7a40x_reg, | ||
661 | &lh7a40x_ports[i].port); | ||
662 | } | ||
663 | } | ||
664 | return ret; | ||
665 | } | ||
666 | |||
667 | static void __exit lh7a40xuart_exit(void) | ||
668 | { | ||
669 | int i; | ||
670 | |||
671 | for (i = 0; i < DEV_NR; i++) | ||
672 | uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port); | ||
673 | |||
674 | uart_unregister_driver (&lh7a40x_reg); | ||
675 | } | ||
676 | |||
677 | module_init (lh7a40xuart_init); | ||
678 | module_exit (lh7a40xuart_exit); | ||
679 | |||
680 | MODULE_AUTHOR ("Marc Singer"); | ||
681 | MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver"); | ||
682 | MODULE_LICENSE ("GPL"); | ||
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index c9014868297d..c0b7246d7339 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c | |||
@@ -519,7 +519,7 @@ static struct console sunhv_console = { | |||
519 | .data = &sunhv_reg, | 519 | .data = &sunhv_reg, |
520 | }; | 520 | }; |
521 | 521 | ||
522 | static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match) | 522 | static int __devinit hv_probe(struct platform_device *op) |
523 | { | 523 | { |
524 | struct uart_port *port; | 524 | struct uart_port *port; |
525 | unsigned long minor; | 525 | unsigned long minor; |
@@ -629,7 +629,7 @@ static const struct of_device_id hv_match[] = { | |||
629 | }; | 629 | }; |
630 | MODULE_DEVICE_TABLE(of, hv_match); | 630 | MODULE_DEVICE_TABLE(of, hv_match); |
631 | 631 | ||
632 | static struct of_platform_driver hv_driver = { | 632 | static struct platform_driver hv_driver = { |
633 | .driver = { | 633 | .driver = { |
634 | .name = "hv", | 634 | .name = "hv", |
635 | .owner = THIS_MODULE, | 635 | .owner = THIS_MODULE, |
@@ -644,12 +644,12 @@ static int __init sunhv_init(void) | |||
644 | if (tlb_type != hypervisor) | 644 | if (tlb_type != hypervisor) |
645 | return -ENODEV; | 645 | return -ENODEV; |
646 | 646 | ||
647 | return of_register_platform_driver(&hv_driver); | 647 | return platform_driver_register(&hv_driver); |
648 | } | 648 | } |
649 | 649 | ||
650 | static void __exit sunhv_exit(void) | 650 | static void __exit sunhv_exit(void) |
651 | { | 651 | { |
652 | of_unregister_platform_driver(&hv_driver); | 652 | platform_driver_unregister(&hv_driver); |
653 | } | 653 | } |
654 | 654 | ||
655 | module_init(sunhv_init); | 655 | module_init(sunhv_init); |
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 5b246b18f42f..b5fa2a57b9da 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c | |||
@@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match) | 1009 | static int __devinit sab_probe(struct platform_device *op) |
1010 | { | 1010 | { |
1011 | static int inst; | 1011 | static int inst; |
1012 | struct uart_sunsab_port *up; | 1012 | struct uart_sunsab_port *up; |
@@ -1092,7 +1092,7 @@ static const struct of_device_id sab_match[] = { | |||
1092 | }; | 1092 | }; |
1093 | MODULE_DEVICE_TABLE(of, sab_match); | 1093 | MODULE_DEVICE_TABLE(of, sab_match); |
1094 | 1094 | ||
1095 | static struct of_platform_driver sab_driver = { | 1095 | static struct platform_driver sab_driver = { |
1096 | .driver = { | 1096 | .driver = { |
1097 | .name = "sab", | 1097 | .name = "sab", |
1098 | .owner = THIS_MODULE, | 1098 | .owner = THIS_MODULE, |
@@ -1130,12 +1130,12 @@ static int __init sunsab_init(void) | |||
1130 | } | 1130 | } |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | return of_register_platform_driver(&sab_driver); | 1133 | return platform_driver_register(&sab_driver); |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | static void __exit sunsab_exit(void) | 1136 | static void __exit sunsab_exit(void) |
1137 | { | 1137 | { |
1138 | of_unregister_platform_driver(&sab_driver); | 1138 | platform_driver_unregister(&sab_driver); |
1139 | if (sunsab_reg.nr) { | 1139 | if (sunsab_reg.nr) { |
1140 | sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr); | 1140 | sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr); |
1141 | } | 1141 | } |
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 551ebfe3ccbb..92aa54550e84 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c | |||
@@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp) | |||
1406 | return SU_PORT_PORT; | 1406 | return SU_PORT_PORT; |
1407 | } | 1407 | } |
1408 | 1408 | ||
1409 | static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match) | 1409 | static int __devinit su_probe(struct platform_device *op) |
1410 | { | 1410 | { |
1411 | static int inst; | 1411 | static int inst; |
1412 | struct device_node *dp = op->dev.of_node; | 1412 | struct device_node *dp = op->dev.of_node; |
@@ -1543,7 +1543,7 @@ static const struct of_device_id su_match[] = { | |||
1543 | }; | 1543 | }; |
1544 | MODULE_DEVICE_TABLE(of, su_match); | 1544 | MODULE_DEVICE_TABLE(of, su_match); |
1545 | 1545 | ||
1546 | static struct of_platform_driver su_driver = { | 1546 | static struct platform_driver su_driver = { |
1547 | .driver = { | 1547 | .driver = { |
1548 | .name = "su", | 1548 | .name = "su", |
1549 | .owner = THIS_MODULE, | 1549 | .owner = THIS_MODULE, |
@@ -1586,7 +1586,7 @@ static int __init sunsu_init(void) | |||
1586 | return err; | 1586 | return err; |
1587 | } | 1587 | } |
1588 | 1588 | ||
1589 | err = of_register_platform_driver(&su_driver); | 1589 | err = platform_driver_register(&su_driver); |
1590 | if (err && num_uart) | 1590 | if (err && num_uart) |
1591 | sunserial_unregister_minors(&sunsu_reg, num_uart); | 1591 | sunserial_unregister_minors(&sunsu_reg, num_uart); |
1592 | 1592 | ||
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index c1967ac1c07f..99ff9abf57ce 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c | |||
@@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) | |||
1399 | 1399 | ||
1400 | static int zilog_irq = -1; | 1400 | static int zilog_irq = -1; |
1401 | 1401 | ||
1402 | static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match) | 1402 | static int __devinit zs_probe(struct platform_device *op) |
1403 | { | 1403 | { |
1404 | static int kbm_inst, uart_inst; | 1404 | static int kbm_inst, uart_inst; |
1405 | int inst; | 1405 | int inst; |
@@ -1540,7 +1540,7 @@ static const struct of_device_id zs_match[] = { | |||
1540 | }; | 1540 | }; |
1541 | MODULE_DEVICE_TABLE(of, zs_match); | 1541 | MODULE_DEVICE_TABLE(of, zs_match); |
1542 | 1542 | ||
1543 | static struct of_platform_driver zs_driver = { | 1543 | static struct platform_driver zs_driver = { |
1544 | .driver = { | 1544 | .driver = { |
1545 | .name = "zs", | 1545 | .name = "zs", |
1546 | .owner = THIS_MODULE, | 1546 | .owner = THIS_MODULE, |
@@ -1576,7 +1576,7 @@ static int __init sunzilog_init(void) | |||
1576 | goto out_free_tables; | 1576 | goto out_free_tables; |
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | err = of_register_platform_driver(&zs_driver); | 1579 | err = platform_driver_register(&zs_driver); |
1580 | if (err) | 1580 | if (err) |
1581 | goto out_unregister_uart; | 1581 | goto out_unregister_uart; |
1582 | 1582 | ||
@@ -1604,7 +1604,7 @@ out: | |||
1604 | return err; | 1604 | return err; |
1605 | 1605 | ||
1606 | out_unregister_driver: | 1606 | out_unregister_driver: |
1607 | of_unregister_platform_driver(&zs_driver); | 1607 | platform_driver_unregister(&zs_driver); |
1608 | 1608 | ||
1609 | out_unregister_uart: | 1609 | out_unregister_uart: |
1610 | if (num_sunzilog) { | 1610 | if (num_sunzilog) { |
@@ -1619,7 +1619,7 @@ out_free_tables: | |||
1619 | 1619 | ||
1620 | static void __exit sunzilog_exit(void) | 1620 | static void __exit sunzilog_exit(void) |
1621 | { | 1621 | { |
1622 | of_unregister_platform_driver(&zs_driver); | 1622 | platform_driver_unregister(&zs_driver); |
1623 | 1623 | ||
1624 | if (zilog_irq != -1) { | 1624 | if (zilog_irq != -1) { |
1625 | struct uart_sunzilog_port *up = sunzilog_irq_chain; | 1625 | struct uart_sunzilog_port *up = sunzilog_irq_chain; |
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index d2fce865b731..8af1ed83a4c0 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c | |||
@@ -19,22 +19,11 @@ | |||
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) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) | ||
23 | #include <linux/of.h> | 22 | #include <linux/of.h> |
24 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
25 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
26 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
27 | 26 | ||
28 | /* Match table for of_platform binding */ | ||
29 | static struct of_device_id ulite_of_match[] __devinitdata = { | ||
30 | { .compatible = "xlnx,opb-uartlite-1.00.b", }, | ||
31 | { .compatible = "xlnx,xps-uartlite-1.00.a", }, | ||
32 | {} | ||
33 | }; | ||
34 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
35 | |||
36 | #endif | ||
37 | |||
38 | #define ULITE_NAME "ttyUL" | 27 | #define ULITE_NAME "ttyUL" |
39 | #define ULITE_MAJOR 204 | 28 | #define ULITE_MAJOR 204 |
40 | #define ULITE_MINOR 187 | 29 | #define ULITE_MINOR 187 |
@@ -571,9 +560,29 @@ static int __devexit ulite_release(struct device *dev) | |||
571 | * Platform bus binding | 560 | * Platform bus binding |
572 | */ | 561 | */ |
573 | 562 | ||
563 | #if defined(CONFIG_OF) | ||
564 | /* Match table for of_platform binding */ | ||
565 | static struct of_device_id ulite_of_match[] __devinitdata = { | ||
566 | { .compatible = "xlnx,opb-uartlite-1.00.b", }, | ||
567 | { .compatible = "xlnx,xps-uartlite-1.00.a", }, | ||
568 | {} | ||
569 | }; | ||
570 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
571 | #else /* CONFIG_OF */ | ||
572 | #define ulite_of_match NULL | ||
573 | #endif /* CONFIG_OF */ | ||
574 | |||
574 | static int __devinit ulite_probe(struct platform_device *pdev) | 575 | static int __devinit ulite_probe(struct platform_device *pdev) |
575 | { | 576 | { |
576 | struct resource *res, *res2; | 577 | struct resource *res, *res2; |
578 | int id = pdev->id; | ||
579 | #ifdef CONFIG_OF | ||
580 | const __be32 *prop; | ||
581 | |||
582 | prop = of_get_property(pdev->dev.of_node, "port-number", NULL); | ||
583 | if (prop) | ||
584 | id = be32_to_cpup(prop); | ||
585 | #endif | ||
577 | 586 | ||
578 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 587 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
579 | if (!res) | 588 | if (!res) |
@@ -583,7 +592,7 @@ static int __devinit ulite_probe(struct platform_device *pdev) | |||
583 | if (!res2) | 592 | if (!res2) |
584 | return -ENODEV; | 593 | return -ENODEV; |
585 | 594 | ||
586 | return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start); | 595 | return ulite_assign(&pdev->dev, id, res->start, res2->start); |
587 | } | 596 | } |
588 | 597 | ||
589 | static int __devexit ulite_remove(struct platform_device *pdev) | 598 | static int __devexit ulite_remove(struct platform_device *pdev) |
@@ -595,72 +604,15 @@ static int __devexit ulite_remove(struct platform_device *pdev) | |||
595 | MODULE_ALIAS("platform:uartlite"); | 604 | MODULE_ALIAS("platform:uartlite"); |
596 | 605 | ||
597 | static struct platform_driver ulite_platform_driver = { | 606 | static struct platform_driver ulite_platform_driver = { |
598 | .probe = ulite_probe, | 607 | .probe = ulite_probe, |
599 | .remove = __devexit_p(ulite_remove), | 608 | .remove = __devexit_p(ulite_remove), |
600 | .driver = { | ||
601 | .owner = THIS_MODULE, | ||
602 | .name = "uartlite", | ||
603 | }, | ||
604 | }; | ||
605 | |||
606 | /* --------------------------------------------------------------------- | ||
607 | * OF bus bindings | ||
608 | */ | ||
609 | #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) | ||
610 | static int __devinit | ||
611 | ulite_of_probe(struct platform_device *op, const struct of_device_id *match) | ||
612 | { | ||
613 | struct resource res; | ||
614 | const unsigned int *id; | ||
615 | int irq, rc; | ||
616 | |||
617 | dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match); | ||
618 | |||
619 | rc = of_address_to_resource(op->dev.of_node, 0, &res); | ||
620 | if (rc) { | ||
621 | dev_err(&op->dev, "invalid address\n"); | ||
622 | return rc; | ||
623 | } | ||
624 | |||
625 | irq = irq_of_parse_and_map(op->dev.of_node, 0); | ||
626 | |||
627 | id = of_get_property(op->dev.of_node, "port-number", NULL); | ||
628 | |||
629 | return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); | ||
630 | } | ||
631 | |||
632 | static int __devexit ulite_of_remove(struct platform_device *op) | ||
633 | { | ||
634 | return ulite_release(&op->dev); | ||
635 | } | ||
636 | |||
637 | static struct of_platform_driver ulite_of_driver = { | ||
638 | .probe = ulite_of_probe, | ||
639 | .remove = __devexit_p(ulite_of_remove), | ||
640 | .driver = { | 609 | .driver = { |
641 | .name = "uartlite", | ||
642 | .owner = THIS_MODULE, | 610 | .owner = THIS_MODULE, |
611 | .name = "uartlite", | ||
643 | .of_match_table = ulite_of_match, | 612 | .of_match_table = ulite_of_match, |
644 | }, | 613 | }, |
645 | }; | 614 | }; |
646 | 615 | ||
647 | /* Registration helpers to keep the number of #ifdefs to a minimum */ | ||
648 | static inline int __init ulite_of_register(void) | ||
649 | { | ||
650 | pr_debug("uartlite: calling of_register_platform_driver()\n"); | ||
651 | return of_register_platform_driver(&ulite_of_driver); | ||
652 | } | ||
653 | |||
654 | static inline void __exit ulite_of_unregister(void) | ||
655 | { | ||
656 | of_unregister_platform_driver(&ulite_of_driver); | ||
657 | } | ||
658 | #else /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ | ||
659 | /* Appropriate config not enabled; do nothing helpers */ | ||
660 | static inline int __init ulite_of_register(void) { return 0; } | ||
661 | static inline void __exit ulite_of_unregister(void) { } | ||
662 | #endif /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */ | ||
663 | |||
664 | /* --------------------------------------------------------------------- | 616 | /* --------------------------------------------------------------------- |
665 | * Module setup/teardown | 617 | * Module setup/teardown |
666 | */ | 618 | */ |
@@ -674,10 +626,6 @@ int __init ulite_init(void) | |||
674 | if (ret) | 626 | if (ret) |
675 | goto err_uart; | 627 | goto err_uart; |
676 | 628 | ||
677 | ret = ulite_of_register(); | ||
678 | if (ret) | ||
679 | goto err_of; | ||
680 | |||
681 | pr_debug("uartlite: calling platform_driver_register()\n"); | 629 | pr_debug("uartlite: calling platform_driver_register()\n"); |
682 | ret = platform_driver_register(&ulite_platform_driver); | 630 | ret = platform_driver_register(&ulite_platform_driver); |
683 | if (ret) | 631 | if (ret) |
@@ -686,8 +634,6 @@ int __init ulite_init(void) | |||
686 | return 0; | 634 | return 0; |
687 | 635 | ||
688 | err_plat: | 636 | err_plat: |
689 | ulite_of_unregister(); | ||
690 | err_of: | ||
691 | uart_unregister_driver(&ulite_uart_driver); | 637 | uart_unregister_driver(&ulite_uart_driver); |
692 | err_uart: | 638 | err_uart: |
693 | printk(KERN_ERR "registering uartlite driver failed: err=%i", ret); | 639 | printk(KERN_ERR "registering uartlite driver failed: err=%i", ret); |
@@ -697,7 +643,6 @@ err_uart: | |||
697 | void __exit ulite_exit(void) | 643 | void __exit ulite_exit(void) |
698 | { | 644 | { |
699 | platform_driver_unregister(&ulite_platform_driver); | 645 | platform_driver_unregister(&ulite_platform_driver); |
700 | ulite_of_unregister(); | ||
701 | uart_unregister_driver(&ulite_uart_driver); | 646 | uart_unregister_driver(&ulite_uart_driver); |
702 | } | 647 | } |
703 | 648 | ||
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 3f4848e2174a..ff51dae1df0c 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c | |||
@@ -1194,8 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) | |||
1194 | release_firmware(fw); | 1194 | release_firmware(fw); |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | static int ucc_uart_probe(struct platform_device *ofdev, | 1197 | static int ucc_uart_probe(struct platform_device *ofdev) |
1198 | const struct of_device_id *match) | ||
1199 | { | 1198 | { |
1200 | struct device_node *np = ofdev->dev.of_node; | 1199 | struct device_node *np = ofdev->dev.of_node; |
1201 | const unsigned int *iprop; /* Integer OF properties */ | 1200 | const unsigned int *iprop; /* Integer OF properties */ |
@@ -1485,7 +1484,7 @@ static struct of_device_id ucc_uart_match[] = { | |||
1485 | }; | 1484 | }; |
1486 | MODULE_DEVICE_TABLE(of, ucc_uart_match); | 1485 | MODULE_DEVICE_TABLE(of, ucc_uart_match); |
1487 | 1486 | ||
1488 | static struct of_platform_driver ucc_uart_of_driver = { | 1487 | static struct platform_driver ucc_uart_of_driver = { |
1489 | .driver = { | 1488 | .driver = { |
1490 | .name = "ucc_uart", | 1489 | .name = "ucc_uart", |
1491 | .owner = THIS_MODULE, | 1490 | .owner = THIS_MODULE, |
@@ -1510,7 +1509,7 @@ static int __init ucc_uart_init(void) | |||
1510 | return ret; | 1509 | return ret; |
1511 | } | 1510 | } |
1512 | 1511 | ||
1513 | ret = of_register_platform_driver(&ucc_uart_of_driver); | 1512 | ret = platform_driver_register(&ucc_uart_of_driver); |
1514 | if (ret) | 1513 | if (ret) |
1515 | printk(KERN_ERR | 1514 | printk(KERN_ERR |
1516 | "ucc-uart: could not register platform driver\n"); | 1515 | "ucc-uart: could not register platform driver\n"); |
@@ -1523,7 +1522,7 @@ static void __exit ucc_uart_exit(void) | |||
1523 | printk(KERN_INFO | 1522 | printk(KERN_INFO |
1524 | "Freescale QUICC Engine UART device driver unloading\n"); | 1523 | "Freescale QUICC Engine UART device driver unloading\n"); |
1525 | 1524 | ||
1526 | of_unregister_platform_driver(&ucc_uart_of_driver); | 1525 | platform_driver_unregister(&ucc_uart_of_driver); |
1527 | uart_unregister_driver(&ucc_uart_driver); | 1526 | uart_unregister_driver(&ucc_uart_driver); |
1528 | } | 1527 | } |
1529 | 1528 | ||