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_lpc_class, 57 #endif 58 }; 59 static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]); 60 61 static bus_addr_t 62 uart_parse_addr(const char **p) 63 { 64 return (strtoul(*p, (char**)(uintptr_t)p, 0)); 65 } 66 67 static struct uart_class * 68 uart_parse_class(struct uart_class *class, const char **p) 69 { 70 struct uart_class *uc; 71 const char *nm; 72 size_t len; 73 u_int i; 74 75 for (i = 0; i < uart_nclasses; i++) { 76 uc = uart_classes[i]; 77 nm = uart_getname(uc); 78 if (nm == NULL || *nm == '\0') 79 continue; 80 len = strlen(nm); 81 if (strncmp(nm, *p, len) == 0) { 82 *p += len; 83 return (uc); 84 } 85 } 86 return (class); 87 } 88 89 static long 90 uart_parse_long(const char **p) 91 { 92 return (strtol(*p, (char**)(uintptr_t)p, 0)); 93 } 94 95 static int 96 uart_parse_parity(const char **p) 97 { 98 if (!strncmp(*p, "even", 4)) { 99 *p += 4; 100 return UART_PARITY_EVEN; 101 } 102 if (!strncmp(*p, "mark", 4)) { 103 *p += 4; 104 return UART_PARITY_MARK; 105 } 106 if (!strncmp(*p, "none", 4)) { 107 *p += 4; 108 return UART_PARITY_NONE; 109 } 110 if (!strncmp(*p, "odd", 3)) { 111 *p += 3; 112 return UART_PARITY_ODD; 113 } 114 if (!strncmp(*p, "space", 5)) { 115 *p += 5; 116 return UART_PARITY_SPACE; 117 } 118 return (-1); 119 } 120 121 static int 122 uart_parse_tag(const char **p) 123 { 124 int tag; 125 126 if ((*p)[0] == 'b' && (*p)[1] == 'r') { 127 tag = UART_TAG_BR; 128 goto out; 129 } 130 if ((*p)[0] == 'c' && (*p)[1] == 'h') { 131 tag = UART_TAG_CH; 132 goto out; 133 } 134 if ((*p)[0] == 'd' && (*p)[1] == 'b') { 135 tag = UART_TAG_DB; 136 goto out; 137 } 138 if ((*p)[0] == 'd' && (*p)[1] == 't') { 139 tag = UART_TAG_DT; 140 goto out; 141 } 142 if ((*p)[0] == 'i' && (*p)[1] == 'o') { 143 tag = UART_TAG_IO; 144 goto out; 145 } 146 if ((*p)[0] == 'm' && (*p)[1] == 'm') { 147 tag = UART_TAG_MM; 148 goto out; 149 } 150 if ((*p)[0] == 'p' && (*p)[1] == 'a') { 151 tag = UART_TAG_PA; 152 goto out; 153 } 154 if ((*p)[0] == 'r' && (*p)[1] == 's') { 155 tag = UART_TAG_RS; 156 goto out; 157 } 158 if ((*p)[0] == 's' && (*p)[1] == 'b') { 159 tag = UART_TAG_SB; 160 goto out; 161 } 162 if ((*p)[0] == 'x' && (*p)[1] == 'o') { 163 tag = UART_TAG_XO; 164 goto out; 165 } 166 return (-1); 167 168 out: 169 *p += 2; 170 if ((*p)[0] != ':') 171 return (-1); 172 (*p)++; 173 return (tag); 174 } 175 176 /* 177 * Parse a device specification. The specification is a list of attributes 178 * separated by commas. Each attribute is a tag-value pair with the tag and 179 * value separated by a colon. Supported tags are: 180 * 181 * br = Baudrate 182 * ch = Channel 183 * db = Data bits 184 * dt = Device type 185 * io = I/O port address 186 * mm = Memory mapped I/O address 187 * pa = Parity 188 * rs = Register shift 189 * sb = Stopbits 190 * xo = Device clock (xtal oscillator) 191 * 192 * The io and mm tags are mutually exclusive. 193 */ 194 195 int 196 uart_getenv(int devtype, struct uart_devinfo *di, struct uart_class *class) 197 { 198 const char *spec; 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 if (devtype == UART_DEV_CONSOLE) 216 spec = getenv("hw.uart.console"); 217 else if (devtype == UART_DEV_DBGPORT) 218 spec = getenv("hw.uart.dbgport"); 219 else 220 spec = NULL; 221 if (spec == NULL) 222 return (ENXIO); 223 224 /* Set defaults. */ 225 di->bas.chan = 0; 226 di->bas.regshft = 0; 227 di->bas.rclk = 0; 228 di->baudrate = 0; 229 di->databits = 8; 230 di->stopbits = 1; 231 di->parity = UART_PARITY_NONE; 232 233 /* Parse the attributes. */ 234 while (1) { 235 switch (uart_parse_tag(&spec)) { 236 case UART_TAG_BR: 237 di->baudrate = uart_parse_long(&spec); 238 break; 239 case UART_TAG_CH: 240 di->bas.chan = uart_parse_long(&spec); 241 break; 242 case UART_TAG_DB: 243 di->databits = uart_parse_long(&spec); 244 break; 245 case UART_TAG_DT: 246 class = uart_parse_class(class, &spec); 247 break; 248 case UART_TAG_IO: 249 di->bas.bst = uart_bus_space_io; 250 addr = uart_parse_addr(&spec); 251 break; 252 case UART_TAG_MM: 253 di->bas.bst = uart_bus_space_mem; 254 addr = uart_parse_addr(&spec); 255 break; 256 case UART_TAG_PA: 257 di->parity = uart_parse_parity(&spec); 258 break; 259 case UART_TAG_RS: 260 di->bas.regshft = uart_parse_long(&spec); 261 break; 262 case UART_TAG_SB: 263 di->stopbits = uart_parse_long(&spec); 264 break; 265 case UART_TAG_XO: 266 di->bas.rclk = uart_parse_long(&spec); 267 break; 268 default: 269 return (EINVAL); 270 } 271 if (*spec == '\0') 272 break; 273 if (*spec != ',') 274 return (EINVAL); 275 spec++; 276 } 277 278 /* 279 * If we still have an invalid address, the specification must be 280 * missing an I/O port or memory address. We don't like that. 281 */ 282 if (addr == ~0U) 283 return (EINVAL); 284 285 /* 286 * Accept only the well-known baudrates. Any invalid baudrate 287 * is silently replaced with a 0-valued baudrate. The 0 baudrate 288 * has special meaning. It means that we're not supposed to 289 * program the baudrate and simply communicate with whatever 290 * speed the hardware is currently programmed for. 291 */ 292 if (di->baudrate >= 19200) { 293 if (di->baudrate % 19200) 294 di->baudrate = 0; 295 } else if (di->baudrate >= 1200) { 296 if (di->baudrate % 1200) 297 di->baudrate = 0; 298 } else if (di->baudrate > 0) { 299 if (di->baudrate % 75) 300 di->baudrate = 0; 301 } else 302 di->baudrate = 0; 303 304 /* Set the ops and create a bus space handle. */ 305 di->ops = uart_getops(class); 306 error = bus_space_map(di->bas.bst, addr, uart_getrange(class), 0, 307 &di->bas.bsh); 308 return (error); 309 } 310