[PATCH 1/1] drivers/gpio: Altera soft IP GPIO driver
Linus Walleij
linus.walleij at linaro.org
Mon Jun 17 19:12:06 EST 2013
On Mon, Jun 17, 2013 at 9:29 AM, Loh Tien Hock <thloh at altera.com> wrote:
> On Mon, Jun 17, 2013 at 2:38 PM, Linus Walleij <linus.walleij at linaro.org> wrote:
>> On Thu, Jun 6, 2013 at 10:05 AM, <thloh at altera.com> wrote:
>>> +static void altera_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
>>> +{
>>> + struct altera_gpio_chip *altera_gc = irq_desc_get_handler_data(desc);
>>> + struct irq_chip *chip = irq_desc_get_chip(desc);
>>> + struct of_mm_gpio_chip *mm_gc = &altera_gc->mmchip;
>>> + unsigned long status;
>>> +
>>> + int base;
>>> + chip->irq_mask(&desc->irq_data);
>>> +
>>> + if (altera_gc->level_trigger) {
>>> + status = __raw_readl(mm_gc->regs + ALTERA_GPIO_DATA);
>>> + status &= __raw_readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
>>> +
>>> + for (base = 0; base < mm_gc->gc.ngpio; base++) {
>>> + if ((1 << base) & status) {
>>> + generic_handle_irq(irq_linear_revmap(
>>> + altera_gc->irq, base));
>>> + }
>>> + }
>>> + } else {
>>> + while ((status =
>>> + (__raw_readl(mm_gc->regs + ALTERA_GPIO_EDGE_CAP) &
>>> + __raw_readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) {
>>> + __raw_writel(status,
>>> + mm_gc->regs + ALTERA_GPIO_EDGE_CAP);
>>> + for (base = 0; base < mm_gc->gc.ngpio; base++) {
>>> + if ((1 << base) & status) {
>>> + generic_handle_irq(irq_linear_revmap(
>>> + altera_gc->irq, base));
>>> + }
>>> + }
>>> + }
>>> + }
>>> +
>>> + chip->irq_eoi(irq_desc_get_irq_data(desc));
>>> + chip->irq_unmask(&desc->irq_data);
>>> +}
>>
>> Why is the above code using __raw_* accessors?
>>
>> Atleast use readl_relaxed() instead of __raw.
>
> Noted.
>
> A question regarding readl_relaxed(), is that because the endianess
> swapping? If that's the case, should codes in other functions use
> readl_relaxed()/writel_relaxed() as well?
Basically I think of it like this:
__raw_* = will just poke the registers without really taking anything
into account, in native endianness.
readl/writel_relaxed() = same thing but always little-endian.
readl()/write() = always little-endian, and will go to lengths to also
drain buffers etc so the write hits the target registers after the PC
passed this instruction. To the extent possible, and may cause a
performance problem due to all buffer draining.
Yours,
Linus Walleij
More information about the devicetree-discuss
mailing list