PERFORCE change 172676 for review
Rafal Jaworowski
raj at FreeBSD.org
Wed Jan 6 22:08:19 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=172676
Change 172676 by raj at 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 <sys/bus.h>
#include <sys/rman.h>
#include <machine/bus.h>
-#include <machine/ocpbus.h>
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <powerpc/mpc85xx/lbc.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
#include <powerpc/mpc85xx/mpc85xx.h>
-#include <powerpc/mpc85xx/ocpbus.h>
-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_ */
More information about the p4-projects
mailing list