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: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
3415097ff0
commit
b15e5691cc
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user