Message ID | 1355952138-20459-7-git-send-email-stigge@antcom.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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@antcom.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, ®_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,
On 12/20/2012 08:08 AM, Jean-Christophe PLAGNIOL-VILLARD wrote: > 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@antcom.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 I suggest to drop the hunk for the AT91 for the moment and wait until the block gpio interface is accepted. Then we can add the block gpio enhancement to the GPIO drivers in arch/... not only for the AT91... also because they have to go through different sub-systems maintainers. Wolfgang.
On 12/20/2012 09:07 AM, Wolfgang Grandegger wrote: > On 12/20/2012 08:08 AM, Jean-Christophe PLAGNIOL-VILLARD wrote: >> 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@antcom.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 > > I suggest to drop the hunk for the AT91 for the moment and wait until > the block gpio interface is accepted. Then we can add the block gpio > enhancement to the GPIO drivers in arch/... not only for the AT91... > also because they have to go through different sub-systems maintainers. OK, thank you two! Will remove the at91 patch from the current series. Block GPIO support for at91 can be added later. I just noticed that the patch set needs another patch not yet in mainline, but in linux-next, linux-gpio and gpio/next. I'm providing a branch to easily pull from for testing, building on v3.7: git://git.antcom.de/linux-2.6.git blockgpio Feedback welcome - thanks! Roland
--- 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, ®_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,
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@antcom.de> --- arch/arm/mach-at91/gpio.c | 33 +++++++++++++++ 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(+)