static int tqmx86_gpio_probe()

in gpio-tqmx86.c [229:328]


static int tqmx86_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct tqmx86_gpio_data *gpio;
	struct gpio_chip *chip;
	struct gpio_irq_chip *girq;
	void __iomem *io_base;
	struct resource *res;
	int ret, irq;

	irq = platform_get_irq_optional(pdev, 0);
	if (irq < 0 && irq != -ENXIO)
		return irq;

	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	if (!res) {
		dev_err(&pdev->dev, "Cannot get I/O\n");
		return -ENODEV;
	}

	io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res));
	if (!io_base)
		return -ENOMEM;

	gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
	if (!gpio)
		return -ENOMEM;

	raw_spin_lock_init(&gpio->spinlock);
	gpio->io_base = io_base;

	tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);

	platform_set_drvdata(pdev, gpio);

	chip = &gpio->chip;
	chip->label = "gpio-tqmx86";
	chip->owner = THIS_MODULE;
	chip->can_sleep = false;
	chip->base = -1;
	chip->direction_input = tqmx86_gpio_direction_input;
	chip->direction_output = tqmx86_gpio_direction_output;
	chip->get_direction = tqmx86_gpio_get_direction;
	chip->get = tqmx86_gpio_get;
	chip->set = tqmx86_gpio_set;
	chip->ngpio = TQMX86_NGPIO;
	chip->parent = pdev->dev.parent;

	pm_runtime_enable(&pdev->dev);

	if (irq > 0) {
		struct irq_chip *irq_chip = &gpio->irq_chip;
		u8 irq_status;

		irq_chip->name = chip->label;
		irq_chip->parent_device = &pdev->dev;
		irq_chip->irq_mask = tqmx86_gpio_irq_mask;
		irq_chip->irq_unmask = tqmx86_gpio_irq_unmask;
		irq_chip->irq_set_type = tqmx86_gpio_irq_set_type;

		/* Mask all interrupts */
		tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC);

		/* Clear all pending interrupts */
		irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
		tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);

		girq = &chip->irq;
		girq->chip = irq_chip;
		girq->parent_handler = tqmx86_gpio_irq_handler;
		girq->num_parents = 1;
		girq->parents = devm_kcalloc(&pdev->dev, 1,
					     sizeof(*girq->parents),
					     GFP_KERNEL);
		if (!girq->parents) {
			ret = -ENOMEM;
			goto out_pm_dis;
		}
		girq->parents[0] = irq;
		girq->default_type = IRQ_TYPE_NONE;
		girq->handler = handle_simple_irq;
		girq->init_valid_mask = tqmx86_init_irq_valid_mask;
	}

	ret = devm_gpiochip_add_data(dev, chip, gpio);
	if (ret) {
		dev_err(dev, "Could not register GPIO chip\n");
		goto out_pm_dis;
	}

	dev_info(dev, "GPIO functionality initialized with %d pins\n",
		 chip->ngpio);

	return 0;

out_pm_dis:
	pm_runtime_disable(&pdev->dev);

	return ret;
}