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