Re: [PATCH V2 2/3] gpio: xilinx: Add interrupt support
From: Robert Hancock <hidden>
Date: 2020-07-24 21:37:56
Also in:
linux-gpio, lkml
On 2020-07-23 12:03 p.m., Andy Shevchenko wrote:
quoted
+/** + * xgpio_xlate - Translate gpio_spec to the GPIO number and flags + * @gc: Pointer to gpio_chip device structure. + * @gpiospec: gpio specifier as found in the device tree + * @flags: A flags pointer based on binding + * + * Return: + * irq number otherwise -EINVAL + */ +static int xgpio_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, u32 *flags) +{ + if (gc->of_gpio_n_cells < 2) { + WARN_ON(1); + return -EINVAL; + } + + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) + return -EINVAL; + + if (gpiospec->args[0] >= gc->ngpio) + return -EINVAL; + + if (flags) + *flags = gpiospec->args[1]; + + return gpiospec->args[0]; +}This looks like a very standart xlate function for GPIO. Why do you need to open-code it?
Indeed, this seems the same as the of_gpio_simple_xlate callback which is used if no xlate callback is specified, so I'm not sure why this is necessary?
...quoted
+/** + * xgpio_irq_ack - Acknowledge a child GPIO interrupt.quoted
+ * This currently does nothing, but irq_ack is unconditionally called by + * handle_edge_irq and therefore must be defined.This should go after parameter description(s).quoted
+ * @irq_data: per irq and chip data passed down to chip functions + */...quoted
/** + * xgpio_irq_mask - Write the specified signal of the GPIO device. + * @irq_data: per irq and chip data passed down to chip functionsIn all comments irq -> IRQ.quoted
+ */ +static void xgpio_irq_mask(struct irq_data *irq_data) +{ + unsigned long flags; + struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); + int irq_offset = irqd_to_hwirq(irq_data); + int index = xgpio_index(chip, irq_offset); + int offset = xgpio_offset(chip, irq_offset); + + spin_lock_irqsave(&chip->gpio_lock, flags); +quoted
+ chip->irq_enable[index] &= ~BIT(offset);If you convert your data structure to use bitmaps (and respective API) like #define XILINX_NGPIOS 64 ... DECLARE_BITMAP(irq_enable, XILINX_NGPIOS); ... it will make code better to read and understand. For example, here it will be just __clear_bit(offset, chip->irq_enable);quoted
+ dev_dbg(chip->gc.parent, "Disable %d irq, irq_enable_mask 0x%x\n", + irq_offset, chip->irq_enable[index]);Under spin lock?! Hmm...quoted
+ if (!chip->irq_enable[index]) { + /* Disable per channel interrupt */ + u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); + + temp &= ~BIT(index); + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); + } + spin_unlock_irqrestore(&chip->gpio_lock, flags); +}...quoted
+ for (index = 0; index < num_channels; index++) { + if ((status & BIT(index))) {If gpio_width is the same among banks, you can use for_each_set_bit() here as well. ...quoted
+ for_each_set_bit(bit, &all_events, 32) { + generic_handle_irq(irq_find_mapping + (chip->gc.irq.domain, offset + bit));Strange indentation. Maybe a temporary variable helps? ...quoted
+ chip->irq = platform_get_irq_optional(pdev, 0); + if (chip->irq <= 0) { + dev_info(&pdev->dev, "GPIO IRQ not set\n");Why do you need an optional variant if you print an error anyway?quoted
+ } else {...quoted
+ chip->gc.irq.parents = (unsigned int *)&chip->irq; + chip->gc.irq.num_parents = 1;Current pattern is to use devm_kcalloc() for it (Linus has plans to simplify this in the future and this will help him to find what patterns are being used)
-- Robert Hancock Senior Hardware Designer SED Systems, a division of Calian Ltd. Email: hancock@sedsystems.ca _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel