|
@@ -1324,6 +1324,120 @@ ce4100_serial_setup(struct serial_private *priv,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#define PCI_DEVICE_ID_INTEL_BYT_UART1 0x0f0a
|
|
|
+#define PCI_DEVICE_ID_INTEL_BYT_UART2 0x0f0c
|
|
|
+
|
|
|
+#define BYT_PRV_CLK 0x800
|
|
|
+#define BYT_PRV_CLK_EN (1 << 0)
|
|
|
+#define BYT_PRV_CLK_M_VAL_SHIFT 1
|
|
|
+#define BYT_PRV_CLK_N_VAL_SHIFT 16
|
|
|
+#define BYT_PRV_CLK_UPDATE (1 << 31)
|
|
|
+
|
|
|
+#define BYT_GENERAL_REG 0x808
|
|
|
+#define BYT_GENERAL_DIS_RTS_N_OVERRIDE (1 << 3)
|
|
|
+
|
|
|
+#define BYT_TX_OVF_INT 0x820
|
|
|
+#define BYT_TX_OVF_INT_MASK (1 << 1)
|
|
|
+
|
|
|
+static void
|
|
|
+byt_set_termios(struct uart_port *p, struct ktermios *termios,
|
|
|
+ struct ktermios *old)
|
|
|
+{
|
|
|
+ unsigned int baud = tty_termios_baud_rate(termios);
|
|
|
+ unsigned int m = 6912;
|
|
|
+ unsigned int n = 15625;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ /* For baud rates 1M, 2M, 3M and 4M 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 << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
|
|
|
+ writel(reg, p->membase + BYT_PRV_CLK);
|
|
|
+ reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
|
|
|
+ writel(reg, p->membase + BYT_PRV_CLK);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If auto-handshake mechanism is not enabled,
|
|
|
+ * disable rts_n override
|
|
|
+ */
|
|
|
+ reg = readl(p->membase + BYT_GENERAL_REG);
|
|
|
+ reg &= ~BYT_GENERAL_DIS_RTS_N_OVERRIDE;
|
|
|
+ if (termios->c_cflag & CRTSCTS)
|
|
|
+ reg |= BYT_GENERAL_DIS_RTS_N_OVERRIDE;
|
|
|
+ writel(reg, p->membase + BYT_GENERAL_REG);
|
|
|
+
|
|
|
+ serial8250_do_set_termios(p, termios, old);
|
|
|
+}
|
|
|
+
|
|
|
+static bool byt_dma_filter(struct dma_chan *chan, void *param)
|
|
|
+{
|
|
|
+ return chan->chan_id == *(int *)param;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+byt_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->tx_chan_id = 2;
|
|
|
+ break;
|
|
|
+ case PCI_DEVICE_ID_INTEL_BYT_UART2:
|
|
|
+ dma->rx_chan_id = 5;
|
|
|
+ dma->tx_chan_id = 4;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ dma->rxconf.slave_id = dma->rx_chan_id;
|
|
|
+ dma->rxconf.src_maxburst = 16;
|
|
|
+
|
|
|
+ dma->txconf.slave_id = dma->tx_chan_id;
|
|
|
+ dma->txconf.dst_maxburst = 16;
|
|
|
+
|
|
|
+ dma->fn = byt_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 = byt_set_termios;
|
|
|
+ port->port.fifosize = 64;
|
|
|
+ port->tx_loadsz = 64;
|
|
|
+ port->dma = dma;
|
|
|
+ port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
|
|
|
+
|
|
|
+ /* Disable Tx counter interrupts */
|
|
|
+ writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
pci_omegapci_setup(struct serial_private *priv,
|
|
|
const struct pciserial_board *board,
|
|
@@ -1662,6 +1776,20 @@ 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 = byt_serial_setup,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .vendor = PCI_VENDOR_ID_INTEL,
|
|
|
+ .device = PCI_DEVICE_ID_INTEL_BYT_UART2,
|
|
|
+ .subvendor = PCI_ANY_ID,
|
|
|
+ .subdevice = PCI_ANY_ID,
|
|
|
+ .setup = byt_serial_setup,
|
|
|
+ },
|
|
|
/*
|
|
|
* ITE
|
|
|
*/
|
|
@@ -2449,6 +2577,7 @@ enum pci_board_num_t {
|
|
|
pbn_ADDIDATA_PCIe_4_3906250,
|
|
|
pbn_ADDIDATA_PCIe_8_3906250,
|
|
|
pbn_ce4100_1_115200,
|
|
|
+ pbn_byt,
|
|
|
pbn_omegapci,
|
|
|
pbn_NETMOS9900_2s_115200,
|
|
|
pbn_brcm_trumanage,
|
|
@@ -3185,6 +3314,13 @@ 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_omegapci] = {
|
|
|
.flags = FL_BASE0,
|
|
|
.num_ports = 8,
|
|
@@ -4846,6 +4982,15 @@ 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 BayTrail */
|
|
|
+ { 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 },
|
|
|
|
|
|
/*
|
|
|
* Cronyx Omega PCI
|