diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 16:41:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 16:41:04 -0500 |
commit | 21eaab6d19ed43e82ed39c8deb7f192134fb4a0e (patch) | |
tree | d995205afdcb7f47462bcd28067dc0c4ab0b7b02 /drivers/tty/serial/rp2.c | |
parent | 74e1a2a39355b2d3ae8c60c78d8add162c6d7183 (diff) | |
parent | 9e17df37d710f8998e9cb10a548304fe33d4a5c2 (diff) |
Merge tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial patches from Greg Kroah-Hartman:
"Here's the big tty/serial driver patches for 3.9-rc1.
More tty port rework and fixes from Jiri here, as well as lots of
individual serial driver updates and fixes.
All of these have been in the linux-next tree for a while."
* tag 'tty-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (140 commits)
tty: mxser: improve error handling in mxser_probe() and mxser_module_init()
serial: imx: fix uninitialized variable warning
serial: tegra: assume CONFIG_OF
TTY: do not update atime/mtime on read/write
lguest: select CONFIG_TTY to build properly.
ARM defconfigs: add missing inclusions of linux/platform_device.h
fb/exynos: include platform_device.h
ARM: sa1100/assabet: include platform_device.h directly
serial: imx: Fix recursive locking bug
pps: Fix build breakage from decoupling pps from tty
tty: Remove ancient hardpps()
pps: Additional cleanups in uart_handle_dcd_change
pps: Move timestamp read into PPS code proper
pps: Don't crash the machine when exiting will do
pps: Fix a use-after free bug when unregistering a source.
pps: Use pps_lookup_dev to reduce ldisc coupling
pps: Add pps_lookup_dev() function
tty: serial: uartlite: Support uartlite on big and little endian systems
tty: serial: uartlite: Fix sparse and checkpatch warnings
serial/arc-uart: Miscll DT related updates (Grant's review comments)
...
Fix up trivial conflicts, mostly just due to the TTY config option
clashing with the EXPERIMENTAL removal.
Diffstat (limited to 'drivers/tty/serial/rp2.c')
-rw-r--r-- | drivers/tty/serial/rp2.c | 885 |
1 files changed, 885 insertions, 0 deletions
diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c new file mode 100644 index 000000000000..a314a943f124 --- /dev/null +++ b/drivers/tty/serial/rp2.c | |||
@@ -0,0 +1,885 @@ | |||
1 | /* | ||
2 | * Driver for Comtrol RocketPort EXPRESS/INFINITY cards | ||
3 | * | ||
4 | * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com> | ||
5 | * | ||
6 | * Inspired by, and loosely based on: | ||
7 | * | ||
8 | * ar933x_uart.c | ||
9 | * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> | ||
10 | * | ||
11 | * rocketport_infinity_express-linux-1.20.tar.gz | ||
12 | * Copyright (C) 2004-2011 Comtrol, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License version 2 as published | ||
16 | * by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/bitops.h> | ||
20 | #include <linux/compiler.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/console.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/firmware.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/log2.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/serial_core.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/sysrq.h> | ||
37 | #include <linux/tty.h> | ||
38 | #include <linux/tty_flip.h> | ||
39 | #include <linux/types.h> | ||
40 | |||
41 | #define DRV_NAME "rp2" | ||
42 | |||
43 | #define RP2_FW_NAME "rp2.fw" | ||
44 | #define RP2_UCODE_BYTES 0x3f | ||
45 | |||
46 | #define PORTS_PER_ASIC 16 | ||
47 | #define ALL_PORTS_MASK (BIT(PORTS_PER_ASIC) - 1) | ||
48 | |||
49 | #define UART_CLOCK 44236800 | ||
50 | #define DEFAULT_BAUD_DIV (UART_CLOCK / (9600 * 16)) | ||
51 | #define FIFO_SIZE 512 | ||
52 | |||
53 | /* BAR0 registers */ | ||
54 | #define RP2_FPGA_CTL0 0x110 | ||
55 | #define RP2_FPGA_CTL1 0x11c | ||
56 | #define RP2_IRQ_MASK 0x1ec | ||
57 | #define RP2_IRQ_MASK_EN_m BIT(0) | ||
58 | #define RP2_IRQ_STATUS 0x1f0 | ||
59 | |||
60 | /* BAR1 registers */ | ||
61 | #define RP2_ASIC_SPACING 0x1000 | ||
62 | #define RP2_ASIC_OFFSET(i) ((i) << ilog2(RP2_ASIC_SPACING)) | ||
63 | |||
64 | #define RP2_PORT_BASE 0x000 | ||
65 | #define RP2_PORT_SPACING 0x040 | ||
66 | |||
67 | #define RP2_UCODE_BASE 0x400 | ||
68 | #define RP2_UCODE_SPACING 0x80 | ||
69 | |||
70 | #define RP2_CLK_PRESCALER 0xc00 | ||
71 | #define RP2_CH_IRQ_STAT 0xc04 | ||
72 | #define RP2_CH_IRQ_MASK 0xc08 | ||
73 | #define RP2_ASIC_IRQ 0xd00 | ||
74 | #define RP2_ASIC_IRQ_EN_m BIT(20) | ||
75 | #define RP2_GLOBAL_CMD 0xd0c | ||
76 | #define RP2_ASIC_CFG 0xd04 | ||
77 | |||
78 | /* port registers */ | ||
79 | #define RP2_DATA_DWORD 0x000 | ||
80 | |||
81 | #define RP2_DATA_BYTE 0x008 | ||
82 | #define RP2_DATA_BYTE_ERR_PARITY_m BIT(8) | ||
83 | #define RP2_DATA_BYTE_ERR_OVERRUN_m BIT(9) | ||
84 | #define RP2_DATA_BYTE_ERR_FRAMING_m BIT(10) | ||
85 | #define RP2_DATA_BYTE_BREAK_m BIT(11) | ||
86 | |||
87 | /* This lets uart_insert_char() drop bytes received on a !CREAD port */ | ||
88 | #define RP2_DUMMY_READ BIT(16) | ||
89 | |||
90 | #define RP2_DATA_BYTE_EXCEPTION_MASK (RP2_DATA_BYTE_ERR_PARITY_m | \ | ||
91 | RP2_DATA_BYTE_ERR_OVERRUN_m | \ | ||
92 | RP2_DATA_BYTE_ERR_FRAMING_m | \ | ||
93 | RP2_DATA_BYTE_BREAK_m) | ||
94 | |||
95 | #define RP2_RX_FIFO_COUNT 0x00c | ||
96 | #define RP2_TX_FIFO_COUNT 0x00e | ||
97 | |||
98 | #define RP2_CHAN_STAT 0x010 | ||
99 | #define RP2_CHAN_STAT_RXDATA_m BIT(0) | ||
100 | #define RP2_CHAN_STAT_DCD_m BIT(3) | ||
101 | #define RP2_CHAN_STAT_DSR_m BIT(4) | ||
102 | #define RP2_CHAN_STAT_CTS_m BIT(5) | ||
103 | #define RP2_CHAN_STAT_RI_m BIT(6) | ||
104 | #define RP2_CHAN_STAT_OVERRUN_m BIT(13) | ||
105 | #define RP2_CHAN_STAT_DSR_CHANGED_m BIT(16) | ||
106 | #define RP2_CHAN_STAT_CTS_CHANGED_m BIT(17) | ||
107 | #define RP2_CHAN_STAT_CD_CHANGED_m BIT(18) | ||
108 | #define RP2_CHAN_STAT_RI_CHANGED_m BIT(22) | ||
109 | #define RP2_CHAN_STAT_TXEMPTY_m BIT(25) | ||
110 | |||
111 | #define RP2_CHAN_STAT_MS_CHANGED_MASK (RP2_CHAN_STAT_DSR_CHANGED_m | \ | ||
112 | RP2_CHAN_STAT_CTS_CHANGED_m | \ | ||
113 | RP2_CHAN_STAT_CD_CHANGED_m | \ | ||
114 | RP2_CHAN_STAT_RI_CHANGED_m) | ||
115 | |||
116 | #define RP2_TXRX_CTL 0x014 | ||
117 | #define RP2_TXRX_CTL_MSRIRQ_m BIT(0) | ||
118 | #define RP2_TXRX_CTL_RXIRQ_m BIT(2) | ||
119 | #define RP2_TXRX_CTL_RX_TRIG_s 3 | ||
120 | #define RP2_TXRX_CTL_RX_TRIG_m (0x3 << RP2_TXRX_CTL_RX_TRIG_s) | ||
121 | #define RP2_TXRX_CTL_RX_TRIG_1 (0x1 << RP2_TXRX_CTL_RX_TRIG_s) | ||
122 | #define RP2_TXRX_CTL_RX_TRIG_256 (0x2 << RP2_TXRX_CTL_RX_TRIG_s) | ||
123 | #define RP2_TXRX_CTL_RX_TRIG_448 (0x3 << RP2_TXRX_CTL_RX_TRIG_s) | ||
124 | #define RP2_TXRX_CTL_RX_EN_m BIT(5) | ||
125 | #define RP2_TXRX_CTL_RTSFLOW_m BIT(6) | ||
126 | #define RP2_TXRX_CTL_DTRFLOW_m BIT(7) | ||
127 | #define RP2_TXRX_CTL_TX_TRIG_s 16 | ||
128 | #define RP2_TXRX_CTL_TX_TRIG_m (0x3 << RP2_TXRX_CTL_RX_TRIG_s) | ||
129 | #define RP2_TXRX_CTL_DSRFLOW_m BIT(18) | ||
130 | #define RP2_TXRX_CTL_TXIRQ_m BIT(19) | ||
131 | #define RP2_TXRX_CTL_CTSFLOW_m BIT(23) | ||
132 | #define RP2_TXRX_CTL_TX_EN_m BIT(24) | ||
133 | #define RP2_TXRX_CTL_RTS_m BIT(25) | ||
134 | #define RP2_TXRX_CTL_DTR_m BIT(26) | ||
135 | #define RP2_TXRX_CTL_LOOP_m BIT(27) | ||
136 | #define RP2_TXRX_CTL_BREAK_m BIT(28) | ||
137 | #define RP2_TXRX_CTL_CMSPAR_m BIT(29) | ||
138 | #define RP2_TXRX_CTL_nPARODD_m BIT(30) | ||
139 | #define RP2_TXRX_CTL_PARENB_m BIT(31) | ||
140 | |||
141 | #define RP2_UART_CTL 0x018 | ||
142 | #define RP2_UART_CTL_MODE_s 0 | ||
143 | #define RP2_UART_CTL_MODE_m (0x7 << RP2_UART_CTL_MODE_s) | ||
144 | #define RP2_UART_CTL_MODE_rs232 (0x1 << RP2_UART_CTL_MODE_s) | ||
145 | #define RP2_UART_CTL_FLUSH_RX_m BIT(3) | ||
146 | #define RP2_UART_CTL_FLUSH_TX_m BIT(4) | ||
147 | #define RP2_UART_CTL_RESET_CH_m BIT(5) | ||
148 | #define RP2_UART_CTL_XMIT_EN_m BIT(6) | ||
149 | #define RP2_UART_CTL_DATABITS_s 8 | ||
150 | #define RP2_UART_CTL_DATABITS_m (0x3 << RP2_UART_CTL_DATABITS_s) | ||
151 | #define RP2_UART_CTL_DATABITS_8 (0x3 << RP2_UART_CTL_DATABITS_s) | ||
152 | #define RP2_UART_CTL_DATABITS_7 (0x2 << RP2_UART_CTL_DATABITS_s) | ||
153 | #define RP2_UART_CTL_DATABITS_6 (0x1 << RP2_UART_CTL_DATABITS_s) | ||
154 | #define RP2_UART_CTL_DATABITS_5 (0x0 << RP2_UART_CTL_DATABITS_s) | ||
155 | #define RP2_UART_CTL_STOPBITS_m BIT(10) | ||
156 | |||
157 | #define RP2_BAUD 0x01c | ||
158 | |||
159 | /* ucode registers */ | ||
160 | #define RP2_TX_SWFLOW 0x02 | ||
161 | #define RP2_TX_SWFLOW_ena 0x81 | ||
162 | #define RP2_TX_SWFLOW_dis 0x9d | ||
163 | |||
164 | #define RP2_RX_SWFLOW 0x0c | ||
165 | #define RP2_RX_SWFLOW_ena 0x81 | ||
166 | #define RP2_RX_SWFLOW_dis 0x8d | ||
167 | |||
168 | #define RP2_RX_FIFO 0x37 | ||
169 | #define RP2_RX_FIFO_ena 0x08 | ||
170 | #define RP2_RX_FIFO_dis 0x81 | ||
171 | |||
172 | static struct uart_driver rp2_uart_driver = { | ||
173 | .owner = THIS_MODULE, | ||
174 | .driver_name = DRV_NAME, | ||
175 | .dev_name = "ttyRP", | ||
176 | .nr = CONFIG_SERIAL_RP2_NR_UARTS, | ||
177 | }; | ||
178 | |||
179 | struct rp2_card; | ||
180 | |||
181 | struct rp2_uart_port { | ||
182 | struct uart_port port; | ||
183 | int idx; | ||
184 | int ignore_rx; | ||
185 | struct rp2_card *card; | ||
186 | void __iomem *asic_base; | ||
187 | void __iomem *base; | ||
188 | void __iomem *ucode; | ||
189 | }; | ||
190 | |||
191 | struct rp2_card { | ||
192 | struct pci_dev *pdev; | ||
193 | struct rp2_uart_port *ports; | ||
194 | int n_ports; | ||
195 | int initialized_ports; | ||
196 | int minor_start; | ||
197 | int smpte; | ||
198 | void __iomem *bar0; | ||
199 | void __iomem *bar1; | ||
200 | spinlock_t card_lock; | ||
201 | struct completion fw_loaded; | ||
202 | }; | ||
203 | |||
204 | #define RP_ID(prod) PCI_VDEVICE(RP, (prod)) | ||
205 | #define RP_CAP(ports, smpte) (((ports) << 8) | ((smpte) << 0)) | ||
206 | |||
207 | static inline void rp2_decode_cap(const struct pci_device_id *id, | ||
208 | int *ports, int *smpte) | ||
209 | { | ||
210 | *ports = id->driver_data >> 8; | ||
211 | *smpte = id->driver_data & 0xff; | ||
212 | } | ||
213 | |||
214 | static DEFINE_SPINLOCK(rp2_minor_lock); | ||
215 | static int rp2_minor_next; | ||
216 | |||
217 | static int rp2_alloc_ports(int n_ports) | ||
218 | { | ||
219 | int ret = -ENOSPC; | ||
220 | |||
221 | spin_lock(&rp2_minor_lock); | ||
222 | if (rp2_minor_next + n_ports <= CONFIG_SERIAL_RP2_NR_UARTS) { | ||
223 | /* sorry, no support for hot unplugging individual cards */ | ||
224 | ret = rp2_minor_next; | ||
225 | rp2_minor_next += n_ports; | ||
226 | } | ||
227 | spin_unlock(&rp2_minor_lock); | ||
228 | |||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static inline struct rp2_uart_port *port_to_up(struct uart_port *port) | ||
233 | { | ||
234 | return container_of(port, struct rp2_uart_port, port); | ||
235 | } | ||
236 | |||
237 | static void rp2_rmw(struct rp2_uart_port *up, int reg, | ||
238 | u32 clr_bits, u32 set_bits) | ||
239 | { | ||
240 | u32 tmp = readl(up->base + reg); | ||
241 | tmp &= ~clr_bits; | ||
242 | tmp |= set_bits; | ||
243 | writel(tmp, up->base + reg); | ||
244 | } | ||
245 | |||
246 | static void rp2_rmw_clr(struct rp2_uart_port *up, int reg, u32 val) | ||
247 | { | ||
248 | rp2_rmw(up, reg, val, 0); | ||
249 | } | ||
250 | |||
251 | static void rp2_rmw_set(struct rp2_uart_port *up, int reg, u32 val) | ||
252 | { | ||
253 | rp2_rmw(up, reg, 0, val); | ||
254 | } | ||
255 | |||
256 | static void rp2_mask_ch_irq(struct rp2_uart_port *up, int ch_num, | ||
257 | int is_enabled) | ||
258 | { | ||
259 | unsigned long flags, irq_mask; | ||
260 | |||
261 | spin_lock_irqsave(&up->card->card_lock, flags); | ||
262 | |||
263 | irq_mask = readl(up->asic_base + RP2_CH_IRQ_MASK); | ||
264 | if (is_enabled) | ||
265 | irq_mask &= ~BIT(ch_num); | ||
266 | else | ||
267 | irq_mask |= BIT(ch_num); | ||
268 | writel(irq_mask, up->asic_base + RP2_CH_IRQ_MASK); | ||
269 | |||
270 | spin_unlock_irqrestore(&up->card->card_lock, flags); | ||
271 | } | ||
272 | |||
273 | static unsigned int rp2_uart_tx_empty(struct uart_port *port) | ||
274 | { | ||
275 | struct rp2_uart_port *up = port_to_up(port); | ||
276 | unsigned long tx_fifo_bytes, flags; | ||
277 | |||
278 | /* | ||
279 | * This should probably check the transmitter, not the FIFO. | ||
280 | * But the TXEMPTY bit doesn't seem to work unless the TX IRQ is | ||
281 | * enabled. | ||
282 | */ | ||
283 | spin_lock_irqsave(&up->port.lock, flags); | ||
284 | tx_fifo_bytes = readw(up->base + RP2_TX_FIFO_COUNT); | ||
285 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
286 | |||
287 | return tx_fifo_bytes ? 0 : TIOCSER_TEMT; | ||
288 | } | ||
289 | |||
290 | static unsigned int rp2_uart_get_mctrl(struct uart_port *port) | ||
291 | { | ||
292 | struct rp2_uart_port *up = port_to_up(port); | ||
293 | u32 status; | ||
294 | |||
295 | status = readl(up->base + RP2_CHAN_STAT); | ||
296 | return ((status & RP2_CHAN_STAT_DCD_m) ? TIOCM_CAR : 0) | | ||
297 | ((status & RP2_CHAN_STAT_DSR_m) ? TIOCM_DSR : 0) | | ||
298 | ((status & RP2_CHAN_STAT_CTS_m) ? TIOCM_CTS : 0) | | ||
299 | ((status & RP2_CHAN_STAT_RI_m) ? TIOCM_RI : 0); | ||
300 | } | ||
301 | |||
302 | static void rp2_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
303 | { | ||
304 | rp2_rmw(port_to_up(port), RP2_TXRX_CTL, | ||
305 | RP2_TXRX_CTL_DTR_m | RP2_TXRX_CTL_RTS_m | RP2_TXRX_CTL_LOOP_m, | ||
306 | ((mctrl & TIOCM_DTR) ? RP2_TXRX_CTL_DTR_m : 0) | | ||
307 | ((mctrl & TIOCM_RTS) ? RP2_TXRX_CTL_RTS_m : 0) | | ||
308 | ((mctrl & TIOCM_LOOP) ? RP2_TXRX_CTL_LOOP_m : 0)); | ||
309 | } | ||
310 | |||
311 | static void rp2_uart_start_tx(struct uart_port *port) | ||
312 | { | ||
313 | rp2_rmw_set(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_TXIRQ_m); | ||
314 | } | ||
315 | |||
316 | static void rp2_uart_stop_tx(struct uart_port *port) | ||
317 | { | ||
318 | rp2_rmw_clr(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_TXIRQ_m); | ||
319 | } | ||
320 | |||
321 | static void rp2_uart_stop_rx(struct uart_port *port) | ||
322 | { | ||
323 | rp2_rmw_clr(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_RXIRQ_m); | ||
324 | } | ||
325 | |||
326 | static void rp2_uart_break_ctl(struct uart_port *port, int break_state) | ||
327 | { | ||
328 | unsigned long flags; | ||
329 | |||
330 | spin_lock_irqsave(&port->lock, flags); | ||
331 | rp2_rmw(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_BREAK_m, | ||
332 | break_state ? RP2_TXRX_CTL_BREAK_m : 0); | ||
333 | spin_unlock_irqrestore(&port->lock, flags); | ||
334 | } | ||
335 | |||
336 | static void rp2_uart_enable_ms(struct uart_port *port) | ||
337 | { | ||
338 | rp2_rmw_set(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_MSRIRQ_m); | ||
339 | } | ||
340 | |||
341 | static void __rp2_uart_set_termios(struct rp2_uart_port *up, | ||
342 | unsigned long cfl, | ||
343 | unsigned long ifl, | ||
344 | unsigned int baud_div) | ||
345 | { | ||
346 | /* baud rate divisor (calculated elsewhere). 0 = divide-by-1 */ | ||
347 | writew(baud_div - 1, up->base + RP2_BAUD); | ||
348 | |||
349 | /* data bits and stop bits */ | ||
350 | rp2_rmw(up, RP2_UART_CTL, | ||
351 | RP2_UART_CTL_STOPBITS_m | RP2_UART_CTL_DATABITS_m, | ||
352 | ((cfl & CSTOPB) ? RP2_UART_CTL_STOPBITS_m : 0) | | ||
353 | (((cfl & CSIZE) == CS8) ? RP2_UART_CTL_DATABITS_8 : 0) | | ||
354 | (((cfl & CSIZE) == CS7) ? RP2_UART_CTL_DATABITS_7 : 0) | | ||
355 | (((cfl & CSIZE) == CS6) ? RP2_UART_CTL_DATABITS_6 : 0) | | ||
356 | (((cfl & CSIZE) == CS5) ? RP2_UART_CTL_DATABITS_5 : 0)); | ||
357 | |||
358 | /* parity and hardware flow control */ | ||
359 | rp2_rmw(up, RP2_TXRX_CTL, | ||
360 | RP2_TXRX_CTL_PARENB_m | RP2_TXRX_CTL_nPARODD_m | | ||
361 | RP2_TXRX_CTL_CMSPAR_m | RP2_TXRX_CTL_DTRFLOW_m | | ||
362 | RP2_TXRX_CTL_DSRFLOW_m | RP2_TXRX_CTL_RTSFLOW_m | | ||
363 | RP2_TXRX_CTL_CTSFLOW_m, | ||
364 | ((cfl & PARENB) ? RP2_TXRX_CTL_PARENB_m : 0) | | ||
365 | ((cfl & PARODD) ? 0 : RP2_TXRX_CTL_nPARODD_m) | | ||
366 | ((cfl & CMSPAR) ? RP2_TXRX_CTL_CMSPAR_m : 0) | | ||
367 | ((cfl & CRTSCTS) ? (RP2_TXRX_CTL_RTSFLOW_m | | ||
368 | RP2_TXRX_CTL_CTSFLOW_m) : 0)); | ||
369 | |||
370 | /* XON/XOFF software flow control */ | ||
371 | writeb((ifl & IXON) ? RP2_TX_SWFLOW_ena : RP2_TX_SWFLOW_dis, | ||
372 | up->ucode + RP2_TX_SWFLOW); | ||
373 | writeb((ifl & IXOFF) ? RP2_RX_SWFLOW_ena : RP2_RX_SWFLOW_dis, | ||
374 | up->ucode + RP2_RX_SWFLOW); | ||
375 | } | ||
376 | |||
377 | static void rp2_uart_set_termios(struct uart_port *port, | ||
378 | struct ktermios *new, | ||
379 | struct ktermios *old) | ||
380 | { | ||
381 | struct rp2_uart_port *up = port_to_up(port); | ||
382 | unsigned long flags; | ||
383 | unsigned int baud, baud_div; | ||
384 | |||
385 | baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); | ||
386 | baud_div = uart_get_divisor(port, baud); | ||
387 | |||
388 | if (tty_termios_baud_rate(new)) | ||
389 | tty_termios_encode_baud_rate(new, baud, baud); | ||
390 | |||
391 | spin_lock_irqsave(&port->lock, flags); | ||
392 | |||
393 | /* ignore all characters if CREAD is not set */ | ||
394 | port->ignore_status_mask = (new->c_cflag & CREAD) ? 0 : RP2_DUMMY_READ; | ||
395 | |||
396 | __rp2_uart_set_termios(up, new->c_cflag, new->c_iflag, baud_div); | ||
397 | uart_update_timeout(port, new->c_cflag, baud); | ||
398 | |||
399 | spin_unlock_irqrestore(&port->lock, flags); | ||
400 | } | ||
401 | |||
402 | static void rp2_rx_chars(struct rp2_uart_port *up) | ||
403 | { | ||
404 | u16 bytes = readw(up->base + RP2_RX_FIFO_COUNT); | ||
405 | struct tty_port *port = &up->port.state->port; | ||
406 | |||
407 | for (; bytes != 0; bytes--) { | ||
408 | u32 byte = readw(up->base + RP2_DATA_BYTE) | RP2_DUMMY_READ; | ||
409 | char ch = byte & 0xff; | ||
410 | |||
411 | if (likely(!(byte & RP2_DATA_BYTE_EXCEPTION_MASK))) { | ||
412 | if (!uart_handle_sysrq_char(&up->port, ch)) | ||
413 | uart_insert_char(&up->port, byte, 0, ch, | ||
414 | TTY_NORMAL); | ||
415 | } else { | ||
416 | char flag = TTY_NORMAL; | ||
417 | |||
418 | if (byte & RP2_DATA_BYTE_BREAK_m) | ||
419 | flag = TTY_BREAK; | ||
420 | else if (byte & RP2_DATA_BYTE_ERR_FRAMING_m) | ||
421 | flag = TTY_FRAME; | ||
422 | else if (byte & RP2_DATA_BYTE_ERR_PARITY_m) | ||
423 | flag = TTY_PARITY; | ||
424 | uart_insert_char(&up->port, byte, | ||
425 | RP2_DATA_BYTE_ERR_OVERRUN_m, ch, flag); | ||
426 | } | ||
427 | up->port.icount.rx++; | ||
428 | } | ||
429 | |||
430 | tty_flip_buffer_push(port); | ||
431 | } | ||
432 | |||
433 | static void rp2_tx_chars(struct rp2_uart_port *up) | ||
434 | { | ||
435 | u16 max_tx = FIFO_SIZE - readw(up->base + RP2_TX_FIFO_COUNT); | ||
436 | struct circ_buf *xmit = &up->port.state->xmit; | ||
437 | |||
438 | if (uart_tx_stopped(&up->port)) { | ||
439 | rp2_uart_stop_tx(&up->port); | ||
440 | return; | ||
441 | } | ||
442 | |||
443 | for (; max_tx != 0; max_tx--) { | ||
444 | if (up->port.x_char) { | ||
445 | writeb(up->port.x_char, up->base + RP2_DATA_BYTE); | ||
446 | up->port.x_char = 0; | ||
447 | up->port.icount.tx++; | ||
448 | continue; | ||
449 | } | ||
450 | if (uart_circ_empty(xmit)) { | ||
451 | rp2_uart_stop_tx(&up->port); | ||
452 | break; | ||
453 | } | ||
454 | writeb(xmit->buf[xmit->tail], up->base + RP2_DATA_BYTE); | ||
455 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
456 | up->port.icount.tx++; | ||
457 | } | ||
458 | |||
459 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
460 | uart_write_wakeup(&up->port); | ||
461 | } | ||
462 | |||
463 | static void rp2_ch_interrupt(struct rp2_uart_port *up) | ||
464 | { | ||
465 | u32 status; | ||
466 | |||
467 | spin_lock(&up->port.lock); | ||
468 | |||
469 | /* | ||
470 | * The IRQ status bits are clear-on-write. Other status bits in | ||
471 | * this register aren't, so it's harmless to write to them. | ||
472 | */ | ||
473 | status = readl(up->base + RP2_CHAN_STAT); | ||
474 | writel(status, up->base + RP2_CHAN_STAT); | ||
475 | |||
476 | if (status & RP2_CHAN_STAT_RXDATA_m) | ||
477 | rp2_rx_chars(up); | ||
478 | if (status & RP2_CHAN_STAT_TXEMPTY_m) | ||
479 | rp2_tx_chars(up); | ||
480 | if (status & RP2_CHAN_STAT_MS_CHANGED_MASK) | ||
481 | wake_up_interruptible(&up->port.state->port.delta_msr_wait); | ||
482 | |||
483 | spin_unlock(&up->port.lock); | ||
484 | } | ||
485 | |||
486 | static int rp2_asic_interrupt(struct rp2_card *card, unsigned int asic_id) | ||
487 | { | ||
488 | void __iomem *base = card->bar1 + RP2_ASIC_OFFSET(asic_id); | ||
489 | int ch, handled = 0; | ||
490 | unsigned long status = readl(base + RP2_CH_IRQ_STAT) & | ||
491 | ~readl(base + RP2_CH_IRQ_MASK); | ||
492 | |||
493 | for_each_set_bit(ch, &status, PORTS_PER_ASIC) { | ||
494 | rp2_ch_interrupt(&card->ports[ch]); | ||
495 | handled++; | ||
496 | } | ||
497 | return handled; | ||
498 | } | ||
499 | |||
500 | static irqreturn_t rp2_uart_interrupt(int irq, void *dev_id) | ||
501 | { | ||
502 | struct rp2_card *card = dev_id; | ||
503 | int handled; | ||
504 | |||
505 | handled = rp2_asic_interrupt(card, 0); | ||
506 | if (card->n_ports >= PORTS_PER_ASIC) | ||
507 | handled += rp2_asic_interrupt(card, 1); | ||
508 | |||
509 | return handled ? IRQ_HANDLED : IRQ_NONE; | ||
510 | } | ||
511 | |||
512 | static inline void rp2_flush_fifos(struct rp2_uart_port *up) | ||
513 | { | ||
514 | rp2_rmw_set(up, RP2_UART_CTL, | ||
515 | RP2_UART_CTL_FLUSH_RX_m | RP2_UART_CTL_FLUSH_TX_m); | ||
516 | readl(up->base + RP2_UART_CTL); | ||
517 | udelay(10); | ||
518 | rp2_rmw_clr(up, RP2_UART_CTL, | ||
519 | RP2_UART_CTL_FLUSH_RX_m | RP2_UART_CTL_FLUSH_TX_m); | ||
520 | } | ||
521 | |||
522 | static int rp2_uart_startup(struct uart_port *port) | ||
523 | { | ||
524 | struct rp2_uart_port *up = port_to_up(port); | ||
525 | |||
526 | rp2_flush_fifos(up); | ||
527 | rp2_rmw(up, RP2_TXRX_CTL, RP2_TXRX_CTL_MSRIRQ_m, RP2_TXRX_CTL_RXIRQ_m); | ||
528 | rp2_rmw(up, RP2_TXRX_CTL, RP2_TXRX_CTL_RX_TRIG_m, | ||
529 | RP2_TXRX_CTL_RX_TRIG_1); | ||
530 | rp2_rmw(up, RP2_CHAN_STAT, 0, 0); | ||
531 | rp2_mask_ch_irq(up, up->idx, 1); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static void rp2_uart_shutdown(struct uart_port *port) | ||
537 | { | ||
538 | struct rp2_uart_port *up = port_to_up(port); | ||
539 | unsigned long flags; | ||
540 | |||
541 | rp2_uart_break_ctl(port, 0); | ||
542 | |||
543 | spin_lock_irqsave(&port->lock, flags); | ||
544 | rp2_mask_ch_irq(up, up->idx, 0); | ||
545 | rp2_rmw(up, RP2_CHAN_STAT, 0, 0); | ||
546 | spin_unlock_irqrestore(&port->lock, flags); | ||
547 | } | ||
548 | |||
549 | static const char *rp2_uart_type(struct uart_port *port) | ||
550 | { | ||
551 | return (port->type == PORT_RP2) ? "RocketPort 2 UART" : NULL; | ||
552 | } | ||
553 | |||
554 | static void rp2_uart_release_port(struct uart_port *port) | ||
555 | { | ||
556 | /* Nothing to release ... */ | ||
557 | } | ||
558 | |||
559 | static int rp2_uart_request_port(struct uart_port *port) | ||
560 | { | ||
561 | /* UARTs always present */ | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static void rp2_uart_config_port(struct uart_port *port, int flags) | ||
566 | { | ||
567 | if (flags & UART_CONFIG_TYPE) | ||
568 | port->type = PORT_RP2; | ||
569 | } | ||
570 | |||
571 | static int rp2_uart_verify_port(struct uart_port *port, | ||
572 | struct serial_struct *ser) | ||
573 | { | ||
574 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_RP2) | ||
575 | return -EINVAL; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static const struct uart_ops rp2_uart_ops = { | ||
581 | .tx_empty = rp2_uart_tx_empty, | ||
582 | .set_mctrl = rp2_uart_set_mctrl, | ||
583 | .get_mctrl = rp2_uart_get_mctrl, | ||
584 | .stop_tx = rp2_uart_stop_tx, | ||
585 | .start_tx = rp2_uart_start_tx, | ||
586 | .stop_rx = rp2_uart_stop_rx, | ||
587 | .enable_ms = rp2_uart_enable_ms, | ||
588 | .break_ctl = rp2_uart_break_ctl, | ||
589 | .startup = rp2_uart_startup, | ||
590 | .shutdown = rp2_uart_shutdown, | ||
591 | .set_termios = rp2_uart_set_termios, | ||
592 | .type = rp2_uart_type, | ||
593 | .release_port = rp2_uart_release_port, | ||
594 | .request_port = rp2_uart_request_port, | ||
595 | .config_port = rp2_uart_config_port, | ||
596 | .verify_port = rp2_uart_verify_port, | ||
597 | }; | ||
598 | |||
599 | static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id) | ||
600 | { | ||
601 | void __iomem *base = card->bar1 + RP2_ASIC_OFFSET(asic_id); | ||
602 | u32 clk_cfg; | ||
603 | |||
604 | writew(1, base + RP2_GLOBAL_CMD); | ||
605 | readw(base + RP2_GLOBAL_CMD); | ||
606 | msleep(100); | ||
607 | writel(0, base + RP2_CLK_PRESCALER); | ||
608 | |||
609 | /* TDM clock configuration */ | ||
610 | clk_cfg = readw(base + RP2_ASIC_CFG); | ||
611 | clk_cfg = (clk_cfg & ~BIT(8)) | BIT(9); | ||
612 | writew(clk_cfg, base + RP2_ASIC_CFG); | ||
613 | |||
614 | /* IRQ routing */ | ||
615 | writel(ALL_PORTS_MASK, base + RP2_CH_IRQ_MASK); | ||
616 | writel(RP2_ASIC_IRQ_EN_m, base + RP2_ASIC_IRQ); | ||
617 | } | ||
618 | |||
619 | static void rp2_init_card(struct rp2_card *card) | ||
620 | { | ||
621 | writel(4, card->bar0 + RP2_FPGA_CTL0); | ||
622 | writel(0, card->bar0 + RP2_FPGA_CTL1); | ||
623 | |||
624 | rp2_reset_asic(card, 0); | ||
625 | if (card->n_ports >= PORTS_PER_ASIC) | ||
626 | rp2_reset_asic(card, 1); | ||
627 | |||
628 | writel(RP2_IRQ_MASK_EN_m, card->bar0 + RP2_IRQ_MASK); | ||
629 | } | ||
630 | |||
631 | static void rp2_init_port(struct rp2_uart_port *up, const struct firmware *fw) | ||
632 | { | ||
633 | int i; | ||
634 | |||
635 | writel(RP2_UART_CTL_RESET_CH_m, up->base + RP2_UART_CTL); | ||
636 | readl(up->base + RP2_UART_CTL); | ||
637 | udelay(1); | ||
638 | |||
639 | writel(0, up->base + RP2_TXRX_CTL); | ||
640 | writel(0, up->base + RP2_UART_CTL); | ||
641 | readl(up->base + RP2_UART_CTL); | ||
642 | udelay(1); | ||
643 | |||
644 | rp2_flush_fifos(up); | ||
645 | |||
646 | for (i = 0; i < min_t(int, fw->size, RP2_UCODE_BYTES); i++) | ||
647 | writeb(fw->data[i], up->ucode + i); | ||
648 | |||
649 | __rp2_uart_set_termios(up, CS8 | CREAD | CLOCAL, 0, DEFAULT_BAUD_DIV); | ||
650 | rp2_uart_set_mctrl(&up->port, 0); | ||
651 | |||
652 | writeb(RP2_RX_FIFO_ena, up->ucode + RP2_RX_FIFO); | ||
653 | rp2_rmw(up, RP2_UART_CTL, RP2_UART_CTL_MODE_m, | ||
654 | RP2_UART_CTL_XMIT_EN_m | RP2_UART_CTL_MODE_rs232); | ||
655 | rp2_rmw_set(up, RP2_TXRX_CTL, | ||
656 | RP2_TXRX_CTL_TX_EN_m | RP2_TXRX_CTL_RX_EN_m); | ||
657 | } | ||
658 | |||
659 | static void rp2_remove_ports(struct rp2_card *card) | ||
660 | { | ||
661 | int i; | ||
662 | |||
663 | for (i = 0; i < card->initialized_ports; i++) | ||
664 | uart_remove_one_port(&rp2_uart_driver, &card->ports[i].port); | ||
665 | card->initialized_ports = 0; | ||
666 | } | ||
667 | |||
668 | static void rp2_fw_cb(const struct firmware *fw, void *context) | ||
669 | { | ||
670 | struct rp2_card *card = context; | ||
671 | resource_size_t phys_base; | ||
672 | int i, rc = -ENOENT; | ||
673 | |||
674 | if (!fw) { | ||
675 | dev_err(&card->pdev->dev, "cannot find '%s' firmware image\n", | ||
676 | RP2_FW_NAME); | ||
677 | goto no_fw; | ||
678 | } | ||
679 | |||
680 | phys_base = pci_resource_start(card->pdev, 1); | ||
681 | |||
682 | for (i = 0; i < card->n_ports; i++) { | ||
683 | struct rp2_uart_port *rp = &card->ports[i]; | ||
684 | struct uart_port *p; | ||
685 | int j = (unsigned)i % PORTS_PER_ASIC; | ||
686 | |||
687 | rp->asic_base = card->bar1; | ||
688 | rp->base = card->bar1 + RP2_PORT_BASE + j*RP2_PORT_SPACING; | ||
689 | rp->ucode = card->bar1 + RP2_UCODE_BASE + j*RP2_UCODE_SPACING; | ||
690 | rp->card = card; | ||
691 | rp->idx = j; | ||
692 | |||
693 | p = &rp->port; | ||
694 | p->line = card->minor_start + i; | ||
695 | p->dev = &card->pdev->dev; | ||
696 | p->type = PORT_RP2; | ||
697 | p->iotype = UPIO_MEM32; | ||
698 | p->uartclk = UART_CLOCK; | ||
699 | p->regshift = 2; | ||
700 | p->fifosize = FIFO_SIZE; | ||
701 | p->ops = &rp2_uart_ops; | ||
702 | p->irq = card->pdev->irq; | ||
703 | p->membase = rp->base; | ||
704 | p->mapbase = phys_base + RP2_PORT_BASE + j*RP2_PORT_SPACING; | ||
705 | |||
706 | if (i >= PORTS_PER_ASIC) { | ||
707 | rp->asic_base += RP2_ASIC_SPACING; | ||
708 | rp->base += RP2_ASIC_SPACING; | ||
709 | rp->ucode += RP2_ASIC_SPACING; | ||
710 | p->mapbase += RP2_ASIC_SPACING; | ||
711 | } | ||
712 | |||
713 | rp2_init_port(rp, fw); | ||
714 | rc = uart_add_one_port(&rp2_uart_driver, p); | ||
715 | if (rc) { | ||
716 | dev_err(&card->pdev->dev, | ||
717 | "error registering port %d: %d\n", i, rc); | ||
718 | rp2_remove_ports(card); | ||
719 | break; | ||
720 | } | ||
721 | card->initialized_ports++; | ||
722 | } | ||
723 | |||
724 | release_firmware(fw); | ||
725 | no_fw: | ||
726 | /* | ||
727 | * rp2_fw_cb() is called from a workqueue long after rp2_probe() | ||
728 | * has already returned success. So if something failed here, | ||
729 | * we'll just leave the now-dormant device in place until somebody | ||
730 | * unbinds it. | ||
731 | */ | ||
732 | if (rc) | ||
733 | dev_warn(&card->pdev->dev, "driver initialization failed\n"); | ||
734 | |||
735 | complete(&card->fw_loaded); | ||
736 | } | ||
737 | |||
738 | static int rp2_probe(struct pci_dev *pdev, | ||
739 | const struct pci_device_id *id) | ||
740 | { | ||
741 | struct rp2_card *card; | ||
742 | struct rp2_uart_port *ports; | ||
743 | void __iomem * const *bars; | ||
744 | int rc; | ||
745 | |||
746 | card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); | ||
747 | if (!card) | ||
748 | return -ENOMEM; | ||
749 | pci_set_drvdata(pdev, card); | ||
750 | spin_lock_init(&card->card_lock); | ||
751 | init_completion(&card->fw_loaded); | ||
752 | |||
753 | rc = pcim_enable_device(pdev); | ||
754 | if (rc) | ||
755 | return rc; | ||
756 | |||
757 | rc = pcim_iomap_regions_request_all(pdev, 0x03, DRV_NAME); | ||
758 | if (rc) | ||
759 | return rc; | ||
760 | |||
761 | bars = pcim_iomap_table(pdev); | ||
762 | card->bar0 = bars[0]; | ||
763 | card->bar1 = bars[1]; | ||
764 | card->pdev = pdev; | ||
765 | |||
766 | rp2_decode_cap(id, &card->n_ports, &card->smpte); | ||
767 | dev_info(&pdev->dev, "found new card with %d ports\n", card->n_ports); | ||
768 | |||
769 | card->minor_start = rp2_alloc_ports(card->n_ports); | ||
770 | if (card->minor_start < 0) { | ||
771 | dev_err(&pdev->dev, | ||
772 | "too many ports (try increasing CONFIG_SERIAL_RP2_NR_UARTS)\n"); | ||
773 | return -EINVAL; | ||
774 | } | ||
775 | |||
776 | rp2_init_card(card); | ||
777 | |||
778 | ports = devm_kzalloc(&pdev->dev, sizeof(*ports) * card->n_ports, | ||
779 | GFP_KERNEL); | ||
780 | if (!ports) | ||
781 | return -ENOMEM; | ||
782 | card->ports = ports; | ||
783 | |||
784 | rc = devm_request_irq(&pdev->dev, pdev->irq, rp2_uart_interrupt, | ||
785 | IRQF_SHARED, DRV_NAME, card); | ||
786 | if (rc) | ||
787 | return rc; | ||
788 | |||
789 | /* | ||
790 | * Only catastrophic errors (e.g. ENOMEM) are reported here. | ||
791 | * If the FW image is missing, we'll find out in rp2_fw_cb() | ||
792 | * and print an error message. | ||
793 | */ | ||
794 | rc = request_firmware_nowait(THIS_MODULE, 1, RP2_FW_NAME, &pdev->dev, | ||
795 | GFP_KERNEL, card, rp2_fw_cb); | ||
796 | if (rc) | ||
797 | return rc; | ||
798 | dev_dbg(&pdev->dev, "waiting for firmware blob...\n"); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | static void rp2_remove(struct pci_dev *pdev) | ||
804 | { | ||
805 | struct rp2_card *card = pci_get_drvdata(pdev); | ||
806 | |||
807 | wait_for_completion(&card->fw_loaded); | ||
808 | rp2_remove_ports(card); | ||
809 | } | ||
810 | |||
811 | static DEFINE_PCI_DEVICE_TABLE(rp2_pci_tbl) = { | ||
812 | |||
813 | /* RocketPort INFINITY cards */ | ||
814 | |||
815 | { RP_ID(0x0040), RP_CAP(8, 0) }, /* INF Octa, RJ45, selectable */ | ||
816 | { RP_ID(0x0041), RP_CAP(32, 0) }, /* INF 32, ext interface */ | ||
817 | { RP_ID(0x0042), RP_CAP(8, 0) }, /* INF Octa, ext interface */ | ||
818 | { RP_ID(0x0043), RP_CAP(16, 0) }, /* INF 16, ext interface */ | ||
819 | { RP_ID(0x0044), RP_CAP(4, 0) }, /* INF Quad, DB, selectable */ | ||
820 | { RP_ID(0x0045), RP_CAP(8, 0) }, /* INF Octa, DB, selectable */ | ||
821 | { RP_ID(0x0046), RP_CAP(4, 0) }, /* INF Quad, ext interface */ | ||
822 | { RP_ID(0x0047), RP_CAP(4, 0) }, /* INF Quad, RJ45 */ | ||
823 | { RP_ID(0x004a), RP_CAP(4, 0) }, /* INF Plus, Quad */ | ||
824 | { RP_ID(0x004b), RP_CAP(8, 0) }, /* INF Plus, Octa */ | ||
825 | { RP_ID(0x004c), RP_CAP(8, 0) }, /* INF III, Octa */ | ||
826 | { RP_ID(0x004d), RP_CAP(4, 0) }, /* INF III, Quad */ | ||
827 | { RP_ID(0x004e), RP_CAP(2, 0) }, /* INF Plus, 2, RS232 */ | ||
828 | { RP_ID(0x004f), RP_CAP(2, 1) }, /* INF Plus, 2, SMPTE */ | ||
829 | { RP_ID(0x0050), RP_CAP(4, 0) }, /* INF Plus, Quad, RJ45 */ | ||
830 | { RP_ID(0x0051), RP_CAP(8, 0) }, /* INF Plus, Octa, RJ45 */ | ||
831 | { RP_ID(0x0052), RP_CAP(8, 1) }, /* INF Octa, SMPTE */ | ||
832 | |||
833 | /* RocketPort EXPRESS cards */ | ||
834 | |||
835 | { RP_ID(0x0060), RP_CAP(8, 0) }, /* EXP Octa, RJ45, selectable */ | ||
836 | { RP_ID(0x0061), RP_CAP(32, 0) }, /* EXP 32, ext interface */ | ||
837 | { RP_ID(0x0062), RP_CAP(8, 0) }, /* EXP Octa, ext interface */ | ||
838 | { RP_ID(0x0063), RP_CAP(16, 0) }, /* EXP 16, ext interface */ | ||
839 | { RP_ID(0x0064), RP_CAP(4, 0) }, /* EXP Quad, DB, selectable */ | ||
840 | { RP_ID(0x0065), RP_CAP(8, 0) }, /* EXP Octa, DB, selectable */ | ||
841 | { RP_ID(0x0066), RP_CAP(4, 0) }, /* EXP Quad, ext interface */ | ||
842 | { RP_ID(0x0067), RP_CAP(4, 0) }, /* EXP Quad, RJ45 */ | ||
843 | { RP_ID(0x0068), RP_CAP(8, 0) }, /* EXP Octa, RJ11 */ | ||
844 | { RP_ID(0x0072), RP_CAP(8, 1) }, /* EXP Octa, SMPTE */ | ||
845 | { } | ||
846 | }; | ||
847 | MODULE_DEVICE_TABLE(pci, rp2_pci_tbl); | ||
848 | |||
849 | static struct pci_driver rp2_pci_driver = { | ||
850 | .name = DRV_NAME, | ||
851 | .id_table = rp2_pci_tbl, | ||
852 | .probe = rp2_probe, | ||
853 | .remove = rp2_remove, | ||
854 | }; | ||
855 | |||
856 | static int __init rp2_uart_init(void) | ||
857 | { | ||
858 | int rc; | ||
859 | |||
860 | rc = uart_register_driver(&rp2_uart_driver); | ||
861 | if (rc) | ||
862 | return rc; | ||
863 | |||
864 | rc = pci_register_driver(&rp2_pci_driver); | ||
865 | if (rc) { | ||
866 | uart_unregister_driver(&rp2_uart_driver); | ||
867 | return rc; | ||
868 | } | ||
869 | |||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | static void __exit rp2_uart_exit(void) | ||
874 | { | ||
875 | pci_unregister_driver(&rp2_pci_driver); | ||
876 | uart_unregister_driver(&rp2_uart_driver); | ||
877 | } | ||
878 | |||
879 | module_init(rp2_uart_init); | ||
880 | module_exit(rp2_uart_exit); | ||
881 | |||
882 | MODULE_DESCRIPTION("Comtrol RocketPort EXPRESS/INFINITY driver"); | ||
883 | MODULE_AUTHOR("Kevin Cernekee <cernekee@gmail.com>"); | ||
884 | MODULE_LICENSE("GPL v2"); | ||
885 | MODULE_FIRMWARE(RP2_FW_NAME); | ||