fdt_console.c revision 1.1 1 /* $NetBSD: fdt_console.c,v 1.1 2025/09/06 22:53:48 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2015 Jared D. McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: fdt_console.c,v 1.1 2025/09/06 22:53:48 thorpej Exp $");
31
32 #include "opt_fdt.h"
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36
37 #include <libfdt.h>
38 #include <dev/fdt/fdtvar.h>
39 #include <dev/fdt/fdt_console.h>
40
41 #ifndef FDT_DEFAULT_STDOUT_PATH
42 #define FDT_DEFAULT_STDOUT_PATH "serial0:115200n8"
43 #endif
44
45 const struct fdt_console *
46 fdtbus_get_console(void)
47 {
48 static const struct fdt_console_info *booted_console = NULL;
49
50 if (booted_console == NULL) {
51 __link_set_decl(fdt_consoles, struct fdt_console_info);
52 struct fdt_console_info * const *info;
53 const struct fdt_console_info *best_info = NULL;
54 const int phandle = fdtbus_get_stdout_phandle();
55 int best_match = 0;
56
57 if (phandle == -1) {
58 printf("WARNING: no console device\n");
59 return NULL;
60 }
61
62 __link_set_foreach(info, fdt_consoles) {
63 const int match = (*info)->ops->match(phandle);
64 if (match > best_match) {
65 best_match = match;
66 best_info = *info;
67 }
68 }
69
70 booted_console = best_info;
71 }
72
73 return booted_console == NULL ? NULL : booted_console->ops;
74 }
75
76 const char *
77 fdtbus_get_stdout_path(void)
78 {
79 const char *prop;
80
81 const int off = fdt_path_offset(fdtbus_get_data(), "/chosen");
82 if (off >= 0) {
83 prop = fdt_getprop(fdtbus_get_data(), off, "stdout-path", NULL);
84 if (prop != NULL)
85 return prop;
86 }
87
88 /* If the stdout-path property is not found, return the default */
89 return FDT_DEFAULT_STDOUT_PATH;
90 }
91
92 int
93 fdtbus_get_stdout_phandle(void)
94 {
95 const char *prop, *p;
96 int off, len;
97
98 prop = fdtbus_get_stdout_path();
99 if (prop == NULL)
100 return -1;
101
102 p = strchr(prop, ':');
103 len = p == NULL ? strlen(prop) : (p - prop);
104 if (*prop != '/') {
105 /* Alias */
106 prop = fdt_get_alias_namelen(fdtbus_get_data(), prop, len);
107 if (prop == NULL)
108 return -1;
109 len = strlen(prop);
110 }
111 off = fdt_path_offset_namelen(fdtbus_get_data(), prop, len);
112 if (off < 0)
113 return -1;
114
115 return fdtbus_offset2phandle(off);
116 }
117
118 int
119 fdtbus_get_stdout_speed(void)
120 {
121 const char *prop, *p;
122
123 prop = fdtbus_get_stdout_path();
124 if (prop == NULL)
125 return -1;
126
127 p = strchr(prop, ':');
128 if (p == NULL)
129 return -1;
130
131 return (int)strtoul(p + 1, NULL, 10);
132 }
133
134 tcflag_t
135 fdtbus_get_stdout_flags(void)
136 {
137 const char *prop, *p;
138 tcflag_t flags = TTYDEF_CFLAG;
139 char *ep;
140
141 prop = fdtbus_get_stdout_path();
142 if (prop == NULL)
143 return flags;
144
145 p = strchr(prop, ':');
146 if (p == NULL)
147 return flags;
148
149 ep = NULL;
150 (void)strtoul(p + 1, &ep, 10);
151 if (ep == NULL)
152 return flags;
153
154 /* <baud>{<parity>{<bits>{<flow>}}} */
155 while (*ep) {
156 switch (*ep) {
157 /* parity */
158 case 'n': flags &= ~(PARENB|PARODD); break;
159 case 'e': flags &= ~PARODD; flags |= PARENB; break;
160 case 'o': flags |= (PARENB|PARODD); break;
161 /* bits */
162 case '5': flags &= ~CSIZE; flags |= CS5; break;
163 case '6': flags &= ~CSIZE; flags |= CS6; break;
164 case '7': flags &= ~CSIZE; flags |= CS7; break;
165 case '8': flags &= ~CSIZE; flags |= CS8; break;
166 /* flow */
167 case 'r': flags |= CRTSCTS; break;
168 }
169 ep++;
170 }
171
172 return flags;
173 }
174