static int sprd_eic_irq_set_type()

in gpio-eic-sprd.c [309:443]


static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
	u32 offset = irqd_to_hwirq(data);
	int state;

	switch (sprd_eic->type) {
	case SPRD_EIC_DEBOUNCE:
		switch (flow_type) {
		case IRQ_TYPE_LEVEL_HIGH:
			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
			break;
		case IRQ_TYPE_LEVEL_LOW:
			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
			break;
		case IRQ_TYPE_EDGE_RISING:
		case IRQ_TYPE_EDGE_FALLING:
		case IRQ_TYPE_EDGE_BOTH:
			state = sprd_eic_get(chip, offset);
			if (state)
				sprd_eic_update(chip, offset,
						SPRD_EIC_DBNC_IEV, 0);
			else
				sprd_eic_update(chip, offset,
						SPRD_EIC_DBNC_IEV, 1);
			break;
		default:
			return -ENOTSUPP;
		}

		irq_set_handler_locked(data, handle_level_irq);
		break;
	case SPRD_EIC_LATCH:
		switch (flow_type) {
		case IRQ_TYPE_LEVEL_HIGH:
			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
			break;
		case IRQ_TYPE_LEVEL_LOW:
			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
			break;
		case IRQ_TYPE_EDGE_RISING:
		case IRQ_TYPE_EDGE_FALLING:
		case IRQ_TYPE_EDGE_BOTH:
			state = sprd_eic_get(chip, offset);
			if (state)
				sprd_eic_update(chip, offset,
						SPRD_EIC_LATCH_INTPOL, 0);
			else
				sprd_eic_update(chip, offset,
						SPRD_EIC_LATCH_INTPOL, 1);
			break;
		default:
			return -ENOTSUPP;
		}

		irq_set_handler_locked(data, handle_level_irq);
		break;
	case SPRD_EIC_ASYNC:
		switch (flow_type) {
		case IRQ_TYPE_EDGE_RISING:
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_EDGE_FALLING:
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_EDGE_BOTH:
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_LEVEL_HIGH:
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
			irq_set_handler_locked(data, handle_level_irq);
			break;
		case IRQ_TYPE_LEVEL_LOW:
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
			irq_set_handler_locked(data, handle_level_irq);
			break;
		default:
			return -ENOTSUPP;
		}
		break;
	case SPRD_EIC_SYNC:
		switch (flow_type) {
		case IRQ_TYPE_EDGE_RISING:
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_EDGE_FALLING:
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_EDGE_BOTH:
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1);
			irq_set_handler_locked(data, handle_edge_irq);
			break;
		case IRQ_TYPE_LEVEL_HIGH:
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
			irq_set_handler_locked(data, handle_level_irq);
			break;
		case IRQ_TYPE_LEVEL_LOW:
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
			irq_set_handler_locked(data, handle_level_irq);
			break;
		default:
			return -ENOTSUPP;
		}
		break;
	default:
		dev_err(chip->parent, "Unsupported EIC type.\n");
		return -ENOTSUPP;
	}

	return 0;
}