[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 |