xref: /linux/drivers/tty/serial/altera_jtaguart.c (revision dd093fb0)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * altera_jtaguart.c -- Altera JTAG 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/bitfield.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
16 #include <linux/module.h>
17 #include <linux/console.h>
18 #include <linux/of.h>
19 #include <linux/tty.h>
20 #include <linux/tty_flip.h>
21 #include <linux/serial.h>
22 #include <linux/serial_core.h>
23 #include <linux/platform_device.h>
24 #include <linux/io.h>
25 #include <linux/altera_jtaguart.h>
26 
27 #define DRV_NAME "altera_jtaguart"
28 
29 /*
30  * Altera JTAG UART register definitions according to the Altera JTAG UART
31  * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
32  */
33 
34 #define ALTERA_JTAGUART_SIZE			8
35 
36 #define ALTERA_JTAGUART_DATA_REG		0
37 
38 #define ALTERA_JTAGUART_DATA_DATA_MSK		0x000000FF
39 #define ALTERA_JTAGUART_DATA_RVALID_MSK		0x00008000
40 #define ALTERA_JTAGUART_DATA_RAVAIL_MSK		0xFFFF0000
41 #define ALTERA_JTAGUART_DATA_RAVAIL_OFF		16
42 
43 #define ALTERA_JTAGUART_CONTROL_REG		4
44 
45 #define ALTERA_JTAGUART_CONTROL_RE_MSK		0x00000001
46 #define ALTERA_JTAGUART_CONTROL_WE_MSK		0x00000002
47 #define ALTERA_JTAGUART_CONTROL_RI_MSK		0x00000100
48 #define ALTERA_JTAGUART_CONTROL_RI_OFF		8
49 #define ALTERA_JTAGUART_CONTROL_WI_MSK		0x00000200
50 #define ALTERA_JTAGUART_CONTROL_AC_MSK		0x00000400
51 #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK	0xFFFF0000
52 
53 static unsigned int altera_jtaguart_tx_space(struct uart_port *port, u32 *ctlp)
54 {
55 	u32 ctl = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG);
56 
57 	if (ctlp)
58 		*ctlp = ctl;
59 
60 	return FIELD_GET(ALTERA_JTAGUART_CONTROL_WSPACE_MSK, ctl);
61 }
62 
63 static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
64 {
65 	return altera_jtaguart_tx_space(port, NULL) ? TIOCSER_TEMT : 0;
66 }
67 
68 static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
69 {
70 	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
71 }
72 
73 static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
74 {
75 }
76 
77 static void altera_jtaguart_start_tx(struct uart_port *port)
78 {
79 	port->read_status_mask |= ALTERA_JTAGUART_CONTROL_WE_MSK;
80 	writel(port->read_status_mask,
81 			port->membase + ALTERA_JTAGUART_CONTROL_REG);
82 }
83 
84 static void altera_jtaguart_stop_tx(struct uart_port *port)
85 {
86 	port->read_status_mask &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
87 	writel(port->read_status_mask,
88 			port->membase + ALTERA_JTAGUART_CONTROL_REG);
89 }
90 
91 static void altera_jtaguart_stop_rx(struct uart_port *port)
92 {
93 	port->read_status_mask &= ~ALTERA_JTAGUART_CONTROL_RE_MSK;
94 	writel(port->read_status_mask,
95 			port->membase + ALTERA_JTAGUART_CONTROL_REG);
96 }
97 
98 static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
99 {
100 }
101 
102 static void altera_jtaguart_set_termios(struct uart_port *port,
103 				        struct ktermios *termios,
104 				        const struct ktermios *old)
105 {
106 	/* Just copy the old termios settings back */
107 	if (old)
108 		tty_termios_copy_hw(termios, old);
109 }
110 
111 static void altera_jtaguart_rx_chars(struct uart_port *port)
112 {
113 	unsigned char ch;
114 	unsigned long status;
115 
116 	while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
117 	       ALTERA_JTAGUART_DATA_RVALID_MSK) {
118 		ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
119 		port->icount.rx++;
120 
121 		if (uart_handle_sysrq_char(port, ch))
122 			continue;
123 		uart_insert_char(port, 0, 0, ch, TTY_NORMAL);
124 	}
125 
126 	tty_flip_buffer_push(&port->state->port);
127 }
128 
129 static void altera_jtaguart_tx_chars(struct uart_port *port)
130 {
131 	unsigned int count;
132 	u8 ch;
133 
134 	count = altera_jtaguart_tx_space(port, NULL);
135 
136 	uart_port_tx_limited(port, ch, count,
137 		true,
138 		writel(ch, port->membase + ALTERA_JTAGUART_DATA_REG),
139 		({}));
140 }
141 
142 static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
143 {
144 	struct uart_port *port = data;
145 	unsigned int isr;
146 
147 	isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
148 	       ALTERA_JTAGUART_CONTROL_RI_OFF) & port->read_status_mask;
149 
150 	spin_lock(&port->lock);
151 
152 	if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
153 		altera_jtaguart_rx_chars(port);
154 	if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
155 		altera_jtaguart_tx_chars(port);
156 
157 	spin_unlock(&port->lock);
158 
159 	return IRQ_RETVAL(isr);
160 }
161 
162 static void altera_jtaguart_config_port(struct uart_port *port, int flags)
163 {
164 	port->type = PORT_ALTERA_JTAGUART;
165 
166 	/* Clear mask, so no surprise interrupts. */
167 	writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG);
168 }
169 
170 static int altera_jtaguart_startup(struct uart_port *port)
171 {
172 	unsigned long flags;
173 	int ret;
174 
175 	ret = request_irq(port->irq, altera_jtaguart_interrupt, 0,
176 			DRV_NAME, port);
177 	if (ret) {
178 		pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
179 		       "interrupt vector=%d\n", port->line, port->irq);
180 		return ret;
181 	}
182 
183 	spin_lock_irqsave(&port->lock, flags);
184 
185 	/* Enable RX interrupts now */
186 	port->read_status_mask = ALTERA_JTAGUART_CONTROL_RE_MSK;
187 	writel(port->read_status_mask,
188 			port->membase + ALTERA_JTAGUART_CONTROL_REG);
189 
190 	spin_unlock_irqrestore(&port->lock, flags);
191 
192 	return 0;
193 }
194 
195 static void altera_jtaguart_shutdown(struct uart_port *port)
196 {
197 	unsigned long flags;
198 
199 	spin_lock_irqsave(&port->lock, flags);
200 
201 	/* Disable all interrupts now */
202 	port->read_status_mask = 0;
203 	writel(port->read_status_mask,
204 			port->membase + ALTERA_JTAGUART_CONTROL_REG);
205 
206 	spin_unlock_irqrestore(&port->lock, flags);
207 
208 	free_irq(port->irq, port);
209 }
210 
211 static const char *altera_jtaguart_type(struct uart_port *port)
212 {
213 	return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
214 }
215 
216 static int altera_jtaguart_request_port(struct uart_port *port)
217 {
218 	/* UARTs always present */
219 	return 0;
220 }
221 
222 static void altera_jtaguart_release_port(struct uart_port *port)
223 {
224 	/* Nothing to release... */
225 }
226 
227 static int altera_jtaguart_verify_port(struct uart_port *port,
228 				       struct serial_struct *ser)
229 {
230 	if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
231 		return -EINVAL;
232 	return 0;
233 }
234 
235 /*
236  *	Define the basic serial functions we support.
237  */
238 static const struct uart_ops altera_jtaguart_ops = {
239 	.tx_empty	= altera_jtaguart_tx_empty,
240 	.get_mctrl	= altera_jtaguart_get_mctrl,
241 	.set_mctrl	= altera_jtaguart_set_mctrl,
242 	.start_tx	= altera_jtaguart_start_tx,
243 	.stop_tx	= altera_jtaguart_stop_tx,
244 	.stop_rx	= altera_jtaguart_stop_rx,
245 	.break_ctl	= altera_jtaguart_break_ctl,
246 	.startup	= altera_jtaguart_startup,
247 	.shutdown	= altera_jtaguart_shutdown,
248 	.set_termios	= altera_jtaguart_set_termios,
249 	.type		= altera_jtaguart_type,
250 	.request_port	= altera_jtaguart_request_port,
251 	.release_port	= altera_jtaguart_release_port,
252 	.config_port	= altera_jtaguart_config_port,
253 	.verify_port	= altera_jtaguart_verify_port,
254 };
255 
256 #define ALTERA_JTAGUART_MAXPORTS 1
257 static struct uart_port altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
258 
259 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
260 
261 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
262 static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
263 {
264 	unsigned long flags;
265 	u32 status;
266 
267 	spin_lock_irqsave(&port->lock, flags);
268 	while (!altera_jtaguart_tx_space(port, &status)) {
269 		spin_unlock_irqrestore(&port->lock, flags);
270 
271 		if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
272 			return;	/* no connection activity */
273 		}
274 
275 		cpu_relax();
276 		spin_lock_irqsave(&port->lock, flags);
277 	}
278 	writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
279 	spin_unlock_irqrestore(&port->lock, flags);
280 }
281 #else
282 static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
283 {
284 	unsigned long flags;
285 
286 	spin_lock_irqsave(&port->lock, flags);
287 	while (!altera_jtaguart_tx_space(port, NULL)) {
288 		spin_unlock_irqrestore(&port->lock, flags);
289 		cpu_relax();
290 		spin_lock_irqsave(&port->lock, flags);
291 	}
292 	writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
293 	spin_unlock_irqrestore(&port->lock, flags);
294 }
295 #endif
296 
297 static void altera_jtaguart_console_write(struct console *co, const char *s,
298 					  unsigned int count)
299 {
300 	struct uart_port *port = &altera_jtaguart_ports[co->index];
301 
302 	uart_console_write(port, s, count, altera_jtaguart_console_putc);
303 }
304 
305 static int __init altera_jtaguart_console_setup(struct console *co,
306 						char *options)
307 {
308 	struct uart_port *port;
309 
310 	if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
311 		return -EINVAL;
312 	port = &altera_jtaguart_ports[co->index];
313 	if (port->membase == NULL)
314 		return -ENODEV;
315 	return 0;
316 }
317 
318 static struct uart_driver altera_jtaguart_driver;
319 
320 static struct console altera_jtaguart_console = {
321 	.name	= "ttyJ",
322 	.write	= altera_jtaguart_console_write,
323 	.device	= uart_console_device,
324 	.setup	= altera_jtaguart_console_setup,
325 	.flags	= CON_PRINTBUFFER,
326 	.index	= -1,
327 	.data	= &altera_jtaguart_driver,
328 };
329 
330 static int __init altera_jtaguart_console_init(void)
331 {
332 	register_console(&altera_jtaguart_console);
333 	return 0;
334 }
335 
336 console_initcall(altera_jtaguart_console_init);
337 
338 #define	ALTERA_JTAGUART_CONSOLE	(&altera_jtaguart_console)
339 
340 static void altera_jtaguart_earlycon_write(struct console *co, const char *s,
341 					   unsigned int count)
342 {
343 	struct earlycon_device *dev = co->data;
344 
345 	uart_console_write(&dev->port, s, count, altera_jtaguart_console_putc);
346 }
347 
348 static int __init altera_jtaguart_earlycon_setup(struct earlycon_device *dev,
349 						 const char *options)
350 {
351 	if (!dev->port.membase)
352 		return -ENODEV;
353 
354 	dev->con->write = altera_jtaguart_earlycon_write;
355 	return 0;
356 }
357 
358 OF_EARLYCON_DECLARE(juart, "altr,juart-1.0", altera_jtaguart_earlycon_setup);
359 
360 #else
361 
362 #define	ALTERA_JTAGUART_CONSOLE	NULL
363 
364 #endif /* CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE */
365 
366 static struct uart_driver altera_jtaguart_driver = {
367 	.owner		= THIS_MODULE,
368 	.driver_name	= "altera_jtaguart",
369 	.dev_name	= "ttyJ",
370 	.major		= ALTERA_JTAGUART_MAJOR,
371 	.minor		= ALTERA_JTAGUART_MINOR,
372 	.nr		= ALTERA_JTAGUART_MAXPORTS,
373 	.cons		= ALTERA_JTAGUART_CONSOLE,
374 };
375 
376 static int altera_jtaguart_probe(struct platform_device *pdev)
377 {
378 	struct altera_jtaguart_platform_uart *platp =
379 			dev_get_platdata(&pdev->dev);
380 	struct uart_port *port;
381 	struct resource *res_mem;
382 	int i = pdev->id;
383 	int irq;
384 
385 	/* -1 emphasizes that the platform must have one port, no .N suffix */
386 	if (i == -1)
387 		i = 0;
388 
389 	if (i >= ALTERA_JTAGUART_MAXPORTS)
390 		return -EINVAL;
391 
392 	port = &altera_jtaguart_ports[i];
393 
394 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
395 	if (res_mem)
396 		port->mapbase = res_mem->start;
397 	else if (platp)
398 		port->mapbase = platp->mapbase;
399 	else
400 		return -ENODEV;
401 
402 	irq = platform_get_irq_optional(pdev, 0);
403 	if (irq < 0 && irq != -ENXIO)
404 		return irq;
405 	if (irq > 0)
406 		port->irq = irq;
407 	else if (platp)
408 		port->irq = platp->irq;
409 	else
410 		return -ENODEV;
411 
412 	port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
413 	if (!port->membase)
414 		return -ENOMEM;
415 
416 	port->line = i;
417 	port->type = PORT_ALTERA_JTAGUART;
418 	port->iotype = SERIAL_IO_MEM;
419 	port->ops = &altera_jtaguart_ops;
420 	port->flags = UPF_BOOT_AUTOCONF;
421 	port->dev = &pdev->dev;
422 
423 	uart_add_one_port(&altera_jtaguart_driver, port);
424 
425 	return 0;
426 }
427 
428 static int altera_jtaguart_remove(struct platform_device *pdev)
429 {
430 	struct uart_port *port;
431 	int i = pdev->id;
432 
433 	if (i == -1)
434 		i = 0;
435 
436 	port = &altera_jtaguart_ports[i];
437 	uart_remove_one_port(&altera_jtaguart_driver, port);
438 	iounmap(port->membase);
439 
440 	return 0;
441 }
442 
443 #ifdef CONFIG_OF
444 static const struct of_device_id altera_jtaguart_match[] = {
445 	{ .compatible = "ALTR,juart-1.0", },
446 	{ .compatible = "altr,juart-1.0", },
447 	{},
448 };
449 MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
450 #endif /* CONFIG_OF */
451 
452 static struct platform_driver altera_jtaguart_platform_driver = {
453 	.probe	= altera_jtaguart_probe,
454 	.remove	= altera_jtaguart_remove,
455 	.driver	= {
456 		.name		= DRV_NAME,
457 		.of_match_table	= of_match_ptr(altera_jtaguart_match),
458 	},
459 };
460 
461 static int __init altera_jtaguart_init(void)
462 {
463 	int rc;
464 
465 	rc = uart_register_driver(&altera_jtaguart_driver);
466 	if (rc)
467 		return rc;
468 	rc = platform_driver_register(&altera_jtaguart_platform_driver);
469 	if (rc)
470 		uart_unregister_driver(&altera_jtaguart_driver);
471 	return rc;
472 }
473 
474 static void __exit altera_jtaguart_exit(void)
475 {
476 	platform_driver_unregister(&altera_jtaguart_platform_driver);
477 	uart_unregister_driver(&altera_jtaguart_driver);
478 }
479 
480 module_init(altera_jtaguart_init);
481 module_exit(altera_jtaguart_exit);
482 
483 MODULE_DESCRIPTION("Altera JTAG UART driver");
484 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
485 MODULE_LICENSE("GPL");
486 MODULE_ALIAS("platform:" DRV_NAME);
487