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