Esempio n. 1
0
/*
 * OFW_GPIOBUS driver.
 */
device_t
ofw_gpiobus_add_fdt_child(device_t bus, const char *drvname, phandle_t child)
{
	device_t childdev;
	int i;
	struct gpiobus_ivar *devi;
	struct ofw_gpiobus_devinfo *dinfo;

	/*
	 * Check to see if we already have a child for @p child, and if so
	 * return it.
	 */
	childdev = ofw_bus_find_child_device_by_phandle(bus, child);
	if (childdev != NULL)
		return (childdev);

	/*
	 * Set up the GPIO child and OFW bus layer devinfo and add it to bus.
	 */
	childdev = device_add_child(bus, drvname, -1);
	if (childdev == NULL)
		return (NULL);
	dinfo = ofw_gpiobus_setup_devinfo(bus, childdev, child);
	if (dinfo == NULL) {
		device_delete_child(bus, childdev);
		return (NULL);
	}
	if (device_probe_and_attach(childdev) != 0) {
		ofw_gpiobus_destroy_devinfo(bus, dinfo);
		device_delete_child(bus, childdev);
		return (NULL);
	}
	/* Use the child name as pin name. */
	devi = &dinfo->opd_dinfo;
	for (i = 0; i < devi->npins; i++)
		GPIOBUS_PIN_SETNAME(bus, devi->pins[i],
		    device_get_nameunit(childdev));

	return (childdev);
}
Esempio n. 2
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);
}
Esempio n. 3
0
static int 
gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 
    struct thread *td)
{
	device_t bus;
	int max_pin, res;
	struct gpioc_softc *sc = cdev->si_drv1;
	struct gpio_pin pin;
	struct gpio_req req;
	uint32_t caps;

	bus = GPIO_GET_BUS(sc->sc_pdev);
	if (bus == NULL)
		return (EINVAL);
	switch (cmd) {
		case GPIOMAXPIN:
			max_pin = -1;
			res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin);
			bcopy(&max_pin, arg, sizeof(max_pin));
			break;
		case GPIOGETCONFIG:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("get config pin %d\n", pin.gp_pin);
			res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin,
			    &pin.gp_flags);
			/* Fail early */
			if (res)
				break;
			GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps);
			GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name);
			bcopy(&pin, arg, sizeof(pin));
			break;
		case GPIOSETCONFIG:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("set config pin %d\n", pin.gp_pin);
			res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps);
			if (res == 0)
				res = gpio_check_flags(caps, pin.gp_flags);
			if (res == 0)
				res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin,
				    pin.gp_flags);
			break;
		case GPIOGET:
			bcopy(arg, &req, sizeof(req));
			res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin,
			    &req.gp_value);
			dprintf("read pin %d -> %d\n", 
			    req.gp_pin, req.gp_value);
			bcopy(&req, arg, sizeof(req));
			break;
		case GPIOSET:
			bcopy(arg, &req, sizeof(req));
			res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 
			    req.gp_value);
			dprintf("write pin %d -> %d\n", 
			    req.gp_pin, req.gp_value);
			break;
		case GPIOTOGGLE:
			bcopy(arg, &req, sizeof(req));
			dprintf("toggle pin %d\n", 
			    req.gp_pin);
			res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin);
			break;
		case GPIOSETNAME:
			bcopy(arg, &pin, sizeof(pin));
			dprintf("set name on pin %d\n", pin.gp_pin);
			res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin,
			    pin.gp_name);
			break;
		default:
			return (ENOTTY);
			break;
	}

	return (res);
}