lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20121220070805.GQ23971@game.jcrosoft.org>
Date:	Thu, 20 Dec 2012 08:08:05 +0100
From:	Jean-Christophe PLAGNIOL-VILLARD <plagnioj@...osoft.com>
To:	Roland Stigge <stigge@...com.de>
Cc:	gregkh@...uxfoundation.org, grant.likely@...retlab.ca,
	linus.walleij@...aro.org, linux-kernel@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org, w.sang@...gutronix.de,
	jbe@...gutronix.de, highguy@...il.com,
	broonie@...nsource.wolfsonmicro.com, daniel-gl@....net,
	rmallon@...il.com, sr@...x.de, wg@...ndegger.com,
	tru@...k-microwave.de, mark.rutland@....com
Subject: Re: [PATCH 6/6 v11] gpio: Add block gpio to several gpio drivers

On 22:22 Wed 19 Dec     , Roland Stigge wrote:
> This patch adds block GPIO support to several gpio drivers.
> 
> This implements block GPIO only for some selected drivers since block GPIO is
> an optional feature which may not be suitable for every GPIO hardware. (With
> automatic fallback to the single GPIO functions if not available in a driver.)
> 
> Signed-off-by: Roland Stigge <stigge@...com.de>
> 
> ---
>  arch/arm/mach-at91/gpio.c         |   33 +++++++++++++++
as said on the previous version the mach-at91 is deprecated for this platform
and boards

you MUST updatethe drivers/pinctrl/pinctrl-at91

nack on at91 untill this is done

Best Regards,
J.
>  drivers/gpio/gpio-em.c            |   23 ++++++++++
>  drivers/gpio/gpio-generic.c       |   56 +++++++++++++++++++++++++
>  drivers/gpio/gpio-lpc32xx.c       |   82 ++++++++++++++++++++++++++++++++++++++
>  drivers/gpio/gpio-max730x.c       |   61 ++++++++++++++++++++++++++++
>  drivers/gpio/gpio-max732x.c       |   59 +++++++++++++++++++++++++++
>  drivers/gpio/gpio-mm-lantiq.c     |   22 ++++++++++
>  drivers/gpio/gpio-pca953x.c       |   64 +++++++++++++++++++++++++++++
>  drivers/gpio/gpio-pcf857x.c       |   24 +++++++++++
>  drivers/gpio/gpio-pch.c           |   27 ++++++++++++
>  drivers/gpio/gpio-pl061.c         |   17 +++++++
>  drivers/gpio/gpio-sa1100.c        |   20 +++++++++
>  drivers/gpio/gpio-samsung.c       |   31 ++++++++++++++
>  drivers/gpio/gpio-twl6040.c       |   32 ++++++++++++++
>  drivers/gpio/gpio-ucb1400.c       |   23 ++++++++++
>  drivers/gpio/gpio-vt8500.c        |   24 +++++++++++
>  drivers/gpio/gpio-xilinx.c        |   44 ++++++++++++++++++++
>  drivers/pinctrl/pinctrl-nomadik.c |   36 ++++++++++++++++
>  18 files changed, 678 insertions(+)
> 
> --- linux-2.6.orig/arch/arm/mach-at91/gpio.c
> +++ linux-2.6/arch/arm/mach-at91/gpio.c
> @@ -42,13 +42,18 @@ struct at91_gpio_chip {
>  	void __iomem		*regbase;	/* PIO bank virtual address */
>  	struct clk		*clock;		/* associated clock */
>  	struct irq_domain	*domain;	/* associated irq domain */
> +	unsigned long		mask_shadow;	/* synchronous data output */
>  };
>  
>  #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
>  
>  static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
>  static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
> +static void at91_gpiolib_set_block(struct gpio_chip *chip, unsigned long mask,
> +				   unsigned long val);
>  static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
> +static unsigned long at91_gpiolib_get_block(struct gpio_chip *chip,
> +					    unsigned long mask);
>  static int at91_gpiolib_direction_output(struct gpio_chip *chip,
>  					 unsigned offset, int val);
>  static int at91_gpiolib_direction_input(struct gpio_chip *chip,
> @@ -62,7 +67,9 @@ static int at91_gpiolib_to_irq(struct gp
>  			.direction_input  = at91_gpiolib_direction_input, \
>  			.direction_output = at91_gpiolib_direction_output, \
>  			.get		  = at91_gpiolib_get,		\
> +			.get_block	  = at91_gpiolib_get_block,	\
>  			.set		  = at91_gpiolib_set,		\
> +			.set_block	  = at91_gpiolib_set_block,	\
>  			.dbg_show	  = at91_gpiolib_dbg_show,	\
>  			.to_irq		  = at91_gpiolib_to_irq,	\
>  			.ngpio		  = nr_gpio,			\
> @@ -896,6 +903,17 @@ static int at91_gpiolib_get(struct gpio_
>  	return (pdsr & mask) != 0;
>  }
>  
> +static unsigned long at91_gpiolib_get_block(struct gpio_chip *chip,
> +					    unsigned long mask)
> +{
> +	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> +	void __iomem *pio = at91_gpio->regbase;
> +	u32 pdsr;
> +
> +	pdsr = __raw_readl(pio + PIO_PDSR);
> +	return pdsr & mask;
> +}
> +
>  static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
>  {
>  	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> @@ -905,6 +923,21 @@ static void at91_gpiolib_set(struct gpio
>  	__raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR));
>  }
>  
> +static void at91_gpiolib_set_block(struct gpio_chip *chip, unsigned long mask,
> +				   unsigned long val)
> +{
> +	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
> +	void __iomem *pio = at91_gpio->regbase;
> +
> +	/* Do synchronous data output with a single write access */
> +	if (mask != at91_gpio->mask_shadow) {
> +		at91_gpio->mask_shadow = mask;
> +		__raw_writel(~mask, pio + PIO_OWDR);
> +		__raw_writel(mask, pio + PIO_OWER);
> +	}
> +	__raw_writel(val, pio + PIO_ODSR);
> +}
> +
>  static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
>  {
>  	int i;
> --- linux-2.6.orig/drivers/gpio/gpio-em.c
> +++ linux-2.6/drivers/gpio/gpio-em.c
> @@ -203,6 +203,27 @@ static void em_gio_set(struct gpio_chip
>  		__em_gio_set(chip, GIO_OH, offset - 16, value);
>  }
>  
> +static unsigned long em_gio_get_block(struct gpio_chip *chip,
> +				      unsigned long mask)
> +{
> +	return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & mask);
> +}
> +
> +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask,
> +			     unsigned long values)
> +{
> +	unsigned long mask_ol = mask & 0xFFFF;
> +	unsigned long mask_oh = mask >> 16;
> +
> +	unsigned long values_ol = values & mask_ol;
> +	unsigned long values_oh = (values >> 16) & mask_oh;
> +
> +	em_gio_write(gpio_to_priv(chip), GIO_OL,
> +		     mask_ol << 16 | values_ol);
> +	em_gio_write(gpio_to_priv(chip), GIO_OH,
> +		     mask_oh << 16 | values_oh);
> +}
> +
>  static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
>  				   int value)
>  {
> @@ -317,8 +338,10 @@ static int __devinit em_gio_probe(struct
>  	gpio_chip = &p->gpio_chip;
>  	gpio_chip->direction_input = em_gio_direction_input;
>  	gpio_chip->get = em_gio_get;
> +	gpio_chip->get_block = em_gio_get_block;
>  	gpio_chip->direction_output = em_gio_direction_output;
>  	gpio_chip->set = em_gio_set;
> +	gpio_chip->set_block = em_gio_set_block;
>  	gpio_chip->to_irq = em_gio_to_irq;
>  	gpio_chip->label = name;
>  	gpio_chip->owner = THIS_MODULE;
> --- linux-2.6.orig/drivers/gpio/gpio-generic.c
> +++ linux-2.6/drivers/gpio/gpio-generic.c
> @@ -122,6 +122,13 @@ static int bgpio_get(struct gpio_chip *g
>  	return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
>  }
>  
> +static unsigned long bgpio_get_block(struct gpio_chip *gc, unsigned long mask)
> +{
> +	struct bgpio_chip *bgc = to_bgpio_chip(gc);
> +
> +	return bgc->read_reg(bgc->reg_dat) & mask;
> +}
> +
>  static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
>  {
>  	struct bgpio_chip *bgc = to_bgpio_chip(gc);
> @@ -170,6 +177,51 @@ static void bgpio_set_set(struct gpio_ch
>  	spin_unlock_irqrestore(&bgc->lock, flags);
>  }
>  
> +static void bgpio_set_block(struct gpio_chip *gc, unsigned long mask,
> +			    unsigned long values)
> +{
> +	struct bgpio_chip *bgc = to_bgpio_chip(gc);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&bgc->lock, flags);
> +
> +	bgc->data &= ~mask;
> +	bgc->data |= values & mask;
> +
> +	bgc->write_reg(bgc->reg_dat, bgc->data);
> +
> +	spin_unlock_irqrestore(&bgc->lock, flags);
> +}
> +
> +static void bgpio_set_with_clear_block(struct gpio_chip *gc, unsigned long mask,
> +				       unsigned long values)
> +{
> +	struct bgpio_chip *bgc = to_bgpio_chip(gc);
> +	unsigned long set_bits = values & mask;
> +	unsigned long clr_bits = ~values & mask;
> +
> +	if (set_bits)
> +		bgc->write_reg(bgc->reg_set, set_bits);
> +	if (clr_bits)
> +		bgc->write_reg(bgc->reg_set, clr_bits);
> +}
> +
> +static void bgpio_set_set_block(struct gpio_chip *gc, unsigned long mask,
> +				unsigned long values)
> +{
> +	struct bgpio_chip *bgc = to_bgpio_chip(gc);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&bgc->lock, flags);
> +
> +	bgc->data &= ~mask;
> +	bgc->data |= values & mask;
> +
> +	bgc->write_reg(bgc->reg_set, bgc->data);
> +
> +	spin_unlock_irqrestore(&bgc->lock, flags);
> +}
> +
>  static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
>  {
>  	return 0;
> @@ -317,14 +369,18 @@ static int bgpio_setup_io(struct bgpio_c
>  		bgc->reg_set = set;
>  		bgc->reg_clr = clr;
>  		bgc->gc.set = bgpio_set_with_clear;
> +		bgc->gc.set_block = bgpio_set_with_clear_block;
>  	} else if (set && !clr) {
>  		bgc->reg_set = set;
>  		bgc->gc.set = bgpio_set_set;
> +		bgc->gc.set_block = bgpio_set_set_block;
>  	} else {
>  		bgc->gc.set = bgpio_set;
> +		bgc->gc.set_block = bgpio_set_block;
>  	}
>  
>  	bgc->gc.get = bgpio_get;
> +	bgc->gc.get_block = bgpio_get_block;
>  
>  	return 0;
>  }
> --- linux-2.6.orig/drivers/gpio/gpio-lpc32xx.c
> +++ linux-2.6/drivers/gpio/gpio-lpc32xx.c
> @@ -297,6 +297,22 @@ static int lpc32xx_gpio_get_value_p3(str
>  	return __get_gpio_state_p3(group, pin);
>  }
>  
> +static unsigned long lpc32xx_gpio_get_block_p3(struct gpio_chip *chip,
> +					       unsigned long mask)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +	u32 bits = __raw_readl(group->gpio_grp->inp_state);
> +
> +	/* In P3_INP_STATE, the 6 GPIOs are scattered over the register,
> +	 * rearranging to bits 0-5
> +	 */
> +	bits >>= 10;
> +	bits &= 0x401F;
> +	bits |= (bits & 0x4000) >> 9;
> +
> +	return bits & mask & 0x3F;
> +}
> +
>  static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
>  {
>  	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> @@ -304,6 +320,15 @@ static int lpc32xx_gpi_get_value(struct
>  	return __get_gpi_state_p3(group, pin);
>  }
>  
> +static unsigned long lpc32xx_gpi_get_block(struct gpio_chip *chip,
> +					   unsigned long mask)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +	u32 bits = __raw_readl(group->gpio_grp->inp_state);
> +
> +	return bits & mask;
> +}
> +
>  static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
>  	int value)
>  {
> @@ -351,6 +376,27 @@ static void lpc32xx_gpio_set_value_p3(st
>  	__set_gpio_level_p3(group, pin, value);
>  }
>  
> +static void lpc32xx_gpio_set_block_p3(struct gpio_chip *chip,
> +				      unsigned long mask,
> +				      unsigned long values)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +	u32 set_bits = values & mask;
> +	u32 clr_bits = ~values & mask;
> +
> +	/* States of GPIO 0-5 start at bit 25 */
> +	set_bits <<= 25;
> +	clr_bits <<= 25;
> +
> +	/* Note: On LPC32xx, GPOs can only be set at once or cleared at once,
> +	 *       but not set and cleared at once
> +	 */
> +	if (set_bits)
> +		__raw_writel(set_bits, group->gpio_grp->outp_set);
> +	if (clr_bits)
> +		__raw_writel(clr_bits, group->gpio_grp->outp_clr);
> +}
> +
>  static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
>  	int value)
>  {
> @@ -366,6 +412,31 @@ static int lpc32xx_gpo_get_value(struct
>  	return __get_gpo_state_p3(group, pin);
>  }
>  
> +static void lpc32xx_gpo_set_block(struct gpio_chip *chip, unsigned long mask,
> +				  unsigned long values)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +	u32 set_bits = values & mask;
> +	u32 clr_bits = ~values & mask;
> +
> +	/* Note: On LPC32xx, GPOs can only be set at once or cleared at once,
> +	 *       but not set and cleared at once
> +	 */
> +	if (set_bits)
> +		__raw_writel(set_bits, group->gpio_grp->outp_set);
> +	if (clr_bits)
> +		__raw_writel(clr_bits, group->gpio_grp->outp_clr);
> +}
> +
> +static unsigned long lpc32xx_gpo_get_block(struct gpio_chip *chip,
> +					   unsigned long mask)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +	u32 bits = __raw_readl(group->gpio_grp->outp_state);
> +
> +	return bits & mask;
> +}
> +
>  static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
>  {
>  	if (pin < chip->ngpio)
> @@ -440,8 +511,10 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpio_p0",
>  			.direction_input	= lpc32xx_gpio_dir_input_p012,
>  			.get			= lpc32xx_gpio_get_value_p012,
> +			.get_block		= lpc32xx_gpi_get_block,
>  			.direction_output	= lpc32xx_gpio_dir_output_p012,
>  			.set			= lpc32xx_gpio_set_value_p012,
> +			.set_block		= lpc32xx_gpo_set_block,
>  			.request		= lpc32xx_gpio_request,
>  			.to_irq			= lpc32xx_gpio_to_irq_p01,
>  			.base			= LPC32XX_GPIO_P0_GRP,
> @@ -456,8 +529,10 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpio_p1",
>  			.direction_input	= lpc32xx_gpio_dir_input_p012,
>  			.get			= lpc32xx_gpio_get_value_p012,
> +			.get_block		= lpc32xx_gpi_get_block,
>  			.direction_output	= lpc32xx_gpio_dir_output_p012,
>  			.set			= lpc32xx_gpio_set_value_p012,
> +			.set_block		= lpc32xx_gpo_set_block,
>  			.request		= lpc32xx_gpio_request,
>  			.to_irq			= lpc32xx_gpio_to_irq_p01,
>  			.base			= LPC32XX_GPIO_P1_GRP,
> @@ -472,8 +547,10 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpio_p2",
>  			.direction_input	= lpc32xx_gpio_dir_input_p012,
>  			.get			= lpc32xx_gpio_get_value_p012,
> +			.get_block		= lpc32xx_gpi_get_block,
>  			.direction_output	= lpc32xx_gpio_dir_output_p012,
>  			.set			= lpc32xx_gpio_set_value_p012,
> +			.set_block		= lpc32xx_gpo_set_block,
>  			.request		= lpc32xx_gpio_request,
>  			.base			= LPC32XX_GPIO_P2_GRP,
>  			.ngpio			= LPC32XX_GPIO_P2_MAX,
> @@ -487,8 +564,10 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpio_p3",
>  			.direction_input	= lpc32xx_gpio_dir_input_p3,
>  			.get			= lpc32xx_gpio_get_value_p3,
> +			.get_block		= lpc32xx_gpio_get_block_p3,
>  			.direction_output	= lpc32xx_gpio_dir_output_p3,
>  			.set			= lpc32xx_gpio_set_value_p3,
> +			.set_block		= lpc32xx_gpio_set_block_p3,
>  			.request		= lpc32xx_gpio_request,
>  			.to_irq			= lpc32xx_gpio_to_irq_gpio_p3,
>  			.base			= LPC32XX_GPIO_P3_GRP,
> @@ -503,6 +582,7 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpi_p3",
>  			.direction_input	= lpc32xx_gpio_dir_in_always,
>  			.get			= lpc32xx_gpi_get_value,
> +			.get_block		= lpc32xx_gpi_get_block,
>  			.request		= lpc32xx_gpio_request,
>  			.to_irq			= lpc32xx_gpio_to_irq_gpi_p3,
>  			.base			= LPC32XX_GPI_P3_GRP,
> @@ -517,7 +597,9 @@ static struct lpc32xx_gpio_chip lpc32xx_
>  			.label			= "gpo_p3",
>  			.direction_output	= lpc32xx_gpio_dir_out_always,
>  			.set			= lpc32xx_gpo_set_value,
> +			.set_block		= lpc32xx_gpo_set_block,
>  			.get			= lpc32xx_gpo_get_value,
> +			.get_block		= lpc32xx_gpo_get_block,
>  			.request		= lpc32xx_gpio_request,
>  			.base			= LPC32XX_GPO_P3_GRP,
>  			.ngpio			= LPC32XX_GPO_P3_MAX,
> --- linux-2.6.orig/drivers/gpio/gpio-max730x.c
> +++ linux-2.6/drivers/gpio/gpio-max730x.c
> @@ -146,6 +146,44 @@ static int max7301_get(struct gpio_chip
>  	return level;
>  }
>  
> +static unsigned long max7301_get_block(struct gpio_chip *chip,
> +				       unsigned long mask)
> +{
> +	struct max7301 *ts = container_of(chip, struct max7301, chip);
> +	int i, j;
> +	unsigned long result = 0;
> +
> +	for (i = 0; i < 4; i++) {
> +		if ((mask >> (i * 8)) & 0xFF) { /* i/o only if necessary */
> +			u8 in_level = ts->read(ts->dev, 0x44 + i * 8);
> +			u8 in_mask = 0;
> +			u8 out_level = (ts->out_level >> (i * 8 + 4)) & 0xFF;
> +			u8 out_mask = 0;
> +
> +			for (j = 0; j < 8; j++) {
> +				int offset = 4 + i * 8 + j;
> +				int config = (ts->port_config[offset >> 2] >>
> +					      ((offset & 3) << 1)) &
> +					PIN_CONFIG_MASK;
> +
> +				switch (config) {
> +				case PIN_CONFIG_OUT:
> +					out_mask |= BIT(j);
> +					break;
> +				case PIN_CONFIG_IN_WO_PULLUP:
> +				case PIN_CONFIG_IN_PULLUP:
> +					in_mask |= BIT(j);
> +				}
> +			}
> +
> +			result |= ((unsigned long)(in_level & in_mask) |
> +				   (out_level & out_mask)) << (i * 8);
> +		}
> +	}
> +
> +	return result & mask;
> +}
> +
>  static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
>  {
>  	struct max7301 *ts = container_of(chip, struct max7301, chip);
> @@ -160,6 +198,27 @@ static void max7301_set(struct gpio_chip
>  	mutex_unlock(&ts->lock);
>  }
>  
> +static void max7301_set_block(struct gpio_chip *chip, unsigned long mask,
> +			      unsigned long values)
> +{
> +	struct max7301 *ts = container_of(chip, struct max7301, chip);
> +	unsigned long changes;
> +	int i;
> +
> +	mutex_lock(&ts->lock);
> +
> +	changes = (ts->out_level ^ (values << 4)) & (mask << 4);
> +	ts->out_level ^= changes;
> +
> +	for (i = 0; i < 4; i++) {
> +		if ((changes >> (i * 8 + 4)) & 0xFF) /* i/o only on change */
> +			ts->write(ts->dev, 0x44 + i * 8,
> +				  (ts->out_level >> (i * 8 + 4)) & 0xFF);
> +	}
> +
> +	mutex_unlock(&ts->lock);
> +}
> +
>  int __devinit __max730x_probe(struct max7301 *ts)
>  {
>  	struct device *dev = ts->dev;
> @@ -184,8 +243,10 @@ int __devinit __max730x_probe(struct max
>  
>  	ts->chip.direction_input = max7301_direction_input;
>  	ts->chip.get = max7301_get;
> +	ts->chip.get_block = max7301_get_block;
>  	ts->chip.direction_output = max7301_direction_output;
>  	ts->chip.set = max7301_set;
> +	ts->chip.set_block = max7301_set_block;
>  
>  	ts->chip.ngpio = PIN_NUMBER;
>  	ts->chip.can_sleep = 1;
> --- linux-2.6.orig/drivers/gpio/gpio-max732x.c
> +++ linux-2.6/drivers/gpio/gpio-max732x.c
> @@ -219,6 +219,63 @@ out:
>  	mutex_unlock(&chip->lock);
>  }
>  
> +static unsigned long max732x_gpio_get_block(struct gpio_chip *gc,
> +					    unsigned long mask)
> +{
> +	struct max732x_chip *chip;
> +	uint8_t lo = 0;
> +	uint8_t hi = 0;
> +	int ret;
> +
> +	chip = container_of(gc, struct max732x_chip, gpio_chip);
> +
> +	if (mask & 0xFF) {
> +		ret = max732x_readb(chip, is_group_a(chip, 0), &lo);
> +		if (ret < 0)
> +			return 0;
> +	}
> +	if (mask & 0xFF00) {
> +		ret = max732x_readb(chip, is_group_a(chip, 8), &hi);
> +		if (ret < 0)
> +			return 0;
> +	}
> +
> +	return (((unsigned long)hi << 8) | lo) & mask;
> +}
> +
> +static void max732x_gpio_set_block(struct gpio_chip *gc, unsigned long mask,
> +				   unsigned long values)
> +{
> +	struct max732x_chip *chip;
> +	uint8_t reg_out;
> +	uint8_t lo_mask = mask & 0xFF;
> +	uint8_t hi_mask = (mask >> 8) & 0xFF;
> +	int ret;
> +
> +	chip = container_of(gc, struct max732x_chip, gpio_chip);
> +
> +	mutex_lock(&chip->lock);
> +
> +	if (lo_mask) {
> +		reg_out = (chip->reg_out[0] & ~lo_mask) | (values & lo_mask);
> +		ret = max732x_writeb(chip, is_group_a(chip, 0), reg_out);
> +		if (ret < 0)
> +			goto out;
> +		chip->reg_out[0] = reg_out;
> +	}
> +	if (hi_mask) {
> +		reg_out = (chip->reg_out[1] & ~hi_mask) |
> +			((values >> 8) & hi_mask);
> +		ret = max732x_writeb(chip, is_group_a(chip, 8), reg_out);
> +		if (ret < 0)
> +			goto out;
> +		chip->reg_out[1] = reg_out;
> +	}
> +
> +out:
> +	mutex_unlock(&chip->lock);
> +}
> +
>  static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
>  {
>  	struct max732x_chip *chip;
> @@ -562,8 +619,10 @@ static int __devinit max732x_setup_gpio(
>  	if (chip->dir_output) {
>  		gc->direction_output = max732x_gpio_direction_output;
>  		gc->set = max732x_gpio_set_value;
> +		gc->set_block = max732x_gpio_set_block;
>  	}
>  	gc->get = max732x_gpio_get_value;
> +	gc->get_block = max732x_gpio_get_block;
>  	gc->can_sleep = 1;
>  
>  	gc->base = gpio_start;
> --- linux-2.6.orig/drivers/gpio/gpio-mm-lantiq.c
> +++ linux-2.6/drivers/gpio/gpio-mm-lantiq.c
> @@ -73,6 +73,27 @@ static void ltq_mm_set(struct gpio_chip
>  }
>  
>  /**
> + * ltq_mm_set_block() - gpio_chip->set_block - set gpios simultaneously.
> + * @gc:     Pointer to gpio_chip device structure.
> + * @mask:   Bit map of masked GPIOs in this gpio_chip.
> + * @values: Values to be written to the specified signals.
> + *
> + * Set the shadow values and call ltq_mm_apply.
> + */
> +static void ltq_mm_set_block(struct gpio_chip *gc, unsigned long mask,
> +			     unsigned long values)
> +{
> +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
> +	struct ltq_mm *chip =
> +		container_of(mm_gc, struct ltq_mm, mmchip);
> +
> +	chip->shadow &= ~mask;
> +	chip->shadow |= values & mask;
> +
> +	ltq_mm_apply(chip);
> +}
> +
> +/**
>   * ltq_mm_dir_out() - gpio_chip->dir_out - set gpio direction.
>   * @gc:     Pointer to gpio_chip device structure.
>   * @gpio:   GPIO signal number.
> @@ -122,6 +143,7 @@ static int ltq_mm_probe(struct platform_
>  	chip->mmchip.gc.label = "gpio-mm-ltq";
>  	chip->mmchip.gc.direction_output = ltq_mm_dir_out;
>  	chip->mmchip.gc.set = ltq_mm_set;
> +	chip->mmchip.gc.set_block = ltq_mm_set_block;
>  	chip->mmchip.save_regs = ltq_mm_save_regs;
>  
>  	/* store the shadow value if one was passed by the devicetree */
> --- linux-2.6.orig/drivers/gpio/gpio-pca953x.c
> +++ linux-2.6/drivers/gpio/gpio-pca953x.c
> @@ -300,6 +300,68 @@ exit:
>  	mutex_unlock(&chip->i2c_lock);
>  }
>  
> +static unsigned long pca953x_gpio_get_block(struct gpio_chip *gc,
> +					    unsigned long mask)
> +{
> +	struct pca953x_chip *chip;
> +	u32 reg_val;
> +	int ret, offset = 0;
> +
> +	chip = container_of(gc, struct pca953x_chip, gpio_chip);
> +
> +	mutex_lock(&chip->i2c_lock);
> +	switch (chip->chip_type) {
> +	case PCA953X_TYPE:
> +		offset = PCA953X_INPUT;
> +		break;
> +	case PCA957X_TYPE:
> +		offset = PCA957X_IN;
> +		break;
> +	}
> +	ret = pca953x_read_reg(chip, offset, &reg_val);
> +	mutex_unlock(&chip->i2c_lock);
> +	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 & mask;
> +}
> +
> +static void pca953x_gpio_set_block(struct gpio_chip *gc, unsigned long mask,
> +				   unsigned long values)
> +{
> +	struct pca953x_chip *chip;
> +	u32 reg_val;
> +	int ret, offset = 0;
> +
> +	chip = container_of(gc, struct pca953x_chip, gpio_chip);
> +
> +	mutex_lock(&chip->i2c_lock);
> +
> +	reg_val = chip->reg_output & ~mask;
> +	reg_val |= values & mask;
> +
> +	switch (chip->chip_type) {
> +	case PCA953X_TYPE:
> +		offset = PCA953X_OUTPUT;
> +		break;
> +	case PCA957X_TYPE:
> +		offset = PCA957X_OUT;
> +		break;
> +	}
> +	ret = pca953x_write_reg(chip, offset, reg_val);
> +	if (ret)
> +		goto exit;
> +
> +	chip->reg_output = reg_val;
> +exit:
> +	mutex_unlock(&chip->i2c_lock);
> +}
> +
>  static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
>  {
>  	struct gpio_chip *gc;
> @@ -310,6 +372,8 @@ static void pca953x_setup_gpio(struct pc
>  	gc->direction_output = pca953x_gpio_direction_output;
>  	gc->get = pca953x_gpio_get_value;
>  	gc->set = pca953x_gpio_set_value;
> +	gc->get_block = pca953x_gpio_get_block;
> +	gc->set_block = pca953x_gpio_set_block;
>  	gc->can_sleep = 1;
>  
>  	gc->base = chip->gpio_start;
> --- linux-2.6.orig/drivers/gpio/gpio-pcf857x.c
> +++ linux-2.6/drivers/gpio/gpio-pcf857x.c
> @@ -158,6 +158,28 @@ static void pcf857x_set(struct gpio_chip
>  	pcf857x_output(chip, offset, value);
>  }
>  
> +static unsigned long pcf857x_get_block(struct gpio_chip *chip,
> +				       unsigned long mask)
> +{
> +	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
> +	int		value;
> +
> +	value = gpio->read(gpio->client);
> +	return (value < 0) ? 0 : (value & mask);
> +}
> +
> +static void pcf857x_set_block(struct gpio_chip *chip, unsigned long mask,
> +			      unsigned long values)
> +{
> +	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
> +
> +	mutex_lock(&gpio->lock);
> +	gpio->out &= ~mask;
> +	gpio->out |= values & mask;
> +	gpio->write(gpio->client, gpio->out);
> +	mutex_unlock(&gpio->lock);
> +}
> +
>  /*-------------------------------------------------------------------------*/
>  
>  static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
> @@ -280,6 +302,8 @@ static int pcf857x_probe(struct i2c_clie
>  	gpio->chip.owner		= THIS_MODULE;
>  	gpio->chip.get			= pcf857x_get;
>  	gpio->chip.set			= pcf857x_set;
> +	gpio->chip.get_block		= pcf857x_get_block;
> +	gpio->chip.set_block		= pcf857x_set_block;
>  	gpio->chip.direction_input	= pcf857x_input;
>  	gpio->chip.direction_output	= pcf857x_output;
>  	gpio->chip.ngpio		= id->driver_data;
> --- linux-2.6.orig/drivers/gpio/gpio-pch.c
> +++ linux-2.6/drivers/gpio/gpio-pch.c
> @@ -122,6 +122,23 @@ static void pch_gpio_set(struct gpio_chi
>  	spin_unlock_irqrestore(&chip->spinlock, flags);
>  }
>  
> +static void pch_gpio_set_block(struct gpio_chip *gpio, unsigned long mask,
> +			       unsigned long values)
> +{
> +	u32 reg_val;
> +	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&chip->spinlock, flags);
> +	reg_val = ioread32(&chip->reg->po);
> +
> +	reg_val &= ~mask;
> +	reg_val |= values & mask;
> +
> +	iowrite32(reg_val, &chip->reg->po);
> +	spin_unlock_irqrestore(&chip->spinlock, flags);
> +}
> +
>  static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
>  {
>  	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
> @@ -129,6 +146,14 @@ static int pch_gpio_get(struct gpio_chip
>  	return ioread32(&chip->reg->pi) & (1 << nr);
>  }
>  
> +static unsigned long pch_gpio_get_block(struct gpio_chip *gpio,
> +					unsigned long mask)
> +{
> +	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
> +
> +	return ioread32(&chip->reg->pi) & mask;
> +}
> +
>  static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
>  				     int val)
>  {
> @@ -218,8 +243,10 @@ static void pch_gpio_setup(struct pch_gp
>  	gpio->owner = THIS_MODULE;
>  	gpio->direction_input = pch_gpio_direction_input;
>  	gpio->get = pch_gpio_get;
> +	gpio->get_block = pch_gpio_get_block;
>  	gpio->direction_output = pch_gpio_direction_output;
>  	gpio->set = pch_gpio_set;
> +	gpio->set_block = pch_gpio_set_block;
>  	gpio->dbg_show = NULL;
>  	gpio->base = -1;
>  	gpio->ngpio = gpio_pins[chip->ioh];
> --- linux-2.6.orig/drivers/gpio/gpio-pl061.c
> +++ linux-2.6/drivers/gpio/gpio-pl061.c
> @@ -123,6 +123,21 @@ static void pl061_set_value(struct gpio_
>  	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
>  }
>  
> +static unsigned long pl061_get_block(struct gpio_chip *gc, unsigned long mask)
> +{
> +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
> +
> +	return !!readb(chip->base + (mask << 2));
> +}
> +
> +static void pl061_set_block(struct gpio_chip *gc, unsigned long mask,
> +			    unsigned long values)
> +{
> +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
> +
> +	writeb(values & mask, chip->base + (mask << 2));
> +}
> +
>  static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
>  {
>  	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
> @@ -256,6 +271,8 @@ static int pl061_probe(struct amba_devic
>  	chip->gc.direction_output = pl061_direction_output;
>  	chip->gc.get = pl061_get_value;
>  	chip->gc.set = pl061_set_value;
> +	chip->gc.get_block = pl061_get_block;
> +	chip->gc.set_block = pl061_set_block;
>  	chip->gc.to_irq = pl061_to_irq;
>  	chip->gc.ngpio = PL061_GPIO_NR;
>  	chip->gc.label = dev_name(&dev->dev);
> --- linux-2.6.orig/drivers/gpio/gpio-sa1100.c
> +++ linux-2.6/drivers/gpio/gpio-sa1100.c
> @@ -27,6 +27,24 @@ static void sa1100_gpio_set(struct gpio_
>  		GPCR = GPIO_GPIO(offset);
>  }
>  
> +static unsigned long sa1100_gpio_get_block(struct gpio_chip *chip,
> +					   unsigned long mask)
> +{
> +	return GPLR & mask;
> +}
> +
> +static void sa1100_gpio_set_block(struct gpio_chip *chip, unsigned long mask,
> +				  unsigned long values)
> +{
> +	unsigned long set_bits = values & mask;
> +	unsigned long clr_bits = ~values & mask;
> +
> +	if (set_bits)
> +		GPSR = set_bits;
> +	if (clr_bits)
> +		GPCR = clr_bits;
> +}
> +
>  static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
>  {
>  	unsigned long flags;
> @@ -59,6 +77,8 @@ static struct gpio_chip sa1100_gpio_chip
>  	.direction_output	= sa1100_direction_output,
>  	.set			= sa1100_gpio_set,
>  	.get			= sa1100_gpio_get,
> +	.set_block		= sa1100_gpio_set_block,
> +	.get_block		= sa1100_gpio_get_block,
>  	.to_irq			= sa1100_to_irq,
>  	.base			= 0,
>  	.ngpio			= GPIO_MAX + 1,
> --- linux-2.6.orig/drivers/gpio/gpio-samsung.c
> +++ linux-2.6/drivers/gpio/gpio-samsung.c
> @@ -865,6 +865,33 @@ static int samsung_gpiolib_get(struct gp
>  	return val;
>  }
>  
> +static void samsung_gpiolib_set_block(struct gpio_chip *chip,
> +				      unsigned long mask,
> +				      unsigned long values)
> +{
> +	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
> +	void __iomem *base = ourchip->base;
> +	unsigned long flags;
> +	unsigned long dat;
> +
> +	samsung_gpio_lock(ourchip, flags);
> +
> +	dat = __raw_readl(base + 0x04);
> +	dat &= ~mask;
> +	dat |= values & mask;
> +	__raw_writel(dat, base + 0x04);
> +
> +	samsung_gpio_unlock(ourchip, flags);
> +}
> +
> +static unsigned long samsung_gpiolib_get_block(struct gpio_chip *chip,
> +					       unsigned long mask)
> +{
> +	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
> +
> +	return __raw_readl(ourchip->base + 0x04) & mask;
> +}
> +
>  /*
>   * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
>   * for use with the configuration calls, and other parts of the s3c gpiolib
> @@ -922,6 +949,10 @@ static void __init samsung_gpiolib_add(s
>  		gc->set = samsung_gpiolib_set;
>  	if (!gc->get)
>  		gc->get = samsung_gpiolib_get;
> +	if (!gc->set_block)
> +		gc->set_block = samsung_gpiolib_set_block;
> +	if (!gc->get_block)
> +		gc->get_block = samsung_gpiolib_get_block;
>  
>  #ifdef CONFIG_PM
>  	if (chip->pm != NULL) {
> --- linux-2.6.orig/drivers/gpio/gpio-twl6040.c
> +++ linux-2.6/drivers/gpio/gpio-twl6040.c
> @@ -46,6 +46,19 @@ static int twl6040gpo_get(struct gpio_ch
>  	return (ret >> offset) & 1;
>  }
>  
> +static unsigned long twl6040gpo_get_block(struct gpio_chip *chip,
> +					  unsigned long mask)
> +{
> +	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
> +	int ret = 0;
> +
> +	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
> +	if (ret < 0)
> +		return 0;
> +
> +	return ret & mask;
> +}
> +
>  static int twl6040gpo_direction_out(struct gpio_chip *chip, unsigned offset,
>  				    int value)
>  {
> @@ -71,12 +84,31 @@ static void twl6040gpo_set(struct gpio_c
>  	twl6040_reg_write(twl6040, TWL6040_REG_GPOCTL, gpoctl);
>  }
>  
> +static void twl6040gpo_set_block(struct gpio_chip *chip, unsigned long mask,
> +				 unsigned long values)
> +{
> +	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
> +	int ret;
> +	u8 gpoctl;
> +
> +	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
> +	if (ret < 0)
> +		return;
> +
> +	gpoctl = ret & ~mask;
> +	gpoctl |= values & mask;
> +
> +	twl6040_reg_write(twl6040, TWL6040_REG_GPOCTL, gpoctl);
> +}
> +
>  static struct gpio_chip twl6040gpo_chip = {
>  	.label			= "twl6040",
>  	.owner			= THIS_MODULE,
>  	.get			= twl6040gpo_get,
> +	.get_block		= twl6040gpo_get_block,
>  	.direction_output	= twl6040gpo_direction_out,
>  	.set			= twl6040gpo_set,
> +	.set_block		= twl6040gpo_set_block,
>  	.can_sleep		= 1,
>  };
>  
> --- linux-2.6.orig/drivers/gpio/gpio-ucb1400.c
> +++ linux-2.6/drivers/gpio/gpio-ucb1400.c
> @@ -45,6 +45,27 @@ static void ucb1400_gpio_set(struct gpio
>  	ucb1400_gpio_set_value(gpio->ac97, off, val);
>  }
>  
> +static unsigned long ucb1400_gpio_get_block(struct gpio_chip *gc,
> +					    unsigned long mask)
> +{
> +	struct ucb1400_gpio *gpio;
> +	gpio = container_of(gc, struct ucb1400_gpio, gc);
> +	return ucb1400_reg_read(gpio->ac97, UCB_IO_DATA) & mask;
> +}
> +
> +static void ucb1400_gpio_set_block(struct gpio_chip *gc, unsigned long mask,
> +				   unsigned long values)
> +{
> +	struct ucb1400_gpio *gpio;
> +	u16 tmp;
> +	gpio = container_of(gc, struct ucb1400_gpio, gc);
> +
> +	tmp = ucb1400_reg_read(gpio->ac97, UCB_IO_DATA) & ~mask;
> +	tmp |= values & mask;
> +
> +	ucb1400_reg_write(gpio->ac97, UCB_IO_DATA, tmp);
> +}
> +
>  static int ucb1400_gpio_probe(struct platform_device *dev)
>  {
>  	struct ucb1400_gpio *ucb = dev->dev.platform_data;
> @@ -66,6 +87,8 @@ static int ucb1400_gpio_probe(struct pla
>  	ucb->gc.direction_output = ucb1400_gpio_dir_out;
>  	ucb->gc.get = ucb1400_gpio_get;
>  	ucb->gc.set = ucb1400_gpio_set;
> +	ucb->gc.get_block = ucb1400_gpio_get_block;
> +	ucb->gc.set_block = ucb1400_gpio_set_block;
>  	ucb->gc.can_sleep = 1;
>  
>  	err = gpiochip_add(&ucb->gc);
> --- linux-2.6.orig/drivers/gpio/gpio-vt8500.c
> +++ linux-2.6/drivers/gpio/gpio-vt8500.c
> @@ -209,6 +209,28 @@ static void vt8500_gpio_set_value(struct
>  	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
>  }
>  
> +static unsigned long vt8500_gpio_get_block(struct gpio_chip *chip,
> +					   unsigned long mask)
> +{
> +	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
> +
> +	return readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) &
> +								mask;
> +}
> +
> +static void vt8500_gpio_set_block(struct gpio_chip *chip, unsigned long mask,
> +				  unsigned long  values)
> +{
> +	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
> +
> +	u32 val = readl_relaxed(vt8500_chip->base +
> +				vt8500_chip->regs->data_out);
> +	val &= ~mask;
> +	val |= values & mask;
> +
> +	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
> +}
> +
>  static int vt8500_of_xlate(struct gpio_chip *gc,
>  			    const struct of_phandle_args *gpiospec, u32 *flags)
>  {
> @@ -251,6 +273,8 @@ static int vt8500_add_chips(struct platf
>  		chip->direction_output = vt8500_gpio_direction_output;
>  		chip->get = vt8500_gpio_get_value;
>  		chip->set = vt8500_gpio_set_value;
> +		chip->get_block = vt8500_gpio_get_block;
> +		chip->set_block = vt8500_gpio_set_block;
>  		chip->can_sleep = 0;
>  		chip->base = pin_cnt;
>  		chip->ngpio = data->banks[i].ngpio;
> --- linux-2.6.orig/drivers/gpio/gpio-xilinx.c
> +++ linux-2.6/drivers/gpio/gpio-xilinx.c
> @@ -49,6 +49,21 @@ static int xgpio_get(struct gpio_chip *g
>  }
>  
>  /**
> + * xgpio_get_block - Read a block of specified signals of the GPIO device.
> + * @gc:     Pointer to gpio_chip device structure.
> + * @mask:   Bit mask (bit 0 == 0th GPIO) for GPIOs to get
> + *
> + * This function reads a block of specified signal of the GPIO device, returned
> + * as a bit mask, each bit representing a GPIO
> + */
> +static unsigned long xgpio_get_block(struct gpio_chip *gc, unsigned long mask)
> +{
> +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
> +
> +	return in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) & mask;
> +}
> +
> +/**
>   * xgpio_set - Write the specified signal of the GPIO device.
>   * @gc:     Pointer to gpio_chip device structure.
>   * @gpio:   GPIO signal number.
> @@ -77,6 +92,33 @@ static void xgpio_set(struct gpio_chip *
>  }
>  
>  /**
> + * xgpio_set_block - Write a block of specified signals of the GPIO device.
> + * @gc:     Pointer to gpio_chip device structure.
> + * @mask:   Bit mask (bit 0 == 0th GPIO) for GPIOs to set
> + * @values: Bit mapped values
> + *
> + * This function writes the specified values in to the specified signals of the
> + * GPIO device.
> + */
> +static void xgpio_set_block(struct gpio_chip *gc, unsigned long mask,
> +			    unsigned long values)
> +{
> +	unsigned long flags;
> +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
> +	struct xgpio_instance *chip =
> +	    container_of(mm_gc, struct xgpio_instance, mmchip);
> +
> +	spin_lock_irqsave(&chip->gpio_lock, flags);
> +
> +	chip->gpio_state &= ~mask;
> +	chip->gpio_state |= mask & values;
> +
> +	out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state);
> +
> +	spin_unlock_irqrestore(&chip->gpio_lock, flags);
> +}
> +
> +/**
>   * xgpio_dir_in - Set the direction of the specified GPIO signal as input.
>   * @gc:     Pointer to gpio_chip device structure.
>   * @gpio:   GPIO signal number.
> @@ -195,6 +237,8 @@ static int __devinit xgpio_of_probe(stru
>  	chip->mmchip.gc.direction_output = xgpio_dir_out;
>  	chip->mmchip.gc.get = xgpio_get;
>  	chip->mmchip.gc.set = xgpio_set;
> +	chip->mmchip.gc.get_block = xgpio_get_block;
> +	chip->mmchip.gc.set_block = xgpio_set_block;
>  
>  	chip->mmchip.save_regs = xgpio_save_regs;
>  
> --- linux-2.6.orig/drivers/pinctrl/pinctrl-nomadik.c
> +++ linux-2.6/drivers/pinctrl/pinctrl-nomadik.c
> @@ -1036,6 +1036,40 @@ static void nmk_gpio_set_output(struct g
>  	clk_disable(nmk_chip->clk);
>  }
>  
> +static unsigned long nmk_gpio_get_block(struct gpio_chip *chip,
> +					unsigned long mask)
> +{
> +	struct nmk_gpio_chip *nmk_chip =
> +		container_of(chip, struct nmk_gpio_chip, chip);
> +	unsigned long values;
> +
> +	clk_enable(nmk_chip->clk);
> +
> +	values = readl(nmk_chip->addr + NMK_GPIO_DAT);
> +
> +	clk_disable(nmk_chip->clk);
> +
> +	return values & mask;
> +}
> +
> +static void nmk_gpio_set_block(struct gpio_chip *chip, unsigned long mask,
> +			       unsigned long values)
> +{
> +	struct nmk_gpio_chip *nmk_chip =
> +		container_of(chip, struct nmk_gpio_chip, chip);
> +	unsigned long set_bits = values & mask;
> +	unsigned long clr_bits = ~values & mask;
> +
> +	clk_enable(nmk_chip->clk);
> +
> +	if (set_bits)
> +		writel(set_bits, nmk_chip->addr + NMK_GPIO_DATS);
> +	if (clr_bits)
> +		writel(clr_bits, nmk_chip->addr + NMK_GPIO_DATC);
> +
> +	clk_disable(nmk_chip->clk);
> +}
> +
>  static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
>  				int val)
>  {
> @@ -1147,8 +1181,10 @@ static struct gpio_chip nmk_gpio_templat
>  	.free			= nmk_gpio_free,
>  	.direction_input	= nmk_gpio_make_input,
>  	.get			= nmk_gpio_get_input,
> +	.get_block		= nmk_gpio_get_block,
>  	.direction_output	= nmk_gpio_make_output,
>  	.set			= nmk_gpio_set_output,
> +	.set_block		= nmk_gpio_set_block,
>  	.to_irq			= nmk_gpio_to_irq,
>  	.dbg_show		= nmk_gpio_dbg_show,
>  	.can_sleep		= 0,
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ