diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-03-09 10:01:20 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-26 09:57:22 -0400 |
commit | b716d38c9b7c48e79ad94aa0b4aa749e7400a59d (patch) | |
tree | 0474092039ab40dfd25a2b127f374b20cfb5a4cc | |
parent | ece2ca9647bc6f7a17486ae2804014da8440d098 (diff) |
serial: remove tile uart driver
The tile architecture is getting removed, and this driver is
useless without it.
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | drivers/tty/serial/Kconfig | 9 | ||||
-rw-r--r-- | drivers/tty/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/tty/serial/tilegx.c | 689 |
3 files changed, 0 insertions, 699 deletions
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 1a48ae6abb2c..736720a8d84f 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -1330,15 +1330,6 @@ config SERIAL_EFM32_UART_CONSOLE | |||
1330 | depends on SERIAL_EFM32_UART=y | 1330 | depends on SERIAL_EFM32_UART=y |
1331 | select SERIAL_CORE_CONSOLE | 1331 | select SERIAL_CORE_CONSOLE |
1332 | 1332 | ||
1333 | config SERIAL_TILEGX | ||
1334 | tristate "TILE-Gx on-chip serial port support" | ||
1335 | depends on TILEGX | ||
1336 | select TILE_GXIO_UART | ||
1337 | select SERIAL_CORE | ||
1338 | ---help--- | ||
1339 | This device provides access to the on-chip UARTs on the TILE-Gx | ||
1340 | processor. | ||
1341 | |||
1342 | config SERIAL_ARC | 1333 | config SERIAL_ARC |
1343 | tristate "ARC UART driver support" | 1334 | tristate "ARC UART driver support" |
1344 | select SERIAL_CORE | 1335 | select SERIAL_CORE |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 606e746b61f1..b30ee2e5d518 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -63,7 +63,6 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o | |||
63 | obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o | 63 | obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o |
64 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | 64 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o |
65 | obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o | 65 | obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o |
66 | obj-$(CONFIG_SERIAL_TILEGX) += tilegx.o | ||
67 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o | 66 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o |
68 | obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o | 67 | obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o |
69 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o | 68 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o |
diff --git a/drivers/tty/serial/tilegx.c b/drivers/tty/serial/tilegx.c deleted file mode 100644 index f0a3ae57f881..000000000000 --- a/drivers/tty/serial/tilegx.c +++ /dev/null | |||
@@ -1,689 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Copyright 2013 Tilera Corporation. All Rights Reserved. | ||
4 | * | ||
5 | * TILEGx UART driver. | ||
6 | */ | ||
7 | |||
8 | #include <linux/delay.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/serial_core.h> | ||
15 | #include <linux/tty.h> | ||
16 | #include <linux/tty_flip.h> | ||
17 | |||
18 | #include <gxio/common.h> | ||
19 | #include <gxio/iorpc_globals.h> | ||
20 | #include <gxio/iorpc_uart.h> | ||
21 | #include <gxio/kiorpc.h> | ||
22 | |||
23 | #include <hv/drv_uart_intf.h> | ||
24 | |||
25 | /* | ||
26 | * Use device name ttyS, major 4, minor 64-65. | ||
27 | * This is the usual serial port name, 8250 conventional range. | ||
28 | */ | ||
29 | #define TILEGX_UART_MAJOR TTY_MAJOR | ||
30 | #define TILEGX_UART_MINOR 64 | ||
31 | #define TILEGX_UART_NAME "ttyS" | ||
32 | #define DRIVER_NAME_STRING "TILEGx_Serial" | ||
33 | #define TILEGX_UART_REF_CLK 125000000; /* REF_CLK is always 125 MHz. */ | ||
34 | |||
35 | struct tile_uart_port { | ||
36 | /* UART port. */ | ||
37 | struct uart_port uart; | ||
38 | |||
39 | /* GXIO device context. */ | ||
40 | gxio_uart_context_t context; | ||
41 | |||
42 | /* UART access mutex. */ | ||
43 | struct mutex mutex; | ||
44 | |||
45 | /* CPU receiving interrupts. */ | ||
46 | int irq_cpu; | ||
47 | }; | ||
48 | |||
49 | static struct tile_uart_port tile_uart_ports[TILEGX_UART_NR]; | ||
50 | static struct uart_driver tilegx_uart_driver; | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Read UART rx fifo, and insert the chars into tty buffer. | ||
55 | */ | ||
56 | static void receive_chars(struct tile_uart_port *tile_uart, | ||
57 | struct tty_struct *tty) | ||
58 | { | ||
59 | int i; | ||
60 | char c; | ||
61 | UART_FIFO_COUNT_t count; | ||
62 | gxio_uart_context_t *context = &tile_uart->context; | ||
63 | struct tty_port *port = tty->port; | ||
64 | |||
65 | count.word = gxio_uart_read(context, UART_FIFO_COUNT); | ||
66 | for (i = 0; i < count.rfifo_count; i++) { | ||
67 | c = (char)gxio_uart_read(context, UART_RECEIVE_DATA); | ||
68 | tty_insert_flip_char(port, c, TTY_NORMAL); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | |||
73 | /* | ||
74 | * Drain the Rx FIFO, called by interrupt handler. | ||
75 | */ | ||
76 | static void handle_receive(struct tile_uart_port *tile_uart) | ||
77 | { | ||
78 | struct tty_port *port = &tile_uart->uart.state->port; | ||
79 | struct tty_struct *tty = tty_port_tty_get(port); | ||
80 | gxio_uart_context_t *context = &tile_uart->context; | ||
81 | |||
82 | if (!tty) | ||
83 | return; | ||
84 | |||
85 | /* First read UART rx fifo. */ | ||
86 | receive_chars(tile_uart, tty); | ||
87 | |||
88 | /* Reset RFIFO_WE interrupt. */ | ||
89 | gxio_uart_write(context, UART_INTERRUPT_STATUS, | ||
90 | UART_INTERRUPT_MASK__RFIFO_WE_MASK); | ||
91 | |||
92 | /* Final read, if any chars comes between the first read and | ||
93 | * the interrupt reset. | ||
94 | */ | ||
95 | receive_chars(tile_uart, tty); | ||
96 | |||
97 | spin_unlock(&tile_uart->uart.lock); | ||
98 | tty_flip_buffer_push(port); | ||
99 | spin_lock(&tile_uart->uart.lock); | ||
100 | tty_kref_put(tty); | ||
101 | } | ||
102 | |||
103 | |||
104 | /* | ||
105 | * Push one char to UART Write FIFO. | ||
106 | * Return 0 on success, -1 if write filo is full. | ||
107 | */ | ||
108 | static int tilegx_putchar(gxio_uart_context_t *context, char c) | ||
109 | { | ||
110 | UART_FLAG_t flag; | ||
111 | flag.word = gxio_uart_read(context, UART_FLAG); | ||
112 | if (flag.wfifo_full) | ||
113 | return -1; | ||
114 | |||
115 | gxio_uart_write(context, UART_TRANSMIT_DATA, (unsigned long)c); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | |||
120 | /* | ||
121 | * Send chars to UART Write FIFO; called by interrupt handler. | ||
122 | */ | ||
123 | static void handle_transmit(struct tile_uart_port *tile_uart) | ||
124 | { | ||
125 | unsigned char ch; | ||
126 | struct uart_port *port; | ||
127 | struct circ_buf *xmit; | ||
128 | gxio_uart_context_t *context = &tile_uart->context; | ||
129 | |||
130 | /* First reset WFIFO_RE interrupt. */ | ||
131 | gxio_uart_write(context, UART_INTERRUPT_STATUS, | ||
132 | UART_INTERRUPT_MASK__WFIFO_RE_MASK); | ||
133 | |||
134 | port = &tile_uart->uart; | ||
135 | xmit = &port->state->xmit; | ||
136 | if (port->x_char) { | ||
137 | if (tilegx_putchar(context, port->x_char)) | ||
138 | return; | ||
139 | port->x_char = 0; | ||
140 | port->icount.tx++; | ||
141 | } | ||
142 | |||
143 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | ||
144 | return; | ||
145 | |||
146 | while (!uart_circ_empty(xmit)) { | ||
147 | ch = xmit->buf[xmit->tail]; | ||
148 | if (tilegx_putchar(context, ch)) | ||
149 | break; | ||
150 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
151 | port->icount.tx++; | ||
152 | } | ||
153 | |||
154 | /* Reset WFIFO_RE interrupt. */ | ||
155 | gxio_uart_write(context, UART_INTERRUPT_STATUS, | ||
156 | UART_INTERRUPT_MASK__WFIFO_RE_MASK); | ||
157 | |||
158 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
159 | uart_write_wakeup(port); | ||
160 | } | ||
161 | |||
162 | |||
163 | /* | ||
164 | * UART Interrupt handler. | ||
165 | */ | ||
166 | static irqreturn_t tilegx_interrupt(int irq, void *dev_id) | ||
167 | { | ||
168 | unsigned long flags; | ||
169 | UART_INTERRUPT_STATUS_t intr_stat; | ||
170 | struct tile_uart_port *tile_uart; | ||
171 | gxio_uart_context_t *context; | ||
172 | struct uart_port *port = dev_id; | ||
173 | irqreturn_t ret = IRQ_NONE; | ||
174 | |||
175 | spin_lock_irqsave(&port->lock, flags); | ||
176 | |||
177 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
178 | context = &tile_uart->context; | ||
179 | intr_stat.word = gxio_uart_read(context, UART_INTERRUPT_STATUS); | ||
180 | |||
181 | if (intr_stat.rfifo_we) { | ||
182 | handle_receive(tile_uart); | ||
183 | ret = IRQ_HANDLED; | ||
184 | } | ||
185 | if (intr_stat.wfifo_re) { | ||
186 | handle_transmit(tile_uart); | ||
187 | ret = IRQ_HANDLED; | ||
188 | } | ||
189 | |||
190 | spin_unlock_irqrestore(&port->lock, flags); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | |||
195 | /* | ||
196 | * Return TIOCSER_TEMT when transmitter FIFO is empty. | ||
197 | */ | ||
198 | static u_int tilegx_tx_empty(struct uart_port *port) | ||
199 | { | ||
200 | int ret; | ||
201 | UART_FLAG_t flag; | ||
202 | struct tile_uart_port *tile_uart; | ||
203 | gxio_uart_context_t *context; | ||
204 | |||
205 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
206 | if (!mutex_trylock(&tile_uart->mutex)) | ||
207 | return 0; | ||
208 | context = &tile_uart->context; | ||
209 | |||
210 | flag.word = gxio_uart_read(context, UART_FLAG); | ||
211 | ret = (flag.wfifo_empty) ? TIOCSER_TEMT : 0; | ||
212 | mutex_unlock(&tile_uart->mutex); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | |||
218 | /* | ||
219 | * Set state of the modem control output lines. | ||
220 | */ | ||
221 | static void tilegx_set_mctrl(struct uart_port *port, u_int mctrl) | ||
222 | { | ||
223 | /* N/A */ | ||
224 | } | ||
225 | |||
226 | |||
227 | /* | ||
228 | * Get state of the modem control input lines. | ||
229 | */ | ||
230 | static u_int tilegx_get_mctrl(struct uart_port *port) | ||
231 | { | ||
232 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
233 | } | ||
234 | |||
235 | |||
236 | /* | ||
237 | * Stop transmitting. | ||
238 | */ | ||
239 | static void tilegx_stop_tx(struct uart_port *port) | ||
240 | { | ||
241 | /* N/A */ | ||
242 | } | ||
243 | |||
244 | |||
245 | /* | ||
246 | * Start transmitting. | ||
247 | */ | ||
248 | static void tilegx_start_tx(struct uart_port *port) | ||
249 | { | ||
250 | unsigned char ch; | ||
251 | struct circ_buf *xmit; | ||
252 | struct tile_uart_port *tile_uart; | ||
253 | gxio_uart_context_t *context; | ||
254 | |||
255 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
256 | if (!mutex_trylock(&tile_uart->mutex)) | ||
257 | return; | ||
258 | context = &tile_uart->context; | ||
259 | xmit = &port->state->xmit; | ||
260 | if (port->x_char) { | ||
261 | if (tilegx_putchar(context, port->x_char)) | ||
262 | return; | ||
263 | port->x_char = 0; | ||
264 | port->icount.tx++; | ||
265 | } | ||
266 | |||
267 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
268 | mutex_unlock(&tile_uart->mutex); | ||
269 | return; | ||
270 | } | ||
271 | |||
272 | while (!uart_circ_empty(xmit)) { | ||
273 | ch = xmit->buf[xmit->tail]; | ||
274 | if (tilegx_putchar(context, ch)) | ||
275 | break; | ||
276 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
277 | port->icount.tx++; | ||
278 | } | ||
279 | |||
280 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
281 | uart_write_wakeup(port); | ||
282 | |||
283 | mutex_unlock(&tile_uart->mutex); | ||
284 | } | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Stop receiving - port is in process of being closed. | ||
289 | */ | ||
290 | static void tilegx_stop_rx(struct uart_port *port) | ||
291 | { | ||
292 | int err; | ||
293 | struct tile_uart_port *tile_uart; | ||
294 | gxio_uart_context_t *context; | ||
295 | int cpu; | ||
296 | |||
297 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
298 | if (!mutex_trylock(&tile_uart->mutex)) | ||
299 | return; | ||
300 | |||
301 | context = &tile_uart->context; | ||
302 | cpu = tile_uart->irq_cpu; | ||
303 | err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), | ||
304 | KERNEL_PL, -1); | ||
305 | mutex_unlock(&tile_uart->mutex); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * Control the transmission of a break signal. | ||
310 | */ | ||
311 | static void tilegx_break_ctl(struct uart_port *port, int break_state) | ||
312 | { | ||
313 | /* N/A */ | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * Perform initialization and enable port for reception. | ||
319 | */ | ||
320 | static int tilegx_startup(struct uart_port *port) | ||
321 | { | ||
322 | struct tile_uart_port *tile_uart; | ||
323 | gxio_uart_context_t *context; | ||
324 | int ret = 0; | ||
325 | int cpu = raw_smp_processor_id(); /* pick an arbitrary cpu */ | ||
326 | |||
327 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
328 | if (mutex_lock_interruptible(&tile_uart->mutex)) | ||
329 | return -EBUSY; | ||
330 | context = &tile_uart->context; | ||
331 | |||
332 | /* Now open the hypervisor device if we haven't already. */ | ||
333 | if (context->fd < 0) { | ||
334 | UART_INTERRUPT_MASK_t intr_mask; | ||
335 | |||
336 | /* Initialize UART device. */ | ||
337 | ret = gxio_uart_init(context, port->line); | ||
338 | if (ret) { | ||
339 | ret = -ENXIO; | ||
340 | goto err; | ||
341 | } | ||
342 | |||
343 | /* Create our IRQs. */ | ||
344 | port->irq = irq_alloc_hwirq(-1); | ||
345 | if (!port->irq) | ||
346 | goto err_uart_dest; | ||
347 | tile_irq_activate(port->irq, TILE_IRQ_PERCPU); | ||
348 | |||
349 | /* Register our IRQs. */ | ||
350 | ret = request_irq(port->irq, tilegx_interrupt, 0, | ||
351 | tilegx_uart_driver.driver_name, port); | ||
352 | if (ret) | ||
353 | goto err_dest_irq; | ||
354 | |||
355 | /* Request that the hardware start sending us interrupts. */ | ||
356 | tile_uart->irq_cpu = cpu; | ||
357 | ret = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), | ||
358 | KERNEL_PL, port->irq); | ||
359 | if (ret) | ||
360 | goto err_free_irq; | ||
361 | |||
362 | /* Enable UART Tx/Rx Interrupt. */ | ||
363 | intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); | ||
364 | intr_mask.wfifo_re = 0; | ||
365 | intr_mask.rfifo_we = 0; | ||
366 | gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); | ||
367 | |||
368 | /* Reset the Tx/Rx interrupt in case it's set. */ | ||
369 | gxio_uart_write(context, UART_INTERRUPT_STATUS, | ||
370 | UART_INTERRUPT_MASK__WFIFO_RE_MASK | | ||
371 | UART_INTERRUPT_MASK__RFIFO_WE_MASK); | ||
372 | } | ||
373 | |||
374 | mutex_unlock(&tile_uart->mutex); | ||
375 | return ret; | ||
376 | |||
377 | err_free_irq: | ||
378 | free_irq(port->irq, port); | ||
379 | err_dest_irq: | ||
380 | irq_free_hwirq(port->irq); | ||
381 | err_uart_dest: | ||
382 | gxio_uart_destroy(context); | ||
383 | ret = -ENXIO; | ||
384 | err: | ||
385 | mutex_unlock(&tile_uart->mutex); | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | |||
390 | /* | ||
391 | * Release kernel resources if it is the last close, disable the port, | ||
392 | * free IRQ and close the port. | ||
393 | */ | ||
394 | static void tilegx_shutdown(struct uart_port *port) | ||
395 | { | ||
396 | int err; | ||
397 | UART_INTERRUPT_MASK_t intr_mask; | ||
398 | struct tile_uart_port *tile_uart; | ||
399 | gxio_uart_context_t *context; | ||
400 | int cpu; | ||
401 | |||
402 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
403 | if (mutex_lock_interruptible(&tile_uart->mutex)) | ||
404 | return; | ||
405 | context = &tile_uart->context; | ||
406 | |||
407 | /* Disable UART Tx/Rx Interrupt. */ | ||
408 | intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); | ||
409 | intr_mask.wfifo_re = 1; | ||
410 | intr_mask.rfifo_we = 1; | ||
411 | gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); | ||
412 | |||
413 | /* Request that the hardware stop sending us interrupts. */ | ||
414 | cpu = tile_uart->irq_cpu; | ||
415 | err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), | ||
416 | KERNEL_PL, -1); | ||
417 | |||
418 | if (port->irq > 0) { | ||
419 | free_irq(port->irq, port); | ||
420 | irq_free_hwirq(port->irq); | ||
421 | port->irq = 0; | ||
422 | } | ||
423 | |||
424 | gxio_uart_destroy(context); | ||
425 | |||
426 | mutex_unlock(&tile_uart->mutex); | ||
427 | } | ||
428 | |||
429 | |||
430 | /* | ||
431 | * Flush the buffer. | ||
432 | */ | ||
433 | static void tilegx_flush_buffer(struct uart_port *port) | ||
434 | { | ||
435 | /* N/A */ | ||
436 | } | ||
437 | |||
438 | |||
439 | /* | ||
440 | * Change the port parameters. | ||
441 | */ | ||
442 | static void tilegx_set_termios(struct uart_port *port, | ||
443 | struct ktermios *termios, struct ktermios *old) | ||
444 | { | ||
445 | int err; | ||
446 | UART_DIVISOR_t divisor; | ||
447 | UART_TYPE_t type; | ||
448 | unsigned int baud; | ||
449 | struct tile_uart_port *tile_uart; | ||
450 | gxio_uart_context_t *context; | ||
451 | |||
452 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
453 | if (!mutex_trylock(&tile_uart->mutex)) | ||
454 | return; | ||
455 | context = &tile_uart->context; | ||
456 | |||
457 | /* Open the hypervisor device if we haven't already. */ | ||
458 | if (context->fd < 0) { | ||
459 | err = gxio_uart_init(context, port->line); | ||
460 | if (err) { | ||
461 | mutex_unlock(&tile_uart->mutex); | ||
462 | return; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | divisor.word = gxio_uart_read(context, UART_DIVISOR); | ||
467 | type.word = gxio_uart_read(context, UART_TYPE); | ||
468 | |||
469 | /* Divisor. */ | ||
470 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | ||
471 | divisor.divisor = uart_get_divisor(port, baud); | ||
472 | |||
473 | /* Byte size. */ | ||
474 | if ((termios->c_cflag & CSIZE) == CS7) | ||
475 | type.dbits = UART_TYPE__DBITS_VAL_SEVEN_DBITS; | ||
476 | else | ||
477 | type.dbits = UART_TYPE__DBITS_VAL_EIGHT_DBITS; | ||
478 | |||
479 | /* Parity. */ | ||
480 | if (termios->c_cflag & PARENB) { | ||
481 | /* Mark or Space parity. */ | ||
482 | if (termios->c_cflag & CMSPAR) | ||
483 | if (termios->c_cflag & PARODD) | ||
484 | type.ptype = UART_TYPE__PTYPE_VAL_MARK; | ||
485 | else | ||
486 | type.ptype = UART_TYPE__PTYPE_VAL_SPACE; | ||
487 | else if (termios->c_cflag & PARODD) | ||
488 | type.ptype = UART_TYPE__PTYPE_VAL_ODD; | ||
489 | else | ||
490 | type.ptype = UART_TYPE__PTYPE_VAL_EVEN; | ||
491 | } else | ||
492 | type.ptype = UART_TYPE__PTYPE_VAL_NONE; | ||
493 | |||
494 | /* Stop bits. */ | ||
495 | if (termios->c_cflag & CSTOPB) | ||
496 | type.sbits = UART_TYPE__SBITS_VAL_TWO_SBITS; | ||
497 | else | ||
498 | type.sbits = UART_TYPE__SBITS_VAL_ONE_SBITS; | ||
499 | |||
500 | /* Set the uart paramters. */ | ||
501 | gxio_uart_write(context, UART_DIVISOR, divisor.word); | ||
502 | gxio_uart_write(context, UART_TYPE, type.word); | ||
503 | |||
504 | mutex_unlock(&tile_uart->mutex); | ||
505 | } | ||
506 | |||
507 | |||
508 | /* | ||
509 | * Return string describing the specified port. | ||
510 | */ | ||
511 | static const char *tilegx_type(struct uart_port *port) | ||
512 | { | ||
513 | return port->type == PORT_TILEGX ? DRIVER_NAME_STRING : NULL; | ||
514 | } | ||
515 | |||
516 | |||
517 | /* | ||
518 | * Release the resources being used by 'port'. | ||
519 | */ | ||
520 | static void tilegx_release_port(struct uart_port *port) | ||
521 | { | ||
522 | /* Nothing to release. */ | ||
523 | } | ||
524 | |||
525 | |||
526 | /* | ||
527 | * Request the resources being used by 'port'. | ||
528 | */ | ||
529 | static int tilegx_request_port(struct uart_port *port) | ||
530 | { | ||
531 | /* Always present. */ | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | |||
536 | /* | ||
537 | * Configure/autoconfigure the port. | ||
538 | */ | ||
539 | static void tilegx_config_port(struct uart_port *port, int flags) | ||
540 | { | ||
541 | if (flags & UART_CONFIG_TYPE) | ||
542 | port->type = PORT_TILEGX; | ||
543 | } | ||
544 | |||
545 | |||
546 | /* | ||
547 | * Verify the new serial_struct (for TIOCSSERIAL). | ||
548 | */ | ||
549 | static int tilegx_verify_port(struct uart_port *port, | ||
550 | struct serial_struct *ser) | ||
551 | { | ||
552 | if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_TILEGX)) | ||
553 | return -EINVAL; | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | #ifdef CONFIG_CONSOLE_POLL | ||
559 | |||
560 | /* | ||
561 | * Console polling routines for writing and reading from the uart while | ||
562 | * in an interrupt or debug context. | ||
563 | */ | ||
564 | |||
565 | static int tilegx_poll_get_char(struct uart_port *port) | ||
566 | { | ||
567 | UART_FIFO_COUNT_t count; | ||
568 | gxio_uart_context_t *context; | ||
569 | struct tile_uart_port *tile_uart; | ||
570 | |||
571 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
572 | context = &tile_uart->context; | ||
573 | count.word = gxio_uart_read(context, UART_FIFO_COUNT); | ||
574 | if (count.rfifo_count == 0) | ||
575 | return NO_POLL_CHAR; | ||
576 | return (char)gxio_uart_read(context, UART_RECEIVE_DATA); | ||
577 | } | ||
578 | |||
579 | static void tilegx_poll_put_char(struct uart_port *port, unsigned char c) | ||
580 | { | ||
581 | gxio_uart_context_t *context; | ||
582 | struct tile_uart_port *tile_uart; | ||
583 | |||
584 | tile_uart = container_of(port, struct tile_uart_port, uart); | ||
585 | context = &tile_uart->context; | ||
586 | gxio_uart_write(context, UART_TRANSMIT_DATA, (unsigned long)c); | ||
587 | } | ||
588 | |||
589 | #endif /* CONFIG_CONSOLE_POLL */ | ||
590 | |||
591 | |||
592 | static const struct uart_ops tilegx_ops = { | ||
593 | .tx_empty = tilegx_tx_empty, | ||
594 | .set_mctrl = tilegx_set_mctrl, | ||
595 | .get_mctrl = tilegx_get_mctrl, | ||
596 | .stop_tx = tilegx_stop_tx, | ||
597 | .start_tx = tilegx_start_tx, | ||
598 | .stop_rx = tilegx_stop_rx, | ||
599 | .break_ctl = tilegx_break_ctl, | ||
600 | .startup = tilegx_startup, | ||
601 | .shutdown = tilegx_shutdown, | ||
602 | .flush_buffer = tilegx_flush_buffer, | ||
603 | .set_termios = tilegx_set_termios, | ||
604 | .type = tilegx_type, | ||
605 | .release_port = tilegx_release_port, | ||
606 | .request_port = tilegx_request_port, | ||
607 | .config_port = tilegx_config_port, | ||
608 | .verify_port = tilegx_verify_port, | ||
609 | #ifdef CONFIG_CONSOLE_POLL | ||
610 | .poll_get_char = tilegx_poll_get_char, | ||
611 | .poll_put_char = tilegx_poll_put_char, | ||
612 | #endif | ||
613 | }; | ||
614 | |||
615 | |||
616 | static void tilegx_init_ports(void) | ||
617 | { | ||
618 | int i; | ||
619 | struct uart_port *port; | ||
620 | |||
621 | for (i = 0; i < TILEGX_UART_NR; i++) { | ||
622 | port = &tile_uart_ports[i].uart; | ||
623 | port->ops = &tilegx_ops; | ||
624 | port->line = i; | ||
625 | port->type = PORT_TILEGX; | ||
626 | port->uartclk = TILEGX_UART_REF_CLK; | ||
627 | port->flags = UPF_BOOT_AUTOCONF; | ||
628 | |||
629 | tile_uart_ports[i].context.fd = -1; | ||
630 | mutex_init(&tile_uart_ports[i].mutex); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | |||
635 | static struct uart_driver tilegx_uart_driver = { | ||
636 | .owner = THIS_MODULE, | ||
637 | .driver_name = DRIVER_NAME_STRING, | ||
638 | .dev_name = TILEGX_UART_NAME, | ||
639 | .major = TILEGX_UART_MAJOR, | ||
640 | .minor = TILEGX_UART_MINOR, | ||
641 | .nr = TILEGX_UART_NR, | ||
642 | }; | ||
643 | |||
644 | |||
645 | static int __init tilegx_init(void) | ||
646 | { | ||
647 | int i; | ||
648 | int ret; | ||
649 | struct tty_driver *tty_drv; | ||
650 | |||
651 | ret = uart_register_driver(&tilegx_uart_driver); | ||
652 | if (ret) | ||
653 | return ret; | ||
654 | tty_drv = tilegx_uart_driver.tty_driver; | ||
655 | tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; | ||
656 | tty_drv->init_termios.c_ispeed = 115200; | ||
657 | tty_drv->init_termios.c_ospeed = 115200; | ||
658 | |||
659 | tilegx_init_ports(); | ||
660 | |||
661 | for (i = 0; i < TILEGX_UART_NR; i++) { | ||
662 | struct uart_port *port = &tile_uart_ports[i].uart; | ||
663 | ret = uart_add_one_port(&tilegx_uart_driver, port); | ||
664 | } | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | |||
670 | static void __exit tilegx_exit(void) | ||
671 | { | ||
672 | int i; | ||
673 | struct uart_port *port; | ||
674 | |||
675 | for (i = 0; i < TILEGX_UART_NR; i++) { | ||
676 | port = &tile_uart_ports[i].uart; | ||
677 | uart_remove_one_port(&tilegx_uart_driver, port); | ||
678 | } | ||
679 | |||
680 | uart_unregister_driver(&tilegx_uart_driver); | ||
681 | } | ||
682 | |||
683 | |||
684 | module_init(tilegx_init); | ||
685 | module_exit(tilegx_exit); | ||
686 | |||
687 | MODULE_AUTHOR("Tilera Corporation"); | ||
688 | MODULE_DESCRIPTION("TILEGx serial port driver"); | ||
689 | MODULE_LICENSE("GPL"); | ||