xref: /linux/drivers/tty/hvc/hvc_udbg.c (revision c441bfb5f2866de71e092c1b9d866a65978dfe1a)
1e3b3d0f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
2d5e54913SDavid Gibson /*
3d5e54913SDavid Gibson  * udbg interface to hvc_console.c
4d5e54913SDavid Gibson  *
5d5e54913SDavid Gibson  * (C) Copyright David Gibson, IBM Corporation 2008.
6d5e54913SDavid Gibson  */
7d5e54913SDavid Gibson 
8d5e54913SDavid Gibson #include <linux/console.h>
9d5e54913SDavid Gibson #include <linux/delay.h>
10d5e54913SDavid Gibson #include <linux/err.h>
11d5e54913SDavid Gibson #include <linux/init.h>
12d5e54913SDavid Gibson #include <linux/moduleparam.h>
13d5e54913SDavid Gibson #include <linux/types.h>
14d5e54913SDavid Gibson #include <linux/irq.h>
15d5e54913SDavid Gibson 
16d5e54913SDavid Gibson #include <asm/udbg.h>
17d5e54913SDavid Gibson 
18d5e54913SDavid Gibson #include "hvc_console.h"
19d5e54913SDavid Gibson 
20*63bbdb4eSYu Kuai static struct hvc_struct *hvc_udbg_dev;
21d5e54913SDavid Gibson 
22d5e54913SDavid Gibson static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
23d5e54913SDavid Gibson {
24d5e54913SDavid Gibson 	int i;
25d5e54913SDavid Gibson 
267d3d897aSBenjamin Herrenschmidt 	for (i = 0; i < count && udbg_putc; i++)
27d5e54913SDavid Gibson 		udbg_putc(buf[i]);
28d5e54913SDavid Gibson 
29d5e54913SDavid Gibson 	return i;
30d5e54913SDavid Gibson }
31d5e54913SDavid Gibson 
32d5e54913SDavid Gibson static int hvc_udbg_get(uint32_t vtermno, char *buf, int count)
33d5e54913SDavid Gibson {
34d5e54913SDavid Gibson 	int i, c;
35d5e54913SDavid Gibson 
36d5e54913SDavid Gibson 	if (!udbg_getc_poll)
37d5e54913SDavid Gibson 		return 0;
38d5e54913SDavid Gibson 
39d5e54913SDavid Gibson 	for (i = 0; i < count; i++) {
40d5e54913SDavid Gibson 		if ((c = udbg_getc_poll()) == -1)
41d5e54913SDavid Gibson 			break;
42d5e54913SDavid Gibson 		buf[i] = c;
43d5e54913SDavid Gibson 	}
44d5e54913SDavid Gibson 
45d5e54913SDavid Gibson 	return i;
46d5e54913SDavid Gibson }
47d5e54913SDavid Gibson 
481dff3996SRusty Russell static const struct hv_ops hvc_udbg_ops = {
49d5e54913SDavid Gibson 	.get_chars = hvc_udbg_get,
50d5e54913SDavid Gibson 	.put_chars = hvc_udbg_put,
51d5e54913SDavid Gibson };
52d5e54913SDavid Gibson 
53d5e54913SDavid Gibson static int __init hvc_udbg_init(void)
54d5e54913SDavid Gibson {
55d5e54913SDavid Gibson 	struct hvc_struct *hp;
56d5e54913SDavid Gibson 
577d3d897aSBenjamin Herrenschmidt 	if (!udbg_putc)
587d3d897aSBenjamin Herrenschmidt 		return -ENODEV;
597d3d897aSBenjamin Herrenschmidt 
60d5e54913SDavid Gibson 	BUG_ON(hvc_udbg_dev);
61d5e54913SDavid Gibson 
62d4e33facSAlan Cox 	hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16);
63d5e54913SDavid Gibson 	if (IS_ERR(hp))
64d5e54913SDavid Gibson 		return PTR_ERR(hp);
65d5e54913SDavid Gibson 
66d5e54913SDavid Gibson 	hvc_udbg_dev = hp;
67d5e54913SDavid Gibson 
68d5e54913SDavid Gibson 	return 0;
69d5e54913SDavid Gibson }
704fedd0bfSPaul Gortmaker device_initcall(hvc_udbg_init);
71d5e54913SDavid Gibson 
72d5e54913SDavid Gibson static int __init hvc_udbg_console_init(void)
73d5e54913SDavid Gibson {
747d3d897aSBenjamin Herrenschmidt 	if (!udbg_putc)
757d3d897aSBenjamin Herrenschmidt 		return -ENODEV;
767d3d897aSBenjamin Herrenschmidt 
77d5e54913SDavid Gibson 	hvc_instantiate(0, 0, &hvc_udbg_ops);
78d5e54913SDavid Gibson 	add_preferred_console("hvc", 0, NULL);
79d5e54913SDavid Gibson 
80d5e54913SDavid Gibson 	return 0;
81d5e54913SDavid Gibson }
82d5e54913SDavid Gibson console_initcall(hvc_udbg_console_init);
83