Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2018 Socionext Inc.
  4 */
  5
  6#include <linux/clk.h>
  7#include <linux/console.h>
  8#include <linux/module.h>
  9#include <linux/of_irq.h>
 10#include <linux/platform_device.h>
 11#include <linux/serial_core.h>
 12#include <linux/tty.h>
 13#include <linux/tty_flip.h>
 14
 15#define USIO_NAME		"mlb-usio-uart"
 16#define USIO_UART_DEV_NAME	"ttyUSI"
 17
 18static struct uart_port mlb_usio_ports[CONFIG_SERIAL_MILBEAUT_USIO_PORTS];
 19
 20#define RX	0
 21#define TX	1
 22static int mlb_usio_irq[CONFIG_SERIAL_MILBEAUT_USIO_PORTS][2];
 23
 24#define MLB_USIO_REG_SMR		0
 25#define MLB_USIO_REG_SCR		1
 26#define MLB_USIO_REG_ESCR		2
 27#define MLB_USIO_REG_SSR		3
 28#define MLB_USIO_REG_DR			4
 29#define MLB_USIO_REG_BGR		6
 30#define MLB_USIO_REG_FCR		12
 31#define MLB_USIO_REG_FBYTE		14
 32
 33#define MLB_USIO_SMR_SOE		BIT(0)
 34#define MLB_USIO_SMR_SBL		BIT(3)
 35#define MLB_USIO_SCR_TXE		BIT(0)
 36#define MLB_USIO_SCR_RXE		BIT(1)
 37#define MLB_USIO_SCR_TBIE		BIT(2)
 38#define MLB_USIO_SCR_TIE		BIT(3)
 39#define MLB_USIO_SCR_RIE		BIT(4)
 40#define MLB_USIO_SCR_UPCL		BIT(7)
 41#define MLB_USIO_ESCR_L_8BIT		0
 42#define MLB_USIO_ESCR_L_5BIT		1
 43#define MLB_USIO_ESCR_L_6BIT		2
 44#define MLB_USIO_ESCR_L_7BIT		3
 45#define MLB_USIO_ESCR_P			BIT(3)
 46#define MLB_USIO_ESCR_PEN		BIT(4)
 47#define MLB_USIO_ESCR_FLWEN		BIT(7)
 48#define MLB_USIO_SSR_TBI		BIT(0)
 49#define MLB_USIO_SSR_TDRE		BIT(1)
 50#define MLB_USIO_SSR_RDRF		BIT(2)
 51#define MLB_USIO_SSR_ORE		BIT(3)
 52#define MLB_USIO_SSR_FRE		BIT(4)
 53#define MLB_USIO_SSR_PE			BIT(5)
 54#define MLB_USIO_SSR_REC		BIT(7)
 55#define MLB_USIO_SSR_BRK		BIT(8)
 56#define MLB_USIO_FCR_FE1		BIT(0)
 57#define MLB_USIO_FCR_FE2		BIT(1)
 58#define MLB_USIO_FCR_FCL1		BIT(2)
 59#define MLB_USIO_FCR_FCL2		BIT(3)
 60#define MLB_USIO_FCR_FSET		BIT(4)
 61#define MLB_USIO_FCR_FTIE		BIT(9)
 62#define MLB_USIO_FCR_FDRQ		BIT(10)
 63#define MLB_USIO_FCR_FRIIE		BIT(11)
 64
 65static void mlb_usio_stop_tx(struct uart_port *port)
 66{
 67	writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE,
 68	       port->membase + MLB_USIO_REG_FCR);
 69	writeb(readb(port->membase + MLB_USIO_REG_SCR) & ~MLB_USIO_SCR_TBIE,
 70	       port->membase + MLB_USIO_REG_SCR);
 71}
 72
 73static void mlb_usio_tx_chars(struct uart_port *port)
 74{
 75	struct circ_buf *xmit = &port->state->xmit;
 76	int count;
 77
 78	writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FTIE,
 79	       port->membase + MLB_USIO_REG_FCR);
 80	writeb(readb(port->membase + MLB_USIO_REG_SCR) &
 81	       ~(MLB_USIO_SCR_TIE | MLB_USIO_SCR_TBIE),
 82	       port->membase + MLB_USIO_REG_SCR);
 83
 84	if (port->x_char) {
 85		writew(port->x_char, port->membase + MLB_USIO_REG_DR);
 86		port->icount.tx++;
 87		port->x_char = 0;
 88		return;
 89	}
 90	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
 91		mlb_usio_stop_tx(port);
 92		return;
 93	}
 94
 95	count = port->fifosize -
 96		(readw(port->membase + MLB_USIO_REG_FBYTE) & 0xff);
 97
 98	do {
 99		writew(xmit->buf[xmit->tail], port->membase + MLB_USIO_REG_DR);
100
101		uart_xmit_advance(port, 1);
102		if (uart_circ_empty(xmit))
103			break;
104
105	} while (--count > 0);
106
107	writew(readw(port->membase + MLB_USIO_REG_FCR) & ~MLB_USIO_FCR_FDRQ,
108	       port->membase + MLB_USIO_REG_FCR);
109
110	writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE,
111	       port->membase + MLB_USIO_REG_SCR);
112
113	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
114		uart_write_wakeup(port);
115
116	if (uart_circ_empty(xmit))
117		mlb_usio_stop_tx(port);
118}
119
120static void mlb_usio_start_tx(struct uart_port *port)
121{
122	u16 fcr = readw(port->membase + MLB_USIO_REG_FCR);
123
124	writew(fcr | MLB_USIO_FCR_FTIE, port->membase + MLB_USIO_REG_FCR);
125	if (!(fcr & MLB_USIO_FCR_FDRQ))
126		return;
127
128	writeb(readb(port->membase + MLB_USIO_REG_SCR) | MLB_USIO_SCR_TBIE,
129	       port->membase + MLB_USIO_REG_SCR);
130
131	if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI)
132		mlb_usio_tx_chars(port);
133}
134
135static void mlb_usio_stop_rx(struct uart_port *port)
136{
137	writeb(readb(port->membase + MLB_USIO_REG_SCR) & ~MLB_USIO_SCR_RIE,
138	       port->membase + MLB_USIO_REG_SCR);
139}
140
141static void mlb_usio_enable_ms(struct uart_port *port)
142{
143	writeb(readb(port->membase + MLB_USIO_REG_SCR) |
144	       MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE,
145	       port->membase + MLB_USIO_REG_SCR);
146}
147
148static void mlb_usio_rx_chars(struct uart_port *port)
149{
150	struct tty_port *ttyport = &port->state->port;
151	unsigned long flag = 0;
152	char ch = 0;
153	u8 status;
154	int max_count = 2;
155
156	while (max_count--) {
157		status = readb(port->membase + MLB_USIO_REG_SSR);
158
159		if (!(status & MLB_USIO_SSR_RDRF))
160			break;
161
162		if (!(status & (MLB_USIO_SSR_ORE | MLB_USIO_SSR_FRE |
163				MLB_USIO_SSR_PE))) {
164			ch = readw(port->membase + MLB_USIO_REG_DR);
165			flag = TTY_NORMAL;
166			port->icount.rx++;
167			if (uart_handle_sysrq_char(port, ch))
168				continue;
169			uart_insert_char(port, status, MLB_USIO_SSR_ORE,
170					 ch, flag);
171			continue;
172		}
173		if (status & MLB_USIO_SSR_PE)
174			port->icount.parity++;
175		if (status & MLB_USIO_SSR_ORE)
176			port->icount.overrun++;
177		status &= port->read_status_mask;
178		if (status & MLB_USIO_SSR_BRK) {
179			flag = TTY_BREAK;
180			ch = 0;
181		} else
182			if (status & MLB_USIO_SSR_PE) {
183				flag = TTY_PARITY;
184				ch = 0;
185			} else
186				if (status & MLB_USIO_SSR_FRE) {
187					flag = TTY_FRAME;
188					ch = 0;
189				}
190		if (flag)
191			uart_insert_char(port, status, MLB_USIO_SSR_ORE,
192					 ch, flag);
193
194		writeb(readb(port->membase + MLB_USIO_REG_SSR) |
195				MLB_USIO_SSR_REC,
196				port->membase + MLB_USIO_REG_SSR);
197
198		max_count = readw(port->membase + MLB_USIO_REG_FBYTE) >> 8;
199		writew(readw(port->membase + MLB_USIO_REG_FCR) |
200		       MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
201		port->membase + MLB_USIO_REG_FCR);
202	}
203
204	tty_flip_buffer_push(ttyport);
205}
206
207static irqreturn_t mlb_usio_rx_irq(int irq, void *dev_id)
208{
209	struct uart_port *port = dev_id;
210
211	spin_lock(&port->lock);
212	mlb_usio_rx_chars(port);
213	spin_unlock(&port->lock);
214
215	return IRQ_HANDLED;
216}
217
218static irqreturn_t mlb_usio_tx_irq(int irq, void *dev_id)
219{
220	struct uart_port *port = dev_id;
221
222	spin_lock(&port->lock);
223	if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI)
224		mlb_usio_tx_chars(port);
225	spin_unlock(&port->lock);
226
227	return IRQ_HANDLED;
228}
229
230static unsigned int mlb_usio_tx_empty(struct uart_port *port)
231{
232	return (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI) ?
233		TIOCSER_TEMT : 0;
234}
235
236static void mlb_usio_set_mctrl(struct uart_port *port, unsigned int mctrl)
237{
238}
239
240static unsigned int mlb_usio_get_mctrl(struct uart_port *port)
241{
242	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
243
244}
245
246static void mlb_usio_break_ctl(struct uart_port *port, int break_state)
247{
248}
249
250static int mlb_usio_startup(struct uart_port *port)
251{
252	const char *portname = to_platform_device(port->dev)->name;
253	unsigned long flags;
254	int ret, index = port->line;
255	unsigned char  escr;
256
257	ret = request_irq(mlb_usio_irq[index][RX], mlb_usio_rx_irq,
258				0, portname, port);
259	if (ret)
260		return ret;
261	ret = request_irq(mlb_usio_irq[index][TX], mlb_usio_tx_irq,
262				0, portname, port);
263	if (ret) {
264		free_irq(mlb_usio_irq[index][RX], port);
265		return ret;
266	}
267
268	escr = readb(port->membase + MLB_USIO_REG_ESCR);
269	if (of_property_read_bool(port->dev->of_node, "auto-flow-control"))
270		escr |= MLB_USIO_ESCR_FLWEN;
271	spin_lock_irqsave(&port->lock, flags);
272	writeb(0, port->membase + MLB_USIO_REG_SCR);
273	writeb(escr, port->membase + MLB_USIO_REG_ESCR);
274	writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR);
275	writeb(MLB_USIO_SSR_REC, port->membase + MLB_USIO_REG_SSR);
276	writew(0, port->membase + MLB_USIO_REG_FCR);
277	writew(MLB_USIO_FCR_FCL1 | MLB_USIO_FCR_FCL2,
278	       port->membase + MLB_USIO_REG_FCR);
279	writew(MLB_USIO_FCR_FE1 | MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
280	       port->membase + MLB_USIO_REG_FCR);
281	writew(0, port->membase + MLB_USIO_REG_FBYTE);
282	writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE);
283
284	writeb(MLB_USIO_SCR_TXE  | MLB_USIO_SCR_RIE | MLB_USIO_SCR_TBIE |
285	       MLB_USIO_SCR_RXE, port->membase + MLB_USIO_REG_SCR);
286	spin_unlock_irqrestore(&port->lock, flags);
287
288	return 0;
289}
290
291static void mlb_usio_shutdown(struct uart_port *port)
292{
293	int index = port->line;
294
295	free_irq(mlb_usio_irq[index][RX], port);
296	free_irq(mlb_usio_irq[index][TX], port);
297}
298
299static void mlb_usio_set_termios(struct uart_port *port,
300				 struct ktermios *termios,
301				 const struct ktermios *old)
302{
303	unsigned int escr, smr = MLB_USIO_SMR_SOE;
304	unsigned long flags, baud, quot;
305
306	switch (termios->c_cflag & CSIZE) {
307	case CS5:
308		escr = MLB_USIO_ESCR_L_5BIT;
309		break;
310	case CS6:
311		escr = MLB_USIO_ESCR_L_6BIT;
312		break;
313	case CS7:
314		escr = MLB_USIO_ESCR_L_7BIT;
315		break;
316	case CS8:
317	default:
318		escr = MLB_USIO_ESCR_L_8BIT;
319		break;
320	}
321
322	if (termios->c_cflag & CSTOPB)
323		smr |= MLB_USIO_SMR_SBL;
324
325	if (termios->c_cflag & PARENB) {
326		escr |= MLB_USIO_ESCR_PEN;
327		if (termios->c_cflag & PARODD)
328			escr |= MLB_USIO_ESCR_P;
329	}
330	/* Set hard flow control */
331	if (of_property_read_bool(port->dev->of_node, "auto-flow-control") ||
332			(termios->c_cflag & CRTSCTS))
333		escr |= MLB_USIO_ESCR_FLWEN;
334
335	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk);
336	if (baud > 1)
337		quot = port->uartclk / baud - 1;
338	else
339		quot = 0;
340
341	spin_lock_irqsave(&port->lock, flags);
342	uart_update_timeout(port, termios->c_cflag, baud);
343	port->read_status_mask = MLB_USIO_SSR_ORE | MLB_USIO_SSR_RDRF |
344				 MLB_USIO_SSR_TDRE;
345	if (termios->c_iflag & INPCK)
346		port->read_status_mask |= MLB_USIO_SSR_FRE | MLB_USIO_SSR_PE;
347
348	port->ignore_status_mask = 0;
349	if (termios->c_iflag & IGNPAR)
350		port->ignore_status_mask |= MLB_USIO_SSR_FRE | MLB_USIO_SSR_PE;
351	if ((termios->c_iflag & IGNBRK) && (termios->c_iflag & IGNPAR))
352		port->ignore_status_mask |= MLB_USIO_SSR_ORE;
353	if ((termios->c_cflag & CREAD) == 0)
354		port->ignore_status_mask |= MLB_USIO_SSR_RDRF;
355
356	writeb(0, port->membase + MLB_USIO_REG_SCR);
357	writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR);
358	writeb(MLB_USIO_SSR_REC, port->membase + MLB_USIO_REG_SSR);
359	writew(0, port->membase + MLB_USIO_REG_FCR);
360	writeb(smr, port->membase + MLB_USIO_REG_SMR);
361	writeb(escr, port->membase + MLB_USIO_REG_ESCR);
362	writew(quot, port->membase + MLB_USIO_REG_BGR);
363	writew(0, port->membase + MLB_USIO_REG_FCR);
364	writew(MLB_USIO_FCR_FCL1 | MLB_USIO_FCR_FCL2 | MLB_USIO_FCR_FE1 |
365	       MLB_USIO_FCR_FE2 | MLB_USIO_FCR_FRIIE,
366	       port->membase + MLB_USIO_REG_FCR);
367	writew(0, port->membase + MLB_USIO_REG_FBYTE);
368	writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE);
369	writeb(MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE | MLB_USIO_SCR_TBIE |
370	       MLB_USIO_SCR_TXE, port->membase + MLB_USIO_REG_SCR);
371	spin_unlock_irqrestore(&port->lock, flags);
372}
373
374static const char *mlb_usio_type(struct uart_port *port)
375{
376	return ((port->type == PORT_MLB_USIO) ? USIO_NAME : NULL);
377}
378
379static void mlb_usio_config_port(struct uart_port *port, int flags)
380{
381	if (flags & UART_CONFIG_TYPE)
382		port->type = PORT_MLB_USIO;
383}
384
385static const struct uart_ops mlb_usio_ops = {
386	.tx_empty	= mlb_usio_tx_empty,
387	.set_mctrl	= mlb_usio_set_mctrl,
388	.get_mctrl	= mlb_usio_get_mctrl,
389	.stop_tx	= mlb_usio_stop_tx,
390	.start_tx	= mlb_usio_start_tx,
391	.stop_rx	= mlb_usio_stop_rx,
392	.enable_ms	= mlb_usio_enable_ms,
393	.break_ctl	= mlb_usio_break_ctl,
394	.startup	= mlb_usio_startup,
395	.shutdown	= mlb_usio_shutdown,
396	.set_termios	= mlb_usio_set_termios,
397	.type		= mlb_usio_type,
398	.config_port	= mlb_usio_config_port,
399};
400
401#ifdef CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE
402
403static void mlb_usio_console_putchar(struct uart_port *port, unsigned char c)
404{
405	while (!(readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TDRE))
406		cpu_relax();
407
408	writew(c, port->membase + MLB_USIO_REG_DR);
409}
410
411static void mlb_usio_console_write(struct console *co, const char *s,
412			       unsigned int count)
413{
414	struct uart_port *port = &mlb_usio_ports[co->index];
415
416	uart_console_write(port, s, count, mlb_usio_console_putchar);
417}
418
419static int __init mlb_usio_console_setup(struct console *co, char *options)
420{
421	struct uart_port *port;
422	int baud = 115200;
423	int parity = 'n';
424	int flow = 'n';
425	int bits = 8;
426
427	if (co->index >= CONFIG_SERIAL_MILBEAUT_USIO_PORTS)
428		return -ENODEV;
429
430	port = &mlb_usio_ports[co->index];
431	if (!port->membase)
432		return -ENODEV;
433
434
435	if (options)
436		uart_parse_options(options, &baud, &parity, &bits, &flow);
437
438	if (of_property_read_bool(port->dev->of_node, "auto-flow-control"))
439		flow = 'r';
440
441	return uart_set_options(port, co, baud, parity, bits, flow);
442}
443
444
445static struct uart_driver mlb_usio_uart_driver;
446static struct console mlb_usio_console = {
447	.name   = USIO_UART_DEV_NAME,
448	.write  = mlb_usio_console_write,
449	.device = uart_console_device,
450	.setup  = mlb_usio_console_setup,
451	.flags  = CON_PRINTBUFFER,
452	.index  = -1,
453	.data   = &mlb_usio_uart_driver,
454};
455
456static int __init mlb_usio_console_init(void)
457{
458	register_console(&mlb_usio_console);
459	return 0;
460}
461console_initcall(mlb_usio_console_init);
462
463
464static void mlb_usio_early_console_write(struct console *co, const char *s,
465					u_int count)
466{
467	struct earlycon_device *dev = co->data;
468
469	uart_console_write(&dev->port, s, count, mlb_usio_console_putchar);
470}
471
472static int __init mlb_usio_early_console_setup(struct earlycon_device *device,
473						const char *opt)
474{
475	if (!device->port.membase)
476		return -ENODEV;
477	device->con->write = mlb_usio_early_console_write;
478	return 0;
479}
480
481OF_EARLYCON_DECLARE(mlb_usio, "socionext,milbeaut-usio-uart",
482			mlb_usio_early_console_setup);
483
484#define USIO_CONSOLE	(&mlb_usio_console)
485#else
486#define USIO_CONSOLE	NULL
487#endif
488
489static struct  uart_driver mlb_usio_uart_driver = {
490	.owner		= THIS_MODULE,
491	.driver_name	= USIO_NAME,
492	.dev_name	= USIO_UART_DEV_NAME,
493	.cons           = USIO_CONSOLE,
494	.nr		= CONFIG_SERIAL_MILBEAUT_USIO_PORTS,
495};
496
497static int mlb_usio_probe(struct platform_device *pdev)
498{
499	struct clk *clk = devm_clk_get(&pdev->dev, NULL);
500	struct uart_port *port;
501	struct resource *res;
502	int index = 0;
503	int ret;
504
505	if (IS_ERR(clk)) {
506		dev_err(&pdev->dev, "Missing clock\n");
507		return PTR_ERR(clk);
508	}
509	ret = clk_prepare_enable(clk);
510	if (ret) {
511		dev_err(&pdev->dev, "Clock enable failed: %d\n", ret);
512		return ret;
513	}
514	of_property_read_u32(pdev->dev.of_node, "index", &index);
515	port = &mlb_usio_ports[index];
516
517	port->private_data = (void *)clk;
518	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
519	if (res == NULL) {
520		dev_err(&pdev->dev, "Missing regs\n");
521		ret = -ENODEV;
522		goto failed;
523	}
524	port->membase = devm_ioremap(&pdev->dev, res->start,
525				resource_size(res));
526
527	ret = platform_get_irq_byname(pdev, "rx");
528	mlb_usio_irq[index][RX] = ret;
529
530	ret = platform_get_irq_byname(pdev, "tx");
531	mlb_usio_irq[index][TX] = ret;
532
533	port->irq = mlb_usio_irq[index][RX];
534	port->uartclk = clk_get_rate(clk);
535	port->fifosize = 128;
536	port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MILBEAUT_USIO_CONSOLE);
537	port->iotype = UPIO_MEM32;
538	port->flags = UPF_BOOT_AUTOCONF | UPF_SPD_VHI;
539	port->line = index;
540	port->ops = &mlb_usio_ops;
541	port->dev = &pdev->dev;
542
543	ret = uart_add_one_port(&mlb_usio_uart_driver, port);
544	if (ret) {
545		dev_err(&pdev->dev, "Adding port failed: %d\n", ret);
546		goto failed;
547	}
548	return 0;
549
550failed:
551	clk_disable_unprepare(clk);
552
553	return ret;
554}
555
556static int mlb_usio_remove(struct platform_device *pdev)
557{
558	struct uart_port *port = &mlb_usio_ports[pdev->id];
559	struct clk *clk = port->private_data;
560
561	uart_remove_one_port(&mlb_usio_uart_driver, port);
562	clk_disable_unprepare(clk);
563
564	return 0;
565}
566
567static const struct of_device_id mlb_usio_dt_ids[] = {
568	{ .compatible = "socionext,milbeaut-usio-uart" },
569	{ /* sentinel */ }
570};
571MODULE_DEVICE_TABLE(of, mlb_usio_dt_ids);
572
573static struct platform_driver mlb_usio_driver = {
574	.probe          = mlb_usio_probe,
575	.remove         = mlb_usio_remove,
576	.driver         = {
577		.name   = USIO_NAME,
578		.of_match_table = mlb_usio_dt_ids,
579	},
580};
581
582static int __init mlb_usio_init(void)
583{
584	int ret = uart_register_driver(&mlb_usio_uart_driver);
585
586	if (ret) {
587		pr_err("%s: uart registration failed: %d\n", __func__, ret);
588		return ret;
589	}
590	ret = platform_driver_register(&mlb_usio_driver);
591	if (ret) {
592		uart_unregister_driver(&mlb_usio_uart_driver);
593		pr_err("%s: drv registration failed: %d\n", __func__, ret);
594		return ret;
595	}
596
597	return 0;
598}
599
600static void __exit mlb_usio_exit(void)
601{
602	platform_driver_unregister(&mlb_usio_driver);
603	uart_unregister_driver(&mlb_usio_uart_driver);
604}
605
606module_init(mlb_usio_init);
607module_exit(mlb_usio_exit);
608
609MODULE_AUTHOR("SOCIONEXT");
610MODULE_DESCRIPTION("MILBEAUT_USIO/UART Driver");
611MODULE_LICENSE("GPL");