From: "Chang, Rebecca Swee Fun" <[email protected]>
Baytrail has two HSUART controllers which can be PCI or ACPI enumerated. Signed-off-by: Chang, Rebecca Swee Fun <[email protected]> --- ...-Add-support-for-HSUART-controllers-on-In.patch | 1295 ++++++++++++++++++++ 1 file changed, 1295 insertions(+) create mode 100644 meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch diff --git a/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch b/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch new file mode 100644 index 0000000..6f9b8e8 --- /dev/null +++ b/meta/cfg/kernel-cache/features/valleyisland-io/0003-serial-8250-Add-support-for-HSUART-controllers-on-In.patch @@ -0,0 +1,1295 @@ +serial/8250: Add support for HSUART controllers on Baytrail + +Baytrail has two HSUART controllers which can be PCI or ACPI enumerated. + +Signed-off-by: Chang, Rebecca Swee Fun <[email protected]> +--- + drivers/tty/serial/8250/8250.c | 72 +++++-- + drivers/tty/serial/8250/8250.h | 55 +++++ + drivers/tty/serial/8250/8250_dma.c | 222 ++++++++++++++++++++ + drivers/tty/serial/8250/8250_dw.c | 378 +++++++++++++++++++++++++++++----- + drivers/tty/serial/8250/8250_early.c | 2 +- + drivers/tty/serial/8250/8250_pci.c | 190 +++++++++++++++++ + drivers/tty/serial/8250/Kconfig | 10 +- + drivers/tty/serial/8250/Makefile | 1 + + include/linux/serial_8250.h | 4 + + 9 files changed, 873 insertions(+), 61 deletions(-) + create mode 100644 drivers/tty/serial/8250/8250_dma.c + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index f932043..469a83c 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -1341,7 +1341,9 @@ static void serial8250_start_tx(struct uart_port *port) + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); + +- if (!(up->ier & UART_IER_THRI)) { ++ if (up->dma && !serial8250_tx_dma(up)) { ++ return; ++ } else if (!(up->ier & UART_IER_THRI)) { + up->ier |= UART_IER_THRI; + serial_port_out(port, UART_IER, up->ier); + +@@ -1397,7 +1399,6 @@ unsigned char + serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) + { + struct uart_port *port = &up->port; +- struct tty_struct *tty = port->state->port.tty; + unsigned char ch; + int max_count = 256; + char flag; +@@ -1462,7 +1463,7 @@ ignore_char: + lsr = serial_in(up, UART_LSR); + } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0)); + spin_unlock(&port->lock); +- tty_flip_buffer_push(tty); ++ tty_flip_buffer_push(&port->state->port); + spin_lock(&port->lock); + return lsr; + } +@@ -1518,6 +1519,10 @@ unsigned int serial8250_modem_status(struct uart_8250_port *up) + struct uart_port *port = &up->port; + unsigned int status = serial_in(up, UART_MSR); + ++ if (up->ier & UART_IER_MSI && up->mcr & UART_MCR_AFE) { ++ status &= ~(UART_MSR_DCTS); ++ status |= UART_MSR_CTS; ++ } + status |= up->msr_saved_flags; + up->msr_saved_flags = 0; + if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI && +@@ -1547,20 +1552,34 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) + unsigned long flags; + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); ++ int dma_err = 0; + + if (iir & UART_IIR_NO_INT) + return 0; + + spin_lock_irqsave(&port->lock, flags); + ++ if( (up->port.dev->id == PCI_DEVICE_ID_INTEL_BYT_UART1 || ++ up->port.dev->id == PCI_DEVICE_ID_INTEL_BYT_UART2) && ++ (iir & UART_IIR_RLSI) ) { ++ ++ readl(port->membase + LPSS_UART_BYTE_CNT); ++ readl(port->membase + LPSS_UART_OVRFLW_INTR_STAT); ++ } ++ + status = serial_port_in(port, UART_LSR); + + DEBUG_INTR("status = %x...", status); + +- if (status & (UART_LSR_DR | UART_LSR_BI)) +- status = serial8250_rx_chars(up, status); ++ if (status & (UART_LSR_DR | UART_LSR_BI)) { ++ if (up->dma) ++ dma_err = serial8250_rx_dma(up, iir); ++ ++ if (!up->dma || dma_err) ++ status = serial8250_rx_chars(up, status); ++ } + serial8250_modem_status(up); +- if (status & UART_LSR_THRE) ++ if (status & UART_LSR_THRE && (iir & 0x3f) == UART_IIR_THRI) + serial8250_tx_chars(up); + + spin_unlock_irqrestore(&port->lock, flags); +@@ -1991,9 +2010,12 @@ static int serial8250_startup(struct uart_port *port) + if (port->type == PORT_8250_CIR) + return -ENODEV; + +- port->fifosize = uart_config[up->port.type].fifo_size; +- up->tx_loadsz = uart_config[up->port.type].tx_loadsz; +- up->capabilities = uart_config[up->port.type].flags; ++ if (!port->fifosize) ++ port->fifosize = uart_config[port->type].fifo_size; ++ if (!up->tx_loadsz) ++ up->tx_loadsz = uart_config[port->type].tx_loadsz; ++ if (!up->capabilities) ++ up->capabilities = uart_config[port->type].flags; + up->mcr = 0; + + if (port->iotype != up->cur_iotype) +@@ -2198,6 +2220,18 @@ dont_test_tx_en: + up->msr_saved_flags = 0; + + /* ++ * Request DMA channels for both RX and TX. ++ */ ++ if (up->dma) { ++ retval = serial8250_request_dma(up); ++ if (retval) { ++ pr_warn_ratelimited("ttyS%d - failed to request DMA\n", ++ serial_index(port)); ++ up->dma = NULL; ++ } ++ } ++ ++ /* + * Finally, enable interrupts. Note: Modem status interrupts + * are set via set_termios(), which will be occurring imminently + * anyway, so we don't enable them here. +@@ -2230,6 +2264,9 @@ static void serial8250_shutdown(struct uart_port *port) + up->ier = 0; + serial_port_out(port, UART_IER, 0); + ++ if (up->dma) ++ serial8250_release_dma(up); ++ + spin_lock_irqsave(&port->lock, flags); + if (port->flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ +@@ -2344,7 +2381,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + + if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { + fcr = uart_config[port->type].fcr; +- if (baud < 2400 || fifo_bug) { ++ if (baud < 2400 && !up->dma || fifo_bug) { + fcr &= ~UART_FCR_TRIGGER_MASK; + fcr |= UART_FCR_TRIGGER_1; + } +@@ -2826,9 +2863,12 @@ static void + serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type) + { + up->port.type = type; +- up->port.fifosize = uart_config[type].fifo_size; +- up->capabilities = uart_config[type].flags; +- up->tx_loadsz = uart_config[type].tx_loadsz; ++ if (!up->port.fifosize) ++ up->port.fifosize = uart_config[type].fifo_size; ++ if (!up->tx_loadsz) ++ up->tx_loadsz = uart_config[type].tx_loadsz; ++ if (!up->capabilities) ++ up->capabilities = uart_config[type].flags; + } + + static void __init +@@ -3262,6 +3302,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up) + uart->bugs = up->bugs; + uart->port.mapbase = up->port.mapbase; + uart->port.private_data = up->port.private_data; ++ uart->port.fifosize = up->port.fifosize; ++ uart->tx_loadsz = up->tx_loadsz; ++ uart->capabilities = up->capabilities; ++ + if (up->port.dev) + uart->port.dev = up->port.dev; + +@@ -3287,6 +3331,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) + uart->dl_read = up->dl_read; + if (up->dl_write) + uart->dl_write = up->dl_write; ++ if (up->dma) ++ uart->dma = up->dma; + + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, +diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h +index 12caa12..aa97212 100644 +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -12,6 +12,35 @@ + */ + + #include <linux/serial_8250.h> ++#include <linux/dmaengine.h> ++ ++struct uart_8250_dma { ++ dma_filter_fn fn; ++ void *rx_param; ++ void *tx_param; ++ ++ int rx_chan_id; ++ int tx_chan_id; ++ ++ struct dma_slave_config rxconf; ++ struct dma_slave_config txconf; ++ ++ struct dma_chan *rxchan; ++ struct dma_chan *txchan; ++ ++ dma_addr_t rx_addr; ++ dma_addr_t tx_addr; ++ ++ dma_cookie_t rx_cookie; ++ dma_cookie_t tx_cookie; ++ ++ void *rx_buf; ++ ++ size_t rx_size; ++ size_t tx_size; ++ ++ unsigned char tx_running:1; ++}; + + struct old_serial_port { + unsigned int uart; +@@ -59,6 +88,11 @@ struct serial8250_config { + #define SERIAL8250_SHARE_IRQS 0 + #endif + ++#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a ++#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c ++#define LPSS_UART_BYTE_CNT 0x818 ++#define LPSS_UART_OVRFLW_INTR_STAT 0x820 ++ + static inline int serial_in(struct uart_8250_port *up, int offset) + { + return up->port.serial_in(&up->port, offset); +@@ -143,3 +177,24 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt) + return 0; + } + #endif ++ ++#ifdef CONFIG_SERIAL_8250_DMA ++extern int serial8250_tx_dma(struct uart_8250_port *); ++extern int serial8250_rx_dma(struct uart_8250_port *, unsigned int iir); ++extern int serial8250_request_dma(struct uart_8250_port *); ++extern void serial8250_release_dma(struct uart_8250_port *); ++#else ++static inline int serial8250_tx_dma(struct uart_8250_port *p) ++{ ++ return -1; ++} ++static inline int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) ++{ ++ return -1; ++} ++static inline int serial8250_request_dma(struct uart_8250_port *p) ++{ ++ return -1; ++} ++static inline void serial8250_release_dma(struct uart_8250_port *p) { } ++#endif +diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c +new file mode 100644 +index 0000000..29d45e7 +--- /dev/null ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -0,0 +1,222 @@ ++/* ++ * 8250_dma.c - DMA Engine API support for 8250.c ++ * ++ * Copyright (C) 2013 Intel Corporation ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include <linux/tty.h> ++#include <linux/tty_flip.h> ++#include <linux/serial_reg.h> ++#include <linux/dma-mapping.h> ++ ++#include "8250.h" ++ ++static void __dma_tx_complete(void *param) ++{ ++ struct uart_8250_port *p = param; ++ struct uart_8250_dma *dma = p->dma; ++ struct circ_buf *xmit = &p->port.state->xmit; ++ ++ dma->tx_running = 0; ++ ++ dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, ++ UART_XMIT_SIZE, DMA_TO_DEVICE); ++ ++ xmit->tail += dma->tx_size; ++ xmit->tail &= UART_XMIT_SIZE - 1; ++ p->port.icount.tx += dma->tx_size; ++ ++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ uart_write_wakeup(&p->port); ++ ++ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) ++ serial8250_tx_dma(p); ++} ++ ++static void __dma_rx_complete(void *param) ++{ ++ struct uart_8250_port *p = param; ++ struct uart_8250_dma *dma = p->dma; ++ struct tty_port *tty_port = &p->port.state->port; ++ struct dma_tx_state state; ++ int count; ++ ++ dma_sync_single_for_cpu(dma->rxchan->device->dev, dma->rx_addr, ++ dma->rx_size, DMA_FROM_DEVICE); ++ ++ dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); ++ dmaengine_terminate_all(dma->rxchan); ++ ++ count = dma->rx_size - state.residue; ++ ++ tty_insert_flip_string(tty_port, dma->rx_buf, count); ++ p->port.icount.rx += count; ++ ++ tty_flip_buffer_push(tty_port); ++} ++ ++int serial8250_tx_dma(struct uart_8250_port *p) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ struct circ_buf *xmit = &p->port.state->xmit; ++ struct dma_async_tx_descriptor *desc; ++ ++ if (uart_tx_stopped(&p->port) || dma->tx_running ++ || uart_circ_empty(xmit)) ++ return 0; ++ ++ dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); ++ ++ desc = dmaengine_prep_slave_single(dma->txchan, ++ dma->tx_addr + xmit->tail, ++ dma->tx_size, DMA_MEM_TO_DEV, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) ++ return -EBUSY; ++ ++ dma->tx_running = 1; ++ ++ desc->callback = __dma_tx_complete; ++ desc->callback_param = p; ++ ++ dma->tx_cookie = dmaengine_submit(desc); ++ ++ dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr, ++ UART_XMIT_SIZE, DMA_TO_DEVICE); ++ ++ dma_async_issue_pending(dma->txchan); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(serial8250_tx_dma); ++ ++int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ struct dma_async_tx_descriptor *desc; ++ struct dma_tx_state state; ++ int dma_status; ++ ++ dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); ++ ++ switch (iir & 0x3f) { ++ case UART_IIR_RLSI: ++ /* 8250.c handles errors and break interrupts */ ++ return -EIO; ++ case UART_IIR_RX_TIMEOUT: ++ /* ++ * If RCVR FIFO trigger level was not reached, complete the ++ * transfer and let 8250.c copy the remaining data. ++ */ ++ if (dma_status == DMA_IN_PROGRESS) { ++ dmaengine_pause(dma->rxchan); ++ __dma_rx_complete(p); ++ } ++ return -ETIMEDOUT; ++ default: ++ break; ++ } ++ ++ if (dma_status) ++ return 0; ++ ++ desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, ++ dma->rx_size, DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) ++ return -EBUSY; ++ ++ desc->callback = __dma_rx_complete; ++ desc->callback_param = p; ++ ++ dma->rx_cookie = dmaengine_submit(desc); ++ ++ dma_sync_single_for_device(dma->rxchan->device->dev, dma->rx_addr, ++ dma->rx_size, DMA_FROM_DEVICE); ++ ++ dma_async_issue_pending(dma->rxchan); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(serial8250_rx_dma); ++ ++int serial8250_request_dma(struct uart_8250_port *p) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ dma_cap_mask_t mask; ++ ++ dma->rxconf.src_addr = p->port.mapbase + UART_RX; ++ dma->txconf.dst_addr = p->port.mapbase + UART_TX; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ /* Get a channel for RX */ ++ dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param); ++ if (!dma->rxchan) ++ return -ENODEV; ++ ++ dmaengine_slave_config(dma->rxchan, &dma->rxconf); ++ ++ /* Get a channel for TX */ ++ dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param); ++ if (!dma->txchan) { ++ dma_release_channel(dma->rxchan); ++ return -ENODEV; ++ } ++ ++ dmaengine_slave_config(dma->txchan, &dma->txconf); ++ ++ /* RX buffer */ ++ if (!dma->rx_size) ++ dma->rx_size = PAGE_SIZE; ++ ++ dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size, ++ &dma->rx_addr, GFP_KERNEL); ++ if (!dma->rx_buf) { ++ dma_release_channel(dma->rxchan); ++ dma_release_channel(dma->txchan); ++ return -ENOMEM; ++ } ++ ++ /* TX buffer */ ++ dma->tx_addr = dma_map_single(dma->txchan->device->dev, ++ p->port.state->xmit.buf, ++ UART_XMIT_SIZE, ++ DMA_TO_DEVICE); ++ ++ dev_dbg_ratelimited(p->port.dev, "got both dma channels\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(serial8250_request_dma); ++ ++void serial8250_release_dma(struct uart_8250_port *p) ++{ ++ struct uart_8250_dma *dma = p->dma; ++ ++ if (!dma) ++ return; ++ ++ /* Release RX resources */ ++ dmaengine_terminate_all(dma->rxchan); ++ dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, dma->rx_buf, ++ dma->rx_addr); ++ dma_release_channel(dma->rxchan); ++ dma->rxchan = NULL; ++ ++ /* Release TX resources */ ++ dmaengine_terminate_all(dma->txchan); ++ dma_unmap_single(dma->txchan->device->dev, dma->tx_addr, ++ UART_XMIT_SIZE, DMA_TO_DEVICE); ++ dma_release_channel(dma->txchan); ++ dma->txchan = NULL; ++ dma->tx_running = 0; ++ ++ dev_dbg_ratelimited(p->port.dev, "dma channels released\n"); ++} ++EXPORT_SYMBOL_GPL(serial8250_release_dma); +diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c +index 096d2ef..1d8ed86 100644 +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -2,6 +2,7 @@ + * Synopsys DesignWare 8250 driver. + * + * Copyright 2011 Picochip, Jamie Iles. ++ * Copyright 2013 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -24,10 +25,42 @@ + #include <linux/of_platform.h> + #include <linux/platform_device.h> + #include <linux/slab.h> ++#include <linux/acpi.h> ++#include <linux/pm_runtime.h> ++#include <linux/clk.h> ++ ++#include "8250.h" ++ ++static bool use_dma = 1; ++module_param(use_dma, bool, 0); ++MODULE_PARM_DESC(use_dma, "use_dma=1 (enable DMA)/use_dma=0(disable DMA)"); ++ ++/* Offsets for the DesignWare specific registers */ ++#define DW_UART_USR 0x1f /* UART Status Register */ ++#define DW_UART_CPR 0xf4 /* Component Parameter Register */ ++#define DW_UART_UCV 0xf8 /* UART Component Version */ ++ ++/* Component Parameter Register bits */ ++#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) ++#define DW_UART_CPR_AFCE_MODE (1 << 4) ++#define DW_UART_CPR_THRE_MODE (1 << 5) ++#define DW_UART_CPR_SIR_MODE (1 << 6) ++#define DW_UART_CPR_SIR_LP_MODE (1 << 7) ++#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) ++#define DW_UART_CPR_FIFO_ACCESS (1 << 9) ++#define DW_UART_CPR_FIFO_STAT (1 << 10) ++#define DW_UART_CPR_SHADOW (1 << 11) ++#define DW_UART_CPR_ENCODED_PARMS (1 << 12) ++#define DW_UART_CPR_DMA_EXTRA (1 << 13) ++#define DW_UART_CPR_FIFO_MODE (0xff << 16) ++/* Helper for fifo size calculation */ ++#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) ++ + + struct dw8250_data { + int last_lcr; + int line; ++ struct clk *clk; + }; + + static void dw8250_serial_out(struct uart_port *p, int offset, int value) +@@ -66,19 +99,79 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) + return readl(p->membase + offset); + } + +-/* Offset for the DesignWare's UART Status Register. */ +-#define UART_USR 0x1f ++#define LPSS_PRV_CLK 0x800 ++#define LPSS_PRV_CLK_EN (1 << 0) ++#define LPSS_PRV_CLK_M_VAL_SHIFT 1 ++#define LPSS_PRV_CLK_N_VAL_SHIFT 16 ++#define LPSS_PRV_CLK_UPDATE (1 << 31) ++ ++#define LPSS_HSUART_GENERAL_REG 0x808 ++#define LPSS_GENERAL_DIS_RTS_N_OVERRIDE (1 << 3) ++ ++static void ++dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ++ struct ktermios *old) ++{ ++ struct uart_8250_port *up = ++ container_of(p, struct uart_8250_port, port); ++ unsigned int baud = tty_termios_baud_rate(termios); ++ unsigned int m = 6912; ++ unsigned int n = 15625; ++ u32 reg; ++ ++ /* ++ * For baud rates 1000000, 2000000 and 4000000 the dividers must be ++ * adjusted. ++ */ ++ if (baud == 1000000 || baud == 2000000 || baud == 4000000) { ++ m = 64; ++ n = 100; ++ ++ p->uartclk = 64000000; ++ } else if (baud == 3000000){ ++ m = 48; ++ n = 100; ++ ++ p->uartclk = 48000000; ++ }else { ++ p->uartclk = 44236800; ++ } ++ ++ /* Reset the clock */ ++ reg = (m << LPSS_PRV_CLK_M_VAL_SHIFT) | (n << LPSS_PRV_CLK_N_VAL_SHIFT); ++ writel(reg, p->membase + LPSS_PRV_CLK); ++ reg |= LPSS_PRV_CLK_EN | LPSS_PRV_CLK_UPDATE; ++ writel(reg, p->membase + LPSS_PRV_CLK); ++ ++ /* For BYT, hs-uart is capable of auto flow control */ ++ up->capabilities |= UART_CAP_AFE; ++ ++ /* If auto-handshake mechanism is not enabled, ++ * disable rts_n override */ ++ reg = readl(p->membase + LPSS_HSUART_GENERAL_REG); ++ reg &= ~LPSS_GENERAL_DIS_RTS_N_OVERRIDE; ++ if (termios->c_cflag & CRTSCTS) ++ reg |= LPSS_GENERAL_DIS_RTS_N_OVERRIDE; ++ writel(reg, p->membase + LPSS_HSUART_GENERAL_REG); ++ ++ serial8250_do_set_termios(p, termios, old); ++} + + static int dw8250_handle_irq(struct uart_port *p) + { + struct dw8250_data *d = p->private_data; + unsigned int iir = p->serial_in(p, UART_IIR); + ++ if(iir & UART_IIR_RLSI) { ++ readl(p->membase + LPSS_UART_BYTE_CNT); ++ readl(p->membase + LPSS_UART_OVRFLW_INTR_STAT); ++ } ++ + if (serial8250_handle_irq(p, iir)) { + return 1; + } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { + /* Clear the USR and write the LCR again. */ +- (void)p->serial_in(p, UART_USR); ++ (void)p->serial_in(p, DW_UART_USR); + p->serial_out(p, UART_LCR, d->last_lcr); + + return 1; +@@ -87,61 +180,216 @@ static int dw8250_handle_irq(struct uart_port *p) + return 0; + } + ++static void ++dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) ++{ ++ if (!state) ++ pm_runtime_get_sync(port->dev); ++ ++ serial8250_do_pm(port, state, old); ++ ++ if (state) ++ pm_runtime_put_sync_suspend(port->dev); ++} ++ ++static int dw8250_probe_of(struct uart_port *p) ++{ ++ struct device_node *np = p->dev->of_node; ++ u32 val; ++ ++ if (!of_property_read_u32(np, "reg-io-width", &val)) { ++ switch (val) { ++ case 1: ++ break; ++ case 4: ++ p->iotype = UPIO_MEM32; ++ p->serial_in = dw8250_serial_in32; ++ p->serial_out = dw8250_serial_out32; ++ break; ++ default: ++ dev_err(p->dev, "unsupported reg-io-width (%u)\n", val); ++ return -EINVAL; ++ } ++ } ++ ++ if (!of_property_read_u32(np, "reg-shift", &val)) ++ p->regshift = val; ++ ++ if (of_property_read_u32(np, "clock-frequency", &val)) { ++ dev_err(p->dev, "no clock-frequency property set\n"); ++ return -EINVAL; ++ } ++ p->uartclk = val; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_ACPI ++static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm) ++{ ++ return chan->chan_id == *(int *)parm; ++} ++ ++static acpi_status ++dw8250_acpi_walk_resource(struct acpi_resource *res, void *data) ++{ ++ struct uart_port *p = data; ++ struct uart_8250_port *port; ++ struct uart_8250_dma *dma; ++ struct acpi_resource_fixed_dma *fixed_dma; ++ struct dma_slave_config *slave; ++ ++ port = container_of(p, struct uart_8250_port, port); ++ ++ switch (res->type) { ++ case ACPI_RESOURCE_TYPE_FIXED_DMA: ++ fixed_dma = &res->data.fixed_dma; ++ ++ /* TX comes first */ ++ if (!port->dma) { ++ dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL); ++ if (!dma) ++ return AE_NO_MEMORY; ++ ++ port->dma = dma; ++ slave = &dma->txconf; ++ ++ slave->direction = DMA_MEM_TO_DEV; ++ slave->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ slave->slave_id = fixed_dma->request_lines; ++ slave->dst_maxburst = port->tx_loadsz / 4; ++ ++ dma->tx_chan_id = fixed_dma->channels; ++ dma->tx_param = &dma->tx_chan_id; ++ dma->fn = dw8250_acpi_dma_filter; ++ } else { ++ dma = port->dma; ++ slave = &dma->rxconf; ++ ++ slave->direction = DMA_DEV_TO_MEM; ++ slave->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ slave->slave_id = fixed_dma->request_lines; ++ slave->src_maxburst = p->fifosize / 4; ++ ++ dma->rx_chan_id = fixed_dma->channels; ++ dma->rx_param = &dma->rx_chan_id; ++ } ++ ++ break; ++ } ++ ++ return AE_OK; ++} ++ ++static int dw8250_probe_acpi(struct uart_port *p) ++{ ++ struct dw8250_data *data = p->private_data; ++ acpi_status status; ++ ++ p->iotype = UPIO_MEM32; ++ p->serial_in = dw8250_serial_in32; ++ p->serial_out = dw8250_serial_out32; ++ p->set_termios = dw8250_set_termios; ++ p->regshift = 2; ++ p->uartclk = clk_get_rate(data->clk); ++ ++ if (use_dma){ ++ status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS, ++ dw8250_acpi_walk_resource, p); ++ if (ACPI_FAILURE(status)) { ++ dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__, ++ acpi_format_exception(status)); ++ return -ENODEV; ++ } ++ } ++ return 0; ++} ++#else ++static inline int dw8250_probe_acpi(struct uart_port *p) ++{ ++ return -ENODEV; ++} ++#endif /* CONFIG_ACPI */ ++ ++static void dw8250_setup_port(struct uart_8250_port *up) ++{ ++ struct uart_port *p = &up->port; ++ u32 reg = readl(p->membase + DW_UART_UCV); ++ ++ /* ++ * If the Component Version Register returns zero, we know that ++ * ADDITIONAL_FEATURES are not enabled. No need to go any further. ++ */ ++ if (!reg) ++ return; ++ ++ dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", ++ (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); ++ ++ reg = readl(p->membase + DW_UART_CPR); ++ if (!reg) ++ return; ++ ++ /* Select the type based on fifo */ ++ if (reg & DW_UART_CPR_FIFO_MODE) { ++ p->type = PORT_16550A; ++ p->flags |= UPF_FIXED_TYPE; ++ p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); ++ up->tx_loadsz = p->fifosize; ++ } ++} ++ + static int dw8250_probe(struct platform_device *pdev) + { + struct uart_8250_port uart = {}; + struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- struct device_node *np = pdev->dev.of_node; +- u32 val; + struct dw8250_data *data; ++ int err; + + if (!regs || !irq) { + dev_err(&pdev->dev, "no registers/irq defined\n"); + return -EINVAL; + } + +- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- uart.port.private_data = data; +- + spin_lock_init(&uart.port.lock); + uart.port.mapbase = regs->start; + uart.port.irq = irq->start; + uart.port.handle_irq = dw8250_handle_irq; ++ uart.port.pm = dw8250_do_pm; + uart.port.type = PORT_8250; +- uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | +- UPF_FIXED_PORT | UPF_FIXED_TYPE; ++ uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; + uart.port.dev = &pdev->dev; + ++ uart.port.membase = ioremap(regs->start, resource_size(regs)); ++ if (!uart.port.membase) ++ return -ENOMEM; ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ + uart.port.iotype = UPIO_MEM; + uart.port.serial_in = dw8250_serial_in; + uart.port.serial_out = dw8250_serial_out; +- if (!of_property_read_u32(np, "reg-io-width", &val)) { +- switch (val) { +- case 1: +- break; +- case 4: +- uart.port.iotype = UPIO_MEM32; +- uart.port.serial_in = dw8250_serial_in32; +- uart.port.serial_out = dw8250_serial_out32; +- break; +- default: +- dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n", +- val); +- return -EINVAL; +- } +- } +- +- if (!of_property_read_u32(np, "reg-shift", &val)) +- uart.port.regshift = val; ++ uart.port.private_data = data; + +- if (of_property_read_u32(np, "clock-frequency", &val)) { +- dev_err(&pdev->dev, "no clock-frequency property set\n"); +- return -EINVAL; ++ data->clk = devm_clk_get(&pdev->dev, NULL); ++ clk_prepare_enable(data->clk); ++ ++ dw8250_setup_port(&uart); ++ ++ if (pdev->dev.of_node) { ++ err = dw8250_probe_of(&uart.port); ++ if (err) ++ return err; ++ } else if (ACPI_HANDLE(&pdev->dev)) { ++ err = dw8250_probe_acpi(&uart.port); ++ if (err) ++ return err; ++ } else { ++ return -ENODEV; + } +- uart.port.uartclk = val; + + data->line = serial8250_register_8250_port(&uart); + if (data->line < 0) +@@ -149,6 +397,8 @@ static int dw8250_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, data); + ++ pm_runtime_forbid(&pdev->dev); ++ + return 0; + } + +@@ -156,50 +406,86 @@ static int dw8250_remove(struct platform_device *pdev) + { + struct dw8250_data *data = platform_get_drvdata(pdev); + ++ pm_runtime_get_sync(&pdev->dev); ++ + serial8250_unregister_port(data->line); ++ clk_disable_unprepare(data->clk); ++ ++ pm_runtime_disable(&pdev->dev); ++ pm_runtime_put_noidle(&pdev->dev); + + return 0; + } + + #ifdef CONFIG_PM +-static int dw8250_suspend(struct platform_device *pdev, pm_message_t state) ++static int dw8250_suspend(struct device *dev) + { +- struct dw8250_data *data = platform_get_drvdata(pdev); ++ struct dw8250_data *data = dev_get_drvdata(dev); + + serial8250_suspend_port(data->line); + + return 0; + } + +-static int dw8250_resume(struct platform_device *pdev) ++static int dw8250_resume(struct device *dev) + { +- struct dw8250_data *data = platform_get_drvdata(pdev); ++ struct dw8250_data *data = dev_get_drvdata(dev); + + serial8250_resume_port(data->line); + + return 0; + } +-#else +-#define dw8250_suspend NULL +-#define dw8250_resume NULL + #endif /* CONFIG_PM */ + +-static const struct of_device_id dw8250_match[] = { ++#ifdef CONFIG_PM_RUNTIME ++static int dw8250_runtime_suspend(struct device *dev) ++{ ++ struct dw8250_data *data = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(data->clk); ++ ++ return 0; ++} ++ ++static int dw8250_runtime_resume(struct device *dev) ++{ ++ struct dw8250_data *data = dev_get_drvdata(dev); ++ ++ clk_prepare_enable(data->clk); ++ ++ return 0; ++} ++#endif ++ ++static const struct dev_pm_ops dw8250_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume) ++ SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id dw8250_of_match[] = { + { .compatible = "snps,dw-apb-uart" }, + { /* Sentinel */ } + }; +-MODULE_DEVICE_TABLE(of, dw8250_match); ++MODULE_DEVICE_TABLE(of, dw8250_of_match); ++ ++static const struct acpi_device_id dw8250_acpi_match[] = { ++ { "80860F0A", 0 }, ++ { "INT33C4", 0 }, ++ { "INT33C5", 0 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); + + static struct platform_driver dw8250_platform_driver = { + .driver = { + .name = "dw-apb-uart", + .owner = THIS_MODULE, +- .of_match_table = dw8250_match, ++ .pm = &dw8250_pm_ops, ++ .of_match_table = dw8250_of_match, ++ .acpi_match_table = ACPI_PTR(dw8250_acpi_match), + }, + .probe = dw8250_probe, + .remove = dw8250_remove, +- .suspend = dw8250_suspend, +- .resume = dw8250_resume, + }; + + module_platform_driver(dw8250_platform_driver); +diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c +index f53a7db..721904f 100644 +--- a/drivers/tty/serial/8250/8250_early.c ++++ b/drivers/tty/serial/8250/8250_early.c +@@ -194,7 +194,7 @@ static int __init parse_options(struct early_serial8250_device *device, + options++; + device->baud = simple_strtoul(options, NULL, 0); + length = min(strcspn(options, " "), sizeof(device->options)); +- strncpy(device->options, options, length); ++ strlcpy(device->options, options, length); + } else { + device->baud = probe_baud(port); + snprintf(device->options, sizeof(device->options), "%u", +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index a27a98e..27b82d4 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -1077,6 +1077,134 @@ ce4100_serial_setup(struct serial_private *priv, + return ret; + } + ++static bool lpss_dma_filter(struct dma_chan *chan, void *param) ++{ ++ return chan->chan_id == *(int*)param; ++} ++ ++#define PCI_DEVICE_ID_INTEL_HSW_UART1 0x9c63 ++#define PCI_DEVICE_ID_INTEL_HSW_UART2 0x9c64 ++ ++#define LPSS_PRV_CLK 0x800 ++#define LPSS_PRV_CLK_EN (1 << 0) ++#define LPSS_PRV_CLK_M_VAL_SHIFT 1 ++#define LPSS_PRV_CLK_N_VAL_SHIFT 16 ++#define LPSS_PRV_CLK_UPDATE (1 << 31) ++ ++#define LPSS_HSUART_GENERAL_REG 0x808 ++#define LPSS_GENERAL_DIS_RTS_N_OVERRIDE (1 << 3) ++ ++static void ++lpss_set_termios(struct uart_port *p, struct ktermios *termios, ++ struct ktermios *old) ++{ ++ struct uart_8250_port *up = ++ container_of(p, struct uart_8250_port, port); ++ unsigned int baud = tty_termios_baud_rate(termios); ++ unsigned int m = 6912; ++ unsigned int n = 15625; ++ u32 reg; ++ ++ /* ++ * For baud rates 1000000, 2000000 and 4000000 the dividers must be ++ * adjusted. ++ */ ++ if (baud == 1000000 || baud == 2000000 || baud == 4000000) { ++ m = 64; ++ n = 100; ++ ++ p->uartclk = 64000000; ++ } else if (baud == 3000000){ ++ m = 48; ++ n = 100; ++ ++ p->uartclk = 48000000; ++ } else { ++ p->uartclk = 44236800; ++ } ++ ++ /* Reset the clock */ ++ reg = (m << LPSS_PRV_CLK_M_VAL_SHIFT) | (n << LPSS_PRV_CLK_N_VAL_SHIFT); ++ writel(reg, p->membase + LPSS_PRV_CLK); ++ reg |= LPSS_PRV_CLK_EN | LPSS_PRV_CLK_UPDATE; ++ writel(reg, p->membase + LPSS_PRV_CLK); ++ ++ /* For BYT, hs-uart is capable of auto flow control */ ++ up->capabilities |= UART_CAP_AFE; ++ ++ /* ++ * If auto-handshake mechanism is not enabled, ++ * disable rts_n override ++ */ ++ reg = readl(p->membase + LPSS_HSUART_GENERAL_REG); ++ reg &= ~LPSS_GENERAL_DIS_RTS_N_OVERRIDE; ++ if (termios->c_cflag & CRTSCTS) ++ reg |= LPSS_GENERAL_DIS_RTS_N_OVERRIDE; ++ writel(reg, p->membase + LPSS_HSUART_GENERAL_REG); ++ ++ serial8250_do_set_termios(p, termios, old); ++} ++ ++static int ++lpss_serial_setup(struct serial_private *priv, ++ const struct pciserial_board *board, ++ struct uart_8250_port *port, int idx) ++{ ++ struct uart_8250_dma *dma; ++ int ret; ++ ++ dma = devm_kzalloc(port->port.dev, sizeof(*dma), GFP_KERNEL); ++ if (!dma) ++ return -ENOMEM; ++ ++ switch (priv->dev->device) { ++ case PCI_DEVICE_ID_INTEL_BYT_UART1: ++ dma->rx_chan_id = 3; ++ dma->rxconf.slave_id = dma->rx_chan_id; ++ dma->tx_chan_id = 2; ++ dma->txconf.slave_id = dma->tx_chan_id; ++ break; ++ case PCI_DEVICE_ID_INTEL_BYT_UART2: ++ dma->rx_chan_id = 5; ++ dma->rxconf.slave_id = dma->rx_chan_id; ++ dma->tx_chan_id = 4; ++ dma->txconf.slave_id = dma->tx_chan_id; ++ break; ++ case PCI_DEVICE_ID_INTEL_HSW_UART1: ++ dma->rx_chan_id = 5; ++ dma->rxconf.slave_id = 21; ++ dma->tx_chan_id = 4; ++ dma->txconf.slave_id = 20; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ dma->rxconf.direction = DMA_DEV_TO_MEM; ++ dma->rxconf.src_addr_width = 1; ++ dma->rxconf.src_maxburst = 16; ++ ++ dma->txconf.direction = DMA_MEM_TO_DEV; ++ dma->txconf.dst_addr_width = 1; ++ dma->rxconf.dst_maxburst = 16; ++ ++ dma->fn = lpss_dma_filter; ++ dma->rx_param = &dma->rx_chan_id; ++ dma->tx_param = &dma->tx_chan_id; ++ ++ ret = pci_default_setup(priv, board, port, idx); ++ port->port.iotype = UPIO_MEM; ++ port->port.type = PORT_16550A; ++ port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); ++ port->port.set_termios = lpss_set_termios; ++ port->port.fifosize = 64; ++ port->tx_loadsz = 64; ++ port->dma = dma; ++ port->port.dev->id = priv->dev->device; ++ ++ return ret; ++} ++ + static int + pci_omegapci_setup(struct serial_private *priv, + const struct pciserial_board *board, +@@ -1409,6 +1537,34 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { + .subdevice = PCI_ANY_ID, + .setup = kt_serial_setup, + }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_UART1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = lpss_serial_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_BYT_UART2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = lpss_serial_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_HSW_UART1, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = lpss_serial_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_HSW_UART2, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_default_setup, ++ }, + /* + * ITE + */ +@@ -2170,6 +2326,8 @@ enum pci_board_num_t { + pbn_ADDIDATA_PCIe_4_3906250, + pbn_ADDIDATA_PCIe_8_3906250, + pbn_ce4100_1_115200, ++ pbn_byt, ++ pbn_hsw, + pbn_omegapci, + pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, +@@ -2906,6 +3064,20 @@ static struct pciserial_board pci_boards[] = { + .base_baud = 921600, + .reg_shift = 2, + }, ++ [pbn_byt] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 2764800, ++ .uart_offset = 0x80, ++ .reg_shift = 2, ++ }, ++ [pbn_hsw] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 6250000, ++ .uart_offset = 0x80, ++ .reg_shift = 2, ++ }, + [pbn_omegapci] = { + .flags = FL_BASE0, + .num_ports = 8, +@@ -4493,6 +4665,24 @@ static struct pci_device_id serial_pci_tbl[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ce4100_1_115200 }, ++ /* Intel BYT */ ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, ++ pbn_byt }, ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2, ++ PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, ++ pbn_byt }, ++ /* Intel Haswell-ULT */ ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_UART1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, ++ pbn_hsw }, ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_UART2, ++ PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, ++ pbn_hsw }, + + /* + * Cronyx Omega PCI +diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig +index c31133a..2748125 100644 +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -84,6 +84,14 @@ config SERIAL_8250_GSC + depends on SERIAL_8250 && GSC + default SERIAL_8250 + ++config SERIAL_8250_DMA ++ bool "DMA support for 16550 compatible UART controllers" if EXPERT ++ depends on SERIAL_8250 && DMADEVICES=y ++ default SERIAL_8250 ++ help ++ This builds DMA support that can be used with 8250/16650 ++ compatible UART controllers that support DMA signaling. ++ + config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EXPERT + depends on SERIAL_8250 && PCI +@@ -265,7 +273,7 @@ config SERIAL_8250_FSL + + config SERIAL_8250_DW + tristate "Support for Synopsys DesignWare 8250 quirks" +- depends on SERIAL_8250 && OF ++ depends on SERIAL_8250 + help + Selecting this option will enable handling of the extra features + present in the Synopsys DesignWare APB UART. +diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile +index 108fe7f..a23838a 100644 +--- a/drivers/tty/serial/8250/Makefile ++++ b/drivers/tty/serial/8250/Makefile +@@ -5,6 +5,7 @@ + obj-$(CONFIG_SERIAL_8250) += 8250_core.o + 8250_core-y := 8250.o + 8250_core-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o ++8250_core-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o + obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o + obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o + obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o +diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h +index c490d20..af47a8a 100644 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -59,6 +59,8 @@ enum { + PLAT8250_DEV_SM501, + }; + ++struct uart_8250_dma; ++ + /* + * This should be used by drivers which want to register + * their own 8250 ports without registering their own +@@ -91,6 +93,8 @@ struct uart_8250_port { + #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA + unsigned char msr_saved_flags; + ++ struct uart_8250_dma *dma; ++ + /* 8250 specific callbacks */ + int (*dl_read)(struct uart_8250_port *); + void (*dl_write)(struct uart_8250_port *, int); +-- +1.7.10.4 + -- 1.7.10.4 _______________________________________________ linux-yocto mailing list [email protected] https://lists.yoctoproject.org/listinfo/linux-yocto
