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