1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004 Marcel Moolenaar 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 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 36 #include <machine/bus.h> 37 #include <machine/vmparam.h> 38 39 #include <dev/uart/uart.h> 40 #include <dev/uart/uart_cpu.h> 41 42 #define UART_TAG_BR 0 43 #define UART_TAG_CH 1 44 #define UART_TAG_DB 2 45 #define UART_TAG_DT 3 46 #define UART_TAG_IO 4 47 #define UART_TAG_MM 5 48 #define UART_TAG_PA 6 49 #define UART_TAG_RS 7 50 #define UART_TAG_SB 8 51 #define UART_TAG_XO 9 52 53 static struct uart_class *uart_classes[] = { 54 &uart_ns8250_class, 55 &uart_sab82532_class, 56 &uart_z8530_class, 57 #if defined(__arm__) 58 &uart_s3c2410_class, 59 #endif 60 }; 61 62 static bus_addr_t 63 uart_parse_addr(const char **p) 64 { 65 return (strtoul(*p, (char**)(uintptr_t)p, 0)); 66 } 67 68 static struct uart_class * 69 uart_parse_class(struct uart_class *class, const char **p) 70 { 71 struct uart_class *uc; 72 const char *nm; 73 size_t len; 74 u_int i; 75 76 for (i = 0; i < nitems(uart_classes); i++) { 77 uc = uart_classes[i]; 78 nm = uart_getname(uc); 79 if (nm == NULL || *nm == '\0') 80 continue; 81 len = strlen(nm); 82 if (strncmp(nm, *p, len) == 0) { 83 *p += len; 84 return (uc); 85 } 86 } 87 return (class); 88 } 89 90 static long 91 uart_parse_long(const char **p) 92 { 93 return (strtol(*p, (char**)(uintptr_t)p, 0)); 94 } 95 96 static int 97 uart_parse_parity(const char **p) 98 { 99 if (!strncmp(*p, "even", 4)) { 100 *p += 4; 101 return UART_PARITY_EVEN; 102 } 103 if (!strncmp(*p, "mark", 4)) { 104 *p += 4; 105 return UART_PARITY_MARK; 106 } 107 if (!strncmp(*p, "none", 4)) { 108 *p += 4; 109 return UART_PARITY_NONE; 110 } 111 if (!strncmp(*p, "odd", 3)) { 112 *p += 3; 113 return UART_PARITY_ODD; 114 } 115 if (!strncmp(*p, "space", 5)) { 116 *p += 5; 117 return UART_PARITY_SPACE; 118 } 119 return (-1); 120 } 121 122 static int 123 uart_parse_tag(const char **p) 124 { 125 int tag; 126 127 if ((*p)[0] == 'b' && (*p)[1] == 'r') { 128 tag = UART_TAG_BR; 129 goto out; 130 } 131 if ((*p)[0] == 'c' && (*p)[1] == 'h') { 132 tag = UART_TAG_CH; 133 goto out; 134 } 135 if ((*p)[0] == 'd' && (*p)[1] == 'b') { 136 tag = UART_TAG_DB; 137 goto out; 138 } 139 if ((*p)[0] == 'd' && (*p)[1] == 't') { 140 tag = UART_TAG_DT; 141 goto out; 142 } 143 if ((*p)[0] == 'i' && (*p)[1] == 'o') { 144 tag = UART_TAG_IO; 145 goto out; 146 } 147 if ((*p)[0] == 'm' && (*p)[1] == 'm') { 148 tag = UART_TAG_MM; 149 goto out; 150 } 151 if ((*p)[0] == 'p' && (*p)[1] == 'a') { 152 tag = UART_TAG_PA; 153 goto out; 154 } 155 if ((*p)[0] == 'r' && (*p)[1] == 's') { 156 tag = UART_TAG_RS; 157 goto out; 158 } 159 if ((*p)[0] == 's' && (*p)[1] == 'b') { 160 tag = UART_TAG_SB; 161 goto out; 162 } 163 if ((*p)[0] == 'x' && (*p)[1] == 'o') { 164 tag = UART_TAG_XO; 165 goto out; 166 } 167 return (-1); 168 169 out: 170 *p += 2; 171 if ((*p)[0] != ':') 172 return (-1); 173 (*p)++; 174 return (tag); 175 } 176 177 /* 178 * Parse a device specification. The specification is a list of attributes 179 * separated by commas. Each attribute is a tag-value pair with the tag and 180 * value separated by a colon. Supported tags are: 181 * 182 * br = Baudrate 183 * ch = Channel 184 * db = Data bits 185 * dt = Device type 186 * io = I/O port address 187 * mm = Memory mapped I/O address 188 * pa = Parity 189 * rs = Register shift 190 * sb = Stopbits 191 * xo = Device clock (xtal oscillator) 192 * 193 * The io and mm tags are mutually exclusive. 194 */ 195 196 int 197 uart_getenv(int devtype, struct uart_devinfo *di, struct uart_class *class) 198 { 199 const char *spec; 200 char *cp; 201 bus_addr_t addr = ~0U; 202 int error; 203 204 /* 205 * All uart_class references are weak. Make sure the default 206 * device class has been compiled-in. 207 */ 208 if (class == NULL) 209 return (ENXIO); 210 211 /* 212 * Check the environment variables "hw.uart.console" and 213 * "hw.uart.dbgport". These variables, when present, specify 214 * which UART port is to be used as serial console or debug 215 * port (resp). 216 */ 217 switch (devtype) { 218 case UART_DEV_CONSOLE: 219 cp = kern_getenv("hw.uart.console"); 220 break; 221 case UART_DEV_DBGPORT: 222 cp = kern_getenv("hw.uart.dbgport"); 223 break; 224 default: 225 cp = NULL; 226 break; 227 } 228 229 if (cp == NULL) 230 return (ENXIO); 231 232 /* Set defaults. */ 233 di->bas.chan = 0; 234 di->bas.regshft = 0; 235 di->bas.rclk = 0; 236 di->baudrate = 0; 237 di->databits = 8; 238 di->stopbits = 1; 239 di->parity = UART_PARITY_NONE; 240 241 /* Parse the attributes. */ 242 spec = cp; 243 for (;;) { 244 switch (uart_parse_tag(&spec)) { 245 case UART_TAG_BR: 246 di->baudrate = uart_parse_long(&spec); 247 break; 248 case UART_TAG_CH: 249 di->bas.chan = uart_parse_long(&spec); 250 break; 251 case UART_TAG_DB: 252 di->databits = uart_parse_long(&spec); 253 break; 254 case UART_TAG_DT: 255 class = uart_parse_class(class, &spec); 256 break; 257 case UART_TAG_IO: 258 di->bas.bst = uart_bus_space_io; 259 addr = uart_parse_addr(&spec); 260 break; 261 case UART_TAG_MM: 262 di->bas.bst = uart_bus_space_mem; 263 addr = uart_parse_addr(&spec); 264 break; 265 case UART_TAG_PA: 266 di->parity = uart_parse_parity(&spec); 267 break; 268 case UART_TAG_RS: 269 di->bas.regshft = uart_parse_long(&spec); 270 break; 271 case UART_TAG_SB: 272 di->stopbits = uart_parse_long(&spec); 273 break; 274 case UART_TAG_XO: 275 di->bas.rclk = uart_parse_long(&spec); 276 break; 277 default: 278 freeenv(cp); 279 return (EINVAL); 280 } 281 if (*spec == '\0') 282 break; 283 if (*spec != ',') { 284 freeenv(cp); 285 return (EINVAL); 286 } 287 spec++; 288 } 289 freeenv(cp); 290 291 /* 292 * If we still have an invalid address, the specification must be 293 * missing an I/O port or memory address. We don't like that. 294 */ 295 if (addr == ~0U) 296 return (EINVAL); 297 298 /* 299 * Accept only the well-known baudrates. Any invalid baudrate 300 * is silently replaced with a 0-valued baudrate. The 0 baudrate 301 * has special meaning. It means that we're not supposed to 302 * program the baudrate and simply communicate with whatever 303 * speed the hardware is currently programmed for. 304 */ 305 if (di->baudrate >= 19200) { 306 if (di->baudrate % 19200) 307 di->baudrate = 0; 308 } else if (di->baudrate >= 1200) { 309 if (di->baudrate % 1200) 310 di->baudrate = 0; 311 } else if (di->baudrate > 0) { 312 if (di->baudrate % 75) 313 di->baudrate = 0; 314 } else 315 di->baudrate = 0; 316 317 /* Set the ops and create a bus space handle. */ 318 di->ops = uart_getops(class); 319 error = bus_space_map(di->bas.bst, addr, uart_getrange(class), 0, 320 &di->bas.bsh); 321 return (error); 322 } 323