int mcp2210_irq_probe(struct mcp2210_device *dev) { uint i; mutex_init(&dev->irq_lock); dev->nr_irqs = 0; for (i = 0; i < 9; ++i) { struct mcp2210_pin_config *pin = &dev->config->pins[i]; if (!pin->has_irq) continue; switch (pin->mode) { case MCP2210_PIN_DEDICATED: if (i != 6) return -EINVAL; dev->s.poll_intr = 1; break; case MCP2210_PIN_GPIO: dev->s.poll_gpio = 1; break; }; if (pin->irq + 1> dev->nr_irqs) dev->nr_irqs = pin->irq + 1; } BUG_ON(dev->nr_irqs > 7); #ifdef CONFIG_MCP2210_GPIO if (dev->s.poll_gpio) { ctl_cmd_init(dev, &dev->cmd_poll_gpio, MCP2210_CMD_GET_PIN_VALUE, 0, NULL, 0, false); dev->cmd_poll_gpio.head.complete = complete_poll; mcp2210_add_cmd(&dev->cmd_poll_gpio.head, false); } #endif /* CONFIG_MCP2210_GPIO */ if (dev->s.poll_intr) { ctl_cmd_init(dev, &dev->cmd_poll_intr, MCP2210_CMD_GET_INTERRUPTS, 0, NULL, 0, false); dev->cmd_poll_intr.head.complete = complete_poll; mcp2210_add_cmd(&dev->cmd_poll_intr.head, false); } return 0; }
/****************************************************************************** * probe & remove */ int mcp2210_irq_probe(struct mcp2210_device *dev) { uint i; int ret; mcp2210_info(); mutex_init(&dev->irq_lock); dev->nr_irqs = 0; dev->poll_intr = 0; dev->poll_gpio = 0; for (i = 0; i < MCP2210_NUM_PINS; ++i) { const struct mcp2210_pin_config *pin = &dev->config->pins[i]; if (pin->mode == MCP2210_PIN_SPI || !pin->has_irq) continue; ++dev->nr_irqs; BUG_ON(dev->irq_revmap[i]); dev->irq_revmap[i] = pin->irq; if (pin->mode == MCP2210_PIN_DEDICATED) dev->poll_intr = 1; else if (pin->mode == MCP2210_PIN_GPIO) { dev->poll_gpio = 1; dev->irq_type[i] = pin->irq_type; } } if (!dev->nr_irqs) return 0; ret = irq_alloc_descs(-1, 0, dev->nr_irqs, 0); if (ret < 0) { /* CONFIG_SPARSE_IRQ needed? */ mcp2210_err("Failed to allocate %u irq descriptors: %d", dev->nr_irqs, ret); return ret; } dev->irq_base = ret; for (i = 0; i < dev->nr_irqs; ++i) { int virq = dev->irq_base + i; dev->irq_descs[i] = irq_to_desc(virq); BUG_ON(!dev->irq_descs[i]); irq_set_chip_data(virq, dev); irq_set_chip(virq, &mcp2210_irq_chip); #if defined(CONFIG_ARM) && LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) set_irq_flags(virq, 0); #else irq_set_noprobe(virq); #endif } #ifdef CONFIG_MCP2210_GPIO if (dev->poll_gpio) { ctl_cmd_init(dev, &dev->cmd_poll_gpio, MCP2210_CMD_GET_PIN_VALUE, 0, NULL, 0, false); dev->cmd_poll_gpio.head.complete = complete_poll; mcp2210_add_cmd(&dev->cmd_poll_gpio.head, false); } #endif /* CONFIG_MCP2210_GPIO */ if (dev->poll_intr) { /* read and then reset */ ctl_cmd_init(dev, &dev->cmd_poll_intr, MCP2210_CMD_GET_INTERRUPTS, 0, NULL, 0, false); dev->cmd_poll_intr.head.complete = complete_poll; mcp2210_add_cmd(&dev->cmd_poll_intr.head, false); } dev->is_irq_probed = 1; dev->suppress_poll_warn = 0; return 0; }