static void
mv_gpio_intr(void *arg)
{
	uint32_t int_cause, gpio_val;
	uint32_t int_cause_hi, gpio_val_hi = 0;
	int i;

	int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE);
	gpio_val = mv_gpio_reg_read(GPIO_DATA_IN);
	gpio_val &= int_cause;
	if (mv_gpio_softc->use_high) {
		int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE);
		gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN);
		gpio_val_hi &= int_cause_hi;
	}

	i = 0;
	while (gpio_val != 0) {
		if (gpio_val & 1)
			mv_gpio_intr_handler(i);
		gpio_val >>= 1;
		i++;
	}

	if (mv_gpio_softc->use_high) {
		i = 0;
		while (gpio_val_hi != 0) {
			if (gpio_val_hi & 1)
				mv_gpio_intr_handler(i + GPIO_PINS_PER_REG);
			gpio_val_hi >>= 1;
			i++;
		}
	}
Beispiel #2
0
static void
mv_gpio_exec_intr_handlers(device_t dev, uint32_t status, int high)
{
	int i, pin;
	struct mv_gpio_softc *sc;
	sc = (struct mv_gpio_softc *)device_get_softc(dev);

	MV_GPIO_ASSERT_LOCKED();

	i = 0;
	while (status != 0) {
		if (status & 1) {
			pin = (high ? (i + GPIO_PINS_PER_REG) : i);
			if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE)
				mv_gpio_debounce_start(dev, pin);
			else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
				mv_gpio_polarity(dev, pin, 0, 1);
				mv_gpio_intr_handler(dev, pin);
			} else
				mv_gpio_intr_handler(dev, pin);
		}
		status >>= 1;
		i++;
	}
}
Beispiel #3
0
static void
mv_gpio_debounce(void *arg)
{
	uint8_t raw_read, last_state;
	int pin;
	device_t dev;
	int *debounce_counter;
	struct mv_gpio_softc *sc;
	struct mv_gpio_pindev *s;

	s = (struct mv_gpio_pindev *)arg;
	dev = s->dev;
	pin = s->pin;
	sc = (struct mv_gpio_softc *)device_get_softc(dev);

	MV_GPIO_LOCK();

	raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
	last_state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
	debounce_counter = &sc->debounce_counters[pin];

	if (raw_read == last_state) {
		if (last_state)
			*debounce_counter = DEBOUNCE_HI_LO_MS /
			    DEBOUNCE_CHECK_MS;
		else
			*debounce_counter = DEBOUNCE_LO_HI_MS /
			    DEBOUNCE_CHECK_MS;

		callout_reset(sc->debounce_callouts[pin],
		    DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
	} else {
		*debounce_counter = *debounce_counter - 1;
		if (*debounce_counter != 0)
			callout_reset(sc->debounce_callouts[pin],
			    DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
		else {
			mv_gpio_debounced_state_set(dev, pin, raw_read);

			if (last_state)
				*debounce_counter = DEBOUNCE_HI_LO_MS /
				    DEBOUNCE_CHECK_MS;
			else
				*debounce_counter = DEBOUNCE_LO_HI_MS /
				    DEBOUNCE_CHECK_MS;

			if (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) &&
			    (raw_read == 0)) ||
			    (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) == 0) &&
			    raw_read) ||
			    (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE))
				mv_gpio_intr_handler(dev, pin);

			/* Toggle polarity for next edge. */
			mv_gpio_polarity(dev, pin, 0, 1);

			free(arg, M_DEVBUF);
			callout_deactivate(sc->debounce_callouts[pin]);
		}
	}

	MV_GPIO_UNLOCK();
}