Commit 98325f8f authored by Ben Dooks's avatar Ben Dooks Committed by Samuel Ortiz

mfd: Ensure sm501 GPIO pin mode is GPIO when configured

When setting an GPIO to either input or output, we
should ensure that the pin configuration elsewhere
in the chip is set to GPIO in-case the initial
setup has not been done correctly.
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarSamuel Ortiz <sameo@openedhand.com>
parent d1fdb4f6
...@@ -41,6 +41,7 @@ struct sm501_gpio_chip { ...@@ -41,6 +41,7 @@ struct sm501_gpio_chip {
struct gpio_chip gpio; struct gpio_chip gpio;
struct sm501_gpio *ourgpio; /* to get back to parent. */ struct sm501_gpio *ourgpio; /* to get back to parent. */
void __iomem *regbase; void __iomem *regbase;
void __iomem *control; /* address of control reg. */
}; };
struct sm501_gpio { struct sm501_gpio {
...@@ -908,6 +909,25 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset) ...@@ -908,6 +909,25 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
return result & 1UL; return result & 1UL;
} }
static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
unsigned long bit)
{
unsigned long ctrl;
/* check and modify if this pin is not set as gpio. */
if (readl(smchip->control) & bit) {
dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
"changing mode of gpio, bit %08lx\n", bit);
ctrl = readl(smchip->control);
ctrl &= ~bit;
writel(ctrl, smchip->control);
sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
}
}
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ {
...@@ -929,6 +949,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -929,6 +949,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
writel(val, regs); writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio)); sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
spin_unlock_irqrestore(&smgpio->lock, save); spin_unlock_irqrestore(&smgpio->lock, save);
} }
...@@ -941,8 +963,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) ...@@ -941,8 +963,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
unsigned long save; unsigned long save;
unsigned long ddr; unsigned long ddr;
dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n", dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
__func__, chip, offset); __func__, chip, offset);
spin_lock_irqsave(&smgpio->lock, save); spin_lock_irqsave(&smgpio->lock, save);
...@@ -950,6 +972,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) ...@@ -950,6 +972,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW); writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio)); sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
spin_unlock_irqrestore(&smgpio->lock, save); spin_unlock_irqrestore(&smgpio->lock, save);
return 0; return 0;
...@@ -1012,9 +1036,11 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm, ...@@ -1012,9 +1036,11 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
if (base > 0) if (base > 0)
base += 32; base += 32;
chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH; chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
chip->control = sm->regs + SM501_GPIO63_32_CONTROL;
gchip->label = "SM501-HIGH"; gchip->label = "SM501-HIGH";
} else { } else {
chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW; chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
chip->control = sm->regs + SM501_GPIO31_0_CONTROL;
gchip->label = "SM501-LOW"; gchip->label = "SM501-LOW";
} }
......
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