Example #1
0
static void irq_sim_handle_irq(struct irq_work *work)
{
	struct irq_sim_work_ctx *work_ctx;

	work_ctx = container_of(work, struct irq_sim_work_ctx, work);
	handle_simple_irq(irq_to_desc(work_ctx->irq));
}
void _mcp2210_irq_do_intr_counter(struct mcp2210_device *dev, u16 count)
{
	struct mcp2210_pin_config *pin = &dev->config->pins[6];
	struct irq_desc *desc = dev->irq_descs[pin->irq];

	if (dev->s.chip_settings.pin_mode[6] != MCP2210_PIN_DEDICATED)
		return;

	/* We're discarding count and just letting handlers know that at least
	 * one interrupt occured.  Should this have a mechanism to report the
	 * interrupt once for each count?  */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
	handle_simple_irq(desc);
#else
	handle_simple_irq(dev->irq_base + pin->irq, desc);
#endif
}
void mcp2210_irq_do_gpio(struct mcp2210_device *dev, u16 old_val, u16 new_val)
{
	uint i;
	for (i = 0; i < MCP2210_NUM_PINS; ++i) {
		struct mcp2210_pin_config *pin = &dev->config->pins[i];
		int old_pin_val;
		int new_pin_val;
		int edge_mask, level_mask;
		struct irq_desc *desc;

		if (!pin->has_irq || pin->mode != MCP2210_PIN_GPIO)
			continue;

		old_pin_val = old_val & (1 << i);
		new_pin_val = new_val & (1 << i);
		level_mask = new_pin_val ? IRQ_TYPE_LEVEL_HIGH
					 : IRQ_TYPE_LEVEL_LOW;
		desc = dev->irq_descs[pin->irq];

		if (new_pin_val > old_val)
			edge_mask = IRQ_TYPE_EDGE_RISING;
		else if (new_pin_val < old_val)
			edge_mask = IRQ_TYPE_EDGE_FALLING;
		else
			edge_mask = 0;

		if (pin->irq_type & edge_mask) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
			handle_simple_irq(desc);
#else
			handle_simple_irq(dev->irq_base + pin->irq, desc);
#endif
		}

		if (pin->irq_type & level_mask) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
			handle_level_irq(desc);
#else
			handle_level_irq(dev->irq_base + pin->irq, desc);
#endif
		}
	}
}