summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250/8250_lpss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250/8250_lpss.c')
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 4dee8a9e0c95..776ec1ef29d6 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -70,7 +70,7 @@ static inline struct lpss8250 *to_lpss8250(struct dw8250_port_data *data)
}
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
- struct ktermios *old)
+ const struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct lpss8250 *lpss = to_lpss8250(p->private_data);
@@ -100,11 +100,7 @@ static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
- p->status &= ~UPSTAT_AUTOCTS;
- if (termios->c_cflag & CRTSCTS)
- p->status |= UPSTAT_AUTOCTS;
-
- serial8250_do_set_termios(p, termios, old);
+ dw8250_do_set_termios(p, termios, old);
}
static unsigned int byt_get_mctrl(struct uart_port *port)
@@ -121,8 +117,7 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
struct dw_dma_slave *param = &lpss->dma_param;
struct pci_dev *pdev = to_pci_dev(port->dev);
- unsigned int dma_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- struct pci_dev *dma_dev = pci_get_slot(pdev->bus, dma_devfn);
+ struct pci_dev *dma_dev;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_BYT_UART1:
@@ -141,6 +136,8 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return -EINVAL;
}
+ dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
+
param->dma_dev = &dma_dev->dev;
param->m_master = 0;
param->p_master = 1;
@@ -156,11 +153,41 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
return 0;
}
+static void byt_serial_exit(struct lpss8250 *lpss)
+{
+ struct dw_dma_slave *param = &lpss->dma_param;
+
+ /* Paired with pci_get_slot() in the byt_serial_setup() above */
+ put_device(param->dma_dev);
+}
+
static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
{
+ struct uart_8250_dma *dma = &lpss->data.dma;
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ /*
+ * This simply makes the checks in the 8250_port to try the DMA
+ * channel request which in turn uses the magic of ACPI tables
+ * parsing (see drivers/dma/acpi-dma.c for the details) and
+ * matching with the registered General Purpose DMA controllers.
+ */
+ up->dma = dma;
+
+ lpss->dma_maxburst = 16;
+
+ port->set_termios = dw8250_do_set_termios;
+
return 0;
}
+static void ehl_serial_exit(struct lpss8250 *lpss)
+{
+ struct uart_8250_port *up = serial8250_get_port(lpss->data.line);
+
+ up->dma = NULL;
+}
+
#ifdef CONFIG_SERIAL_8250_DMA
static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
.nr_channels = 2,
@@ -252,28 +279,32 @@ static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port
struct dw_dma_slave *rx_param, *tx_param;
struct device *dev = port->port.dev;
- if (!lpss->dma_param.dma_dev)
+ if (!lpss->dma_param.dma_dev) {
+ dma = port->dma;
+ if (dma)
+ goto out_configuration_only;
+
return 0;
+ }
- rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+ rx_param = devm_kmemdup(dev, &lpss->dma_param, sizeof(*rx_param), GFP_KERNEL);
if (!rx_param)
return -ENOMEM;
- tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+ tx_param = devm_kmemdup(dev, &lpss->dma_param, sizeof(*tx_param), GFP_KERNEL);
if (!tx_param)
return -ENOMEM;
- *rx_param = lpss->dma_param;
- dma->rxconf.src_maxburst = lpss->dma_maxburst;
-
- *tx_param = lpss->dma_param;
- dma->txconf.dst_maxburst = lpss->dma_maxburst;
-
dma->fn = lpss8250_dma_filter;
dma->rx_param = rx_param;
dma->tx_param = tx_param;
port->dma = dma;
+
+out_configuration_only:
+ dma->rxconf.src_maxburst = lpss->dma_maxburst;
+ dma->txconf.dst_maxburst = lpss->dma_maxburst;
+
return 0;
}
@@ -305,7 +336,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
uart.port.irq = pci_irq_vector(pdev, 0);
uart.port.private_data = &lpss->data;
uart.port.type = PORT_16550A;
- uart.port.iotype = UPIO_MEM;
+ uart.port.iotype = UPIO_MEM32;
uart.port.regshift = 2;
uart.port.uartclk = lpss->board->base_baud * 16;
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
@@ -335,8 +366,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
err_exit:
- if (lpss->board->exit)
- lpss->board->exit(lpss);
+ lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
return ret;
}
@@ -347,8 +377,7 @@ static void lpss8250_remove(struct pci_dev *pdev)
serial8250_unregister_port(lpss->data.line);
- if (lpss->board->exit)
- lpss->board->exit(lpss);
+ lpss->board->exit(lpss);
pci_free_irq_vectors(pdev);
}
@@ -356,12 +385,14 @@ static const struct lpss8250_board byt_board = {
.freq = 100000000,
.base_baud = 2764800,
.setup = byt_serial_setup,
+ .exit = byt_serial_exit,
};
static const struct lpss8250_board ehl_board = {
.freq = 200000000,
.base_baud = 12500000,
.setup = ehl_serial_setup,
+ .exit = ehl_serial_exit,
};
static const struct lpss8250_board qrk_board = {