All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
@ 2009-07-31 17:27 H Hartley Sweeten
  2009-08-04 21:14 ` David Brownell
  0 siblings, 1 reply; 7+ messages in thread
From: H Hartley Sweeten @ 2009-07-31 17:27 UTC (permalink / raw)
  To: Linux Kernel; +Cc: David Brownell

gpiolib: introduce for_each_gpio_in_chip macro

There are a number of places in gpiolib where all the gpio's handled by a
chip are walked thru using a for() loop.  This introduces a for_each_*
macro to clarify the code.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>

---

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 51a8d41..b060f73 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -56,6 +56,11 @@ struct gpio_desc {
 };
 static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
 
+#define for_each_gpio_in_chip(__gpio, __chip)			\
+	for ((__gpio) = (__chip)->base;				\
+		(__gpio) < (__chip)->base + (__chip)->ngpio;	\
+		(__gpio)++)
+
 static inline void desc_set_label(struct gpio_desc *d, const char *label)
 {
 #ifdef CONFIG_DEBUG_FS
@@ -694,14 +699,14 @@ int gpiochip_add(struct gpio_chip *chip)
 	}
 
 	/* these GPIO numbers must not be managed by another gpio_chip */
-	for (id = base; id < base + chip->ngpio; id++) {
+	for_each_gpio_in_chip(id, chip) {
 		if (gpio_desc[id].chip != NULL) {
 			status = -EBUSY;
 			break;
 		}
 	}
 	if (status == 0) {
-		for (id = base; id < base + chip->ngpio; id++) {
+		for_each_gpio_in_chip(id, chip) {
 			gpio_desc[id].chip = chip;
 
 			/* REVISIT:  most hardware initializes GPIOs as
@@ -744,14 +749,14 @@ int gpiochip_remove(struct gpio_chip *chip)
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
-	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
+	for_each_gpio_in_chip(id, chip) {
 		if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
 			status = -EBUSY;
 			break;
 		}
 	}
 	if (status == 0) {
-		for (id = chip->base; id < chip->base + chip->ngpio; id++)
+		for_each_gpio_in_chip(id, chip)
 			gpio_desc[id].chip = NULL;
 	}
 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-07-31 17:27 [PATCH] gpiolib: introduce for_each_gpio_in_chip macro H Hartley Sweeten
@ 2009-08-04 21:14 ` David Brownell
  2009-08-05  0:48   ` H Hartley Sweeten
  0 siblings, 1 reply; 7+ messages in thread
From: David Brownell @ 2009-08-04 21:14 UTC (permalink / raw)
  To: H Hartley Sweeten; +Cc: Linux Kernel

On Friday 31 July 2009, H Hartley Sweeten wrote:
> gpiolib: introduce for_each_gpio_in_chip macro
> 
> There are a number of places in gpiolib where all the gpio's handled by a
> chip are walked thru using a for() loop.  This introduces a for_each_*
> macro to clarify the code.

I'd rather not.  There are four such loops, and these are
really simple iterators.  Such a macro IMO just obfuscates,
when it's just hiding such trivial index ops.

NAK.

> Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
> 
> ---
> 
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index 51a8d41..b060f73 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -56,6 +56,11 @@ struct gpio_desc {
>  };
>  static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
>  
> +#define for_each_gpio_in_chip(__gpio, __chip)			\
> +	for ((__gpio) = (__chip)->base;				\
> +		(__gpio) < (__chip)->base + (__chip)->ngpio;	\
> +		(__gpio)++)
> +
>  static inline void desc_set_label(struct gpio_desc *d, const char *label)
>  {
>  #ifdef CONFIG_DEBUG_FS
> @@ -694,14 +699,14 @@ int gpiochip_add(struct gpio_chip *chip)
>  	}
>  
>  	/* these GPIO numbers must not be managed by another gpio_chip */
> -	for (id = base; id < base + chip->ngpio; id++) {
> +	for_each_gpio_in_chip(id, chip) {
>  		if (gpio_desc[id].chip != NULL) {
>  			status = -EBUSY;
>  			break;
>  		}
>  	}
>  	if (status == 0) {
> -		for (id = base; id < base + chip->ngpio; id++) {
> +		for_each_gpio_in_chip(id, chip) {
>  			gpio_desc[id].chip = chip;
>  
>  			/* REVISIT:  most hardware initializes GPIOs as
> @@ -744,14 +749,14 @@ int gpiochip_remove(struct gpio_chip *chip)
>  
>  	spin_lock_irqsave(&gpio_lock, flags);
>  
> -	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
> +	for_each_gpio_in_chip(id, chip) {
>  		if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
>  			status = -EBUSY;
>  			break;
>  		}
>  	}
>  	if (status == 0) {
> -		for (id = chip->base; id < chip->base + chip->ngpio; id++)
> +		for_each_gpio_in_chip(id, chip)
>  			gpio_desc[id].chip = NULL;
>  	}
>  
> 
> 




^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-08-04 21:14 ` David Brownell
@ 2009-08-05  0:48   ` H Hartley Sweeten
  2009-08-06  3:31     ` Ben Nizette
  0 siblings, 1 reply; 7+ messages in thread
From: H Hartley Sweeten @ 2009-08-05  0:48 UTC (permalink / raw)
  To: David Brownell; +Cc: Linux Kernel

On Tuesday, August 04, 2009 2:14 PM, David Brownell wrote:
> On Friday 31 July 2009, H Hartley Sweeten wrote:
>> gpiolib: introduce for_each_gpio_in_chip macro
>> 
>> There are a number of places in gpiolib where all the gpio's handled by a
>> chip are walked thru using a for() loop.  This introduces a for_each_*
>> macro to clarify the code.
>
> I'd rather not.  There are four such loops, and these are
> really simple iterators.  Such a macro IMO just obfuscates,
> when it's just hiding such trivial index ops.
>
> NAK.

Ok.

For the record. The reason I sent this is I'm trying to work out an
extension to gpiolib that adds gpio_port_* access to the API.  Most
of the gpiolib drivers already the necessary logic since the raw I/O
is performed on the entire 'chip'.  The API just needs the extensions
added to request/free the port, set the direction and get/set the value.

Is this a worthwhile addition?

Regards,
Hartley

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-08-05  0:48   ` H Hartley Sweeten
@ 2009-08-06  3:31     ` Ben Nizette
  2009-09-19  0:03       ` Jaya Kumar
  0 siblings, 1 reply; 7+ messages in thread
From: Ben Nizette @ 2009-08-06  3:31 UTC (permalink / raw)
  To: H Hartley Sweeten; +Cc: David Brownell, Linux Kernel, Jaya Kumar

On Tue, 2009-08-04 at 20:48 -0400, H Hartley Sweeten wrote:

> For the record. The reason I sent this is I'm trying to work out an
> extension to gpiolib that adds gpio_port_* access to the API.  Most
> of the gpiolib drivers already the necessary logic since the raw I/O
> is performed on the entire 'chip'.  The API just needs the extensions
> added to request/free the port, set the direction and get/set the value.
> 
> Is this a worthwhile addition?

Plenty of people seem to think so.  Personally I haven't seen a great
use case except "'coz I can", but if you've got one I'd love to hear.

Have you seen http://lkml.org/lkml/2009/1/25/10 ?  Donno what ended up
happening to that patchset..

	--Ben.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-08-06  3:31     ` Ben Nizette
@ 2009-09-19  0:03       ` Jaya Kumar
  2009-09-19  0:42         ` H Hartley Sweeten
  0 siblings, 1 reply; 7+ messages in thread
From: Jaya Kumar @ 2009-09-19  0:03 UTC (permalink / raw)
  To: Ben Nizette; +Cc: H Hartley Sweeten, David Brownell, Linux Kernel

On Thu, Aug 6, 2009 at 11:31 AM, Ben Nizette <bn@niasdigital.com> wrote:
> On Tue, 2009-08-04 at 20:48 -0400, H Hartley Sweeten wrote:
>
>> For the record. The reason I sent this is I'm trying to work out an
>> extension to gpiolib that adds gpio_port_* access to the API.  Most
>> of the gpiolib drivers already the necessary logic since the raw I/O
>> is performed on the entire 'chip'.  The API just needs the extensions
>> added to request/free the port, set the direction and get/set the value.
>>
>> Is this a worthwhile addition?
>
> Plenty of people seem to think so.  Personally I haven't seen a great
> use case except "'coz I can", but if you've got one I'd love to hear.

Yes, you're right that there has been no major demand for it. There
are (luckily?) only a moderate number of devices that are using gpio
as their parallel bus interface. I've been supporting the batch-gpio
patchset below out-of-the-tree because it has come in handy with a few
e-paper display controllers and LCD 8080-IO that I've been developing
with.

>
> Have you seen http://lkml.org/lkml/2009/1/25/10 ?  Donno what ended up
> happening to that patchset..
>

I didn't pursue it further and have maintained it out-of-tree. I felt
that David had concerns about the API I implemented so it was unlikely
to get merged and I didn't have the motivation to implement another.
:-)

Thanks,
jaya

ps: I'm in Portland for the festival of linux conferences this week
and would be happy to work on this/discuss alternate APIs if it is of
interest.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-09-19  0:03       ` Jaya Kumar
@ 2009-09-19  0:42         ` H Hartley Sweeten
  2009-09-19  4:40           ` Jaya Kumar
  0 siblings, 1 reply; 7+ messages in thread
From: H Hartley Sweeten @ 2009-09-19  0:42 UTC (permalink / raw)
  To: Jaya Kumar, Ben Nizette; +Cc: David Brownell, Linux Kernel

On Friday, September 18, 2009 5:03 PM, Jaya Kumar wrote:
> On Thu, Aug 6, 2009 at 11:31 AM, Ben Nizette <bn@niasdigital.com> wrote:
>> On Tue, 2009-08-04 at 20:48 -0400, H Hartley Sweeten wrote:
>>
>>> For the record. The reason I sent this is I'm trying to work out an
>>> extension to gpiolib that adds gpio_port_* access to the API.  Most
>>> of the gpiolib drivers already the necessary logic since the raw I/O
>>> is performed on the entire 'chip'.  The API just needs the extensions
>>> added to request/free the port, set the direction and get/set the value.
>>>
>>> Is this a worthwhile addition?
>>
>> Plenty of people seem to think so.  Personally I haven't seen a great
>> use case except "'coz I can", but if you've got one I'd love to hear.
>
> Yes, you're right that there has been no major demand for it. There
> are (luckily?) only a moderate number of devices that are using gpio
> as their parallel bus interface. I've been supporting the batch-gpio
> patchset below out-of-the-tree because it has come in handy with a few
> e-paper display controllers and LCD 8080-IO that I've been developing
> with.

With the abundant number of GPIO's available on many of the ARM chips it
seemed to me a "port" extension would be worthwhile.  It would allow a
side-band bus from the chip to access low-speed devices like a character
LCD as an example.

>>
>> Have you seen http://lkml.org/lkml/2009/1/25/10 ?  Donno what ended up
>> happening to that patchset..
>>
>
> I didn't pursue it further and have maintained it out-of-tree. I felt
> that David had concerns about the API I implemented so it was unlikely
> to get merged and I didn't have the motivation to implement another.
> :-)

Hmm.. That patchset is a lot different than what I was thinking of.  Your 
patch allows a variable width to the number of gpio's in the "port".  But
it also still gets/sets the "port" by individual bit accesses to the
gpio_chip.  By doing this I don't see how you could get a performance
increase.

The extension I was working on just allowed accessing the native width
of the gpio chip.  Most of the gpiolib drivers read/write the bits in a
native width, the individual gpio pin is masked in/out.  My patch just
allows access to the raw data without masking anything.

Take the .get method in pca953x.c driver as an example.

static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{
	struct pca953x_chip *chip;
	uint16_t reg_val;
	int ret;

	chip = container_of(gc, struct pca953x_chip, gpio_chip);

	ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
	if (ret < 0) {
		/* NOTE:  diagnostic already emitted; that's all we should
		 * do unless gpio_*_value_cansleep() calls become different
		 * from their nonsleeping siblings (and report faults).
		 */
		return 0;
	}

	return (reg_val & (1u << off)) ? 1 : 0;
}

The native width of the device is either 8 or 16 bits.  To get a gpio value
all of the bits are read then the desired gpio is masked out.

My thought was to just add the following methods to struct gpio_chip:

int			(*port_direction_input)(struct gpio_chip *chip);
unsigned int	(*port_get)(struct gpio_chip *chip);
int			(*port_direction_output)(struct gpio_chip *chip, unsigned int value);
void			(*port_set)(struct gpio_chip *chip,	unsigned int value);

I basically stopped working on this after Ben's comment and getting
no other feedback.  If this appears useful I can look at it again.

> Thanks,
> jaya
> 
> ps: I'm in Portland for the festival of linux conferences this week
> and would be happy to work on this/discuss alternate APIs if it is of
> interest.

Regards,
Hartley

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] gpiolib: introduce for_each_gpio_in_chip macro
  2009-09-19  0:42         ` H Hartley Sweeten
@ 2009-09-19  4:40           ` Jaya Kumar
  0 siblings, 0 replies; 7+ messages in thread
From: Jaya Kumar @ 2009-09-19  4:40 UTC (permalink / raw)
  To: H Hartley Sweeten; +Cc: Ben Nizette, David Brownell, Linux Kernel

On Sat, Sep 19, 2009 at 8:42 AM, H Hartley Sweeten
<hartleys@visionengravers.com> wrote:
> On Friday, September 18, 2009 5:03 PM, Jaya Kumar wrote:
>
> Hmm.. That patchset is a lot different than what I was thinking of.  Your
> patch allows a variable width to the number of gpio's in the "port".  But
> it also still gets/sets the "port" by individual bit accesses to the
> gpio_chip.  By doing this I don't see how you could get a performance
> increase.

It only does individual bit set/get if the specific arch does not
offer a multi bit set/get. See __gpio_set_batch_generic which calls
chip->set versus __gpio_set_batch which calls chip->set_batch so that
if the underlying architecture supports it then we do multi-bit
access. I provided one for pxa here:
http://marc.info/?l=linux-kernel&m=123287743104542&w=2 . So, the
following scenarios should all be optimized for:

a) if the user calls gpio_s/get_batch with a width that fits the
native register width and all those bits fit into the said register,
then it results in a call directly to the multibit register set/get
function/inline. For example, on pxa with above implementation,
gpio_set_batch(1, mask=0xFFFFFFF, value=0xc001f00d), at compile time,
that will result in a single GPSR/GPCR.
b) if the user calls gpio_s/get_batch with a width that more than one
register, the implementation walks the bits and splits it across the
registers as needed. This is done in __gpio_s/get_batch
c) if the user calls the gpio_s/get_batch with non-consecutive bits
using the 32-bit mask, then the implementation walks the bits and
splits it across the registers as needed.

So, it is fairly optimized. If I understood David's suggested design
correctly, it is one where the user does not need to worry about masks
or widths at all. Instead, you register with the library, a list of
bits you want to make a bus out of, and then the library is
responsible for taking that and optimizing that further as much as
possible. I agree that that would be a more elegant API. What I was
hoping for is that my implementation above could be a starting point
for that by first providing optimized multi-bit access that could be
used by the more elegant API.

Thanks,
jaya

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-09-19  4:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-31 17:27 [PATCH] gpiolib: introduce for_each_gpio_in_chip macro H Hartley Sweeten
2009-08-04 21:14 ` David Brownell
2009-08-05  0:48   ` H Hartley Sweeten
2009-08-06  3:31     ` Ben Nizette
2009-09-19  0:03       ` Jaya Kumar
2009-09-19  0:42         ` H Hartley Sweeten
2009-09-19  4:40           ` Jaya Kumar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.