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 **)&reg);
+	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