1 /*- 2 * Copyright (c) 2006-2008, Juniper Networks, Inc. 3 * Copyright (c) 2008 Semihalf, Rafal Czubak 4 * Copyright (c) 2009 The FreeBSD Foundation 5 * All rights reserved. 6 * 7 * Portions of this software were developed by Semihalf 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/ktr.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/module.h> 43 #include <sys/bus.h> 44 #include <sys/rman.h> 45 #include <machine/bus.h> 46 47 #include <vm/vm.h> 48 #include <vm/pmap.h> 49 50 #include <dev/fdt/fdt_common.h> 51 #include <dev/ofw/ofw_bus.h> 52 #include <dev/ofw/ofw_bus_subr.h> 53 54 #include <powerpc/mpc85xx/mpc85xx.h> 55 56 #include "ofw_bus_if.h" 57 #include "lbc.h" 58 59 #define DEBUG 60 #undef DEBUG 61 62 #ifdef DEBUG 63 #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ 64 printf(fmt,##args); } while (0) 65 #else 66 #define debugf(fmt, args...) 67 #endif 68 69 static __inline void 70 lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) 71 { 72 73 bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); 74 } 75 76 static __inline uint32_t 77 lbc_read_reg(struct lbc_softc *sc, bus_size_t off) 78 { 79 80 return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); 81 } 82 83 static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information"); 84 85 static int lbc_probe(device_t); 86 static int lbc_attach(device_t); 87 static int lbc_shutdown(device_t); 88 static struct resource *lbc_alloc_resource(device_t, device_t, int, int *, 89 u_long, u_long, u_long, u_int); 90 static int lbc_print_child(device_t, device_t); 91 static int lbc_release_resource(device_t, device_t, int, int, 92 struct resource *); 93 static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t); 94 95 /* 96 * Bus interface definition 97 */ 98 static device_method_t lbc_methods[] = { 99 /* Device interface */ 100 DEVMETHOD(device_probe, lbc_probe), 101 DEVMETHOD(device_attach, lbc_attach), 102 DEVMETHOD(device_shutdown, lbc_shutdown), 103 104 /* Bus interface */ 105 DEVMETHOD(bus_print_child, lbc_print_child), 106 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 107 DEVMETHOD(bus_teardown_intr, NULL), 108 109 DEVMETHOD(bus_alloc_resource, lbc_alloc_resource), 110 DEVMETHOD(bus_release_resource, lbc_release_resource), 111 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 112 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 113 114 /* OFW bus interface */ 115 DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo), 116 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 117 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 118 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 119 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 120 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 121 122 { 0, 0 } 123 }; 124 125 static driver_t lbc_driver = { 126 "lbc", 127 lbc_methods, 128 sizeof(struct lbc_softc) 129 }; 130 131 devclass_t lbc_devclass; 132 133 DRIVER_MODULE(lbc, fdtbus, lbc_driver, lbc_devclass, 0, 0); 134 135 /* 136 * Calculate address mask used by OR(n) registers. Use memory region size to 137 * determine mask value. The size must be a power of two and within the range 138 * of 32KB - 4GB. Otherwise error code is returned. Value representing 139 * 4GB size can be passed as 0xffffffff. 140 */ 141 static uint32_t 142 lbc_address_mask(uint32_t size) 143 { 144 int n = 15; 145 146 if (size == ~0UL) 147 return (0); 148 149 while (n < 32) { 150 if (size == (1UL << n)) 151 break; 152 n++; 153 } 154 155 if (n == 32) 156 return (EINVAL); 157 158 return (0xffff8000 << (n - 15)); 159 } 160 161 static void 162 lbc_banks_unmap(struct lbc_softc *sc) 163 { 164 int i; 165 166 for (i = 0; i < LBC_DEV_MAX; i++) { 167 if (sc->sc_banks[i].size == 0) 168 continue; 169 170 law_disable(OCP85XX_TGTIF_LBC, sc->sc_banks[i].pa, 171 sc->sc_banks[i].size); 172 pmap_unmapdev(sc->sc_banks[i].va, sc->sc_banks[i].size); 173 } 174 } 175 176 static int 177 lbc_banks_map(struct lbc_softc *sc) 178 { 179 u_long start, size; 180 int error, i; 181 182 for (i = 0; i < LBC_DEV_MAX; i++) { 183 if (sc->sc_banks[i].size == 0) 184 continue; 185 186 /* Physical address start/size. */ 187 start = sc->sc_banks[i].pa; 188 size = sc->sc_banks[i].size; 189 190 /* 191 * Configure LAW for this LBC bank (CS) and map its physical 192 * memory region into KVA. 193 */ 194 error = law_enable(OCP85XX_TGTIF_LBC, start, size); 195 if (error) 196 return (error); 197 198 sc->sc_banks[i].va = (vm_offset_t)pmap_mapdev(start, size); 199 if (sc->sc_banks[i].va == 0) { 200 lbc_banks_unmap(sc); 201 return (ENOSPC); 202 } 203 } 204 return (0); 205 } 206 207 static int 208 lbc_banks_enable(struct lbc_softc *sc) 209 { 210 u_long size; 211 uint32_t regval; 212 int error, i; 213 214 for (i = 0; i < LBC_DEV_MAX; i++) { 215 size = sc->sc_banks[i].size; 216 if (size == 0) 217 continue; 218 /* 219 * Compute and program BR value. 220 */ 221 regval = 0; 222 regval |= sc->sc_banks[i].pa; 223 224 switch (sc->sc_banks[i].width) { 225 case 8: 226 regval |= (1 << 11); 227 break; 228 case 16: 229 regval |= (2 << 11); 230 break; 231 case 32: 232 regval |= (3 << 11); 233 break; 234 default: 235 error = EINVAL; 236 goto fail; 237 } 238 regval |= (sc->sc_banks[i].decc << 9); 239 regval |= (sc->sc_banks[i].wp << 8); 240 regval |= (sc->sc_banks[i].msel << 5); 241 regval |= (sc->sc_banks[i].atom << 2); 242 regval |= 1; 243 244 lbc_write_reg(sc, LBC85XX_BR(i), regval); 245 246 /* 247 * Compute and program OR value. 248 */ 249 regval = 0; 250 regval |= lbc_address_mask(size); 251 252 switch (sc->sc_banks[i].msel) { 253 case LBCRES_MSEL_GPCM: 254 /* TODO Add flag support for option registers */ 255 regval |= 0x00000ff7; 256 break; 257 case LBCRES_MSEL_FCM: 258 printf("FCM mode not supported yet!"); 259 error = ENOSYS; 260 goto fail; 261 case LBCRES_MSEL_UPMA: 262 case LBCRES_MSEL_UPMB: 263 case LBCRES_MSEL_UPMC: 264 printf("UPM mode not supported yet!"); 265 error = ENOSYS; 266 goto fail; 267 } 268 lbc_write_reg(sc, LBC85XX_OR(i), regval); 269 } 270 271 /* 272 * Initialize configuration register: 273 * - enable Local Bus 274 * - set data buffer control signal function 275 * - disable parity byte select 276 * - set ECC parity type 277 * - set bus monitor timing and timer prescale 278 */ 279 lbc_write_reg(sc, LBC85XX_LBCR, 0); 280 281 /* 282 * Initialize clock ratio register: 283 * - disable PLL bypass mode 284 * - configure LCLK delay cycles for the assertion of LALE 285 * - set system clock divider 286 */ 287 lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008); 288 289 return (0); 290 291 fail: 292 lbc_banks_unmap(sc); 293 return (error); 294 } 295 296 static void 297 fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di) 298 { 299 pcell_t width; 300 int bank; 301 302 if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0) 303 return; 304 305 bank = di->di_bank; 306 if (sc->sc_banks[bank].size == 0) 307 return; 308 309 /* Express width in bits. */ 310 sc->sc_banks[bank].width = width * 8; 311 } 312 313 static int 314 fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc, 315 struct lbc_devinfo *di) 316 { 317 u_long start, end, count; 318 pcell_t *reg, *regptr; 319 pcell_t addr_cells, size_cells; 320 int tuple_size, tuples; 321 int i, rv, bank; 322 323 if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0) 324 return (ENXIO); 325 326 tuple_size = sizeof(pcell_t) * (addr_cells + size_cells); 327 tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®); 328 debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells); 329 debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size); 330 if (tuples <= 0) 331 /* No 'reg' property in this node. */ 332 return (0); 333 334 regptr = reg; 335 for (i = 0; i < tuples; i++) { 336 337 bank = fdt_data_get((void *)reg, 1); 338 di->di_bank = bank; 339 reg += 1; 340 341 /* Get address/size. */ 342 rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start, 343 &count); 344 if (rv != 0) { 345 resource_list_free(&di->di_res); 346 goto out; 347 } 348 reg += addr_cells - 1 + size_cells; 349 350 /* Calculate address range relative to VA base. */ 351 start = sc->sc_banks[bank].va + start; 352 end = start + count - 1; 353 354 debugf("reg addr bank = %d, start = %lx, end = %lx, " 355 "count = %lx\n", bank, start, end, count); 356 357 /* Use bank (CS) cell as rid. */ 358 resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start, 359 end, count); 360 } 361 rv = 0; 362 out: 363 free(regptr, M_OFWPROP); 364 return (rv); 365 } 366 367 static int 368 lbc_probe(device_t dev) 369 { 370 371 if (!(ofw_bus_is_compatible(dev, "fsl,lbc") || 372 ofw_bus_is_compatible(dev, "fsl,elbc"))) 373 return (ENXIO); 374 375 device_set_desc(dev, "Freescale Local Bus Controller"); 376 return (BUS_PROBE_DEFAULT); 377 } 378 379 static int 380 lbc_attach(device_t dev) 381 { 382 struct lbc_softc *sc; 383 struct lbc_devinfo *di; 384 struct rman *rm; 385 u_long offset, start, size; 386 device_t cdev; 387 phandle_t node, child; 388 pcell_t *ranges, *rangesptr; 389 int tuple_size, tuples; 390 int par_addr_cells; 391 int bank, error, i; 392 393 sc = device_get_softc(dev); 394 sc->sc_dev = dev; 395 396 sc->sc_rid = 0; 397 sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, 398 RF_ACTIVE); 399 if (sc->sc_res == NULL) 400 return (ENXIO); 401 402 sc->sc_bst = rman_get_bustag(sc->sc_res); 403 sc->sc_bsh = rman_get_bushandle(sc->sc_res); 404 rangesptr = NULL; 405 406 rm = &sc->sc_rman; 407 rm->rm_type = RMAN_ARRAY; 408 rm->rm_descr = "Local Bus Space"; 409 rm->rm_start = 0UL; 410 rm->rm_end = ~0UL; 411 error = rman_init(rm); 412 if (error) 413 goto fail; 414 415 error = rman_manage_region(rm, rm->rm_start, rm->rm_end); 416 if (error) { 417 rman_fini(rm); 418 goto fail; 419 } 420 421 /* 422 * Process 'ranges' property. 423 */ 424 node = ofw_bus_get_node(dev); 425 if ((fdt_addrsize_cells(node, &sc->sc_addr_cells, 426 &sc->sc_size_cells)) != 0) { 427 error = ENXIO; 428 goto fail; 429 } 430 431 par_addr_cells = fdt_parent_addr_cells(node); 432 if (par_addr_cells > 2) { 433 device_printf(dev, "unsupported parent #addr-cells\n"); 434 error = ERANGE; 435 goto fail; 436 } 437 tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells + 438 sc->sc_size_cells); 439 440 tuples = OF_getprop_alloc(node, "ranges", tuple_size, 441 (void **)&ranges); 442 if (tuples < 0) { 443 device_printf(dev, "could not retrieve 'ranges' property\n"); 444 error = ENXIO; 445 goto fail; 446 } 447 rangesptr = ranges; 448 449 debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, " 450 "tuple_size = %d, tuples = %d\n", par_addr_cells, 451 sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples); 452 453 start = 0; 454 size = 0; 455 for (i = 0; i < tuples; i++) { 456 457 /* The first cell is the bank (chip select) number. */ 458 bank = fdt_data_get((void *)ranges, 1); 459 if (bank < 0 || bank > LBC_DEV_MAX) { 460 device_printf(dev, "bank out of range: %d\n", bank); 461 error = ERANGE; 462 goto fail; 463 } 464 ranges += 1; 465 466 /* 467 * Remaining cells of the child address define offset into 468 * this CS. 469 */ 470 offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1); 471 ranges += sc->sc_addr_cells - 1; 472 473 /* Parent bus start address of this bank. */ 474 start = fdt_data_get((void *)ranges, par_addr_cells); 475 ranges += par_addr_cells; 476 477 size = fdt_data_get((void *)ranges, sc->sc_size_cells); 478 ranges += sc->sc_size_cells; 479 debugf("bank = %d, start = %lx, size = %lx\n", bank, 480 start, size); 481 482 sc->sc_banks[bank].pa = start + offset; 483 sc->sc_banks[bank].size = size; 484 485 /* 486 * Attributes for the bank. 487 * 488 * XXX Note there are no DT bindings defined for them at the 489 * moment, so we need to provide some defaults. 490 */ 491 sc->sc_banks[bank].width = 16; 492 sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM; 493 sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED; 494 sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED; 495 sc->sc_banks[bank].wp = 0; 496 } 497 498 /* 499 * Initialize mem-mappings for the LBC banks (i.e. chip selects). 500 */ 501 error = lbc_banks_map(sc); 502 if (error) 503 goto fail; 504 505 /* 506 * Walk the localbus and add direct subordinates as our children. 507 */ 508 for (child = OF_child(node); child != 0; child = OF_peer(child)) { 509 510 di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO); 511 512 if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) { 513 free(di, M_LBC); 514 device_printf(dev, "could not set up devinfo\n"); 515 continue; 516 } 517 518 resource_list_init(&di->di_res); 519 520 if (fdt_lbc_reg_decode(child, sc, di)) { 521 device_printf(dev, "could not process 'reg' " 522 "property\n"); 523 ofw_bus_gen_destroy_devinfo(&di->di_ofw); 524 free(di, M_LBC); 525 continue; 526 } 527 528 fdt_lbc_fixup(child, sc, di); 529 530 /* Add newbus device for this FDT node */ 531 cdev = device_add_child(dev, NULL, -1); 532 if (cdev == NULL) { 533 device_printf(dev, "could not add child: %s\n", 534 di->di_ofw.obd_name); 535 resource_list_free(&di->di_res); 536 ofw_bus_gen_destroy_devinfo(&di->di_ofw); 537 free(di, M_LBC); 538 continue; 539 } 540 debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name, 541 (void *)child); 542 device_set_ivars(cdev, di); 543 } 544 545 /* 546 * Enable the LBC. 547 */ 548 lbc_banks_enable(sc); 549 550 free(rangesptr, M_OFWPROP); 551 return (bus_generic_attach(dev)); 552 553 fail: 554 free(rangesptr, M_OFWPROP); 555 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 556 return (error); 557 } 558 559 static int 560 lbc_shutdown(device_t dev) 561 { 562 563 /* TODO */ 564 return(0); 565 } 566 567 static struct resource * 568 lbc_alloc_resource(device_t bus, device_t child, int type, int *rid, 569 u_long start, u_long end, u_long count, u_int flags) 570 { 571 struct lbc_softc *sc; 572 struct lbc_devinfo *di; 573 struct resource_list_entry *rle; 574 struct resource *res; 575 struct rman *rm; 576 int needactivate; 577 578 /* We only support default allocations. */ 579 if (start != 0ul || end != ~0ul) 580 return (NULL); 581 582 sc = device_get_softc(bus); 583 if (type == SYS_RES_IRQ) 584 return (bus_alloc_resource(bus, type, rid, start, end, count, 585 flags)); 586 587 /* 588 * Request for the default allocation with a given rid: use resource 589 * list stored in the local device info. 590 */ 591 if ((di = device_get_ivars(child)) == NULL) 592 return (NULL); 593 594 if (type == SYS_RES_IOPORT) 595 type = SYS_RES_MEMORY; 596 597 rid = &di->di_bank; 598 599 rle = resource_list_find(&di->di_res, type, *rid); 600 if (rle == NULL) { 601 device_printf(bus, "no default resources for " 602 "rid = %d, type = %d\n", *rid, type); 603 return (NULL); 604 } 605 start = rle->start; 606 count = rle->count; 607 end = start + count - 1; 608 609 sc = device_get_softc(bus); 610 611 needactivate = flags & RF_ACTIVE; 612 flags &= ~RF_ACTIVE; 613 614 rm = &sc->sc_rman; 615 616 res = rman_reserve_resource(rm, start, end, count, flags, child); 617 if (res == NULL) { 618 device_printf(bus, "failed to reserve resource %#lx - %#lx " 619 "(%#lx)\n", start, end, count); 620 return (NULL); 621 } 622 623 rman_set_rid(res, *rid); 624 rman_set_bustag(res, &bs_be_tag); 625 rman_set_bushandle(res, rman_get_start(res)); 626 627 if (needactivate) 628 if (bus_activate_resource(child, type, *rid, res)) { 629 device_printf(child, "resource activation failed\n"); 630 rman_release_resource(res); 631 return (NULL); 632 } 633 634 return (res); 635 } 636 637 static int 638 lbc_print_child(device_t dev, device_t child) 639 { 640 struct lbc_devinfo *di; 641 struct resource_list *rl; 642 int rv; 643 644 di = device_get_ivars(child); 645 rl = &di->di_res; 646 647 rv = 0; 648 rv += bus_print_child_header(dev, child); 649 rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); 650 rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); 651 rv += bus_print_child_footer(dev, child); 652 653 return (rv); 654 } 655 656 static int 657 lbc_release_resource(device_t dev, device_t child, int type, int rid, 658 struct resource *res) 659 { 660 int err; 661 662 if (rman_get_flags(res) & RF_ACTIVE) { 663 err = bus_deactivate_resource(child, type, rid, res); 664 if (err) 665 return (err); 666 } 667 668 return (rman_release_resource(res)); 669 } 670 671 static const struct ofw_bus_devinfo * 672 lbc_get_devinfo(device_t bus, device_t child) 673 { 674 struct lbc_devinfo *di; 675 676 di = device_get_ivars(child); 677 return (&di->di_ofw); 678 } 679