1 /*
2 * xen/drivers/char/arm-uart.c
3 *
4 * Generic uart retrieved via the device tree or ACPI
5 *
6 * Julien Grall <julien.grall@linaro.org>
7 * Copyright (c) 2013 Linaro Limited.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20 #include <asm/device.h>
21 #include <asm/types.h>
22 #include <xen/console.h>
23 #include <xen/device_tree.h>
24 #include <xen/param.h>
25 #include <xen/serial.h>
26 #include <xen/errno.h>
27 #include <xen/acpi.h>
28
29 /*
30 * Configure UART port with a string:
31 * path:options
32 *
33 * @path: full path used in the device tree for the UART. If the path
34 * doesn't start with '/', we assuming that it's an alias.
35 * @options: UART speficic options (see in each UART driver)
36 */
37 static char __initdata opt_dtuart[256] = "";
38 string_param("dtuart", opt_dtuart);
39
dt_uart_init(void)40 static void __init dt_uart_init(void)
41 {
42 struct dt_device_node *dev;
43 int ret;
44 const char *devpath = opt_dtuart;
45 char *options;
46
47 if ( !console_has("dtuart") )
48 return; /* Not for us */
49
50 if ( !strcmp(opt_dtuart, "") )
51 {
52 const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
53
54 if ( chosen )
55 {
56 const char *stdout;
57
58 ret = dt_property_read_string(chosen, "stdout-path", &stdout);
59 if ( ret >= 0 )
60 {
61 printk("Taking dtuart configuration from /chosen/stdout-path\n");
62 if ( strlcpy(opt_dtuart, stdout, sizeof(opt_dtuart))
63 >= sizeof(opt_dtuart) )
64 printk("WARNING: /chosen/stdout-path too long, truncated\n");
65 }
66 else if ( ret != -EINVAL /* Not present */ )
67 printk("Failed to read /chosen/stdout-path (%d)\n", ret);
68 }
69 }
70
71 if ( !strcmp(opt_dtuart, "") )
72 {
73 printk("No dtuart path configured\n");
74 return;
75 }
76
77 options = strchr(opt_dtuart, ':');
78 if ( options != NULL )
79 *(options++) = '\0';
80 else
81 options = "";
82
83 printk("Looking for dtuart at \"%s\", options \"%s\"\n", devpath, options);
84 if ( *devpath == '/' )
85 dev = dt_find_node_by_path(devpath);
86 else
87 dev = dt_find_node_by_alias(devpath);
88
89 if ( !dev )
90 {
91 printk("Unable to find device \"%s\"\n", devpath);
92 return;
93 }
94
95 ret = device_init(dev, DEVICE_SERIAL, options);
96
97 if ( ret )
98 printk("Unable to initialize dtuart: %d\n", ret);
99 }
100
101 #ifdef CONFIG_ACPI
acpi_uart_init(void)102 static void __init acpi_uart_init(void)
103 {
104 struct acpi_table_spcr *spcr = NULL;
105 int ret;
106
107 acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&spcr);
108
109 if ( spcr == NULL )
110 {
111 printk("Unable to get spcr table\n");
112 }
113 else
114 {
115 ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type);
116
117 if ( ret )
118 printk("Unable to initialize acpi uart: %d\n", ret);
119 }
120 }
121 #else
acpi_uart_init(void)122 static void __init acpi_uart_init(void) { }
123 #endif
124
arm_uart_init(void)125 void __init arm_uart_init(void)
126 {
127 if ( acpi_disabled )
128 dt_uart_init();
129 else
130 acpi_uart_init();
131 }
132
133 /*
134 * Local variables:
135 * mode: C
136 * c-file-style: "BSD"
137 * c-basic-offset: 4
138 * tab-width: 4
139 * indent-tabs-mode: nil
140 * End:
141 */
142