port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM;
port->sdata = device_get_match_data(dev);
dual_base = port->sdata->have_dual_base;
/* * Handle legacy compatible combinations which used two reg values * for the i.MX8ULP and i.MX93.
*/ if (device_is_compatible(dev, "fsl,imx7ulp-gpio") &&
(device_is_compatible(dev, "fsl,imx93-gpio") ||
(device_is_compatible(dev, "fsl,imx8ulp-gpio"))))
dual_base = true;
if (dual_base) {
port->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(port->base)) return PTR_ERR(port->base);
port->gpio_base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(port->gpio_base)) return PTR_ERR(port->gpio_base);
} else {
port->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(port->base)) return PTR_ERR(port->base);
port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) return port->irq;
port->clk_port = devm_clk_get(dev, "port");
ret = PTR_ERR_OR_ZERO(port->clk_port); if (!ret) {
ret = clk_prepare_enable(port->clk_port); if (ret) return ret;
ret = devm_add_action_or_reset(dev, vf610_gpio_disable_clk,
port->clk_port); if (ret) return ret;
} elseif (ret == -EPROBE_DEFER) { /* * Percolate deferrals, for anything else, * just live without the clocking.
*/ return ret;
}
port->clk_gpio = devm_clk_get(dev, "gpio");
ret = PTR_ERR_OR_ZERO(port->clk_gpio); if (!ret) {
ret = clk_prepare_enable(port->clk_gpio); if (ret) return ret;
ret = devm_add_action_or_reset(dev, vf610_gpio_disable_clk,
port->clk_gpio); if (ret) return ret;
} elseif (ret == -EPROBE_DEFER) { return ret;
}
gc = &port->gc;
flags = BGPIOF_PINCTRL_BACKEND; /* * We only read the output register for current value on output * lines if the direction register is available so we can switch * direction.
*/ if (port->sdata->have_paddr)
flags |= BGPIOF_READ_OUTPUT_REG_SET;
ret = bgpio_init(gc, dev, 4,
port->gpio_base + GPIO_PDIR,
port->gpio_base + GPIO_PDOR,
NULL,
port->sdata->have_paddr ? port->gpio_base + GPIO_PDDR : NULL,
NULL,
flags); if (ret) return dev_err_probe(dev, ret, "unable to init generic GPIO\n");
gc->label = dev_name(dev);
gc->base = -1;
/* Mask all GPIO interrupts */ for (i = 0; i < gc->ngpio; i++)
vf610_gpio_writel(0, port->base + PORT_PCR(i));
/* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.