提交 dc96efb7 编写于 作者: M Matt Schulte 提交者: Greg Kroah-Hartman

Serial: Add support for new devices: Exar's XR17V35x family of multi-port PCIe UARTs

Add support for new devices: Exar's XR17V35x family of multi-port PCIe UARTs.
Signed-off-by: NMatt Schulte <matts@commtech-fastcom.com>
Acked-by: NAlan Cox <alan@linux.intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 ae8d8a14
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -282,6 +282,15 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
},
[PORT_XR17V35X] = {
.name = "XR17V35X",
.fifo_size = 256,
.tx_loadsz = 256,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
UART_FCR_T_TRIG_11,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_LPC3220] = {
.name = "LPC3220",
.fifo_size = 64,
......@@ -455,6 +464,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
}
static int serial8250_default_handle_irq(struct uart_port *port);
static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p)
{
......@@ -574,6 +584,18 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
*/
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* register is accessible to each UART at the UART_EXAR_SLEEP
* offset but the UART channel may only write to the corresponding
* bit.
*/
if (p->port.type == PORT_XR17V35X) {
serial_out(p, UART_EXAR_SLEEP, 0xff);
return;
}
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
......@@ -881,6 +903,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
/*
* XR17V35x UARTs have an extra divisor register, DLD
* that gets enabled with when DLAB is set which will
* cause the device to incorrectly match and assign
* port type to PORT_16650. The EFR for this UART is
* found at offset 0x09. Instead check the Deice ID (DVID)
* register for a 2, 4 or 8 port UART.
*/
status1 = serial_in(up, UART_EXAR_DVID);
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
if (up->port.flags & UPF_EXAR_EFR) {
DEBUG_AUTOCONF("Exar XR17V35x ");
up->port.type = PORT_XR17V35X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
}
/*
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
......@@ -1515,6 +1558,30 @@ static int serial8250_default_handle_irq(struct uart_port *port)
return serial8250_handle_irq(port, iir);
}
/*
* These Exar UARTs have an extra interrupt indicator that could
* fire for a few unimplemented interrupts. One of which is a
* wakeup event when coming out of sleep. Put this here just
* to be on the safe side that these interrupts don't go unhandled.
*/
static int exar_handle_irq(struct uart_port *port)
{
unsigned char int0, int1, int2, int3;
unsigned int iir = serial_port_in(port, UART_IIR);
int ret;
ret = serial8250_handle_irq(port, iir);
if (port->type == PORT_XR17V35X) {
int0 = serial_port_in(port, 0x80);
int1 = serial_port_in(port, 0x81);
int2 = serial_port_in(port, 0x82);
int3 = serial_port_in(port, 0x83);
}
return ret;
}
/*
* This is the serial driver's interrupt routine.
*
......@@ -2614,6 +2681,10 @@ static void serial8250_config_port(struct uart_port *port, int flags)
serial8250_release_rsa_resource(up);
if (port->type == PORT_UNKNOWN)
serial8250_release_std_resource(up);
/* Fixme: probably not the best place for this */
if (port->type == PORT_XR17V35X)
port->handle_irq = exar_handle_irq;
}
static int
......
......@@ -1164,6 +1164,39 @@ pci_xr17c154_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx);
}
static int
pci_xr17v35x_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
u8 __iomem *p;
p = pci_ioremap_bar(priv->dev, 0);
port->port.flags |= UPF_EXAR_EFR;
/*
* Setup Multipurpose Input/Output pins.
*/
if (idx == 0) {
writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
}
iounmap(p);
return pci_default_setup(priv, board, port, idx);
}
static int
pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board,
......@@ -1622,6 +1655,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = pci_xr17c154_setup,
},
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V352,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V354,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V358,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
/*
* Xircom cards
*/
......@@ -1962,6 +2016,9 @@ enum pci_board_num_t {
pbn_exar_XR17C152,
pbn_exar_XR17C154,
pbn_exar_XR17C158,
pbn_exar_XR17V352,
pbn_exar_XR17V354,
pbn_exar_XR17V358,
pbn_exar_ibm_saturn,
pbn_pasemi_1682M,
pbn_ni8430_2,
......@@ -2580,6 +2637,30 @@ static struct pciserial_board pci_boards[] = {
.base_baud = 921600,
.uart_offset = 0x200,
},
[pbn_exar_XR17V352] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_XR17V354] = {
.flags = FL_BASE0,
.num_ports = 4,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_XR17V358] = {
.flags = FL_BASE0,
.num_ports = 8,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_ibm_saturn] = {
.flags = FL_BASE0,
.num_ports = 1,
......@@ -3826,6 +3907,21 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17C158 },
/*
* Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
*/
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V352 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V354 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V358 },
/*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
......
......@@ -1985,6 +1985,9 @@
#define PCI_DEVICE_ID_EXAR_XR17C152 0x0152
#define PCI_DEVICE_ID_EXAR_XR17C154 0x0154
#define PCI_DEVICE_ID_EXAR_XR17C158 0x0158
#define PCI_DEVICE_ID_EXAR_XR17V352 0x0352
#define PCI_DEVICE_ID_EXAR_XR17V354 0x0354
#define PCI_DEVICE_ID_EXAR_XR17V358 0x0358
#define PCI_VENDOR_ID_MICROGATE 0x13c0
#define PCI_DEVICE_ID_MICROGATE_USC 0x0010
......
......@@ -49,7 +49,8 @@
#define PORT_XR17D15X 21 /* Exar XR17D15x UART */
#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */
#define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */
#define PORT_MAX_8250 23 /* max port ID */
#define PORT_XR17V35X 24 /* Exar XR17V35x UARTs */
#define PORT_MAX_8250 24 /* max port ID */
/*
* ARM specific type numbers. These are not currently guaranteed
......
......@@ -367,5 +367,11 @@
#define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */
#define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */
/*
* These are definitions for the XR17V35X and XR17D15X
*/
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
#define UART_EXAR_DVID 0x8d /* Device identification */
#endif /* _LINUX_SERIAL_REG_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部