gpiolib: add support for batch set of pins
Subsystems (5)
RFC 1/1 gpiolib: add support for batch set of pins
This forward tool drops the CC list ... it was everyone listed on the patch itself as a CC.
---------- Forwarded Message ----------
Subject: [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins
Date: Tuesday 25 November 2008
From: Jaya Kumar <[email protected]>
To: [email protected]
Beloved friends,
I would like to request your feedback on the following idea. I hope I have made sure to CC all the right people and the right lists! If not, PLEASE let me know! I couldn't find a MAINTAINERS entry for gpiolib so I just used what I saw in the git log and have also added people and lists that I think may be interested.
This is just an RFC. If you all feel it is looking like the right approach then I'll clean it up and make it a patch.
Thanks,
jaya
am300epd was doing 800*600*16*gpio_set_value for each framebuffer transfer (it uses 16-pins of gpio as its data bus). I found this caused a wee performance limitation. This patch adds an API for gpio_set_value_bus which allows users to set batches of consecutive gpio together in a single call. I have done a test implementation on gumstix (pxa255) with am300epd and it provides a nice improvement in performance.
--- arch/arm/mach-pxa/am300epd.c | 9 ++++++ arch/arm/mach-pxa/gpio.c | 28 +++++++++++++++++++++ arch/arm/mach-pxa/include/mach/gpio.h | 24 ++++++++++++++++++ drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 6 ++++ 5 files changed, 111 insertions(+), 0 deletions(-)
arch/arm/mach-pxa/am300epd.c +9 -0
@@ -222,8 +222,17 @@ static void am300_set_hdb(struct broadsheetfb_par *par, u16 data) {int i; +#if 1 +gpio_set_value_bus (DB0_GPIO_PIN , data,16 ); +#endif +#if 0 +gpio_set_value_bus (DB0_GPIO_PIN , data,6 ); +gpio_set_value_bus (DB0_GPIO_PIN +6 , data >>6 ,10 ); +#endif +#if 0 /* simple set */ for (i =0 ; i <= (DB15_GPIO_PIN -DB0_GPIO_PIN ) ; i++)gpio_set_value (DB0_GPIO_PIN + i, (data >> i) &0x01 ); +#endif }
arch/arm/mach-pxa/gpio.c +28 -0
@@ -132,6 +132,33 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)__raw_writel (mask, pxa->regbase +GPCR_OFFSET ); } +/* +* Set output GPIO level in batches +*/ +static void pxa_gpio_set_bus (struct gpio_chip *chip,unsigned offset, +int values,int bitwidth) +{ +struct pxa_gpio_chip *pxa; +int mask; + +/* we're guaranteed by the caller that offset + bitwidth remains +* in this chip. +*/ + pxa = container_of(chip, struct pxa_gpio_chip, chip); + + mask = ((1 << bitwidth) -1 ) << offset; + values <<= offset; + + values &= mask; +if (values) +__raw_writel (values, pxa->regbase +GPSR_OFFSET ); + + values = ~values; + values &= mask; +if (values) +__raw_writel (values, pxa->regbase +GPCR_OFFSET ); +} +#define GPIO_CHIP (_n) \ [_n] = { \ .regbase = GPIO##_n##_BASE, \
@@ -141,6 +168,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) .direction_output = pxa_gpio_direction_output, \ .get = pxa_gpio_get, \ .set = pxa_gpio_set, \ + .set_bus = pxa_gpio_set_bus, \ .base = (_n) * 32, \ .ngpio = 32, \ }, \
arch/arm/mach-pxa/include/mach/gpio.h +24 -0
@@ -56,6 +56,30 @@ static inline void gpio_set_value(unsigned gpio, int value) } } +static inline void gpio_set_value_bus (unsigned gpio,int values,int bitwidth) +{ +if (__builtin_constant_p (gpio) && + (gpio + bitwidth <NR_BUILTIN_GPIO ) && + ((gpio + bitwidth) <=roundup (gpio+1 ,32 ))) { +int shift, mask; + + shift = gpio %32 ; + mask = ((1 << bitwidth) -1 ) << shift; + values <<= shift; + + values &= mask; +if (values) +GPSR (gpio) = values; + + values = ~values; + values &= mask; +if (values) +GPCR (gpio) = values; + }else { +__gpio_set_value_bus (gpio, values, bitwidth); + } +} +#define gpio_cansleep __gpio_cansleep#define gpio_to_irq (gpio) IRQ_GPIO(gpio)
drivers/gpio/gpiolib.c +44 -0
50 lines not on this page · raw message
include/asm-generic/gpio.h +6 -0
@@ -44,6 +44,8 @@ struct module;* returns either the value actually sensed, or zero * @direction_output: configures signal "offset" as output, or returns error * @set: assigns output value for signal "offset" +* @set_bus: batch assigns output values for consecutive signals starting at +* "offset" with width in bits "bitwidth" * @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * implementation may not sleep * @dbg_show: optional routine to show contents in debugfs; default code
@@ -84,6 +86,9 @@ struct gpio_chip { unsigned offset, int value);void (*set)(struct gpio_chip *chip,unsigned offset,int value); +void (*set_bus)(struct gpio_chip *chip, +unsigned offset,int values, +int bitwidth);int (*to_irq)(struct gpio_chip *chip,unsigned offset);
@@ -124,6 +129,7 @@ extern void gpio_set_value_cansleep(unsigned gpio, int value);*/ extern int __gpio_get_value (unsigned gpio);extern void __gpio_set_value (unsigned gpio,int value); +extern void __gpio_set_value_bus (unsigned gpio,int values,int bitwidth);extern int __gpio_cansleep (unsigned gpio);
Signature · 4 lines
1.5.2.3 -------------------------------------------------------