Пример #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);
}
Пример #2
0
int
gpiobus_init_softc(device_t dev)
{
	struct gpiobus_softc *sc;

	sc = GPIOBUS_SOFTC(dev);
	sc->sc_busdev = dev;
	sc->sc_dev = device_get_parent(dev);
	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
	sc->sc_intr_rman.rm_descr = "GPIO Interrupts";
	if (rman_init(&sc->sc_intr_rman) != 0 ||
	    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0)
		panic("%s: failed to set up rman.", __func__);

	if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
		return (ENXIO);

	KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));

	/* Pins = GPIO_PIN_MAX() + 1 */
	sc->sc_npins++;

	sc->sc_pins = malloc(sizeof(*sc->sc_pins) * sc->sc_npins, M_DEVBUF,
	    M_NOWAIT | M_ZERO);
	if (sc->sc_pins == NULL)
		return (ENOMEM);

	/* Initialize the bus lock. */
	GPIOBUS_LOCK_INIT(sc);

	return (0);
}
Пример #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]);
}
Пример #4
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);
}
Пример #5
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
0
static int
gpiobus_pin_getname(device_t dev, uint32_t pin, char *name)
{
	struct gpiobus_softc *sc;

	sc = GPIOBUS_SOFTC(dev);
	if (pin > sc->sc_npins)
		return (EINVAL);
	/* Did we have a name for this pin ? */
	if (sc->sc_pins[pin].name != NULL) {
		memcpy(name, sc->sc_pins[pin].name, GPIOMAXNAME);
		return (0);
	}

	/* Return the default pin name. */
	return (GPIO_PIN_GETNAME(device_get_parent(dev), pin, name));
}
Пример #9
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));
}
Пример #10
0
static int
gpiobus_pin_setname(device_t dev, uint32_t pin, const char *name)
{
	struct gpiobus_softc *sc;

	sc = GPIOBUS_SOFTC(dev);
	if (pin > sc->sc_npins)
		return (EINVAL);
	if (name == NULL)
		return (EINVAL);
	/* Save the pin name. */
	if (sc->sc_pins[pin].name == NULL)
		sc->sc_pins[pin].name = malloc(GPIOMAXNAME, M_DEVBUF,
		    M_WAITOK | M_ZERO);
	strlcpy(sc->sc_pins[pin].name, name, GPIOMAXNAME);

	return (0);
}
Пример #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 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");
	}
}
Пример #12
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);
}
Пример #13
0
static int
gpiobus_attach(device_t dev)
{
	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
	int res;

	sc->sc_busdev = dev;
	sc->sc_dev = device_get_parent(dev);
	res = GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins);
	if (res)
		return (ENXIO);

	KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));

	/*
	 * Increase to get number of pins
	 */
	sc->sc_npins++;

	sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 
	    M_NOWAIT | M_ZERO);

	if (!sc->sc_pins_mapped)
		return (ENOMEM);

	/* init bus lock */
	GPIOBUS_LOCK_INIT(sc);

	/*
	 * Get parent's pins and mark them as unmapped
	 */
	bus_generic_probe(dev);
	bus_enumerate_hinted_children(dev);

	return (bus_generic_attach(dev));
}