static int lp_gpio_probe()

in intel/pinctrl-lynxpoint.c [800:910]


static int lp_gpio_probe(struct platform_device *pdev)
{
	const struct intel_pinctrl_soc_data *soc;
	struct intel_pinctrl *lg;
	struct gpio_chip *gc;
	struct device *dev = &pdev->dev;
	struct resource *io_rc;
	void __iomem *regs;
	unsigned int i;
	int irq, ret;

	soc = (const struct intel_pinctrl_soc_data *)device_get_match_data(dev);
	if (!soc)
		return -ENODEV;

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

	lg->dev = dev;
	lg->soc = soc;

	lg->ncommunities = lg->soc->ncommunities;
	lg->communities = devm_kcalloc(dev, lg->ncommunities,
				       sizeof(*lg->communities), GFP_KERNEL);
	if (!lg->communities)
		return -ENOMEM;

	lg->pctldesc           = lptlp_pinctrl_desc;
	lg->pctldesc.name      = dev_name(dev);
	lg->pctldesc.pins      = lg->soc->pins;
	lg->pctldesc.npins     = lg->soc->npins;

	lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg);
	if (IS_ERR(lg->pctldev)) {
		dev_err(dev, "failed to register pinctrl driver\n");
		return PTR_ERR(lg->pctldev);
	}

	platform_set_drvdata(pdev, lg);

	io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
	if (!io_rc) {
		dev_err(dev, "missing IO resources\n");
		return -EINVAL;
	}

	regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc));
	if (!regs) {
		dev_err(dev, "failed mapping IO region %pR\n", &io_rc);
		return -EBUSY;
	}

	for (i = 0; i < lg->soc->ncommunities; i++) {
		struct intel_community *comm = &lg->communities[i];

		*comm = lg->soc->communities[i];

		comm->regs = regs;
		comm->pad_regs = regs + 0x100;
	}

	raw_spin_lock_init(&lg->lock);

	gc = &lg->chip;
	gc->label = dev_name(dev);
	gc->owner = THIS_MODULE;
	gc->request = gpiochip_generic_request;
	gc->free = gpiochip_generic_free;
	gc->direction_input = lp_gpio_direction_input;
	gc->direction_output = lp_gpio_direction_output;
	gc->get = lp_gpio_get;
	gc->set = lp_gpio_set;
	gc->set_config = gpiochip_generic_config;
	gc->get_direction = lp_gpio_get_direction;
	gc->base = -1;
	gc->ngpio = LP_NUM_GPIO;
	gc->can_sleep = false;
	gc->add_pin_ranges = lp_gpio_add_pin_ranges;
	gc->parent = dev;

	/* set up interrupts  */
	irq = platform_get_irq_optional(pdev, 0);
	if (irq > 0) {
		struct gpio_irq_chip *girq;

		girq = &gc->irq;
		girq->chip = &lp_irqchip;
		girq->init_hw = lp_gpio_irq_init_hw;
		girq->parent_handler = lp_gpio_irq_handler;
		girq->num_parents = 1;
		girq->parents = devm_kcalloc(dev, girq->num_parents,
					     sizeof(*girq->parents),
					     GFP_KERNEL);
		if (!girq->parents)
			return -ENOMEM;
		girq->parents[0] = irq;
		girq->default_type = IRQ_TYPE_NONE;
		girq->handler = handle_bad_irq;
	}

	ret = devm_gpiochip_add_data(dev, gc, lg);
	if (ret) {
		dev_err(dev, "failed adding lp-gpio chip\n");
		return ret;
	}

	pm_runtime_enable(dev);

	return 0;
}