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;
}