From owner-p4-projects@FreeBSD.ORG Wed Jan 6 22:08:19 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7D7831065693; Wed, 6 Jan 2010 22:08:19 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 417CF106568F for ; Wed, 6 Jan 2010 22:08:19 +0000 (UTC) (envelope-from raj@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 2E71B8FC0C for ; Wed, 6 Jan 2010 22:08:19 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o06M8JBw043672 for ; Wed, 6 Jan 2010 22:08:19 GMT (envelope-from raj@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o06M8JAr043670 for perforce@freebsd.org; Wed, 6 Jan 2010 22:08:19 GMT (envelope-from raj@freebsd.org) Date: Wed, 6 Jan 2010 22:08:19 GMT Message-Id: <201001062208.o06M8JAr043670@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to raj@freebsd.org using -f From: Rafal Jaworowski To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 172676 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Jan 2010 22:08:19 -0000 http://p4web.freebsd.org/chv.cgi?CH=172676 Change 172676 by raj@raj_fdt on 2010/01/06 22:07:36 Convert LBC driver to FDT convention. Temporarily disconnect DS1553 and cfi(4) LBC attachments from the build. Affected files ... .. //depot/projects/fdt/sys/conf/files.powerpc#11 edit .. //depot/projects/fdt/sys/powerpc/mpc85xx/lbc.c#2 edit .. //depot/projects/fdt/sys/powerpc/mpc85xx/lbc.h#2 edit Differences ... ==== //depot/projects/fdt/sys/conf/files.powerpc#11 (text+ko) ==== @@ -29,7 +29,7 @@ dev/adb/adb_mouse.c optional adb dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb -dev/cfi/cfi_bus_lbc.c optional cfi +#dev/cfi/cfi_bus_lbc.c optional cfi dev/fb/fb.c optional sc dev/hwpmc/hwpmc_powerpc.c optional hwpmc dev/kbd/kbd.c optional sc @@ -117,13 +117,13 @@ powerpc/fpu/fpu_sqrt.c optional fpu_emu powerpc/fpu/fpu_subr.c optional fpu_emu powerpc/mpc85xx/atpic.c optional mpc85xx isa -powerpc/mpc85xx/ds1553_bus_lbc.c optional ds1553 mpc85xx +#powerpc/mpc85xx/ds1553_bus_lbc.c optional ds1553 mpc85xx powerpc/mpc85xx/ds1553_core.c optional ds1553 powerpc/mpc85xx/fdt_common.c optional fdt powerpc/mpc85xx/fdtbus.c optional fdt powerpc/mpc85xx/i2c.c optional iicbus fdt powerpc/mpc85xx/isa.c optional mpc85xx isa -#powerpc/mpc85xx/lbc.c optional mpc85xx +powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/mpc85xx.c optional mpc85xx powerpc/mpc85xx/nexus.c optional mpc85xx powerpc/mpc85xx/ocpbus.c optional mpc85xx ==== //depot/projects/fdt/sys/powerpc/mpc85xx/lbc.c#2 (text+ko) ==== @@ -1,8 +1,12 @@ /*- * Copyright (c) 2006-2008, Juniper Networks, Inc. * Copyright (c) 2008 Semihalf, Rafal Czubak + * Copyright (c) 2009 The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed by Semihalf + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,70 +43,54 @@ #include #include #include -#include #include #include -#include +#include +#include + #include -#include -struct lbc_softc { - device_t sc_dev; +#include "fdt_common.h" +#include "ofw_bus_if.h" +#include "lbc.h" - struct resource *sc_res; - bus_space_handle_t sc_bsh; - bus_space_tag_t sc_bst; - int sc_rid; +#define DEBUG +#undef DEBUG - struct rman sc_rman; - vm_offset_t sc_kva[LBC_DEV_MAX]; -}; +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif -struct lbc_devinfo { - int lbc_devtype; - /* LBC child unit. It also represents resource table entry number */ - int lbc_unit; -}; +static __inline void +lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) +{ -/* Resources for MPC8555CDS system */ -const struct lbc_resource mpc85xx_lbc_resources[] = { - /* Boot flash bank */ - { - LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, + bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); +} - /* Second flash bank */ - { - LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, +static __inline uint32_t +lbc_read_reg(struct lbc_softc *sc, bus_size_t off) +{ - /* DS1553 RTC/NVRAM */ - { - LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8, - LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED, - LBCRES_ATOM_DISABLED, 0 - }, + return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); +} - {0} -}; +static MALLOC_DEFINE(M_LBC, "localbus", "localbus devices information"); static int lbc_probe(device_t); static int lbc_attach(device_t); static int lbc_shutdown(device_t); -static int lbc_get_resource(device_t, device_t, int, int, u_long *, - u_long *); static struct resource *lbc_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int lbc_print_child(device_t, device_t); static int lbc_release_resource(device_t, device_t, int, int, struct resource *); -static int lbc_read_ivar(device_t, device_t, int, uintptr_t *); +static const struct ofw_bus_devinfo *lbc_get_devinfo(device_t, device_t); /* * Bus interface definition @@ -115,16 +103,22 @@ /* Bus interface */ DEVMETHOD(bus_print_child, lbc_print_child), - DEVMETHOD(bus_read_ivar, lbc_read_ivar), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, NULL), - DEVMETHOD(bus_get_resource, NULL), DEVMETHOD(bus_alloc_resource, lbc_alloc_resource), DEVMETHOD(bus_release_resource, lbc_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, lbc_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + { 0, 0 } }; @@ -133,23 +127,11 @@ lbc_methods, sizeof(struct lbc_softc) }; + devclass_t lbc_devclass; -DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0); -static __inline void -lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val) -{ - - bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); -} +DRIVER_MODULE(lbc, fdtbus, lbc_driver, lbc_devclass, 0, 0); -static __inline uint32_t -lbc_read_reg(struct lbc_softc *sc, bus_size_t off) -{ - - return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off)); -} - /* * Calculate address mask used by OR(n) registers. Use memory region size to * determine mask value. The size must be a power of two and within the range @@ -176,103 +158,101 @@ return (0xffff8000 << (n - 15)); } -static device_t -lbc_mk_child(device_t dev, const struct lbc_resource *lbcres) +static void +lbc_banks_unmap(struct lbc_softc *sc) { - struct lbc_devinfo *dinfo; - device_t child; + int i; - if (lbcres->lbr_unit > LBC_DEV_MAX - 1) - return (NULL); + for (i = 0; i < LBC_DEV_MAX; i++) { + if (sc->sc_banks[i].size == 0) + continue; - child = device_add_child(dev, NULL, -1); - if (child == NULL) { - device_printf(dev, "could not add LBC child device\n"); - return (NULL); + law_disable(OCP85XX_TGTIF_LBC, sc->sc_banks[i].pa, + sc->sc_banks[i].size); + pmap_unmapdev(sc->sc_banks[i].va, sc->sc_banks[i].size); } - dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO); - dinfo->lbc_devtype = lbcres->lbr_devtype; - dinfo->lbc_unit = lbcres->lbr_unit; - device_set_ivars(child, dinfo); - return (child); } static int -lbc_init_child(device_t dev, device_t child) +lbc_banks_map(struct lbc_softc *sc) { - struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - const struct lbc_resource *res; u_long start, size; - uint32_t regbuff; - int error, unit; + int error, i; - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); - - res = mpc85xx_lbc_resources; - - regbuff = 0; - unit = -1; - for (; res->lbr_devtype; res++) { - if (res->lbr_unit != dinfo->lbc_unit) + for (i = 0; i < LBC_DEV_MAX; i++) { + if (sc->sc_banks[i].size == 0) continue; - start = res->lbr_base_addr; - size = res->lbr_size; - unit = res->lbr_unit; + /* Physical address start/size. */ + start = sc->sc_banks[i].pa; + size = sc->sc_banks[i].size; /* - * Configure LAW for this LBC device and map its physical - * memory region into KVA + * Configure LAW for this LBC bank (CS) and map its physical + * memory region into KVA. */ error = law_enable(OCP85XX_TGTIF_LBC, start, size); if (error) return (error); - sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size); - if (sc->sc_kva[unit] == 0) { - law_disable(OCP85XX_TGTIF_LBC, start, size); + sc->sc_banks[i].va = (vm_offset_t)pmap_mapdev(start, size); + if (sc->sc_banks[i].va == 0) { + lbc_banks_unmap(sc); return (ENOSPC); } + } + return (0); +} + +static int +lbc_banks_enable(struct lbc_softc *sc) +{ + u_long size; + uint32_t regval; + int error, i; + for (i = 0; i < LBC_DEV_MAX; i++) { + size = sc->sc_banks[i].size; + if (size == 0) + continue; /* - * Compute and program BR value + * Compute and program BR value. */ - regbuff |= start; + regval = 0; + regval |= sc->sc_banks[i].pa; - switch (res->lbr_port_size) { + switch (sc->sc_banks[i].width) { case 8: - regbuff |= (1 << 11); + regval |= (1 << 11); break; case 16: - regbuff |= (2 << 11); + regval |= (2 << 11); break; case 32: - regbuff |= (3 << 11); + regval |= (3 << 11); break; default: error = EINVAL; goto fail; } - regbuff |= (res->lbr_decc << 9); - regbuff |= (res->lbr_wp << 8); - regbuff |= (res->lbr_msel << 5); - regbuff |= (res->lbr_atom << 2); - regbuff |= 1; + regval |= (sc->sc_banks[i].decc << 9); + regval |= (sc->sc_banks[i].wp << 8); + regval |= (sc->sc_banks[i].msel << 5); + regval |= (sc->sc_banks[i].atom << 2); + regval |= 1; - lbc_write_reg(sc, LBC85XX_BR(unit), regbuff); + lbc_write_reg(sc, LBC85XX_BR(i), regval); /* - * Compute and program OR value + * Compute and program OR value. */ - regbuff = 0; - regbuff |= lbc_address_mask(size); + regval = 0; + regval |= lbc_address_mask(size); - switch (res->lbr_msel) { + switch (sc->sc_banks[i].msel) { case LBCRES_MSEL_GPCM: /* TODO Add flag support for option registers */ - regbuff |= 0x00000ff7; + regval |= 0x00000ff7; break; case LBCRES_MSEL_FCM: printf("FCM mode not supported yet!"); @@ -285,35 +265,119 @@ error = ENOSYS; goto fail; } + lbc_write_reg(sc, LBC85XX_OR(i), regval); + } + + /* + * Initialize configuration register: + * - enable Local Bus + * - set data buffer control signal function + * - disable parity byte select + * - set ECC parity type + * - set bus monitor timing and timer prescale + */ + lbc_write_reg(sc, LBC85XX_LBCR, 0); + + /* + * Initialize clock ratio register: + * - disable PLL bypass mode + * - configure LCLK delay cycles for the assertion of LALE + * - set system clock divider + */ + lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008); + + return (0); + +fail: + lbc_banks_unmap(sc); + return (error); +} + +static void +fdt_lbc_fixup(phandle_t node, struct lbc_softc *sc, struct lbc_devinfo *di) +{ + pcell_t width; + int bank; + + if (OF_getprop(node, "bank-width", (void *)&width, sizeof(width)) <= 0) + return; - lbc_write_reg(sc, LBC85XX_OR(unit), regbuff); + bank = di->di_bank; + if (sc->sc_banks[bank].size == 0) + return; + + /* Express width in bits. */ + sc->sc_banks[bank].width = width * 8; +} + +static int +fdt_lbc_reg_decode(phandle_t node, struct lbc_softc *sc, + struct lbc_devinfo *di) +{ + u_long start, end, count; + pcell_t *reg, *regptr; + pcell_t addr_cells, size_cells; + int tuple_size, tuples; + int i, rv, bank; + + addr_cells = fdt_parent_addr_cells(node); + if (addr_cells > 0) { + rv = OF_searchprop(OF_parent(node), "#size-cells", + &size_cells, sizeof(size_cells)); + if (rv <= 0) + size_cells = 1; + } else + size_cells = 0; + tuple_size = sizeof(pcell_t) * (addr_cells + size_cells); + tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®); + debugf("addr_cells = %d, size_cells = %d\n", addr_cells, size_cells); + debugf("tuples = %d, tuple size = %d\n", tuples, tuple_size); + if (tuples <= 0) + /* No 'reg' property in this node. */ return (0); + + regptr = reg; + for (i = 0; i < tuples; i++) { + + bank = fdt_data_get((void *)reg, 1); + di->di_bank = bank; + reg += 1; + + /* Get address/size. */ + rv = fdt_data_to_res(reg, addr_cells - 1, size_cells, &start, + &count); + if (rv != 0) { + resource_list_free(&di->di_res); + goto out; + } + reg += addr_cells - 1 + size_cells; + + /* Calculate address range relative to VA base. */ + start = sc->sc_banks[bank].va + start; + end = start + count - 1; + + debugf("reg addr bank = %d, start = %lx, end = %lx, " + "count = %lx\n", bank, start, end, count); + + /* Use bank (CS) cell as rid. */ + resource_list_add(&di->di_res, SYS_RES_MEMORY, bank, start, + end, count); } -fail: - if (unit != -1) { - law_disable(OCP85XX_TGTIF_LBC, start, size); - pmap_unmapdev(sc->sc_kva[unit], size); - return (error); - } else - return (ENOENT); + rv = 0; +out: + free(regptr, M_OFWPROP); + return (rv); } static int lbc_probe(device_t dev) { - device_t parent; - uintptr_t devtype; - int error; - parent = device_get_parent(dev); - error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); - if (error) - return (error); - if (devtype != OCPBUS_DEVTYPE_LBC) + if (!ofw_bus_is_compatible(dev, "fsl,lbc")) return (ENXIO); - device_set_desc(dev, "Freescale MPC85xx Local Bus Controller"); + device_set_desc(dev, "Freescale Local Bus Controller"); return (BUS_PROBE_DEFAULT); } @@ -321,9 +385,15 @@ lbc_attach(device_t dev) { struct lbc_softc *sc; + struct lbc_devinfo *di; struct rman *rm; - const struct lbc_resource *lbcres; - int error; + u_long offset, start, size; + device_t cdev; + phandle_t node, child; + pcell_t *ranges, *rangesptr; + int tuple_size, tuples; + int par_addr_cells; + int bank, error, i; sc = device_get_softc(dev); sc->sc_dev = dev; @@ -336,10 +406,11 @@ sc->sc_bst = rman_get_bustag(sc->sc_res); sc->sc_bsh = rman_get_bushandle(sc->sc_res); + rangesptr = NULL; rm = &sc->sc_rman; rm->rm_type = RMAN_ARRAY; - rm->rm_descr = "MPC85XX Local Bus Space"; + rm->rm_descr = "Local Bus Space"; rm->rm_start = 0UL; rm->rm_end = ~0UL; error = rman_init(rm); @@ -353,34 +424,142 @@ } /* - * Initialize configuration register: - * - enable Local Bus - * - set data buffer control signal function - * - disable parity byte select - * - set ECC parity type - * - set bus monitor timing and timer prescale + * Process 'ranges' property. + */ + node = ofw_bus_get_node(dev); + if ((fdt_addrsize_cells(node, &sc->sc_addr_cells, + &sc->sc_size_cells)) != 0) { + error = ENXIO; + goto fail; + } + + par_addr_cells = fdt_parent_addr_cells(node); + if (par_addr_cells > 2) { + device_printf(dev, "unsupported parent #addr-cells\n"); + error = ERANGE; + goto fail; + } + tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells + + sc->sc_size_cells); + + tuples = OF_getprop_alloc(node, "ranges", tuple_size, + (void **)&ranges); + if (tuples < 0) { + device_printf(dev, "could not retrieve 'ranges' property\n"); + error = ENXIO; + goto fail; + } + rangesptr = ranges; + + debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, " + "tuple_size = %d, tuples = %d\n", par_addr_cells, + sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples); + + if (tuples > 0) + fdt_ranges_dump(ranges, tuples, par_addr_cells, + sc->sc_addr_cells, sc->sc_size_cells); + start = 0; + size = 0; + for (i = 0; i < tuples; i++) { + + /* The first cell is the bank (chip select) number. */ + bank = fdt_data_get((void *)ranges, 1); + if (bank < 0 || bank > LBC_DEV_MAX) { + device_printf(dev, "bank out of range: %d\n", bank); + error = ERANGE; + goto fail; + } + ranges += 1; + + /* + * Remaining cells of the child address define offset into + * this CS. + */ + offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1); + ranges += sc->sc_addr_cells - 1; + + /* Parent bus start address of this bank. */ + start = fdt_data_get((void *)ranges, par_addr_cells); + ranges += par_addr_cells; + + size = fdt_data_get((void *)ranges, sc->sc_size_cells); + ranges += sc->sc_size_cells; + debugf("bank = %d, start = %lx, size = %lx\n", bank, + start, size); + + sc->sc_banks[bank].pa = start + offset; + sc->sc_banks[bank].size = size; + + /* + * Attributes for the bank. + * + * XXX Note there are no DT bindings defined for them at the + * moment, so we need to provide some defaults. + */ + sc->sc_banks[bank].width = 16; + sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM; + sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED; + sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED; + sc->sc_banks[bank].wp = 0; + } + + /* + * Initialize mem-mappings for the LBC banks (i.e. chip selects). */ - lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000); + error = lbc_banks_map(sc); + if (error) + goto fail; /* - * Initialize clock ratio register: - * - disable PLL bypass mode - * - configure LCLK delay cycles for the assertion of LALE - * - set system clock divider + * Walk the localbus and add direct subordinates as our children. */ - lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008); + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + + di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO); + + if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) { + free(di, M_LBC); + device_printf(dev, "could not set up devinfo\n"); + continue; + } + + resource_list_init(&di->di_res); + + if (fdt_lbc_reg_decode(child, sc, di)) { + device_printf(dev, "could not process 'reg' " + "property\n"); + ofw_bus_gen_destroy_devinfo(&di->di_ofw); + free(di, M_LBC); + continue; + } - lbcres = mpc85xx_lbc_resources; + fdt_lbc_fixup(child, sc, di); - for (; lbcres->lbr_devtype; lbcres++) - if (!lbc_mk_child(dev, lbcres)) { - error = ENXIO; - goto fail; + /* Add newbus device for this FDT node */ + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "could not add child: %s\n", + di->di_ofw.obd_name); + resource_list_free(&di->di_res); + ofw_bus_gen_destroy_devinfo(&di->di_ofw); + free(di, M_LBC); + continue; } + debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name, + (void *)child); + device_set_ivars(cdev, di); + } + + /* + * Enable the LBC. + */ + lbc_banks_enable(sc); + free(rangesptr, M_OFWPROP); return (bus_generic_attach(dev)); fail: + free(rangesptr, M_OFWPROP); bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); return (error); } @@ -394,137 +573,114 @@ } static struct resource * -lbc_alloc_resource(device_t dev, device_t child, int type, int *rid, +lbc_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - struct resource *rv; + struct lbc_devinfo *di; + struct resource_list_entry *rle; + struct resource *res; struct rman *rm; - int error; - - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); - - if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ) - return (NULL); + int needactivate; /* We only support default allocations. */ if (start != 0ul || end != ~0ul) return (NULL); + sc = device_get_softc(bus); if (type == SYS_RES_IRQ) - return (bus_alloc_resource(dev, type, rid, start, end, count, + return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); - if (!sc->sc_kva[dinfo->lbc_unit]) { - error = lbc_init_child(dev, child); - if (error) - return (NULL); + /* + * Request for the default allocation with a given rid: use resource + * list stored in the local device info. + */ + if ((di = device_get_ivars(child)) == NULL) + return (NULL); + + if (type == SYS_RES_IOPORT) + type = SYS_RES_MEMORY; + + rid = &di->di_bank; + + rle = resource_list_find(&di->di_res, type, *rid); + if (rle == NULL) { + device_printf(bus, "no default resources for " + "rid = %d, type = %d\n", *rid, type); + return (NULL); } + start = rle->start; + count = rle->count; + end = start + count - 1; - error = lbc_get_resource(dev, child, type, *rid, &start, &count); - if (error) - return (NULL); + sc = device_get_softc(bus); + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; rm = &sc->sc_rman; - end = start + count - 1; - rv = rman_reserve_resource(rm, start, end, count, flags, child); - if (rv != NULL) { - rman_set_bustag(rv, &bs_be_tag); - rman_set_bushandle(rv, rman_get_start(rv)); + + res = rman_reserve_resource(rm, start, end, count, flags, child); + if (res == NULL) { + device_printf(bus, "failed to reserve resource %#lx - %#lx " + "(%#lx)\n", start, end, count); + return (NULL); } - return (rv); -} -static int -lbc_print_child(device_t dev, device_t child) -{ - u_long size, start; - int error, retval, rid; + rman_set_rid(res, *rid); + rman_set_bustag(res, &bs_be_tag); + rman_set_bushandle(res, rman_get_start(res)); - retval = bus_print_child_header(dev, child); + if (needactivate) + if (bus_activate_resource(child, type, *rid, res)) { + device_printf(child, "resource activation failed\n"); + rman_release_resource(res); + return (NULL); + } - rid = 0; - while (1) { - error = lbc_get_resource(dev, child, SYS_RES_MEMORY, rid, - &start, &size); - if (error) - break; - retval += (rid == 0) ? printf(" iomem ") : printf(","); - retval += printf("%#lx", start); - if (size > 1) - retval += printf("-%#lx", start + size - 1); - rid++; - } - - retval += bus_print_child_footer(dev, child); - return (retval); + return (res); } static int -lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +lbc_print_child(device_t dev, device_t child) { - struct lbc_devinfo *dinfo; + struct lbc_devinfo *di; + struct resource_list *rl; + int rv; - if (device_get_parent(child) != dev) - return (EINVAL); + di = device_get_ivars(child); + rl = &di->di_res; - dinfo = device_get_ivars(child); + rv = 0; + rv += bus_print_child_header(dev, child); + rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); + rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + rv += bus_print_child_footer(dev, child); - switch (index) { - case LBC_IVAR_DEVTYPE: - *result = dinfo->lbc_devtype; - return (0); - default: - break; - } - return (EINVAL); + return (rv); } static int lbc_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { + int err; + + if (rman_get_flags(res) & RF_ACTIVE) { + err = bus_deactivate_resource(child, type, rid, res); + if (err) + return (err); + } return (rman_release_resource(res)); } -static int -lbc_get_resource(device_t dev, device_t child, int type, int rid, - u_long *startp, u_long *countp) +static const struct ofw_bus_devinfo * +lbc_get_devinfo(device_t bus, device_t child) { - struct lbc_softc *sc; - struct lbc_devinfo *dinfo; - const struct lbc_resource *lbcres; + struct lbc_devinfo *di; - if (type != SYS_RES_MEMORY) - return (ENOENT); - - /* Currently all LBC devices have a single RID per type. */ - if (rid != 0) - return (ENOENT); - - sc = device_get_softc(dev); - dinfo = device_get_ivars(child); - - if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1))) - return (EINVAL); - - lbcres = mpc85xx_lbc_resources; - - switch (dinfo->lbc_devtype) { - case LBC_DEVTYPE_CFI: - case LBC_DEVTYPE_RTC: - for (; lbcres->lbr_devtype; lbcres++) { - if (dinfo->lbc_unit == lbcres->lbr_unit) { - *startp = sc->sc_kva[lbcres->lbr_unit]; - *countp = lbcres->lbr_size; - return (0); - } - } - default: - return (EDOOFUS); - } - return (0); + di = device_get_ivars(child); + return (&di->di_ofw); } ==== //depot/projects/fdt/sys/powerpc/mpc85xx/lbc.h#2 (text+ko) ==== @@ -29,15 +29,9 @@ #ifndef _MACHINE_LBC_H_ #define _MACHINE_LBC_H_ -#define LBC_IVAR_DEVTYPE 1 - /* Maximum number of devices on Local Bus */ #define LBC_DEV_MAX 8 -/* Device types. */ -#define LBC_DEVTYPE_CFI 1 -#define LBC_DEVTYPE_RTC 2 - /* Local access registers */ #define LBC85XX_BR(n) (8 * n) #define LBC85XX_OR(n) (4 + (8 * n)) @@ -61,18 +55,42 @@ #define LBCRES_ATOM_RAWA 1 #define LBCRES_ATOM_WARA 2 -struct lbc_resource { - int lbr_devtype; /* LBC device type */ - int lbr_unit; /* Resource table entry number */ - vm_paddr_t lbr_base_addr; /* Device mem region base address */ - size_t lbr_size; /* Device mem region size */ - int lbr_port_size; /* Data bus width */ - uint8_t lbr_msel; /* LBC machine select */ - uint8_t lbr_decc; /* Data error checking mode */ - uint8_t lbr_atom; /* Atomic operation mode */ - uint8_t lbr_wp; /* Write protect */ +struct lbc_bank { + u_long pa; /* physical addr of the bank */ + u_long size; /* bank size */ + vm_offset_t va; /* VA of the bank */ + + /* + * XXX the following bank attributes do not have properties specified + * in the LBC DTS bindings yet (11.2009), so they are mainly a + * placeholder for future extensions. + */ + int width; /* data bus width */ + uint8_t msel; /* machine select */ + uint8_t atom; /* atomic op mode */ + uint8_t wp; /* write protect */ + uint8_t decc; /* data error checking */ +}; + +struct lbc_softc { + device_t sc_dev; + struct resource *sc_res; + bus_space_handle_t sc_bsh; + bus_space_tag_t sc_bst; + int sc_rid; + + struct rman sc_rman; + + int sc_addr_cells; + int sc_size_cells; + + struct lbc_bank sc_banks[LBC_DEV_MAX]; }; -extern const struct lbc_resource mpc85xx_lbc_resources[]; +struct lbc_devinfo { + struct ofw_bus_devinfo di_ofw; + struct resource_list di_res; + int di_bank; +}; #endif /* _MACHINE_LBC_H_ */