forked from QubesOS/qubes-vmm-xen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch-0003-ns16550-add-Exar-PCIe-UART-cards-support.patch
197 lines (180 loc) · 6.1 KB
/
patch-0003-ns16550-add-Exar-PCIe-UART-cards-support.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
From 5ffd37db2ff6fecfaee5bb2ebdaaff1cfb54b1a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
Date: Fri, 20 Aug 2021 12:29:45 +0200
Subject: [PATCH 3/3] ns16550: add Exar PCIe UART cards 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 2-, 4-, and 8- port cards only. I have tested
the functionality on 2-port card but based on the Linux driver, the same
applies to other models too.
Additionally, Exar card supports fractional divisor (DLD[3:0] register,
at 0x02). This part is not supported here yet, and seems to not
be required for working 115200bps at the very least.
The specification for the 2-port card is available at:
https://www.maxlinear.com/product/interface/uarts/pcie-uarts/xr17v352
Signed-off-by: Marek Marczykowski-Górecki <[email protected]>
Reviewed-by: Jan Beulich <[email protected]>
---
xen/drivers/char/ns16550.c | 83 ++++++++++++++++++++++++++++++++++++-
xen/include/xen/8250-uart.h | 4 ++
xen/include/xen/pci_ids.h | 2 +
3 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 20da8fd3b421..b777c8711ee0 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -88,6 +88,9 @@ struct ns16550_config {
param_pericom_2port,
param_pericom_4port,
param_pericom_8port,
+ param_exar_xr17v352,
+ param_exar_xr17v354,
+ param_exar_xr17v358,
} param;
};
@@ -104,6 +107,8 @@ struct ns16550_config_param {
unsigned int uart_offset;
unsigned int first_offset;
};
+
+static void enable_exar_enhanced_bits(const struct ns16550 *uart);
/*
* Create lookup tables for specific devices. It is assumed that if
@@ -237,7 +247,37 @@ static const struct ns16550_config_param __initconst uart_param[] = {
.lsr_mask = UART_LSR_THRE,
.bar0 = 1,
.max_ports = 8,
- }
+ },
+ [param_exar_xr17v352] = {
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_width = 1,
+ .fifo_size = 256,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .mmio = 1,
+ .max_ports = 2,
+ },
+ [param_exar_xr17v354] = {
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_width = 1,
+ .fifo_size = 256,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .mmio = 1,
+ .max_ports = 4,
+ },
+ [param_exar_xr17v358] = {
+ .base_baud = 7812500,
+ .uart_offset = 0x400,
+ .reg_width = 1,
+ .fifo_size = 256,
+ .lsr_mask = UART_LSR_THRE,
+ .bar0 = 1,
+ .mmio = 1,
+ .max_ports = 8,
+ },
};
static const struct ns16550_config __initconst uart_config[] =
{
@@ -462,7 +502,25 @@ static const struct ns16550_config __initconst uart_config[] =
.vendor_id = PCI_VENDOR_ID_PERICOM,
.dev_id = 0x7958,
.param = param_pericom_8port
- }
+ },
+ /* Exar Corp. XR17V352 Dual PCIe UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_EXAR,
+ .dev_id = 0x0352,
+ .param = param_exar_xr17v352
+ },
+ /* Exar Corp. XR17V354 Quad PCIe UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_EXAR,
+ .dev_id = 0x0354,
+ .param = param_exar_xr17v354
+ },
+ /* Exar Corp. XR17V358 Octal PCIe UART */
+ {
+ .vendor_id = PCI_VENDOR_ID_EXAR,
+ .dev_id = 0x0358,
+ .param = param_exar_xr17v358
+ },
};
#endif
@@ -663,6 +668,11 @@ static void ns16550_setup_preirq(struct ns16550 *uart)
/* Handle the DesignWare 8250 'busy-detect' quirk. */
handle_dw_usr_busy_quirk(uart);
+#ifdef CONFIG_HAS_PCI
+ /* Enable Exar "Enhanced function bits" */
+ enable_exar_enhanced_bits(uart);
+#endif
+
/* Line control and baud-rate generator. */
ns_write_reg(uart, UART_LCR, lcr | UART_LCR_DLAB);
if ( uart->baud != BAUD_AUTO )
@@ -1222,6 +1279,28 @@ pci_uart_config(struct ns16550 *uart, bool_t skip_amt, unsigned int idx)
return 0;
}
+
+static void enable_exar_enhanced_bits(const struct ns16550 *uart)
+{
+ uint8_t efr;
+
+ switch ( uart->param - uart_param )
+ {
+ case param_exar_xr17v352:
+ case param_exar_xr17v354:
+ case param_exar_xr17v358:
+ /*
+ * Exar XR17V35x cards ignore setting MCR[2] (hardware flow control)
+ * unless "Enhanced control bits" is enabled.
+ * The below checks for a 2, 4 or 8 port UART, following Linux driver.
+ */
+ efr = ns_read_reg(uart, UART_XR_EFR);
+ efr |= UART_EFR_ECB;
+ ns_write_reg(uart, UART_XR_EFR, efr);
+ break;
+ }
+}
+
#endif
/*
diff --git a/xen/include/xen/8250-uart.h b/xen/include/xen/8250-uart.h
index 5c3bac33221e..d13352940c13 100644
--- a/xen/include/xen/8250-uart.h
+++ b/xen/include/xen/8250-uart.h
@@ -35,6 +35,7 @@
#define UART_USR 0x1f /* Status register (DW) */
#define UART_DLL 0x00 /* divisor latch (ls) (DLAB=1) */
#define UART_DLM 0x01 /* divisor latch (ms) (DLAB=1) */
+#define UART_XR_EFR 0x09 /* Enhanced function register (Exar) */
/* Interrupt Enable Register */
#define UART_IER_ERDAI 0x01 /* rx data recv'd */
@@ -121,6 +122,9 @@
/* Frequency of external clock source. This definition assumes PC platform. */
#define UART_CLOCK_HZ 1843200
+/* Bits in Exar specific UART_XR_EFR register */
+#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