1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Probe module for 8250/16550-type Exar chips PCI serial ports. |
4 | * |
5 | * Based on drivers/tty/serial/8250/8250_pci.c, |
6 | * |
7 | * Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved. |
8 | */ |
9 | #include <linux/bits.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/device.h> |
12 | #include <linux/dmi.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> |
15 | #include <linux/math.h> |
16 | #include <linux/module.h> |
17 | #include <linux/pci.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/pm.h> |
20 | #include <linux/property.h> |
21 | #include <linux/string.h> |
22 | #include <linux/types.h> |
23 | |
24 | #include <linux/serial_8250.h> |
25 | #include <linux/serial_core.h> |
26 | #include <linux/serial_reg.h> |
27 | |
28 | #include <asm/byteorder.h> |
29 | |
30 | #include "8250.h" |
31 | #include "8250_pcilib.h" |
32 | |
33 | #define PCI_DEVICE_ID_ACCESSIO_COM_2S 0x1052 |
34 | #define PCI_DEVICE_ID_ACCESSIO_COM_4S 0x105d |
35 | #define PCI_DEVICE_ID_ACCESSIO_COM_8S 0x106c |
36 | #define PCI_DEVICE_ID_ACCESSIO_COM232_8 0x10a8 |
37 | #define PCI_DEVICE_ID_ACCESSIO_COM_2SM 0x10d2 |
38 | #define PCI_DEVICE_ID_ACCESSIO_COM_4SM 0x10db |
39 | #define PCI_DEVICE_ID_ACCESSIO_COM_8SM 0x10ea |
40 | |
41 | #define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002 |
42 | #define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 |
43 | #define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a |
44 | #define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b |
45 | #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 |
46 | #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 |
47 | #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 |
48 | |
49 | #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 |
50 | #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 |
51 | |
52 | #define PCI_SUBDEVICE_ID_USR_2980 0x0128 |
53 | #define PCI_SUBDEVICE_ID_USR_2981 0x0129 |
54 | |
55 | #define UART_EXAR_INT0 0x80 |
56 | #define UART_EXAR_8XMODE 0x88 /* 8X sampling rate select */ |
57 | #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ |
58 | #define UART_EXAR_DVID 0x8d /* Device identification */ |
59 | |
60 | #define UART_EXAR_FCTR 0x08 /* Feature Control Register */ |
61 | #define UART_FCTR_EXAR_IRDA 0x10 /* IrDa data encode select */ |
62 | #define UART_FCTR_EXAR_485 0x20 /* Auto 485 half duplex dir ctl */ |
63 | #define UART_FCTR_EXAR_TRGA 0x00 /* FIFO trigger table A */ |
64 | #define UART_FCTR_EXAR_TRGB 0x60 /* FIFO trigger table B */ |
65 | #define UART_FCTR_EXAR_TRGC 0x80 /* FIFO trigger table C */ |
66 | #define UART_FCTR_EXAR_TRGD 0xc0 /* FIFO trigger table D programmable */ |
67 | |
68 | #define UART_EXAR_TXTRG 0x0a /* Tx FIFO trigger level write-only */ |
69 | #define UART_EXAR_RXTRG 0x0b /* Rx FIFO trigger level write-only */ |
70 | |
71 | #define UART_EXAR_MPIOINT_7_0 0x8f /* MPIOINT[7:0] */ |
72 | #define UART_EXAR_MPIOLVL_7_0 0x90 /* MPIOLVL[7:0] */ |
73 | #define UART_EXAR_MPIO3T_7_0 0x91 /* MPIO3T[7:0] */ |
74 | #define UART_EXAR_MPIOINV_7_0 0x92 /* MPIOINV[7:0] */ |
75 | #define UART_EXAR_MPIOSEL_7_0 0x93 /* MPIOSEL[7:0] */ |
76 | #define UART_EXAR_MPIOOD_7_0 0x94 /* MPIOOD[7:0] */ |
77 | #define UART_EXAR_MPIOINT_15_8 0x95 /* MPIOINT[15:8] */ |
78 | #define UART_EXAR_MPIOLVL_15_8 0x96 /* MPIOLVL[15:8] */ |
79 | #define UART_EXAR_MPIO3T_15_8 0x97 /* MPIO3T[15:8] */ |
80 | #define UART_EXAR_MPIOINV_15_8 0x98 /* MPIOINV[15:8] */ |
81 | #define UART_EXAR_MPIOSEL_15_8 0x99 /* MPIOSEL[15:8] */ |
82 | #define UART_EXAR_MPIOOD_15_8 0x9a /* MPIOOD[15:8] */ |
83 | |
84 | #define UART_EXAR_RS485_DLY(x) ((x) << 4) |
85 | |
86 | #define UART_EXAR_DLD 0x02 /* Divisor Fractional */ |
87 | #define UART_EXAR_DLD_485_POLARITY 0x80 /* RS-485 Enable Signal Polarity */ |
88 | |
89 | /* |
90 | * IOT2040 MPIO wiring semantics: |
91 | * |
92 | * MPIO Port Function |
93 | * ---- ---- -------- |
94 | * 0 2 Mode bit 0 |
95 | * 1 2 Mode bit 1 |
96 | * 2 2 Terminate bus |
97 | * 3 - <reserved> |
98 | * 4 3 Mode bit 0 |
99 | * 5 3 Mode bit 1 |
100 | * 6 3 Terminate bus |
101 | * 7 - <reserved> |
102 | * 8 2 Enable |
103 | * 9 3 Enable |
104 | * 10 - Red LED |
105 | * 11..15 - <unused> |
106 | */ |
107 | |
108 | /* IOT2040 MPIOs 0..7 */ |
109 | #define IOT2040_UART_MODE_RS232 0x01 |
110 | #define IOT2040_UART_MODE_RS485 0x02 |
111 | #define IOT2040_UART_MODE_RS422 0x03 |
112 | #define IOT2040_UART_TERMINATE_BUS 0x04 |
113 | |
114 | #define IOT2040_UART1_MASK 0x0f |
115 | #define IOT2040_UART2_SHIFT 4 |
116 | |
117 | #define IOT2040_UARTS_DEFAULT_MODE 0x11 /* both RS232 */ |
118 | #define IOT2040_UARTS_GPIO_LO_MODE 0x88 /* reserved pins as input */ |
119 | |
120 | /* IOT2040 MPIOs 8..15 */ |
121 | #define IOT2040_UARTS_ENABLE 0x03 |
122 | #define IOT2040_UARTS_GPIO_HI_MODE 0xF8 /* enable & LED as outputs */ |
123 | |
124 | struct exar8250; |
125 | |
126 | struct exar8250_platform { |
127 | int (*rs485_config)(struct uart_port *port, struct ktermios *termios, |
128 | struct serial_rs485 *rs485); |
129 | const struct serial_rs485 *rs485_supported; |
130 | int (*register_gpio)(struct pci_dev *, struct uart_8250_port *); |
131 | void (*unregister_gpio)(struct uart_8250_port *); |
132 | }; |
133 | |
134 | /** |
135 | * struct exar8250_board - board information |
136 | * @num_ports: number of serial ports |
137 | * @reg_shift: describes UART register mapping in PCI memory |
138 | * @setup: quirk run at ->probe() stage |
139 | * @exit: quirk run at ->remove() stage |
140 | */ |
141 | struct exar8250_board { |
142 | unsigned int num_ports; |
143 | unsigned int reg_shift; |
144 | int (*setup)(struct exar8250 *, struct pci_dev *, |
145 | struct uart_8250_port *, int); |
146 | void (*exit)(struct pci_dev *pcidev); |
147 | }; |
148 | |
149 | struct exar8250 { |
150 | unsigned int nr; |
151 | struct exar8250_board *board; |
152 | void __iomem *virt; |
153 | int line[]; |
154 | }; |
155 | |
156 | static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old) |
157 | { |
158 | /* |
159 | * Exar UARTs have a SLEEP register that enables or disables each UART |
160 | * to enter sleep mode separately. On the XR17V35x the register |
161 | * is accessible to each UART at the UART_EXAR_SLEEP offset, but |
162 | * the UART channel may only write to the corresponding bit. |
163 | */ |
164 | serial_port_out(up: port, UART_EXAR_SLEEP, value: state ? 0xff : 0); |
165 | } |
166 | |
167 | /* |
168 | * XR17V35x UARTs have an extra fractional divisor register (DLD) |
169 | * Calculate divisor with extra 4-bit fractional portion |
170 | */ |
171 | static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud, |
172 | unsigned int *frac) |
173 | { |
174 | unsigned int quot_16; |
175 | |
176 | quot_16 = DIV_ROUND_CLOSEST(p->uartclk, baud); |
177 | *frac = quot_16 & 0x0f; |
178 | |
179 | return quot_16 >> 4; |
180 | } |
181 | |
182 | static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud, |
183 | unsigned int quot, unsigned int quot_frac) |
184 | { |
185 | serial8250_do_set_divisor(port: p, baud, quot, quot_frac); |
186 | |
187 | /* Preserve bits not related to baudrate; DLD[7:4]. */ |
188 | quot_frac |= serial_port_in(up: p, offset: 0x2) & 0xf0; |
189 | serial_port_out(up: p, offset: 0x2, value: quot_frac); |
190 | } |
191 | |
192 | static int xr17v35x_startup(struct uart_port *port) |
193 | { |
194 | /* |
195 | * First enable access to IER [7:5], ISR [5:4], FCR [5:4], |
196 | * MCR [7:5] and MSR [7:0] |
197 | */ |
198 | serial_port_out(up: port, UART_XR_EFR, UART_EFR_ECB); |
199 | |
200 | /* |
201 | * Make sure all interrups are masked until initialization is |
202 | * complete and the FIFOs are cleared |
203 | * |
204 | * Synchronize UART_IER access against the console. |
205 | */ |
206 | uart_port_lock_irq(up: port); |
207 | serial_port_out(up: port, UART_IER, value: 0); |
208 | uart_port_unlock_irq(up: port); |
209 | |
210 | return serial8250_do_startup(port); |
211 | } |
212 | |
213 | static void exar_shutdown(struct uart_port *port) |
214 | { |
215 | bool tx_complete = false; |
216 | struct uart_8250_port *up = up_to_u8250p(up: port); |
217 | struct circ_buf *xmit = &port->state->xmit; |
218 | int i = 0; |
219 | u16 lsr; |
220 | |
221 | do { |
222 | lsr = serial_in(up, UART_LSR); |
223 | if (lsr & (UART_LSR_TEMT | UART_LSR_THRE)) |
224 | tx_complete = true; |
225 | else |
226 | tx_complete = false; |
227 | usleep_range(min: 1000, max: 1100); |
228 | } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000); |
229 | |
230 | serial8250_do_shutdown(port); |
231 | } |
232 | |
233 | static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, |
234 | int idx, unsigned int offset, |
235 | struct uart_8250_port *port) |
236 | { |
237 | const struct exar8250_board *board = priv->board; |
238 | unsigned char status; |
239 | int err; |
240 | |
241 | err = serial8250_pci_setup_port(dev: pcidev, port, bar: 0, offset, regshift: board->reg_shift); |
242 | if (err) |
243 | return err; |
244 | |
245 | /* |
246 | * XR17V35x UARTs have an extra divisor register, DLD that gets enabled |
247 | * with when DLAB is set which will cause the device to incorrectly match |
248 | * and assign port type to PORT_16650. The EFR for this UART is found |
249 | * at offset 0x09. Instead check the Deice ID (DVID) register |
250 | * for a 2, 4 or 8 port UART. |
251 | */ |
252 | status = readb(addr: port->port.membase + UART_EXAR_DVID); |
253 | if (status == 0x82 || status == 0x84 || status == 0x88) { |
254 | port->port.type = PORT_XR17V35X; |
255 | |
256 | port->port.get_divisor = xr17v35x_get_divisor; |
257 | port->port.set_divisor = xr17v35x_set_divisor; |
258 | |
259 | port->port.startup = xr17v35x_startup; |
260 | } else { |
261 | port->port.type = PORT_XR17D15X; |
262 | } |
263 | |
264 | port->port.pm = exar_pm; |
265 | port->port.shutdown = exar_shutdown; |
266 | |
267 | return 0; |
268 | } |
269 | |
270 | static int |
271 | pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev, |
272 | struct uart_8250_port *port, int idx) |
273 | { |
274 | unsigned int offset = idx * 0x200; |
275 | unsigned int baud = 1843200; |
276 | u8 __iomem *p; |
277 | int err; |
278 | |
279 | port->port.uartclk = baud * 16; |
280 | |
281 | err = default_setup(priv, pcidev, idx, offset, port); |
282 | if (err) |
283 | return err; |
284 | |
285 | p = port->port.membase; |
286 | |
287 | writeb(val: 0x00, addr: p + UART_EXAR_8XMODE); |
288 | writeb(UART_FCTR_EXAR_TRGD, addr: p + UART_EXAR_FCTR); |
289 | writeb(val: 32, addr: p + UART_EXAR_TXTRG); |
290 | writeb(val: 32, addr: p + UART_EXAR_RXTRG); |
291 | |
292 | /* |
293 | * Setup Multipurpose Input/Output pins. |
294 | */ |
295 | if (idx == 0) { |
296 | switch (pcidev->device) { |
297 | case PCI_DEVICE_ID_COMMTECH_4222PCI335: |
298 | case PCI_DEVICE_ID_COMMTECH_4224PCI335: |
299 | writeb(val: 0x78, addr: p + UART_EXAR_MPIOLVL_7_0); |
300 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINV_7_0); |
301 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOSEL_7_0); |
302 | break; |
303 | case PCI_DEVICE_ID_COMMTECH_2324PCI335: |
304 | case PCI_DEVICE_ID_COMMTECH_2328PCI335: |
305 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOLVL_7_0); |
306 | writeb(val: 0xc0, addr: p + UART_EXAR_MPIOINV_7_0); |
307 | writeb(val: 0xc0, addr: p + UART_EXAR_MPIOSEL_7_0); |
308 | break; |
309 | } |
310 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINT_7_0); |
311 | writeb(val: 0x00, addr: p + UART_EXAR_MPIO3T_7_0); |
312 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOOD_7_0); |
313 | } |
314 | |
315 | return 0; |
316 | } |
317 | |
318 | static int |
319 | pci_connect_tech_setup(struct exar8250 *priv, struct pci_dev *pcidev, |
320 | struct uart_8250_port *port, int idx) |
321 | { |
322 | unsigned int offset = idx * 0x200; |
323 | unsigned int baud = 1843200; |
324 | |
325 | port->port.uartclk = baud * 16; |
326 | return default_setup(priv, pcidev, idx, offset, port); |
327 | } |
328 | |
329 | static int |
330 | pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev, |
331 | struct uart_8250_port *port, int idx) |
332 | { |
333 | unsigned int offset = idx * 0x200; |
334 | unsigned int baud = 921600; |
335 | |
336 | port->port.uartclk = baud * 16; |
337 | return default_setup(priv, pcidev, idx, offset, port); |
338 | } |
339 | |
340 | static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p) |
341 | { |
342 | /* |
343 | * The Commtech adapters required the MPIOs to be driven low. The Exar |
344 | * devices will export them as GPIOs, so we pre-configure them safely |
345 | * as inputs. |
346 | */ |
347 | |
348 | u8 dir = 0x00; |
349 | |
350 | if ((pcidev->vendor == PCI_VENDOR_ID_EXAR) && |
351 | (pcidev->subsystem_vendor != PCI_VENDOR_ID_SEALEVEL)) { |
352 | // Configure GPIO as inputs for Commtech adapters |
353 | dir = 0xff; |
354 | } else { |
355 | // Configure GPIO as outputs for SeaLevel adapters |
356 | dir = 0x00; |
357 | } |
358 | |
359 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINT_7_0); |
360 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOLVL_7_0); |
361 | writeb(val: 0x00, addr: p + UART_EXAR_MPIO3T_7_0); |
362 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINV_7_0); |
363 | writeb(val: dir, addr: p + UART_EXAR_MPIOSEL_7_0); |
364 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOOD_7_0); |
365 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINT_15_8); |
366 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOLVL_15_8); |
367 | writeb(val: 0x00, addr: p + UART_EXAR_MPIO3T_15_8); |
368 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOINV_15_8); |
369 | writeb(val: dir, addr: p + UART_EXAR_MPIOSEL_15_8); |
370 | writeb(val: 0x00, addr: p + UART_EXAR_MPIOOD_15_8); |
371 | } |
372 | |
373 | static struct platform_device *__xr17v35x_register_gpio(struct pci_dev *pcidev, |
374 | const struct software_node *node) |
375 | { |
376 | struct platform_device *pdev; |
377 | |
378 | pdev = platform_device_alloc(name: "gpio_exar" , PLATFORM_DEVID_AUTO); |
379 | if (!pdev) |
380 | return NULL; |
381 | |
382 | pdev->dev.parent = &pcidev->dev; |
383 | device_set_node(dev: &pdev->dev, dev_fwnode(&pcidev->dev)); |
384 | |
385 | if (device_add_software_node(dev: &pdev->dev, node) < 0 || |
386 | platform_device_add(pdev) < 0) { |
387 | platform_device_put(pdev); |
388 | return NULL; |
389 | } |
390 | |
391 | return pdev; |
392 | } |
393 | |
394 | static void __xr17v35x_unregister_gpio(struct platform_device *pdev) |
395 | { |
396 | device_remove_software_node(dev: &pdev->dev); |
397 | platform_device_unregister(pdev); |
398 | } |
399 | |
400 | static const struct property_entry exar_gpio_properties[] = { |
401 | PROPERTY_ENTRY_U32("exar,first-pin" , 0), |
402 | PROPERTY_ENTRY_U32("ngpios" , 16), |
403 | { } |
404 | }; |
405 | |
406 | static const struct software_node exar_gpio_node = { |
407 | .properties = exar_gpio_properties, |
408 | }; |
409 | |
410 | static int xr17v35x_register_gpio(struct pci_dev *pcidev, struct uart_8250_port *port) |
411 | { |
412 | if (pcidev->vendor == PCI_VENDOR_ID_EXAR) |
413 | port->port.private_data = |
414 | __xr17v35x_register_gpio(pcidev, node: &exar_gpio_node); |
415 | |
416 | return 0; |
417 | } |
418 | |
419 | static void xr17v35x_unregister_gpio(struct uart_8250_port *port) |
420 | { |
421 | if (!port->port.private_data) |
422 | return; |
423 | |
424 | __xr17v35x_unregister_gpio(pdev: port->port.private_data); |
425 | port->port.private_data = NULL; |
426 | } |
427 | |
428 | static int generic_rs485_config(struct uart_port *port, struct ktermios *termios, |
429 | struct serial_rs485 *rs485) |
430 | { |
431 | bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); |
432 | u8 __iomem *p = port->membase; |
433 | u8 value; |
434 | |
435 | value = readb(addr: p + UART_EXAR_FCTR); |
436 | if (is_rs485) |
437 | value |= UART_FCTR_EXAR_485; |
438 | else |
439 | value &= ~UART_FCTR_EXAR_485; |
440 | |
441 | writeb(val: value, addr: p + UART_EXAR_FCTR); |
442 | |
443 | if (is_rs485) |
444 | writeb(UART_EXAR_RS485_DLY(4), addr: p + UART_MSR); |
445 | |
446 | return 0; |
447 | } |
448 | |
449 | static int sealevel_rs485_config(struct uart_port *port, struct ktermios *termios, |
450 | struct serial_rs485 *rs485) |
451 | { |
452 | u8 __iomem *p = port->membase; |
453 | u8 old_lcr; |
454 | u8 efr; |
455 | u8 dld; |
456 | int ret; |
457 | |
458 | ret = generic_rs485_config(port, termios, rs485); |
459 | if (ret) |
460 | return ret; |
461 | |
462 | if (rs485->flags & SER_RS485_ENABLED) { |
463 | old_lcr = readb(addr: p + UART_LCR); |
464 | |
465 | /* Set EFR[4]=1 to enable enhanced feature registers */ |
466 | efr = readb(addr: p + UART_XR_EFR); |
467 | efr |= UART_EFR_ECB; |
468 | writeb(val: efr, addr: p + UART_XR_EFR); |
469 | |
470 | /* Set MCR to use DTR as Auto-RS485 Enable signal */ |
471 | writeb(UART_MCR_OUT1, addr: p + UART_MCR); |
472 | |
473 | /* Set LCR[7]=1 to enable access to DLD register */ |
474 | writeb(val: old_lcr | UART_LCR_DLAB, addr: p + UART_LCR); |
475 | |
476 | /* Set DLD[7]=1 for inverted RS485 Enable logic */ |
477 | dld = readb(addr: p + UART_EXAR_DLD); |
478 | dld |= UART_EXAR_DLD_485_POLARITY; |
479 | writeb(val: dld, addr: p + UART_EXAR_DLD); |
480 | |
481 | writeb(val: old_lcr, addr: p + UART_LCR); |
482 | } |
483 | |
484 | return 0; |
485 | } |
486 | |
487 | static const struct serial_rs485 generic_rs485_supported = { |
488 | .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND, |
489 | }; |
490 | |
491 | static const struct exar8250_platform exar8250_default_platform = { |
492 | .register_gpio = xr17v35x_register_gpio, |
493 | .unregister_gpio = xr17v35x_unregister_gpio, |
494 | .rs485_config = generic_rs485_config, |
495 | .rs485_supported = &generic_rs485_supported, |
496 | }; |
497 | |
498 | static int iot2040_rs485_config(struct uart_port *port, struct ktermios *termios, |
499 | struct serial_rs485 *rs485) |
500 | { |
501 | bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); |
502 | u8 __iomem *p = port->membase; |
503 | u8 mask = IOT2040_UART1_MASK; |
504 | u8 mode, value; |
505 | |
506 | if (is_rs485) { |
507 | if (rs485->flags & SER_RS485_RX_DURING_TX) |
508 | mode = IOT2040_UART_MODE_RS422; |
509 | else |
510 | mode = IOT2040_UART_MODE_RS485; |
511 | |
512 | if (rs485->flags & SER_RS485_TERMINATE_BUS) |
513 | mode |= IOT2040_UART_TERMINATE_BUS; |
514 | } else { |
515 | mode = IOT2040_UART_MODE_RS232; |
516 | } |
517 | |
518 | if (port->line == 3) { |
519 | mask <<= IOT2040_UART2_SHIFT; |
520 | mode <<= IOT2040_UART2_SHIFT; |
521 | } |
522 | |
523 | value = readb(addr: p + UART_EXAR_MPIOLVL_7_0); |
524 | value &= ~mask; |
525 | value |= mode; |
526 | writeb(val: value, addr: p + UART_EXAR_MPIOLVL_7_0); |
527 | |
528 | return generic_rs485_config(port, termios, rs485); |
529 | } |
530 | |
531 | static const struct serial_rs485 iot2040_rs485_supported = { |
532 | .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | |
533 | SER_RS485_RX_DURING_TX | SER_RS485_TERMINATE_BUS, |
534 | }; |
535 | |
536 | static const struct property_entry iot2040_gpio_properties[] = { |
537 | PROPERTY_ENTRY_U32("exar,first-pin" , 10), |
538 | PROPERTY_ENTRY_U32("ngpios" , 1), |
539 | { } |
540 | }; |
541 | |
542 | static const struct software_node iot2040_gpio_node = { |
543 | .properties = iot2040_gpio_properties, |
544 | }; |
545 | |
546 | static int iot2040_register_gpio(struct pci_dev *pcidev, |
547 | struct uart_8250_port *port) |
548 | { |
549 | u8 __iomem *p = port->port.membase; |
550 | |
551 | writeb(IOT2040_UARTS_DEFAULT_MODE, addr: p + UART_EXAR_MPIOLVL_7_0); |
552 | writeb(IOT2040_UARTS_GPIO_LO_MODE, addr: p + UART_EXAR_MPIOSEL_7_0); |
553 | writeb(IOT2040_UARTS_ENABLE, addr: p + UART_EXAR_MPIOLVL_15_8); |
554 | writeb(IOT2040_UARTS_GPIO_HI_MODE, addr: p + UART_EXAR_MPIOSEL_15_8); |
555 | |
556 | port->port.private_data = |
557 | __xr17v35x_register_gpio(pcidev, node: &iot2040_gpio_node); |
558 | |
559 | return 0; |
560 | } |
561 | |
562 | static const struct exar8250_platform iot2040_platform = { |
563 | .rs485_config = iot2040_rs485_config, |
564 | .rs485_supported = &iot2040_rs485_supported, |
565 | .register_gpio = iot2040_register_gpio, |
566 | .unregister_gpio = xr17v35x_unregister_gpio, |
567 | }; |
568 | |
569 | /* |
570 | * For SIMATIC IOT2000, only IOT2040 and its variants have the Exar device, |
571 | * IOT2020 doesn't have. Therefore it is sufficient to match on the common |
572 | * board name after the device was found. |
573 | */ |
574 | static const struct dmi_system_id exar_platforms[] = { |
575 | { |
576 | .matches = { |
577 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000" ), |
578 | }, |
579 | .driver_data = (void *)&iot2040_platform, |
580 | }, |
581 | {} |
582 | }; |
583 | |
584 | static const struct exar8250_platform *exar_get_platform(void) |
585 | { |
586 | const struct dmi_system_id *dmi_match; |
587 | |
588 | dmi_match = dmi_first_match(list: exar_platforms); |
589 | if (dmi_match) |
590 | return dmi_match->driver_data; |
591 | |
592 | return &exar8250_default_platform; |
593 | } |
594 | |
595 | static int |
596 | pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev, |
597 | struct uart_8250_port *port, int idx) |
598 | { |
599 | const struct exar8250_platform *platform = exar_get_platform(); |
600 | unsigned int offset = idx * 0x400; |
601 | unsigned int baud = 7812500; |
602 | u8 __iomem *p; |
603 | int ret; |
604 | |
605 | port->port.uartclk = baud * 16; |
606 | port->port.rs485_config = platform->rs485_config; |
607 | port->port.rs485_supported = *(platform->rs485_supported); |
608 | |
609 | if (pcidev->subsystem_vendor == PCI_VENDOR_ID_SEALEVEL) |
610 | port->port.rs485_config = sealevel_rs485_config; |
611 | |
612 | /* |
613 | * Setup the UART clock for the devices on expansion slot to |
614 | * half the clock speed of the main chip (which is 125MHz) |
615 | */ |
616 | if (idx >= 8) |
617 | port->port.uartclk /= 2; |
618 | |
619 | ret = default_setup(priv, pcidev, idx, offset, port); |
620 | if (ret) |
621 | return ret; |
622 | |
623 | p = port->port.membase; |
624 | |
625 | writeb(val: 0x00, addr: p + UART_EXAR_8XMODE); |
626 | writeb(UART_FCTR_EXAR_TRGD, addr: p + UART_EXAR_FCTR); |
627 | writeb(val: 128, addr: p + UART_EXAR_TXTRG); |
628 | writeb(val: 128, addr: p + UART_EXAR_RXTRG); |
629 | |
630 | if (idx == 0) { |
631 | /* Setup Multipurpose Input/Output pins. */ |
632 | setup_gpio(pcidev, p); |
633 | |
634 | ret = platform->register_gpio(pcidev, port); |
635 | } |
636 | |
637 | return ret; |
638 | } |
639 | |
640 | static void pci_xr17v35x_exit(struct pci_dev *pcidev) |
641 | { |
642 | const struct exar8250_platform *platform = exar_get_platform(); |
643 | struct exar8250 *priv = pci_get_drvdata(pdev: pcidev); |
644 | struct uart_8250_port *port = serial8250_get_port(line: priv->line[0]); |
645 | |
646 | platform->unregister_gpio(port); |
647 | } |
648 | |
649 | static inline void exar_misc_clear(struct exar8250 *priv) |
650 | { |
651 | /* Clear all PCI interrupts by reading INT0. No effect on IIR */ |
652 | readb(addr: priv->virt + UART_EXAR_INT0); |
653 | |
654 | /* Clear INT0 for Expansion Interface slave ports, too */ |
655 | if (priv->board->num_ports > 8) |
656 | readb(addr: priv->virt + 0x2000 + UART_EXAR_INT0); |
657 | } |
658 | |
659 | /* |
660 | * These Exar UARTs have an extra interrupt indicator that could fire for a |
661 | * few interrupts that are not presented/cleared through IIR. One of which is |
662 | * a wakeup interrupt when coming out of sleep. These interrupts are only |
663 | * cleared by reading global INT0 or INT1 registers as interrupts are |
664 | * associated with channel 0. The INT[3:0] registers _are_ accessible from each |
665 | * channel's address space, but for the sake of bus efficiency we register a |
666 | * dedicated handler at the PCI device level to handle them. |
667 | */ |
668 | static irqreturn_t exar_misc_handler(int irq, void *data) |
669 | { |
670 | exar_misc_clear(priv: data); |
671 | |
672 | return IRQ_HANDLED; |
673 | } |
674 | |
675 | static int |
676 | exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) |
677 | { |
678 | unsigned int nr_ports, i, bar = 0, maxnr; |
679 | struct exar8250_board *board; |
680 | struct uart_8250_port uart; |
681 | struct exar8250 *priv; |
682 | int rc; |
683 | |
684 | board = (struct exar8250_board *)ent->driver_data; |
685 | if (!board) |
686 | return -EINVAL; |
687 | |
688 | rc = pcim_enable_device(pdev: pcidev); |
689 | if (rc) |
690 | return rc; |
691 | |
692 | maxnr = pci_resource_len(pcidev, bar) >> (board->reg_shift + 3); |
693 | |
694 | if (pcidev->vendor == PCI_VENDOR_ID_ACCESSIO) |
695 | nr_ports = BIT(((pcidev->device & 0x38) >> 3) - 1); |
696 | else if (board->num_ports) |
697 | nr_ports = board->num_ports; |
698 | else |
699 | nr_ports = pcidev->device & 0x0f; |
700 | |
701 | priv = devm_kzalloc(dev: &pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL); |
702 | if (!priv) |
703 | return -ENOMEM; |
704 | |
705 | priv->board = board; |
706 | priv->virt = pcim_iomap(pdev: pcidev, bar, maxlen: 0); |
707 | if (!priv->virt) |
708 | return -ENOMEM; |
709 | |
710 | pci_set_master(dev: pcidev); |
711 | |
712 | rc = pci_alloc_irq_vectors(dev: pcidev, min_vecs: 1, max_vecs: 1, PCI_IRQ_ALL_TYPES); |
713 | if (rc < 0) |
714 | return rc; |
715 | |
716 | memset(&uart, 0, sizeof(uart)); |
717 | uart.port.flags = UPF_SHARE_IRQ | UPF_EXAR_EFR | UPF_FIXED_TYPE | UPF_FIXED_PORT; |
718 | uart.port.irq = pci_irq_vector(dev: pcidev, nr: 0); |
719 | uart.port.dev = &pcidev->dev; |
720 | |
721 | /* Clear interrupts */ |
722 | exar_misc_clear(priv); |
723 | |
724 | rc = devm_request_irq(dev: &pcidev->dev, irq: uart.port.irq, handler: exar_misc_handler, |
725 | IRQF_SHARED, devname: "exar_uart" , dev_id: priv); |
726 | if (rc) |
727 | return rc; |
728 | |
729 | for (i = 0; i < nr_ports && i < maxnr; i++) { |
730 | rc = board->setup(priv, pcidev, &uart, i); |
731 | if (rc) { |
732 | dev_err(&pcidev->dev, "Failed to setup port %u\n" , i); |
733 | break; |
734 | } |
735 | |
736 | dev_dbg(&pcidev->dev, "Setup PCI port: port %lx, irq %d, type %d\n" , |
737 | uart.port.iobase, uart.port.irq, uart.port.iotype); |
738 | |
739 | priv->line[i] = serial8250_register_8250_port(&uart); |
740 | if (priv->line[i] < 0) { |
741 | dev_err(&pcidev->dev, |
742 | "Couldn't register serial port %lx, irq %d, type %d, error %d\n" , |
743 | uart.port.iobase, uart.port.irq, |
744 | uart.port.iotype, priv->line[i]); |
745 | break; |
746 | } |
747 | } |
748 | priv->nr = i; |
749 | pci_set_drvdata(pdev: pcidev, data: priv); |
750 | return 0; |
751 | } |
752 | |
753 | static void exar_pci_remove(struct pci_dev *pcidev) |
754 | { |
755 | struct exar8250 *priv = pci_get_drvdata(pdev: pcidev); |
756 | unsigned int i; |
757 | |
758 | for (i = 0; i < priv->nr; i++) |
759 | serial8250_unregister_port(line: priv->line[i]); |
760 | |
761 | /* Ensure that every init quirk is properly torn down */ |
762 | if (priv->board->exit) |
763 | priv->board->exit(pcidev); |
764 | } |
765 | |
766 | static int exar_suspend(struct device *dev) |
767 | { |
768 | struct exar8250 *priv = dev_get_drvdata(dev); |
769 | unsigned int i; |
770 | |
771 | for (i = 0; i < priv->nr; i++) |
772 | if (priv->line[i] >= 0) |
773 | serial8250_suspend_port(line: priv->line[i]); |
774 | |
775 | return 0; |
776 | } |
777 | |
778 | static int exar_resume(struct device *dev) |
779 | { |
780 | struct exar8250 *priv = dev_get_drvdata(dev); |
781 | unsigned int i; |
782 | |
783 | exar_misc_clear(priv); |
784 | |
785 | for (i = 0; i < priv->nr; i++) |
786 | if (priv->line[i] >= 0) |
787 | serial8250_resume_port(line: priv->line[i]); |
788 | |
789 | return 0; |
790 | } |
791 | |
792 | static DEFINE_SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); |
793 | |
794 | static const struct exar8250_board pbn_fastcom335_2 = { |
795 | .num_ports = 2, |
796 | .setup = pci_fastcom335_setup, |
797 | }; |
798 | |
799 | static const struct exar8250_board pbn_fastcom335_4 = { |
800 | .num_ports = 4, |
801 | .setup = pci_fastcom335_setup, |
802 | }; |
803 | |
804 | static const struct exar8250_board pbn_fastcom335_8 = { |
805 | .num_ports = 8, |
806 | .setup = pci_fastcom335_setup, |
807 | }; |
808 | |
809 | static const struct exar8250_board pbn_connect = { |
810 | .setup = pci_connect_tech_setup, |
811 | }; |
812 | |
813 | static const struct exar8250_board pbn_exar_ibm_saturn = { |
814 | .num_ports = 1, |
815 | .setup = pci_xr17c154_setup, |
816 | }; |
817 | |
818 | static const struct exar8250_board pbn_exar_XR17C15x = { |
819 | .setup = pci_xr17c154_setup, |
820 | }; |
821 | |
822 | static const struct exar8250_board pbn_exar_XR17V35x = { |
823 | .setup = pci_xr17v35x_setup, |
824 | .exit = pci_xr17v35x_exit, |
825 | }; |
826 | |
827 | static const struct exar8250_board pbn_fastcom35x_2 = { |
828 | .num_ports = 2, |
829 | .setup = pci_xr17v35x_setup, |
830 | .exit = pci_xr17v35x_exit, |
831 | }; |
832 | |
833 | static const struct exar8250_board pbn_fastcom35x_4 = { |
834 | .num_ports = 4, |
835 | .setup = pci_xr17v35x_setup, |
836 | .exit = pci_xr17v35x_exit, |
837 | }; |
838 | |
839 | static const struct exar8250_board pbn_fastcom35x_8 = { |
840 | .num_ports = 8, |
841 | .setup = pci_xr17v35x_setup, |
842 | .exit = pci_xr17v35x_exit, |
843 | }; |
844 | |
845 | static const struct exar8250_board pbn_exar_XR17V4358 = { |
846 | .num_ports = 12, |
847 | .setup = pci_xr17v35x_setup, |
848 | .exit = pci_xr17v35x_exit, |
849 | }; |
850 | |
851 | static const struct exar8250_board pbn_exar_XR17V8358 = { |
852 | .num_ports = 16, |
853 | .setup = pci_xr17v35x_setup, |
854 | .exit = pci_xr17v35x_exit, |
855 | }; |
856 | |
857 | #define CONNECT_DEVICE(devid, sdevid, bd) { \ |
858 | PCI_DEVICE_SUB( \ |
859 | PCI_VENDOR_ID_EXAR, \ |
860 | PCI_DEVICE_ID_EXAR_##devid, \ |
861 | PCI_SUBVENDOR_ID_CONNECT_TECH, \ |
862 | PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_##sdevid), 0, 0, \ |
863 | (kernel_ulong_t)&bd \ |
864 | } |
865 | |
866 | #define EXAR_DEVICE(vend, devid, bd) { PCI_DEVICE_DATA(vend, devid, &bd) } |
867 | |
868 | #define IBM_DEVICE(devid, sdevid, bd) { \ |
869 | PCI_DEVICE_SUB( \ |
870 | PCI_VENDOR_ID_EXAR, \ |
871 | PCI_DEVICE_ID_EXAR_##devid, \ |
872 | PCI_VENDOR_ID_IBM, \ |
873 | PCI_SUBDEVICE_ID_IBM_##sdevid), 0, 0, \ |
874 | (kernel_ulong_t)&bd \ |
875 | } |
876 | |
877 | #define USR_DEVICE(devid, sdevid, bd) { \ |
878 | PCI_DEVICE_SUB( \ |
879 | PCI_VENDOR_ID_USR, \ |
880 | PCI_DEVICE_ID_EXAR_##devid, \ |
881 | PCI_VENDOR_ID_EXAR, \ |
882 | PCI_SUBDEVICE_ID_USR_##sdevid), 0, 0, \ |
883 | (kernel_ulong_t)&bd \ |
884 | } |
885 | |
886 | static const struct pci_device_id exar_pci_tbl[] = { |
887 | EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x), |
888 | EXAR_DEVICE(ACCESSIO, COM_4S, pbn_exar_XR17C15x), |
889 | EXAR_DEVICE(ACCESSIO, COM_8S, pbn_exar_XR17C15x), |
890 | EXAR_DEVICE(ACCESSIO, COM232_8, pbn_exar_XR17C15x), |
891 | EXAR_DEVICE(ACCESSIO, COM_2SM, pbn_exar_XR17C15x), |
892 | EXAR_DEVICE(ACCESSIO, COM_4SM, pbn_exar_XR17C15x), |
893 | EXAR_DEVICE(ACCESSIO, COM_8SM, pbn_exar_XR17C15x), |
894 | |
895 | CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect), |
896 | CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect), |
897 | CONNECT_DEVICE(XR17C158, UART_8_232, pbn_connect), |
898 | CONNECT_DEVICE(XR17C152, UART_1_1, pbn_connect), |
899 | CONNECT_DEVICE(XR17C154, UART_2_2, pbn_connect), |
900 | CONNECT_DEVICE(XR17C158, UART_4_4, pbn_connect), |
901 | CONNECT_DEVICE(XR17C152, UART_2, pbn_connect), |
902 | CONNECT_DEVICE(XR17C154, UART_4, pbn_connect), |
903 | CONNECT_DEVICE(XR17C158, UART_8, pbn_connect), |
904 | CONNECT_DEVICE(XR17C152, UART_2_485, pbn_connect), |
905 | CONNECT_DEVICE(XR17C154, UART_4_485, pbn_connect), |
906 | CONNECT_DEVICE(XR17C158, UART_8_485, pbn_connect), |
907 | |
908 | IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn), |
909 | |
910 | /* USRobotics USR298x-OEM PCI Modems */ |
911 | USR_DEVICE(XR17C152, 2980, pbn_exar_XR17C15x), |
912 | USR_DEVICE(XR17C152, 2981, pbn_exar_XR17C15x), |
913 | |
914 | /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */ |
915 | EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x), |
916 | EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x), |
917 | EXAR_DEVICE(EXAR, XR17C158, pbn_exar_XR17C15x), |
918 | |
919 | /* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */ |
920 | EXAR_DEVICE(EXAR, XR17V352, pbn_exar_XR17V35x), |
921 | EXAR_DEVICE(EXAR, XR17V354, pbn_exar_XR17V35x), |
922 | EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x), |
923 | EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358), |
924 | EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358), |
925 | EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_fastcom35x_2), |
926 | EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_fastcom35x_4), |
927 | EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_fastcom35x_8), |
928 | |
929 | EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2), |
930 | EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4), |
931 | EXAR_DEVICE(COMMTECH, 2324PCI335, pbn_fastcom335_4), |
932 | EXAR_DEVICE(COMMTECH, 2328PCI335, pbn_fastcom335_8), |
933 | { 0, } |
934 | }; |
935 | MODULE_DEVICE_TABLE(pci, exar_pci_tbl); |
936 | |
937 | static struct pci_driver exar_pci_driver = { |
938 | .name = "exar_serial" , |
939 | .probe = exar_pci_probe, |
940 | .remove = exar_pci_remove, |
941 | .driver = { |
942 | .pm = pm_sleep_ptr(&exar_pci_pm), |
943 | }, |
944 | .id_table = exar_pci_tbl, |
945 | }; |
946 | module_pci_driver(exar_pci_driver); |
947 | |
948 | MODULE_IMPORT_NS(SERIAL_8250_PCI); |
949 | MODULE_LICENSE("GPL" ); |
950 | MODULE_DESCRIPTION("Exar Serial Driver" ); |
951 | MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>" ); |
952 | |