|
@@ -27,6 +27,7 @@
|
|
|
|
|
|
#include <linux/dmaengine.h>
|
|
|
#include <linux/platform_data/dma-dw.h>
|
|
|
+#include <linux/platform_data/dma-hsu.h>
|
|
|
|
|
|
#include "8250.h"
|
|
|
|
|
@@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#define INTEL_MID_UART_PS 0x30
|
|
|
+#define INTEL_MID_UART_MUL 0x34
|
|
|
+
|
|
|
+static void intel_mid_set_termios_50M(struct uart_port *p,
|
|
|
+ struct ktermios *termios,
|
|
|
+ struct ktermios *old)
|
|
|
+{
|
|
|
+ unsigned int baud = tty_termios_baud_rate(termios);
|
|
|
+ u32 ps, mul;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The uart clk is 50Mhz, and the baud rate come from:
|
|
|
+ * baud = 50M * MUL / (DIV * PS * DLAB)
|
|
|
+ *
|
|
|
+ * For those basic low baud rate we can get the direct
|
|
|
+ * scalar from 2746800, like 115200 = 2746800/24. For those
|
|
|
+ * higher baud rate, we handle them case by case, mainly by
|
|
|
+ * adjusting the MUL/PS registers, and DIV register is kept
|
|
|
+ * as default value 0x3d09 to make things simple.
|
|
|
+ */
|
|
|
+
|
|
|
+ ps = 0x10;
|
|
|
+
|
|
|
+ switch (baud) {
|
|
|
+ case 500000:
|
|
|
+ case 1000000:
|
|
|
+ case 1500000:
|
|
|
+ case 3000000:
|
|
|
+ mul = 0x3a98;
|
|
|
+ p->uartclk = 48000000;
|
|
|
+ break;
|
|
|
+ case 2000000:
|
|
|
+ case 4000000:
|
|
|
+ mul = 0x2710;
|
|
|
+ ps = 0x08;
|
|
|
+ p->uartclk = 64000000;
|
|
|
+ break;
|
|
|
+ case 2500000:
|
|
|
+ mul = 0x30d4;
|
|
|
+ p->uartclk = 40000000;
|
|
|
+ break;
|
|
|
+ case 3500000:
|
|
|
+ mul = 0x3345;
|
|
|
+ ps = 0x0c;
|
|
|
+ p->uartclk = 56000000;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ mul = 0x2400;
|
|
|
+ p->uartclk = 29491200;
|
|
|
+ }
|
|
|
+
|
|
|
+ writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
|
|
|
+ writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
|
|
|
+
|
|
|
+ serial8250_do_set_termios(p, termios, old);
|
|
|
+}
|
|
|
+
|
|
|
+static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
|
|
|
+{
|
|
|
+ struct hsu_dma_slave *s = param;
|
|
|
+
|
|
|
+ if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ chan->private = s;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static int intel_mid_serial_setup(struct serial_private *priv,
|
|
|
+ const struct pciserial_board *board,
|
|
|
+ struct uart_8250_port *port, int idx,
|
|
|
+ int index, struct pci_dev *dma_dev)
|
|
|
+{
|
|
|
+ struct device *dev = port->port.dev;
|
|
|
+ struct uart_8250_dma *dma;
|
|
|
+ struct hsu_dma_slave *tx_param, *rx_param;
|
|
|
+
|
|
|
+ dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
|
|
|
+ if (!dma)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
|
|
|
+ if (!tx_param)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
|
|
|
+ if (!rx_param)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ rx_param->chan_id = index * 2 + 1;
|
|
|
+ tx_param->chan_id = index * 2;
|
|
|
+
|
|
|
+ dma->rxconf.src_maxburst = 64;
|
|
|
+ dma->txconf.dst_maxburst = 64;
|
|
|
+
|
|
|
+ rx_param->dma_dev = &dma_dev->dev;
|
|
|
+ tx_param->dma_dev = &dma_dev->dev;
|
|
|
+
|
|
|
+ dma->fn = intel_mid_dma_filter;
|
|
|
+ dma->rx_param = rx_param;
|
|
|
+ dma->tx_param = tx_param;
|
|
|
+
|
|
|
+ port->port.type = PORT_16750;
|
|
|
+ port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
|
|
|
+ port->dma = dma;
|
|
|
+
|
|
|
+ return pci_default_setup(priv, board, port, idx);
|
|
|
+}
|
|
|
+
|
|
|
+#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b
|
|
|
+#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c
|
|
|
+#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d
|
|
|
+
|
|
|
+static int pnw_serial_setup(struct serial_private *priv,
|
|
|
+ const struct pciserial_board *board,
|
|
|
+ struct uart_8250_port *port, int idx)
|
|
|
+{
|
|
|
+ struct pci_dev *pdev = priv->dev;
|
|
|
+ struct pci_dev *dma_dev;
|
|
|
+ int index;
|
|
|
+
|
|
|
+ switch (pdev->device) {
|
|
|
+ case PCI_DEVICE_ID_INTEL_PNW_UART1:
|
|
|
+ index = 0;
|
|
|
+ break;
|
|
|
+ case PCI_DEVICE_ID_INTEL_PNW_UART2:
|
|
|
+ index = 1;
|
|
|
+ break;
|
|
|
+ case PCI_DEVICE_ID_INTEL_PNW_UART3:
|
|
|
+ index = 2;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
|
|
|
+
|
|
|
+ port->port.set_termios = intel_mid_set_termios_50M;
|
|
|
+
|
|
|
+ return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
pci_omegapci_setup(struct serial_private *priv,
|
|
|
const struct pciserial_board *board,
|
|
@@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|
|
.subdevice = PCI_ANY_ID,
|
|
|
.setup = byt_serial_setup,
|
|
|
},
|
|
|
+ {
|
|
|
+ .vendor = PCI_VENDOR_ID_INTEL,
|
|
|
+ .device = PCI_DEVICE_ID_INTEL_PNW_UART1,
|
|
|
+ .subvendor = PCI_ANY_ID,
|
|
|
+ .subdevice = PCI_ANY_ID,
|
|
|
+ .setup = pnw_serial_setup,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .vendor = PCI_VENDOR_ID_INTEL,
|
|
|
+ .device = PCI_DEVICE_ID_INTEL_PNW_UART2,
|
|
|
+ .subvendor = PCI_ANY_ID,
|
|
|
+ .subdevice = PCI_ANY_ID,
|
|
|
+ .setup = pnw_serial_setup,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .vendor = PCI_VENDOR_ID_INTEL,
|
|
|
+ .device = PCI_DEVICE_ID_INTEL_PNW_UART3,
|
|
|
+ .subvendor = PCI_ANY_ID,
|
|
|
+ .subdevice = PCI_ANY_ID,
|
|
|
+ .setup = pnw_serial_setup,
|
|
|
+ },
|
|
|
{
|
|
|
.vendor = PCI_VENDOR_ID_INTEL,
|
|
|
.device = PCI_DEVICE_ID_INTEL_QRK_UART,
|
|
@@ -2878,6 +3042,7 @@ enum pci_board_num_t {
|
|
|
pbn_ADDIDATA_PCIe_8_3906250,
|
|
|
pbn_ce4100_1_115200,
|
|
|
pbn_byt,
|
|
|
+ pbn_pnw,
|
|
|
pbn_qrk,
|
|
|
pbn_omegapci,
|
|
|
pbn_NETMOS9900_2s_115200,
|
|
@@ -3644,6 +3809,11 @@ static struct pciserial_board pci_boards[] = {
|
|
|
.uart_offset = 0x80,
|
|
|
.reg_shift = 2,
|
|
|
},
|
|
|
+ [pbn_pnw] = {
|
|
|
+ .flags = FL_BASE0,
|
|
|
+ .num_ports = 1,
|
|
|
+ .base_baud = 115200,
|
|
|
+ },
|
|
|
[pbn_qrk] = {
|
|
|
.flags = FL_BASE0,
|
|
|
.num_ports = 1,
|
|
@@ -5376,6 +5546,19 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|
|
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
|
|
|
pbn_byt },
|
|
|
|
|
|
+ /*
|
|
|
+ * Intel Penwell
|
|
|
+ */
|
|
|
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
|
+ pbn_pnw},
|
|
|
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
|
+ pbn_pnw},
|
|
|
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
|
+ pbn_pnw},
|
|
|
+
|
|
|
/*
|
|
|
* Intel Quark x1000
|
|
|
*/
|