[PATCH v3 11/13] gpio/omap: fix dataout register overwrite in _set_gpio_dataout_*

DebBarma, Tarun Kanti tarun.kanti at ti.com
Tue Mar 13 02:52:28 EDT 2012


On Tue, Mar 13, 2012 at 12:03 PM, DebBarma, Tarun Kanti
<tarun.kanti at ti.com> wrote:
> On Tue, Mar 13, 2012 at 11:33 AM, DebBarma, Tarun Kanti
> <tarun.kanti at ti.com> wrote:
>> On Tue, Mar 13, 2012 at 3:24 AM, Kevin Hilman <khilman at ti.com> wrote:
>>> Tarun Kanti DebBarma <tarun.kanti at ti.com> writes:
>>>
>>>> In the existing _set_gpio_dataout_*() implementation, the dataout
>>>> register is overwritten every time the function is called. This is
>>>> not intended behavior because that would end up one user of a GPIO
>>>> line overwriting what is written by another. Fix this so that previous
>>>> value is always preserved until explicitly changed by respective
>>>> user/driver of the GPIO line.
>>>>
>>>> Signed-off-by: Tarun Kanti DebBarma <tarun.kanti at ti.com>
>>>> ---
>>>>  drivers/gpio/gpio-omap.c |    3 +++
>>>>  1 files changed, 3 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
>>>> index 04c2677..2e8e476 100644
>>>> --- a/drivers/gpio/gpio-omap.c
>>>> +++ b/drivers/gpio/gpio-omap.c
>>>> @@ -114,6 +114,7 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
>>>>       else
>>>>               reg += bank->regs->clr_dataout;
>>>>
>>>> +     l |= __raw_readl(bank->base + bank->regs->set_dataout);
>>>
>>> minor: IMO, it's more reader-friendly if this looks like
>>>
>>>       l = __raw_read(...)
>>>       l |= GPIO_BIT(...)
>>>       __raw_write(...)
>> Agreed. I will make the change.
> Also, the read should be: __raw_readl(bank->base + bank->regs->dataout);
> instead of bank->regs->set_dataout.
I see a problem with this implementation. It is not correct to write l
|= GPIO_BIT(...).
For example if we write to clr_dataout register we would end up
clearing bits which
we are not supposed to. We should just be operating on current GPIO_BIT(...).
The l |= GPIO_BIT(...) is needed just to make sure that we have the
right context
stored. So the overall sequence should be something like this:

        void __iomem *reg = bank->base;
        u32 l = GPIO_BIT(bank, gpio);

        if (enable)
                reg += bank->regs->set_dataout;
        else
                reg += bank->regs->clr_dataout;

        __raw_writel(l, reg);
        l |= __raw_readl(bank->base + bank->regs->dataout);
        bank->context.dataout = l;
--
Tarun
>>
>>>
>>>>       __raw_writel(l, reg);
>>>>       bank->context.dataout = l;
>>>>  }
>>>> @@ -130,6 +131,8 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
>>>>               l |= gpio_bit;
>>>>       else
>>>>               l &= ~gpio_bit;
>>>> +
>>>> +     l |= __raw_readl(bank->base + bank->regs->set_dataout);
>>>
>>> There's already a __raw_read() in this function just above.
>> Right. Thanks.
>> --
>> Tarun
>>>
>>>>       __raw_writel(l, reg);
>>>>       bank->context.dataout = l;
>>>>  }



More information about the linux-arm-kernel mailing list