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/serial.h>
25 #include <xen/errno.h>
26 #include <xen/acpi.h>
27
28 /*
29 * Configure UART port with a string:
30 * path:options
31 *
32 * @path: full path used in the device tree for the UART. If the path
33 * doesn't start with '/', we assuming that it's an alias.
34 * @options: UART speficic options (see in each UART driver)
35 */
36 static char __initdata opt_dtuart[256] = "";
37 string_param("dtuart", opt_dtuart);
38
dt_uart_init(void)39 static void __init dt_uart_init(void)
40 {
41 struct dt_device_node *dev;
42 int ret;
43 const char *devpath = opt_dtuart;
44 char *options;
45
46 if ( !console_has("dtuart") )
47 return; /* Not for us */
48
49 if ( !strcmp(opt_dtuart, "") )
50 {
51 const struct dt_device_node *chosen = dt_find_node_by_path("/chosen");
52
53 if ( chosen )
54 {
55 const char *stdout;
56
57 ret = dt_property_read_string(chosen, "stdout-path", &stdout);
58 if ( ret >= 0 )
59 {
60 printk("Taking dtuart configuration from /chosen/stdout-path\n");
61 if ( strlcpy(opt_dtuart, stdout, sizeof(opt_dtuart))
62 >= sizeof(opt_dtuart) )
63 printk("WARNING: /chosen/stdout-path too long, truncated\n");
64 }
65 else if ( ret != -EINVAL /* Not present */ )
66 printk("Failed to read /chosen/stdout-path (%d)\n", ret);
67 }
68 }
69
70 if ( !strcmp(opt_dtuart, "") )
71 {
72 printk("No dtuart path configured\n");
73 return;
74 }
75
76 options = strchr(opt_dtuart, ':');
77 if ( options != NULL )
78 *(options++) = '\0';
79 else
80 options = "";
81
82 printk("Looking for dtuart at \"%s\", options \"%s\"\n", devpath, options);
83 if ( *devpath == '/' )
84 dev = dt_find_node_by_path(devpath);
85 else
86 dev = dt_find_node_by_alias(devpath);
87
88 if ( !dev )
89 {
90 printk("Unable to find device \"%s\"\n", devpath);
91 return;
92 }
93
94 ret = device_init(dev, DEVICE_SERIAL, options);
95
96 if ( ret )
97 printk("Unable to initialize dtuart: %d\n", ret);
98 }
99
100 #ifdef CONFIG_ACPI
acpi_uart_init(void)101 static void __init acpi_uart_init(void)
102 {
103 struct acpi_table_spcr *spcr = NULL;
104 int ret;
105
106 acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&spcr);
107
108 if ( spcr == NULL )
109 {
110 printk("Unable to get spcr table\n");
111 }
112 else
113 {
114 ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type);
115
116 if ( ret )
117 printk("Unable to initialize acpi uart: %d\n", ret);
118 }
119 }
120 #else
acpi_uart_init(void)121 static void __init acpi_uart_init(void) { }
122 #endif
123
arm_uart_init(void)124 void __init arm_uart_init(void)
125 {
126 if ( acpi_disabled )
127 dt_uart_init();
128 else
129 acpi_uart_init();
130 }
131
132 /*
133 * Local variables:
134 * mode: C
135 * c-file-style: "BSD"
136 * c-basic-offset: 4
137 * tab-width: 4
138 * indent-tabs-mode: nil
139 * End:
140 */
141