diff options
author | Feng Tang <feng.tang@intel.com> | 2010-07-27 03:20:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 16:47:46 -0400 |
commit | 06c77e21ae7c199435097116b8212b0761fc8ba8 (patch) | |
tree | 2ae53076c07cbf8c112345aeeedb26a22ad7fd59 /drivers/serial | |
parent | 669b7a0938e759097c150400cd36bd49befaf5bb (diff) |
hsu: some code cleanup
Major changes are:
* refine the comments in the driver
* remove unused member from structure "hsu_port"
* extended spin_lock protoction for dma mode in port_irq()
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/mfd.c | 85 |
1 files changed, 19 insertions, 66 deletions
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index ed2bf6b14a4a..f5e7569c1773 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ | 4 | * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ |
5 | * | 5 | * |
6 | * (C) Copyright 2009 Intel Corporation | 6 | * (C) Copyright 2010 Intel Corporation |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
@@ -11,30 +11,16 @@ | |||
11 | * of the License. | 11 | * of the License. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | |||
15 | /* Notes: | 14 | /* Notes: |
16 | * 1. there should be 2 types of register access method, one for | 15 | * 1. DMA channel allocation: 0/1 channel are assigned to port 0, |
17 | * UART ports, the other for the general purpose registers | 16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans |
18 | * | 17 | * are used for RX, odd chans for TX |
19 | * 2. It used to have a Irda port, but was defeatured recently | ||
20 | * | ||
21 | * 3. Based on the info from HSU MAS, 0/1 channel are assigned to | ||
22 | * port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number | ||
23 | * chan will be read, odd chan for write | ||
24 | * | ||
25 | * 4. HUS supports both the 64B and 16B FIFO version, but this driver | ||
26 | * will only use 64B version | ||
27 | * | 18 | * |
28 | * 5. In A0 stepping, UART will not support TX half empty flag, thus | 19 | * 2. In A0 stepping, UART will not support TX half empty flag |
29 | * need add a #ifdef judgement | ||
30 | * | 20 | * |
31 | * 6. One more bug for A0, the loopback mode won't support AFC | 21 | * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always |
32 | * auto-flow control | 22 | * asserted, only when the HW is reset the DDCD and DDSR will |
33 | * | 23 | * be triggered |
34 | * 7. HSU has some special FCR control bits, we add it to serial_reg.h | ||
35 | * | ||
36 | * 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted, | ||
37 | * only when the HW is reset the DDCD and DDSR will be triggered | ||
38 | */ | 24 | */ |
39 | 25 | ||
40 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -75,7 +61,7 @@ struct hsu_dma_buffer { | |||
75 | 61 | ||
76 | struct hsu_dma_chan { | 62 | struct hsu_dma_chan { |
77 | u32 id; | 63 | u32 id; |
78 | u32 dirt; /* to or from device */ | 64 | enum dma_data_direction dirt; |
79 | struct uart_hsu_port *uport; | 65 | struct uart_hsu_port *uport; |
80 | void __iomem *reg; | 66 | void __iomem *reg; |
81 | struct timer_list rx_timer; /* only needed by RX channel */ | 67 | struct timer_list rx_timer; /* only needed by RX channel */ |
@@ -102,8 +88,6 @@ struct uart_hsu_port { | |||
102 | 88 | ||
103 | /* Top level data structure of HSU */ | 89 | /* Top level data structure of HSU */ |
104 | struct hsu_port { | 90 | struct hsu_port { |
105 | struct pci_device *pdev; | ||
106 | |||
107 | void __iomem *reg; | 91 | void __iomem *reg; |
108 | unsigned long paddr; | 92 | unsigned long paddr; |
109 | unsigned long iolen; | 93 | unsigned long iolen; |
@@ -112,23 +96,9 @@ struct hsu_port { | |||
112 | struct uart_hsu_port port[3]; | 96 | struct uart_hsu_port port[3]; |
113 | struct hsu_dma_chan chans[10]; | 97 | struct hsu_dma_chan chans[10]; |
114 | 98 | ||
115 | #ifdef CONFIG_DEBUG_FS | ||
116 | struct dentry *debugfs; | 99 | struct dentry *debugfs; |
117 | #endif | ||
118 | }; | 100 | }; |
119 | 101 | ||
120 | static inline void hexdump(char *str, u8 *addr, int cnt) | ||
121 | { | ||
122 | int i; | ||
123 | |||
124 | for (i = 0; i < cnt; i += 8) { | ||
125 | printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", | ||
126 | addr[i], addr[i+1], addr[i+2], addr[i+3], | ||
127 | addr[i+4], addr[i+5], addr[i+6], addr[i+7]); | ||
128 | printk("\n"); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) | 102 | static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) |
133 | { | 103 | { |
134 | unsigned int val; | 104 | unsigned int val; |
@@ -353,9 +323,6 @@ void hsu_dma_tx(struct uart_hsu_port *up) | |||
353 | | (0x1 << 8) | 323 | | (0x1 << 8) |
354 | | (0x1 << 16) | 324 | | (0x1 << 16) |
355 | | (0x1 << 24)); | 325 | | (0x1 << 24)); |
356 | |||
357 | WARN(chan_readl(up->txc, HSU_CH_CR) & 0x1, | ||
358 | "TX channel has already be started!!\n"); | ||
359 | up->dma_tx_on = 1; | 326 | up->dma_tx_on = 1; |
360 | chan_writel(up->txc, HSU_CH_CR, 0x1); | 327 | chan_writel(up->txc, HSU_CH_CR, 0x1); |
361 | } | 328 | } |
@@ -367,7 +334,6 @@ void hsu_dma_tx(struct uart_hsu_port *up) | |||
367 | /* The buffer is already cache coherent */ | 334 | /* The buffer is already cache coherent */ |
368 | void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) | 335 | void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) |
369 | { | 336 | { |
370 | /* Need start RX dma channel here */ | ||
371 | dbuf->ofs = 0; | 337 | dbuf->ofs = 0; |
372 | 338 | ||
373 | chan_writel(rxc, HSU_CH_BSR, 32); | 339 | chan_writel(rxc, HSU_CH_BSR, 32); |
@@ -426,35 +392,32 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | |||
426 | return; | 392 | return; |
427 | 393 | ||
428 | /* | 394 | /* |
429 | * first need to know how many is already transferred, | 395 | * First need to know how many is already transferred, |
430 | * then check if its a timeout DMA irq, and return | 396 | * then check if its a timeout DMA irq, and return |
431 | * the trail bytes out, push them up and reenable the | 397 | * the trail bytes out, push them up and reenable the |
432 | * channel, better to use 2 descriptors at the same time | 398 | * channel |
433 | */ | 399 | */ |
434 | 400 | ||
435 | /* timeout IRQ, need wait some time, see Errata 2 */ | 401 | /* Timeout IRQ, need wait some time, see Errata 2 */ |
436 | if (int_sts & 0xf00) | 402 | if (int_sts & 0xf00) |
437 | udelay(2); | 403 | udelay(2); |
438 | 404 | ||
439 | /* Stop the channel */ | 405 | /* Stop the channel */ |
440 | chan_writel(chan, HSU_CH_CR, 0x0); | 406 | chan_writel(chan, HSU_CH_CR, 0x0); |
441 | 407 | ||
442 | /* We can use 2 ways to calc the actual transfer len */ | ||
443 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | 408 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; |
444 | |||
445 | if (!count) { | 409 | if (!count) { |
446 | /* restart the channel before we leave */ | 410 | /* Restart the channel before we leave */ |
447 | chan_writel(chan, HSU_CH_CR, 0x3); | 411 | chan_writel(chan, HSU_CH_CR, 0x3); |
448 | return; | 412 | return; |
449 | } | 413 | } |
450 | |||
451 | del_timer(&chan->rx_timer); | 414 | del_timer(&chan->rx_timer); |
452 | 415 | ||
453 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, | 416 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, |
454 | dbuf->dma_size, DMA_FROM_DEVICE); | 417 | dbuf->dma_size, DMA_FROM_DEVICE); |
455 | 418 | ||
456 | /* | 419 | /* |
457 | * head will only wrap around when we recycle | 420 | * Head will only wrap around when we recycle |
458 | * the DMA buffer, and when that happens, we | 421 | * the DMA buffer, and when that happens, we |
459 | * explicitly set tail to 0. So head will | 422 | * explicitly set tail to 0. So head will |
460 | * always be greater than tail. | 423 | * always be greater than tail. |
@@ -496,10 +459,6 @@ static void serial_hsu_stop_rx(struct uart_port *port) | |||
496 | } | 459 | } |
497 | } | 460 | } |
498 | 461 | ||
499 | /* | ||
500 | * if there is error flag, should we just reset the FIFO or keeps | ||
501 | * working on it | ||
502 | */ | ||
503 | static inline void receive_chars(struct uart_hsu_port *up, int *status) | 462 | static inline void receive_chars(struct uart_hsu_port *up, int *status) |
504 | { | 463 | { |
505 | struct tty_struct *tty = up->port.state->port.tty; | 464 | struct tty_struct *tty = up->port.state->port.tty; |
@@ -571,7 +530,6 @@ static void transmit_chars(struct uart_hsu_port *up) | |||
571 | { | 530 | { |
572 | struct circ_buf *xmit = &up->port.state->xmit; | 531 | struct circ_buf *xmit = &up->port.state->xmit; |
573 | int count; | 532 | int count; |
574 | int i = 0; /* for debug use */ | ||
575 | 533 | ||
576 | if (up->port.x_char) { | 534 | if (up->port.x_char) { |
577 | serial_out(up, UART_TX, up->port.x_char); | 535 | serial_out(up, UART_TX, up->port.x_char); |
@@ -592,13 +550,11 @@ static void transmit_chars(struct uart_hsu_port *up) | |||
592 | * into it won't clear the EMPT bit, so we may need be cautious | 550 | * into it won't clear the EMPT bit, so we may need be cautious |
593 | * by useing a shorter buffer | 551 | * by useing a shorter buffer |
594 | */ | 552 | */ |
595 | /* count = up->port.fifosize; */ | ||
596 | count = up->port.fifosize - 4; | 553 | count = up->port.fifosize - 4; |
597 | #endif | 554 | #endif |
598 | do { | 555 | do { |
599 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | 556 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); |
600 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 557 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
601 | i++; | ||
602 | 558 | ||
603 | up->port.icount.tx++; | 559 | up->port.icount.tx++; |
604 | if (uart_circ_empty(xmit)) | 560 | if (uart_circ_empty(xmit)) |
@@ -628,7 +584,7 @@ static inline void check_modem_status(struct uart_hsu_port *up) | |||
628 | /* We may only get DDCD when HW init and reset */ | 584 | /* We may only get DDCD when HW init and reset */ |
629 | if (status & UART_MSR_DDCD) | 585 | if (status & UART_MSR_DDCD) |
630 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | 586 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); |
631 | /* will start/stop_tx accordingly */ | 587 | /* Will start/stop_tx accordingly */ |
632 | if (status & UART_MSR_DCTS) | 588 | if (status & UART_MSR_DCTS) |
633 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | 589 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); |
634 | 590 | ||
@@ -647,6 +603,7 @@ static irqreturn_t port_irq(int irq, void *dev_id) | |||
647 | if (unlikely(!up->running)) | 603 | if (unlikely(!up->running)) |
648 | return IRQ_NONE; | 604 | return IRQ_NONE; |
649 | 605 | ||
606 | spin_lock_irqsave(&up->port.lock, flags); | ||
650 | if (up->use_dma) { | 607 | if (up->use_dma) { |
651 | lsr = serial_in(up, UART_LSR); | 608 | lsr = serial_in(up, UART_LSR); |
652 | if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | | 609 | if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | |
@@ -655,10 +612,10 @@ static irqreturn_t port_irq(int irq, void *dev_id) | |||
655 | "Got lsr irq while using DMA, lsr = 0x%2x\n", | 612 | "Got lsr irq while using DMA, lsr = 0x%2x\n", |
656 | lsr); | 613 | lsr); |
657 | check_modem_status(up); | 614 | check_modem_status(up); |
615 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
658 | return IRQ_HANDLED; | 616 | return IRQ_HANDLED; |
659 | } | 617 | } |
660 | 618 | ||
661 | spin_lock_irqsave(&up->port.lock, flags); | ||
662 | iir = serial_in(up, UART_IIR); | 619 | iir = serial_in(up, UART_IIR); |
663 | if (iir & UART_IIR_NO_INT) { | 620 | if (iir & UART_IIR_NO_INT) { |
664 | spin_unlock_irqrestore(&up->port.lock, flags); | 621 | spin_unlock_irqrestore(&up->port.lock, flags); |
@@ -666,9 +623,9 @@ static irqreturn_t port_irq(int irq, void *dev_id) | |||
666 | } | 623 | } |
667 | 624 | ||
668 | lsr = serial_in(up, UART_LSR); | 625 | lsr = serial_in(up, UART_LSR); |
669 | |||
670 | if (lsr & UART_LSR_DR) | 626 | if (lsr & UART_LSR_DR) |
671 | receive_chars(up, &lsr); | 627 | receive_chars(up, &lsr); |
628 | check_modem_status(up); | ||
672 | 629 | ||
673 | /* lsr will be renewed during the receive_chars */ | 630 | /* lsr will be renewed during the receive_chars */ |
674 | if (lsr & UART_LSR_THRE) | 631 | if (lsr & UART_LSR_THRE) |
@@ -701,7 +658,6 @@ static inline void dma_chan_irq(struct hsu_dma_chan *chan) | |||
701 | 658 | ||
702 | /* Tx channel */ | 659 | /* Tx channel */ |
703 | if (chan->dirt == DMA_TO_DEVICE) { | 660 | if (chan->dirt == DMA_TO_DEVICE) { |
704 | /* dma for irq should be done */ | ||
705 | chan_writel(chan, HSU_CH_CR, 0x0); | 661 | chan_writel(chan, HSU_CH_CR, 0x0); |
706 | up->dma_tx_on = 0; | 662 | up->dma_tx_on = 0; |
707 | hsu_dma_tx(up); | 663 | hsu_dma_tx(up); |
@@ -851,7 +807,6 @@ static int serial_hsu_startup(struct uart_port *port) | |||
851 | spin_unlock_irqrestore(&up->port.lock, flags); | 807 | spin_unlock_irqrestore(&up->port.lock, flags); |
852 | 808 | ||
853 | /* DMA init */ | 809 | /* DMA init */ |
854 | /* When use DMA, TX/RX's FIFO and IRQ should be disabled */ | ||
855 | if (up->use_dma) { | 810 | if (up->use_dma) { |
856 | struct hsu_dma_buffer *dbuf; | 811 | struct hsu_dma_buffer *dbuf; |
857 | struct circ_buf *xmit = &port->state->xmit; | 812 | struct circ_buf *xmit = &port->state->xmit; |
@@ -1090,11 +1045,9 @@ static int serial_hsu_request_port(struct uart_port *port) | |||
1090 | 1045 | ||
1091 | static void serial_hsu_config_port(struct uart_port *port, int flags) | 1046 | static void serial_hsu_config_port(struct uart_port *port, int flags) |
1092 | { | 1047 | { |
1093 | #if 0 | ||
1094 | struct uart_hsu_port *up = | 1048 | struct uart_hsu_port *up = |
1095 | container_of(port, struct uart_hsu_port, port); | 1049 | container_of(port, struct uart_hsu_port, port); |
1096 | up->port.type = PORT_MFD; | 1050 | up->port.type = PORT_MFD; |
1097 | #endif | ||
1098 | } | 1051 | } |
1099 | 1052 | ||
1100 | static int | 1053 | static int |
@@ -1426,7 +1379,7 @@ static void hsu_global_init(void) | |||
1426 | uport->port.ops = &serial_hsu_pops; | 1379 | uport->port.ops = &serial_hsu_pops; |
1427 | uport->port.line = i; | 1380 | uport->port.line = i; |
1428 | uport->port.flags = UPF_IOREMAP; | 1381 | uport->port.flags = UPF_IOREMAP; |
1429 | /* make the maxim support rate to 2746800 bps */ | 1382 | /* set the scalable maxim support rate to 2746800 bps */ |
1430 | uport->port.uartclk = 115200 * 24 * 16; | 1383 | uport->port.uartclk = 115200 * 24 * 16; |
1431 | 1384 | ||
1432 | uport->running = 0; | 1385 | uport->running = 0; |