Skip to content

Commit

Permalink
MFD: ucb1x00-core: add missing ucb1x00_enable()/ucb1x00_disable()
Browse files Browse the repository at this point in the history
ucb1x00_enable() and ucb1x00_disable() are used for power saving on the
SIB interface, allowing the host supplied clock to be disabled when not
required.  We require drivers which access the ucb1x00 to ensure that
they have enabled the clock prior to accessing the device, and they
should disable it once they're done.

As we don't expect gpiolib users to be aware of this detail, we must
make these calls in the gpiolib interfaces.  Add them.

Also add them to the resume method, which needs to re-establish the
GPIO pin settings.

Acked-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Russell King committed Feb 18, 2012
1 parent 65b539b commit ed442b6
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion drivers/mfd/ucb1x00-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
else
ucb->io_out &= ~(1 << offset);

ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags);
}

static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
unsigned val;

ucb1x00_enable(ucb);
val = ucb1x00_reg_read(ucb, UCB_IO_DATA);
ucb1x00_disable(ucb);

return val & (1 << offset);
}

static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
Expand All @@ -133,7 +141,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)

spin_lock_irqsave(&ucb->io_lock, flags);
ucb->io_dir &= ~(1 << offset);
ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags);

return 0;
Expand All @@ -153,13 +163,15 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
else
ucb->io_out &= ~mask;

ucb1x00_enable(ucb);
if (old != ucb->io_out)
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);

if (!(ucb->io_dir & mask)) {
ucb->io_dir |= mask;
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
}
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags);

return 0;
Expand Down Expand Up @@ -703,8 +715,10 @@ static int ucb1x00_resume(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;

ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
ucb1x00_disable(ucb);
mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->resume)
Expand Down

0 comments on commit ed442b6

Please sign in to comment.