Linux Audio

Check our new training course

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