1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2016 The FreeBSD Foundation 5 * Copyright (c) 2019 Colin Percival 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 34 #include <machine/bus.h> 35 36 #include <dev/pci/pcireg.h> 37 38 #include <dev/uart/uart.h> 39 #include <dev/uart/uart_bus.h> 40 #include <dev/uart/uart_cpu.h> 41 #include <dev/uart/uart_cpu_acpi.h> 42 43 #include <contrib/dev/acpica/include/acpi.h> 44 #include <contrib/dev/acpica/include/accommon.h> 45 #include <contrib/dev/acpica/include/actables.h> 46 47 static struct acpi_spcr_compat_data * 48 uart_cpu_acpi_scan(uint8_t interface_type) 49 { 50 struct acpi_spcr_compat_data **cd, *curcd; 51 int i; 52 53 SET_FOREACH(cd, uart_acpi_spcr_class_set) { 54 curcd = *cd; 55 for (i = 0; curcd[i].cd_class != NULL; i++) { 56 if (curcd[i].cd_port_subtype == interface_type) 57 return (&curcd[i]); 58 } 59 } 60 61 return (NULL); 62 } 63 64 static int 65 uart_cpu_acpi_init_devinfo(struct uart_devinfo *di, struct uart_class *class, 66 ACPI_GENERIC_ADDRESS *addr) 67 { 68 /* Fill in some fixed details. */ 69 di->bas.chan = 0; 70 di->bas.rclk = 0; 71 di->databits = 8; 72 di->stopbits = 1; 73 di->parity = UART_PARITY_NONE; 74 di->ops = uart_getops(class); 75 76 /* Fill in details from SPCR table. */ 77 switch (addr->SpaceId) { 78 case 0: 79 di->bas.bst = uart_bus_space_mem; 80 break; 81 case 1: 82 di->bas.bst = uart_bus_space_io; 83 break; 84 default: 85 printf("UART in unrecognized address space: %d!\n", 86 (int)addr->SpaceId); 87 return (ENXIO); 88 } 89 switch (addr->AccessWidth) { 90 case 0: /* EFI_ACPI_6_0_UNDEFINED */ 91 /* FALLTHROUGH */ 92 case 1: /* EFI_ACPI_6_0_BYTE */ 93 di->bas.regiowidth = 1; 94 break; 95 case 2: /* EFI_ACPI_6_0_WORD */ 96 di->bas.regiowidth = 2; 97 break; 98 case 3: /* EFI_ACPI_6_0_DWORD */ 99 di->bas.regiowidth = 4; 100 break; 101 case 4: /* EFI_ACPI_6_0_QWORD */ 102 di->bas.regiowidth = 8; 103 break; 104 default: 105 printf("UART unsupported access width: %d!\n", 106 (int)addr->AccessWidth); 107 return (ENXIO); 108 } 109 switch (addr->BitWidth) { 110 case 0: 111 /* FALLTHROUGH */ 112 case 8: 113 di->bas.regshft = 0; 114 break; 115 case 16: 116 di->bas.regshft = 1; 117 break; 118 case 32: 119 di->bas.regshft = 2; 120 break; 121 case 64: 122 di->bas.regshft = 3; 123 break; 124 default: 125 printf("UART unsupported bit width: %d!\n", 126 (int)addr->BitWidth); 127 return (ENXIO); 128 } 129 130 return (0); 131 } 132 133 static int 134 uart_cpu_acpi_spcr(int devtype, struct uart_devinfo *di) 135 { 136 vm_paddr_t spcr_physaddr; 137 ACPI_TABLE_SPCR *spcr; 138 struct acpi_spcr_compat_data *cd; 139 struct uart_class *class; 140 int error = ENXIO; 141 142 /* Look for the SPCR table. */ 143 spcr_physaddr = acpi_find_table(ACPI_SIG_SPCR); 144 if (spcr_physaddr == 0) 145 return (error); 146 spcr = acpi_map_table(spcr_physaddr, ACPI_SIG_SPCR); 147 if (spcr == NULL) { 148 printf("Unable to map the SPCR table!\n"); 149 return (error); 150 } 151 152 /* Search for information about this SPCR interface type. */ 153 cd = uart_cpu_acpi_scan(spcr->InterfaceType); 154 if (cd == NULL) 155 goto out; 156 class = cd->cd_class; 157 158 error = uart_cpu_acpi_init_devinfo(di, class, &spcr->SerialPort); 159 if (error != 0) 160 goto out; 161 162 /* 163 * SPCR Rev 4 and newer allow a precise baudrate to be passed in for 164 * things like 1.5M or 2.0M. If we have that, then use that value, 165 * otherwise try to decode the older enumeration. 166 */ 167 if (spcr->Header.Revision >= 4 && spcr->PreciseBaudrate != 0) { 168 di->baudrate = spcr->PreciseBaudrate; 169 } else { 170 switch (spcr->BaudRate) { 171 case 0: 172 /* Special value; means "keep current value unchanged". */ 173 di->baudrate = 0; 174 break; 175 case 3: 176 di->baudrate = 9600; 177 break; 178 case 4: 179 di->baudrate = 19200; 180 break; 181 case 6: 182 di->baudrate = 57600; 183 break; 184 case 7: 185 di->baudrate = 115200; 186 break; 187 default: 188 printf("SPCR has reserved BaudRate value: %d!\n", 189 (int)spcr->BaudRate); 190 goto out; 191 } 192 } 193 194 /* 195 * Rev 3 and newer can specify a rclk, use it if it's there. It's 196 * defined to be 0 when it's not known, and we've initialized rclk to 0 197 * in uart_cpu_acpi_init_devinfo, so we don't have to test for it. 198 */ 199 if (spcr->Header.Revision >= 3) 200 di->bas.rclk = spcr->UartClkFreq; 201 202 /* 203 * If no rclk is set, then we will assume the BIOS has configured the 204 * hardware at the stated baudrate, so we can use it to guess the rclk 205 * relatively accurately, so make a note for later. 206 */ 207 if (di->bas.rclk == 0) 208 di->bas.rclk_guess = 1; 209 210 if (spcr->PciVendorId != PCIV_INVALID && 211 spcr->PciDeviceId != PCIV_INVALID) { 212 di->pci_info.vendor = spcr->PciVendorId; 213 di->pci_info.device = spcr->PciDeviceId; 214 } 215 216 /* Create a bus space handle. */ 217 error = bus_space_map(di->bas.bst, spcr->SerialPort.Address, 218 uart_getrange(class), 0, &di->bas.bsh); 219 220 out: 221 acpi_unmap_table(spcr); 222 return (error); 223 } 224 225 static int 226 uart_cpu_acpi_dbg2(struct uart_devinfo *di) 227 { 228 vm_paddr_t dbg2_physaddr; 229 ACPI_TABLE_DBG2 *dbg2; 230 ACPI_DBG2_DEVICE *dbg2_dev; 231 ACPI_GENERIC_ADDRESS *base_address; 232 struct acpi_spcr_compat_data *cd; 233 struct uart_class *class; 234 int error; 235 bool found; 236 237 /* Look for the DBG2 table. */ 238 dbg2_physaddr = acpi_find_table(ACPI_SIG_DBG2); 239 if (dbg2_physaddr == 0) 240 return (ENXIO); 241 242 dbg2 = acpi_map_table(dbg2_physaddr, ACPI_SIG_DBG2); 243 if (dbg2 == NULL) { 244 printf("Unable to map the DBG2 table!\n"); 245 return (ENXIO); 246 } 247 248 error = ENXIO; 249 250 dbg2_dev = (ACPI_DBG2_DEVICE *)((uintptr_t)dbg2 + dbg2->InfoOffset); 251 found = false; 252 while ((uintptr_t)dbg2_dev + dbg2_dev->Length <= 253 (uintptr_t)dbg2 + dbg2->Header.Length) { 254 if (dbg2_dev->PortType != ACPI_DBG2_SERIAL_PORT) 255 goto next; 256 257 /* XXX: Too restrictive? */ 258 if (dbg2_dev->RegisterCount != 1) 259 goto next; 260 261 cd = uart_cpu_acpi_scan(dbg2_dev->PortSubtype); 262 if (cd == NULL) 263 goto next; 264 265 class = cd->cd_class; 266 base_address = (ACPI_GENERIC_ADDRESS *) 267 ((uintptr_t)dbg2_dev + dbg2_dev->BaseAddressOffset); 268 269 error = uart_cpu_acpi_init_devinfo(di, class, base_address); 270 if (error == 0) { 271 found = true; 272 break; 273 } 274 275 next: 276 dbg2_dev = (ACPI_DBG2_DEVICE *) 277 ((uintptr_t)dbg2_dev + dbg2_dev->Length); 278 } 279 if (!found) 280 goto out; 281 282 /* XXX: Find the correct value */ 283 di->baudrate = 115200; 284 285 /* Create a bus space handle. */ 286 error = bus_space_map(di->bas.bst, base_address->Address, 287 uart_getrange(class), 0, &di->bas.bsh); 288 289 out: 290 acpi_unmap_table(dbg2); 291 return (error); 292 } 293 294 int 295 uart_cpu_acpi_setup(int devtype, struct uart_devinfo *di) 296 { 297 char *cp; 298 299 switch(devtype) { 300 case UART_DEV_CONSOLE: 301 return (uart_cpu_acpi_spcr(devtype, di)); 302 case UART_DEV_DBGPORT: 303 /* Use the Debug Port Table 2 (DBG2) to find a debug uart */ 304 cp = kern_getenv("hw.acpi.enable_dbg2"); 305 if (cp != NULL && strcasecmp(cp, "yes") == 0) 306 return (uart_cpu_acpi_dbg2(di)); 307 break; 308 } 309 return (ENXIO); 310 } 311