Commit 2af1f667 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Bartosz Golaszewski
Browse files

gpio: xilinx: Use better bitmap APIs where appropriate



There are bitmap_gather() and bitmap_scatter() that are factually
simplified version of the APIs used in the driver. Use them where
appropriate.

While at it, replace bitmap_bitremap() with find_nth_bit()
for the sake of simplification.

Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20250205093200.373709-2-andriy.shevchenko@linux.intel.com


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent 8beaf839
Loading
Loading
Loading
Loading
+27 −41
Original line number Diff line number Diff line
@@ -45,8 +45,7 @@
 * struct xgpio_instance - Stores information about GPIO device
 * @gc: GPIO chip
 * @regs: register block
 * @hw_map: GPIO pin mapping on hardware side
 * @sw_map: GPIO pin mapping on software side
 * @map: GPIO pin mapping on hardware side
 * @state: GPIO write state shadow register
 * @last_irq_read: GPIO read state register from last interrupt
 * @dir: GPIO direction shadow register
@@ -60,8 +59,7 @@
struct xgpio_instance {
	struct gpio_chip gc;
	void __iomem *regs;
	DECLARE_BITMAP(hw_map, 64);
	DECLARE_BITMAP(sw_map, 64);
	DECLARE_BITMAP(map, 64);
	DECLARE_BITMAP(state, 64);
	DECLARE_BITMAP(last_irq_read, 64);
	DECLARE_BITMAP(dir, 64);
@@ -73,16 +71,6 @@ struct xgpio_instance {
	struct clk *clk;
};

static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit)
{
	return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64);
}

static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio)
{
	return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64);
}

static inline u32 xgpio_get_value32(const unsigned long *map, int bit)
{
	const size_t index = BIT_WORD(bit);
@@ -128,7 +116,8 @@ static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsign

static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
{
	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
	unsigned long lastbit = find_nth_bit(chip->map, 64, chip->gc.ngpio - 1);
	int bit;

	for (bit = 0; bit <= lastbit ; bit += 32)
		xgpio_read_ch(chip, reg, bit, a);
@@ -136,7 +125,8 @@ static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned lon

static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a)
{
	int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1);
	unsigned long lastbit = find_nth_bit(chip->map, 64, chip->gc.ngpio - 1);
	int bit;

	for (bit = 0; bit <= lastbit ; bit += 32)
		xgpio_write_ch(chip, reg, bit, a);
@@ -156,7 +146,7 @@ static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned lo
static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
	struct xgpio_instance *chip = gpiochip_get_data(gc);
	int bit = xgpio_to_bit(chip, gpio);
	unsigned long bit = find_nth_bit(chip->map, 64, gpio);
	DECLARE_BITMAP(state, 64);

	xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state);
@@ -177,7 +167,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
	unsigned long flags;
	struct xgpio_instance *chip = gpiochip_get_data(gc);
	int bit = xgpio_to_bit(chip, gpio);
	unsigned long bit = find_nth_bit(chip->map, 64, gpio);

	raw_spin_lock_irqsave(&chip->gpio_lock, flags);

@@ -207,8 +197,8 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
	unsigned long flags;
	struct xgpio_instance *chip = gpiochip_get_data(gc);

	bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64);
	bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64);
	bitmap_scatter(hw_mask, mask, chip->map, 64);
	bitmap_scatter(hw_bits, bits, chip->map, 64);

	raw_spin_lock_irqsave(&chip->gpio_lock, flags);

@@ -234,7 +224,7 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
	unsigned long flags;
	struct xgpio_instance *chip = gpiochip_get_data(gc);
	int bit = xgpio_to_bit(chip, gpio);
	unsigned long bit = find_nth_bit(chip->map, 64, gpio);

	raw_spin_lock_irqsave(&chip->gpio_lock, flags);

@@ -263,7 +253,7 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
	unsigned long flags;
	struct xgpio_instance *chip = gpiochip_get_data(gc);
	int bit = xgpio_to_bit(chip, gpio);
	unsigned long bit = find_nth_bit(chip->map, 64, gpio);

	raw_spin_lock_irqsave(&chip->gpio_lock, flags);

@@ -395,7 +385,7 @@ 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 bit = xgpio_to_bit(chip, irq_offset);
	unsigned long bit = find_nth_bit(chip->map, 64, irq_offset);
	u32 mask = BIT(bit / 32), temp;

	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
@@ -422,7 +412,7 @@ static void xgpio_irq_unmask(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 bit = xgpio_to_bit(chip, irq_offset);
	unsigned long bit = find_nth_bit(chip->map, 64, irq_offset);
	u32 old_enable = xgpio_get_value32(chip->enable, bit);
	u32 mask = BIT(bit / 32), val;

@@ -462,7 +452,7 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
{
	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
	int irq_offset = irqd_to_hwirq(irq_data);
	int bit = xgpio_to_bit(chip, irq_offset);
	unsigned long bit = find_nth_bit(chip->map, 64, irq_offset);

	/*
	 * The Xilinx GPIO hardware provides a single interrupt status
@@ -502,10 +492,10 @@ static void xgpio_irqhandler(struct irq_desc *desc)
	struct irq_chip *irqchip = irq_desc_get_chip(desc);
	DECLARE_BITMAP(rising, 64);
	DECLARE_BITMAP(falling, 64);
	DECLARE_BITMAP(all, 64);
	DECLARE_BITMAP(hw, 64);
	DECLARE_BITMAP(sw, 64);
	int irq_offset;
	u32 status;
	u32 bit;

	status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
	xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status);
@@ -514,29 +504,28 @@ static void xgpio_irqhandler(struct irq_desc *desc)

	raw_spin_lock(&chip->gpio_lock);

	xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all);
	xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, hw);

	bitmap_complement(rising, chip->last_irq_read, 64);
	bitmap_and(rising, rising, all, 64);
	bitmap_and(rising, rising, hw, 64);
	bitmap_and(rising, rising, chip->enable, 64);
	bitmap_and(rising, rising, chip->rising_edge, 64);

	bitmap_complement(falling, all, 64);
	bitmap_complement(falling, hw, 64);
	bitmap_and(falling, falling, chip->last_irq_read, 64);
	bitmap_and(falling, falling, chip->enable, 64);
	bitmap_and(falling, falling, chip->falling_edge, 64);

	bitmap_copy(chip->last_irq_read, all, 64);
	bitmap_or(all, rising, falling, 64);
	bitmap_copy(chip->last_irq_read, hw, 64);
	bitmap_or(hw, rising, falling, 64);

	raw_spin_unlock(&chip->gpio_lock);

	dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling);

	for_each_set_bit(bit, all, 64) {
		irq_offset = xgpio_from_bit(chip, bit);
	bitmap_gather(sw, hw, chip->map, 64);
	for_each_set_bit(irq_offset, sw, 64)
		generic_handle_domain_irq(gc->irq.domain, irq_offset);
	}

	chained_irq_exit(irqchip, desc);
}
@@ -613,17 +602,14 @@ static int xgpio_probe(struct platform_device *pdev)
	if (width[1] > 32)
		return -EINVAL;

	/* Setup software pin mapping */
	bitmap_set(chip->sw_map, 0, width[0] + width[1]);

	/* Setup hardware pin mapping */
	bitmap_set(chip->hw_map,  0, width[0]);
	bitmap_set(chip->hw_map, 32, width[1]);
	bitmap_set(chip->map,  0, width[0]);
	bitmap_set(chip->map, 32, width[1]);

	raw_spin_lock_init(&chip->gpio_lock);

	chip->gc.base = -1;
	chip->gc.ngpio = bitmap_weight(chip->hw_map, 64);
	chip->gc.ngpio = bitmap_weight(chip->map, 64);
	chip->gc.parent = dev;
	chip->gc.direction_input = xgpio_dir_in;
	chip->gc.direction_output = xgpio_dir_out;