diff options
Diffstat (limited to 'drivers/tty/serial/mfd.c')
-rw-r--r-- | drivers/tty/serial/mfd.c | 73 |
1 files changed, 15 insertions, 58 deletions
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index d40010a22ecd..c111f36f5d21 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -16,9 +16,7 @@ | |||
16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans | 16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans |
17 | * are used for RX, odd chans for TX | 17 | * are used for RX, odd chans for TX |
18 | * | 18 | * |
19 | * 2. In A0 stepping, UART will not support TX half empty flag | 19 | * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always |
20 | * | ||
21 | * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always | ||
22 | * asserted, only when the HW is reset the DDCD and DDSR will | 20 | * asserted, only when the HW is reset the DDCD and DDSR will |
23 | * be triggered | 21 | * be triggered |
24 | */ | 22 | */ |
@@ -41,8 +39,6 @@ | |||
41 | #include <linux/io.h> | 39 | #include <linux/io.h> |
42 | #include <linux/debugfs.h> | 40 | #include <linux/debugfs.h> |
43 | 41 | ||
44 | #define MFD_HSU_A0_STEPPING 1 | ||
45 | |||
46 | #define HSU_DMA_BUF_SIZE 2048 | 42 | #define HSU_DMA_BUF_SIZE 2048 |
47 | 43 | ||
48 | #define chan_readl(chan, offset) readl(chan->reg + offset) | 44 | #define chan_readl(chan, offset) readl(chan->reg + offset) |
@@ -51,7 +47,10 @@ | |||
51 | #define mfd_readl(obj, offset) readl(obj->reg + offset) | 47 | #define mfd_readl(obj, offset) readl(obj->reg + offset) |
52 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) | 48 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) |
53 | 49 | ||
54 | #define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) | 50 | static int hsu_dma_enable; |
51 | module_param(hsu_dma_enable, int, 0); | ||
52 | MODULE_PARM_DESC(hsu_dma_enable, "It is a bitmap to set working mode, if \ | ||
53 | bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode."); | ||
55 | 54 | ||
56 | struct hsu_dma_buffer { | 55 | struct hsu_dma_buffer { |
57 | u8 *buf; | 56 | u8 *buf; |
@@ -65,7 +64,6 @@ struct hsu_dma_chan { | |||
65 | enum dma_data_direction dirt; | 64 | enum dma_data_direction dirt; |
66 | struct uart_hsu_port *uport; | 65 | struct uart_hsu_port *uport; |
67 | void __iomem *reg; | 66 | void __iomem *reg; |
68 | struct timer_list rx_timer; /* only needed by RX channel */ | ||
69 | }; | 67 | }; |
70 | 68 | ||
71 | struct uart_hsu_port { | 69 | struct uart_hsu_port { |
@@ -355,8 +353,6 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf | |||
355 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | 353 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ |
356 | ); | 354 | ); |
357 | chan_writel(rxc, HSU_CH_CR, 0x3); | 355 | chan_writel(rxc, HSU_CH_CR, 0x3); |
358 | |||
359 | mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
360 | } | 356 | } |
361 | 357 | ||
362 | /* Protected by spin_lock_irqsave(port->lock) */ | 358 | /* Protected by spin_lock_irqsave(port->lock) */ |
@@ -420,7 +416,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | |||
420 | chan_writel(chan, HSU_CH_CR, 0x3); | 416 | chan_writel(chan, HSU_CH_CR, 0x3); |
421 | return; | 417 | return; |
422 | } | 418 | } |
423 | del_timer(&chan->rx_timer); | ||
424 | 419 | ||
425 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, | 420 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, |
426 | dbuf->dma_size, DMA_FROM_DEVICE); | 421 | dbuf->dma_size, DMA_FROM_DEVICE); |
@@ -448,8 +443,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | |||
448 | tty_flip_buffer_push(tty); | 443 | tty_flip_buffer_push(tty); |
449 | 444 | ||
450 | chan_writel(chan, HSU_CH_CR, 0x3); | 445 | chan_writel(chan, HSU_CH_CR, 0x3); |
451 | chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; | ||
452 | add_timer(&chan->rx_timer); | ||
453 | 446 | ||
454 | } | 447 | } |
455 | 448 | ||
@@ -551,16 +544,9 @@ static void transmit_chars(struct uart_hsu_port *up) | |||
551 | return; | 544 | return; |
552 | } | 545 | } |
553 | 546 | ||
554 | #ifndef MFD_HSU_A0_STEPPING | 547 | /* The IRQ is for TX FIFO half-empty */ |
555 | count = up->port.fifosize / 2; | 548 | count = up->port.fifosize / 2; |
556 | #else | 549 | |
557 | /* | ||
558 | * A0 only supports fully empty IRQ, and the first char written | ||
559 | * into it won't clear the EMPT bit, so we may need be cautious | ||
560 | * by useing a shorter buffer | ||
561 | */ | ||
562 | count = up->port.fifosize - 4; | ||
563 | #endif | ||
564 | do { | 550 | do { |
565 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | 551 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); |
566 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 552 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
@@ -769,9 +755,8 @@ static void serial_hsu_break_ctl(struct uart_port *port, int break_state) | |||
769 | /* | 755 | /* |
770 | * What special to do: | 756 | * What special to do: |
771 | * 1. chose the 64B fifo mode | 757 | * 1. chose the 64B fifo mode |
772 | * 2. make sure not to select half empty mode for A0 stepping | 758 | * 2. start dma or pio depends on configuration |
773 | * 3. start dma or pio depends on configuration | 759 | * 3. we only allocate dma memory when needed |
774 | * 4. we only allocate dma memory when needed | ||
775 | */ | 760 | */ |
776 | static int serial_hsu_startup(struct uart_port *port) | 761 | static int serial_hsu_startup(struct uart_port *port) |
777 | { | 762 | { |
@@ -870,8 +855,6 @@ static void serial_hsu_shutdown(struct uart_port *port) | |||
870 | container_of(port, struct uart_hsu_port, port); | 855 | container_of(port, struct uart_hsu_port, port); |
871 | unsigned long flags; | 856 | unsigned long flags; |
872 | 857 | ||
873 | del_timer_sync(&up->rxc->rx_timer); | ||
874 | |||
875 | /* Disable interrupts from this port */ | 858 | /* Disable interrupts from this port */ |
876 | up->ier = 0; | 859 | up->ier = 0; |
877 | serial_out(up, UART_IER, 0); | 860 | serial_out(up, UART_IER, 0); |
@@ -977,10 +960,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | |||
977 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; | 960 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; |
978 | 961 | ||
979 | fcr |= UART_FCR_HSU_64B_FIFO; | 962 | fcr |= UART_FCR_HSU_64B_FIFO; |
980 | #ifdef MFD_HSU_A0_STEPPING | ||
981 | /* A0 doesn't support half empty IRQ */ | ||
982 | fcr |= UART_FCR_FULL_EMPT_TXI; | ||
983 | #endif | ||
984 | 963 | ||
985 | /* | 964 | /* |
986 | * Ok, we're now changing the port state. Do it with | 965 | * Ok, we're now changing the port state. Do it with |
@@ -1343,28 +1322,6 @@ err_disable: | |||
1343 | return ret; | 1322 | return ret; |
1344 | } | 1323 | } |
1345 | 1324 | ||
1346 | static void hsu_dma_rx_timeout(unsigned long data) | ||
1347 | { | ||
1348 | struct hsu_dma_chan *chan = (void *)data; | ||
1349 | struct uart_hsu_port *up = chan->uport; | ||
1350 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
1351 | int count = 0; | ||
1352 | unsigned long flags; | ||
1353 | |||
1354 | spin_lock_irqsave(&up->port.lock, flags); | ||
1355 | |||
1356 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
1357 | |||
1358 | if (!count) { | ||
1359 | mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
1360 | goto exit; | ||
1361 | } | ||
1362 | |||
1363 | hsu_dma_rx(up, 0); | ||
1364 | exit: | ||
1365 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1366 | } | ||
1367 | |||
1368 | static void hsu_global_init(void) | 1325 | static void hsu_global_init(void) |
1369 | { | 1326 | { |
1370 | struct hsu_port *hsu; | 1327 | struct hsu_port *hsu; |
@@ -1415,6 +1372,12 @@ static void hsu_global_init(void) | |||
1415 | 1372 | ||
1416 | serial_hsu_ports[i] = uport; | 1373 | serial_hsu_ports[i] = uport; |
1417 | uport->index = i; | 1374 | uport->index = i; |
1375 | |||
1376 | if (hsu_dma_enable & (1<<i)) | ||
1377 | uport->use_dma = 1; | ||
1378 | else | ||
1379 | uport->use_dma = 0; | ||
1380 | |||
1418 | uport++; | 1381 | uport++; |
1419 | } | 1382 | } |
1420 | 1383 | ||
@@ -1427,12 +1390,6 @@ static void hsu_global_init(void) | |||
1427 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + | 1390 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + |
1428 | i * HSU_DMA_CHANS_REG_LENGTH; | 1391 | i * HSU_DMA_CHANS_REG_LENGTH; |
1429 | 1392 | ||
1430 | /* Work around for RX */ | ||
1431 | if (dchan->dirt == DMA_FROM_DEVICE) { | ||
1432 | init_timer(&dchan->rx_timer); | ||
1433 | dchan->rx_timer.function = hsu_dma_rx_timeout; | ||
1434 | dchan->rx_timer.data = (unsigned long)dchan; | ||
1435 | } | ||
1436 | dchan++; | 1393 | dchan++; |
1437 | } | 1394 | } |
1438 | 1395 | ||