gpio: xilinx: Utilize for_each_set_clump macro
Subsystems (3)
PATCH 6/6 gpio: xilinx: Utilize for_each_set_clump macro
This patch reimplements the xgpio_set_multiple function in drivers/gpio/gpio-xilinx.c to use the new for_each_set_clump macro. Instead of looping for each bit in xgpio_set_multiple function, now we can check each channel at a time and save cycles.
Cc Linus Walleij <[email protected]>
Cc Bartosz Golaszewski <[email protected]>
Cc Michal Simek <[email protected]>
Signed-off-by Syed Nayyar Waris <[email protected]>
Signed-off-by William Breathitt Gray <[email protected]>
--- drivers/gpio/gpio-xilinx.c | 64 ++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 30 deletions(-)
drivers/gpio/gpio-xilinx.c +34 -30
@@ -136,39 +136,43 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)static void xgpio_set_multiple (struct gpio_chip *gc,unsigned long *mask,unsigned long *bits) { -unsigned long flags; +unsigned long flags[2 ];struct xgpio_instance *chip =gpiochip_get_data (gc); -int index =xgpio_index (chip,0 ); -int offset, i; - -spin_lock_irqsave (&chip->gpio_lock[index], flags); - -/* Write to GPIO signals */ -for (i =0 ; i < gc->ngpio; i++) { -if (*mask ==0 ) -break ; -/* Once finished with an index write it out to the register */ -if (index !=xgpio_index (chip, i)) { -xgpio_writereg (chip->regs +XGPIO_DATA_OFFSET + - index *XGPIO_CHANNEL_OFFSET , - chip->gpio_state[index]); -spin_unlock_irqrestore (&chip->gpio_lock[index], flags); - index =xgpio_index (chip, i); -spin_lock_irqsave (&chip->gpio_lock[index], flags); - } -if (__test_and_clear_bit (i, mask)) { - offset =xgpio_offset (chip, i); -if (test_bit (i, bits)) - chip->gpio_state[index] |=BIT (offset); -else - chip->gpio_state[index] &= ~BIT (offset); - } +u32 *const state = chip->gpio_state; +unsigned int *const width = chip->gpio_width; +const unsigned long state_size =BITS_PER_TYPE (*state); +unsigned long offset, clump; +size_t index; + +#define TOTAL_BITS BITS_PER_TYPE(chip->gpio_state) +DECLARE_BITMAP (old,TOTAL_BITS ); +DECLARE_BITMAP (new,TOTAL_BITS ); +DECLARE_BITMAP (changed,TOTAL_BITS ); + +spin_lock_irqsave (&chip->gpio_lock[0 ], flags[0 ]); +spin_lock_irqsave (&chip->gpio_lock[1 ], flags[1 ]); + +bitmap_set_value (old, state[0 ],0 , width[0 ]); +bitmap_set_value (old, state[1 ], width[0 ], width[1 ]); +bitmap_replace (new, old, bits, mask, gc->ngpio); + +bitmap_set_value (old, state[0 ],0 , state_size); +bitmap_set_value (old, state[1 ], state_size, state_size); + state[0 ] =bitmap_get_value (new,0 , width[0 ]); + state[1 ] =bitmap_get_value (new, width[0 ], width[1 ]); +bitmap_set_value (new, state[0 ],0 , state_size); +bitmap_set_value (new, state[1 ], state_size, state_size); +bitmap_xor (changed, old, new,TOTAL_BITS ); + +for_each_set_clump (offset, clump, changed,TOTAL_BITS , state_size) { + index = offset / state_size; +xgpio_writereg (chip->regs +XGPIO_DATA_OFFSET + + index *XGPIO_CHANNEL_OFFSET , + state[index]); } -xgpio_writereg (chip->regs +XGPIO_DATA_OFFSET + - index *XGPIO_CHANNEL_OFFSET , chip->gpio_state[index]); - -spin_unlock_irqrestore (&chip->gpio_lock[index], flags); +spin_unlock_irqrestore (&chip->gpio_lock[1 ], flags[1 ]); +spin_unlock_irqrestore (&chip->gpio_lock[0 ], flags[0 ]); }/**
Signature · 1 line
2.7.4