Commit ed442b67 authored by Russell King's avatar Russell King

MFD: ucb1x00-core: add missing ucb1x00_enable()/ucb1x00_disable()

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: default avatarJochen Friedrich <jochen@scram.de>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 65b539bb
...@@ -116,14 +116,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -116,14 +116,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
else else
ucb->io_out &= ~(1 << offset); ucb->io_out &= ~(1 << offset);
ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags); spin_unlock_irqrestore(&ucb->io_lock, flags);
} }
static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
{ {
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio); 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) static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
...@@ -133,7 +141,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -133,7 +141,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&ucb->io_lock, flags); spin_lock_irqsave(&ucb->io_lock, flags);
ucb->io_dir &= ~(1 << offset); ucb->io_dir &= ~(1 << offset);
ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags); spin_unlock_irqrestore(&ucb->io_lock, flags);
return 0; return 0;
...@@ -153,6 +163,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset ...@@ -153,6 +163,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
else else
ucb->io_out &= ~mask; ucb->io_out &= ~mask;
ucb1x00_enable(ucb);
if (old != ucb->io_out) if (old != ucb->io_out)
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
...@@ -160,6 +171,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset ...@@ -160,6 +171,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
ucb->io_dir |= mask; ucb->io_dir |= mask;
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
} }
ucb1x00_disable(ucb);
spin_unlock_irqrestore(&ucb->io_lock, flags); spin_unlock_irqrestore(&ucb->io_lock, flags);
return 0; return 0;
...@@ -703,8 +715,10 @@ static int ucb1x00_resume(struct mcp *mcp) ...@@ -703,8 +715,10 @@ static int ucb1x00_resume(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp); struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev; struct ucb1x00_dev *dev;
ucb1x00_enable(ucb);
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir); ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
ucb1x00_disable(ucb);
mutex_lock(&ucb1x00_mutex); mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) { list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->resume) if (dev->drv->resume)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment