Thanks Conor. On Wed, 2022-07-13 at 11:26 +0000, Conor Dooley - M52691 wrote: > 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 Can do. > > > + 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? Was not going to as I don't think it breaks if error. I will do a little more checking if required. > > > + 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 OK. > > > + 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... Maybe, will check. > > > + 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? eh, OK. > > > + 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 OK. > > > +}; > > + > > +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? Can add.. > > Thanks, > Conor.