Hey Lewis, Couple comments. On 13/07/2022 11:59, lewis.hanly@xxxxxxxxxxxxx wrote: > From: Lewis Hanly <lewis.hanly@xxxxxxxxxxxxx> > > Add a driver to support the Polarfire SoC gpio controller. > > Signed-off-by: Lewis Hanly <lewis.hanly@xxxxxxxxxxxxx> > --- > drivers/gpio/Kconfig | 9 + > drivers/gpio/Makefile | 1 + > drivers/gpio/gpio-mpfs.c | 379 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 389 insertions(+) > create mode 100644 drivers/gpio/gpio-mpfs.c > > + > +static int mpfs_gpio_probe(struct platform_device *pdev) > +{ > + struct clk *clk; > + struct device *dev = &pdev->dev; > + struct device_node *node = pdev->dev.of_node; > + struct device_node *irq_parent; > + struct gpio_irq_chip *girq; > + struct irq_domain *parent; > + struct mpfs_gpio_chip *mpfs_gpio; > + int i, ret, ngpio; > + > + mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL); > + if (!mpfs_gpio) > + return -ENOMEM; > + > + mpfs_gpio->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(mpfs_gpio->base)) > + return PTR_ERR(mpfs_gpio->base); > + > + clk = devm_clk_get(&pdev->dev, NULL); > + if (IS_ERR(clk)) { > + dev_err(&pdev->dev, "devm_clk_get failed\n"); > + return PTR_ERR(clk); > + } > + > + ret = clk_prepare_enable(clk); > + if (ret) { > + dev_err(&pdev->dev, "failed to enable clock\n"); > + return ret; > + } > + > + mpfs_gpio->clk = clk; > + > + ngpio = of_irq_count(node); > + if (ngpio > NUM_GPIO) { > + dev_err(dev, "Too many GPIO interrupts (max=%d)\n", > + NUM_GPIO); This should fit on one line > + ret = -ENXIO; > + goto cleanup_clock; > + } > + > + irq_parent = of_irq_find_parent(node); > + if (!irq_parent) { > + dev_err(dev, "no IRQ parent node\n"); > + ret = -ENODEV; > + goto cleanup_clock; > + } > + parent = irq_find_host(irq_parent); > + if (!parent) { > + dev_err(dev, "no IRQ parent domain\n"); > + ret = -ENODEV; > + goto cleanup_clock; > + } > + > + /* Get the interrupt numbers. netdev style comment > + * Clear/Disable All interrupts before enabling parent interrupts. > + */ > + for (i = 0; i < ngpio; i++) { > + mpfs_gpio->irq_number[i] = platform_get_irq(pdev, i); You need to handle the case where platform_get_irq returns an error right? > + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, i, 1); > + mpfs_gpio_assign_bit(mpfs_gpio->base + (i * BYTE_BOUNDARY), > + MPFS_GPIO_EN_INT, 0); > + } > + > + raw_spin_lock_init(&mpfs_gpio->lock); > + > + mpfs_gpio->gc.direction_input = mpfs_gpio_direction_input; > + mpfs_gpio->gc.direction_output = mpfs_gpio_direction_output; > + mpfs_gpio->gc.get_direction = mpfs_gpio_get_direction; > + mpfs_gpio->gc.get = mpfs_gpio_get; > + mpfs_gpio->gc.set = mpfs_gpio_set; > + mpfs_gpio->gc.base = -1; > + mpfs_gpio->gc.ngpio = ngpio; > + mpfs_gpio->gc.label = dev_name(dev); > + mpfs_gpio->gc.parent = dev; > + mpfs_gpio->gc.owner = THIS_MODULE; > + > + /* Get a pointer to the gpio_irq_chip */ I doubt this comment is needed > + girq = &mpfs_gpio->gc.irq; > + gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip); > + girq->fwnode = of_node_to_fwnode(node); > + girq->parent_domain = parent; > + girq->child_to_parent_hwirq = mpfs_gpio_child_to_parent_hwirq; > + girq->handler = handle_bad_irq; > + girq->default_type = IRQ_TYPE_NONE; > + > + ret = gpiochip_add_data(&mpfs_gpio->gc, mpfs_gpio); Can we use a devm_ variant instead here... > + if (ret) > + goto cleanup_clock; > + > + platform_set_drvdata(pdev, mpfs_gpio); > + dev_info(dev, "Microchip MPFS GPIO registered, ngpio=%d\n", ngpio); > + > + return 0; > + > +cleanup_clock: > + clk_disable_unprepare(mpfs_gpio->clk); > + return ret; > +} > + > +static int mpfs_gpio_remove(struct platform_device *pdev) > +{ > + struct mpfs_gpio_chip *mpfs_gpio = platform_get_drvdata(pdev); > + > + gpiochip_remove(&mpfs_gpio->gc); ... and drop this? > + clk_disable_unprepare(mpfs_gpio->clk); > + > + return 0; > +} > + > +static const struct of_device_id mpfs_gpio_match[] = { > + { .compatible = "microchip,mpfs-gpio", }, > + { /* end of list */ }, Don't need a comma after the sentinel > +}; > + > +static struct platform_driver mpfs_gpio_driver = { > + .probe = mpfs_gpio_probe, > + .driver = { > + .name = "microchip,mpfs-gpio", > + .of_match_table = of_match_ptr(mpfs_gpio_match), > + }, > + .remove = mpfs_gpio_remove, > +}; > +builtin_platform_driver(mpfs_gpio_driver) Mising semicolon? Thanks, Conor.