|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/2] ns16550: add Exar dual PCIe UART card support
Besides standard UART setup, this device needs enabling
(vendor-specific) "Enhanced Control Bits" - otherwise disabling hardware
control flow (MCR[2]) is ignored. Add appropriate quirk to the
ns16550_setup_preirq(), similar to the handle_dw_usr_busy_quirk(). The
new function act on Exar cards only (based on vendor ID).
Additionally, Exar card supports fractional divisor (DLD[3:0] register,
at 0x10). This part is not supported here yet, and seems to not
be required for working 115200bps at the very least.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
---
xen/drivers/char/ns16550.c | 39 +++++++++++++++++++++++++++++++++++--
xen/include/xen/8250-uart.h | 4 ++++
xen/include/xen/pci_ids.h | 2 ++
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 97b85b0225cc..540124b198df 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -88,6 +88,7 @@ struct ns16550_config {
param_pericom_2port,
param_pericom_4port,
param_pericom_8port,
+ param_exar_xr17v3521,
} param;
};
@@ -169,6 +170,21 @@ static void handle_dw_usr_busy_quirk(struct ns16550 *uart)
}
}
+static void enable_exar_enhanced_bits(struct ns16550 *uart)
+{
+#ifdef NS16550_PCI
+ if ( uart->bar &&
+ pci_conf_read16(PCI_SBDF(0, uart->ps_bdf[0], uart->ps_bdf[2],
+ uart->ps_bdf[2]), PCI_VENDOR_ID) ==
PCI_VENDOR_ID_EXAR )
+ {
+ /* Exar cards ignores setting MCR[2] (hardware flow control) unless
+ * "Enhanced control bits" is enabled.
+ */
+ ns_write_reg(uart, UART_XR_EFR, UART_EFR_ECB);
+ }
+#endif
+}
+
static void ns16550_interrupt(
int irq, void *dev_id, struct cpu_user_regs *regs)
{
@@ -303,6 +319,9 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
/* Handle the DesignWare 8250 'busy-detect' quirk. */
handle_dw_usr_busy_quirk(uart);
+ /* Enable Exar "Enhanced function bits" */
+ enable_exar_enhanced_bits(uart);
+
/* Line control and baud-rate generator. */
ns_write_reg(uart, UART_LCR, lcr | UART_LCR_DLAB);
if ( uart->baud != BAUD_AUTO )
@@ -781,7 +800,17 @@ static const struct ns16550_config_param __initconst
uart_param[] = {
.lsr_mask = UART_LSR_THRE,
.bar0 = 1,
.max_ports = 8,
- }
+ },
+ [param_exar_xr17v3521] = {
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_width = 1,
+ .fifo_size = 256,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .mmio = 1,
+ .max_ports = 2,
+ },
};
static const struct ns16550_config __initconst uart_config[] =
@@ -1007,7 +1036,13 @@ static const struct ns16550_config __initconst
uart_config[] =
.vendor_id = PCI_VENDOR_ID_PERICOM,
.dev_id = 0x7958,
.param = param_pericom_8port
- }
+ },
+ /* Exar Corp. XR17V3521 Dual PCIe UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_EXAR,
+ .dev_id = 0x0352,
+ .param = param_exar_xr17v3521
+ },
};
static int __init
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index 5c3bac33221e..8c12fbbb3d5a 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -121,6 +121,10 @@
/* Frequency of external clock source. This definition assumes PC platform. */
#define UART_CLOCK_HZ 1843200
+/* Exar specific */
+#define UART_XR_EFR 0x09
+#define UART_EFR_ECB 0x10
+
/* Resume retry settings */
#define RESUME_DELAY MILLISECS(10)
#define RESUME_RETRIES 100
diff --git a/xen/include/xen/pci_ids.h b/xen/include/xen/pci_ids.h
index 7788ba9d2f34..e798477a7e23 100644
--- a/xen/include/xen/pci_ids.h
+++ b/xen/include/xen/pci_ids.h
@@ -4,6 +4,8 @@
#define PCI_VENDOR_ID_PERICOM 0x12d8
+#define PCI_VENDOR_ID_EXAR 0x13a8
+
#define PCI_VENDOR_ID_OXSEMI 0x1415
#define PCI_VENDOR_ID_BROADCOM 0x14e4
--
2.31.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |