gpio-mpc8xxx: add mpc8xxx_gpio_set_multiple function
PATCH v4 2/2 gpio-mpc8xxx: add mpc8xxx_gpio_set_multiple function
Add a set_multiple function to the MPC8xxx GPIO chip driver and thereby allow for actual performance improvements when setting multiple outputs simultaneously. In my case the time needed to configure an FPGA goes down from 48 s to 20 s.
---
This patch depends on my previous patch "gpiolib: allow simultaneous setting of multiple GPIO outputs".
Change log:
v4: - change interface of the set_multiple driver function to use
unsigned long as type for the bit fields
- use generic bitops (which also use unsigned long for bit fields)
v3: - change commit message
v2: - add this patch (v1 included only changes to gpiolib)
drivers/gpio/gpio-mpc8xxx.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
drivers/gpio/gpio-mpc8xxx.c +27 -0
@@ -105,6 +105,32 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)spin_unlock_irqrestore (&mpc8xxx_gc->lock, flags); } +static void mpc8xxx_gpio_set_multiple (struct gpio_chip *gc, +unsigned long *mask,unsigned long *bits) +{ +struct of_mm_gpio_chip *mm =to_of_mm_gpio_chip (gc); +struct mpc8xxx_gpio_chip *mpc8xxx_gc =to_mpc8xxx_gpio_chip (mm); +unsigned long flags; +int i; + +spin_lock_irqsave (&mpc8xxx_gc->lock, flags); + +for (i =0 ; i < gc->ngpio; i++) { +if (*mask ==0 ) +break ; +if (__test_and_clear_bit (i, mask)) { +if (test_bit (i, bits)) + mpc8xxx_gc->data |=mpc8xxx_gpio2mask (i); +else + mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask (i); + } + } + +out_be32 (mm->regs +GPIO_DAT , mpc8xxx_gc->data); + +spin_unlock_irqrestore (&mpc8xxx_gc->lock, flags); +} +static int mpc8xxx_gpio_dir_in (struct gpio_chip *gc,unsigned int gpio) {struct of_mm_gpio_chip *mm =to_of_mm_gpio_chip (gc);
@@ -344,6 +370,7 @@ static void __init mpc8xxx_add_controller(struct device_node *np) gc->get =of_device_is_compatible (np,"fsl,mpc8572-gpio" ) ? mpc8572_gpio_get : mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; + gc->set_multiple = mpc8xxx_gpio_set_multiple; gc->to_irq = mpc8xxx_gpio_to_irq; ret =of_mm_gpiochip_add (np, mm_gc);
--
1.8.5.5
Quoted 31 lines · Rojhalat Ibrahim
Add a
set_multiplefunction to the MPC8xxx GPIO chip driver and thereby allow for actual performance improvements when setting multiple outputs simultaneously. In my case the time needed to configure an FPGA goes down from 48 s to 20 s.Signed-off-by Rojhalat Ibrahim <[email protected]>---
This patch depends on my previous patch "gpiolib: allow simultaneous setting of multiple GPIO outputs".Change log:
v4: - change interface of theset_multipledriver function to use
unsigned long as type for the bit fields
- use generic bitops (which also use unsigned long for bit fields)
v3: - change commit message
v2: - add this patch (v1 included only changes to gpiolib)drivers/gpio/gpio-mpc8xxx.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)drivers/gpio/gpio-mpc8xxx.c +3
-0@@ -105,6 +105,32 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)spin_unlock_irqrestore (&mpc8xxx_gc->lock, flags); } +static void mpc8xxx_gpio_set_multiple (struct gpio_chip *gc, +unsigned long *mask,unsigned long *bits) +{
drivers/gpio/gpio-mpc8xxx.c static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) · line 120
Quoted 10 lines
drivers/gpio/gpio-mpc8xxx.c +10
-0+struct of_mm_gpio_chip *mm =to_of_mm_gpio_chip (gc); +struct mpc8xxx_gpio_chip *mpc8xxx_gc =to_mpc8xxx_gpio_chip (mm); +unsigned long flags; +int i; + +spin_lock_irqsave (&mpc8xxx_gc->lock, flags); + +for (i =0 ; i < gc->ngpio; i++) { +if (*mask ==0 ) +break ;
Ok, so this works because presentely you can only have 32 GPIOs max on this chip. But you cannot be sure that future revisions won't extend that number ; and if this happens this function won't work as-is anymore. I won't take much more code to make it more generic, so please do it now to avoid hours of horrendous debugging to your future self.
Quoted 27 lines
drivers/gpio/gpio-mpc8xxx.c +14
-1+if (__test_and_clear_bit (i, mask)) { +if (test_bit (i, bits)) + mpc8xxx_gc->data |=mpc8xxx_gpio2mask (i); +else + mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask (i); + } + } + +out_be32 (mm->regs +GPIO_DAT , mpc8xxx_gc->data); + +spin_unlock_irqrestore (&mpc8xxx_gc->lock, flags); +} +static int mpc8xxx_gpio_dir_in (struct gpio_chip *gc,unsigned int gpio) {struct of_mm_gpio_chip *mm =to_of_mm_gpio_chip (gc);@@ -344,6 +370,7 @@ static void __init mpc8xxx_add_controller(struct device_node *np) gc->get =of_device_is_compatible (np,"fsl,mpc8572-gpio" ) ? mpc8572_gpio_get : mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; + gc->set_multiple = mpc8xxx_gpio_set_multiple; gc->to_irq = mpc8xxx_gpio_to_irq; ret =of_mm_gpiochip_add (np, mm_gc); --1.8.5.5
Alexandre Courbot
Reviewed-byQuoted 41 lines · Alexandre Courbot
Quoted 40 lines · Rojhalat Ibrahim
Add a
set_multiplefunction to the MPC8xxx GPIO chip driver and thereby allow for actual performance improvements when setting multiple outputs simultaneously. In my case the time needed to configure an FPGA goes down from 48 s to 20 s.Signed-off-by Rojhalat Ibrahim <[email protected]>---
This patch depends on my previous patch "gpiolib: allow simultaneous setting of multiple GPIO outputs".Change log:
v4: - change interface of theset_multipledriver function to use
unsigned long as type for the bit fields
- use generic bitops (which also use unsigned long for bit fields)
v3: - change commit message
v2: - add this patch (v1 included only changes to gpiolib)drivers/gpio/gpio-mpc8xxx.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)drivers/gpio/gpio-mpc8xxx.c +12
-0@@ -105,6 +105,32 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)spin_unlock_irqrestore (&mpc8xxx_gc->lock, flags); } +static void mpc8xxx_gpio_set_multiple (struct gpio_chip *gc, +unsigned long *mask,unsigned long *bits) +{ +struct of_mm_gpio_chip *mm =to_of_mm_gpio_chip (gc); +struct mpc8xxx_gpio_chip *mpc8xxx_gc =to_mpc8xxx_gpio_chip (mm); +unsigned long flags; +int i; + +spin_lock_irqsave (&mpc8xxx_gc->lock, flags); + +for (i =0 ; i < gc->ngpio; i++) { +if (*mask ==0 )
Quoted 8 lines
drivers/gpio/gpio-mpc8xxx.c static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) · line 120
Quoted 1 line
drivers/gpio/gpio-mpc8xxx.c +1
-0+break ;Ok, so this works because presentely you can only have 32 GPIOs max on this chip. But you cannot be sure that future revisions won't extend that number ; and if this happens this function won't work as-is anymore. I won't take much more code to make it more generic, so please do it now to avoid hours of horrendous debugging to your future self.
Looking at it twice you only have one data register, so there is probably not much you can do for the moment - please ignore my previous comment.