Exemple #1
0
/*
 * Since this is not a self-enumerating bus, and since we always add
 * children in attach, we have to always delete children here.
 */
static int
gpiobus_detach(device_t dev)
{
	struct gpiobus_softc *sc;
	struct gpiobus_ivar *devi;
	device_t *devlist;
	int i, err, ndevs;

	sc = GPIOBUS_SOFTC(dev);
	KASSERT(mtx_initialized(&sc->sc_mtx),
	    ("gpiobus mutex not initialized"));
	GPIOBUS_LOCK_DESTROY(sc);

	if ((err = bus_generic_detach(dev)) != 0)
		return (err);

	if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
		return (err);
	for (i = 0; i < ndevs; i++) {
		device_delete_child(dev, devlist[i]);
		devi = GPIOBUS_IVAR(devlist[i]);
		if (devi->pins) {
			free(devi->pins, M_DEVBUF);
			devi->pins = NULL;
		}
	}
	free(devlist, M_TEMP);

	if (sc->sc_pins_mapped) {
		free(sc->sc_pins_mapped, M_DEVBUF);
		sc->sc_pins_mapped = NULL;
	}

	return (0);
}
Exemple #2
0
static struct resource_list *
gpiobus_get_resource_list(device_t bus __unused, device_t child)
{
	struct gpiobus_ivar *ivar;

	ivar = GPIOBUS_IVAR(child);

	return (&ivar->rl);
}
Exemple #3
0
static int
gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);

	if (pin >= devi->npins)
		return (EINVAL);

	return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]);
}
Exemple #4
0
static int
gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin, 
    uint32_t *caps)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);

	if (pin >= devi->npins)
		return (EINVAL);

	return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps);
}
Exemple #5
0
static int
gpiobus_pin_get(device_t dev, device_t child, uint32_t pin, 
    unsigned int *value)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);

	if (pin >= devi->npins)
		return (EINVAL);

	return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value);
}
Exemple #6
0
static int
gpiobus_child_location_str(device_t bus, device_t child, char *buf,
    size_t buflen)
{
	struct gpiobus_ivar *devi;

	devi = GPIOBUS_IVAR(child);
	strlcpy(buf, "pin(s)=", buflen);
	gpiobus_print_pins(devi, buf, buflen);

	return (0);
}
Exemple #7
0
static int
gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 
    uint32_t flags)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);

	if (pin >= devi->npins)
		return (EINVAL);

	return GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags);
}
Exemple #8
0
static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
	int i, npins;

	npins = 0;
	for (i = 0; i < 32; i++) {
		if (mask & (1 << i))
			npins++;
	}

	if (npins == 0) {
		device_printf(child, "empty pin mask\n");
		return (EINVAL);
	}

	devi->npins = npins;
	devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, 
	    M_NOWAIT | M_ZERO);

	if (!devi->pins)
		return (ENOMEM);

	npins = 0;
	for (i = 0; i < 32; i++) {

		if ((mask & (1 << i)) == 0)
			continue;

		if (i >= sc->sc_npins) {
			device_printf(child, 
			    "invalid pin %d, max: %d\n", i, sc->sc_npins - 1);
			free(devi->pins, M_DEVBUF);
			return (EINVAL);
		}

		devi->pins[npins++] = i;
		/*
		 * Mark pin as mapped and give warning if it's already mapped
		 */
		if (sc->sc_pins_mapped[i]) {
			device_printf(child, 
			    "warning: pin %d is already mapped\n", i);
			free(devi->pins, M_DEVBUF);
			return (EINVAL);
		}
		sc->sc_pins_mapped[i] = 1;
	}

	return (0);
}
Exemple #9
0
static int
gpiobus_print_child(device_t dev, device_t child)
{
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
	int retval = 0;

	retval += bus_print_child_header(dev, child);
	retval += printf(" at pin(s) ");
	gpiobus_print_pins(devi);
	retval += bus_print_child_footer(dev, child);

	return (retval);
}
Exemple #10
0
static void
gpiobus_probe_nomatch(device_t dev, device_t child)
{
	char pins[128];
	struct gpiobus_ivar *devi;

	devi = GPIOBUS_IVAR(child);
	memset(pins, 0, sizeof(pins));
	gpiobus_print_pins(devi, pins, sizeof(pins));
	device_printf(dev, "<unknown device> at pin(s) %s", pins);
	resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
	printf("\n");
}
Exemple #11
0
static void
gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
	struct gpiobus_ivar *devi;
	device_t child;
	int pins;


	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
	devi = GPIOBUS_IVAR(child);
	resource_int_value(dname, dunit, "pins", &pins);
	if (gpiobus_parse_pins(sc, child, pins))
		device_delete_child(bus, child);
}
Exemple #12
0
static int
gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 
    uint32_t flags)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
	uint32_t caps;

	if (pin >= devi->npins)
		return (EINVAL);
	if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0)
		return (EINVAL);
	if (gpio_check_flags(caps, flags) != 0)
		return (EINVAL);

	return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags));
}
Exemple #13
0
static int
gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
    u_long start, u_long count)
{
	struct gpiobus_ivar *devi;
	struct resource_list_entry *rle;

	dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
	    __func__, dev, child, type, rid, (void *)(intptr_t)start, count);
	devi = GPIOBUS_IVAR(child);
	rle = resource_list_add(&devi->rl, type, rid, start,
	    start + count - 1, count);
	if (rle == NULL)
		return (ENXIO);

	return (0);
}
Exemple #14
0
static int
gpioiic_attach(device_t dev)
{
	device_t		bitbang;
#ifdef FDT
	phandle_t		node;
	pcell_t			pin;
#endif
	struct gpiobus_ivar	*devi;
	struct gpioiic_softc	*sc;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	sc->sc_busdev = device_get_parent(dev);
	if (resource_int_value(device_get_name(dev),
		device_get_unit(dev), "scl", &sc->scl_pin))
		sc->scl_pin = SCL_PIN_DEFAULT;
	if (resource_int_value(device_get_name(dev),
		device_get_unit(dev), "sda", &sc->sda_pin))
		sc->sda_pin = SDA_PIN_DEFAULT;

#ifdef FDT
	if ((node = ofw_bus_get_node(dev)) == -1)
		return (ENXIO);
	if (OF_getencprop(node, "scl", &pin, sizeof(pin)) > 0)
		sc->scl_pin = (int)pin;
	if (OF_getencprop(node, "sda", &pin, sizeof(pin)) > 0)
		sc->sda_pin = (int)pin;
#endif

	if (sc->scl_pin < 0 || sc->scl_pin > 1)
		sc->scl_pin = SCL_PIN_DEFAULT;
	if (sc->sda_pin < 0 || sc->sda_pin > 1)
		sc->sda_pin = SDA_PIN_DEFAULT;

	devi = GPIOBUS_IVAR(dev);
	device_printf(dev, "SCL pin: %d, SDA pin: %d\n",
	    devi->pins[sc->scl_pin], devi->pins[sc->sda_pin]);

	/* add generic bit-banging code */
	bitbang = device_add_child(dev, "iicbb", -1);
	device_probe_and_attach(bitbang);

	return (0);
}
Exemple #15
0
static int
gpiobus_print_child(device_t dev, device_t child)
{
	char pins[128];
	int retval = 0;
	struct gpiobus_ivar *devi;

	devi = GPIOBUS_IVAR(child);
	memset(pins, 0, sizeof(pins));
	retval += bus_print_child_header(dev, child);
	retval += printf(" at pin(s) ");
	gpiobus_print_pins(devi, pins, sizeof(pins));
	retval += printf("%s", pins);
	resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
	retval += bus_print_child_footer(dev, child);

	return (retval);
}
Exemple #16
0
static void
gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
	struct gpiobus_ivar *devi;
	device_t child;
	int irq, pins;

	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
	devi = GPIOBUS_IVAR(child);
	resource_int_value(dname, dunit, "pins", &pins);
	if (gpiobus_parse_pins(sc, child, pins))
		device_delete_child(bus, child);
	if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
		if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
			device_printf(bus,
			    "warning: bus_set_resource() failed\n");
	}
}
Exemple #17
0
/*
 * Since this is not a self-enumerating bus, and since we always add
 * children in attach, we have to always delete children here.
 */
static int
gpiobus_detach(device_t dev)
{
	struct gpiobus_softc *sc;
	struct gpiobus_ivar *devi;
	device_t *devlist;
	int i, err, ndevs;

	sc = GPIOBUS_SOFTC(dev);
	KASSERT(mtx_initialized(&sc->sc_mtx),
	    ("gpiobus mutex not initialized"));
	GPIOBUS_LOCK_DESTROY(sc);

	if ((err = bus_generic_detach(dev)) != 0)
		return (err);

	if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
		return (err);
	for (i = 0; i < ndevs; i++) {
		devi = GPIOBUS_IVAR(devlist[i]);
		gpiobus_free_ivars(devi);
		resource_list_free(&devi->rl);
		free(devi, M_DEVBUF);
		device_delete_child(dev, devlist[i]);
	}
	free(devlist, M_TEMP);
	rman_fini(&sc->sc_intr_rman);
	if (sc->sc_pins) {
		for (i = 0; i < sc->sc_npins; i++) {
			if (sc->sc_pins[i].name != NULL)
				free(sc->sc_pins[i].name, M_DEVBUF);
			sc->sc_pins[i].name = NULL;
		}
		free(sc->sc_pins, M_DEVBUF);
		sc->sc_pins = NULL;
	}

	return (0);
}
Exemple #18
0
static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
	int i, npins;

	npins = 0;
	for (i = 0; i < 32; i++) {
		if (mask & (1 << i))
			npins++;
	}
	if (npins == 0) {
		device_printf(child, "empty pin mask\n");
		return (EINVAL);
	}
	devi->npins = npins;
	if (gpiobus_alloc_ivars(devi) != 0) {
		device_printf(child, "cannot allocate device ivars\n");
		return (EINVAL);
	}
	npins = 0;
	for (i = 0; i < 32; i++) {
		if ((mask & (1 << i)) == 0)
			continue;
		/* Reserve the GPIO pin. */
		if (gpiobus_map_pin(sc->sc_busdev, i) != 0) {
			gpiobus_free_ivars(devi);
			return (EINVAL);
		}
		devi->pins[npins++] = i;
		/* Use the child name as pin name. */
		GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
		    device_get_nameunit(child));
	}

	return (0);
}