lkml.org 
[lkml]   [2012]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6/6 v8] gpio: Add block gpio to several gpio drivers
    Date
    This patch adds block GPIO support to several gpio drivers.

    Signed-off-by: Roland Stigge <stigge@antcom.de>

    ---
    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-pca953x.c | 64 ++++++++++++++++++++++++++++++++++
    drivers/gpio/gpio-pcf857x.c | 24 ++++++++++++
    drivers/gpio/gpio-pch.c | 27 ++++++++++++++
    drivers/gpio/gpio-pl061.c | 17 +++++++++
    drivers/gpio/gpio-twl6040.c | 32 +++++++++++++++++
    drivers/gpio/gpio-ucb1400.c | 23 ++++++++++++
    drivers/gpio/gpio-vt8500.c | 24 ++++++++++++
    drivers/gpio/gpio-xilinx.c | 44 +++++++++++++++++++++++
    13 files changed, 536 insertions(+)

    --- 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-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-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;


    \
     
     \ /
      Last update: 2012-11-30 19:41    [W:2.771 / U:1.108 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site