diff options
Diffstat (limited to 'drivers/tty')
83 files changed, 2774 insertions, 453 deletions
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 3fd7199301b6..bd7cc0527999 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig | |||
@@ -319,3 +319,34 @@ config N_GSM | |||
319 | This line discipline provides support for the GSM MUX protocol and | 319 | This line discipline provides support for the GSM MUX protocol and |
320 | presents the mux as a set of 61 individual tty devices. | 320 | presents the mux as a set of 61 individual tty devices. |
321 | 321 | ||
322 | config TRACE_ROUTER | ||
323 | tristate "Trace data router for MIPI P1149.7 cJTAG standard" | ||
324 | depends on TRACE_SINK | ||
325 | default n | ||
326 | help | ||
327 | The trace router uses the Linux tty line discipline framework to | ||
328 | route trace data coming from a tty port (say UART for example) to | ||
329 | the trace sink line discipline driver and to another tty port (say | ||
330 | USB). This is part of a solution for the MIPI P1149.7, compact JTAG, | ||
331 | standard, which is for debugging mobile devices. The PTI driver in | ||
332 | drivers/misc/pti.c defines the majority of this MIPI solution. | ||
333 | |||
334 | You should select this driver if the target kernel is meant for | ||
335 | a mobile device containing a modem. Then you will need to select | ||
336 | "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline | ||
337 | driver. | ||
338 | |||
339 | config TRACE_SINK | ||
340 | tristate "Trace data sink for MIPI P1149.7 cJTAG standard" | ||
341 | default n | ||
342 | help | ||
343 | The trace sink uses the Linux line discipline framework to receive | ||
344 | trace data coming from the trace router line discipline driver | ||
345 | to a user-defined tty port target, like USB. | ||
346 | This is to provide a way to extract modem trace data on | ||
347 | devices that do not have a PTI HW module, or just need modem | ||
348 | trace data to come out of a different HW output port. | ||
349 | This is part of a solution for the P1149.7, compact JTAG, standard. | ||
350 | |||
351 | If you select this option, you need to select | ||
352 | "Trace data router for MIPI P1149.7 cJTAG standard". | ||
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 690522fcb338..ea89b0bd15fe 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile | |||
@@ -6,6 +6,8 @@ obj-$(CONFIG_AUDIT) += tty_audit.o | |||
6 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 6 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
7 | obj-$(CONFIG_N_HDLC) += n_hdlc.o | 7 | obj-$(CONFIG_N_HDLC) += n_hdlc.o |
8 | obj-$(CONFIG_N_GSM) += n_gsm.o | 8 | obj-$(CONFIG_N_GSM) += n_gsm.o |
9 | obj-$(CONFIG_TRACE_ROUTER) += n_tracerouter.o | ||
10 | obj-$(CONFIG_TRACE_SINK) += n_tracesink.o | ||
9 | obj-$(CONFIG_R3964) += n_r3964.o | 11 | obj-$(CONFIG_R3964) += n_r3964.o |
10 | 12 | ||
11 | obj-y += vt/ | 13 | obj-y += vt/ |
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index f214e5022472..220579592c20 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/amiserial.c | ||
3 | * | ||
4 | * Serial driver for the amiga builtin port. | 2 | * Serial driver for the amiga builtin port. |
5 | * | 3 | * |
6 | * This code was created by taking serial.c version 4.30 from kernel | 4 | * This code was created by taking serial.c version 4.30 from kernel |
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index c99728f0cd9f..bfa05e801823 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c | |||
@@ -3,8 +3,6 @@ | |||
3 | #undef Z_EXT_CHARS_IN_BUFFER | 3 | #undef Z_EXT_CHARS_IN_BUFFER |
4 | 4 | ||
5 | /* | 5 | /* |
6 | * linux/drivers/char/cyclades.c | ||
7 | * | ||
8 | * This file contains the driver for the Cyclades async multiport | 6 | * This file contains the driver for the Cyclades async multiport |
9 | * serial boards. | 7 | * serial boards. |
10 | * | 8 | * |
@@ -1445,13 +1443,11 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) | |||
1445 | { | 1443 | { |
1446 | struct cyclades_card *card; | 1444 | struct cyclades_card *card; |
1447 | unsigned long flags; | 1445 | unsigned long flags; |
1448 | int channel; | ||
1449 | 1446 | ||
1450 | if (!(info->port.flags & ASYNC_INITIALIZED)) | 1447 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
1451 | return; | 1448 | return; |
1452 | 1449 | ||
1453 | card = info->card; | 1450 | card = info->card; |
1454 | channel = info->line - card->first_line; | ||
1455 | if (!cy_is_Z(card)) { | 1451 | if (!cy_is_Z(card)) { |
1456 | spin_lock_irqsave(&card->card_lock, flags); | 1452 | spin_lock_irqsave(&card->card_lock, flags); |
1457 | 1453 | ||
@@ -1476,6 +1472,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) | |||
1476 | spin_unlock_irqrestore(&card->card_lock, flags); | 1472 | spin_unlock_irqrestore(&card->card_lock, flags); |
1477 | } else { | 1473 | } else { |
1478 | #ifdef CY_DEBUG_OPEN | 1474 | #ifdef CY_DEBUG_OPEN |
1475 | int channel = info->line - card->first_line; | ||
1479 | printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " | 1476 | printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " |
1480 | "base_addr %p\n", card, channel, card->base_addr); | 1477 | "base_addr %p\n", card, channel, card->base_addr); |
1481 | #endif | 1478 | #endif |
diff --git a/drivers/tty/ipwireless/Makefile b/drivers/tty/ipwireless/Makefile index db80873d7f20..fe2e1730986b 100644 --- a/drivers/tty/ipwireless/Makefile +++ b/drivers/tty/ipwireless/Makefile | |||
@@ -1,6 +1,4 @@ | |||
1 | # | 1 | # |
2 | # drivers/char/pcmcia/ipwireless/Makefile | ||
3 | # | ||
4 | # Makefile for the IPWireless driver | 2 | # Makefile for the IPWireless driver |
5 | # | 3 | # |
6 | 4 | ||
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 35b0c38590e6..ba679ce0a774 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c | |||
@@ -371,7 +371,7 @@ static int moxa_ioctl(struct tty_struct *tty, | |||
371 | tmp.cflag = p->cflag; | 371 | tmp.cflag = p->cflag; |
372 | else | 372 | else |
373 | tmp.cflag = ttyp->termios->c_cflag; | 373 | tmp.cflag = ttyp->termios->c_cflag; |
374 | tty_kref_put(tty); | 374 | tty_kref_put(ttyp); |
375 | copy: | 375 | copy: |
376 | if (copy_to_user(argm, &tmp, sizeof(tmp))) | 376 | if (copy_to_user(argm, &tmp, sizeof(tmp))) |
377 | return -EFAULT; | 377 | return -EFAULT; |
@@ -1129,7 +1129,6 @@ static void moxa_shutdown(struct tty_port *port) | |||
1129 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 1129 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1130 | MoxaPortDisable(ch); | 1130 | MoxaPortDisable(ch); |
1131 | MoxaPortFlushData(ch, 2); | 1131 | MoxaPortFlushData(ch, 2); |
1132 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | ||
1133 | } | 1132 | } |
1134 | 1133 | ||
1135 | static int moxa_carrier_raised(struct tty_port *port) | 1134 | static int moxa_carrier_raised(struct tty_port *port) |
@@ -1155,7 +1154,6 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1155 | struct moxa_board_conf *brd; | 1154 | struct moxa_board_conf *brd; |
1156 | struct moxa_port *ch; | 1155 | struct moxa_port *ch; |
1157 | int port; | 1156 | int port; |
1158 | int retval; | ||
1159 | 1157 | ||
1160 | port = tty->index; | 1158 | port = tty->index; |
1161 | if (port == MAX_PORTS) { | 1159 | if (port == MAX_PORTS) { |
@@ -1190,10 +1188,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1190 | mutex_unlock(&ch->port.mutex); | 1188 | mutex_unlock(&ch->port.mutex); |
1191 | mutex_unlock(&moxa_openlock); | 1189 | mutex_unlock(&moxa_openlock); |
1192 | 1190 | ||
1193 | retval = tty_port_block_til_ready(&ch->port, tty, filp); | 1191 | return tty_port_block_til_ready(&ch->port, tty, filp); |
1194 | if (retval == 0) | ||
1195 | set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); | ||
1196 | return retval; | ||
1197 | } | 1192 | } |
1198 | 1193 | ||
1199 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 1194 | static void moxa_close(struct tty_struct *tty, struct file *filp) |
@@ -1207,14 +1202,15 @@ static int moxa_write(struct tty_struct *tty, | |||
1207 | const unsigned char *buf, int count) | 1202 | const unsigned char *buf, int count) |
1208 | { | 1203 | { |
1209 | struct moxa_port *ch = tty->driver_data; | 1204 | struct moxa_port *ch = tty->driver_data; |
1205 | unsigned long flags; | ||
1210 | int len; | 1206 | int len; |
1211 | 1207 | ||
1212 | if (ch == NULL) | 1208 | if (ch == NULL) |
1213 | return 0; | 1209 | return 0; |
1214 | 1210 | ||
1215 | spin_lock_bh(&moxa_lock); | 1211 | spin_lock_irqsave(&moxa_lock, flags); |
1216 | len = MoxaPortWriteData(tty, buf, count); | 1212 | len = MoxaPortWriteData(tty, buf, count); |
1217 | spin_unlock_bh(&moxa_lock); | 1213 | spin_unlock_irqrestore(&moxa_lock, flags); |
1218 | 1214 | ||
1219 | set_bit(LOWWAIT, &ch->statusflags); | 1215 | set_bit(LOWWAIT, &ch->statusflags); |
1220 | return len; | 1216 | return len; |
@@ -1281,10 +1277,8 @@ static int moxa_tiocmset(struct tty_struct *tty, | |||
1281 | unsigned int set, unsigned int clear) | 1277 | unsigned int set, unsigned int clear) |
1282 | { | 1278 | { |
1283 | struct moxa_port *ch; | 1279 | struct moxa_port *ch; |
1284 | int port; | ||
1285 | int dtr, rts; | 1280 | int dtr, rts; |
1286 | 1281 | ||
1287 | port = tty->index; | ||
1288 | mutex_lock(&moxa_openlock); | 1282 | mutex_lock(&moxa_openlock); |
1289 | ch = tty->driver_data; | 1283 | ch = tty->driver_data; |
1290 | if (!ch) { | 1284 | if (!ch) { |
@@ -1756,11 +1750,9 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, | |||
1756 | speed_t baud) | 1750 | speed_t baud) |
1757 | { | 1751 | { |
1758 | void __iomem *ofsAddr; | 1752 | void __iomem *ofsAddr; |
1759 | tcflag_t cflag; | ||
1760 | tcflag_t mode = 0; | 1753 | tcflag_t mode = 0; |
1761 | 1754 | ||
1762 | ofsAddr = port->tableAddr; | 1755 | ofsAddr = port->tableAddr; |
1763 | cflag = termio->c_cflag; /* termio->c_cflag */ | ||
1764 | 1756 | ||
1765 | mode = termio->c_cflag & CSIZE; | 1757 | mode = termio->c_cflag & CSIZE; |
1766 | if (mode == CS5) | 1758 | if (mode == CS5) |
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 74273e638c0d..a4c42a75a3bf 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -526,19 +526,6 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len) | |||
526 | return olen; | 526 | return olen; |
527 | } | 527 | } |
528 | 528 | ||
529 | static void hex_packet(const unsigned char *p, int len) | ||
530 | { | ||
531 | int i; | ||
532 | for (i = 0; i < len; i++) { | ||
533 | if (i && (i % 16) == 0) { | ||
534 | pr_cont("\n"); | ||
535 | pr_debug(""); | ||
536 | } | ||
537 | pr_cont("%02X ", *p++); | ||
538 | } | ||
539 | pr_cont("\n"); | ||
540 | } | ||
541 | |||
542 | /** | 529 | /** |
543 | * gsm_send - send a control frame | 530 | * gsm_send - send a control frame |
544 | * @gsm: our GSM mux | 531 | * @gsm: our GSM mux |
@@ -685,10 +672,10 @@ static void gsm_data_kick(struct gsm_mux *gsm) | |||
685 | len = msg->len + 2; | 672 | len = msg->len + 2; |
686 | } | 673 | } |
687 | 674 | ||
688 | if (debug & 4) { | 675 | if (debug & 4) |
689 | pr_debug("gsm_data_kick:\n"); | 676 | print_hex_dump_bytes("gsm_data_kick: ", |
690 | hex_packet(gsm->txframe, len); | 677 | DUMP_PREFIX_OFFSET, |
691 | } | 678 | gsm->txframe, len); |
692 | 679 | ||
693 | if (gsm->output(gsm, gsm->txframe + skip_sof, | 680 | if (gsm->output(gsm, gsm->txframe + skip_sof, |
694 | len - skip_sof) < 0) | 681 | len - skip_sof) < 0) |
@@ -2095,10 +2082,9 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len) | |||
2095 | set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); | 2082 | set_bit(TTY_DO_WRITE_WAKEUP, &gsm->tty->flags); |
2096 | return -ENOSPC; | 2083 | return -ENOSPC; |
2097 | } | 2084 | } |
2098 | if (debug & 4) { | 2085 | if (debug & 4) |
2099 | pr_debug("-->%d bytes out\n", len); | 2086 | print_hex_dump_bytes("gsmld_output: ", DUMP_PREFIX_OFFSET, |
2100 | hex_packet(data, len); | 2087 | data, len); |
2101 | } | ||
2102 | gsm->tty->ops->write(gsm->tty, data, len); | 2088 | gsm->tty->ops->write(gsm->tty, data, len); |
2103 | return len; | 2089 | return len; |
2104 | } | 2090 | } |
@@ -2128,7 +2114,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | |||
2128 | 2114 | ||
2129 | /** | 2115 | /** |
2130 | * gsmld_detach_gsm - stop doing 0710 mux | 2116 | * gsmld_detach_gsm - stop doing 0710 mux |
2131 | * @tty: tty atttached to the mux | 2117 | * @tty: tty attached to the mux |
2132 | * @gsm: mux | 2118 | * @gsm: mux |
2133 | * | 2119 | * |
2134 | * Shutdown and then clean up the resources used by the line discipline | 2120 | * Shutdown and then clean up the resources used by the line discipline |
@@ -2142,8 +2128,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm) | |||
2142 | gsm->tty = NULL; | 2128 | gsm->tty = NULL; |
2143 | } | 2129 | } |
2144 | 2130 | ||
2145 | static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 2131 | static unsigned int gsmld_receive_buf(struct tty_struct *tty, |
2146 | char *fp, int count) | 2132 | const unsigned char *cp, char *fp, int count) |
2147 | { | 2133 | { |
2148 | struct gsm_mux *gsm = tty->disc_data; | 2134 | struct gsm_mux *gsm = tty->disc_data; |
2149 | const unsigned char *dp; | 2135 | const unsigned char *dp; |
@@ -2152,10 +2138,9 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
2152 | char buf[64]; | 2138 | char buf[64]; |
2153 | char flags; | 2139 | char flags; |
2154 | 2140 | ||
2155 | if (debug & 4) { | 2141 | if (debug & 4) |
2156 | pr_debug("Inbytes %dd\n", count); | 2142 | print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET, |
2157 | hex_packet(cp, count); | 2143 | cp, count); |
2158 | } | ||
2159 | 2144 | ||
2160 | for (i = count, dp = cp, f = fp; i; i--, dp++) { | 2145 | for (i = count, dp = cp, f = fp; i; i--, dp++) { |
2161 | flags = *f++; | 2146 | flags = *f++; |
@@ -2177,6 +2162,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
2177 | } | 2162 | } |
2178 | /* FASYNC if needed ? */ | 2163 | /* FASYNC if needed ? */ |
2179 | /* If clogged call tty_throttle(tty); */ | 2164 | /* If clogged call tty_throttle(tty); */ |
2165 | |||
2166 | return count; | ||
2180 | } | 2167 | } |
2181 | 2168 | ||
2182 | /** | 2169 | /** |
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index cea56033b34c..cac666314aef 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c | |||
@@ -188,8 +188,8 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, | |||
188 | poll_table *wait); | 188 | poll_table *wait); |
189 | static int n_hdlc_tty_open(struct tty_struct *tty); | 189 | static int n_hdlc_tty_open(struct tty_struct *tty); |
190 | static void n_hdlc_tty_close(struct tty_struct *tty); | 190 | static void n_hdlc_tty_close(struct tty_struct *tty); |
191 | static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp, | 191 | static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, |
192 | char *fp, int count); | 192 | const __u8 *cp, char *fp, int count); |
193 | static void n_hdlc_tty_wakeup(struct tty_struct *tty); | 193 | static void n_hdlc_tty_wakeup(struct tty_struct *tty); |
194 | 194 | ||
195 | #define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) | 195 | #define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) |
@@ -509,8 +509,8 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) | |||
509 | * Called by tty low level driver when receive data is available. Data is | 509 | * Called by tty low level driver when receive data is available. Data is |
510 | * interpreted as one HDLC frame. | 510 | * interpreted as one HDLC frame. |
511 | */ | 511 | */ |
512 | static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, | 512 | static unsigned int n_hdlc_tty_receive(struct tty_struct *tty, |
513 | char *flags, int count) | 513 | const __u8 *data, char *flags, int count) |
514 | { | 514 | { |
515 | register struct n_hdlc *n_hdlc = tty2n_hdlc (tty); | 515 | register struct n_hdlc *n_hdlc = tty2n_hdlc (tty); |
516 | register struct n_hdlc_buf *buf; | 516 | register struct n_hdlc_buf *buf; |
@@ -521,20 +521,20 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, | |||
521 | 521 | ||
522 | /* This can happen if stuff comes in on the backup tty */ | 522 | /* This can happen if stuff comes in on the backup tty */ |
523 | if (!n_hdlc || tty != n_hdlc->tty) | 523 | if (!n_hdlc || tty != n_hdlc->tty) |
524 | return; | 524 | return -ENODEV; |
525 | 525 | ||
526 | /* verify line is using HDLC discipline */ | 526 | /* verify line is using HDLC discipline */ |
527 | if (n_hdlc->magic != HDLC_MAGIC) { | 527 | if (n_hdlc->magic != HDLC_MAGIC) { |
528 | printk("%s(%d) line not using HDLC discipline\n", | 528 | printk("%s(%d) line not using HDLC discipline\n", |
529 | __FILE__,__LINE__); | 529 | __FILE__,__LINE__); |
530 | return; | 530 | return -EINVAL; |
531 | } | 531 | } |
532 | 532 | ||
533 | if ( count>maxframe ) { | 533 | if ( count>maxframe ) { |
534 | if (debuglevel >= DEBUG_LEVEL_INFO) | 534 | if (debuglevel >= DEBUG_LEVEL_INFO) |
535 | printk("%s(%d) rx count>maxframesize, data discarded\n", | 535 | printk("%s(%d) rx count>maxframesize, data discarded\n", |
536 | __FILE__,__LINE__); | 536 | __FILE__,__LINE__); |
537 | return; | 537 | return -EINVAL; |
538 | } | 538 | } |
539 | 539 | ||
540 | /* get a free HDLC buffer */ | 540 | /* get a free HDLC buffer */ |
@@ -550,7 +550,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, | |||
550 | if (debuglevel >= DEBUG_LEVEL_INFO) | 550 | if (debuglevel >= DEBUG_LEVEL_INFO) |
551 | printk("%s(%d) no more rx buffers, data discarded\n", | 551 | printk("%s(%d) no more rx buffers, data discarded\n", |
552 | __FILE__,__LINE__); | 552 | __FILE__,__LINE__); |
553 | return; | 553 | return -EINVAL; |
554 | } | 554 | } |
555 | 555 | ||
556 | /* copy received data to HDLC buffer */ | 556 | /* copy received data to HDLC buffer */ |
@@ -565,6 +565,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, | |||
565 | if (n_hdlc->tty->fasync != NULL) | 565 | if (n_hdlc->tty->fasync != NULL) |
566 | kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); | 566 | kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); |
567 | 567 | ||
568 | return count; | ||
569 | |||
568 | } /* end of n_hdlc_tty_receive() */ | 570 | } /* end of n_hdlc_tty_receive() */ |
569 | 571 | ||
570 | /** | 572 | /** |
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2f..a4bc39c21a43 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c | |||
@@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file, | |||
139 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); | 139 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); |
140 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, | 140 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
141 | struct poll_table_struct *wait); | 141 | struct poll_table_struct *wait); |
142 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 142 | static unsigned int r3964_receive_buf(struct tty_struct *tty, |
143 | char *fp, int count); | 143 | const unsigned char *cp, char *fp, int count); |
144 | 144 | ||
145 | static struct tty_ldisc_ops tty_ldisc_N_R3964 = { | 145 | static struct tty_ldisc_ops tty_ldisc_N_R3964 = { |
146 | .owner = THIS_MODULE, | 146 | .owner = THIS_MODULE, |
@@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, | |||
1239 | return result; | 1239 | return result; |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1242 | static unsigned int r3964_receive_buf(struct tty_struct *tty, |
1243 | char *fp, int count) | 1243 | const unsigned char *cp, char *fp, int count) |
1244 | { | 1244 | { |
1245 | struct r3964_info *pInfo = tty->disc_data; | 1245 | struct r3964_info *pInfo = tty->disc_data; |
1246 | const unsigned char *p; | 1246 | const unsigned char *p; |
@@ -1257,6 +1257,8 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | } | 1259 | } |
1260 | |||
1261 | return count; | ||
1260 | } | 1262 | } |
1261 | 1263 | ||
1262 | MODULE_LICENSE("GPL"); | 1264 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/tty/n_tracerouter.c b/drivers/tty/n_tracerouter.c new file mode 100644 index 000000000000..1f063d3aa32f --- /dev/null +++ b/drivers/tty/n_tracerouter.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * n_tracerouter.c - Trace data router through tty space | ||
3 | * | ||
4 | * Copyright (C) Intel 2011 | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * 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. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | * This trace router uses the Linux line discipline framework to route | ||
20 | * trace data coming from a HW Modem to a PTI (Parallel Trace Module) port. | ||
21 | * The solution is not specific to a HW modem and this line disciple can | ||
22 | * be used to route any stream of data in kernel space. | ||
23 | * This is part of a solution for the P1149.7, compact JTAG, standard. | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/ioctl.h> | ||
31 | #include <linux/tty.h> | ||
32 | #include <linux/tty_ldisc.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/mutex.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <asm-generic/bug.h> | ||
38 | #include "n_tracesink.h" | ||
39 | |||
40 | /* | ||
41 | * Other ldisc drivers use 65536 which basically means, | ||
42 | * 'I can always accept 64k' and flow control is off. | ||
43 | * This number is deemed appropriate for this driver. | ||
44 | */ | ||
45 | #define RECEIVE_ROOM 65536 | ||
46 | #define DRIVERNAME "n_tracerouter" | ||
47 | |||
48 | /* | ||
49 | * struct to hold private configuration data for this ldisc. | ||
50 | * opencalled is used to hold if this ldisc has been opened. | ||
51 | * kref_tty holds the tty reference the ldisc sits on top of. | ||
52 | */ | ||
53 | struct tracerouter_data { | ||
54 | u8 opencalled; | ||
55 | struct tty_struct *kref_tty; | ||
56 | }; | ||
57 | static struct tracerouter_data *tr_data; | ||
58 | |||
59 | /* lock for when tty reference is being used */ | ||
60 | static DEFINE_MUTEX(routelock); | ||
61 | |||
62 | /** | ||
63 | * n_tracerouter_open() - Called when a tty is opened by a SW entity. | ||
64 | * @tty: terminal device to the ldisc. | ||
65 | * | ||
66 | * Return: | ||
67 | * 0 for success. | ||
68 | * | ||
69 | * Caveats: This should only be opened one time per SW entity. | ||
70 | */ | ||
71 | static int n_tracerouter_open(struct tty_struct *tty) | ||
72 | { | ||
73 | int retval = -EEXIST; | ||
74 | |||
75 | mutex_lock(&routelock); | ||
76 | if (tr_data->opencalled == 0) { | ||
77 | |||
78 | tr_data->kref_tty = tty_kref_get(tty); | ||
79 | if (tr_data->kref_tty == NULL) { | ||
80 | retval = -EFAULT; | ||
81 | } else { | ||
82 | tr_data->opencalled = 1; | ||
83 | tty->disc_data = tr_data; | ||
84 | tty->receive_room = RECEIVE_ROOM; | ||
85 | tty_driver_flush_buffer(tty); | ||
86 | retval = 0; | ||
87 | } | ||
88 | } | ||
89 | mutex_unlock(&routelock); | ||
90 | return retval; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * n_tracerouter_close() - close connection | ||
95 | * @tty: terminal device to the ldisc. | ||
96 | * | ||
97 | * Called when a software entity wants to close a connection. | ||
98 | */ | ||
99 | static void n_tracerouter_close(struct tty_struct *tty) | ||
100 | { | ||
101 | struct tracerouter_data *tptr = tty->disc_data; | ||
102 | |||
103 | mutex_lock(&routelock); | ||
104 | WARN_ON(tptr->kref_tty != tr_data->kref_tty); | ||
105 | tty_driver_flush_buffer(tty); | ||
106 | tty_kref_put(tr_data->kref_tty); | ||
107 | tr_data->kref_tty = NULL; | ||
108 | tr_data->opencalled = 0; | ||
109 | tty->disc_data = NULL; | ||
110 | mutex_unlock(&routelock); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * n_tracerouter_read() - read request from user space | ||
115 | * @tty: terminal device passed into the ldisc. | ||
116 | * @file: pointer to open file object. | ||
117 | * @buf: pointer to the data buffer that gets eventually returned. | ||
118 | * @nr: number of bytes of the data buffer that is returned. | ||
119 | * | ||
120 | * function that allows read() functionality in userspace. By default if this | ||
121 | * is not implemented it returns -EIO. This module is functioning like a | ||
122 | * router via n_tracerouter_receivebuf(), and there is no real requirement | ||
123 | * to implement this function. However, an error return value other than | ||
124 | * -EIO should be used just to show that there was an intent not to have | ||
125 | * this function implemented. Return value based on read() man pages. | ||
126 | * | ||
127 | * Return: | ||
128 | * -EINVAL | ||
129 | */ | ||
130 | static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, | ||
131 | unsigned char __user *buf, size_t nr) { | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * n_tracerouter_write() - Function that allows write() in userspace. | ||
137 | * @tty: terminal device passed into the ldisc. | ||
138 | * @file: pointer to open file object. | ||
139 | * @buf: pointer to the data buffer that gets eventually returned. | ||
140 | * @nr: number of bytes of the data buffer that is returned. | ||
141 | * | ||
142 | * By default if this is not implemented, it returns -EIO. | ||
143 | * This should not be implemented, ever, because | ||
144 | * 1. this driver is functioning like a router via | ||
145 | * n_tracerouter_receivebuf() | ||
146 | * 2. No writes to HW will ever go through this line discpline driver. | ||
147 | * However, an error return value other than -EIO should be used | ||
148 | * just to show that there was an intent not to have this function | ||
149 | * implemented. Return value based on write() man pages. | ||
150 | * | ||
151 | * Return: | ||
152 | * -EINVAL | ||
153 | */ | ||
154 | static ssize_t n_tracerouter_write(struct tty_struct *tty, struct file *file, | ||
155 | const unsigned char *buf, size_t nr) { | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * n_tracerouter_receivebuf() - Routing function for driver. | ||
161 | * @tty: terminal device passed into the ldisc. It's assumed | ||
162 | * tty will never be NULL. | ||
163 | * @cp: buffer, block of characters to be eventually read by | ||
164 | * someone, somewhere (user read() call or some kernel function). | ||
165 | * @fp: flag buffer. | ||
166 | * @count: number of characters (aka, bytes) in cp. | ||
167 | * | ||
168 | * This function takes the input buffer, cp, and passes it to | ||
169 | * an external API function for processing. | ||
170 | */ | ||
171 | static void n_tracerouter_receivebuf(struct tty_struct *tty, | ||
172 | const unsigned char *cp, | ||
173 | char *fp, int count) | ||
174 | { | ||
175 | mutex_lock(&routelock); | ||
176 | n_tracesink_datadrain((u8 *) cp, count); | ||
177 | mutex_unlock(&routelock); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * Flush buffer is not impelemented as the ldisc has no internal buffering | ||
182 | * so the tty_driver_flush_buffer() is sufficient for this driver's needs. | ||
183 | */ | ||
184 | |||
185 | static struct tty_ldisc_ops tty_ptirouter_ldisc = { | ||
186 | .owner = THIS_MODULE, | ||
187 | .magic = TTY_LDISC_MAGIC, | ||
188 | .name = DRIVERNAME, | ||
189 | .open = n_tracerouter_open, | ||
190 | .close = n_tracerouter_close, | ||
191 | .read = n_tracerouter_read, | ||
192 | .write = n_tracerouter_write, | ||
193 | .receive_buf = n_tracerouter_receivebuf | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * n_tracerouter_init - module initialisation | ||
198 | * | ||
199 | * Registers this module as a line discipline driver. | ||
200 | * | ||
201 | * Return: | ||
202 | * 0 for success, any other value error. | ||
203 | */ | ||
204 | static int __init n_tracerouter_init(void) | ||
205 | { | ||
206 | int retval; | ||
207 | |||
208 | tr_data = kzalloc(sizeof(struct tracerouter_data), GFP_KERNEL); | ||
209 | if (tr_data == NULL) | ||
210 | return -ENOMEM; | ||
211 | |||
212 | |||
213 | /* Note N_TRACEROUTER is defined in linux/tty.h */ | ||
214 | retval = tty_register_ldisc(N_TRACEROUTER, &tty_ptirouter_ldisc); | ||
215 | if (retval < 0) { | ||
216 | pr_err("%s: Registration failed: %d\n", __func__, retval); | ||
217 | kfree(tr_data); | ||
218 | } | ||
219 | return retval; | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * n_tracerouter_exit - module unload | ||
224 | * | ||
225 | * Removes this module as a line discipline driver. | ||
226 | */ | ||
227 | static void __exit n_tracerouter_exit(void) | ||
228 | { | ||
229 | int retval = tty_unregister_ldisc(N_TRACEROUTER); | ||
230 | |||
231 | if (retval < 0) | ||
232 | pr_err("%s: Unregistration failed: %d\n", __func__, retval); | ||
233 | else | ||
234 | kfree(tr_data); | ||
235 | } | ||
236 | |||
237 | module_init(n_tracerouter_init); | ||
238 | module_exit(n_tracerouter_exit); | ||
239 | |||
240 | MODULE_LICENSE("GPL"); | ||
241 | MODULE_AUTHOR("Jay Freyensee"); | ||
242 | MODULE_ALIAS_LDISC(N_TRACEROUTER); | ||
243 | MODULE_DESCRIPTION("Trace router ldisc driver"); | ||
diff --git a/drivers/tty/n_tracesink.c b/drivers/tty/n_tracesink.c new file mode 100644 index 000000000000..ddce58b973d2 --- /dev/null +++ b/drivers/tty/n_tracesink.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * n_tracesink.c - Trace data router and sink path through tty space. | ||
3 | * | ||
4 | * Copyright (C) Intel 2011 | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * 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. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | * The trace sink uses the Linux line discipline framework to receive | ||
20 | * trace data coming from the PTI source line discipline driver | ||
21 | * to a user-desired tty port, like USB. | ||
22 | * This is to provide a way to extract modem trace data on | ||
23 | * devices that do not have a PTI HW module, or just need modem | ||
24 | * trace data to come out of a different HW output port. | ||
25 | * This is part of a solution for the P1149.7, compact JTAG, standard. | ||
26 | */ | ||
27 | |||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/ioctl.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/tty_ldisc.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <asm-generic/bug.h> | ||
38 | #include "n_tracesink.h" | ||
39 | |||
40 | /* | ||
41 | * Other ldisc drivers use 65536 which basically means, | ||
42 | * 'I can always accept 64k' and flow control is off. | ||
43 | * This number is deemed appropriate for this driver. | ||
44 | */ | ||
45 | #define RECEIVE_ROOM 65536 | ||
46 | #define DRIVERNAME "n_tracesink" | ||
47 | |||
48 | /* | ||
49 | * there is a quirk with this ldisc is he can write data | ||
50 | * to a tty from anyone calling his kernel API, which | ||
51 | * meets customer requirements in the drivers/misc/pti.c | ||
52 | * project. So he needs to know when he can and cannot write when | ||
53 | * the API is called. In theory, the API can be called | ||
54 | * after an init() but before a successful open() which | ||
55 | * would crash the system if tty is not checked. | ||
56 | */ | ||
57 | static struct tty_struct *this_tty; | ||
58 | static DEFINE_MUTEX(writelock); | ||
59 | |||
60 | /** | ||
61 | * n_tracesink_open() - Called when a tty is opened by a SW entity. | ||
62 | * @tty: terminal device to the ldisc. | ||
63 | * | ||
64 | * Return: | ||
65 | * 0 for success, | ||
66 | * -EFAULT = couldn't get a tty kref n_tracesink will sit | ||
67 | * on top of | ||
68 | * -EEXIST = open() called successfully once and it cannot | ||
69 | * be called again. | ||
70 | * | ||
71 | * Caveats: open() should only be successful the first time a | ||
72 | * SW entity calls it. | ||
73 | */ | ||
74 | static int n_tracesink_open(struct tty_struct *tty) | ||
75 | { | ||
76 | int retval = -EEXIST; | ||
77 | |||
78 | mutex_lock(&writelock); | ||
79 | if (this_tty == NULL) { | ||
80 | this_tty = tty_kref_get(tty); | ||
81 | if (this_tty == NULL) { | ||
82 | retval = -EFAULT; | ||
83 | } else { | ||
84 | tty->disc_data = this_tty; | ||
85 | tty_driver_flush_buffer(tty); | ||
86 | retval = 0; | ||
87 | } | ||
88 | } | ||
89 | mutex_unlock(&writelock); | ||
90 | |||
91 | return retval; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * n_tracesink_close() - close connection | ||
96 | * @tty: terminal device to the ldisc. | ||
97 | * | ||
98 | * Called when a software entity wants to close a connection. | ||
99 | */ | ||
100 | static void n_tracesink_close(struct tty_struct *tty) | ||
101 | { | ||
102 | mutex_lock(&writelock); | ||
103 | tty_driver_flush_buffer(tty); | ||
104 | tty_kref_put(this_tty); | ||
105 | this_tty = NULL; | ||
106 | tty->disc_data = NULL; | ||
107 | mutex_unlock(&writelock); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * n_tracesink_read() - read request from user space | ||
112 | * @tty: terminal device passed into the ldisc. | ||
113 | * @file: pointer to open file object. | ||
114 | * @buf: pointer to the data buffer that gets eventually returned. | ||
115 | * @nr: number of bytes of the data buffer that is returned. | ||
116 | * | ||
117 | * function that allows read() functionality in userspace. By default if this | ||
118 | * is not implemented it returns -EIO. This module is functioning like a | ||
119 | * router via n_tracesink_receivebuf(), and there is no real requirement | ||
120 | * to implement this function. However, an error return value other than | ||
121 | * -EIO should be used just to show that there was an intent not to have | ||
122 | * this function implemented. Return value based on read() man pages. | ||
123 | * | ||
124 | * Return: | ||
125 | * -EINVAL | ||
126 | */ | ||
127 | static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, | ||
128 | unsigned char __user *buf, size_t nr) { | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * n_tracesink_write() - Function that allows write() in userspace. | ||
134 | * @tty: terminal device passed into the ldisc. | ||
135 | * @file: pointer to open file object. | ||
136 | * @buf: pointer to the data buffer that gets eventually returned. | ||
137 | * @nr: number of bytes of the data buffer that is returned. | ||
138 | * | ||
139 | * By default if this is not implemented, it returns -EIO. | ||
140 | * This should not be implemented, ever, because | ||
141 | * 1. this driver is functioning like a router via | ||
142 | * n_tracesink_receivebuf() | ||
143 | * 2. No writes to HW will ever go through this line discpline driver. | ||
144 | * However, an error return value other than -EIO should be used | ||
145 | * just to show that there was an intent not to have this function | ||
146 | * implemented. Return value based on write() man pages. | ||
147 | * | ||
148 | * Return: | ||
149 | * -EINVAL | ||
150 | */ | ||
151 | static ssize_t n_tracesink_write(struct tty_struct *tty, struct file *file, | ||
152 | const unsigned char *buf, size_t nr) { | ||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * n_tracesink_datadrain() - Kernel API function used to route | ||
158 | * trace debugging data to user-defined | ||
159 | * port like USB. | ||
160 | * | ||
161 | * @buf: Trace debuging data buffer to write to tty target | ||
162 | * port. Null value will return with no write occurring. | ||
163 | * @count: Size of buf. Value of 0 or a negative number will | ||
164 | * return with no write occuring. | ||
165 | * | ||
166 | * Caveat: If this line discipline does not set the tty it sits | ||
167 | * on top of via an open() call, this API function will not | ||
168 | * call the tty's write() call because it will have no pointer | ||
169 | * to call the write(). | ||
170 | */ | ||
171 | void n_tracesink_datadrain(u8 *buf, int count) | ||
172 | { | ||
173 | mutex_lock(&writelock); | ||
174 | |||
175 | if ((buf != NULL) && (count > 0) && (this_tty != NULL)) | ||
176 | this_tty->ops->write(this_tty, buf, count); | ||
177 | |||
178 | mutex_unlock(&writelock); | ||
179 | } | ||
180 | EXPORT_SYMBOL_GPL(n_tracesink_datadrain); | ||
181 | |||
182 | /* | ||
183 | * Flush buffer is not impelemented as the ldisc has no internal buffering | ||
184 | * so the tty_driver_flush_buffer() is sufficient for this driver's needs. | ||
185 | */ | ||
186 | |||
187 | /* | ||
188 | * tty_ldisc function operations for this driver. | ||
189 | */ | ||
190 | static struct tty_ldisc_ops tty_n_tracesink = { | ||
191 | .owner = THIS_MODULE, | ||
192 | .magic = TTY_LDISC_MAGIC, | ||
193 | .name = DRIVERNAME, | ||
194 | .open = n_tracesink_open, | ||
195 | .close = n_tracesink_close, | ||
196 | .read = n_tracesink_read, | ||
197 | .write = n_tracesink_write | ||
198 | }; | ||
199 | |||
200 | /** | ||
201 | * n_tracesink_init- module initialisation | ||
202 | * | ||
203 | * Registers this module as a line discipline driver. | ||
204 | * | ||
205 | * Return: | ||
206 | * 0 for success, any other value error. | ||
207 | */ | ||
208 | static int __init n_tracesink_init(void) | ||
209 | { | ||
210 | /* Note N_TRACESINK is defined in linux/tty.h */ | ||
211 | int retval = tty_register_ldisc(N_TRACESINK, &tty_n_tracesink); | ||
212 | |||
213 | if (retval < 0) | ||
214 | pr_err("%s: Registration failed: %d\n", __func__, retval); | ||
215 | |||
216 | return retval; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * n_tracesink_exit - module unload | ||
221 | * | ||
222 | * Removes this module as a line discipline driver. | ||
223 | */ | ||
224 | static void __exit n_tracesink_exit(void) | ||
225 | { | ||
226 | int retval = tty_unregister_ldisc(N_TRACESINK); | ||
227 | |||
228 | if (retval < 0) | ||
229 | pr_err("%s: Unregistration failed: %d\n", __func__, retval); | ||
230 | } | ||
231 | |||
232 | module_init(n_tracesink_init); | ||
233 | module_exit(n_tracesink_exit); | ||
234 | |||
235 | MODULE_LICENSE("GPL"); | ||
236 | MODULE_AUTHOR("Jay Freyensee"); | ||
237 | MODULE_ALIAS_LDISC(N_TRACESINK); | ||
238 | MODULE_DESCRIPTION("Trace sink ldisc driver"); | ||
diff --git a/drivers/tty/n_tracesink.h b/drivers/tty/n_tracesink.h new file mode 100644 index 000000000000..a68bb44f1ef5 --- /dev/null +++ b/drivers/tty/n_tracesink.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * n_tracesink.h - Kernel driver API to route trace data in kernel space. | ||
3 | * | ||
4 | * Copyright (C) Intel 2011 | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 | ||
10 | * 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. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
18 | * | ||
19 | * The PTI (Parallel Trace Interface) driver directs trace data routed from | ||
20 | * various parts in the system out through the Intel Penwell PTI port and | ||
21 | * out of the mobile device for analysis with a debugging tool | ||
22 | * (Lauterbach, Fido). This is part of a solution for the MIPI P1149.7, | ||
23 | * compact JTAG, standard. | ||
24 | * | ||
25 | * This header file is used by n_tracerouter to be able to send the | ||
26 | * data of it's tty port to the tty port this module sits. This | ||
27 | * mechanism can also be used independent of the PTI module. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #ifndef N_TRACESINK_H_ | ||
32 | #define N_TRACESINK_H_ | ||
33 | |||
34 | void n_tracesink_datadrain(u8 *buf, int count); | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0ad32888091c..95d0a9c2dd13 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | |||
81 | return put_user(x, ptr); | 81 | return put_user(x, ptr); |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | ||
85 | * n_tty_set__room - receive space | ||
86 | * @tty: terminal | ||
87 | * | ||
88 | * Called by the driver to find out how much data it is | ||
89 | * permitted to feed to the line discipline without any being lost | ||
90 | * and thus to manage flow control. Not serialized. Answers for the | ||
91 | * "instant". | ||
92 | */ | ||
93 | |||
94 | static void n_tty_set_room(struct tty_struct *tty) | ||
95 | { | ||
96 | /* tty->read_cnt is not read locked ? */ | ||
97 | int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; | ||
98 | int old_left; | ||
99 | |||
100 | /* | ||
101 | * If we are doing input canonicalization, and there are no | ||
102 | * pending newlines, let characters through without limit, so | ||
103 | * that erase characters will be handled. Other excess | ||
104 | * characters will be beeped. | ||
105 | */ | ||
106 | if (left <= 0) | ||
107 | left = tty->icanon && !tty->canon_data; | ||
108 | old_left = tty->receive_room; | ||
109 | tty->receive_room = left; | ||
110 | |||
111 | /* Did this open up the receive buffer? We may need to flip */ | ||
112 | if (left && !old_left) | ||
113 | schedule_work(&tty->buf.work); | ||
114 | } | ||
115 | |||
116 | static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) | 84 | static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) |
117 | { | 85 | { |
118 | if (tty->read_cnt < N_TTY_BUF_SIZE) { | 86 | if (tty->read_cnt < N_TTY_BUF_SIZE) { |
@@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty) | |||
184 | 152 | ||
185 | tty->canon_head = tty->canon_data = tty->erasing = 0; | 153 | tty->canon_head = tty->canon_data = tty->erasing = 0; |
186 | memset(&tty->read_flags, 0, sizeof tty->read_flags); | 154 | memset(&tty->read_flags, 0, sizeof tty->read_flags); |
187 | n_tty_set_room(tty); | ||
188 | check_unthrottle(tty); | 155 | check_unthrottle(tty); |
189 | } | 156 | } |
190 | 157 | ||
@@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty) | |||
1360 | * calls one at a time and in order (or using flush_to_ldisc) | 1327 | * calls one at a time and in order (or using flush_to_ldisc) |
1361 | */ | 1328 | */ |
1362 | 1329 | ||
1363 | static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1330 | static unsigned int n_tty_receive_buf(struct tty_struct *tty, |
1364 | char *fp, int count) | 1331 | const unsigned char *cp, char *fp, int count) |
1365 | { | 1332 | { |
1366 | const unsigned char *p; | 1333 | const unsigned char *p; |
1367 | char *f, flags = TTY_NORMAL; | 1334 | char *f, flags = TTY_NORMAL; |
1368 | int i; | 1335 | int i; |
1369 | char buf[64]; | 1336 | char buf[64]; |
1370 | unsigned long cpuflags; | 1337 | unsigned long cpuflags; |
1338 | int left; | ||
1339 | int ret = 0; | ||
1371 | 1340 | ||
1372 | if (!tty->read_buf) | 1341 | if (!tty->read_buf) |
1373 | return; | 1342 | return 0; |
1374 | 1343 | ||
1375 | if (tty->real_raw) { | 1344 | if (tty->real_raw) { |
1376 | spin_lock_irqsave(&tty->read_lock, cpuflags); | 1345 | spin_lock_irqsave(&tty->read_lock, cpuflags); |
@@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1380 | memcpy(tty->read_buf + tty->read_head, cp, i); | 1349 | memcpy(tty->read_buf + tty->read_head, cp, i); |
1381 | tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); | 1350 | tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); |
1382 | tty->read_cnt += i; | 1351 | tty->read_cnt += i; |
1352 | ret += i; | ||
1383 | cp += i; | 1353 | cp += i; |
1384 | count -= i; | 1354 | count -= i; |
1385 | 1355 | ||
@@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1389 | memcpy(tty->read_buf + tty->read_head, cp, i); | 1359 | memcpy(tty->read_buf + tty->read_head, cp, i); |
1390 | tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); | 1360 | tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1); |
1391 | tty->read_cnt += i; | 1361 | tty->read_cnt += i; |
1362 | ret += i; | ||
1392 | spin_unlock_irqrestore(&tty->read_lock, cpuflags); | 1363 | spin_unlock_irqrestore(&tty->read_lock, cpuflags); |
1393 | } else { | 1364 | } else { |
1365 | ret = count; | ||
1394 | for (i = count, p = cp, f = fp; i; i--, p++) { | 1366 | for (i = count, p = cp, f = fp; i; i--, p++) { |
1395 | if (f) | 1367 | if (f) |
1396 | flags = *f++; | 1368 | flags = *f++; |
@@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1418 | tty->ops->flush_chars(tty); | 1390 | tty->ops->flush_chars(tty); |
1419 | } | 1391 | } |
1420 | 1392 | ||
1421 | n_tty_set_room(tty); | ||
1422 | |||
1423 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || | 1393 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || |
1424 | L_EXTPROC(tty)) { | 1394 | L_EXTPROC(tty)) { |
1425 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1395 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
@@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1432 | * mode. We don't want to throttle the driver if we're in | 1402 | * mode. We don't want to throttle the driver if we're in |
1433 | * canonical mode and don't have a newline yet! | 1403 | * canonical mode and don't have a newline yet! |
1434 | */ | 1404 | */ |
1435 | if (tty->receive_room < TTY_THRESHOLD_THROTTLE) | 1405 | left = N_TTY_BUF_SIZE - tty->read_cnt - 1; |
1406 | |||
1407 | if (left < TTY_THRESHOLD_THROTTLE) | ||
1436 | tty_throttle(tty); | 1408 | tty_throttle(tty); |
1409 | |||
1410 | return ret; | ||
1437 | } | 1411 | } |
1438 | 1412 | ||
1439 | int is_ignored(int sig) | 1413 | int is_ignored(int sig) |
@@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1477 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { | 1451 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { |
1478 | tty->raw = 1; | 1452 | tty->raw = 1; |
1479 | tty->real_raw = 1; | 1453 | tty->real_raw = 1; |
1480 | n_tty_set_room(tty); | ||
1481 | return; | 1454 | return; |
1482 | } | 1455 | } |
1483 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || | 1456 | if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || |
@@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1530 | else | 1503 | else |
1531 | tty->real_raw = 0; | 1504 | tty->real_raw = 0; |
1532 | } | 1505 | } |
1533 | n_tty_set_room(tty); | ||
1534 | /* The termios change make the tty ready for I/O */ | 1506 | /* The termios change make the tty ready for I/O */ |
1535 | wake_up_interruptible(&tty->write_wait); | 1507 | wake_up_interruptible(&tty->write_wait); |
1536 | wake_up_interruptible(&tty->read_wait); | 1508 | wake_up_interruptible(&tty->read_wait); |
@@ -1812,8 +1784,6 @@ do_it_again: | |||
1812 | retval = -ERESTARTSYS; | 1784 | retval = -ERESTARTSYS; |
1813 | break; | 1785 | break; |
1814 | } | 1786 | } |
1815 | /* FIXME: does n_tty_set_room need locking ? */ | ||
1816 | n_tty_set_room(tty); | ||
1817 | timeout = schedule_timeout(timeout); | 1787 | timeout = schedule_timeout(timeout); |
1818 | continue; | 1788 | continue; |
1819 | } | 1789 | } |
@@ -1885,10 +1855,8 @@ do_it_again: | |||
1885 | * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, | 1855 | * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, |
1886 | * we won't get any more characters. | 1856 | * we won't get any more characters. |
1887 | */ | 1857 | */ |
1888 | if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { | 1858 | if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) |
1889 | n_tty_set_room(tty); | ||
1890 | check_unthrottle(tty); | 1859 | check_unthrottle(tty); |
1891 | } | ||
1892 | 1860 | ||
1893 | if (b - buf >= minimum) | 1861 | if (b - buf >= minimum) |
1894 | break; | 1862 | break; |
@@ -1910,7 +1878,6 @@ do_it_again: | |||
1910 | } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) | 1878 | } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) |
1911 | goto do_it_again; | 1879 | goto do_it_again; |
1912 | 1880 | ||
1913 | n_tty_set_room(tty); | ||
1914 | return retval; | 1881 | return retval; |
1915 | } | 1882 | } |
1916 | 1883 | ||
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index fd0a98524d51..b1aecc7bb32a 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c | |||
@@ -364,8 +364,6 @@ struct port { | |||
364 | u8 toggle_ul; | 364 | u8 toggle_ul; |
365 | u16 token_dl; | 365 | u16 token_dl; |
366 | 366 | ||
367 | /* mutex to ensure one access patch to this port */ | ||
368 | struct mutex tty_sem; | ||
369 | wait_queue_head_t tty_wait; | 367 | wait_queue_head_t tty_wait; |
370 | struct async_icount tty_icount; | 368 | struct async_icount tty_icount; |
371 | 369 | ||
@@ -1431,8 +1429,8 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1431 | } | 1429 | } |
1432 | 1430 | ||
1433 | for (i = PORT_MDM; i < MAX_PORT; i++) { | 1431 | for (i = PORT_MDM; i < MAX_PORT; i++) { |
1434 | if (kfifo_alloc(&dc->port[i].fifo_ul, | 1432 | if (kfifo_alloc(&dc->port[i].fifo_ul, FIFO_BUFFER_SIZE_UL, |
1435 | FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { | 1433 | GFP_KERNEL)) { |
1436 | dev_err(&pdev->dev, | 1434 | dev_err(&pdev->dev, |
1437 | "Could not allocate kfifo buffer\n"); | 1435 | "Could not allocate kfifo buffer\n"); |
1438 | ret = -ENOMEM; | 1436 | ret = -ENOMEM; |
@@ -1474,7 +1472,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, | |||
1474 | struct device *tty_dev; | 1472 | struct device *tty_dev; |
1475 | struct port *port = &dc->port[i]; | 1473 | struct port *port = &dc->port[i]; |
1476 | port->dc = dc; | 1474 | port->dc = dc; |
1477 | mutex_init(&port->tty_sem); | ||
1478 | tty_port_init(&port->port); | 1475 | tty_port_init(&port->port); |
1479 | port->port.ops = &noz_tty_port_ops; | 1476 | port->port.ops = &noz_tty_port_ops; |
1480 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, | 1477 | tty_dev = tty_register_device(ntty_driver, dc->index_start + i, |
@@ -1688,13 +1685,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1688 | if (!dc || !port) | 1685 | if (!dc || !port) |
1689 | return -ENODEV; | 1686 | return -ENODEV; |
1690 | 1687 | ||
1691 | mutex_lock(&port->tty_sem); | ||
1692 | |||
1693 | if (unlikely(!port->port.count)) { | ||
1694 | DBG1(" "); | ||
1695 | goto exit; | ||
1696 | } | ||
1697 | |||
1698 | rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); | 1688 | rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); |
1699 | 1689 | ||
1700 | /* notify card */ | 1690 | /* notify card */ |
@@ -1719,7 +1709,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, | |||
1719 | spin_unlock_irqrestore(&dc->spin_mutex, flags); | 1709 | spin_unlock_irqrestore(&dc->spin_mutex, flags); |
1720 | 1710 | ||
1721 | exit: | 1711 | exit: |
1722 | mutex_unlock(&port->tty_sem); | ||
1723 | return rval; | 1712 | return rval; |
1724 | } | 1713 | } |
1725 | 1714 | ||
@@ -1738,12 +1727,9 @@ static int ntty_write_room(struct tty_struct *tty) | |||
1738 | int room = 4096; | 1727 | int room = 4096; |
1739 | const struct nozomi *dc = get_dc_by_tty(tty); | 1728 | const struct nozomi *dc = get_dc_by_tty(tty); |
1740 | 1729 | ||
1741 | if (dc) { | 1730 | if (dc) |
1742 | mutex_lock(&port->tty_sem); | 1731 | room = kfifo_avail(&port->fifo_ul); |
1743 | if (port->port.count) | 1732 | |
1744 | room = kfifo_avail(&port->fifo_ul); | ||
1745 | mutex_unlock(&port->tty_sem); | ||
1746 | } | ||
1747 | return room; | 1733 | return room; |
1748 | } | 1734 | } |
1749 | 1735 | ||
@@ -1889,11 +1875,6 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) | |||
1889 | goto exit_in_buffer; | 1875 | goto exit_in_buffer; |
1890 | } | 1876 | } |
1891 | 1877 | ||
1892 | if (unlikely(!port->port.count)) { | ||
1893 | dev_err(&dc->pdev->dev, "No tty open?\n"); | ||
1894 | goto exit_in_buffer; | ||
1895 | } | ||
1896 | |||
1897 | rval = kfifo_len(&port->fifo_ul); | 1878 | rval = kfifo_len(&port->fifo_ul); |
1898 | 1879 | ||
1899 | exit_in_buffer: | 1880 | exit_in_buffer: |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 210774726add..98b6e3bdb000 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/pty.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 3 | * |
6 | * Added support for a Unix98-style ptmx device. | 4 | * Added support for a Unix98-style ptmx device. |
@@ -295,8 +293,8 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
295 | return -ENOMEM; | 293 | return -ENOMEM; |
296 | if (!try_module_get(driver->other->owner)) { | 294 | if (!try_module_get(driver->other->owner)) { |
297 | /* This cannot in fact currently happen */ | 295 | /* This cannot in fact currently happen */ |
298 | free_tty_struct(o_tty); | 296 | retval = -ENOMEM; |
299 | return -ENOMEM; | 297 | goto err_free_tty; |
300 | } | 298 | } |
301 | initialize_tty_struct(o_tty, driver->other, idx); | 299 | initialize_tty_struct(o_tty, driver->other, idx); |
302 | 300 | ||
@@ -304,13 +302,11 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
304 | the easy way .. */ | 302 | the easy way .. */ |
305 | retval = tty_init_termios(tty); | 303 | retval = tty_init_termios(tty); |
306 | if (retval) | 304 | if (retval) |
307 | goto free_mem_out; | 305 | goto err_deinit_tty; |
308 | 306 | ||
309 | retval = tty_init_termios(o_tty); | 307 | retval = tty_init_termios(o_tty); |
310 | if (retval) { | 308 | if (retval) |
311 | tty_free_termios(tty); | 309 | goto err_free_termios; |
312 | goto free_mem_out; | ||
313 | } | ||
314 | 310 | ||
315 | /* | 311 | /* |
316 | * Everything allocated ... set up the o_tty structure. | 312 | * Everything allocated ... set up the o_tty structure. |
@@ -327,10 +323,14 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
327 | tty->count++; | 323 | tty->count++; |
328 | driver->ttys[idx] = tty; | 324 | driver->ttys[idx] = tty; |
329 | return 0; | 325 | return 0; |
330 | free_mem_out: | 326 | err_free_termios: |
327 | tty_free_termios(tty); | ||
328 | err_deinit_tty: | ||
329 | deinitialize_tty_struct(o_tty); | ||
331 | module_put(o_tty->driver->owner); | 330 | module_put(o_tty->driver->owner); |
331 | err_free_tty: | ||
332 | free_tty_struct(o_tty); | 332 | free_tty_struct(o_tty); |
333 | return -ENOMEM; | 333 | return retval; |
334 | } | 334 | } |
335 | 335 | ||
336 | static int pty_bsd_ioctl(struct tty_struct *tty, | 336 | static int pty_bsd_ioctl(struct tty_struct *tty, |
@@ -559,20 +559,19 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) | |||
559 | return -ENOMEM; | 559 | return -ENOMEM; |
560 | if (!try_module_get(driver->other->owner)) { | 560 | if (!try_module_get(driver->other->owner)) { |
561 | /* This cannot in fact currently happen */ | 561 | /* This cannot in fact currently happen */ |
562 | free_tty_struct(o_tty); | 562 | goto err_free_tty; |
563 | return -ENOMEM; | ||
564 | } | 563 | } |
565 | initialize_tty_struct(o_tty, driver->other, idx); | 564 | initialize_tty_struct(o_tty, driver->other, idx); |
566 | 565 | ||
567 | tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); | 566 | tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); |
568 | if (tty->termios == NULL) | 567 | if (tty->termios == NULL) |
569 | goto free_mem_out; | 568 | goto err_free_mem; |
570 | *tty->termios = driver->init_termios; | 569 | *tty->termios = driver->init_termios; |
571 | tty->termios_locked = tty->termios + 1; | 570 | tty->termios_locked = tty->termios + 1; |
572 | 571 | ||
573 | o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); | 572 | o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); |
574 | if (o_tty->termios == NULL) | 573 | if (o_tty->termios == NULL) |
575 | goto free_mem_out; | 574 | goto err_free_mem; |
576 | *o_tty->termios = driver->other->init_termios; | 575 | *o_tty->termios = driver->other->init_termios; |
577 | o_tty->termios_locked = o_tty->termios + 1; | 576 | o_tty->termios_locked = o_tty->termios + 1; |
578 | 577 | ||
@@ -591,11 +590,13 @@ static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) | |||
591 | tty->count++; | 590 | tty->count++; |
592 | pty_count++; | 591 | pty_count++; |
593 | return 0; | 592 | return 0; |
594 | free_mem_out: | 593 | err_free_mem: |
594 | deinitialize_tty_struct(o_tty); | ||
595 | kfree(o_tty->termios); | 595 | kfree(o_tty->termios); |
596 | kfree(tty->termios); | ||
596 | module_put(o_tty->driver->owner); | 597 | module_put(o_tty->driver->owner); |
598 | err_free_tty: | ||
597 | free_tty_struct(o_tty); | 599 | free_tty_struct(o_tty); |
598 | kfree(tty->termios); | ||
599 | return -ENOMEM; | 600 | return -ENOMEM; |
600 | } | 601 | } |
601 | 602 | ||
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 036feeb5e3f6..13043e8d37fe 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c | |||
@@ -1380,7 +1380,6 @@ static void rp_send_xchar(struct tty_struct *tty, char ch) | |||
1380 | static void rp_throttle(struct tty_struct *tty) | 1380 | static void rp_throttle(struct tty_struct *tty) |
1381 | { | 1381 | { |
1382 | struct r_port *info = tty->driver_data; | 1382 | struct r_port *info = tty->driver_data; |
1383 | CHANNEL_t *cp; | ||
1384 | 1383 | ||
1385 | #ifdef ROCKET_DEBUG_THROTTLE | 1384 | #ifdef ROCKET_DEBUG_THROTTLE |
1386 | printk(KERN_INFO "throttle %s: %d....\n", tty->name, | 1385 | printk(KERN_INFO "throttle %s: %d....\n", tty->name, |
@@ -1390,7 +1389,6 @@ static void rp_throttle(struct tty_struct *tty) | |||
1390 | if (rocket_paranoia_check(info, "rp_throttle")) | 1389 | if (rocket_paranoia_check(info, "rp_throttle")) |
1391 | return; | 1390 | return; |
1392 | 1391 | ||
1393 | cp = &info->channel; | ||
1394 | if (I_IXOFF(tty)) | 1392 | if (I_IXOFF(tty)) |
1395 | rp_send_xchar(tty, STOP_CHAR(tty)); | 1393 | rp_send_xchar(tty, STOP_CHAR(tty)); |
1396 | 1394 | ||
@@ -1400,7 +1398,6 @@ static void rp_throttle(struct tty_struct *tty) | |||
1400 | static void rp_unthrottle(struct tty_struct *tty) | 1398 | static void rp_unthrottle(struct tty_struct *tty) |
1401 | { | 1399 | { |
1402 | struct r_port *info = tty->driver_data; | 1400 | struct r_port *info = tty->driver_data; |
1403 | CHANNEL_t *cp; | ||
1404 | #ifdef ROCKET_DEBUG_THROTTLE | 1401 | #ifdef ROCKET_DEBUG_THROTTLE |
1405 | printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, | 1402 | printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, |
1406 | tty->ldisc.chars_in_buffer(tty)); | 1403 | tty->ldisc.chars_in_buffer(tty)); |
@@ -1409,7 +1406,6 @@ static void rp_unthrottle(struct tty_struct *tty) | |||
1409 | if (rocket_paranoia_check(info, "rp_throttle")) | 1406 | if (rocket_paranoia_check(info, "rp_throttle")) |
1410 | return; | 1407 | return; |
1411 | 1408 | ||
1412 | cp = &info->channel; | ||
1413 | if (I_IXOFF(tty)) | 1409 | if (I_IXOFF(tty)) |
1414 | rp_send_xchar(tty, START_CHAR(tty)); | 1410 | rp_send_xchar(tty, START_CHAR(tty)); |
1415 | 1411 | ||
@@ -1722,13 +1718,10 @@ static int rp_write_room(struct tty_struct *tty) | |||
1722 | static int rp_chars_in_buffer(struct tty_struct *tty) | 1718 | static int rp_chars_in_buffer(struct tty_struct *tty) |
1723 | { | 1719 | { |
1724 | struct r_port *info = tty->driver_data; | 1720 | struct r_port *info = tty->driver_data; |
1725 | CHANNEL_t *cp; | ||
1726 | 1721 | ||
1727 | if (rocket_paranoia_check(info, "rp_chars_in_buffer")) | 1722 | if (rocket_paranoia_check(info, "rp_chars_in_buffer")) |
1728 | return 0; | 1723 | return 0; |
1729 | 1724 | ||
1730 | cp = &info->channel; | ||
1731 | |||
1732 | #ifdef ROCKET_DEBUG_WRITE | 1725 | #ifdef ROCKET_DEBUG_WRITE |
1733 | printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); | 1726 | printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); |
1734 | #endif | 1727 | #endif |
@@ -1779,7 +1772,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1779 | { | 1772 | { |
1780 | int num_aiops, aiop, max_num_aiops, num_chan, chan; | 1773 | int num_aiops, aiop, max_num_aiops, num_chan, chan; |
1781 | unsigned int aiopio[MAX_AIOPS_PER_BOARD]; | 1774 | unsigned int aiopio[MAX_AIOPS_PER_BOARD]; |
1782 | char *str, *board_type; | ||
1783 | CONTROLLER_t *ctlp; | 1775 | CONTROLLER_t *ctlp; |
1784 | 1776 | ||
1785 | int fast_clock = 0; | 1777 | int fast_clock = 0; |
@@ -1800,7 +1792,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1800 | /* Depending on the model, set up some config variables */ | 1792 | /* Depending on the model, set up some config variables */ |
1801 | switch (dev->device) { | 1793 | switch (dev->device) { |
1802 | case PCI_DEVICE_ID_RP4QUAD: | 1794 | case PCI_DEVICE_ID_RP4QUAD: |
1803 | str = "Quadcable"; | ||
1804 | max_num_aiops = 1; | 1795 | max_num_aiops = 1; |
1805 | ports_per_aiop = 4; | 1796 | ports_per_aiop = 4; |
1806 | rocketModel[i].model = MODEL_RP4QUAD; | 1797 | rocketModel[i].model = MODEL_RP4QUAD; |
@@ -1808,42 +1799,36 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1808 | rocketModel[i].numPorts = 4; | 1799 | rocketModel[i].numPorts = 4; |
1809 | break; | 1800 | break; |
1810 | case PCI_DEVICE_ID_RP8OCTA: | 1801 | case PCI_DEVICE_ID_RP8OCTA: |
1811 | str = "Octacable"; | ||
1812 | max_num_aiops = 1; | 1802 | max_num_aiops = 1; |
1813 | rocketModel[i].model = MODEL_RP8OCTA; | 1803 | rocketModel[i].model = MODEL_RP8OCTA; |
1814 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable"); | 1804 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable"); |
1815 | rocketModel[i].numPorts = 8; | 1805 | rocketModel[i].numPorts = 8; |
1816 | break; | 1806 | break; |
1817 | case PCI_DEVICE_ID_URP8OCTA: | 1807 | case PCI_DEVICE_ID_URP8OCTA: |
1818 | str = "Octacable"; | ||
1819 | max_num_aiops = 1; | 1808 | max_num_aiops = 1; |
1820 | rocketModel[i].model = MODEL_UPCI_RP8OCTA; | 1809 | rocketModel[i].model = MODEL_UPCI_RP8OCTA; |
1821 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable"); | 1810 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable"); |
1822 | rocketModel[i].numPorts = 8; | 1811 | rocketModel[i].numPorts = 8; |
1823 | break; | 1812 | break; |
1824 | case PCI_DEVICE_ID_RP8INTF: | 1813 | case PCI_DEVICE_ID_RP8INTF: |
1825 | str = "8"; | ||
1826 | max_num_aiops = 1; | 1814 | max_num_aiops = 1; |
1827 | rocketModel[i].model = MODEL_RP8INTF; | 1815 | rocketModel[i].model = MODEL_RP8INTF; |
1828 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F"); | 1816 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F"); |
1829 | rocketModel[i].numPorts = 8; | 1817 | rocketModel[i].numPorts = 8; |
1830 | break; | 1818 | break; |
1831 | case PCI_DEVICE_ID_URP8INTF: | 1819 | case PCI_DEVICE_ID_URP8INTF: |
1832 | str = "8"; | ||
1833 | max_num_aiops = 1; | 1820 | max_num_aiops = 1; |
1834 | rocketModel[i].model = MODEL_UPCI_RP8INTF; | 1821 | rocketModel[i].model = MODEL_UPCI_RP8INTF; |
1835 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F"); | 1822 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F"); |
1836 | rocketModel[i].numPorts = 8; | 1823 | rocketModel[i].numPorts = 8; |
1837 | break; | 1824 | break; |
1838 | case PCI_DEVICE_ID_RP8J: | 1825 | case PCI_DEVICE_ID_RP8J: |
1839 | str = "8J"; | ||
1840 | max_num_aiops = 1; | 1826 | max_num_aiops = 1; |
1841 | rocketModel[i].model = MODEL_RP8J; | 1827 | rocketModel[i].model = MODEL_RP8J; |
1842 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors"); | 1828 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors"); |
1843 | rocketModel[i].numPorts = 8; | 1829 | rocketModel[i].numPorts = 8; |
1844 | break; | 1830 | break; |
1845 | case PCI_DEVICE_ID_RP4J: | 1831 | case PCI_DEVICE_ID_RP4J: |
1846 | str = "4J"; | ||
1847 | max_num_aiops = 1; | 1832 | max_num_aiops = 1; |
1848 | ports_per_aiop = 4; | 1833 | ports_per_aiop = 4; |
1849 | rocketModel[i].model = MODEL_RP4J; | 1834 | rocketModel[i].model = MODEL_RP4J; |
@@ -1851,56 +1836,48 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1851 | rocketModel[i].numPorts = 4; | 1836 | rocketModel[i].numPorts = 4; |
1852 | break; | 1837 | break; |
1853 | case PCI_DEVICE_ID_RP8SNI: | 1838 | case PCI_DEVICE_ID_RP8SNI: |
1854 | str = "8 (DB78 Custom)"; | ||
1855 | max_num_aiops = 1; | 1839 | max_num_aiops = 1; |
1856 | rocketModel[i].model = MODEL_RP8SNI; | 1840 | rocketModel[i].model = MODEL_RP8SNI; |
1857 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78"); | 1841 | strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78"); |
1858 | rocketModel[i].numPorts = 8; | 1842 | rocketModel[i].numPorts = 8; |
1859 | break; | 1843 | break; |
1860 | case PCI_DEVICE_ID_RP16SNI: | 1844 | case PCI_DEVICE_ID_RP16SNI: |
1861 | str = "16 (DB78 Custom)"; | ||
1862 | max_num_aiops = 2; | 1845 | max_num_aiops = 2; |
1863 | rocketModel[i].model = MODEL_RP16SNI; | 1846 | rocketModel[i].model = MODEL_RP16SNI; |
1864 | strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78"); | 1847 | strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78"); |
1865 | rocketModel[i].numPorts = 16; | 1848 | rocketModel[i].numPorts = 16; |
1866 | break; | 1849 | break; |
1867 | case PCI_DEVICE_ID_RP16INTF: | 1850 | case PCI_DEVICE_ID_RP16INTF: |
1868 | str = "16"; | ||
1869 | max_num_aiops = 2; | 1851 | max_num_aiops = 2; |
1870 | rocketModel[i].model = MODEL_RP16INTF; | 1852 | rocketModel[i].model = MODEL_RP16INTF; |
1871 | strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F"); | 1853 | strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F"); |
1872 | rocketModel[i].numPorts = 16; | 1854 | rocketModel[i].numPorts = 16; |
1873 | break; | 1855 | break; |
1874 | case PCI_DEVICE_ID_URP16INTF: | 1856 | case PCI_DEVICE_ID_URP16INTF: |
1875 | str = "16"; | ||
1876 | max_num_aiops = 2; | 1857 | max_num_aiops = 2; |
1877 | rocketModel[i].model = MODEL_UPCI_RP16INTF; | 1858 | rocketModel[i].model = MODEL_UPCI_RP16INTF; |
1878 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F"); | 1859 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F"); |
1879 | rocketModel[i].numPorts = 16; | 1860 | rocketModel[i].numPorts = 16; |
1880 | break; | 1861 | break; |
1881 | case PCI_DEVICE_ID_CRP16INTF: | 1862 | case PCI_DEVICE_ID_CRP16INTF: |
1882 | str = "16"; | ||
1883 | max_num_aiops = 2; | 1863 | max_num_aiops = 2; |
1884 | rocketModel[i].model = MODEL_CPCI_RP16INTF; | 1864 | rocketModel[i].model = MODEL_CPCI_RP16INTF; |
1885 | strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F"); | 1865 | strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F"); |
1886 | rocketModel[i].numPorts = 16; | 1866 | rocketModel[i].numPorts = 16; |
1887 | break; | 1867 | break; |
1888 | case PCI_DEVICE_ID_RP32INTF: | 1868 | case PCI_DEVICE_ID_RP32INTF: |
1889 | str = "32"; | ||
1890 | max_num_aiops = 4; | 1869 | max_num_aiops = 4; |
1891 | rocketModel[i].model = MODEL_RP32INTF; | 1870 | rocketModel[i].model = MODEL_RP32INTF; |
1892 | strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F"); | 1871 | strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F"); |
1893 | rocketModel[i].numPorts = 32; | 1872 | rocketModel[i].numPorts = 32; |
1894 | break; | 1873 | break; |
1895 | case PCI_DEVICE_ID_URP32INTF: | 1874 | case PCI_DEVICE_ID_URP32INTF: |
1896 | str = "32"; | ||
1897 | max_num_aiops = 4; | 1875 | max_num_aiops = 4; |
1898 | rocketModel[i].model = MODEL_UPCI_RP32INTF; | 1876 | rocketModel[i].model = MODEL_UPCI_RP32INTF; |
1899 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F"); | 1877 | strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F"); |
1900 | rocketModel[i].numPorts = 32; | 1878 | rocketModel[i].numPorts = 32; |
1901 | break; | 1879 | break; |
1902 | case PCI_DEVICE_ID_RPP4: | 1880 | case PCI_DEVICE_ID_RPP4: |
1903 | str = "Plus Quadcable"; | ||
1904 | max_num_aiops = 1; | 1881 | max_num_aiops = 1; |
1905 | ports_per_aiop = 4; | 1882 | ports_per_aiop = 4; |
1906 | altChanRingIndicator++; | 1883 | altChanRingIndicator++; |
@@ -1910,7 +1887,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1910 | rocketModel[i].numPorts = 4; | 1887 | rocketModel[i].numPorts = 4; |
1911 | break; | 1888 | break; |
1912 | case PCI_DEVICE_ID_RPP8: | 1889 | case PCI_DEVICE_ID_RPP8: |
1913 | str = "Plus Octacable"; | ||
1914 | max_num_aiops = 2; | 1890 | max_num_aiops = 2; |
1915 | ports_per_aiop = 4; | 1891 | ports_per_aiop = 4; |
1916 | altChanRingIndicator++; | 1892 | altChanRingIndicator++; |
@@ -1920,7 +1896,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1920 | rocketModel[i].numPorts = 8; | 1896 | rocketModel[i].numPorts = 8; |
1921 | break; | 1897 | break; |
1922 | case PCI_DEVICE_ID_RP2_232: | 1898 | case PCI_DEVICE_ID_RP2_232: |
1923 | str = "Plus 2 (RS-232)"; | ||
1924 | max_num_aiops = 1; | 1899 | max_num_aiops = 1; |
1925 | ports_per_aiop = 2; | 1900 | ports_per_aiop = 2; |
1926 | altChanRingIndicator++; | 1901 | altChanRingIndicator++; |
@@ -1930,7 +1905,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1930 | rocketModel[i].numPorts = 2; | 1905 | rocketModel[i].numPorts = 2; |
1931 | break; | 1906 | break; |
1932 | case PCI_DEVICE_ID_RP2_422: | 1907 | case PCI_DEVICE_ID_RP2_422: |
1933 | str = "Plus 2 (RS-422)"; | ||
1934 | max_num_aiops = 1; | 1908 | max_num_aiops = 1; |
1935 | ports_per_aiop = 2; | 1909 | ports_per_aiop = 2; |
1936 | altChanRingIndicator++; | 1910 | altChanRingIndicator++; |
@@ -1943,7 +1917,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1943 | 1917 | ||
1944 | max_num_aiops = 1; | 1918 | max_num_aiops = 1; |
1945 | ports_per_aiop = 6; | 1919 | ports_per_aiop = 6; |
1946 | str = "6-port"; | ||
1947 | 1920 | ||
1948 | /* If revision is 1, the rocketmodem flash must be loaded. | 1921 | /* If revision is 1, the rocketmodem flash must be loaded. |
1949 | * If it is 2 it is a "socketed" version. */ | 1922 | * If it is 2 it is a "socketed" version. */ |
@@ -1961,7 +1934,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1961 | case PCI_DEVICE_ID_RP4M: | 1934 | case PCI_DEVICE_ID_RP4M: |
1962 | max_num_aiops = 1; | 1935 | max_num_aiops = 1; |
1963 | ports_per_aiop = 4; | 1936 | ports_per_aiop = 4; |
1964 | str = "4-port"; | ||
1965 | if (dev->revision == 1) { | 1937 | if (dev->revision == 1) { |
1966 | rcktpt_type[i] = ROCKET_TYPE_MODEMII; | 1938 | rcktpt_type[i] = ROCKET_TYPE_MODEMII; |
1967 | rocketModel[i].loadrm2 = 1; | 1939 | rocketModel[i].loadrm2 = 1; |
@@ -1974,7 +1946,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
1974 | rocketModel[i].numPorts = 4; | 1946 | rocketModel[i].numPorts = 4; |
1975 | break; | 1947 | break; |
1976 | default: | 1948 | default: |
1977 | str = "(unknown/unsupported)"; | ||
1978 | max_num_aiops = 0; | 1949 | max_num_aiops = 0; |
1979 | break; | 1950 | break; |
1980 | } | 1951 | } |
@@ -2000,14 +1971,12 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
2000 | if (! | 1971 | if (! |
2001 | (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) & | 1972 | (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) & |
2002 | PCI_GPIO_CTRL_8PORT)) { | 1973 | PCI_GPIO_CTRL_8PORT)) { |
2003 | str = "Quadcable"; | ||
2004 | ports_per_aiop = 4; | 1974 | ports_per_aiop = 4; |
2005 | rocketModel[i].numPorts = 4; | 1975 | rocketModel[i].numPorts = 4; |
2006 | } | 1976 | } |
2007 | } | 1977 | } |
2008 | break; | 1978 | break; |
2009 | case PCI_DEVICE_ID_UPCI_RM3_8PORT: | 1979 | case PCI_DEVICE_ID_UPCI_RM3_8PORT: |
2010 | str = "8 ports"; | ||
2011 | max_num_aiops = 1; | 1980 | max_num_aiops = 1; |
2012 | rocketModel[i].model = MODEL_UPCI_RM3_8PORT; | 1981 | rocketModel[i].model = MODEL_UPCI_RM3_8PORT; |
2013 | strcpy(rocketModel[i].modelString, "RocketModem III 8 port"); | 1982 | strcpy(rocketModel[i].modelString, "RocketModem III 8 port"); |
@@ -2018,7 +1987,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
2018 | rcktpt_type[i] = ROCKET_TYPE_MODEMIII; | 1987 | rcktpt_type[i] = ROCKET_TYPE_MODEMIII; |
2019 | break; | 1988 | break; |
2020 | case PCI_DEVICE_ID_UPCI_RM3_4PORT: | 1989 | case PCI_DEVICE_ID_UPCI_RM3_4PORT: |
2021 | str = "4 ports"; | ||
2022 | max_num_aiops = 1; | 1990 | max_num_aiops = 1; |
2023 | rocketModel[i].model = MODEL_UPCI_RM3_4PORT; | 1991 | rocketModel[i].model = MODEL_UPCI_RM3_4PORT; |
2024 | strcpy(rocketModel[i].modelString, "RocketModem III 4 port"); | 1992 | strcpy(rocketModel[i].modelString, "RocketModem III 4 port"); |
@@ -2032,21 +2000,6 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
2032 | break; | 2000 | break; |
2033 | } | 2001 | } |
2034 | 2002 | ||
2035 | switch (rcktpt_type[i]) { | ||
2036 | case ROCKET_TYPE_MODEM: | ||
2037 | board_type = "RocketModem"; | ||
2038 | break; | ||
2039 | case ROCKET_TYPE_MODEMII: | ||
2040 | board_type = "RocketModem II"; | ||
2041 | break; | ||
2042 | case ROCKET_TYPE_MODEMIII: | ||
2043 | board_type = "RocketModem III"; | ||
2044 | break; | ||
2045 | default: | ||
2046 | board_type = "RocketPort"; | ||
2047 | break; | ||
2048 | } | ||
2049 | |||
2050 | if (fast_clock) { | 2003 | if (fast_clock) { |
2051 | sClockPrescale = 0x12; /* mod 2 (divide by 3) */ | 2004 | sClockPrescale = 0x12; /* mod 2 (divide by 3) */ |
2052 | rp_baud_base[i] = 921600; | 2005 | rp_baud_base[i] = 921600; |
diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c index d89aa38c5cf0..1b37626e8f13 100644 --- a/drivers/tty/serial/21285.c +++ b/drivers/tty/serial/21285.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/21285.c | ||
3 | * | ||
4 | * Driver for the serial port on the 21285 StrongArm-110 core logic chip. | 2 | * Driver for the serial port on the 21285 StrongArm-110 core logic chip. |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c | 4 | * Based on drivers/char/serial.c |
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 6611535f4440..b40f7b90c81d 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/8250.c | ||
3 | * | ||
4 | * Driver for 8250/16550-type serial ports | 2 | * Driver for 8250/16550-type serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
@@ -273,7 +271,7 @@ static const struct serial8250_config uart_config[] = { | |||
273 | .fifo_size = 32, | 271 | .fifo_size = 32, |
274 | .tx_loadsz = 32, | 272 | .tx_loadsz = 32, |
275 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 273 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
276 | .flags = UART_CAP_FIFO | UART_CAP_UUE, | 274 | .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE, |
277 | }, | 275 | }, |
278 | [PORT_RM9000] = { | 276 | [PORT_RM9000] = { |
279 | .name = "RM9000", | 277 | .name = "RM9000", |
@@ -303,6 +301,14 @@ static const struct serial8250_config uart_config[] = { | |||
303 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 301 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
304 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | 302 | .flags = UART_CAP_FIFO | UART_CAP_AFE, |
305 | }, | 303 | }, |
304 | [PORT_TEGRA] = { | ||
305 | .name = "Tegra", | ||
306 | .fifo_size = 32, | ||
307 | .tx_loadsz = 8, | ||
308 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 | | ||
309 | UART_FCR_T_TRIG_01, | ||
310 | .flags = UART_CAP_FIFO | UART_CAP_RTOIE, | ||
311 | }, | ||
306 | }; | 312 | }; |
307 | 313 | ||
308 | #if defined(CONFIG_MIPS_ALCHEMY) | 314 | #if defined(CONFIG_MIPS_ALCHEMY) |
@@ -1427,6 +1433,27 @@ static void serial8250_enable_ms(struct uart_port *port) | |||
1427 | serial_out(up, UART_IER, up->ier); | 1433 | serial_out(up, UART_IER, up->ier); |
1428 | } | 1434 | } |
1429 | 1435 | ||
1436 | /* | ||
1437 | * Clear the Tegra rx fifo after a break | ||
1438 | * | ||
1439 | * FIXME: This needs to become a port specific callback once we have a | ||
1440 | * framework for this | ||
1441 | */ | ||
1442 | static void clear_rx_fifo(struct uart_8250_port *up) | ||
1443 | { | ||
1444 | unsigned int status, tmout = 10000; | ||
1445 | do { | ||
1446 | status = serial_in(up, UART_LSR); | ||
1447 | if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) | ||
1448 | status = serial_in(up, UART_RX); | ||
1449 | else | ||
1450 | break; | ||
1451 | if (--tmout == 0) | ||
1452 | break; | ||
1453 | udelay(1); | ||
1454 | } while (1); | ||
1455 | } | ||
1456 | |||
1430 | static void | 1457 | static void |
1431 | receive_chars(struct uart_8250_port *up, unsigned int *status) | 1458 | receive_chars(struct uart_8250_port *up, unsigned int *status) |
1432 | { | 1459 | { |
@@ -1462,6 +1489,13 @@ receive_chars(struct uart_8250_port *up, unsigned int *status) | |||
1462 | lsr &= ~(UART_LSR_FE | UART_LSR_PE); | 1489 | lsr &= ~(UART_LSR_FE | UART_LSR_PE); |
1463 | up->port.icount.brk++; | 1490 | up->port.icount.brk++; |
1464 | /* | 1491 | /* |
1492 | * If tegra port then clear the rx fifo to | ||
1493 | * accept another break/character. | ||
1494 | */ | ||
1495 | if (up->port.type == PORT_TEGRA) | ||
1496 | clear_rx_fifo(up); | ||
1497 | |||
1498 | /* | ||
1465 | * We do the SysRQ and SAK checking | 1499 | * We do the SysRQ and SAK checking |
1466 | * here because otherwise the break | 1500 | * here because otherwise the break |
1467 | * may get masked by ignore_status_mask | 1501 | * may get masked by ignore_status_mask |
@@ -2405,7 +2439,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2405 | UART_ENABLE_MS(&up->port, termios->c_cflag)) | 2439 | UART_ENABLE_MS(&up->port, termios->c_cflag)) |
2406 | up->ier |= UART_IER_MSI; | 2440 | up->ier |= UART_IER_MSI; |
2407 | if (up->capabilities & UART_CAP_UUE) | 2441 | if (up->capabilities & UART_CAP_UUE) |
2408 | up->ier |= UART_IER_UUE | UART_IER_RTOIE; | 2442 | up->ier |= UART_IER_UUE; |
2443 | if (up->capabilities & UART_CAP_RTOIE) | ||
2444 | up->ier |= UART_IER_RTOIE; | ||
2409 | 2445 | ||
2410 | serial_out(up, UART_IER, up->ier); | 2446 | serial_out(up, UART_IER, up->ier); |
2411 | 2447 | ||
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250.h index 6e19ea3e48d5..6edf4a6a22d4 100644 --- a/drivers/tty/serial/8250.h +++ b/drivers/tty/serial/8250.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/8250.h | ||
3 | * | ||
4 | * Driver for 8250/16550-type serial ports | 2 | * Driver for 8250/16550-type serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
@@ -44,6 +42,7 @@ struct serial8250_config { | |||
44 | #define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ | 42 | #define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */ |
45 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ | 43 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ |
46 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ | 44 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ |
45 | #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ | ||
47 | 46 | ||
48 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ | 47 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ |
49 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ | 48 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ |
diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250_accent.c index 9c10262f2469..34b51c651192 100644 --- a/drivers/tty/serial/8250_accent.c +++ b/drivers/tty/serial/8250_accent.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_accent.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | 2 | * Copyright (C) 2005 Russell King. |
5 | * Data taken from include/asm-i386/serial.h | 3 | * Data taken from include/asm-i386/serial.h |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250_boca.c index 3bfe0f7b26fb..d125dc107985 100644 --- a/drivers/tty/serial/8250_boca.c +++ b/drivers/tty/serial/8250_boca.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_boca.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | 2 | * Copyright (C) 2005 Russell King. |
5 | * Data taken from include/asm-i386/serial.h | 3 | * Data taken from include/asm-i386/serial.h |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250_exar_st16c554.c index 567143ace159..bf53aabf9b5e 100644 --- a/drivers/tty/serial/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250_exar_st16c554.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_exar.c | ||
3 | * | ||
4 | * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com > | 2 | * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com > |
5 | * Based on 8250_boca. | 3 | * Based on 8250_boca. |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250_fourport.c index 6375d68b7913..be1582609626 100644 --- a/drivers/tty/serial/8250_fourport.c +++ b/drivers/tty/serial/8250_fourport.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_fourport.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | 2 | * Copyright (C) 2005 Russell King. |
5 | * Data taken from include/asm-i386/serial.h | 3 | * Data taken from include/asm-i386/serial.h |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250_hub6.c index 7609150e7d5e..a5c778e83de0 100644 --- a/drivers/tty/serial/8250_hub6.c +++ b/drivers/tty/serial/8250_hub6.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_hub6.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | 2 | * Copyright (C) 2005 Russell King. |
5 | * Data taken from include/asm-i386/serial.h | 3 | * Data taken from include/asm-i386/serial.h |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250_mca.c index d10be944ad44..d20abf04541e 100644 --- a/drivers/tty/serial/8250_mca.c +++ b/drivers/tty/serial/8250_mca.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/8250_mca.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Russell King. | 2 | * Copyright (C) 2005 Russell King. |
5 | * Data taken from include/asm-i386/serial.h | 3 | * Data taken from include/asm-i386/serial.h |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 738cec9807d3..4b4968a294b2 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/8250_pci.c | ||
3 | * | ||
4 | * Probe module for 8250/16550-type PCI serial ports. | 2 | * Probe module for 8250/16550-type PCI serial ports. |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
@@ -973,6 +971,14 @@ ce4100_serial_setup(struct serial_private *priv, | |||
973 | return ret; | 971 | return ret; |
974 | } | 972 | } |
975 | 973 | ||
974 | static int | ||
975 | pci_omegapci_setup(struct serial_private *priv, | ||
976 | struct pciserial_board *board, | ||
977 | struct uart_port *port, int idx) | ||
978 | { | ||
979 | return setup_port(priv, port, 2, idx * 8, 0); | ||
980 | } | ||
981 | |||
976 | static int skip_tx_en_setup(struct serial_private *priv, | 982 | static int skip_tx_en_setup(struct serial_private *priv, |
977 | const struct pciserial_board *board, | 983 | const struct pciserial_board *board, |
978 | struct uart_port *port, int idx) | 984 | struct uart_port *port, int idx) |
@@ -1012,6 +1018,8 @@ static int skip_tx_en_setup(struct serial_private *priv, | |||
1012 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 | 1018 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 |
1013 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 | 1019 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 |
1014 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 | 1020 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 |
1021 | #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 | ||
1022 | #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 | ||
1015 | 1023 | ||
1016 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 1024 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
1017 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 | 1025 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
@@ -1412,7 +1420,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1412 | .setup = pci_default_setup, | 1420 | .setup = pci_default_setup, |
1413 | }, | 1421 | }, |
1414 | /* | 1422 | /* |
1415 | * For Oxford Semiconductor and Mainpine | 1423 | * For Oxford Semiconductor Tornado based devices |
1416 | */ | 1424 | */ |
1417 | { | 1425 | { |
1418 | .vendor = PCI_VENDOR_ID_OXSEMI, | 1426 | .vendor = PCI_VENDOR_ID_OXSEMI, |
@@ -1430,6 +1438,24 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1430 | .init = pci_oxsemi_tornado_init, | 1438 | .init = pci_oxsemi_tornado_init, |
1431 | .setup = pci_default_setup, | 1439 | .setup = pci_default_setup, |
1432 | }, | 1440 | }, |
1441 | { | ||
1442 | .vendor = PCI_VENDOR_ID_DIGI, | ||
1443 | .device = PCIE_DEVICE_ID_NEO_2_OX_IBM, | ||
1444 | .subvendor = PCI_SUBVENDOR_ID_IBM, | ||
1445 | .subdevice = PCI_ANY_ID, | ||
1446 | .init = pci_oxsemi_tornado_init, | ||
1447 | .setup = pci_default_setup, | ||
1448 | }, | ||
1449 | /* | ||
1450 | * Cronyx Omega PCI (PLX-chip based) | ||
1451 | */ | ||
1452 | { | ||
1453 | .vendor = PCI_VENDOR_ID_PLX, | ||
1454 | .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA, | ||
1455 | .subvendor = PCI_ANY_ID, | ||
1456 | .subdevice = PCI_ANY_ID, | ||
1457 | .setup = pci_omegapci_setup, | ||
1458 | }, | ||
1433 | /* | 1459 | /* |
1434 | * Default "match everything" terminator entry | 1460 | * Default "match everything" terminator entry |
1435 | */ | 1461 | */ |
@@ -1617,6 +1643,7 @@ enum pci_board_num_t { | |||
1617 | pbn_ADDIDATA_PCIe_4_3906250, | 1643 | pbn_ADDIDATA_PCIe_4_3906250, |
1618 | pbn_ADDIDATA_PCIe_8_3906250, | 1644 | pbn_ADDIDATA_PCIe_8_3906250, |
1619 | pbn_ce4100_1_115200, | 1645 | pbn_ce4100_1_115200, |
1646 | pbn_omegapci, | ||
1620 | }; | 1647 | }; |
1621 | 1648 | ||
1622 | /* | 1649 | /* |
@@ -2312,6 +2339,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { | |||
2312 | .base_baud = 921600, | 2339 | .base_baud = 921600, |
2313 | .reg_shift = 2, | 2340 | .reg_shift = 2, |
2314 | }, | 2341 | }, |
2342 | [pbn_omegapci] = { | ||
2343 | .flags = FL_BASE0, | ||
2344 | .num_ports = 8, | ||
2345 | .base_baud = 115200, | ||
2346 | .uart_offset = 0x200, | ||
2347 | }, | ||
2315 | }; | 2348 | }; |
2316 | 2349 | ||
2317 | static const struct pci_device_id softmodem_blacklist[] = { | 2350 | static const struct pci_device_id softmodem_blacklist[] = { |
@@ -3075,6 +3108,14 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3075 | { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ | 3108 | { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ |
3076 | PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, | 3109 | PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, |
3077 | pbn_oxsemi_8_4000000 }, | 3110 | pbn_oxsemi_8_4000000 }, |
3111 | |||
3112 | /* | ||
3113 | * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado | ||
3114 | */ | ||
3115 | { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, | ||
3116 | PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, | ||
3117 | pbn_oxsemi_2_4000000 }, | ||
3118 | |||
3078 | /* | 3119 | /* |
3079 | * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, | 3120 | * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, |
3080 | * from skokodyn@yahoo.com | 3121 | * from skokodyn@yahoo.com |
@@ -3801,6 +3842,12 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3801 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 3842 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
3802 | pbn_ce4100_1_115200 }, | 3843 | pbn_ce4100_1_115200 }, |
3803 | 3844 | ||
3845 | /* | ||
3846 | * Cronyx Omega PCI | ||
3847 | */ | ||
3848 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA, | ||
3849 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
3850 | pbn_omegapci }, | ||
3804 | 3851 | ||
3805 | /* | 3852 | /* |
3806 | * These entries match devices with class COMMUNICATION_SERIAL, | 3853 | * These entries match devices with class COMMUNICATION_SERIAL, |
diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250_pnp.c index 4822cb50cd0f..fc301f6722e1 100644 --- a/drivers/tty/serial/8250_pnp.c +++ b/drivers/tty/serial/8250_pnp.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/8250_pnp.c | ||
3 | * | ||
4 | * Probe module for 8250/16550-type ISAPNP serial ports. | 2 | * Probe module for 8250/16550-type ISAPNP serial ports. |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 80484af781e1..636144cea932 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -537,7 +537,7 @@ config SERIAL_S3C6400 | |||
537 | 537 | ||
538 | config SERIAL_S5PV210 | 538 | config SERIAL_S5PV210 |
539 | tristate "Samsung S5PV210 Serial port support" | 539 | tristate "Samsung S5PV210 Serial port support" |
540 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_EXYNOS4210) | 540 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210) |
541 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210) | 541 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210) |
542 | default y | 542 | default y |
543 | help | 543 | help |
@@ -1391,6 +1391,14 @@ config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE | |||
1391 | help | 1391 | help |
1392 | Support for Console on the NWP serial ports. | 1392 | Support for Console on the NWP serial ports. |
1393 | 1393 | ||
1394 | config SERIAL_LANTIQ | ||
1395 | bool "Lantiq serial driver" | ||
1396 | depends on LANTIQ | ||
1397 | select SERIAL_CORE | ||
1398 | select SERIAL_CORE_CONSOLE | ||
1399 | help | ||
1400 | Support for console and UART on Lantiq SoCs. | ||
1401 | |||
1394 | config SERIAL_QE | 1402 | config SERIAL_QE |
1395 | tristate "Freescale QUICC Engine serial port support" | 1403 | tristate "Freescale QUICC Engine serial port support" |
1396 | depends on QUICC_ENGINE | 1404 | depends on QUICC_ENGINE |
@@ -1577,7 +1585,7 @@ config SERIAL_IFX6X60 | |||
1577 | Support for the IFX6x60 modem devices on Intel MID platforms. | 1585 | Support for the IFX6x60 modem devices on Intel MID platforms. |
1578 | 1586 | ||
1579 | config SERIAL_PCH_UART | 1587 | config SERIAL_PCH_UART |
1580 | tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH" | 1588 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART" |
1581 | depends on PCI | 1589 | depends on PCI |
1582 | select SERIAL_CORE | 1590 | select SERIAL_CORE |
1583 | help | 1591 | help |
@@ -1585,10 +1593,12 @@ config SERIAL_PCH_UART | |||
1585 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 1593 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
1586 | Enabling PCH_DMA, this PCH UART works as DMA mode. | 1594 | Enabling PCH_DMA, this PCH UART works as DMA mode. |
1587 | 1595 | ||
1588 | This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/ | 1596 | This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ |
1589 | Output Hub) which is for IVI(In-Vehicle Infotainment) use. | 1597 | Output Hub), ML7213 and ML7223. |
1590 | ML7213 is companion chip for Intel Atom E6xx series. | 1598 | ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is |
1591 | ML7213 is completely compatible for Intel EG20T PCH. | 1599 | for MP(Media Phone) use. |
1600 | ML7213/ML7223 is companion chip for Intel Atom E6xx series. | ||
1601 | ML7213/ML7223 is completely compatible for Intel EG20T PCH. | ||
1592 | 1602 | ||
1593 | config SERIAL_MSM_SMD | 1603 | config SERIAL_MSM_SMD |
1594 | bool "Enable tty device interface for some SMD ports" | 1604 | bool "Enable tty device interface for some SMD ports" |
@@ -1612,4 +1622,17 @@ config SERIAL_MXS_AUART_CONSOLE | |||
1612 | help | 1622 | help |
1613 | Enable a MXS AUART port to be the system console. | 1623 | Enable a MXS AUART port to be the system console. |
1614 | 1624 | ||
1625 | config SERIAL_XILINX_PS_UART | ||
1626 | tristate "Xilinx PS UART support" | ||
1627 | select SERIAL_CORE | ||
1628 | help | ||
1629 | This driver supports the Xilinx PS UART port. | ||
1630 | |||
1631 | config SERIAL_XILINX_PS_UART_CONSOLE | ||
1632 | bool "Xilinx PS UART console support" | ||
1633 | depends on SERIAL_XILINX_PS_UART=y | ||
1634 | select SERIAL_CORE_CONSOLE | ||
1635 | help | ||
1636 | Enable a Xilinx PS UART port to be the system console. | ||
1637 | |||
1615 | endmenu | 1638 | endmenu |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index fee0690ef8e3..cb2628fee4c7 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -94,3 +94,5 @@ 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 | 95 | obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o |
96 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o | 96 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o |
97 | obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o | ||
98 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o | ||
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 6d5b036ac783..50bc5a5ac653 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -540,11 +540,14 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
540 | int i = pdev->id; | 540 | int i = pdev->id; |
541 | int ret; | 541 | int ret; |
542 | 542 | ||
543 | /* -1 emphasizes that the platform must have one port, no .N suffix */ | 543 | /* if id is -1 scan for a free id and use that one */ |
544 | if (i == -1) | 544 | if (i == -1) { |
545 | i = 0; | 545 | for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) |
546 | if (altera_uart_ports[i].port.mapbase == 0) | ||
547 | break; | ||
548 | } | ||
546 | 549 | ||
547 | if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) | 550 | if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS) |
548 | return -EINVAL; | 551 | return -EINVAL; |
549 | 552 | ||
550 | port = &altera_uart_ports[i].port; | 553 | port = &altera_uart_ports[i].port; |
@@ -587,6 +590,8 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
587 | port->ops = &altera_uart_ops; | 590 | port->ops = &altera_uart_ops; |
588 | port->flags = UPF_BOOT_AUTOCONF; | 591 | port->flags = UPF_BOOT_AUTOCONF; |
589 | 592 | ||
593 | dev_set_drvdata(&pdev->dev, port); | ||
594 | |||
590 | uart_add_one_port(&altera_uart_driver, port); | 595 | uart_add_one_port(&altera_uart_driver, port); |
591 | 596 | ||
592 | return 0; | 597 | return 0; |
@@ -594,14 +599,13 @@ static int __devinit altera_uart_probe(struct platform_device *pdev) | |||
594 | 599 | ||
595 | static int __devexit altera_uart_remove(struct platform_device *pdev) | 600 | static int __devexit altera_uart_remove(struct platform_device *pdev) |
596 | { | 601 | { |
597 | struct uart_port *port; | 602 | struct uart_port *port = dev_get_drvdata(&pdev->dev); |
598 | int i = pdev->id; | ||
599 | 603 | ||
600 | if (i == -1) | 604 | if (port) { |
601 | i = 0; | 605 | uart_remove_one_port(&altera_uart_driver, port); |
602 | 606 | dev_set_drvdata(&pdev->dev, NULL); | |
603 | port = &altera_uart_ports[i].port; | 607 | port->mapbase = 0; |
604 | uart_remove_one_port(&altera_uart_driver, port); | 608 | } |
605 | 609 | ||
606 | return 0; | 610 | return 0; |
607 | } | 611 | } |
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index d742dd2c525c..c0d10c4ddb73 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/amba.c | ||
3 | * | ||
4 | * Driver for AMBA serial ports | 2 | * Driver for AMBA serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 6deee4e546be..8dc0541feecc 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/amba.c | ||
3 | * | ||
4 | * Driver for AMBA serial ports | 2 | * Driver for AMBA serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index f119d1761106..652bdac8ce8e 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/atmel_serial.c | ||
3 | * | ||
4 | * Driver for Atmel AT91 / AT32 Serial ports | 2 | * Driver for Atmel AT91 / AT32 Serial ports |
5 | * Copyright (C) 2003 Rick Bronson | 3 | * Copyright (C) 2003 Rick Bronson |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index c3ec0a61d859..891d194ae754 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c | |||
@@ -296,8 +296,7 @@ static int sport_startup(struct uart_port *port) | |||
296 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | | 296 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
297 | IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) { | 297 | IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) { |
298 | up->cts_pin = -1; | 298 | up->cts_pin = -1; |
299 | dev_info(port->dev, "Unable to attach BlackFin UART \ | 299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); |
300 | over SPORT CTS interrupt. So, disable it.\n"); | ||
301 | } | 300 | } |
302 | } | 301 | } |
303 | if (up->rts_pin >= 0) | 302 | if (up->rts_pin >= 0) |
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index b6acd19b458e..e6c3dbd781d6 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/clps711x.c | ||
3 | * | ||
4 | * Driver for CLPS711x serial ports | 2 | * Driver for CLPS711x serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h index b754dcf0fda5..cf34d26ff6cd 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart.h | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports | 2 | * Driver for CPM (SCC/SMC) serial ports |
5 | * | 3 | * |
6 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 4 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index a9a6a5fd169e..9488da74d4f7 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart.c | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports; core driver | 2 | * Driver for CPM (SCC/SMC) serial ports; core driver |
5 | * | 3 | * |
6 | * Based on arch/ppc/cpm2_io/uart.c by Dan Malek | 4 | * Based on arch/ppc/cpm2_io/uart.c by Dan Malek |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c index 3fc1d66e32c6..18f79575894a 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart.c | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions | 2 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions |
5 | * | 3 | * |
6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) | 4 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h index 10eecd6af6d4..60c7e94cde1e 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart/cpm_uart_cpm1.h | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports | 2 | * Driver for CPM (SCC/SMC) serial ports |
5 | * | 3 | * |
6 | * definitions for cpm1 | 4 | * definitions for cpm1 |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c index 814ac006393f..a4927e66e741 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart_cpm2.c | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions | 2 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions |
5 | * | 3 | * |
6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) | 4 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h index 7194c63dcf5f..51e651a69938 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm2.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/cpm_uart/cpm_uart_cpm2.h | ||
3 | * | ||
4 | * Driver for CPM (SCC/SMC) serial ports | 2 | * Driver for CPM (SCC/SMC) serial ports |
5 | * | 3 | * |
6 | * definitions for cpm2 | 4 | * definitions for cpm2 |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 8ee5a41d340d..5315525220fb 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/tty.h> | 41 | #include <linux/tty.h> |
42 | #include <linux/device.h> | 42 | #include <linux/device.h> |
43 | #include <linux/spi/spi.h> | 43 | #include <linux/spi/spi.h> |
44 | #include <linux/tty.h> | ||
45 | #include <linux/kfifo.h> | 44 | #include <linux/kfifo.h> |
46 | #include <linux/tty_flip.h> | 45 | #include <linux/tty_flip.h> |
47 | #include <linux/timer.h> | 46 | #include <linux/timer.h> |
@@ -56,7 +55,6 @@ | |||
56 | #include <linux/sched.h> | 55 | #include <linux/sched.h> |
57 | #include <linux/time.h> | 56 | #include <linux/time.h> |
58 | #include <linux/wait.h> | 57 | #include <linux/wait.h> |
59 | #include <linux/tty.h> | ||
60 | #include <linux/pm.h> | 58 | #include <linux/pm.h> |
61 | #include <linux/pm_runtime.h> | 59 | #include <linux/pm_runtime.h> |
62 | #include <linux/spi/ifx_modem.h> | 60 | #include <linux/spi/ifx_modem.h> |
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 62df72d9f0aa..a54473123e0a 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/imx.c | ||
3 | * | ||
4 | * Driver for Motorola IMX serial ports | 2 | * Driver for Motorola IMX serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c new file mode 100644 index 000000000000..58cf279ed879 --- /dev/null +++ b/drivers/tty/serial/lantiq.c | |||
@@ -0,0 +1,756 @@ | |||
1 | /* | ||
2 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published | ||
6 | * by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | * | ||
17 | * Copyright (C) 2004 Infineon IFAP DC COM CPE | ||
18 | * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> | ||
19 | * Copyright (C) 2007 John Crispin <blogic@openwrt.org> | ||
20 | * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com> | ||
21 | */ | ||
22 | |||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/sysrq.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/tty.h> | ||
31 | #include <linux/tty_flip.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/io.h> | ||
36 | #include <linux/clk.h> | ||
37 | |||
38 | #include <lantiq_soc.h> | ||
39 | |||
40 | #define PORT_LTQ_ASC 111 | ||
41 | #define MAXPORTS 2 | ||
42 | #define UART_DUMMY_UER_RX 1 | ||
43 | #define DRVNAME "ltq_asc" | ||
44 | #ifdef __BIG_ENDIAN | ||
45 | #define LTQ_ASC_TBUF (0x0020 + 3) | ||
46 | #define LTQ_ASC_RBUF (0x0024 + 3) | ||
47 | #else | ||
48 | #define LTQ_ASC_TBUF 0x0020 | ||
49 | #define LTQ_ASC_RBUF 0x0024 | ||
50 | #endif | ||
51 | #define LTQ_ASC_FSTAT 0x0048 | ||
52 | #define LTQ_ASC_WHBSTATE 0x0018 | ||
53 | #define LTQ_ASC_STATE 0x0014 | ||
54 | #define LTQ_ASC_IRNCR 0x00F8 | ||
55 | #define LTQ_ASC_CLC 0x0000 | ||
56 | #define LTQ_ASC_ID 0x0008 | ||
57 | #define LTQ_ASC_PISEL 0x0004 | ||
58 | #define LTQ_ASC_TXFCON 0x0044 | ||
59 | #define LTQ_ASC_RXFCON 0x0040 | ||
60 | #define LTQ_ASC_CON 0x0010 | ||
61 | #define LTQ_ASC_BG 0x0050 | ||
62 | #define LTQ_ASC_IRNREN 0x00F4 | ||
63 | |||
64 | #define ASC_IRNREN_TX 0x1 | ||
65 | #define ASC_IRNREN_RX 0x2 | ||
66 | #define ASC_IRNREN_ERR 0x4 | ||
67 | #define ASC_IRNREN_TX_BUF 0x8 | ||
68 | #define ASC_IRNCR_TIR 0x1 | ||
69 | #define ASC_IRNCR_RIR 0x2 | ||
70 | #define ASC_IRNCR_EIR 0x4 | ||
71 | |||
72 | #define ASCOPT_CSIZE 0x3 | ||
73 | #define TXFIFO_FL 1 | ||
74 | #define RXFIFO_FL 1 | ||
75 | #define ASCCLC_DISS 0x2 | ||
76 | #define ASCCLC_RMCMASK 0x0000FF00 | ||
77 | #define ASCCLC_RMCOFFSET 8 | ||
78 | #define ASCCON_M_8ASYNC 0x0 | ||
79 | #define ASCCON_M_7ASYNC 0x2 | ||
80 | #define ASCCON_ODD 0x00000020 | ||
81 | #define ASCCON_STP 0x00000080 | ||
82 | #define ASCCON_BRS 0x00000100 | ||
83 | #define ASCCON_FDE 0x00000200 | ||
84 | #define ASCCON_R 0x00008000 | ||
85 | #define ASCCON_FEN 0x00020000 | ||
86 | #define ASCCON_ROEN 0x00080000 | ||
87 | #define ASCCON_TOEN 0x00100000 | ||
88 | #define ASCSTATE_PE 0x00010000 | ||
89 | #define ASCSTATE_FE 0x00020000 | ||
90 | #define ASCSTATE_ROE 0x00080000 | ||
91 | #define ASCSTATE_ANY (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE) | ||
92 | #define ASCWHBSTATE_CLRREN 0x00000001 | ||
93 | #define ASCWHBSTATE_SETREN 0x00000002 | ||
94 | #define ASCWHBSTATE_CLRPE 0x00000004 | ||
95 | #define ASCWHBSTATE_CLRFE 0x00000008 | ||
96 | #define ASCWHBSTATE_CLRROE 0x00000020 | ||
97 | #define ASCTXFCON_TXFEN 0x0001 | ||
98 | #define ASCTXFCON_TXFFLU 0x0002 | ||
99 | #define ASCTXFCON_TXFITLMASK 0x3F00 | ||
100 | #define ASCTXFCON_TXFITLOFF 8 | ||
101 | #define ASCRXFCON_RXFEN 0x0001 | ||
102 | #define ASCRXFCON_RXFFLU 0x0002 | ||
103 | #define ASCRXFCON_RXFITLMASK 0x3F00 | ||
104 | #define ASCRXFCON_RXFITLOFF 8 | ||
105 | #define ASCFSTAT_RXFFLMASK 0x003F | ||
106 | #define ASCFSTAT_TXFFLMASK 0x3F00 | ||
107 | #define ASCFSTAT_TXFREEMASK 0x3F000000 | ||
108 | #define ASCFSTAT_TXFREEOFF 24 | ||
109 | |||
110 | static void lqasc_tx_chars(struct uart_port *port); | ||
111 | static struct ltq_uart_port *lqasc_port[MAXPORTS]; | ||
112 | static struct uart_driver lqasc_reg; | ||
113 | static DEFINE_SPINLOCK(ltq_asc_lock); | ||
114 | |||
115 | struct ltq_uart_port { | ||
116 | struct uart_port port; | ||
117 | struct clk *clk; | ||
118 | unsigned int tx_irq; | ||
119 | unsigned int rx_irq; | ||
120 | unsigned int err_irq; | ||
121 | }; | ||
122 | |||
123 | static inline struct | ||
124 | ltq_uart_port *to_ltq_uart_port(struct uart_port *port) | ||
125 | { | ||
126 | return container_of(port, struct ltq_uart_port, port); | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | lqasc_stop_tx(struct uart_port *port) | ||
131 | { | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | lqasc_start_tx(struct uart_port *port) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | spin_lock_irqsave(<q_asc_lock, flags); | ||
140 | lqasc_tx_chars(port); | ||
141 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | static void | ||
146 | lqasc_stop_rx(struct uart_port *port) | ||
147 | { | ||
148 | ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE); | ||
149 | } | ||
150 | |||
151 | static void | ||
152 | lqasc_enable_ms(struct uart_port *port) | ||
153 | { | ||
154 | } | ||
155 | |||
156 | static int | ||
157 | lqasc_rx_chars(struct uart_port *port) | ||
158 | { | ||
159 | struct tty_struct *tty = tty_port_tty_get(&port->state->port); | ||
160 | unsigned int ch = 0, rsr = 0, fifocnt; | ||
161 | |||
162 | if (!tty) { | ||
163 | dev_dbg(port->dev, "%s:tty is busy now", __func__); | ||
164 | return -EBUSY; | ||
165 | } | ||
166 | fifocnt = | ||
167 | ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; | ||
168 | while (fifocnt--) { | ||
169 | u8 flag = TTY_NORMAL; | ||
170 | ch = ltq_r8(port->membase + LTQ_ASC_RBUF); | ||
171 | rsr = (ltq_r32(port->membase + LTQ_ASC_STATE) | ||
172 | & ASCSTATE_ANY) | UART_DUMMY_UER_RX; | ||
173 | tty_flip_buffer_push(tty); | ||
174 | port->icount.rx++; | ||
175 | |||
176 | /* | ||
177 | * Note that the error handling code is | ||
178 | * out of the main execution path | ||
179 | */ | ||
180 | if (rsr & ASCSTATE_ANY) { | ||
181 | if (rsr & ASCSTATE_PE) { | ||
182 | port->icount.parity++; | ||
183 | ltq_w32_mask(0, ASCWHBSTATE_CLRPE, | ||
184 | port->membase + LTQ_ASC_WHBSTATE); | ||
185 | } else if (rsr & ASCSTATE_FE) { | ||
186 | port->icount.frame++; | ||
187 | ltq_w32_mask(0, ASCWHBSTATE_CLRFE, | ||
188 | port->membase + LTQ_ASC_WHBSTATE); | ||
189 | } | ||
190 | if (rsr & ASCSTATE_ROE) { | ||
191 | port->icount.overrun++; | ||
192 | ltq_w32_mask(0, ASCWHBSTATE_CLRROE, | ||
193 | port->membase + LTQ_ASC_WHBSTATE); | ||
194 | } | ||
195 | |||
196 | rsr &= port->read_status_mask; | ||
197 | |||
198 | if (rsr & ASCSTATE_PE) | ||
199 | flag = TTY_PARITY; | ||
200 | else if (rsr & ASCSTATE_FE) | ||
201 | flag = TTY_FRAME; | ||
202 | } | ||
203 | |||
204 | if ((rsr & port->ignore_status_mask) == 0) | ||
205 | tty_insert_flip_char(tty, ch, flag); | ||
206 | |||
207 | if (rsr & ASCSTATE_ROE) | ||
208 | /* | ||
209 | * Overrun is special, since it's reported | ||
210 | * immediately, and doesn't affect the current | ||
211 | * character | ||
212 | */ | ||
213 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
214 | } | ||
215 | if (ch != 0) | ||
216 | tty_flip_buffer_push(tty); | ||
217 | tty_kref_put(tty); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static void | ||
222 | lqasc_tx_chars(struct uart_port *port) | ||
223 | { | ||
224 | struct circ_buf *xmit = &port->state->xmit; | ||
225 | if (uart_tx_stopped(port)) { | ||
226 | lqasc_stop_tx(port); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) & | ||
231 | ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) { | ||
232 | if (port->x_char) { | ||
233 | ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF); | ||
234 | port->icount.tx++; | ||
235 | port->x_char = 0; | ||
236 | continue; | ||
237 | } | ||
238 | |||
239 | if (uart_circ_empty(xmit)) | ||
240 | break; | ||
241 | |||
242 | ltq_w8(port->state->xmit.buf[port->state->xmit.tail], | ||
243 | port->membase + LTQ_ASC_TBUF); | ||
244 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
245 | port->icount.tx++; | ||
246 | } | ||
247 | |||
248 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
249 | uart_write_wakeup(port); | ||
250 | } | ||
251 | |||
252 | static irqreturn_t | ||
253 | lqasc_tx_int(int irq, void *_port) | ||
254 | { | ||
255 | unsigned long flags; | ||
256 | struct uart_port *port = (struct uart_port *)_port; | ||
257 | spin_lock_irqsave(<q_asc_lock, flags); | ||
258 | ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR); | ||
259 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
260 | lqasc_start_tx(port); | ||
261 | return IRQ_HANDLED; | ||
262 | } | ||
263 | |||
264 | static irqreturn_t | ||
265 | lqasc_err_int(int irq, void *_port) | ||
266 | { | ||
267 | unsigned long flags; | ||
268 | struct uart_port *port = (struct uart_port *)_port; | ||
269 | spin_lock_irqsave(<q_asc_lock, flags); | ||
270 | /* clear any pending interrupts */ | ||
271 | ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | | ||
272 | ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE); | ||
273 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
274 | return IRQ_HANDLED; | ||
275 | } | ||
276 | |||
277 | static irqreturn_t | ||
278 | lqasc_rx_int(int irq, void *_port) | ||
279 | { | ||
280 | unsigned long flags; | ||
281 | struct uart_port *port = (struct uart_port *)_port; | ||
282 | spin_lock_irqsave(<q_asc_lock, flags); | ||
283 | ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR); | ||
284 | lqasc_rx_chars(port); | ||
285 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
286 | return IRQ_HANDLED; | ||
287 | } | ||
288 | |||
289 | static unsigned int | ||
290 | lqasc_tx_empty(struct uart_port *port) | ||
291 | { | ||
292 | int status; | ||
293 | status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; | ||
294 | return status ? 0 : TIOCSER_TEMT; | ||
295 | } | ||
296 | |||
297 | static unsigned int | ||
298 | lqasc_get_mctrl(struct uart_port *port) | ||
299 | { | ||
300 | return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR; | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | lqasc_set_mctrl(struct uart_port *port, u_int mctrl) | ||
305 | { | ||
306 | } | ||
307 | |||
308 | static void | ||
309 | lqasc_break_ctl(struct uart_port *port, int break_state) | ||
310 | { | ||
311 | } | ||
312 | |||
313 | static int | ||
314 | lqasc_startup(struct uart_port *port) | ||
315 | { | ||
316 | struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); | ||
317 | int retval; | ||
318 | |||
319 | port->uartclk = clk_get_rate(ltq_port->clk); | ||
320 | |||
321 | ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), | ||
322 | port->membase + LTQ_ASC_CLC); | ||
323 | |||
324 | ltq_w32(0, port->membase + LTQ_ASC_PISEL); | ||
325 | ltq_w32( | ||
326 | ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | | ||
327 | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, | ||
328 | port->membase + LTQ_ASC_TXFCON); | ||
329 | ltq_w32( | ||
330 | ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ||
331 | | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, | ||
332 | port->membase + LTQ_ASC_RXFCON); | ||
333 | /* make sure other settings are written to hardware before | ||
334 | * setting enable bits | ||
335 | */ | ||
336 | wmb(); | ||
337 | ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | | ||
338 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); | ||
339 | |||
340 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, | ||
341 | IRQF_DISABLED, "asc_tx", port); | ||
342 | if (retval) { | ||
343 | pr_err("failed to request lqasc_tx_int\n"); | ||
344 | return retval; | ||
345 | } | ||
346 | |||
347 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, | ||
348 | IRQF_DISABLED, "asc_rx", port); | ||
349 | if (retval) { | ||
350 | pr_err("failed to request lqasc_rx_int\n"); | ||
351 | goto err1; | ||
352 | } | ||
353 | |||
354 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, | ||
355 | IRQF_DISABLED, "asc_err", port); | ||
356 | if (retval) { | ||
357 | pr_err("failed to request lqasc_err_int\n"); | ||
358 | goto err2; | ||
359 | } | ||
360 | |||
361 | ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX, | ||
362 | port->membase + LTQ_ASC_IRNREN); | ||
363 | return 0; | ||
364 | |||
365 | err2: | ||
366 | free_irq(ltq_port->rx_irq, port); | ||
367 | err1: | ||
368 | free_irq(ltq_port->tx_irq, port); | ||
369 | return retval; | ||
370 | } | ||
371 | |||
372 | static void | ||
373 | lqasc_shutdown(struct uart_port *port) | ||
374 | { | ||
375 | struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); | ||
376 | free_irq(ltq_port->tx_irq, port); | ||
377 | free_irq(ltq_port->rx_irq, port); | ||
378 | free_irq(ltq_port->err_irq, port); | ||
379 | |||
380 | ltq_w32(0, port->membase + LTQ_ASC_CON); | ||
381 | ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU, | ||
382 | port->membase + LTQ_ASC_RXFCON); | ||
383 | ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, | ||
384 | port->membase + LTQ_ASC_TXFCON); | ||
385 | } | ||
386 | |||
387 | static void | ||
388 | lqasc_set_termios(struct uart_port *port, | ||
389 | struct ktermios *new, struct ktermios *old) | ||
390 | { | ||
391 | unsigned int cflag; | ||
392 | unsigned int iflag; | ||
393 | unsigned int divisor; | ||
394 | unsigned int baud; | ||
395 | unsigned int con = 0; | ||
396 | unsigned long flags; | ||
397 | |||
398 | cflag = new->c_cflag; | ||
399 | iflag = new->c_iflag; | ||
400 | |||
401 | switch (cflag & CSIZE) { | ||
402 | case CS7: | ||
403 | con = ASCCON_M_7ASYNC; | ||
404 | break; | ||
405 | |||
406 | case CS5: | ||
407 | case CS6: | ||
408 | default: | ||
409 | new->c_cflag &= ~ CSIZE; | ||
410 | new->c_cflag |= CS8; | ||
411 | con = ASCCON_M_8ASYNC; | ||
412 | break; | ||
413 | } | ||
414 | |||
415 | cflag &= ~CMSPAR; /* Mark/Space parity is not supported */ | ||
416 | |||
417 | if (cflag & CSTOPB) | ||
418 | con |= ASCCON_STP; | ||
419 | |||
420 | if (cflag & PARENB) { | ||
421 | if (!(cflag & PARODD)) | ||
422 | con &= ~ASCCON_ODD; | ||
423 | else | ||
424 | con |= ASCCON_ODD; | ||
425 | } | ||
426 | |||
427 | port->read_status_mask = ASCSTATE_ROE; | ||
428 | if (iflag & INPCK) | ||
429 | port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE; | ||
430 | |||
431 | port->ignore_status_mask = 0; | ||
432 | if (iflag & IGNPAR) | ||
433 | port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE; | ||
434 | |||
435 | if (iflag & IGNBRK) { | ||
436 | /* | ||
437 | * If we're ignoring parity and break indicators, | ||
438 | * ignore overruns too (for real raw support). | ||
439 | */ | ||
440 | if (iflag & IGNPAR) | ||
441 | port->ignore_status_mask |= ASCSTATE_ROE; | ||
442 | } | ||
443 | |||
444 | if ((cflag & CREAD) == 0) | ||
445 | port->ignore_status_mask |= UART_DUMMY_UER_RX; | ||
446 | |||
447 | /* set error signals - framing, parity and overrun, enable receiver */ | ||
448 | con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; | ||
449 | |||
450 | spin_lock_irqsave(<q_asc_lock, flags); | ||
451 | |||
452 | /* set up CON */ | ||
453 | ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON); | ||
454 | |||
455 | /* Set baud rate - take a divider of 2 into account */ | ||
456 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); | ||
457 | divisor = uart_get_divisor(port, baud); | ||
458 | divisor = divisor / 2 - 1; | ||
459 | |||
460 | /* disable the baudrate generator */ | ||
461 | ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON); | ||
462 | |||
463 | /* make sure the fractional divider is off */ | ||
464 | ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON); | ||
465 | |||
466 | /* set up to use divisor of 2 */ | ||
467 | ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON); | ||
468 | |||
469 | /* now we can write the new baudrate into the register */ | ||
470 | ltq_w32(divisor, port->membase + LTQ_ASC_BG); | ||
471 | |||
472 | /* turn the baudrate generator back on */ | ||
473 | ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON); | ||
474 | |||
475 | /* enable rx */ | ||
476 | ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE); | ||
477 | |||
478 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
479 | |||
480 | /* Don't rewrite B0 */ | ||
481 | if (tty_termios_baud_rate(new)) | ||
482 | tty_termios_encode_baud_rate(new, baud, baud); | ||
483 | } | ||
484 | |||
485 | static const char* | ||
486 | lqasc_type(struct uart_port *port) | ||
487 | { | ||
488 | if (port->type == PORT_LTQ_ASC) | ||
489 | return DRVNAME; | ||
490 | else | ||
491 | return NULL; | ||
492 | } | ||
493 | |||
494 | static void | ||
495 | lqasc_release_port(struct uart_port *port) | ||
496 | { | ||
497 | if (port->flags & UPF_IOREMAP) { | ||
498 | iounmap(port->membase); | ||
499 | port->membase = NULL; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | static int | ||
504 | lqasc_request_port(struct uart_port *port) | ||
505 | { | ||
506 | struct platform_device *pdev = to_platform_device(port->dev); | ||
507 | struct resource *res; | ||
508 | int size; | ||
509 | |||
510 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
511 | if (!res) { | ||
512 | dev_err(&pdev->dev, "cannot obtain I/O memory region"); | ||
513 | return -ENODEV; | ||
514 | } | ||
515 | size = resource_size(res); | ||
516 | |||
517 | res = devm_request_mem_region(&pdev->dev, res->start, | ||
518 | size, dev_name(&pdev->dev)); | ||
519 | if (!res) { | ||
520 | dev_err(&pdev->dev, "cannot request I/O memory region"); | ||
521 | return -EBUSY; | ||
522 | } | ||
523 | |||
524 | if (port->flags & UPF_IOREMAP) { | ||
525 | port->membase = devm_ioremap_nocache(&pdev->dev, | ||
526 | port->mapbase, size); | ||
527 | if (port->membase == NULL) | ||
528 | return -ENOMEM; | ||
529 | } | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static void | ||
534 | lqasc_config_port(struct uart_port *port, int flags) | ||
535 | { | ||
536 | if (flags & UART_CONFIG_TYPE) { | ||
537 | port->type = PORT_LTQ_ASC; | ||
538 | lqasc_request_port(port); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | static int | ||
543 | lqasc_verify_port(struct uart_port *port, | ||
544 | struct serial_struct *ser) | ||
545 | { | ||
546 | int ret = 0; | ||
547 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC) | ||
548 | ret = -EINVAL; | ||
549 | if (ser->irq < 0 || ser->irq >= NR_IRQS) | ||
550 | ret = -EINVAL; | ||
551 | if (ser->baud_base < 9600) | ||
552 | ret = -EINVAL; | ||
553 | return ret; | ||
554 | } | ||
555 | |||
556 | static struct uart_ops lqasc_pops = { | ||
557 | .tx_empty = lqasc_tx_empty, | ||
558 | .set_mctrl = lqasc_set_mctrl, | ||
559 | .get_mctrl = lqasc_get_mctrl, | ||
560 | .stop_tx = lqasc_stop_tx, | ||
561 | .start_tx = lqasc_start_tx, | ||
562 | .stop_rx = lqasc_stop_rx, | ||
563 | .enable_ms = lqasc_enable_ms, | ||
564 | .break_ctl = lqasc_break_ctl, | ||
565 | .startup = lqasc_startup, | ||
566 | .shutdown = lqasc_shutdown, | ||
567 | .set_termios = lqasc_set_termios, | ||
568 | .type = lqasc_type, | ||
569 | .release_port = lqasc_release_port, | ||
570 | .request_port = lqasc_request_port, | ||
571 | .config_port = lqasc_config_port, | ||
572 | .verify_port = lqasc_verify_port, | ||
573 | }; | ||
574 | |||
575 | static void | ||
576 | lqasc_console_putchar(struct uart_port *port, int ch) | ||
577 | { | ||
578 | int fifofree; | ||
579 | |||
580 | if (!port->membase) | ||
581 | return; | ||
582 | |||
583 | do { | ||
584 | fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT) | ||
585 | & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF; | ||
586 | } while (fifofree == 0); | ||
587 | ltq_w8(ch, port->membase + LTQ_ASC_TBUF); | ||
588 | } | ||
589 | |||
590 | |||
591 | static void | ||
592 | lqasc_console_write(struct console *co, const char *s, u_int count) | ||
593 | { | ||
594 | struct ltq_uart_port *ltq_port; | ||
595 | struct uart_port *port; | ||
596 | unsigned long flags; | ||
597 | |||
598 | if (co->index >= MAXPORTS) | ||
599 | return; | ||
600 | |||
601 | ltq_port = lqasc_port[co->index]; | ||
602 | if (!ltq_port) | ||
603 | return; | ||
604 | |||
605 | port = <q_port->port; | ||
606 | |||
607 | spin_lock_irqsave(<q_asc_lock, flags); | ||
608 | uart_console_write(port, s, count, lqasc_console_putchar); | ||
609 | spin_unlock_irqrestore(<q_asc_lock, flags); | ||
610 | } | ||
611 | |||
612 | static int __init | ||
613 | lqasc_console_setup(struct console *co, char *options) | ||
614 | { | ||
615 | struct ltq_uart_port *ltq_port; | ||
616 | struct uart_port *port; | ||
617 | int baud = 115200; | ||
618 | int bits = 8; | ||
619 | int parity = 'n'; | ||
620 | int flow = 'n'; | ||
621 | |||
622 | if (co->index >= MAXPORTS) | ||
623 | return -ENODEV; | ||
624 | |||
625 | ltq_port = lqasc_port[co->index]; | ||
626 | if (!ltq_port) | ||
627 | return -ENODEV; | ||
628 | |||
629 | port = <q_port->port; | ||
630 | |||
631 | port->uartclk = clk_get_rate(ltq_port->clk); | ||
632 | |||
633 | if (options) | ||
634 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
635 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
636 | } | ||
637 | |||
638 | static struct console lqasc_console = { | ||
639 | .name = "ttyLTQ", | ||
640 | .write = lqasc_console_write, | ||
641 | .device = uart_console_device, | ||
642 | .setup = lqasc_console_setup, | ||
643 | .flags = CON_PRINTBUFFER, | ||
644 | .index = -1, | ||
645 | .data = &lqasc_reg, | ||
646 | }; | ||
647 | |||
648 | static int __init | ||
649 | lqasc_console_init(void) | ||
650 | { | ||
651 | register_console(&lqasc_console); | ||
652 | return 0; | ||
653 | } | ||
654 | console_initcall(lqasc_console_init); | ||
655 | |||
656 | static struct uart_driver lqasc_reg = { | ||
657 | .owner = THIS_MODULE, | ||
658 | .driver_name = DRVNAME, | ||
659 | .dev_name = "ttyLTQ", | ||
660 | .major = 0, | ||
661 | .minor = 0, | ||
662 | .nr = MAXPORTS, | ||
663 | .cons = &lqasc_console, | ||
664 | }; | ||
665 | |||
666 | static int __init | ||
667 | lqasc_probe(struct platform_device *pdev) | ||
668 | { | ||
669 | struct ltq_uart_port *ltq_port; | ||
670 | struct uart_port *port; | ||
671 | struct resource *mmres, *irqres; | ||
672 | int tx_irq, rx_irq, err_irq; | ||
673 | struct clk *clk; | ||
674 | int ret; | ||
675 | |||
676 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
677 | irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
678 | if (!mmres || !irqres) | ||
679 | return -ENODEV; | ||
680 | |||
681 | if (pdev->id >= MAXPORTS) | ||
682 | return -EBUSY; | ||
683 | |||
684 | if (lqasc_port[pdev->id] != NULL) | ||
685 | return -EBUSY; | ||
686 | |||
687 | clk = clk_get(&pdev->dev, "fpi"); | ||
688 | if (IS_ERR(clk)) { | ||
689 | pr_err("failed to get fpi clk\n"); | ||
690 | return -ENOENT; | ||
691 | } | ||
692 | |||
693 | tx_irq = platform_get_irq_byname(pdev, "tx"); | ||
694 | rx_irq = platform_get_irq_byname(pdev, "rx"); | ||
695 | err_irq = platform_get_irq_byname(pdev, "err"); | ||
696 | if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0)) | ||
697 | return -ENODEV; | ||
698 | |||
699 | ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL); | ||
700 | if (!ltq_port) | ||
701 | return -ENOMEM; | ||
702 | |||
703 | port = <q_port->port; | ||
704 | |||
705 | port->iotype = SERIAL_IO_MEM; | ||
706 | port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP; | ||
707 | port->ops = &lqasc_pops; | ||
708 | port->fifosize = 16; | ||
709 | port->type = PORT_LTQ_ASC, | ||
710 | port->line = pdev->id; | ||
711 | port->dev = &pdev->dev; | ||
712 | |||
713 | port->irq = tx_irq; /* unused, just to be backward-compatibe */ | ||
714 | port->mapbase = mmres->start; | ||
715 | |||
716 | ltq_port->clk = clk; | ||
717 | |||
718 | ltq_port->tx_irq = tx_irq; | ||
719 | ltq_port->rx_irq = rx_irq; | ||
720 | ltq_port->err_irq = err_irq; | ||
721 | |||
722 | lqasc_port[pdev->id] = ltq_port; | ||
723 | platform_set_drvdata(pdev, ltq_port); | ||
724 | |||
725 | ret = uart_add_one_port(&lqasc_reg, port); | ||
726 | |||
727 | return ret; | ||
728 | } | ||
729 | |||
730 | static struct platform_driver lqasc_driver = { | ||
731 | .driver = { | ||
732 | .name = DRVNAME, | ||
733 | .owner = THIS_MODULE, | ||
734 | }, | ||
735 | }; | ||
736 | |||
737 | int __init | ||
738 | init_lqasc(void) | ||
739 | { | ||
740 | int ret; | ||
741 | |||
742 | ret = uart_register_driver(&lqasc_reg); | ||
743 | if (ret != 0) | ||
744 | return ret; | ||
745 | |||
746 | ret = platform_driver_probe(&lqasc_driver, lqasc_probe); | ||
747 | if (ret != 0) | ||
748 | uart_unregister_driver(&lqasc_reg); | ||
749 | |||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | module_init(init_lqasc); | ||
754 | |||
755 | MODULE_DESCRIPTION("Lantiq serial port driver"); | ||
756 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index c111f36f5d21..cab52f4a88b0 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -49,8 +49,8 @@ | |||
49 | 49 | ||
50 | static int hsu_dma_enable; | 50 | static int hsu_dma_enable; |
51 | module_param(hsu_dma_enable, int, 0); | 51 | module_param(hsu_dma_enable, int, 0); |
52 | MODULE_PARM_DESC(hsu_dma_enable, "It is a bitmap to set working mode, if \ | 52 | MODULE_PARM_DESC(hsu_dma_enable, |
53 | bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode."); | 53 | "It is a bitmap to set working mode, if bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode."); |
54 | 54 | ||
55 | struct hsu_dma_buffer { | 55 | struct hsu_dma_buffer { |
56 | u8 *buf; | 56 | u8 *buf; |
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 2f548af4e98a..1bd28450ca40 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c | |||
@@ -56,7 +56,7 @@ struct uart_max3110 { | |||
56 | wait_queue_head_t wq; | 56 | wait_queue_head_t wq; |
57 | struct task_struct *main_thread; | 57 | struct task_struct *main_thread; |
58 | struct task_struct *read_thread; | 58 | struct task_struct *read_thread; |
59 | struct mutex thread_mutex;; | 59 | struct mutex thread_mutex; |
60 | 60 | ||
61 | u32 baud; | 61 | u32 baud; |
62 | u16 cur_conf; | 62 | u16 cur_conf; |
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index bfee9b4c6661..e6ba83876508 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/msm_serial.c - driver for msm7k serial device and console | 2 | * Driver for msm7k serial device and console |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Google, Inc. | 4 | * Copyright (C) 2007 Google, Inc. |
5 | * Author: Robert Love <rlove@google.com> | 5 | * Author: Robert Love <rlove@google.com> |
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h index 9b8dc5d0d855..e4acef5de77e 100644 --- a/drivers/tty/serial/msm_serial.h +++ b/drivers/tty/serial/msm_serial.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/msm_serial.h | ||
3 | * | ||
4 | * Copyright (C) 2007 Google, Inc. | 2 | * Copyright (C) 2007 Google, Inc. |
5 | * Author: Robert Love <rlove@google.com> | 3 | * Author: Robert Love <rlove@google.com> |
6 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | 4 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c index beeff1e86093..4f41dcdcb771 100644 --- a/drivers/tty/serial/msm_smd_tty.c +++ b/drivers/tty/serial/msm_smd_tty.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* drivers/tty/serial/msm_smd_tty.c | 1 | /* |
2 | * | ||
3 | * Copyright (C) 2007 Google, Inc. | 2 | * Copyright (C) 2007 Google, Inc. |
4 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | 3 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
5 | * Author: Brian Swetland <swetland@google.com> | 4 | * Author: Brian Swetland <swetland@google.com> |
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c index 7735c9f35fa0..d40da78e7c85 100644 --- a/drivers/tty/serial/netx-serial.c +++ b/drivers/tty/serial/netx-serial.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/netx-serial.c | ||
3 | * | ||
4 | * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix | 2 | * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 0e8eec516df4..c911b2419abb 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -80,14 +80,17 @@ 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 struct of_device_id of_platform_serial_table[]; | ||
83 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev) | 84 | static int __devinit of_platform_serial_probe(struct platform_device *ofdev) |
84 | { | 85 | { |
86 | const struct of_device_id *match; | ||
85 | struct of_serial_info *info; | 87 | struct of_serial_info *info; |
86 | struct uart_port port; | 88 | struct uart_port port; |
87 | int port_type; | 89 | int port_type; |
88 | int ret; | 90 | int ret; |
89 | 91 | ||
90 | if (!ofdev->dev.of_match) | 92 | match = of_match_device(of_platform_serial_table, &ofdev->dev); |
93 | if (!match) | ||
91 | return -EINVAL; | 94 | return -EINVAL; |
92 | 95 | ||
93 | if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) | 96 | if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) |
@@ -97,7 +100,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev) | |||
97 | if (info == NULL) | 100 | if (info == NULL) |
98 | return -ENOMEM; | 101 | return -ENOMEM; |
99 | 102 | ||
100 | port_type = (unsigned long)ofdev->dev.of_match->data; | 103 | port_type = (unsigned long)match->data; |
101 | ret = of_platform_serial_setup(ofdev, port_type, &port); | 104 | ret = of_platform_serial_setup(ofdev, port_type, &port); |
102 | if (ret) | 105 | if (ret) |
103 | goto out; | 106 | goto out; |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 26403b8e4b9b..c63d0d152af6 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -253,6 +253,8 @@ enum pch_uart_num_t { | |||
253 | pch_ml7213_uart0, | 253 | pch_ml7213_uart0, |
254 | pch_ml7213_uart1, | 254 | pch_ml7213_uart1, |
255 | pch_ml7213_uart2, | 255 | pch_ml7213_uart2, |
256 | pch_ml7223_uart0, | ||
257 | pch_ml7223_uart1, | ||
256 | }; | 258 | }; |
257 | 259 | ||
258 | static struct pch_uart_driver_data drv_dat[] = { | 260 | static struct pch_uart_driver_data drv_dat[] = { |
@@ -263,6 +265,8 @@ static struct pch_uart_driver_data drv_dat[] = { | |||
263 | [pch_ml7213_uart0] = {PCH_UART_8LINE, 0}, | 265 | [pch_ml7213_uart0] = {PCH_UART_8LINE, 0}, |
264 | [pch_ml7213_uart1] = {PCH_UART_2LINE, 1}, | 266 | [pch_ml7213_uart1] = {PCH_UART_2LINE, 1}, |
265 | [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, | 267 | [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, |
268 | [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, | ||
269 | [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, | ||
266 | }; | 270 | }; |
267 | 271 | ||
268 | static unsigned int default_baud = 9600; | 272 | static unsigned int default_baud = 9600; |
@@ -1534,6 +1538,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { | |||
1534 | .driver_data = pch_ml7213_uart1}, | 1538 | .driver_data = pch_ml7213_uart1}, |
1535 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029), | 1539 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029), |
1536 | .driver_data = pch_ml7213_uart2}, | 1540 | .driver_data = pch_ml7213_uart2}, |
1541 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800C), | ||
1542 | .driver_data = pch_ml7223_uart0}, | ||
1543 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D), | ||
1544 | .driver_data = pch_ml7223_uart1}, | ||
1537 | {0,}, | 1545 | {0,}, |
1538 | }; | 1546 | }; |
1539 | 1547 | ||
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index e1c8d4f1ce58..5acd24a27d08 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/pmac_zilog.c | ||
3 | * | ||
4 | * Driver for PowerMac Z85c30 based ESCC cell found in the | 2 | * Driver for PowerMac Z85c30 based ESCC cell found in the |
5 | * "macio" ASICs of various PowerMac models | 3 | * "macio" ASICs of various PowerMac models |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 1102a39b44f5..4302e6e3768e 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/serial/pxa.c | ||
3 | * | ||
4 | * Based on drivers/serial/8250.c by Russell King. | 2 | * Based on drivers/serial/8250.c by Russell King. |
5 | * | 3 | * |
6 | * Author: Nicolas Pitre | 4 | * Author: Nicolas Pitre |
diff --git a/drivers/tty/serial/s3c2400.c b/drivers/tty/serial/s3c2400.c index fed1a9a1ffb4..d13051b3df87 100644 --- a/drivers/tty/serial/s3c2400.c +++ b/drivers/tty/serial/s3c2400.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c240.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung SoC onboard UARTs. | 2 | * Driver for Samsung SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics |
diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c index 73f089d3efd6..bffe6ff9b158 100644 --- a/drivers/tty/serial/s3c2410.c +++ b/drivers/tty/serial/s3c2410.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c2410.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung S3C2410 SoC onboard UARTs. | 2 | * Driver for Samsung S3C2410 SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics |
diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c index 1700b1a2fb7e..7e2b9504a687 100644 --- a/drivers/tty/serial/s3c2412.c +++ b/drivers/tty/serial/s3c2412.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c2412.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs. | 2 | * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics |
diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c index 094cc3904b13..9e10d415d5fd 100644 --- a/drivers/tty/serial/s3c2440.c +++ b/drivers/tty/serial/s3c2440.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c2440.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs. | 2 | * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics |
diff --git a/drivers/tty/serial/s3c24a0.c b/drivers/tty/serial/s3c24a0.c index fad6083ca427..914eff22e499 100644 --- a/drivers/tty/serial/s3c24a0.c +++ b/drivers/tty/serial/s3c24a0.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c24a0.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung S3C24A0 SoC onboard UARTs. | 2 | * Driver for Samsung S3C24A0 SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Based on drivers/serial/s3c2410.c | 4 | * Based on drivers/serial/s3c2410.c |
diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c index 4be92ab50058..ded26c42ff37 100644 --- a/drivers/tty/serial/s3c6400.c +++ b/drivers/tty/serial/s3c6400.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s3c6400.c | 1 | /* |
2 | * | ||
3 | * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. | 2 | * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Copyright 2008 Openmoko, Inc. | 4 | * Copyright 2008 Openmoko, Inc. |
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c index 6ebccd70a707..fb2619f93d84 100644 --- a/drivers/tty/serial/s5pv210.c +++ b/drivers/tty/serial/s5pv210.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/s5pv210.c | 1 | /* |
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | 2 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com/ | 3 | * http://www.samsung.com/ |
5 | * | 4 | * |
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 2199d819a987..ef7a21a6a01b 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/sa1100.c | ||
3 | * | ||
4 | * Driver for SA11x0 serial ports | 2 | * Driver for SA11x0 serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 9e2fa8d784e2..f66f64829303 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/samsuing.c | 1 | /* |
2 | * | ||
3 | * Driver core for Samsung SoC onboard UARTs. | 2 | * Driver core for Samsung SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics |
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index 0ac06a07d25f..5b098cd76040 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* linux/drivers/serial/samsung.h | 1 | /* |
2 | * | ||
3 | * Driver for Samsung SoC onboard UARTs. | 2 | * Driver for Samsung SoC onboard UARTs. |
4 | * | 3 | * |
5 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics | 4 | * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics |
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 602d9845c52f..ea2340b814e9 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/sb1250-duart.c | ||
3 | * | ||
4 | * Support for the asynchronous serial interface (DUART) included | 2 | * Support for the asynchronous serial interface (DUART) included |
5 | * in the BCM1250 and derived System-On-a-Chip (SOC) devices. | 3 | * in the BCM1250 and derived System-On-a-Chip (SOC) devices. |
6 | * | 4 | * |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 733fe8e73f0f..db7912cb7ae0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/core.c | ||
3 | * | ||
4 | * Driver core for serial ports | 2 | * Driver core for serial ports |
5 | * | 3 | * |
6 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. |
@@ -172,12 +170,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in | |||
172 | 170 | ||
173 | retval = uport->ops->startup(uport); | 171 | retval = uport->ops->startup(uport); |
174 | if (retval == 0) { | 172 | if (retval == 0) { |
175 | if (init_hw) { | 173 | if (uart_console(uport) && uport->cons->cflag) { |
176 | /* | 174 | tty->termios->c_cflag = uport->cons->cflag; |
177 | * Initialise the hardware port settings. | 175 | uport->cons->cflag = 0; |
178 | */ | 176 | } |
179 | uart_change_speed(tty, state, NULL); | 177 | /* |
178 | * Initialise the hardware port settings. | ||
179 | */ | ||
180 | uart_change_speed(tty, state, NULL); | ||
180 | 181 | ||
182 | if (init_hw) { | ||
181 | /* | 183 | /* |
182 | * Setup the RTS and DTR signals once the | 184 | * Setup the RTS and DTR signals once the |
183 | * port is open and ready to respond. | 185 | * port is open and ready to respond. |
@@ -1240,17 +1242,6 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1240 | } | 1242 | } |
1241 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1243 | spin_unlock_irqrestore(&state->uart_port->lock, flags); |
1242 | } | 1244 | } |
1243 | #if 0 | ||
1244 | /* | ||
1245 | * No need to wake up processes in open wait, since they | ||
1246 | * sample the CLOCAL flag once, and don't recheck it. | ||
1247 | * XXX It's not clear whether the current behavior is correct | ||
1248 | * or not. Hence, this may change..... | ||
1249 | */ | ||
1250 | if (!(old_termios->c_cflag & CLOCAL) && | ||
1251 | (tty->termios->c_cflag & CLOCAL)) | ||
1252 | wake_up_interruptible(&state->uart_port.open_wait); | ||
1253 | #endif | ||
1254 | } | 1245 | } |
1255 | 1246 | ||
1256 | /* | 1247 | /* |
@@ -1423,7 +1414,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout) | |||
1423 | if (time_after(jiffies, expire)) | 1414 | if (time_after(jiffies, expire)) |
1424 | break; | 1415 | break; |
1425 | } | 1416 | } |
1426 | set_current_state(TASK_RUNNING); /* might not be needed */ | ||
1427 | } | 1417 | } |
1428 | 1418 | ||
1429 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | 1419 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) |
@@ -1466,45 +1456,6 @@ static void uart_hangup(struct tty_struct *tty) | |||
1466 | mutex_unlock(&port->mutex); | 1456 | mutex_unlock(&port->mutex); |
1467 | } | 1457 | } |
1468 | 1458 | ||
1469 | /** | ||
1470 | * uart_update_termios - update the terminal hw settings | ||
1471 | * @tty: tty associated with UART | ||
1472 | * @state: UART to update | ||
1473 | * | ||
1474 | * Copy across the serial console cflag setting into the termios settings | ||
1475 | * for the initial open of the port. This allows continuity between the | ||
1476 | * kernel settings, and the settings init adopts when it opens the port | ||
1477 | * for the first time. | ||
1478 | */ | ||
1479 | static void uart_update_termios(struct tty_struct *tty, | ||
1480 | struct uart_state *state) | ||
1481 | { | ||
1482 | struct uart_port *port = state->uart_port; | ||
1483 | |||
1484 | if (uart_console(port) && port->cons->cflag) { | ||
1485 | tty->termios->c_cflag = port->cons->cflag; | ||
1486 | port->cons->cflag = 0; | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | * If the device failed to grab its irq resources, | ||
1491 | * or some other error occurred, don't try to talk | ||
1492 | * to the port hardware. | ||
1493 | */ | ||
1494 | if (!(tty->flags & (1 << TTY_IO_ERROR))) { | ||
1495 | /* | ||
1496 | * Make termios settings take effect. | ||
1497 | */ | ||
1498 | uart_change_speed(tty, state, NULL); | ||
1499 | |||
1500 | /* | ||
1501 | * And finally enable the RTS and DTR signals. | ||
1502 | */ | ||
1503 | if (tty->termios->c_cflag & CBAUD) | ||
1504 | uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1508 | static int uart_carrier_raised(struct tty_port *port) | 1459 | static int uart_carrier_raised(struct tty_port *port) |
1509 | { | 1460 | { |
1510 | struct uart_state *state = container_of(port, struct uart_state, port); | 1461 | struct uart_state *state = container_of(port, struct uart_state, port); |
@@ -1524,16 +1475,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) | |||
1524 | struct uart_state *state = container_of(port, struct uart_state, port); | 1475 | struct uart_state *state = container_of(port, struct uart_state, port); |
1525 | struct uart_port *uport = state->uart_port; | 1476 | struct uart_port *uport = state->uart_port; |
1526 | 1477 | ||
1527 | if (onoff) { | 1478 | if (onoff) |
1528 | uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); | 1479 | uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1529 | |||
1530 | /* | ||
1531 | * If this is the first open to succeed, | ||
1532 | * adjust things to suit. | ||
1533 | */ | ||
1534 | if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) | ||
1535 | uart_update_termios(port->tty, state); | ||
1536 | } | ||
1537 | else | 1480 | else |
1538 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); | 1481 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1539 | } | 1482 | } |
@@ -1586,15 +1529,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1586 | pr_debug("uart_open(%d) called\n", line); | 1529 | pr_debug("uart_open(%d) called\n", line); |
1587 | 1530 | ||
1588 | /* | 1531 | /* |
1589 | * tty->driver->num won't change, so we won't fail here with | ||
1590 | * tty->driver_data set to something non-NULL (and therefore | ||
1591 | * we won't get caught by uart_close()). | ||
1592 | */ | ||
1593 | retval = -ENODEV; | ||
1594 | if (line >= tty->driver->num) | ||
1595 | goto fail; | ||
1596 | |||
1597 | /* | ||
1598 | * We take the semaphore inside uart_get to guarantee that we won't | 1532 | * We take the semaphore inside uart_get to guarantee that we won't |
1599 | * be re-entered while allocating the state structure, or while we | 1533 | * be re-entered while allocating the state structure, or while we |
1600 | * request any IRQs that the driver may need. This also has the nice | 1534 | * request any IRQs that the driver may need. This also has the nice |
@@ -1972,13 +1906,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) | |||
1972 | struct tty_port *port = &state->port; | 1906 | struct tty_port *port = &state->port; |
1973 | struct device *tty_dev; | 1907 | struct device *tty_dev; |
1974 | struct uart_match match = {uport, drv}; | 1908 | struct uart_match match = {uport, drv}; |
1975 | struct tty_struct *tty; | ||
1976 | 1909 | ||
1977 | mutex_lock(&port->mutex); | 1910 | mutex_lock(&port->mutex); |
1978 | 1911 | ||
1979 | /* Must be inside the mutex lock until we convert to tty_port */ | ||
1980 | tty = port->tty; | ||
1981 | |||
1982 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); | 1912 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); |
1983 | if (device_may_wakeup(tty_dev)) { | 1913 | if (device_may_wakeup(tty_dev)) { |
1984 | if (!enable_irq_wake(uport->irq)) | 1914 | if (!enable_irq_wake(uport->irq)) |
diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index b1962025b1aa..2430319f2f52 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/serial_ks8695.c | ||
3 | * | ||
4 | * Driver for KS8695 serial ports | 2 | * Driver for KS8695 serial ports |
5 | * | 3 | * |
6 | * Based on drivers/serial/serial_amba.c, by Kam Lee. | 4 | * Based on drivers/serial/serial_amba.c, by Kam Lee. |
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index c50e9fbbf743..8e3fc1944e6d 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/serial_txx9.c | ||
3 | * | ||
4 | * Derived from many drivers using generic_serial interface, | 2 | * Derived from many drivers using generic_serial interface, |
5 | * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c | 3 | * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c |
6 | * (was in Linux/VR tree) by Jim Pick. | 4 | * (was in Linux/VR tree) by Jim Pick. |
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 920a6f929c8b..ebd8629c108d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/sh-sci.c | ||
3 | * | ||
4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) | 2 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) |
5 | * | 3 | * |
6 | * Copyright (C) 2002 - 2011 Paul Mundt | 4 | * Copyright (C) 2002 - 2011 Paul Mundt |
@@ -43,6 +41,7 @@ | |||
43 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
44 | #include <linux/serial_sci.h> | 42 | #include <linux/serial_sci.h> |
45 | #include <linux/notifier.h> | 43 | #include <linux/notifier.h> |
44 | #include <linux/pm_runtime.h> | ||
46 | #include <linux/cpufreq.h> | 45 | #include <linux/cpufreq.h> |
47 | #include <linux/clk.h> | 46 | #include <linux/clk.h> |
48 | #include <linux/ctype.h> | 47 | #include <linux/ctype.h> |
@@ -562,6 +561,9 @@ static void sci_break_timer(unsigned long data) | |||
562 | { | 561 | { |
563 | struct sci_port *port = (struct sci_port *)data; | 562 | struct sci_port *port = (struct sci_port *)data; |
564 | 563 | ||
564 | if (port->enable) | ||
565 | port->enable(&port->port); | ||
566 | |||
565 | if (sci_rxd_in(&port->port) == 0) { | 567 | if (sci_rxd_in(&port->port) == 0) { |
566 | port->break_flag = 1; | 568 | port->break_flag = 1; |
567 | sci_schedule_break_timer(port); | 569 | sci_schedule_break_timer(port); |
@@ -571,6 +573,9 @@ static void sci_break_timer(unsigned long data) | |||
571 | sci_schedule_break_timer(port); | 573 | sci_schedule_break_timer(port); |
572 | } else | 574 | } else |
573 | port->break_flag = 0; | 575 | port->break_flag = 0; |
576 | |||
577 | if (port->disable) | ||
578 | port->disable(&port->port); | ||
574 | } | 579 | } |
575 | 580 | ||
576 | static int sci_handle_errors(struct uart_port *port) | 581 | static int sci_handle_errors(struct uart_port *port) |
@@ -839,6 +844,8 @@ static void sci_clk_enable(struct uart_port *port) | |||
839 | { | 844 | { |
840 | struct sci_port *sci_port = to_sci_port(port); | 845 | struct sci_port *sci_port = to_sci_port(port); |
841 | 846 | ||
847 | pm_runtime_get_sync(port->dev); | ||
848 | |||
842 | clk_enable(sci_port->iclk); | 849 | clk_enable(sci_port->iclk); |
843 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); | 850 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
844 | clk_enable(sci_port->fclk); | 851 | clk_enable(sci_port->fclk); |
@@ -850,6 +857,8 @@ static void sci_clk_disable(struct uart_port *port) | |||
850 | 857 | ||
851 | clk_disable(sci_port->fclk); | 858 | clk_disable(sci_port->fclk); |
852 | clk_disable(sci_port->iclk); | 859 | clk_disable(sci_port->iclk); |
860 | |||
861 | pm_runtime_put_sync(port->dev); | ||
853 | } | 862 | } |
854 | 863 | ||
855 | static int sci_request_irq(struct sci_port *port) | 864 | static int sci_request_irq(struct sci_port *port) |
@@ -1758,6 +1767,8 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1758 | sci_port->enable = sci_clk_enable; | 1767 | sci_port->enable = sci_clk_enable; |
1759 | sci_port->disable = sci_clk_disable; | 1768 | sci_port->disable = sci_clk_disable; |
1760 | port->dev = &dev->dev; | 1769 | port->dev = &dev->dev; |
1770 | |||
1771 | pm_runtime_enable(&dev->dev); | ||
1761 | } | 1772 | } |
1762 | 1773 | ||
1763 | sci_port->break_timer.data = (unsigned long)sci_port; | 1774 | sci_port->break_timer.data = (unsigned long)sci_port; |
@@ -1777,7 +1788,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1777 | * | 1788 | * |
1778 | * For the muxed case there's nothing more to do. | 1789 | * For the muxed case there's nothing more to do. |
1779 | */ | 1790 | */ |
1780 | port->irq = p->irqs[SCIx_TXI_IRQ]; | 1791 | port->irq = p->irqs[SCIx_RXI_IRQ]; |
1781 | 1792 | ||
1782 | if (p->dma_dev) | 1793 | if (p->dma_dev) |
1783 | dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", | 1794 | dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", |
@@ -1938,6 +1949,7 @@ static int sci_remove(struct platform_device *dev) | |||
1938 | clk_put(port->iclk); | 1949 | clk_put(port->iclk); |
1939 | clk_put(port->fclk); | 1950 | clk_put(port->fclk); |
1940 | 1951 | ||
1952 | pm_runtime_disable(&dev->dev); | ||
1941 | return 0; | 1953 | return 0; |
1942 | } | 1954 | } |
1943 | 1955 | ||
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index 5fefed53fa42..b04d937c9110 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h | |||
@@ -270,12 +270,12 @@ | |||
270 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 270 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
271 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 271 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
272 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 272 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
273 | defined(CONFIG_ARCH_SH73A0) || \ | 273 | defined(CONFIG_ARCH_SH7367) |
274 | defined(CONFIG_ARCH_SH7367) || \ | ||
275 | defined(CONFIG_ARCH_SH7377) | ||
276 | #define SCIF_FNS(name, scif_offset, scif_size) \ | 274 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
277 | CPU_SCIF_FNS(name, scif_offset, scif_size) | 275 | CPU_SCIF_FNS(name, scif_offset, scif_size) |
278 | #elif defined(CONFIG_ARCH_SH7372) | 276 | #elif defined(CONFIG_ARCH_SH7377) || \ |
277 | defined(CONFIG_ARCH_SH7372) || \ | ||
278 | defined(CONFIG_ARCH_SH73A0) | ||
279 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ | 279 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ |
280 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) | 280 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) |
281 | #define SCIF_FNS(name, scif_offset, scif_size) \ | 281 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
@@ -313,9 +313,7 @@ | |||
313 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | 313 | #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ |
314 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 314 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
315 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 315 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
316 | defined(CONFIG_ARCH_SH73A0) || \ | 316 | defined(CONFIG_ARCH_SH7367) |
317 | defined(CONFIG_ARCH_SH7367) || \ | ||
318 | defined(CONFIG_ARCH_SH7377) | ||
319 | 317 | ||
320 | SCIF_FNS(SCSMR, 0x00, 16) | 318 | SCIF_FNS(SCSMR, 0x00, 16) |
321 | SCIF_FNS(SCBRR, 0x04, 8) | 319 | SCIF_FNS(SCBRR, 0x04, 8) |
@@ -326,7 +324,9 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
326 | SCIF_FNS(SCxTDR, 0x20, 8) | 324 | SCIF_FNS(SCxTDR, 0x20, 8) |
327 | SCIF_FNS(SCxRDR, 0x24, 8) | 325 | SCIF_FNS(SCxRDR, 0x24, 8) |
328 | SCIF_FNS(SCLSR, 0x00, 0) | 326 | SCIF_FNS(SCLSR, 0x00, 0) |
329 | #elif defined(CONFIG_ARCH_SH7372) | 327 | #elif defined(CONFIG_ARCH_SH7377) || \ |
328 | defined(CONFIG_ARCH_SH7372) || \ | ||
329 | defined(CONFIG_ARCH_SH73A0) | ||
330 | SCIF_FNS(SCSMR, 0x00, 16) | 330 | SCIF_FNS(SCSMR, 0x00, 16) |
331 | SCIF_FNS(SCBRR, 0x04, 8) | 331 | SCIF_FNS(SCBRR, 0x04, 8) |
332 | SCIF_FNS(SCSCR, 0x08, 16) | 332 | SCIF_FNS(SCSCR, 0x08, 16) |
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 322bf56c0d89..37fc4e3d487c 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/serial/vt8500_serial.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | 2 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> |
5 | * | 3 | * |
6 | * Based on msm_serial.c, which is: | 4 | * Based on msm_serial.c, which is: |
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c new file mode 100644 index 000000000000..19cc1e8149dd --- /dev/null +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | /* | ||
2 | * Xilinx PS UART driver | ||
3 | * | ||
4 | * 2011 (c) Xilinx Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it | ||
7 | * and/or modify it under the terms of the GNU General Public | ||
8 | * License as published by the Free Software Foundation; | ||
9 | * either version 2 of the License, or (at your option) any | ||
10 | * later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/serial_core.h> | ||
16 | #include <linux/console.h> | ||
17 | #include <linux/serial.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/of.h> | ||
21 | |||
22 | #define XUARTPS_TTY_NAME "ttyPS" | ||
23 | #define XUARTPS_NAME "xuartps" | ||
24 | #define XUARTPS_MAJOR 0 /* use dynamic node allocation */ | ||
25 | #define XUARTPS_MINOR 0 /* works best with devtmpfs */ | ||
26 | #define XUARTPS_NR_PORTS 2 | ||
27 | #define XUARTPS_FIFO_SIZE 16 /* FIFO size */ | ||
28 | #define XUARTPS_REGISTER_SPACE 0xFFF | ||
29 | |||
30 | #define xuartps_readl(offset) ioread32(port->membase + offset) | ||
31 | #define xuartps_writel(val, offset) iowrite32(val, port->membase + offset) | ||
32 | |||
33 | /********************************Register Map********************************/ | ||
34 | /** UART | ||
35 | * | ||
36 | * Register offsets for the UART. | ||
37 | * | ||
38 | */ | ||
39 | #define XUARTPS_CR_OFFSET 0x00 /* Control Register [8:0] */ | ||
40 | #define XUARTPS_MR_OFFSET 0x04 /* Mode Register [10:0] */ | ||
41 | #define XUARTPS_IER_OFFSET 0x08 /* Interrupt Enable [10:0] */ | ||
42 | #define XUARTPS_IDR_OFFSET 0x0C /* Interrupt Disable [10:0] */ | ||
43 | #define XUARTPS_IMR_OFFSET 0x10 /* Interrupt Mask [10:0] */ | ||
44 | #define XUARTPS_ISR_OFFSET 0x14 /* Interrupt Status [10:0]*/ | ||
45 | #define XUARTPS_BAUDGEN_OFFSET 0x18 /* Baud Rate Generator [15:0] */ | ||
46 | #define XUARTPS_RXTOUT_OFFSET 0x1C /* RX Timeout [7:0] */ | ||
47 | #define XUARTPS_RXWM_OFFSET 0x20 /* RX FIFO Trigger Level [5:0] */ | ||
48 | #define XUARTPS_MODEMCR_OFFSET 0x24 /* Modem Control [5:0] */ | ||
49 | #define XUARTPS_MODEMSR_OFFSET 0x28 /* Modem Status [8:0] */ | ||
50 | #define XUARTPS_SR_OFFSET 0x2C /* Channel Status [11:0] */ | ||
51 | #define XUARTPS_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */ | ||
52 | #define XUARTPS_BAUDDIV_OFFSET 0x34 /* Baud Rate Divider [7:0] */ | ||
53 | #define XUARTPS_FLOWDEL_OFFSET 0x38 /* Flow Delay [15:0] */ | ||
54 | #define XUARTPS_IRRX_PWIDTH_OFFSET 0x3C /* IR Minimum Received Pulse | ||
55 | Width [15:0] */ | ||
56 | #define XUARTPS_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse | ||
57 | Width [7:0] */ | ||
58 | #define XUARTPS_TXWM_OFFSET 0x44 /* TX FIFO Trigger Level [5:0] */ | ||
59 | |||
60 | /** Control Register | ||
61 | * | ||
62 | * The Control register (CR) controls the major functions of the device. | ||
63 | * | ||
64 | * Control Register Bit Definitions | ||
65 | */ | ||
66 | #define XUARTPS_CR_STOPBRK 0x00000100 /* Stop TX break */ | ||
67 | #define XUARTPS_CR_STARTBRK 0x00000080 /* Set TX break */ | ||
68 | #define XUARTPS_CR_TX_DIS 0x00000020 /* TX disabled. */ | ||
69 | #define XUARTPS_CR_TX_EN 0x00000010 /* TX enabled */ | ||
70 | #define XUARTPS_CR_RX_DIS 0x00000008 /* RX disabled. */ | ||
71 | #define XUARTPS_CR_RX_EN 0x00000004 /* RX enabled */ | ||
72 | #define XUARTPS_CR_TXRST 0x00000002 /* TX logic reset */ | ||
73 | #define XUARTPS_CR_RXRST 0x00000001 /* RX logic reset */ | ||
74 | #define XUARTPS_CR_RST_TO 0x00000040 /* Restart Timeout Counter */ | ||
75 | |||
76 | /** Mode Register | ||
77 | * | ||
78 | * The mode register (MR) defines the mode of transfer as well as the data | ||
79 | * format. If this register is modified during transmission or reception, | ||
80 | * data validity cannot be guaranteed. | ||
81 | * | ||
82 | * Mode Register Bit Definitions | ||
83 | * | ||
84 | */ | ||
85 | #define XUARTPS_MR_CLKSEL 0x00000001 /* Pre-scalar selection */ | ||
86 | #define XUARTPS_MR_CHMODE_L_LOOP 0x00000200 /* Local loop back mode */ | ||
87 | #define XUARTPS_MR_CHMODE_NORM 0x00000000 /* Normal mode */ | ||
88 | |||
89 | #define XUARTPS_MR_STOPMODE_2_BIT 0x00000080 /* 2 stop bits */ | ||
90 | #define XUARTPS_MR_STOPMODE_1_BIT 0x00000000 /* 1 stop bit */ | ||
91 | |||
92 | #define XUARTPS_MR_PARITY_NONE 0x00000020 /* No parity mode */ | ||
93 | #define XUARTPS_MR_PARITY_MARK 0x00000018 /* Mark parity mode */ | ||
94 | #define XUARTPS_MR_PARITY_SPACE 0x00000010 /* Space parity mode */ | ||
95 | #define XUARTPS_MR_PARITY_ODD 0x00000008 /* Odd parity mode */ | ||
96 | #define XUARTPS_MR_PARITY_EVEN 0x00000000 /* Even parity mode */ | ||
97 | |||
98 | #define XUARTPS_MR_CHARLEN_6_BIT 0x00000006 /* 6 bits data */ | ||
99 | #define XUARTPS_MR_CHARLEN_7_BIT 0x00000004 /* 7 bits data */ | ||
100 | #define XUARTPS_MR_CHARLEN_8_BIT 0x00000000 /* 8 bits data */ | ||
101 | |||
102 | /** Interrupt Registers | ||
103 | * | ||
104 | * Interrupt control logic uses the interrupt enable register (IER) and the | ||
105 | * interrupt disable register (IDR) to set the value of the bits in the | ||
106 | * interrupt mask register (IMR). The IMR determines whether to pass an | ||
107 | * interrupt to the interrupt status register (ISR). | ||
108 | * Writing a 1 to IER Enables an interrupt, writing a 1 to IDR disables an | ||
109 | * interrupt. IMR and ISR are read only, and IER and IDR are write only. | ||
110 | * Reading either IER or IDR returns 0x00. | ||
111 | * | ||
112 | * All four registers have the same bit definitions. | ||
113 | */ | ||
114 | #define XUARTPS_IXR_TOUT 0x00000100 /* RX Timeout error interrupt */ | ||
115 | #define XUARTPS_IXR_PARITY 0x00000080 /* Parity error interrupt */ | ||
116 | #define XUARTPS_IXR_FRAMING 0x00000040 /* Framing error interrupt */ | ||
117 | #define XUARTPS_IXR_OVERRUN 0x00000020 /* Overrun error interrupt */ | ||
118 | #define XUARTPS_IXR_TXFULL 0x00000010 /* TX FIFO Full interrupt */ | ||
119 | #define XUARTPS_IXR_TXEMPTY 0x00000008 /* TX FIFO empty interrupt */ | ||
120 | #define XUARTPS_ISR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt */ | ||
121 | #define XUARTPS_IXR_RXTRIG 0x00000001 /* RX FIFO trigger interrupt */ | ||
122 | #define XUARTPS_IXR_RXFULL 0x00000004 /* RX FIFO full interrupt. */ | ||
123 | #define XUARTPS_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ | ||
124 | #define XUARTPS_IXR_MASK 0x00001FFF /* Valid bit mask */ | ||
125 | |||
126 | /** Channel Status Register | ||
127 | * | ||
128 | * The channel status register (CSR) is provided to enable the control logic | ||
129 | * to monitor the status of bits in the channel interrupt status register, | ||
130 | * even if these are masked out by the interrupt mask register. | ||
131 | */ | ||
132 | #define XUARTPS_SR_RXEMPTY 0x00000002 /* RX FIFO empty */ | ||
133 | #define XUARTPS_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ | ||
134 | #define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ | ||
135 | #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ | ||
136 | |||
137 | /** | ||
138 | * xuartps_isr - Interrupt handler | ||
139 | * @irq: Irq number | ||
140 | * @dev_id: Id of the port | ||
141 | * | ||
142 | * Returns IRQHANDLED | ||
143 | **/ | ||
144 | static irqreturn_t xuartps_isr(int irq, void *dev_id) | ||
145 | { | ||
146 | struct uart_port *port = (struct uart_port *)dev_id; | ||
147 | struct tty_struct *tty; | ||
148 | unsigned long flags; | ||
149 | unsigned int isrstatus, numbytes; | ||
150 | unsigned int data; | ||
151 | char status = TTY_NORMAL; | ||
152 | |||
153 | /* Get the tty which could be NULL so don't assume it's valid */ | ||
154 | tty = tty_port_tty_get(&port->state->port); | ||
155 | |||
156 | spin_lock_irqsave(&port->lock, flags); | ||
157 | |||
158 | /* Read the interrupt status register to determine which | ||
159 | * interrupt(s) is/are active. | ||
160 | */ | ||
161 | isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); | ||
162 | |||
163 | /* drop byte with parity error if IGNPAR specified */ | ||
164 | if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) | ||
165 | isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); | ||
166 | |||
167 | isrstatus &= port->read_status_mask; | ||
168 | isrstatus &= ~port->ignore_status_mask; | ||
169 | |||
170 | if ((isrstatus & XUARTPS_IXR_TOUT) || | ||
171 | (isrstatus & XUARTPS_IXR_RXTRIG)) { | ||
172 | /* Receive Timeout Interrupt */ | ||
173 | while ((xuartps_readl(XUARTPS_SR_OFFSET) & | ||
174 | XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { | ||
175 | data = xuartps_readl(XUARTPS_FIFO_OFFSET); | ||
176 | port->icount.rx++; | ||
177 | |||
178 | if (isrstatus & XUARTPS_IXR_PARITY) { | ||
179 | port->icount.parity++; | ||
180 | status = TTY_PARITY; | ||
181 | } else if (isrstatus & XUARTPS_IXR_FRAMING) { | ||
182 | port->icount.frame++; | ||
183 | status = TTY_FRAME; | ||
184 | } else if (isrstatus & XUARTPS_IXR_OVERRUN) | ||
185 | port->icount.overrun++; | ||
186 | |||
187 | if (tty) | ||
188 | uart_insert_char(port, isrstatus, | ||
189 | XUARTPS_IXR_OVERRUN, data, | ||
190 | status); | ||
191 | } | ||
192 | spin_unlock(&port->lock); | ||
193 | if (tty) | ||
194 | tty_flip_buffer_push(tty); | ||
195 | spin_lock(&port->lock); | ||
196 | } | ||
197 | |||
198 | /* Dispatch an appropriate handler */ | ||
199 | if ((isrstatus & XUARTPS_IXR_TXEMPTY) == XUARTPS_IXR_TXEMPTY) { | ||
200 | if (uart_circ_empty(&port->state->xmit)) { | ||
201 | xuartps_writel(XUARTPS_IXR_TXEMPTY, | ||
202 | XUARTPS_IDR_OFFSET); | ||
203 | } else { | ||
204 | numbytes = port->fifosize; | ||
205 | /* Break if no more data available in the UART buffer */ | ||
206 | while (numbytes--) { | ||
207 | if (uart_circ_empty(&port->state->xmit)) | ||
208 | break; | ||
209 | /* Get the data from the UART circular buffer | ||
210 | * and write it to the xuartps's TX_FIFO | ||
211 | * register. | ||
212 | */ | ||
213 | xuartps_writel( | ||
214 | port->state->xmit.buf[port->state->xmit. | ||
215 | tail], XUARTPS_FIFO_OFFSET); | ||
216 | |||
217 | port->icount.tx++; | ||
218 | |||
219 | /* Adjust the tail of the UART buffer and wrap | ||
220 | * the buffer if it reaches limit. | ||
221 | */ | ||
222 | port->state->xmit.tail = | ||
223 | (port->state->xmit.tail + 1) & \ | ||
224 | (UART_XMIT_SIZE - 1); | ||
225 | } | ||
226 | |||
227 | if (uart_circ_chars_pending( | ||
228 | &port->state->xmit) < WAKEUP_CHARS) | ||
229 | uart_write_wakeup(port); | ||
230 | } | ||
231 | } | ||
232 | |||
233 | xuartps_writel(isrstatus, XUARTPS_ISR_OFFSET); | ||
234 | |||
235 | /* be sure to release the lock and tty before leaving */ | ||
236 | spin_unlock_irqrestore(&port->lock, flags); | ||
237 | tty_kref_put(tty); | ||
238 | |||
239 | return IRQ_HANDLED; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * xuartps_set_baud_rate - Calculate and set the baud rate | ||
244 | * @port: Handle to the uart port structure | ||
245 | * @baud: Baud rate to set | ||
246 | * | ||
247 | * Returns baud rate, requested baud when possible, or actual baud when there | ||
248 | * was too much error | ||
249 | **/ | ||
250 | static unsigned int xuartps_set_baud_rate(struct uart_port *port, | ||
251 | unsigned int baud) | ||
252 | { | ||
253 | unsigned int sel_clk; | ||
254 | unsigned int calc_baud = 0; | ||
255 | unsigned int brgr_val, brdiv_val; | ||
256 | unsigned int bauderror; | ||
257 | |||
258 | /* Formula to obtain baud rate is | ||
259 | * baud_tx/rx rate = sel_clk/CD * (BDIV + 1) | ||
260 | * input_clk = (Uart User Defined Clock or Apb Clock) | ||
261 | * depends on UCLKEN in MR Reg | ||
262 | * sel_clk = input_clk or input_clk/8; | ||
263 | * depends on CLKS in MR reg | ||
264 | * CD and BDIV depends on values in | ||
265 | * baud rate generate register | ||
266 | * baud rate clock divisor register | ||
267 | */ | ||
268 | sel_clk = port->uartclk; | ||
269 | if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL) | ||
270 | sel_clk = sel_clk / 8; | ||
271 | |||
272 | /* Find the best values for baud generation */ | ||
273 | for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) { | ||
274 | |||
275 | brgr_val = sel_clk / (baud * (brdiv_val + 1)); | ||
276 | if (brgr_val < 2 || brgr_val > 65535) | ||
277 | continue; | ||
278 | |||
279 | calc_baud = sel_clk / (brgr_val * (brdiv_val + 1)); | ||
280 | |||
281 | if (baud > calc_baud) | ||
282 | bauderror = baud - calc_baud; | ||
283 | else | ||
284 | bauderror = calc_baud - baud; | ||
285 | |||
286 | /* use the values when percent error is acceptable */ | ||
287 | if (((bauderror * 100) / baud) < 3) { | ||
288 | calc_baud = baud; | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /* Set the values for the new baud rate */ | ||
294 | xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET); | ||
295 | xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET); | ||
296 | |||
297 | return calc_baud; | ||
298 | } | ||
299 | |||
300 | /*----------------------Uart Operations---------------------------*/ | ||
301 | |||
302 | /** | ||
303 | * xuartps_start_tx - Start transmitting bytes | ||
304 | * @port: Handle to the uart port structure | ||
305 | * | ||
306 | **/ | ||
307 | static void xuartps_start_tx(struct uart_port *port) | ||
308 | { | ||
309 | unsigned int status, numbytes = port->fifosize; | ||
310 | |||
311 | if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) | ||
312 | return; | ||
313 | |||
314 | status = xuartps_readl(XUARTPS_CR_OFFSET); | ||
315 | /* Set the TX enable bit and clear the TX disable bit to enable the | ||
316 | * transmitter. | ||
317 | */ | ||
318 | xuartps_writel((status & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, | ||
319 | XUARTPS_CR_OFFSET); | ||
320 | |||
321 | while (numbytes-- && ((xuartps_readl(XUARTPS_SR_OFFSET) | ||
322 | & XUARTPS_SR_TXFULL)) != XUARTPS_SR_TXFULL) { | ||
323 | |||
324 | /* Break if no more data available in the UART buffer */ | ||
325 | if (uart_circ_empty(&port->state->xmit)) | ||
326 | break; | ||
327 | |||
328 | /* Get the data from the UART circular buffer and | ||
329 | * write it to the xuartps's TX_FIFO register. | ||
330 | */ | ||
331 | xuartps_writel( | ||
332 | port->state->xmit.buf[port->state->xmit.tail], | ||
333 | XUARTPS_FIFO_OFFSET); | ||
334 | port->icount.tx++; | ||
335 | |||
336 | /* Adjust the tail of the UART buffer and wrap | ||
337 | * the buffer if it reaches limit. | ||
338 | */ | ||
339 | port->state->xmit.tail = (port->state->xmit.tail + 1) & | ||
340 | (UART_XMIT_SIZE - 1); | ||
341 | } | ||
342 | |||
343 | /* Enable the TX Empty interrupt */ | ||
344 | xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET); | ||
345 | |||
346 | if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) | ||
347 | uart_write_wakeup(port); | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * xuartps_stop_tx - Stop TX | ||
352 | * @port: Handle to the uart port structure | ||
353 | * | ||
354 | **/ | ||
355 | static void xuartps_stop_tx(struct uart_port *port) | ||
356 | { | ||
357 | unsigned int regval; | ||
358 | |||
359 | regval = xuartps_readl(XUARTPS_CR_OFFSET); | ||
360 | regval |= XUARTPS_CR_TX_DIS; | ||
361 | /* Disable the transmitter */ | ||
362 | xuartps_writel(regval, XUARTPS_CR_OFFSET); | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * xuartps_stop_rx - Stop RX | ||
367 | * @port: Handle to the uart port structure | ||
368 | * | ||
369 | **/ | ||
370 | static void xuartps_stop_rx(struct uart_port *port) | ||
371 | { | ||
372 | unsigned int regval; | ||
373 | |||
374 | regval = xuartps_readl(XUARTPS_CR_OFFSET); | ||
375 | regval |= XUARTPS_CR_RX_DIS; | ||
376 | /* Disable the receiver */ | ||
377 | xuartps_writel(regval, XUARTPS_CR_OFFSET); | ||
378 | } | ||
379 | |||
380 | /** | ||
381 | * xuartps_tx_empty - Check whether TX is empty | ||
382 | * @port: Handle to the uart port structure | ||
383 | * | ||
384 | * Returns TIOCSER_TEMT on success, 0 otherwise | ||
385 | **/ | ||
386 | static unsigned int xuartps_tx_empty(struct uart_port *port) | ||
387 | { | ||
388 | unsigned int status; | ||
389 | |||
390 | status = xuartps_readl(XUARTPS_ISR_OFFSET) & XUARTPS_IXR_TXEMPTY; | ||
391 | return status ? TIOCSER_TEMT : 0; | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * xuartps_break_ctl - Based on the input ctl we have to start or stop | ||
396 | * transmitting char breaks | ||
397 | * @port: Handle to the uart port structure | ||
398 | * @ctl: Value based on which start or stop decision is taken | ||
399 | * | ||
400 | **/ | ||
401 | static void xuartps_break_ctl(struct uart_port *port, int ctl) | ||
402 | { | ||
403 | unsigned int status; | ||
404 | unsigned long flags; | ||
405 | |||
406 | spin_lock_irqsave(&port->lock, flags); | ||
407 | |||
408 | status = xuartps_readl(XUARTPS_CR_OFFSET); | ||
409 | |||
410 | if (ctl == -1) | ||
411 | xuartps_writel(XUARTPS_CR_STARTBRK | status, | ||
412 | XUARTPS_CR_OFFSET); | ||
413 | else { | ||
414 | if ((status & XUARTPS_CR_STOPBRK) == 0) | ||
415 | xuartps_writel(XUARTPS_CR_STOPBRK | status, | ||
416 | XUARTPS_CR_OFFSET); | ||
417 | } | ||
418 | spin_unlock_irqrestore(&port->lock, flags); | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * xuartps_set_termios - termios operations, handling data length, parity, | ||
423 | * stop bits, flow control, baud rate | ||
424 | * @port: Handle to the uart port structure | ||
425 | * @termios: Handle to the input termios structure | ||
426 | * @old: Values of the previously saved termios structure | ||
427 | * | ||
428 | **/ | ||
429 | static void xuartps_set_termios(struct uart_port *port, | ||
430 | struct ktermios *termios, struct ktermios *old) | ||
431 | { | ||
432 | unsigned int cval = 0; | ||
433 | unsigned int baud; | ||
434 | unsigned long flags; | ||
435 | unsigned int ctrl_reg, mode_reg; | ||
436 | |||
437 | spin_lock_irqsave(&port->lock, flags); | ||
438 | |||
439 | /* Empty the receive FIFO 1st before making changes */ | ||
440 | while ((xuartps_readl(XUARTPS_SR_OFFSET) & | ||
441 | XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { | ||
442 | xuartps_readl(XUARTPS_FIFO_OFFSET); | ||
443 | } | ||
444 | |||
445 | /* Disable the TX and RX to set baud rate */ | ||
446 | xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | | ||
447 | (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), | ||
448 | XUARTPS_CR_OFFSET); | ||
449 | |||
450 | /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ | ||
451 | baud = uart_get_baud_rate(port, termios, old, 0, 10000000); | ||
452 | baud = xuartps_set_baud_rate(port, baud); | ||
453 | if (tty_termios_baud_rate(termios)) | ||
454 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
455 | |||
456 | /* | ||
457 | * Update the per-port timeout. | ||
458 | */ | ||
459 | uart_update_timeout(port, termios->c_cflag, baud); | ||
460 | |||
461 | /* Set TX/RX Reset */ | ||
462 | xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | | ||
463 | (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), | ||
464 | XUARTPS_CR_OFFSET); | ||
465 | |||
466 | ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); | ||
467 | |||
468 | /* Clear the RX disable and TX disable bits and then set the TX enable | ||
469 | * bit and RX enable bit to enable the transmitter and receiver. | ||
470 | */ | ||
471 | xuartps_writel( | ||
472 | (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | ||
473 | | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), | ||
474 | XUARTPS_CR_OFFSET); | ||
475 | |||
476 | xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); | ||
477 | |||
478 | port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | | ||
479 | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; | ||
480 | port->ignore_status_mask = 0; | ||
481 | |||
482 | if (termios->c_iflag & INPCK) | ||
483 | port->read_status_mask |= XUARTPS_IXR_PARITY | | ||
484 | XUARTPS_IXR_FRAMING; | ||
485 | |||
486 | if (termios->c_iflag & IGNPAR) | ||
487 | port->ignore_status_mask |= XUARTPS_IXR_PARITY | | ||
488 | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; | ||
489 | |||
490 | /* ignore all characters if CREAD is not set */ | ||
491 | if ((termios->c_cflag & CREAD) == 0) | ||
492 | port->ignore_status_mask |= XUARTPS_IXR_RXTRIG | | ||
493 | XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | | ||
494 | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; | ||
495 | |||
496 | mode_reg = xuartps_readl(XUARTPS_MR_OFFSET); | ||
497 | |||
498 | /* Handling Data Size */ | ||
499 | switch (termios->c_cflag & CSIZE) { | ||
500 | case CS6: | ||
501 | cval |= XUARTPS_MR_CHARLEN_6_BIT; | ||
502 | break; | ||
503 | case CS7: | ||
504 | cval |= XUARTPS_MR_CHARLEN_7_BIT; | ||
505 | break; | ||
506 | default: | ||
507 | case CS8: | ||
508 | cval |= XUARTPS_MR_CHARLEN_8_BIT; | ||
509 | termios->c_cflag &= ~CSIZE; | ||
510 | termios->c_cflag |= CS8; | ||
511 | break; | ||
512 | } | ||
513 | |||
514 | /* Handling Parity and Stop Bits length */ | ||
515 | if (termios->c_cflag & CSTOPB) | ||
516 | cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */ | ||
517 | else | ||
518 | cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */ | ||
519 | |||
520 | if (termios->c_cflag & PARENB) { | ||
521 | /* Mark or Space parity */ | ||
522 | if (termios->c_cflag & CMSPAR) { | ||
523 | if (termios->c_cflag & PARODD) | ||
524 | cval |= XUARTPS_MR_PARITY_MARK; | ||
525 | else | ||
526 | cval |= XUARTPS_MR_PARITY_SPACE; | ||
527 | } else if (termios->c_cflag & PARODD) | ||
528 | cval |= XUARTPS_MR_PARITY_ODD; | ||
529 | else | ||
530 | cval |= XUARTPS_MR_PARITY_EVEN; | ||
531 | } else | ||
532 | cval |= XUARTPS_MR_PARITY_NONE; | ||
533 | xuartps_writel(cval , XUARTPS_MR_OFFSET); | ||
534 | |||
535 | spin_unlock_irqrestore(&port->lock, flags); | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * xuartps_startup - Called when an application opens a xuartps port | ||
540 | * @port: Handle to the uart port structure | ||
541 | * | ||
542 | * Returns 0 on success, negative error otherwise | ||
543 | **/ | ||
544 | static int xuartps_startup(struct uart_port *port) | ||
545 | { | ||
546 | unsigned int retval = 0, status = 0; | ||
547 | |||
548 | retval = request_irq(port->irq, xuartps_isr, 0, XUARTPS_NAME, | ||
549 | (void *)port); | ||
550 | if (retval) | ||
551 | return retval; | ||
552 | |||
553 | /* Disable the TX and RX */ | ||
554 | xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS, | ||
555 | XUARTPS_CR_OFFSET); | ||
556 | |||
557 | /* Set the Control Register with TX/RX Enable, TX/RX Reset, | ||
558 | * no break chars. | ||
559 | */ | ||
560 | xuartps_writel(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST, | ||
561 | XUARTPS_CR_OFFSET); | ||
562 | |||
563 | status = xuartps_readl(XUARTPS_CR_OFFSET); | ||
564 | |||
565 | /* Clear the RX disable and TX disable bits and then set the TX enable | ||
566 | * bit and RX enable bit to enable the transmitter and receiver. | ||
567 | */ | ||
568 | xuartps_writel((status & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | ||
569 | | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN | | ||
570 | XUARTPS_CR_STOPBRK), XUARTPS_CR_OFFSET); | ||
571 | |||
572 | /* Set the Mode Register with normal mode,8 data bits,1 stop bit, | ||
573 | * no parity. | ||
574 | */ | ||
575 | xuartps_writel(XUARTPS_MR_CHMODE_NORM | XUARTPS_MR_STOPMODE_1_BIT | ||
576 | | XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT, | ||
577 | XUARTPS_MR_OFFSET); | ||
578 | |||
579 | /* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */ | ||
580 | xuartps_writel(14, XUARTPS_RXWM_OFFSET); | ||
581 | |||
582 | /* Receive Timeout register is enabled with value of 10 */ | ||
583 | xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); | ||
584 | |||
585 | |||
586 | /* Set the Interrupt Registers with desired interrupts */ | ||
587 | xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | | ||
588 | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | | ||
589 | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET); | ||
590 | xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | | ||
591 | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | | ||
592 | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET); | ||
593 | |||
594 | return retval; | ||
595 | } | ||
596 | |||
597 | /** | ||
598 | * xuartps_shutdown - Called when an application closes a xuartps port | ||
599 | * @port: Handle to the uart port structure | ||
600 | * | ||
601 | **/ | ||
602 | static void xuartps_shutdown(struct uart_port *port) | ||
603 | { | ||
604 | int status; | ||
605 | |||
606 | /* Disable interrupts */ | ||
607 | status = xuartps_readl(XUARTPS_IMR_OFFSET); | ||
608 | xuartps_writel(status, XUARTPS_IDR_OFFSET); | ||
609 | |||
610 | /* Disable the TX and RX */ | ||
611 | xuartps_writel(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS, | ||
612 | XUARTPS_CR_OFFSET); | ||
613 | free_irq(port->irq, port); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * xuartps_type - Set UART type to xuartps port | ||
618 | * @port: Handle to the uart port structure | ||
619 | * | ||
620 | * Returns string on success, NULL otherwise | ||
621 | **/ | ||
622 | static const char *xuartps_type(struct uart_port *port) | ||
623 | { | ||
624 | return port->type == PORT_XUARTPS ? XUARTPS_NAME : NULL; | ||
625 | } | ||
626 | |||
627 | /** | ||
628 | * xuartps_verify_port - Verify the port params | ||
629 | * @port: Handle to the uart port structure | ||
630 | * @ser: Handle to the structure whose members are compared | ||
631 | * | ||
632 | * Returns 0 if success otherwise -EINVAL | ||
633 | **/ | ||
634 | static int xuartps_verify_port(struct uart_port *port, | ||
635 | struct serial_struct *ser) | ||
636 | { | ||
637 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_XUARTPS) | ||
638 | return -EINVAL; | ||
639 | if (port->irq != ser->irq) | ||
640 | return -EINVAL; | ||
641 | if (ser->io_type != UPIO_MEM) | ||
642 | return -EINVAL; | ||
643 | if (port->iobase != ser->port) | ||
644 | return -EINVAL; | ||
645 | if (ser->hub6 != 0) | ||
646 | return -EINVAL; | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | /** | ||
651 | * xuartps_request_port - Claim the memory region attached to xuartps port, | ||
652 | * called when the driver adds a xuartps port via | ||
653 | * uart_add_one_port() | ||
654 | * @port: Handle to the uart port structure | ||
655 | * | ||
656 | * Returns 0, -ENOMEM if request fails | ||
657 | **/ | ||
658 | static int xuartps_request_port(struct uart_port *port) | ||
659 | { | ||
660 | if (!request_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE, | ||
661 | XUARTPS_NAME)) { | ||
662 | return -ENOMEM; | ||
663 | } | ||
664 | |||
665 | port->membase = ioremap(port->mapbase, XUARTPS_REGISTER_SPACE); | ||
666 | if (!port->membase) { | ||
667 | dev_err(port->dev, "Unable to map registers\n"); | ||
668 | release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE); | ||
669 | return -ENOMEM; | ||
670 | } | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * xuartps_release_port - Release the memory region attached to a xuartps | ||
676 | * port, called when the driver removes a xuartps | ||
677 | * port via uart_remove_one_port(). | ||
678 | * @port: Handle to the uart port structure | ||
679 | * | ||
680 | **/ | ||
681 | static void xuartps_release_port(struct uart_port *port) | ||
682 | { | ||
683 | release_mem_region(port->mapbase, XUARTPS_REGISTER_SPACE); | ||
684 | iounmap(port->membase); | ||
685 | port->membase = NULL; | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * xuartps_config_port - Configure xuartps, called when the driver adds a | ||
690 | * xuartps port | ||
691 | * @port: Handle to the uart port structure | ||
692 | * @flags: If any | ||
693 | * | ||
694 | **/ | ||
695 | static void xuartps_config_port(struct uart_port *port, int flags) | ||
696 | { | ||
697 | if (flags & UART_CONFIG_TYPE && xuartps_request_port(port) == 0) | ||
698 | port->type = PORT_XUARTPS; | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * xuartps_get_mctrl - Get the modem control state | ||
703 | * | ||
704 | * @port: Handle to the uart port structure | ||
705 | * | ||
706 | * Returns the modem control state | ||
707 | * | ||
708 | **/ | ||
709 | static unsigned int xuartps_get_mctrl(struct uart_port *port) | ||
710 | { | ||
711 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
712 | } | ||
713 | |||
714 | static void xuartps_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
715 | { | ||
716 | /* N/A */ | ||
717 | } | ||
718 | |||
719 | static void xuartps_enable_ms(struct uart_port *port) | ||
720 | { | ||
721 | /* N/A */ | ||
722 | } | ||
723 | |||
724 | /** The UART operations structure | ||
725 | */ | ||
726 | static struct uart_ops xuartps_ops = { | ||
727 | .set_mctrl = xuartps_set_mctrl, | ||
728 | .get_mctrl = xuartps_get_mctrl, | ||
729 | .enable_ms = xuartps_enable_ms, | ||
730 | |||
731 | .start_tx = xuartps_start_tx, /* Start transmitting */ | ||
732 | .stop_tx = xuartps_stop_tx, /* Stop transmission */ | ||
733 | .stop_rx = xuartps_stop_rx, /* Stop reception */ | ||
734 | .tx_empty = xuartps_tx_empty, /* Transmitter busy? */ | ||
735 | .break_ctl = xuartps_break_ctl, /* Start/stop | ||
736 | * transmitting break | ||
737 | */ | ||
738 | .set_termios = xuartps_set_termios, /* Set termios */ | ||
739 | .startup = xuartps_startup, /* App opens xuartps */ | ||
740 | .shutdown = xuartps_shutdown, /* App closes xuartps */ | ||
741 | .type = xuartps_type, /* Set UART type */ | ||
742 | .verify_port = xuartps_verify_port, /* Verification of port | ||
743 | * params | ||
744 | */ | ||
745 | .request_port = xuartps_request_port, /* Claim resources | ||
746 | * associated with a | ||
747 | * xuartps port | ||
748 | */ | ||
749 | .release_port = xuartps_release_port, /* Release resources | ||
750 | * associated with a | ||
751 | * xuartps port | ||
752 | */ | ||
753 | .config_port = xuartps_config_port, /* Configure when driver | ||
754 | * adds a xuartps port | ||
755 | */ | ||
756 | }; | ||
757 | |||
758 | static struct uart_port xuartps_port[2]; | ||
759 | |||
760 | /** | ||
761 | * xuartps_get_port - Configure the port from the platform device resource | ||
762 | * info | ||
763 | * | ||
764 | * Returns a pointer to a uart_port or NULL for failure | ||
765 | **/ | ||
766 | static struct uart_port *xuartps_get_port(void) | ||
767 | { | ||
768 | struct uart_port *port; | ||
769 | int id; | ||
770 | |||
771 | /* Find the next unused port */ | ||
772 | for (id = 0; id < XUARTPS_NR_PORTS; id++) | ||
773 | if (xuartps_port[id].mapbase == 0) | ||
774 | break; | ||
775 | |||
776 | if (id >= XUARTPS_NR_PORTS) | ||
777 | return NULL; | ||
778 | |||
779 | port = &xuartps_port[id]; | ||
780 | |||
781 | /* At this point, we've got an empty uart_port struct, initialize it */ | ||
782 | spin_lock_init(&port->lock); | ||
783 | port->membase = NULL; | ||
784 | port->iobase = 1; /* mark port in use */ | ||
785 | port->irq = 0; | ||
786 | port->type = PORT_UNKNOWN; | ||
787 | port->iotype = UPIO_MEM32; | ||
788 | port->flags = UPF_BOOT_AUTOCONF; | ||
789 | port->ops = &xuartps_ops; | ||
790 | port->fifosize = XUARTPS_FIFO_SIZE; | ||
791 | port->line = id; | ||
792 | port->dev = NULL; | ||
793 | return port; | ||
794 | } | ||
795 | |||
796 | /*-----------------------Console driver operations--------------------------*/ | ||
797 | |||
798 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE | ||
799 | /** | ||
800 | * xuartps_console_wait_tx - Wait for the TX to be full | ||
801 | * @port: Handle to the uart port structure | ||
802 | * | ||
803 | **/ | ||
804 | static void xuartps_console_wait_tx(struct uart_port *port) | ||
805 | { | ||
806 | while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY) | ||
807 | != XUARTPS_SR_TXEMPTY) | ||
808 | barrier(); | ||
809 | } | ||
810 | |||
811 | /** | ||
812 | * xuartps_console_putchar - write the character to the FIFO buffer | ||
813 | * @port: Handle to the uart port structure | ||
814 | * @ch: Character to be written | ||
815 | * | ||
816 | **/ | ||
817 | static void xuartps_console_putchar(struct uart_port *port, int ch) | ||
818 | { | ||
819 | xuartps_console_wait_tx(port); | ||
820 | xuartps_writel(ch, XUARTPS_FIFO_OFFSET); | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * xuartps_console_write - perform write operation | ||
825 | * @port: Handle to the uart port structure | ||
826 | * @s: Pointer to character array | ||
827 | * @count: No of characters | ||
828 | **/ | ||
829 | static void xuartps_console_write(struct console *co, const char *s, | ||
830 | unsigned int count) | ||
831 | { | ||
832 | struct uart_port *port = &xuartps_port[co->index]; | ||
833 | unsigned long flags; | ||
834 | unsigned int imr; | ||
835 | int locked = 1; | ||
836 | |||
837 | if (oops_in_progress) | ||
838 | locked = spin_trylock_irqsave(&port->lock, flags); | ||
839 | else | ||
840 | spin_lock_irqsave(&port->lock, flags); | ||
841 | |||
842 | /* save and disable interrupt */ | ||
843 | imr = xuartps_readl(XUARTPS_IMR_OFFSET); | ||
844 | xuartps_writel(imr, XUARTPS_IDR_OFFSET); | ||
845 | |||
846 | uart_console_write(port, s, count, xuartps_console_putchar); | ||
847 | xuartps_console_wait_tx(port); | ||
848 | |||
849 | /* restore interrupt state, it seems like there may be a h/w bug | ||
850 | * in that the interrupt enable register should not need to be | ||
851 | * written based on the data sheet | ||
852 | */ | ||
853 | xuartps_writel(~imr, XUARTPS_IDR_OFFSET); | ||
854 | xuartps_writel(imr, XUARTPS_IER_OFFSET); | ||
855 | |||
856 | if (locked) | ||
857 | spin_unlock_irqrestore(&port->lock, flags); | ||
858 | } | ||
859 | |||
860 | /** | ||
861 | * xuartps_console_setup - Initialize the uart to default config | ||
862 | * @co: Console handle | ||
863 | * @options: Initial settings of uart | ||
864 | * | ||
865 | * Returns 0, -ENODEV if no device | ||
866 | **/ | ||
867 | static int __init xuartps_console_setup(struct console *co, char *options) | ||
868 | { | ||
869 | struct uart_port *port = &xuartps_port[co->index]; | ||
870 | int baud = 9600; | ||
871 | int bits = 8; | ||
872 | int parity = 'n'; | ||
873 | int flow = 'n'; | ||
874 | |||
875 | if (co->index < 0 || co->index >= XUARTPS_NR_PORTS) | ||
876 | return -EINVAL; | ||
877 | |||
878 | if (!port->mapbase) { | ||
879 | pr_debug("console on ttyPS%i not present\n", co->index); | ||
880 | return -ENODEV; | ||
881 | } | ||
882 | |||
883 | if (options) | ||
884 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
885 | |||
886 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
887 | } | ||
888 | |||
889 | static struct uart_driver xuartps_uart_driver; | ||
890 | |||
891 | static struct console xuartps_console = { | ||
892 | .name = XUARTPS_TTY_NAME, | ||
893 | .write = xuartps_console_write, | ||
894 | .device = uart_console_device, | ||
895 | .setup = xuartps_console_setup, | ||
896 | .flags = CON_PRINTBUFFER, | ||
897 | .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ | ||
898 | .data = &xuartps_uart_driver, | ||
899 | }; | ||
900 | |||
901 | /** | ||
902 | * xuartps_console_init - Initialization call | ||
903 | * | ||
904 | * Returns 0 on success, negative error otherwise | ||
905 | **/ | ||
906 | static int __init xuartps_console_init(void) | ||
907 | { | ||
908 | register_console(&xuartps_console); | ||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | console_initcall(xuartps_console_init); | ||
913 | |||
914 | #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ | ||
915 | |||
916 | /** Structure Definitions | ||
917 | */ | ||
918 | static struct uart_driver xuartps_uart_driver = { | ||
919 | .owner = THIS_MODULE, /* Owner */ | ||
920 | .driver_name = XUARTPS_NAME, /* Driver name */ | ||
921 | .dev_name = XUARTPS_TTY_NAME, /* Node name */ | ||
922 | .major = XUARTPS_MAJOR, /* Major number */ | ||
923 | .minor = XUARTPS_MINOR, /* Minor number */ | ||
924 | .nr = XUARTPS_NR_PORTS, /* Number of UART ports */ | ||
925 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE | ||
926 | .cons = &xuartps_console, /* Console */ | ||
927 | #endif | ||
928 | }; | ||
929 | |||
930 | /* --------------------------------------------------------------------- | ||
931 | * Platform bus binding | ||
932 | */ | ||
933 | /** | ||
934 | * xuartps_probe - Platform driver probe | ||
935 | * @pdev: Pointer to the platform device structure | ||
936 | * | ||
937 | * Returns 0 on success, negative error otherwise | ||
938 | **/ | ||
939 | static int __devinit xuartps_probe(struct platform_device *pdev) | ||
940 | { | ||
941 | int rc; | ||
942 | struct uart_port *port; | ||
943 | struct resource *res, *res2; | ||
944 | int clk = 0; | ||
945 | |||
946 | #ifdef CONFIG_OF | ||
947 | const unsigned int *prop; | ||
948 | |||
949 | prop = of_get_property(pdev->dev.of_node, "clock", NULL); | ||
950 | if (prop) | ||
951 | clk = be32_to_cpup(prop); | ||
952 | #else | ||
953 | clk = *((unsigned int *)(pdev->dev.platform_data)); | ||
954 | #endif | ||
955 | if (!clk) { | ||
956 | dev_err(&pdev->dev, "no clock specified\n"); | ||
957 | return -ENODEV; | ||
958 | } | ||
959 | |||
960 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
961 | if (!res) | ||
962 | return -ENODEV; | ||
963 | |||
964 | res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
965 | if (!res2) | ||
966 | return -ENODEV; | ||
967 | |||
968 | /* Initialize the port structure */ | ||
969 | port = xuartps_get_port(); | ||
970 | |||
971 | if (!port) { | ||
972 | dev_err(&pdev->dev, "Cannot get uart_port structure\n"); | ||
973 | return -ENODEV; | ||
974 | } else { | ||
975 | /* Register the port. | ||
976 | * This function also registers this device with the tty layer | ||
977 | * and triggers invocation of the config_port() entry point. | ||
978 | */ | ||
979 | port->mapbase = res->start; | ||
980 | port->irq = res2->start; | ||
981 | port->dev = &pdev->dev; | ||
982 | port->uartclk = clk; | ||
983 | dev_set_drvdata(&pdev->dev, port); | ||
984 | rc = uart_add_one_port(&xuartps_uart_driver, port); | ||
985 | if (rc) { | ||
986 | dev_err(&pdev->dev, | ||
987 | "uart_add_one_port() failed; err=%i\n", rc); | ||
988 | dev_set_drvdata(&pdev->dev, NULL); | ||
989 | return rc; | ||
990 | } | ||
991 | return 0; | ||
992 | } | ||
993 | } | ||
994 | |||
995 | /** | ||
996 | * xuartps_remove - called when the platform driver is unregistered | ||
997 | * @pdev: Pointer to the platform device structure | ||
998 | * | ||
999 | * Returns 0 on success, negative error otherwise | ||
1000 | **/ | ||
1001 | static int __devexit xuartps_remove(struct platform_device *pdev) | ||
1002 | { | ||
1003 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | ||
1004 | int rc = 0; | ||
1005 | |||
1006 | /* Remove the xuartps port from the serial core */ | ||
1007 | if (port) { | ||
1008 | rc = uart_remove_one_port(&xuartps_uart_driver, port); | ||
1009 | dev_set_drvdata(&pdev->dev, NULL); | ||
1010 | port->mapbase = 0; | ||
1011 | } | ||
1012 | return rc; | ||
1013 | } | ||
1014 | |||
1015 | /** | ||
1016 | * xuartps_suspend - suspend event | ||
1017 | * @pdev: Pointer to the platform device structure | ||
1018 | * @state: State of the device | ||
1019 | * | ||
1020 | * Returns 0 | ||
1021 | **/ | ||
1022 | static int xuartps_suspend(struct platform_device *pdev, pm_message_t state) | ||
1023 | { | ||
1024 | /* Call the API provided in serial_core.c file which handles | ||
1025 | * the suspend. | ||
1026 | */ | ||
1027 | uart_suspend_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | /** | ||
1032 | * xuartps_resume - Resume after a previous suspend | ||
1033 | * @pdev: Pointer to the platform device structure | ||
1034 | * | ||
1035 | * Returns 0 | ||
1036 | **/ | ||
1037 | static int xuartps_resume(struct platform_device *pdev) | ||
1038 | { | ||
1039 | uart_resume_port(&xuartps_uart_driver, &xuartps_port[pdev->id]); | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | /* Match table for of_platform binding */ | ||
1044 | |||
1045 | #ifdef CONFIG_OF | ||
1046 | static struct of_device_id xuartps_of_match[] __devinitdata = { | ||
1047 | { .compatible = "xlnx,xuartps", }, | ||
1048 | {} | ||
1049 | }; | ||
1050 | MODULE_DEVICE_TABLE(of, xuartps_of_match); | ||
1051 | #else | ||
1052 | #define xuartps_of_match NULL | ||
1053 | #endif | ||
1054 | |||
1055 | static struct platform_driver xuartps_platform_driver = { | ||
1056 | .probe = xuartps_probe, /* Probe method */ | ||
1057 | .remove = __exit_p(xuartps_remove), /* Detach method */ | ||
1058 | .suspend = xuartps_suspend, /* Suspend */ | ||
1059 | .resume = xuartps_resume, /* Resume after a suspend */ | ||
1060 | .driver = { | ||
1061 | .owner = THIS_MODULE, | ||
1062 | .name = XUARTPS_NAME, /* Driver name */ | ||
1063 | .of_match_table = xuartps_of_match, | ||
1064 | }, | ||
1065 | }; | ||
1066 | |||
1067 | /* --------------------------------------------------------------------- | ||
1068 | * Module Init and Exit | ||
1069 | */ | ||
1070 | /** | ||
1071 | * xuartps_init - Initial driver registration call | ||
1072 | * | ||
1073 | * Returns whether the registration was successful or not | ||
1074 | **/ | ||
1075 | static int __init xuartps_init(void) | ||
1076 | { | ||
1077 | int retval = 0; | ||
1078 | |||
1079 | /* Register the xuartps driver with the serial core */ | ||
1080 | retval = uart_register_driver(&xuartps_uart_driver); | ||
1081 | if (retval) | ||
1082 | return retval; | ||
1083 | |||
1084 | /* Register the platform driver */ | ||
1085 | retval = platform_driver_register(&xuartps_platform_driver); | ||
1086 | if (retval) | ||
1087 | uart_unregister_driver(&xuartps_uart_driver); | ||
1088 | |||
1089 | return retval; | ||
1090 | } | ||
1091 | |||
1092 | /** | ||
1093 | * xuartps_exit - Driver unregistration call | ||
1094 | **/ | ||
1095 | static void __exit xuartps_exit(void) | ||
1096 | { | ||
1097 | /* The order of unregistration is important. Unregister the | ||
1098 | * UART driver before the platform driver crashes the system. | ||
1099 | */ | ||
1100 | |||
1101 | /* Unregister the platform driver */ | ||
1102 | platform_driver_unregister(&xuartps_platform_driver); | ||
1103 | |||
1104 | /* Unregister the xuartps driver */ | ||
1105 | uart_unregister_driver(&xuartps_uart_driver); | ||
1106 | } | ||
1107 | |||
1108 | module_init(xuartps_init); | ||
1109 | module_exit(xuartps_exit); | ||
1110 | |||
1111 | MODULE_DESCRIPTION("Driver for PS UART"); | ||
1112 | MODULE_AUTHOR("Xilinx Inc."); | ||
1113 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 27da23d98e3f..272e417a9b0d 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/synclink.c | ||
3 | * | ||
4 | * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ | 2 | * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ |
5 | * | 3 | * |
6 | * Device driver for Microgate SyncLink ISA and PCI | 4 | * Device driver for Microgate SyncLink ISA and PCI |
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1a7918d71aa..46de2e075dac 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -416,6 +416,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
416 | struct tty_buffer *head, *tail = tty->buf.tail; | 416 | struct tty_buffer *head, *tail = tty->buf.tail; |
417 | int seen_tail = 0; | 417 | int seen_tail = 0; |
418 | while ((head = tty->buf.head) != NULL) { | 418 | while ((head = tty->buf.head) != NULL) { |
419 | int copied; | ||
419 | int count; | 420 | int count; |
420 | char *char_buf; | 421 | char *char_buf; |
421 | unsigned char *flag_buf; | 422 | unsigned char *flag_buf; |
@@ -442,17 +443,19 @@ static void flush_to_ldisc(struct work_struct *work) | |||
442 | line discipline as we want to empty the queue */ | 443 | line discipline as we want to empty the queue */ |
443 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | 444 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) |
444 | break; | 445 | break; |
445 | if (!tty->receive_room || seen_tail) | ||
446 | break; | ||
447 | if (count > tty->receive_room) | ||
448 | count = tty->receive_room; | ||
449 | char_buf = head->char_buf_ptr + head->read; | 446 | char_buf = head->char_buf_ptr + head->read; |
450 | flag_buf = head->flag_buf_ptr + head->read; | 447 | flag_buf = head->flag_buf_ptr + head->read; |
451 | head->read += count; | ||
452 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 448 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
453 | disc->ops->receive_buf(tty, char_buf, | 449 | copied = disc->ops->receive_buf(tty, char_buf, |
454 | flag_buf, count); | 450 | flag_buf, count); |
455 | spin_lock_irqsave(&tty->buf.lock, flags); | 451 | spin_lock_irqsave(&tty->buf.lock, flags); |
452 | |||
453 | head->read += copied; | ||
454 | |||
455 | if (copied == 0 || seen_tail) { | ||
456 | schedule_work(&tty->buf.work); | ||
457 | break; | ||
458 | } | ||
456 | } | 459 | } |
457 | clear_bit(TTY_FLUSHING, &tty->flags); | 460 | clear_bit(TTY_FLUSHING, &tty->flags); |
458 | } | 461 | } |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d7d50b48287e..6556f7452ba6 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/tty_io.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | */ | 3 | */ |
6 | 4 | ||
@@ -964,12 +962,14 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
964 | } | 962 | } |
965 | 963 | ||
966 | void tty_write_unlock(struct tty_struct *tty) | 964 | void tty_write_unlock(struct tty_struct *tty) |
965 | __releases(&tty->atomic_write_lock) | ||
967 | { | 966 | { |
968 | mutex_unlock(&tty->atomic_write_lock); | 967 | mutex_unlock(&tty->atomic_write_lock); |
969 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | 968 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
970 | } | 969 | } |
971 | 970 | ||
972 | int tty_write_lock(struct tty_struct *tty, int ndelay) | 971 | int tty_write_lock(struct tty_struct *tty, int ndelay) |
972 | __acquires(&tty->atomic_write_lock) | ||
973 | { | 973 | { |
974 | if (!mutex_trylock(&tty->atomic_write_lock)) { | 974 | if (!mutex_trylock(&tty->atomic_write_lock)) { |
975 | if (ndelay) | 975 | if (ndelay) |
@@ -1391,16 +1391,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1391 | return ERR_PTR(-ENODEV); | 1391 | return ERR_PTR(-ENODEV); |
1392 | 1392 | ||
1393 | tty = alloc_tty_struct(); | 1393 | tty = alloc_tty_struct(); |
1394 | if (!tty) | 1394 | if (!tty) { |
1395 | goto fail_no_mem; | 1395 | retval = -ENOMEM; |
1396 | goto err_module_put; | ||
1397 | } | ||
1396 | initialize_tty_struct(tty, driver, idx); | 1398 | initialize_tty_struct(tty, driver, idx); |
1397 | 1399 | ||
1398 | retval = tty_driver_install_tty(driver, tty); | 1400 | retval = tty_driver_install_tty(driver, tty); |
1399 | if (retval < 0) { | 1401 | if (retval < 0) |
1400 | free_tty_struct(tty); | 1402 | goto err_deinit_tty; |
1401 | module_put(driver->owner); | ||
1402 | return ERR_PTR(retval); | ||
1403 | } | ||
1404 | 1403 | ||
1405 | /* | 1404 | /* |
1406 | * Structures all installed ... call the ldisc open routines. | 1405 | * Structures all installed ... call the ldisc open routines. |
@@ -1409,15 +1408,18 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1409 | */ | 1408 | */ |
1410 | retval = tty_ldisc_setup(tty, tty->link); | 1409 | retval = tty_ldisc_setup(tty, tty->link); |
1411 | if (retval) | 1410 | if (retval) |
1412 | goto release_mem_out; | 1411 | goto err_release_tty; |
1413 | return tty; | 1412 | return tty; |
1414 | 1413 | ||
1415 | fail_no_mem: | 1414 | err_deinit_tty: |
1415 | deinitialize_tty_struct(tty); | ||
1416 | free_tty_struct(tty); | ||
1417 | err_module_put: | ||
1416 | module_put(driver->owner); | 1418 | module_put(driver->owner); |
1417 | return ERR_PTR(-ENOMEM); | 1419 | return ERR_PTR(retval); |
1418 | 1420 | ||
1419 | /* call the tty release_tty routine to clean out this slot */ | 1421 | /* call the tty release_tty routine to clean out this slot */ |
1420 | release_mem_out: | 1422 | err_release_tty: |
1421 | if (printk_ratelimit()) | 1423 | if (printk_ratelimit()) |
1422 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1424 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1423 | "clearing slot %d\n", idx); | 1425 | "clearing slot %d\n", idx); |
@@ -1892,6 +1894,7 @@ got_driver: | |||
1892 | retval = tty_add_file(tty, filp); | 1894 | retval = tty_add_file(tty, filp); |
1893 | if (retval) { | 1895 | if (retval) { |
1894 | tty_unlock(); | 1896 | tty_unlock(); |
1897 | tty_release(inode, filp); | ||
1895 | return retval; | 1898 | return retval; |
1896 | } | 1899 | } |
1897 | 1900 | ||
@@ -1902,12 +1905,10 @@ got_driver: | |||
1902 | #ifdef TTY_DEBUG_HANGUP | 1905 | #ifdef TTY_DEBUG_HANGUP |
1903 | printk(KERN_DEBUG "opening %s...", tty->name); | 1906 | printk(KERN_DEBUG "opening %s...", tty->name); |
1904 | #endif | 1907 | #endif |
1905 | if (!retval) { | 1908 | if (tty->ops->open) |
1906 | if (tty->ops->open) | 1909 | retval = tty->ops->open(tty, filp); |
1907 | retval = tty->ops->open(tty, filp); | 1910 | else |
1908 | else | 1911 | retval = -ENODEV; |
1909 | retval = -ENODEV; | ||
1910 | } | ||
1911 | filp->f_flags = saved_flags; | 1912 | filp->f_flags = saved_flags; |
1912 | 1913 | ||
1913 | if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && | 1914 | if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && |
@@ -2888,6 +2889,20 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2888 | } | 2889 | } |
2889 | 2890 | ||
2890 | /** | 2891 | /** |
2892 | * deinitialize_tty_struct | ||
2893 | * @tty: tty to deinitialize | ||
2894 | * | ||
2895 | * This subroutine deinitializes a tty structure that has been newly | ||
2896 | * allocated but tty_release cannot be called on that yet. | ||
2897 | * | ||
2898 | * Locking: none - tty in question must not be exposed at this point | ||
2899 | */ | ||
2900 | void deinitialize_tty_struct(struct tty_struct *tty) | ||
2901 | { | ||
2902 | tty_ldisc_deinit(tty); | ||
2903 | } | ||
2904 | |||
2905 | /** | ||
2891 | * tty_put_char - write one character to a tty | 2906 | * tty_put_char - write one character to a tty |
2892 | * @tty: tty | 2907 | * @tty: tty |
2893 | * @ch: character | 2908 | * @ch: character |
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 21574cb32343..53f2442c6099 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/tty_ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 2 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
5 | * | 3 | * |
6 | * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines | 4 | * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines |
@@ -309,7 +307,7 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate); | |||
309 | * @ospeed: output speed | 307 | * @ospeed: output speed |
310 | * | 308 | * |
311 | * Encode the speeds set into the passed termios structure. This is | 309 | * Encode the speeds set into the passed termios structure. This is |
312 | * used as a library helper for drivers os that they can report back | 310 | * used as a library helper for drivers so that they can report back |
313 | * the actual speed selected when it differs from the speed requested | 311 | * the actual speed selected when it differs from the speed requested |
314 | * | 312 | * |
315 | * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour | 313 | * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour |
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e19e13647116..5d01d32e2cf0 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -956,6 +956,19 @@ void tty_ldisc_init(struct tty_struct *tty) | |||
956 | tty_ldisc_assign(tty, ld); | 956 | tty_ldisc_assign(tty, ld); |
957 | } | 957 | } |
958 | 958 | ||
959 | /** | ||
960 | * tty_ldisc_init - ldisc cleanup for new tty | ||
961 | * @tty: tty that was allocated recently | ||
962 | * | ||
963 | * The tty structure must not becompletely set up (tty_ldisc_setup) when | ||
964 | * this call is made. | ||
965 | */ | ||
966 | void tty_ldisc_deinit(struct tty_struct *tty) | ||
967 | { | ||
968 | put_ldisc(tty->ldisc); | ||
969 | tty_ldisc_assign(tty, NULL); | ||
970 | } | ||
971 | |||
959 | void tty_ldisc_begin(void) | 972 | void tty_ldisc_begin(void) |
960 | { | 973 | { |
961 | /* Setup the default TTY line discipline. */ | 974 | /* Setup the default TTY line discipline. */ |
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 133697540c73..3b2bb7719442 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c | |||
@@ -1,6 +1,3 @@ | |||
1 | /* | ||
2 | * drivers/char/tty_lock.c | ||
3 | */ | ||
4 | #include <linux/tty.h> | 1 | #include <linux/tty.h> |
5 | #include <linux/module.h> | 2 | #include <linux/module.h> |
6 | #include <linux/kallsyms.h> | 3 | #include <linux/kallsyms.h> |
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index d6b342b5b423..3761ccf0f340 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/keyboard.c | ||
3 | * | ||
4 | * Written for linux by Johan Myreen as a translation from | 2 | * Written for linux by Johan Myreen as a translation from |
5 | * the assembly version by Linus (with diacriticals added) | 3 | * the assembly version by Linus (with diacriticals added) |
6 | * | 4 | * |
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index adf0ad2a8851..67b1d0d7c8ac 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/selection.c | ||
3 | * | ||
4 | * This module exports the functions: | 2 | * This module exports the functions: |
5 | * | 3 | * |
6 | * 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)' | 4 | * 'int set_selection(struct tiocl_selection __user *, struct tty_struct *)' |
@@ -334,8 +332,7 @@ int paste_selection(struct tty_struct *tty) | |||
334 | continue; | 332 | continue; |
335 | } | 333 | } |
336 | count = sel_buffer_lth - pasted; | 334 | count = sel_buffer_lth - pasted; |
337 | count = min(count, tty->receive_room); | 335 | count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, |
338 | tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, | ||
339 | NULL, count); | 336 | NULL, count); |
340 | pasted += count; | 337 | pasted += count; |
341 | } | 338 | } |
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 1564261e80c8..66825c9f516a 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/vc_screen.c | ||
3 | * | ||
4 | * Provide access to virtual console memory. | 2 | * Provide access to virtual console memory. |
5 | * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled) | 3 | * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled) |
6 | * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63) | 4 | * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63) |
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4bea1efaec98..b3915b7ad3e2 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/vt.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | */ | 3 | */ |
6 | 4 | ||
@@ -858,7 +856,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
858 | { | 856 | { |
859 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; | 857 | unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; |
860 | unsigned long end; | 858 | unsigned long end; |
861 | unsigned int old_cols, old_rows, old_row_size, old_screen_size; | 859 | unsigned int old_rows, old_row_size; |
862 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; | 860 | unsigned int new_cols, new_rows, new_row_size, new_screen_size; |
863 | unsigned int user; | 861 | unsigned int user; |
864 | unsigned short *newscreen; | 862 | unsigned short *newscreen; |
@@ -887,9 +885,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
887 | return -ENOMEM; | 885 | return -ENOMEM; |
888 | 886 | ||
889 | old_rows = vc->vc_rows; | 887 | old_rows = vc->vc_rows; |
890 | old_cols = vc->vc_cols; | ||
891 | old_row_size = vc->vc_size_row; | 888 | old_row_size = vc->vc_size_row; |
892 | old_screen_size = vc->vc_screenbuf_size; | ||
893 | 889 | ||
894 | err = resize_screen(vc, new_cols, new_rows, user); | 890 | err = resize_screen(vc, new_cols, new_rows, user); |
895 | if (err) { | 891 | if (err) { |
@@ -1197,6 +1193,13 @@ static void csi_J(struct vc_data *vc, int vpar) | |||
1197 | vc->vc_x + 1); | 1193 | vc->vc_x + 1); |
1198 | } | 1194 | } |
1199 | break; | 1195 | break; |
1196 | case 3: /* erase scroll-back buffer (and whole display) */ | ||
1197 | scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, | ||
1198 | vc->vc_screenbuf_size >> 1); | ||
1199 | set_origin(vc); | ||
1200 | if (CON_IS_VISIBLE(vc)) | ||
1201 | update_screen(vc); | ||
1202 | /* fall through */ | ||
1200 | case 2: /* erase whole display */ | 1203 | case 2: /* erase whole display */ |
1201 | count = vc->vc_cols * vc->vc_rows; | 1204 | count = vc->vc_cols * vc->vc_rows; |
1202 | start = (unsigned short *)vc->vc_origin; | 1205 | start = (unsigned short *)vc->vc_origin; |
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 937d17219984..5e096f43bcea 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/vt_ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 1992 obz under the linux copyright | 2 | * Copyright (C) 1992 obz under the linux copyright |
5 | * | 3 | * |
6 | * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 | 4 | * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 |
@@ -698,10 +696,23 @@ int vt_ioctl(struct tty_struct *tty, | |||
698 | break; | 696 | break; |
699 | 697 | ||
700 | case KDGKBMODE: | 698 | case KDGKBMODE: |
701 | uival = ((kbd->kbdmode == VC_RAW) ? K_RAW : | 699 | switch (kbd->kbdmode) { |
702 | (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : | 700 | case VC_RAW: |
703 | (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : | 701 | uival = K_RAW; |
704 | K_XLATE); | 702 | break; |
703 | case VC_MEDIUMRAW: | ||
704 | uival = K_MEDIUMRAW; | ||
705 | break; | ||
706 | case VC_UNICODE: | ||
707 | uival = K_UNICODE; | ||
708 | break; | ||
709 | case VC_OFF: | ||
710 | uival = K_OFF; | ||
711 | break; | ||
712 | default: | ||
713 | uival = K_XLATE; | ||
714 | break; | ||
715 | } | ||
705 | goto setint; | 716 | goto setint; |
706 | 717 | ||
707 | /* this could be folded into KDSKBMODE, but for compatibility | 718 | /* this could be folded into KDSKBMODE, but for compatibility |
@@ -1499,7 +1510,6 @@ long vt_compat_ioctl(struct tty_struct *tty, | |||
1499 | { | 1510 | { |
1500 | struct vc_data *vc = tty->driver_data; | 1511 | struct vc_data *vc = tty->driver_data; |
1501 | struct console_font_op op; /* used in multiple places here */ | 1512 | struct console_font_op op; /* used in multiple places here */ |
1502 | struct kbd_struct *kbd; | ||
1503 | unsigned int console; | 1513 | unsigned int console; |
1504 | void __user *up = (void __user *)arg; | 1514 | void __user *up = (void __user *)arg; |
1505 | int perm; | 1515 | int perm; |
@@ -1522,7 +1532,6 @@ long vt_compat_ioctl(struct tty_struct *tty, | |||
1522 | if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) | 1532 | if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) |
1523 | perm = 1; | 1533 | perm = 1; |
1524 | 1534 | ||
1525 | kbd = kbd_table + console; | ||
1526 | switch (cmd) { | 1535 | switch (cmd) { |
1527 | /* | 1536 | /* |
1528 | * these need special handlers for incompatible data structures | 1537 | * these need special handlers for incompatible data structures |