• Home
  • Raw
  • Download

Lines Matching +full:s3c6400 +full:- +full:uart

1 // SPDX-License-Identifier: GPL-2.0
5 * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
12 * UERSTAT register in the UART blocks, and keeps marking some of the
21 * BJD, 04-Nov-2004
29 #include <linux/dma-mapping.h>
74 /* UART name and device definitions */
86 #define tx_enabled(port) ((port)->unused[0])
87 #define rx_enabled(port) ((port)->unused[1])
101 return to_platform_device(port->dev)->name; in s3c24xx_serial_portname()
116 return to_ourport(port)->info->type == PORT_S3C6400; in s3c24xx_serial_has_interrupt_mask()
125 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_rx_enable()
127 while (--count && !s3c24xx_serial_txempty_nofifo(port)) in s3c24xx_serial_rx_enable()
139 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_rx_enable()
147 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_rx_disable()
154 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_rx_disable()
160 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_stop_tx()
161 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_stop_tx()
171 disable_irq_nosync(ourport->tx_irq); in s3c24xx_serial_stop_tx()
173 if (dma && dma->tx_chan && ourport->tx_in_progress == S3C24XX_TX_DMA) { in s3c24xx_serial_stop_tx()
174 dmaengine_pause(dma->tx_chan); in s3c24xx_serial_stop_tx()
175 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); in s3c24xx_serial_stop_tx()
176 dmaengine_terminate_all(dma->tx_chan); in s3c24xx_serial_stop_tx()
177 dma_sync_single_for_cpu(ourport->port.dev, in s3c24xx_serial_stop_tx()
178 dma->tx_transfer_addr, dma->tx_size, DMA_TO_DEVICE); in s3c24xx_serial_stop_tx()
179 async_tx_ack(dma->tx_desc); in s3c24xx_serial_stop_tx()
180 count = dma->tx_bytes_requested - state.residue; in s3c24xx_serial_stop_tx()
181 xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); in s3c24xx_serial_stop_tx()
182 port->icount.tx += count; in s3c24xx_serial_stop_tx()
186 ourport->tx_in_progress = 0; in s3c24xx_serial_stop_tx()
188 if (port->flags & UPF_CONS_FLOW) in s3c24xx_serial_stop_tx()
191 ourport->tx_mode = 0; in s3c24xx_serial_stop_tx()
199 struct uart_port *port = &ourport->port; in s3c24xx_serial_tx_dma_complete()
200 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_tx_dma_complete()
201 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_tx_dma_complete()
207 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); in s3c24xx_serial_tx_dma_complete()
208 count = dma->tx_bytes_requested - state.residue; in s3c24xx_serial_tx_dma_complete()
209 async_tx_ack(dma->tx_desc); in s3c24xx_serial_tx_dma_complete()
211 dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, in s3c24xx_serial_tx_dma_complete()
212 dma->tx_size, DMA_TO_DEVICE); in s3c24xx_serial_tx_dma_complete()
214 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_tx_dma_complete()
216 xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); in s3c24xx_serial_tx_dma_complete()
217 port->icount.tx += count; in s3c24xx_serial_tx_dma_complete()
218 ourport->tx_in_progress = 0; in s3c24xx_serial_tx_dma_complete()
224 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_tx_dma_complete()
229 struct uart_port *port = &ourport->port; in enable_tx_dma()
236 disable_irq_nosync(ourport->tx_irq); in enable_tx_dma()
246 ourport->tx_mode = S3C24XX_TX_DMA; in enable_tx_dma()
251 struct uart_port *port = &ourport->port; in enable_tx_pio()
255 ourport->tx_in_progress = S3C24XX_TX_PIO; in enable_tx_pio()
270 enable_irq(ourport->tx_irq); in enable_tx_pio()
272 ourport->tx_mode = S3C24XX_TX_PIO; in enable_tx_pio()
277 if (ourport->tx_mode != S3C24XX_TX_PIO) in s3c24xx_serial_start_tx_pio()
284 struct uart_port *port = &ourport->port; in s3c24xx_serial_start_tx_dma()
285 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_start_tx_dma()
286 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_start_tx_dma()
289 if (ourport->tx_mode != S3C24XX_TX_DMA) in s3c24xx_serial_start_tx_dma()
292 dma->tx_size = count & ~(dma_get_cache_alignment() - 1); in s3c24xx_serial_start_tx_dma()
293 dma->tx_transfer_addr = dma->tx_addr + xmit->tail; in s3c24xx_serial_start_tx_dma()
295 dma_sync_single_for_device(ourport->port.dev, dma->tx_transfer_addr, in s3c24xx_serial_start_tx_dma()
296 dma->tx_size, DMA_TO_DEVICE); in s3c24xx_serial_start_tx_dma()
298 dma->tx_desc = dmaengine_prep_slave_single(dma->tx_chan, in s3c24xx_serial_start_tx_dma()
299 dma->tx_transfer_addr, dma->tx_size, in s3c24xx_serial_start_tx_dma()
301 if (!dma->tx_desc) { in s3c24xx_serial_start_tx_dma()
302 dev_err(ourport->port.dev, "Unable to get desc for Tx\n"); in s3c24xx_serial_start_tx_dma()
303 return -EIO; in s3c24xx_serial_start_tx_dma()
306 dma->tx_desc->callback = s3c24xx_serial_tx_dma_complete; in s3c24xx_serial_start_tx_dma()
307 dma->tx_desc->callback_param = ourport; in s3c24xx_serial_start_tx_dma()
308 dma->tx_bytes_requested = dma->tx_size; in s3c24xx_serial_start_tx_dma()
310 ourport->tx_in_progress = S3C24XX_TX_DMA; in s3c24xx_serial_start_tx_dma()
311 dma->tx_cookie = dmaengine_submit(dma->tx_desc); in s3c24xx_serial_start_tx_dma()
312 dma_async_issue_pending(dma->tx_chan); in s3c24xx_serial_start_tx_dma()
318 struct uart_port *port = &ourport->port; in s3c24xx_serial_start_next_tx()
319 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_start_next_tx()
323 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); in s3c24xx_serial_start_next_tx()
330 if (!ourport->dma || !ourport->dma->tx_chan || in s3c24xx_serial_start_next_tx()
331 count < ourport->min_dma_size || in s3c24xx_serial_start_next_tx()
332 xmit->tail & (dma_get_cache_alignment() - 1)) in s3c24xx_serial_start_next_tx()
341 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_start_tx()
344 if (port->flags & UPF_CONS_FLOW) in s3c24xx_serial_start_tx()
348 if (!ourport->dma || !ourport->dma->tx_chan) in s3c24xx_serial_start_tx()
352 if (ourport->dma && ourport->dma->tx_chan) { in s3c24xx_serial_start_tx()
353 if (!uart_circ_empty(xmit) && !ourport->tx_in_progress) in s3c24xx_serial_start_tx()
361 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_uart_copy_rx_to_tty()
367 dma_sync_single_for_cpu(ourport->port.dev, dma->rx_addr, in s3c24xx_uart_copy_rx_to_tty()
368 dma->rx_size, DMA_FROM_DEVICE); in s3c24xx_uart_copy_rx_to_tty()
370 ourport->port.icount.rx += count; in s3c24xx_uart_copy_rx_to_tty()
372 dev_err(ourport->port.dev, "No tty port\n"); in s3c24xx_uart_copy_rx_to_tty()
376 ((unsigned char *)(ourport->dma->rx_buf)), count); in s3c24xx_uart_copy_rx_to_tty()
379 dev_err(ourport->port.dev, "RxData copy to tty layer failed\n"); in s3c24xx_uart_copy_rx_to_tty()
386 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_stop_rx()
387 struct tty_port *t = &port->state->port; in s3c24xx_serial_stop_rx()
398 disable_irq_nosync(ourport->rx_irq); in s3c24xx_serial_stop_rx()
401 if (dma && dma->rx_chan) { in s3c24xx_serial_stop_rx()
402 dmaengine_pause(dma->tx_chan); in s3c24xx_serial_stop_rx()
403 dma_status = dmaengine_tx_status(dma->rx_chan, in s3c24xx_serial_stop_rx()
404 dma->rx_cookie, &state); in s3c24xx_serial_stop_rx()
407 received = dma->rx_bytes_requested - state.residue; in s3c24xx_serial_stop_rx()
408 dmaengine_terminate_all(dma->rx_chan); in s3c24xx_serial_stop_rx()
417 return to_ourport(port)->info; in s3c24xx_port_to_info()
425 if (port->dev == NULL) in s3c24xx_port_to_cfg()
429 return ourport->cfg; in s3c24xx_port_to_cfg()
435 struct s3c24xx_uart_info *info = ourport->info; in s3c24xx_serial_rx_fifocnt()
437 if (ufstat & info->rx_fifofull) in s3c24xx_serial_rx_fifocnt()
438 return ourport->port.fifosize; in s3c24xx_serial_rx_fifocnt()
440 return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; in s3c24xx_serial_rx_fifocnt()
447 struct uart_port *port = &ourport->port; in s3c24xx_serial_rx_dma_complete()
449 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_rx_dma_complete()
450 struct tty_port *t = &port->state->port; in s3c24xx_serial_rx_dma_complete()
451 struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); in s3c24xx_serial_rx_dma_complete()
457 dmaengine_tx_status(dma->rx_chan, dma->rx_cookie, &state); in s3c24xx_serial_rx_dma_complete()
458 received = dma->rx_bytes_requested - state.residue; in s3c24xx_serial_rx_dma_complete()
459 async_tx_ack(dma->rx_desc); in s3c24xx_serial_rx_dma_complete()
461 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_rx_dma_complete()
473 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_rx_dma_complete()
478 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c64xx_start_rx_dma()
480 dma_sync_single_for_device(ourport->port.dev, dma->rx_addr, in s3c64xx_start_rx_dma()
481 dma->rx_size, DMA_FROM_DEVICE); in s3c64xx_start_rx_dma()
483 dma->rx_desc = dmaengine_prep_slave_single(dma->rx_chan, in s3c64xx_start_rx_dma()
484 dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, in s3c64xx_start_rx_dma()
486 if (!dma->rx_desc) { in s3c64xx_start_rx_dma()
487 dev_err(ourport->port.dev, "Unable to get desc for Rx\n"); in s3c64xx_start_rx_dma()
491 dma->rx_desc->callback = s3c24xx_serial_rx_dma_complete; in s3c64xx_start_rx_dma()
492 dma->rx_desc->callback_param = ourport; in s3c64xx_start_rx_dma()
493 dma->rx_bytes_requested = dma->rx_size; in s3c64xx_start_rx_dma()
495 dma->rx_cookie = dmaengine_submit(dma->rx_desc); in s3c64xx_start_rx_dma()
496 dma_async_issue_pending(dma->rx_chan); in s3c64xx_start_rx_dma()
499 /* ? - where has parity gone?? */
504 struct uart_port *port = &ourport->port; in enable_rx_dma()
522 ourport->rx_mode = S3C24XX_RX_DMA; in enable_rx_dma()
527 struct uart_port *port = &ourport->port; in enable_rx_pio()
542 ourport->rx_mode = S3C24XX_RX_PIO; in enable_rx_pio()
551 struct uart_port *port = &ourport->port; in s3c24xx_serial_rx_chars_dma()
552 struct s3c24xx_uart_dma *dma = ourport->dma; in s3c24xx_serial_rx_chars_dma()
553 struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port); in s3c24xx_serial_rx_chars_dma()
554 struct tty_port *t = &port->state->port; in s3c24xx_serial_rx_chars_dma()
561 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_rx_chars_dma()
565 if (ourport->rx_mode == S3C24XX_RX_PIO) in s3c24xx_serial_rx_chars_dma()
570 if (ourport->rx_mode == S3C24XX_RX_DMA) { in s3c24xx_serial_rx_chars_dma()
571 dmaengine_pause(dma->rx_chan); in s3c24xx_serial_rx_chars_dma()
572 dmaengine_tx_status(dma->rx_chan, dma->rx_cookie, &state); in s3c24xx_serial_rx_chars_dma()
573 dmaengine_terminate_all(dma->rx_chan); in s3c24xx_serial_rx_chars_dma()
574 received = dma->rx_bytes_requested - state.residue; in s3c24xx_serial_rx_chars_dma()
590 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_rx_chars_dma()
597 struct uart_port *port = &ourport->port; in s3c24xx_serial_rx_drain_fifo()
600 int max_count = port->fifosize; in s3c24xx_serial_rx_drain_fifo()
602 while (max_count-- > 0) { in s3c24xx_serial_rx_drain_fifo()
613 fifocnt--; in s3c24xx_serial_rx_drain_fifo()
618 if (port->flags & UPF_CONS_FLOW) { in s3c24xx_serial_rx_drain_fifo()
641 port->icount.rx++; in s3c24xx_serial_rx_drain_fifo()
650 port->icount.brk++; in s3c24xx_serial_rx_drain_fifo()
656 port->icount.frame++; in s3c24xx_serial_rx_drain_fifo()
658 port->icount.overrun++; in s3c24xx_serial_rx_drain_fifo()
660 uerstat &= port->read_status_mask; in s3c24xx_serial_rx_drain_fifo()
678 tty_flip_buffer_push(&port->state->port); in s3c24xx_serial_rx_drain_fifo()
684 struct uart_port *port = &ourport->port; in s3c24xx_serial_rx_chars_pio()
687 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_rx_chars_pio()
689 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_rx_chars_pio()
699 if (ourport->dma && ourport->dma->rx_chan) in s3c24xx_serial_rx_chars()
707 struct uart_port *port = &ourport->port; in s3c24xx_serial_tx_chars()
708 struct circ_buf *xmit = &port->state->xmit; in s3c24xx_serial_tx_chars()
712 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_tx_chars()
714 count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); in s3c24xx_serial_tx_chars()
716 if (ourport->dma && ourport->dma->tx_chan && in s3c24xx_serial_tx_chars()
717 count >= ourport->min_dma_size) { in s3c24xx_serial_tx_chars()
718 int align = dma_get_cache_alignment() - in s3c24xx_serial_tx_chars()
719 (xmit->tail & (dma_get_cache_alignment() - 1)); in s3c24xx_serial_tx_chars()
720 if (count-align >= ourport->min_dma_size) { in s3c24xx_serial_tx_chars()
721 dma_count = count-align; in s3c24xx_serial_tx_chars()
726 if (port->x_char) { in s3c24xx_serial_tx_chars()
727 wr_regb(port, S3C2410_UTXH, port->x_char); in s3c24xx_serial_tx_chars()
728 port->icount.tx++; in s3c24xx_serial_tx_chars()
729 port->x_char = 0; in s3c24xx_serial_tx_chars()
733 /* if there isn't anything more to transmit, or the uart is now in s3c24xx_serial_tx_chars()
734 * stopped, disable the uart and exit in s3c24xx_serial_tx_chars()
744 if (count > port->fifosize) { in s3c24xx_serial_tx_chars()
745 count = port->fifosize; in s3c24xx_serial_tx_chars()
750 if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) in s3c24xx_serial_tx_chars()
753 wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); in s3c24xx_serial_tx_chars()
754 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); in s3c24xx_serial_tx_chars()
755 port->icount.tx++; in s3c24xx_serial_tx_chars()
756 count--; in s3c24xx_serial_tx_chars()
765 spin_unlock(&port->lock); in s3c24xx_serial_tx_chars()
767 spin_lock(&port->lock); in s3c24xx_serial_tx_chars()
774 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_tx_chars()
782 struct uart_port *port = &ourport->port; in s3c64xx_serial_handle_irq()
804 if ((ufstat & info->tx_fifomask) != 0 || in s3c24xx_serial_tx_empty()
805 (ufstat & info->tx_fifofull)) in s3c24xx_serial_tx_empty()
842 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_break_ctl()
853 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_break_ctl()
858 struct s3c24xx_uart_dma *dma = p->dma; in s3c24xx_serial_request_dma()
864 dma->rx_conf.direction = DMA_DEV_TO_MEM; in s3c24xx_serial_request_dma()
865 dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; in s3c24xx_serial_request_dma()
866 dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH; in s3c24xx_serial_request_dma()
867 dma->rx_conf.src_maxburst = 1; in s3c24xx_serial_request_dma()
869 dma->tx_conf.direction = DMA_MEM_TO_DEV; in s3c24xx_serial_request_dma()
870 dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; in s3c24xx_serial_request_dma()
871 dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH; in s3c24xx_serial_request_dma()
872 dma->tx_conf.dst_maxburst = 1; in s3c24xx_serial_request_dma()
874 dma->rx_chan = dma_request_chan(p->port.dev, "rx"); in s3c24xx_serial_request_dma()
876 if (IS_ERR(dma->rx_chan)) { in s3c24xx_serial_request_dma()
878 ret = PTR_ERR(dma->rx_chan); in s3c24xx_serial_request_dma()
882 ret = dma_get_slave_caps(dma->rx_chan, &dma_caps); in s3c24xx_serial_request_dma()
886 ret = -EOPNOTSUPP; in s3c24xx_serial_request_dma()
890 dmaengine_slave_config(dma->rx_chan, &dma->rx_conf); in s3c24xx_serial_request_dma()
892 dma->tx_chan = dma_request_chan(p->port.dev, "tx"); in s3c24xx_serial_request_dma()
893 if (IS_ERR(dma->tx_chan)) { in s3c24xx_serial_request_dma()
895 ret = PTR_ERR(dma->tx_chan); in s3c24xx_serial_request_dma()
899 ret = dma_get_slave_caps(dma->tx_chan, &dma_caps); in s3c24xx_serial_request_dma()
903 ret = -EOPNOTSUPP; in s3c24xx_serial_request_dma()
907 dmaengine_slave_config(dma->tx_chan, &dma->tx_conf); in s3c24xx_serial_request_dma()
910 dma->rx_size = PAGE_SIZE; in s3c24xx_serial_request_dma()
912 dma->rx_buf = kmalloc(dma->rx_size, GFP_KERNEL); in s3c24xx_serial_request_dma()
913 if (!dma->rx_buf) { in s3c24xx_serial_request_dma()
914 ret = -ENOMEM; in s3c24xx_serial_request_dma()
918 dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf, in s3c24xx_serial_request_dma()
919 dma->rx_size, DMA_FROM_DEVICE); in s3c24xx_serial_request_dma()
920 if (dma_mapping_error(p->port.dev, dma->rx_addr)) { in s3c24xx_serial_request_dma()
922 ret = -EIO; in s3c24xx_serial_request_dma()
927 dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf, in s3c24xx_serial_request_dma()
929 if (dma_mapping_error(p->port.dev, dma->tx_addr)) { in s3c24xx_serial_request_dma()
931 ret = -EIO; in s3c24xx_serial_request_dma()
938 dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size, in s3c24xx_serial_request_dma()
941 kfree(dma->rx_buf); in s3c24xx_serial_request_dma()
943 dma_release_channel(dma->tx_chan); in s3c24xx_serial_request_dma()
945 dma_release_channel(dma->rx_chan); in s3c24xx_serial_request_dma()
948 dev_warn(p->port.dev, "%s, DMA will not be used\n", reason); in s3c24xx_serial_request_dma()
954 struct s3c24xx_uart_dma *dma = p->dma; in s3c24xx_serial_release_dma()
956 if (dma->rx_chan) { in s3c24xx_serial_release_dma()
957 dmaengine_terminate_all(dma->rx_chan); in s3c24xx_serial_release_dma()
958 dma_unmap_single(p->port.dev, dma->rx_addr, in s3c24xx_serial_release_dma()
959 dma->rx_size, DMA_FROM_DEVICE); in s3c24xx_serial_release_dma()
960 kfree(dma->rx_buf); in s3c24xx_serial_release_dma()
961 dma_release_channel(dma->rx_chan); in s3c24xx_serial_release_dma()
962 dma->rx_chan = NULL; in s3c24xx_serial_release_dma()
965 if (dma->tx_chan) { in s3c24xx_serial_release_dma()
966 dmaengine_terminate_all(dma->tx_chan); in s3c24xx_serial_release_dma()
967 dma_unmap_single(p->port.dev, dma->tx_addr, in s3c24xx_serial_release_dma()
969 dma_release_channel(dma->tx_chan); in s3c24xx_serial_release_dma()
970 dma->tx_chan = NULL; in s3c24xx_serial_release_dma()
978 if (ourport->tx_claimed) { in s3c24xx_serial_shutdown()
980 free_irq(ourport->tx_irq, ourport); in s3c24xx_serial_shutdown()
982 ourport->tx_claimed = 0; in s3c24xx_serial_shutdown()
983 ourport->tx_mode = 0; in s3c24xx_serial_shutdown()
986 if (ourport->rx_claimed) { in s3c24xx_serial_shutdown()
988 free_irq(ourport->rx_irq, ourport); in s3c24xx_serial_shutdown()
989 ourport->rx_claimed = 0; in s3c24xx_serial_shutdown()
995 free_irq(port->irq, ourport); in s3c24xx_serial_shutdown()
1001 if (ourport->dma) in s3c24xx_serial_shutdown()
1004 ourport->tx_in_progress = 0; in s3c24xx_serial_shutdown()
1013 port, (unsigned long long)port->mapbase, port->membase); in s3c24xx_serial_startup()
1017 ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0, in s3c24xx_serial_startup()
1021 dev_err(port->dev, "cannot get irq %d\n", ourport->rx_irq); in s3c24xx_serial_startup()
1025 ourport->rx_claimed = 1; in s3c24xx_serial_startup()
1031 ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0, in s3c24xx_serial_startup()
1035 dev_err(port->dev, "cannot get irq %d\n", ourport->tx_irq); in s3c24xx_serial_startup()
1039 ourport->tx_claimed = 1; in s3c24xx_serial_startup()
1061 port, (unsigned long long)port->mapbase, port->membase); in s3c64xx_serial_startup()
1064 if (ourport->dma) { in s3c64xx_serial_startup()
1067 devm_kfree(port->dev, ourport->dma); in s3c64xx_serial_startup()
1068 ourport->dma = NULL; in s3c64xx_serial_startup()
1072 ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, in s3c64xx_serial_startup()
1075 dev_err(port->dev, "cannot get irq %d\n", port->irq); in s3c64xx_serial_startup()
1081 ourport->rx_claimed = 1; in s3c64xx_serial_startup()
1083 ourport->tx_claimed = 1; in s3c64xx_serial_startup()
1085 spin_lock_irqsave(&port->lock, flags); in s3c64xx_serial_startup()
1095 spin_unlock_irqrestore(&port->lock, flags); in s3c64xx_serial_startup()
1112 ourport->pm_level = level; in s3c24xx_serial_pm()
1116 while (--timeout && !s3c24xx_serial_txempty_nofifo(port)) in s3c24xx_serial_pm()
1119 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_pm()
1120 clk_disable_unprepare(ourport->baudclk); in s3c24xx_serial_pm()
1122 clk_disable_unprepare(ourport->clk); in s3c24xx_serial_pm()
1126 clk_prepare_enable(ourport->clk); in s3c24xx_serial_pm()
1128 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_pm()
1129 clk_prepare_enable(ourport->baudclk); in s3c24xx_serial_pm()
1133 dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level); in s3c24xx_serial_pm()
1157 if (info->num_clks == 1) in s3c24xx_serial_getsource()
1161 ucon &= info->clksel_mask; in s3c24xx_serial_getsource()
1162 return ucon >> info->clksel_shift; in s3c24xx_serial_getsource()
1171 if (info->num_clks == 1) in s3c24xx_serial_setsource()
1175 if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel) in s3c24xx_serial_setsource()
1178 ucon &= ~info->clksel_mask; in s3c24xx_serial_setsource()
1179 ucon |= clk_sel << info->clksel_shift; in s3c24xx_serial_setsource()
1187 struct s3c24xx_uart_info *info = ourport->info; in s3c24xx_serial_getclk()
1192 int calc_deviation, deviation = (1 << 30) - 1; in s3c24xx_serial_getclk()
1194 for (cnt = 0; cnt < info->num_clks; cnt++) { in s3c24xx_serial_getclk()
1196 if (ourport->cfg->clk_sel && in s3c24xx_serial_getclk()
1197 !(ourport->cfg->clk_sel & (1 << cnt))) in s3c24xx_serial_getclk()
1201 clk = clk_get(ourport->port.dev, clkname); in s3c24xx_serial_getclk()
1209 if (ourport->info->has_divslot) { in s3c24xx_serial_getclk()
1226 quot--; in s3c24xx_serial_getclk()
1228 calc_deviation = req_baud - baud; in s3c24xx_serial_getclk()
1230 calc_deviation = -calc_deviation; in s3c24xx_serial_getclk()
1273 struct clk *clk = ERR_PTR(-EINVAL); in s3c24xx_serial_set_termios()
1283 termios->c_cflag &= ~(HUPCL | CMSPAR); in s3c24xx_serial_set_termios()
1284 termios->c_cflag |= CLOCAL; in s3c24xx_serial_set_termios()
1292 if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) in s3c24xx_serial_set_termios()
1293 quot = port->custom_divisor; in s3c24xx_serial_set_termios()
1299 if (ourport->baudclk != clk) { in s3c24xx_serial_set_termios()
1304 if (!IS_ERR(ourport->baudclk)) { in s3c24xx_serial_set_termios()
1305 clk_disable_unprepare(ourport->baudclk); in s3c24xx_serial_set_termios()
1306 ourport->baudclk = ERR_PTR(-EINVAL); in s3c24xx_serial_set_termios()
1309 ourport->baudclk = clk; in s3c24xx_serial_set_termios()
1310 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; in s3c24xx_serial_set_termios()
1313 if (ourport->info->has_divslot) { in s3c24xx_serial_set_termios()
1314 unsigned int div = ourport->baudclk_rate / baud; in s3c24xx_serial_set_termios()
1316 if (cfg->has_fracval) { in s3c24xx_serial_set_termios()
1325 switch (termios->c_cflag & CSIZE) { in s3c24xx_serial_set_termios()
1346 ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); in s3c24xx_serial_set_termios()
1348 if (termios->c_cflag & CSTOPB) in s3c24xx_serial_set_termios()
1351 if (termios->c_cflag & PARENB) { in s3c24xx_serial_set_termios()
1352 if (termios->c_cflag & PARODD) in s3c24xx_serial_set_termios()
1360 spin_lock_irqsave(&port->lock, flags); in s3c24xx_serial_set_termios()
1368 port->status &= ~UPSTAT_AUTOCTS; in s3c24xx_serial_set_termios()
1371 if (termios->c_cflag & CRTSCTS) { in s3c24xx_serial_set_termios()
1375 port->status = UPSTAT_AUTOCTS; in s3c24xx_serial_set_termios()
1381 if (ourport->info->has_divslot) in s3c24xx_serial_set_termios()
1384 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", in s3c24xx_serial_set_termios()
1390 * Update the per-port timeout. in s3c24xx_serial_set_termios()
1392 uart_update_timeout(port, termios->c_cflag, baud); in s3c24xx_serial_set_termios()
1397 port->read_status_mask = S3C2410_UERSTAT_OVERRUN; in s3c24xx_serial_set_termios()
1398 if (termios->c_iflag & INPCK) in s3c24xx_serial_set_termios()
1399 port->read_status_mask |= S3C2410_UERSTAT_FRAME | in s3c24xx_serial_set_termios()
1404 port->ignore_status_mask = 0; in s3c24xx_serial_set_termios()
1405 if (termios->c_iflag & IGNPAR) in s3c24xx_serial_set_termios()
1406 port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN; in s3c24xx_serial_set_termios()
1407 if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR) in s3c24xx_serial_set_termios()
1408 port->ignore_status_mask |= S3C2410_UERSTAT_FRAME; in s3c24xx_serial_set_termios()
1413 if ((termios->c_cflag & CREAD) == 0) in s3c24xx_serial_set_termios()
1414 port->ignore_status_mask |= RXSTAT_DUMMY_READ; in s3c24xx_serial_set_termios()
1416 spin_unlock_irqrestore(&port->lock, flags); in s3c24xx_serial_set_termios()
1421 switch (port->type) { in s3c24xx_serial_type()
1429 return "S3C6400/10"; in s3c24xx_serial_type()
1439 release_mem_region(port->mapbase, MAP_SIZE); in s3c24xx_serial_release_port()
1445 return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; in s3c24xx_serial_request_port()
1454 port->type = info->type; in s3c24xx_serial_config_port()
1465 if (ser->type != PORT_UNKNOWN && ser->type != info->type) in s3c24xx_serial_verify_port()
1466 return -EINVAL; in s3c24xx_serial_verify_port()
1595 ucon_mask = info->clksel_mask; in s3c24xx_serial_resetport()
1596 if (info->type == PORT_S3C2440) in s3c24xx_serial_resetport()
1600 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); in s3c24xx_serial_resetport()
1603 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); in s3c24xx_serial_resetport()
1604 wr_regl(port, S3C2410_UFCON, cfg->ufcon); in s3c24xx_serial_resetport()
1620 uport = &port->port; in s3c24xx_serial_cpufreq_transition()
1624 if (port->pm_level != 0) in s3c24xx_serial_cpufreq_transition()
1629 * a disturbance in the clock-rate over the change. in s3c24xx_serial_cpufreq_transition()
1632 if (IS_ERR(port->baudclk)) in s3c24xx_serial_cpufreq_transition()
1635 if (port->baudclk_rate == clk_get_rate(port->baudclk)) in s3c24xx_serial_cpufreq_transition()
1646 if (uport->state == NULL) in s3c24xx_serial_cpufreq_transition()
1649 tty = uport->state->port.tty; in s3c24xx_serial_cpufreq_transition()
1654 termios = &tty->termios; in s3c24xx_serial_cpufreq_transition()
1657 dev_warn(uport->dev, "%s: no termios?\n", __func__); in s3c24xx_serial_cpufreq_transition()
1671 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition; in s3c24xx_serial_cpufreq_register()
1673 return cpufreq_register_notifier(&port->freq_transition, in s3c24xx_serial_cpufreq_register()
1680 cpufreq_unregister_notifier(&port->freq_transition, in s3c24xx_serial_cpufreq_deregister()
1705 struct uart_port *port = &ourport->port; in s3c24xx_serial_init_port()
1706 struct s3c2410_uartcfg *cfg = ourport->cfg; in s3c24xx_serial_init_port()
1713 return -ENODEV; in s3c24xx_serial_init_port()
1715 if (port->mapbase != 0) in s3c24xx_serial_init_port()
1716 return -EINVAL; in s3c24xx_serial_init_port()
1719 port->dev = &platdev->dev; in s3c24xx_serial_init_port()
1725 port->uartclk = 1; in s3c24xx_serial_init_port()
1727 if (cfg->uart_flags & UPF_CONS_FLOW) { in s3c24xx_serial_init_port()
1729 port->flags |= UPF_CONS_FLOW; in s3c24xx_serial_init_port()
1732 /* sort our the physical and virtual addresses for each UART */ in s3c24xx_serial_init_port()
1736 dev_err(port->dev, "failed to find memory resource for uart\n"); in s3c24xx_serial_init_port()
1737 return -EINVAL; in s3c24xx_serial_init_port()
1742 port->membase = devm_ioremap(port->dev, res->start, resource_size(res)); in s3c24xx_serial_init_port()
1743 if (!port->membase) { in s3c24xx_serial_init_port()
1744 dev_err(port->dev, "failed to remap controller address\n"); in s3c24xx_serial_init_port()
1745 return -EBUSY; in s3c24xx_serial_init_port()
1748 port->mapbase = res->start; in s3c24xx_serial_init_port()
1751 port->irq = 0; in s3c24xx_serial_init_port()
1753 port->irq = ret; in s3c24xx_serial_init_port()
1754 ourport->rx_irq = ret; in s3c24xx_serial_init_port()
1755 ourport->tx_irq = ret + 1; in s3c24xx_serial_init_port()
1761 ourport->tx_irq = ret; in s3c24xx_serial_init_port()
1767 if (platdev->dev.of_node && of_find_property(platdev->dev.of_node, in s3c24xx_serial_init_port()
1769 ourport->dma = devm_kzalloc(port->dev, in s3c24xx_serial_init_port()
1770 sizeof(*ourport->dma), in s3c24xx_serial_init_port()
1772 if (!ourport->dma) { in s3c24xx_serial_init_port()
1773 ret = -ENOMEM; in s3c24xx_serial_init_port()
1778 ourport->clk = clk_get(&platdev->dev, "uart"); in s3c24xx_serial_init_port()
1779 if (IS_ERR(ourport->clk)) { in s3c24xx_serial_init_port()
1781 dev_name(&platdev->dev)); in s3c24xx_serial_init_port()
1782 ret = PTR_ERR(ourport->clk); in s3c24xx_serial_init_port()
1786 ret = clk_prepare_enable(ourport->clk); in s3c24xx_serial_init_port()
1788 pr_err("uart: clock failed to prepare+enable: %d\n", ret); in s3c24xx_serial_init_port()
1789 clk_put(ourport->clk); in s3c24xx_serial_init_port()
1801 &port->mapbase, port->membase, port->irq, in s3c24xx_serial_init_port()
1802 ourport->rx_irq, ourport->tx_irq, port->uartclk); in s3c24xx_serial_init_port()
1804 /* reset the fifos (and setup the uart) */ in s3c24xx_serial_init_port()
1810 port->mapbase = 0; in s3c24xx_serial_init_port()
1823 if (pdev->dev.of_node) { in s3c24xx_get_driver_data()
1825 match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); in s3c24xx_get_driver_data()
1826 return (struct s3c24xx_serial_drv_data *)match->data; in s3c24xx_get_driver_data()
1830 platform_get_device_id(pdev)->driver_data; in s3c24xx_get_driver_data()
1835 struct device_node *np = pdev->dev.of_node; in s3c24xx_serial_probe()
1849 dev_err(&pdev->dev, "serial%d out of range\n", index); in s3c24xx_serial_probe()
1850 return -EINVAL; in s3c24xx_serial_probe()
1854 ourport->drv_data = s3c24xx_get_driver_data(pdev); in s3c24xx_serial_probe()
1855 if (!ourport->drv_data) { in s3c24xx_serial_probe()
1856 dev_err(&pdev->dev, "could not find driver data\n"); in s3c24xx_serial_probe()
1857 return -ENODEV; in s3c24xx_serial_probe()
1860 ourport->baudclk = ERR_PTR(-EINVAL); in s3c24xx_serial_probe()
1861 ourport->info = ourport->drv_data->info; in s3c24xx_serial_probe()
1862 ourport->cfg = (dev_get_platdata(&pdev->dev)) ? in s3c24xx_serial_probe()
1863 dev_get_platdata(&pdev->dev) : in s3c24xx_serial_probe()
1864 ourport->drv_data->def_cfg; in s3c24xx_serial_probe()
1868 "samsung,uart-fifosize", &ourport->port.fifosize); in s3c24xx_serial_probe()
1870 if (ourport->drv_data->fifosize[index]) in s3c24xx_serial_probe()
1871 ourport->port.fifosize = ourport->drv_data->fifosize[index]; in s3c24xx_serial_probe()
1872 else if (ourport->info->fifosize) in s3c24xx_serial_probe()
1873 ourport->port.fifosize = ourport->info->fifosize; in s3c24xx_serial_probe()
1879 ourport->min_dma_size = max_t(int, ourport->port.fifosize, in s3c24xx_serial_probe()
1891 pr_err("Failed to register Samsung UART driver\n"); in s3c24xx_serial_probe()
1897 uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); in s3c24xx_serial_probe()
1898 platform_set_drvdata(pdev, &ourport->port); in s3c24xx_serial_probe()
1902 * so that a potential re-enablement through the pm-callback overlaps in s3c24xx_serial_probe()
1905 clk_disable_unprepare(ourport->clk); in s3c24xx_serial_probe()
1909 dev_err(&pdev->dev, "failed to add cpufreq notifier\n"); in s3c24xx_serial_probe()
1918 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); in s3c24xx_serial_remove()
1930 /* UART power management code */
1948 clk_prepare_enable(ourport->clk); in s3c24xx_serial_resume()
1949 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_resume()
1950 clk_prepare_enable(ourport->baudclk); in s3c24xx_serial_resume()
1952 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_resume()
1953 clk_disable_unprepare(ourport->baudclk); in s3c24xx_serial_resume()
1954 clk_disable_unprepare(ourport->clk); in s3c24xx_serial_resume()
1975 clk_prepare_enable(ourport->clk); in s3c24xx_serial_resume_noirq()
1976 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_resume_noirq()
1977 clk_prepare_enable(ourport->baudclk); in s3c24xx_serial_resume_noirq()
1979 if (!IS_ERR(ourport->baudclk)) in s3c24xx_serial_resume_noirq()
1980 clk_disable_unprepare(ourport->baudclk); in s3c24xx_serial_resume_noirq()
1981 clk_disable_unprepare(ourport->clk); in s3c24xx_serial_resume_noirq()
2013 /* fifo mode - check amount of data in fifo registers... */ in s3c24xx_serial_console_txrdy()
2016 return (ufstat & info->tx_fifofull) ? 0 : 1; in s3c24xx_serial_console_txrdy()
2019 /* in non-fifo mode, we go and use the tx buffer empty */ in s3c24xx_serial_console_txrdy()
2034 * Console polling routines for writing and reading from the uart while
2146 clk = clk_get(port->dev, clk_name); in s3c24xx_serial_get_options()
2168 co, co->index, options); in s3c24xx_serial_console_setup()
2172 if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) in s3c24xx_serial_console_setup()
2173 co->index = 0; in s3c24xx_serial_console_setup()
2175 port = &s3c24xx_serial_ports[co->index].port; in s3c24xx_serial_console_setup()
2179 if (port->mapbase == 0x0) in s3c24xx_serial_console_setup()
2180 return -ENODEV; in s3c24xx_serial_console_setup()
2184 dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index); in s3c24xx_serial_console_setup()
2187 * Check whether an invalid uart number has been specified, and in s3c24xx_serial_console_setup()
2205 .index = -1,
2215 .name = "Samsung S3C2410 UART",
2242 .name = "Samsung S3C2412 UART",
2271 .name = "Samsung S3C2440 UART",
2299 .name = "Samsung S3C6400 UART",
2327 .name = "Samsung S5PV210 UART",
2355 .name = "Samsung Exynos UART", \
2394 .name = "s3c2410-uart",
2397 .name = "s3c2412-uart",
2400 .name = "s3c2440-uart",
2403 .name = "s3c6400-uart",
2406 .name = "s5pv210-uart",
2409 .name = "exynos4210-uart",
2412 .name = "exynos5433-uart",
2421 { .compatible = "samsung,s3c2410-uart",
2423 { .compatible = "samsung,s3c2412-uart",
2425 { .compatible = "samsung,s3c2440-uart",
2427 { .compatible = "samsung,s3c6400-uart",
2429 { .compatible = "samsung,s5pv210-uart",
2431 { .compatible = "samsung,exynos4210-uart",
2433 { .compatible = "samsung,exynos5433-uart",
2445 .name = "samsung-uart",
2464 while (!(readl(port->membase + S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE)) in samsung_early_busyuart()
2470 struct samsung_early_console_data *data = port->private_data; in samsung_early_busyuart_fifo()
2472 while (readl(port->membase + S3C2410_UFSTAT) & data->txfull_mask) in samsung_early_busyuart_fifo()
2478 if (readl(port->membase + S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) in samsung_early_putc()
2483 writeb(c, port->membase + S3C2410_UTXH); in samsung_early_putc()
2488 struct earlycon_device *dev = con->data; in samsung_early_write()
2490 uart_console_write(&dev->port, s, n, samsung_early_putc); in samsung_early_write()
2496 if (!device->port.membase) in samsung_early_console_setup()
2497 return -ENODEV; in samsung_early_console_setup()
2499 device->con->write = samsung_early_write; in samsung_early_console_setup()
2511 device->port.private_data = &s3c2410_early_console_data; in s3c2410_early_console_setup()
2514 OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
2525 device->port.private_data = &s3c2440_early_console_data; in s3c2440_early_console_setup()
2528 OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
2530 OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
2532 OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
2543 device->port.private_data = &s5pv210_early_console_data; in s5pv210_early_console_setup()
2546 OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
2548 OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
2552 MODULE_ALIAS("platform:samsung-uart");