File Index
Files and directories
Sign in
FILE

altera_uart.c

File preview with syntax highlighting.

linux-6.19.14/drivers/tty/serial/altera_uart.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * altera_uart.c -- Altera UART driver
  4 *
  5 * Based on mcf.c -- Freescale ColdFire UART driver
  6 *
  7 * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
  8 * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
  9 * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
 10 */
 11
 12#include <linux/kernel.h>
 13#include <linux/init.h>
 14#include <linux/timer.h>
 15#include <linux/interrupt.h>
 16#include <linux/module.h>
 17#include <linux/console.h>
 18#include <linux/tty.h>
 19#include <linux/tty_flip.h>
 20#include <linux/serial.h>
 21#include <linux/serial_core.h>
 22#include <linux/platform_device.h>
 23#include <linux/of.h>
 24#include <linux/io.h>
 25#include <linux/altera_uart.h>
 26
 27#define SERIAL_ALTERA_MAJOR 204
 28#define SERIAL_ALTERA_MINOR 213
 29
 30/*
 31 * Altera UART register definitions according to the Nios UART datasheet:
 32 * http://www.altera.com/literature/ds/ds_nios_uart.pdf
 33 */
 34
 35#define ALTERA_UART_SIZE		32
 36
 37#define ALTERA_UART_RXDATA_REG		0
 38#define ALTERA_UART_TXDATA_REG		4
 39#define ALTERA_UART_STATUS_REG		8
 40#define ALTERA_UART_CONTROL_REG		12
 41#define ALTERA_UART_DIVISOR_REG		16
 42#define ALTERA_UART_EOP_REG		20
 43
 44#define ALTERA_UART_STATUS_PE_MSK	0x0001	/* parity error */
 45#define ALTERA_UART_STATUS_FE_MSK	0x0002	/* framing error */
 46#define ALTERA_UART_STATUS_BRK_MSK	0x0004	/* break */
 47#define ALTERA_UART_STATUS_ROE_MSK	0x0008	/* RX overrun error */
 48#define ALTERA_UART_STATUS_TOE_MSK	0x0010	/* TX overrun error */
 49#define ALTERA_UART_STATUS_TMT_MSK	0x0020	/* TX shift register state */
 50#define ALTERA_UART_STATUS_TRDY_MSK	0x0040	/* TX ready */
 51#define ALTERA_UART_STATUS_RRDY_MSK	0x0080	/* RX ready */
 52#define ALTERA_UART_STATUS_E_MSK	0x0100	/* exception condition */
 53#define ALTERA_UART_STATUS_DCTS_MSK	0x0400	/* CTS logic-level change */
 54#define ALTERA_UART_STATUS_CTS_MSK	0x0800	/* CTS logic state */
 55#define ALTERA_UART_STATUS_EOP_MSK	0x1000	/* EOP written/read */
 56
 57						/* Enable interrupt on... */
 58#define ALTERA_UART_CONTROL_PE_MSK	0x0001	/* ...parity error */
 59#define ALTERA_UART_CONTROL_FE_MSK	0x0002	/* ...framing error */
 60#define ALTERA_UART_CONTROL_BRK_MSK	0x0004	/* ...break */
 61#define ALTERA_UART_CONTROL_ROE_MSK	0x0008	/* ...RX overrun */
 62#define ALTERA_UART_CONTROL_TOE_MSK	0x0010	/* ...TX overrun */
 63#define ALTERA_UART_CONTROL_TMT_MSK	0x0020	/* ...TX shift register empty */
 64#define ALTERA_UART_CONTROL_TRDY_MSK	0x0040	/* ...TX ready */
 65#define ALTERA_UART_CONTROL_RRDY_MSK	0x0080	/* ...RX ready */
 66#define ALTERA_UART_CONTROL_E_MSK	0x0100	/* ...exception*/
 67
 68#define ALTERA_UART_CONTROL_TRBK_MSK	0x0200	/* TX break */
 69#define ALTERA_UART_CONTROL_DCTS_MSK	0x0400	/* Interrupt on CTS change */
 70#define ALTERA_UART_CONTROL_RTS_MSK	0x0800	/* RTS signal */
 71#define ALTERA_UART_CONTROL_EOP_MSK	0x1000	/* Interrupt on EOP */
 72
 73/*
 74 * Local per-uart structure.
 75 */
 76struct altera_uart {
 77	struct uart_port port;
 78	struct timer_list tmr;
 79	unsigned int sigs;	/* Local copy of line sigs */
 80	unsigned short imr;	/* Local IMR mirror */
 81};
 82
 83static u32 altera_uart_readl(struct uart_port *port, int reg)
 84{
 85	return readl(port->membase + (reg << port->regshift));
 86}
 87
 88static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
 89{
 90	writel(dat, port->membase + (reg << port->regshift));
 91}
 92
 93static unsigned int altera_uart_tx_empty(struct uart_port *port)
 94{
 95	return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 96		ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
 97}
 98
 99static unsigned int altera_uart_get_mctrl(struct uart_port *port)
100{
101	struct altera_uart *pp = container_of(port, struct altera_uart, port);
102	unsigned int sigs;
103
104	sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
105	     ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
106	sigs |= (pp->sigs & TIOCM_RTS);
107
108	return sigs;
109}
110
111static void altera_uart_update_ctrl_reg(struct altera_uart *pp)
112{
113	unsigned short imr = pp->imr;
114
115	/*
116	 * If the device doesn't have an irq, ensure that the irq bits are
117	 * masked out to keep the irq line inactive.
118	 */
119	if (!pp->port.irq)
120		imr &= ALTERA_UART_CONTROL_TRBK_MSK | ALTERA_UART_CONTROL_RTS_MSK;
121
122	altera_uart_writel(&pp->port, imr, ALTERA_UART_CONTROL_REG);
123}
124
125static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
126{
127	struct altera_uart *pp = container_of(port, struct altera_uart, port);
128
129	pp->sigs = sigs;
130	if (sigs & TIOCM_RTS)
131		pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
132	else
133		pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
134	altera_uart_update_ctrl_reg(pp);
135}
136
137static void altera_uart_start_tx(struct uart_port *port)
138{
139	struct altera_uart *pp = container_of(port, struct altera_uart, port);
140
141	pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
142	altera_uart_update_ctrl_reg(pp);
143}
144
145static void altera_uart_stop_tx(struct uart_port *port)
146{
147	struct altera_uart *pp = container_of(port, struct altera_uart, port);
148
149	pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
150	altera_uart_update_ctrl_reg(pp);
151}
152
153static void altera_uart_stop_rx(struct uart_port *port)
154{
155	struct altera_uart *pp = container_of(port, struct altera_uart, port);
156
157	pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
158	altera_uart_update_ctrl_reg(pp);
159}
160
161static void altera_uart_break_ctl(struct uart_port *port, int break_state)
162{
163	struct altera_uart *pp = container_of(port, struct altera_uart, port);
164	unsigned long flags;
165
166	uart_port_lock_irqsave(port, &flags);
167	if (break_state == -1)
168		pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
169	else
170		pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
171	altera_uart_update_ctrl_reg(pp);
172	uart_port_unlock_irqrestore(port, flags);
173}
174
175static void altera_uart_set_termios(struct uart_port *port,
176				    struct ktermios *termios,
177				    const struct ktermios *old)
178{
179	unsigned long flags;
180	unsigned int baud, baudclk;
181
182	baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
183	baudclk = port->uartclk / baud;
184
185	if (old)
186		tty_termios_copy_hw(termios, old);
187	tty_termios_encode_baud_rate(termios, baud, baud);
188
189	uart_port_lock_irqsave(port, &flags);
190	uart_update_timeout(port, termios->c_cflag, baud);
191	altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
192	uart_port_unlock_irqrestore(port, flags);
193
194	/*
195	 * FIXME: port->read_status_mask and port->ignore_status_mask
196	 * need to be initialized based on termios settings for
197	 * INPCK, IGNBRK, IGNPAR, PARMRK, BRKINT
198	 */
199}
200
201static void altera_uart_rx_chars(struct uart_port *port)
202{
203	unsigned short status;
204	u8 ch, flag;
205
206	while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
207	       ALTERA_UART_STATUS_RRDY_MSK) {
208		ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
209		flag = TTY_NORMAL;
210		port->icount.rx++;
211
212		if (status & ALTERA_UART_STATUS_E_MSK) {
213			altera_uart_writel(port, status,
214					   ALTERA_UART_STATUS_REG);
215
216			if (status & ALTERA_UART_STATUS_BRK_MSK) {
217				port->icount.brk++;
218				if (uart_handle_break(port))
219					continue;
220			} else if (status & ALTERA_UART_STATUS_PE_MSK) {
221				port->icount.parity++;
222			} else if (status & ALTERA_UART_STATUS_ROE_MSK) {
223				port->icount.overrun++;
224			} else if (status & ALTERA_UART_STATUS_FE_MSK) {
225				port->icount.frame++;
226			}
227
228			status &= port->read_status_mask;
229
230			if (status & ALTERA_UART_STATUS_BRK_MSK)
231				flag = TTY_BREAK;
232			else if (status & ALTERA_UART_STATUS_PE_MSK)
233				flag = TTY_PARITY;
234			else if (status & ALTERA_UART_STATUS_FE_MSK)
235				flag = TTY_FRAME;
236		}
237
238		if (uart_handle_sysrq_char(port, ch))
239			continue;
240		uart_insert_char(port, status, ALTERA_UART_STATUS_ROE_MSK, ch,
241				 flag);
242	}
243
244	tty_flip_buffer_push(&port->state->port);
245}
246
247static void altera_uart_tx_chars(struct uart_port *port)
248{
249	u8 ch;
250
251	uart_port_tx(port, ch,
252		altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
253		                ALTERA_UART_STATUS_TRDY_MSK,
254		altera_uart_writel(port, ch, ALTERA_UART_TXDATA_REG));
255}
256
257static irqreturn_t altera_uart_interrupt(int irq, void *data)
258{
259	struct uart_port *port = data;
260	struct altera_uart *pp = container_of(port, struct altera_uart, port);
261	unsigned long flags;
262	unsigned int isr;
263
264	isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
265
266	uart_port_lock_irqsave(port, &flags);
267	if (isr & ALTERA_UART_STATUS_RRDY_MSK)
268		altera_uart_rx_chars(port);
269	if (isr & ALTERA_UART_STATUS_TRDY_MSK)
270		altera_uart_tx_chars(port);
271	uart_port_unlock_irqrestore(port, flags);
272
273	return IRQ_RETVAL(isr);
274}
275
276static void altera_uart_timer(struct timer_list *t)
277{
278	struct altera_uart *pp = timer_container_of(pp, t, tmr);
279	struct uart_port *port = &pp->port;
280
281	altera_uart_interrupt(0, port);
282	mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
283}
284
285static void altera_uart_config_port(struct uart_port *port, int flags)
286{
287	port->type = PORT_ALTERA_UART;
288
289	/* Clear mask, so no surprise interrupts. */
290	altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
291	/* Clear status register */
292	altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
293}
294
295static int altera_uart_startup(struct uart_port *port)
296{
297	struct altera_uart *pp = container_of(port, struct altera_uart, port);
298	unsigned long flags;
299
300	if (!port->irq) {
301		timer_setup(&pp->tmr, altera_uart_timer, 0);
302		mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
303	} else {
304		int ret;
305
306		ret = request_irq(port->irq, altera_uart_interrupt, 0,
307				dev_name(port->dev), port);
308		if (ret) {
309			dev_err(port->dev, "unable to attach Altera UART %d interrupt vector=%d\n",
310				port->line, port->irq);
311			return ret;
312		}
313	}
314
315	uart_port_lock_irqsave(port, &flags);
316
317	/* Enable RX interrupts now */
318	pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
319	altera_uart_update_ctrl_reg(pp);
320
321	uart_port_unlock_irqrestore(port, flags);
322
323	return 0;
324}
325
326static void altera_uart_shutdown(struct uart_port *port)
327{
328	struct altera_uart *pp = container_of(port, struct altera_uart, port);
329	unsigned long flags;
330
331	uart_port_lock_irqsave(port, &flags);
332
333	/* Disable all interrupts now */
334	pp->imr = 0;
335	altera_uart_update_ctrl_reg(pp);
336
337	uart_port_unlock_irqrestore(port, flags);
338
339	if (port->irq)
340		free_irq(port->irq, port);
341	else
342		timer_delete_sync(&pp->tmr);
343}
344
345static const char *altera_uart_type(struct uart_port *port)
346{
347	return (port->type == PORT_ALTERA_UART) ? "Altera UART" : NULL;
348}
349
350static int altera_uart_request_port(struct uart_port *port)
351{
352	/* UARTs always present */
353	return 0;
354}
355
356static void altera_uart_release_port(struct uart_port *port)
357{
358	/* Nothing to release... */
359}
360
361static int altera_uart_verify_port(struct uart_port *port,
362				   struct serial_struct *ser)
363{
364	if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_ALTERA_UART))
365		return -EINVAL;
366	return 0;
367}
368
369#ifdef CONFIG_CONSOLE_POLL
370static int altera_uart_poll_get_char(struct uart_port *port)
371{
372	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
373		 ALTERA_UART_STATUS_RRDY_MSK))
374		cpu_relax();
375
376	return altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
377}
378
379static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c)
380{
381	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
382		 ALTERA_UART_STATUS_TRDY_MSK))
383		cpu_relax();
384
385	altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG);
386}
387#endif
388
389/*
390 *	Define the basic serial functions we support.
391 */
392static const struct uart_ops altera_uart_ops = {
393	.tx_empty	= altera_uart_tx_empty,
394	.get_mctrl	= altera_uart_get_mctrl,
395	.set_mctrl	= altera_uart_set_mctrl,
396	.start_tx	= altera_uart_start_tx,
397	.stop_tx	= altera_uart_stop_tx,
398	.stop_rx	= altera_uart_stop_rx,
399	.break_ctl	= altera_uart_break_ctl,
400	.startup	= altera_uart_startup,
401	.shutdown	= altera_uart_shutdown,
402	.set_termios	= altera_uart_set_termios,
403	.type		= altera_uart_type,
404	.request_port	= altera_uart_request_port,
405	.release_port	= altera_uart_release_port,
406	.config_port	= altera_uart_config_port,
407	.verify_port	= altera_uart_verify_port,
408#ifdef CONFIG_CONSOLE_POLL
409	.poll_get_char	= altera_uart_poll_get_char,
410	.poll_put_char	= altera_uart_poll_put_char,
411#endif
412};
413
414static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
415
416#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
417
418static void altera_uart_console_putc(struct uart_port *port, unsigned char c)
419{
420	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
421		 ALTERA_UART_STATUS_TRDY_MSK))
422		cpu_relax();
423
424	altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG);
425}
426
427static void altera_uart_console_write(struct console *co, const char *s,
428				      unsigned int count)
429{
430	struct uart_port *port = &(altera_uart_ports + co->index)->port;
431
432	uart_console_write(port, s, count, altera_uart_console_putc);
433}
434
435static int __init altera_uart_console_setup(struct console *co, char *options)
436{
437	struct uart_port *port;
438	int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
439	int bits = 8;
440	int parity = 'n';
441	int flow = 'n';
442
443	if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
444		return -EINVAL;
445	port = &altera_uart_ports[co->index].port;
446	if (!port->membase)
447		return -ENODEV;
448
449	if (options)
450		uart_parse_options(options, &baud, &parity, &bits, &flow);
451
452	return uart_set_options(port, co, baud, parity, bits, flow);
453}
454
455static struct uart_driver altera_uart_driver;
456
457static struct console altera_uart_console = {
458	.name	= "ttyAL",
459	.write	= altera_uart_console_write,
460	.device	= uart_console_device,
461	.setup	= altera_uart_console_setup,
462	.flags	= CON_PRINTBUFFER,
463	.index	= -1,
464	.data	= &altera_uart_driver,
465};
466
467static int __init altera_uart_console_init(void)
468{
469	register_console(&altera_uart_console);
470	return 0;
471}
472
473console_initcall(altera_uart_console_init);
474
475#define	ALTERA_UART_CONSOLE	(&altera_uart_console)
476
477static void altera_uart_earlycon_write(struct console *co, const char *s,
478				       unsigned int count)
479{
480	struct earlycon_device *dev = co->data;
481
482	uart_console_write(&dev->port, s, count, altera_uart_console_putc);
483}
484
485static int __init altera_uart_earlycon_setup(struct earlycon_device *dev,
486					     const char *options)
487{
488	struct uart_port *port = &dev->port;
489
490	if (!port->membase)
491		return -ENODEV;
492
493	/* Enable RX interrupts now */
494	altera_uart_writel(port, ALTERA_UART_CONTROL_RRDY_MSK,
495			   ALTERA_UART_CONTROL_REG);
496
497	if (dev->baud) {
498		unsigned int baudclk = port->uartclk / dev->baud;
499
500		altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
501	}
502
503	dev->con->write = altera_uart_earlycon_write;
504	return 0;
505}
506
507OF_EARLYCON_DECLARE(uart, "altr,uart-1.0", altera_uart_earlycon_setup);
508
509#else
510
511#define	ALTERA_UART_CONSOLE	NULL
512
513#endif /* CONFIG_SERIAL_ALTERA_UART_CONSOLE */
514
515/*
516 *	Define the altera_uart UART driver structure.
517 */
518static struct uart_driver altera_uart_driver = {
519	.owner		= THIS_MODULE,
520	.driver_name	= KBUILD_MODNAME,
521	.dev_name	= "ttyAL",
522	.major		= SERIAL_ALTERA_MAJOR,
523	.minor		= SERIAL_ALTERA_MINOR,
524	.nr		= CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
525	.cons		= ALTERA_UART_CONSOLE,
526};
527
528static int altera_uart_probe(struct platform_device *pdev)
529{
530	struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
531	struct uart_port *port;
532	struct resource *res_mem;
533	int i = pdev->id;
534	int ret;
535
536	/* if id is -1 scan for a free id and use that one */
537	if (i == -1) {
538		for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++)
539			if (altera_uart_ports[i].port.mapbase == 0)
540				break;
541	}
542
543	if (i < 0 || i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
544		return -EINVAL;
545
546	port = &altera_uart_ports[i].port;
547
548	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
549	if (res_mem)
550		port->mapbase = res_mem->start;
551	else if (platp)
552		port->mapbase = platp->mapbase;
553	else
554		return -EINVAL;
555
556	ret = platform_get_irq_optional(pdev, 0);
557	if (ret < 0 && ret != -ENXIO)
558		return ret;
559	if (ret > 0)
560		port->irq = ret;
561	else if (platp)
562		port->irq = platp->irq;
563
564	/* Check platform data first so we can override device node data */
565	if (platp)
566		port->uartclk = platp->uartclk;
567	else {
568		ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
569					   &port->uartclk);
570		if (ret)
571			return ret;
572	}
573
574	port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
575	if (!port->membase)
576		return -ENOMEM;
577
578	if (platp)
579		port->regshift = platp->bus_shift;
580	else
581		port->regshift = 0;
582
583	port->line = i;
584	port->type = PORT_ALTERA_UART;
585	port->iotype = SERIAL_IO_MEM;
586	port->ops = &altera_uart_ops;
587	port->flags = UPF_BOOT_AUTOCONF;
588	port->dev = &pdev->dev;
589
590	platform_set_drvdata(pdev, port);
591
592	uart_add_one_port(&altera_uart_driver, port);
593
594	return 0;
595}
596
597static void altera_uart_remove(struct platform_device *pdev)
598{
599	struct uart_port *port = platform_get_drvdata(pdev);
600
601	if (port) {
602		uart_remove_one_port(&altera_uart_driver, port);
603		port->mapbase = 0;
604		iounmap(port->membase);
605	}
606}
607
608#ifdef CONFIG_OF
609static const struct of_device_id altera_uart_match[] = {
610	{ .compatible = "ALTR,uart-1.0", },
611	{ .compatible = "altr,uart-1.0", },
612	{},
613};
614MODULE_DEVICE_TABLE(of, altera_uart_match);
615#endif /* CONFIG_OF */
616
617static struct platform_driver altera_uart_platform_driver = {
618	.probe	= altera_uart_probe,
619	.remove = altera_uart_remove,
620	.driver	= {
621		.name		= KBUILD_MODNAME,
622		.of_match_table	= of_match_ptr(altera_uart_match),
623	},
624};
625
626static int __init altera_uart_init(void)
627{
628	int rc;
629
630	rc = uart_register_driver(&altera_uart_driver);
631	if (rc)
632		return rc;
633	rc = platform_driver_register(&altera_uart_platform_driver);
634	if (rc)
635		uart_unregister_driver(&altera_uart_driver);
636	return rc;
637}
638
639static void __exit altera_uart_exit(void)
640{
641	platform_driver_unregister(&altera_uart_platform_driver);
642	uart_unregister_driver(&altera_uart_driver);
643}
644
645module_init(altera_uart_init);
646module_exit(altera_uart_exit);
647
648MODULE_DESCRIPTION("Altera UART driver");
649MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
650MODULE_LICENSE("GPL");
651MODULE_ALIAS("platform:" KBUILD_MODNAME);
652MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
~/ Read-only file preview.