1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org> 5 * Copyright (c) 2017 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Landon Fuller 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/kobj.h> 42 43 #include <machine/bus.h> 44 #include <sys/rman.h> 45 #include <machine/resource.h> 46 47 #include <dev/bhnd/bhndreg.h> 48 #include <dev/bhnd/bhndvar.h> 49 50 #include <dev/bhnd/bhnd_erom.h> 51 #include <dev/bhnd/bhnd_eromvar.h> 52 53 #include <dev/bhnd/cores/chipc/chipcreg.h> 54 55 static int bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, 56 bhnd_size_t size); 57 static int bhnd_erom_iores_tell(struct bhnd_erom_io *eio, 58 bhnd_addr_t *addr, bhnd_size_t *size); 59 static uint32_t bhnd_erom_iores_read(struct bhnd_erom_io *eio, 60 bhnd_size_t offset, u_int width); 61 static void bhnd_erom_iores_fini(struct bhnd_erom_io *eio); 62 63 static int bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, 64 bhnd_size_t size); 65 static int bhnd_erom_iobus_tell(struct bhnd_erom_io *eio, 66 bhnd_addr_t *addr, bhnd_size_t *size); 67 static uint32_t bhnd_erom_iobus_read(struct bhnd_erom_io *eio, 68 bhnd_size_t offset, u_int width); 69 70 /** 71 * An implementation of bhnd_erom_io that manages mappings via 72 * bhnd_alloc_resource() and bhnd_release_resource(). 73 */ 74 struct bhnd_erom_iores { 75 struct bhnd_erom_io eio; 76 device_t owner; /**< device from which we'll allocate resources */ 77 int owner_rid; /**< rid to use when allocating new mappings */ 78 struct bhnd_resource *mapped; /**< current mapping, or NULL */ 79 int mapped_rid; /**< resource ID of current mapping, or -1 */ 80 }; 81 82 /** 83 * Fetch the device enumeration parser class from all bhnd(4)-compatible drivers 84 * registered for @p bus_devclass, probe @p eio for supporting parser classes, 85 * and return the best available supporting enumeration parser class. 86 * 87 * @param bus_devclass The bus device class to be queried for 88 * bhnd(4)-compatible drivers. 89 * @param eio An erom bus I/O instance, configured with a 90 * mapping of the first bus core. 91 * @param hint Identification hint used to identify the device. 92 * If the chipset supports standard chip 93 * identification registers within the first core, 94 * this parameter should be NULL. 95 * @param[out] cid On success, the probed chip identifier. 96 * 97 * @retval non-NULL on success, the best available EROM class. 98 * @retval NULL if no erom class returned a successful probe result for 99 * @p eio. 100 */ 101 bhnd_erom_class_t * 102 bhnd_erom_probe_driver_classes(devclass_t bus_devclass, 103 struct bhnd_erom_io *eio, const struct bhnd_chipid *hint, 104 struct bhnd_chipid *cid) 105 { 106 driver_t **drivers; 107 int drv_count; 108 bhnd_erom_class_t *erom_cls; 109 int error, prio, result; 110 111 erom_cls = NULL; 112 prio = 0; 113 114 /* Fetch all available drivers */ 115 error = devclass_get_drivers(bus_devclass, &drivers, &drv_count); 116 if (error) { 117 printf("error fetching bhnd(4) drivers for %s: %d\n", 118 devclass_get_name(bus_devclass), error); 119 return (NULL); 120 } 121 122 /* Enumerate the drivers looking for the best available EROM class */ 123 for (int i = 0; i < drv_count; i++) { 124 struct bhnd_chipid pcid; 125 bhnd_erom_class_t *cls; 126 127 /* The default implementation of BHND_BUS_GET_EROM_CLASS() 128 * returns NULL if unimplemented; this should always be safe 129 * to call on arbitrary drivers */ 130 cls = bhnd_driver_get_erom_class(drivers[i]); 131 if (cls == NULL) 132 continue; 133 134 kobj_class_compile(cls); 135 136 /* Probe the bus */ 137 result = bhnd_erom_probe(cls, eio, hint, &pcid); 138 139 /* The parser did not match if an error was returned */ 140 if (result > 0) 141 continue; 142 143 /* Check for a new highest priority match */ 144 if (erom_cls == NULL || result > prio) { 145 prio = result; 146 147 *cid = pcid; 148 erom_cls = cls; 149 } 150 151 /* Terminate immediately on BUS_PROBE_SPECIFIC */ 152 if (result == BUS_PROBE_SPECIFIC) 153 break; 154 } 155 156 free(drivers, M_TEMP); 157 return (erom_cls); 158 } 159 160 /** 161 * Allocate and return a new device enumeration table parser. 162 * 163 * @param cls The parser class for which an instance will be 164 * allocated. 165 * @param eio The bus I/O callbacks to use when reading the device 166 * enumeration table. 167 * @param cid The device's chip identifier. 168 * 169 * @retval non-NULL success 170 * @retval NULL if an error occured allocating or initializing the 171 * EROM parser. 172 */ 173 bhnd_erom_t * 174 bhnd_erom_alloc(bhnd_erom_class_t *cls, const struct bhnd_chipid *cid, 175 struct bhnd_erom_io *eio) 176 { 177 bhnd_erom_t *erom; 178 int error; 179 180 erom = (bhnd_erom_t *)kobj_create((kobj_class_t)cls, M_BHND, 181 M_WAITOK|M_ZERO); 182 183 if ((error = BHND_EROM_INIT(erom, cid, eio))) { 184 printf("error initializing %s parser at %#jx: %d\n", cls->name, 185 (uintmax_t)cid->enum_addr, error); 186 187 kobj_delete((kobj_t)erom, M_BHND); 188 return (NULL); 189 } 190 191 return (erom); 192 } 193 194 /** 195 * Perform static initialization of a device enumeration table parser. 196 * 197 * This may be used to initialize a caller-allocated erom instance state 198 * during early boot, prior to malloc availability. 199 * 200 * @param cls The parser class for which an instance will be 201 * allocated. 202 * @param erom The erom parser instance to initialize. 203 * @param esize The total available number of bytes allocated for 204 * @p erom. If this is less than is required by @p cls, 205 * ENOMEM will be returned. 206 * @param cid The device's chip identifier. 207 * @param eio The bus I/O callbacks to use when reading the device 208 * enumeration table. 209 * 210 * @retval 0 success 211 * @retval ENOMEM if @p esize is smaller than required by @p cls. 212 * @retval non-zero if an error occurs initializing the EROM parser, 213 * a regular unix error code will be returned. 214 */ 215 int 216 bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom, size_t esize, 217 const struct bhnd_chipid *cid, struct bhnd_erom_io *eio) 218 { 219 kobj_class_t kcls; 220 221 kcls = (kobj_class_t)cls; 222 223 /* Verify allocation size */ 224 if (kcls->size > esize) 225 return (ENOMEM); 226 227 /* Perform instance initialization */ 228 kobj_init_static((kobj_t)erom, kcls); 229 return (BHND_EROM_INIT(erom, cid, eio)); 230 } 231 232 /** 233 * Release any resources held by a @p erom parser previously 234 * initialized via bhnd_erom_init_static(). 235 * 236 * @param erom An erom parser instance previously initialized via 237 * bhnd_erom_init_static(). 238 */ 239 void 240 bhnd_erom_fini_static(bhnd_erom_t *erom) 241 { 242 return (BHND_EROM_FINI(erom)); 243 } 244 245 /** 246 * Release all resources held by a @p erom parser previously 247 * allocated via bhnd_erom_alloc(). 248 * 249 * @param erom An erom parser instance previously allocated via 250 * bhnd_erom_alloc(). 251 */ 252 void 253 bhnd_erom_free(bhnd_erom_t *erom) 254 { 255 BHND_EROM_FINI(erom); 256 kobj_delete((kobj_t)erom, M_BHND); 257 } 258 259 /** 260 * Read the chip identification registers mapped by @p eio, popuating @p cid 261 * with the parsed result 262 * 263 * @param eio A bus I/O instance, configured with a mapping 264 * of the ChipCommon core. 265 * @param[out] cid On success, the parsed chip identification. 266 * 267 * @warning 268 * On early siba(4) devices, the ChipCommon core does not provide 269 * a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions 270 * (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return 271 * an invalid `ncores` value. 272 */ 273 int 274 bhnd_erom_read_chipid(struct bhnd_erom_io *eio, struct bhnd_chipid *cid) 275 { 276 bhnd_addr_t cc_addr; 277 bhnd_size_t cc_size; 278 uint32_t idreg, cc_caps; 279 int error; 280 281 /* Fetch ChipCommon address */ 282 if ((error = bhnd_erom_io_tell(eio, &cc_addr, &cc_size))) 283 return (error); 284 285 /* Read chip identifier */ 286 idreg = bhnd_erom_io_read(eio, CHIPC_ID, 4); 287 288 /* Extract the basic chip info */ 289 cid->chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP); 290 cid->chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG); 291 cid->chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV); 292 cid->chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); 293 cid->ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE); 294 295 /* Populate EROM address */ 296 if (BHND_CHIPTYPE_HAS_EROM(cid->chip_type)) { 297 cid->enum_addr = bhnd_erom_io_read(eio, CHIPC_EROMPTR, 4); 298 } else { 299 cid->enum_addr = cc_addr; 300 } 301 302 /* Populate capability flags */ 303 cc_caps = bhnd_erom_io_read(eio, CHIPC_CAPABILITIES, 4); 304 cid->chip_caps = 0x0; 305 306 if (cc_caps & CHIPC_CAP_BKPLN64) 307 cid->chip_caps |= BHND_CAP_BP64; 308 309 if (cc_caps & CHIPC_CAP_PMU) 310 cid->chip_caps |= BHND_CAP_PMU; 311 312 return (0); 313 } 314 315 316 /** 317 * Attempt to map @p size bytes at @p addr, replacing any existing 318 * @p eio mapping. 319 * 320 * @param eio I/O instance state. 321 * @param addr The address to be mapped. 322 * @param size The number of bytes to be mapped at @p addr. 323 * 324 * @retval 0 success 325 * @retval non-zero if mapping @p addr otherwise fails, a regular 326 * unix error code should be returned. 327 */ 328 int 329 bhnd_erom_io_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, bhnd_size_t size) 330 { 331 return (eio->map(eio, addr, size)); 332 } 333 334 /** 335 * Return the address range mapped by @p eio, if any. 336 * 337 * @param eio I/O instance state. 338 * @param[out] addr The address mapped by @p eio. 339 * @param[out] size The number of bytes mapped at @p addr. 340 * 341 * @retval 0 success 342 * @retval ENXIO if @p eio has no mapping. 343 */ 344 int 345 bhnd_erom_io_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr, 346 bhnd_size_t *size) 347 { 348 return (eio->tell(eio, addr, size)); 349 } 350 351 /** 352 * Read a 1, 2, or 4 byte data item from @p eio, at the given @p offset 353 * relative to @p eio's current mapping. 354 * 355 * @param eio erom I/O callbacks 356 * @param offset read offset. 357 * @param width item width (1, 2, or 4 bytes). 358 */ 359 uint32_t 360 bhnd_erom_io_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width) 361 { 362 return (eio->read(eio, offset, width)); 363 } 364 365 /** 366 * Free all resources held by @p eio. 367 */ 368 void 369 bhnd_erom_io_fini(struct bhnd_erom_io *eio) 370 { 371 if (eio->fini != NULL) 372 return (eio->fini(eio)); 373 } 374 375 /** 376 * Allocate, initialize, and return a new I/O instance that will perform 377 * mapping by allocating SYS_RES_MEMORY resources from @p dev using @p rid. 378 * 379 * @param dev The device to pass to bhnd_alloc_resource() and 380 * bhnd_release_resource() functions. 381 * @param rid The resource ID to be used when allocating memory resources. 382 */ 383 struct bhnd_erom_io * 384 bhnd_erom_iores_new(device_t dev, int rid) 385 { 386 struct bhnd_erom_iores *iores; 387 388 iores = malloc(sizeof(*iores), M_BHND, M_WAITOK | M_ZERO); 389 iores->eio.map = bhnd_erom_iores_map; 390 iores->eio.tell = bhnd_erom_iores_tell; 391 iores->eio.read = bhnd_erom_iores_read; 392 iores->eio.fini = bhnd_erom_iores_fini; 393 394 iores->owner = dev; 395 iores->owner_rid = rid; 396 iores->mapped = NULL; 397 iores->mapped_rid = -1; 398 399 return (&iores->eio); 400 } 401 402 static int 403 bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, 404 bhnd_size_t size) 405 { 406 struct bhnd_erom_iores *iores; 407 408 iores = (struct bhnd_erom_iores *)eio; 409 410 /* Sanity check the addr/size */ 411 if (size == 0) 412 return (EINVAL); 413 414 if (BHND_ADDR_MAX - size < addr) 415 return (EINVAL); /* would overflow */ 416 417 /* Check for an existing mapping */ 418 if (iores->mapped) { 419 /* If already mapped, nothing else to do */ 420 if (rman_get_start(iores->mapped->res) == addr && 421 rman_get_size(iores->mapped->res) == size) 422 { 423 return (0); 424 } 425 426 /* Otherwise, we need to drop the existing mapping */ 427 bhnd_release_resource(iores->owner, SYS_RES_MEMORY, 428 iores->mapped_rid, iores->mapped); 429 iores->mapped = NULL; 430 iores->mapped_rid = -1; 431 } 432 433 /* Try to allocate the new mapping */ 434 iores->mapped_rid = iores->owner_rid; 435 iores->mapped = bhnd_alloc_resource(iores->owner, SYS_RES_MEMORY, 436 &iores->mapped_rid, addr, addr+size-1, size, 437 RF_ACTIVE|RF_SHAREABLE); 438 if (iores->mapped == NULL) { 439 iores->mapped_rid = -1; 440 return (ENXIO); 441 } 442 443 return (0); 444 } 445 446 static int 447 bhnd_erom_iores_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr, 448 bhnd_size_t *size) 449 { 450 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio; 451 452 if (iores->mapped == NULL) 453 return (ENXIO); 454 455 *addr = rman_get_start(iores->mapped->res); 456 *size = rman_get_size(iores->mapped->res); 457 458 return (0); 459 } 460 461 static uint32_t 462 bhnd_erom_iores_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width) 463 { 464 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio; 465 466 if (iores->mapped == NULL) 467 panic("read with invalid mapping"); 468 469 switch (width) { 470 case 1: 471 return (bhnd_bus_read_1(iores->mapped, offset)); 472 case 2: 473 return (bhnd_bus_read_2(iores->mapped, offset)); 474 case 4: 475 return (bhnd_bus_read_4(iores->mapped, offset)); 476 default: 477 panic("invalid width %u", width); 478 } 479 } 480 481 static void 482 bhnd_erom_iores_fini(struct bhnd_erom_io *eio) 483 { 484 struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio; 485 486 /* Release any mapping */ 487 if (iores->mapped) { 488 bhnd_release_resource(iores->owner, SYS_RES_MEMORY, 489 iores->mapped_rid, iores->mapped); 490 iores->mapped = NULL; 491 iores->mapped_rid = -1; 492 } 493 494 free(eio, M_BHND); 495 } 496 497 /** 498 * Initialize an I/O instance that will perform mapping directly from the 499 * given bus space tag and handle. 500 * 501 * @param iobus The I/O instance to be initialized. 502 * @param addr The base address mapped by @p bsh. 503 * @param size The total size mapped by @p bsh. 504 * @param bst Bus space tag for @p bsh. 505 * @param bsh Bus space handle mapping the full bus enumeration space. 506 * 507 * @retval 0 success 508 * @retval non-zero if initializing @p iobus otherwise fails, a regular 509 * unix error code will be returned. 510 */ 511 int 512 bhnd_erom_iobus_init(struct bhnd_erom_iobus *iobus, bhnd_addr_t addr, 513 bhnd_size_t size, bus_space_tag_t bst, bus_space_handle_t bsh) 514 { 515 iobus->eio.map = bhnd_erom_iobus_map; 516 iobus->eio.tell = bhnd_erom_iobus_tell; 517 iobus->eio.read = bhnd_erom_iobus_read; 518 iobus->eio.fini = NULL; 519 520 iobus->addr = addr; 521 iobus->size = size; 522 iobus->bst = bst; 523 iobus->bsh = bsh; 524 iobus->mapped = false; 525 526 return (0); 527 } 528 529 static int 530 bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, 531 bhnd_size_t size) 532 { 533 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio; 534 535 /* Sanity check the addr/size */ 536 if (size == 0) 537 return (EINVAL); 538 539 /* addr+size must not overflow */ 540 if (BHND_ADDR_MAX - size < addr) 541 return (EINVAL); 542 543 /* addr/size must fit within our bus tag's mapping */ 544 if (addr < iobus->addr || size > iobus->size) 545 return (ENXIO); 546 547 if (iobus->size - (addr - iobus->addr) < size) 548 return (ENXIO); 549 550 /* The new addr offset and size must be representible as a bus_size_t */ 551 if ((addr - iobus->addr) > BUS_SPACE_MAXSIZE) 552 return (ENXIO); 553 554 if (size > BUS_SPACE_MAXSIZE) 555 return (ENXIO); 556 557 iobus->offset = addr - iobus->addr; 558 iobus->limit = size; 559 iobus->mapped = true; 560 561 return (0); 562 } 563 564 static int 565 bhnd_erom_iobus_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr, 566 bhnd_size_t *size) 567 { 568 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio; 569 570 if (!iobus->mapped) 571 return (ENXIO); 572 573 *addr = iobus->addr + iobus->offset; 574 *size = iobus->limit; 575 576 return (0); 577 } 578 579 static uint32_t 580 bhnd_erom_iobus_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width) 581 { 582 struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio; 583 584 if (!iobus->mapped) 585 panic("no active mapping"); 586 587 if (iobus->limit < width || iobus->limit - width < offset) 588 panic("invalid offset %#jx", offset); 589 590 switch (width) { 591 case 1: 592 return (bus_space_read_1(iobus->bst, iobus->bsh, 593 iobus->offset + offset)); 594 case 2: 595 return (bus_space_read_2(iobus->bst, iobus->bsh, 596 iobus->offset + offset)); 597 case 4: 598 return (bus_space_read_4(iobus->bst, iobus->bsh, 599 iobus->offset + offset)); 600 default: 601 panic("invalid width %u", width); 602 } 603 } 604