void __init orion_gpio_init()

in plat-orion/gpio.c [519:619]


void __init orion_gpio_init(struct device_node *np,
			    int gpio_base, int ngpio,
			    void __iomem *base, int mask_offset,
			    int secondary_irq_base,
			    int irqs[4])
{
	struct orion_gpio_chip *ochip;
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;
	char gc_label[16];
	int i;

	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
		return;

	snprintf(gc_label, sizeof(gc_label), "orion_gpio%d",
		orion_gpio_chip_count);

	ochip = orion_gpio_chips + orion_gpio_chip_count;
	ochip->chip.label = kstrdup(gc_label, GFP_KERNEL);
	ochip->chip.request = orion_gpio_request;
	ochip->chip.direction_input = orion_gpio_direction_input;
	ochip->chip.get = orion_gpio_get;
	ochip->chip.direction_output = orion_gpio_direction_output;
	ochip->chip.set = orion_gpio_set;
	ochip->chip.to_irq = orion_gpio_to_irq;
	ochip->chip.base = gpio_base;
	ochip->chip.ngpio = ngpio;
	ochip->chip.can_sleep = 0;
#ifdef CONFIG_OF
	ochip->chip.of_node = np;
#endif
	ochip->chip.dbg_show = orion_gpio_dbg_show;

	spin_lock_init(&ochip->lock);
	ochip->base = (void __iomem *)base;
	ochip->valid_input = 0;
	ochip->valid_output = 0;
	ochip->mask_offset = mask_offset;
	ochip->secondary_irq_base = secondary_irq_base;

	gpiochip_add_data(&ochip->chip, ochip);

	/*
	 * Mask and clear GPIO interrupts.
	 */
	writel(0, GPIO_EDGE_CAUSE(ochip));
	writel(0, GPIO_EDGE_MASK(ochip));
	writel(0, GPIO_LEVEL_MASK(ochip));

	/* Setup the interrupt handlers. Each chip can have up to 4
	 * interrupt handlers, with each handler dealing with 8 GPIO
	 * pins. */

	for (i = 0; i < 4; i++) {
		if (irqs[i]) {
			irq_set_chained_handler_and_data(irqs[i],
							 gpio_irq_handler,
							 ochip);
		}
	}

	gc = irq_alloc_generic_chip("orion_gpio_irq", 2,
				    secondary_irq_base,
				    ochip->base, handle_level_irq);
	gc->private = ochip;
	ct = gc->chip_types;
	ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
	ct->chip.irq_mask = orion_gpio_mask_irq;
	ct->chip.irq_unmask = orion_gpio_unmask_irq;
	ct->chip.irq_set_type = gpio_irq_set_type;
	ct->chip.name = ochip->chip.label;

	ct++;
	ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;
	ct->regs.ack = GPIO_EDGE_CAUSE_OFF;
	ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
	ct->chip.irq_ack = irq_gc_ack_clr_bit;
	ct->chip.irq_mask = orion_gpio_mask_irq;
	ct->chip.irq_unmask = orion_gpio_unmask_irq;
	ct->chip.irq_set_type = gpio_irq_set_type;
	ct->handler = handle_edge_irq;
	ct->chip.name = ochip->chip.label;

	irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);

	/* Setup irq domain on top of the generic chip. */
	ochip->domain = irq_domain_add_legacy(np,
					      ochip->chip.ngpio,
					      ochip->secondary_irq_base,
					      ochip->secondary_irq_base,
					      &irq_domain_simple_ops,
					      ochip);
	if (!ochip->domain)
		panic("%s: couldn't allocate irq domain (DT).\n",
		      ochip->chip.label);

	orion_gpio_chip_count++;
}