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