Commit b15e5691 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman

serial: 8250_pci: add support for Intel BayTrail

Intel BayTrail has two HS-UARTs with 64 byte fifo, support
for DMA and support for 16750 compatible Auto Flow Control.
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3415097f
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment