ar71xx: build ALFA AP96 images with default profile as well
[openwrt/openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / gpio.c
index c1990ad453a64ce2b180914aee1f2b11f55dd4e4..91c838345d2ae05a7965d05b121795d3fa364a52 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  Atheros AR71xx SoC GPIO API support
+ *  Atheros AR7XXX/AR9XXX SoC GPIO API support
  *
- *  Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -27,22 +27,18 @@ EXPORT_SYMBOL(ar71xx_gpio_count);
 
 void __ar71xx_gpio_set_value(unsigned gpio, int value)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&ar71xx_gpio_lock, flags);
+       void __iomem *base = ar71xx_gpio_base;
 
        if (value)
-               ar71xx_gpio_wr(GPIO_REG_SET, (1 << gpio));
+               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
        else
-               ar71xx_gpio_wr(GPIO_REG_CLEAR, (1 << gpio));
-
-       spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
+               __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
 }
 EXPORT_SYMBOL(__ar71xx_gpio_set_value);
 
 int __ar71xx_gpio_get_value(unsigned gpio)
 {
-       return (ar71xx_gpio_rr(GPIO_REG_IN) & (1 << gpio)) ? 1 : 0;
+       return (__raw_readl(ar71xx_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
 }
 EXPORT_SYMBOL(__ar71xx_gpio_get_value);
 
@@ -60,12 +56,13 @@ static void ar71xx_gpio_set_value(struct gpio_chip *chip,
 static int ar71xx_gpio_direction_input(struct gpio_chip *chip,
                                       unsigned offset)
 {
+       void __iomem *base = ar71xx_gpio_base;
        unsigned long flags;
 
        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
 
-       ar71xx_gpio_wr(GPIO_REG_OE,
-                       ar71xx_gpio_rr(GPIO_REG_OE) & ~(1 << offset));
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
 
        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
 
@@ -75,17 +72,55 @@ static int ar71xx_gpio_direction_input(struct gpio_chip *chip,
 static int ar71xx_gpio_direction_output(struct gpio_chip *chip,
                                        unsigned offset, int value)
 {
+       void __iomem *base = ar71xx_gpio_base;
        unsigned long flags;
 
        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
 
        if (value)
-               ar71xx_gpio_wr(GPIO_REG_SET, (1 << offset));
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
        else
-               ar71xx_gpio_wr(GPIO_REG_CLEAR, (1 << offset));
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
+
+       return 0;
+}
 
-       ar71xx_gpio_wr(GPIO_REG_OE,
-                       ar71xx_gpio_rr(GPIO_REG_OE) | (1 << offset));
+static int ar934x_gpio_direction_input(struct gpio_chip *chip,
+                                      unsigned offset)
+{
+       void __iomem *base = ar71xx_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ar71xx_gpio_lock, flags);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
+
+       spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
+
+       return 0;
+}
+
+static int ar934x_gpio_direction_output(struct gpio_chip *chip,
+                                       unsigned offset, int value)
+{
+       void __iomem *base = ar71xx_gpio_base;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ar71xx_gpio_lock, flags);
+
+       if (value)
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+       else
+               __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+       __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+                    base + AR71XX_GPIO_REG_OE);
 
        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
 
@@ -104,22 +139,101 @@ static struct gpio_chip ar71xx_gpio_chip = {
 
 void ar71xx_gpio_function_enable(u32 mask)
 {
+       void __iomem *base = ar71xx_gpio_base;
        unsigned long flags;
+       unsigned int reg;
+
+       if (ar71xx_soc == AR71XX_SOC_AR9341 ||
+           ar71xx_soc == AR71XX_SOC_AR9342 ||
+           ar71xx_soc == AR71XX_SOC_AR9344) {
+               reg = AR934X_GPIO_REG_FUNC;
+       } else {
+               reg = AR71XX_GPIO_REG_FUNC;
+       }
 
        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
 
-       ar71xx_gpio_wr(GPIO_REG_FUNC, ar71xx_gpio_rr(GPIO_REG_FUNC) | mask);
+       __raw_writel(__raw_readl(base + reg) | mask, base + reg);
+       /* flush write */
+       (void) __raw_readl(base + reg);
 
        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
 }
 
 void ar71xx_gpio_function_disable(u32 mask)
 {
+       void __iomem *base = ar71xx_gpio_base;
        unsigned long flags;
+       unsigned int reg;
+
+       if (ar71xx_soc == AR71XX_SOC_AR9341 ||
+           ar71xx_soc == AR71XX_SOC_AR9342 ||
+           ar71xx_soc == AR71XX_SOC_AR9344) {
+               reg = AR934X_GPIO_REG_FUNC;
+       } else {
+               reg = AR71XX_GPIO_REG_FUNC;
+       }
 
        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
 
-       ar71xx_gpio_wr(GPIO_REG_FUNC, ar71xx_gpio_rr(GPIO_REG_FUNC) & ~mask);
+       __raw_writel(__raw_readl(base + reg) & ~mask, base + reg);
+       /* flush write */
+       (void) __raw_readl(base + reg);
+
+       spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
+}
+
+void ar71xx_gpio_function_setup(u32 set, u32 clear)
+{
+       void __iomem *base = ar71xx_gpio_base;
+       unsigned long flags;
+       unsigned int reg;
+
+       if (ar71xx_soc == AR71XX_SOC_AR9341 ||
+           ar71xx_soc == AR71XX_SOC_AR9342 ||
+           ar71xx_soc == AR71XX_SOC_AR9344) {
+               reg = AR934X_GPIO_REG_FUNC;
+       } else {
+               reg = AR71XX_GPIO_REG_FUNC;
+       }
+
+       spin_lock_irqsave(&ar71xx_gpio_lock, flags);
+
+       __raw_writel((__raw_readl(base + reg) & ~clear) | set, base + reg);
+       /* flush write */
+       (void) __raw_readl(base + reg);
+
+       spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
+}
+EXPORT_SYMBOL(ar71xx_gpio_function_setup);
+
+void __init ar71xx_gpio_output_select(unsigned gpio, u8 val)
+{
+       void __iomem *base = ar71xx_gpio_base;
+       unsigned long flags;
+       unsigned int reg;
+       u32 t, s;
+
+       if (ar71xx_soc != AR71XX_SOC_AR9341 &&
+           ar71xx_soc != AR71XX_SOC_AR9342 &&
+           ar71xx_soc != AR71XX_SOC_AR9344)
+               return;
+
+       if (gpio >= AR934X_GPIO_COUNT)
+               return;
+
+       reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4);
+       s = 8 * (gpio % 4);
+
+       spin_lock_irqsave(&ar71xx_gpio_lock, flags);
+
+       t = __raw_readl(base + reg);
+       t &= ~(0xff << s);
+       t |= val << s;
+       __raw_writel(t, base + reg);
+
+       /* flush write */
+       (void) __raw_readl(base + reg);
 
        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
 }
@@ -140,7 +254,12 @@ void __init ar71xx_gpio_init(void)
                break;
 
        case AR71XX_SOC_AR7240:
-               ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT;
+               ar71xx_gpio_chip.ngpio = AR7240_GPIO_COUNT;
+               break;
+
+       case AR71XX_SOC_AR7241:
+       case AR71XX_SOC_AR7242:
+               ar71xx_gpio_chip.ngpio = AR7241_GPIO_COUNT;
                break;
 
        case AR71XX_SOC_AR9130:
@@ -148,6 +267,19 @@ void __init ar71xx_gpio_init(void)
                ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT;
                break;
 
+       case AR71XX_SOC_AR9330:
+       case AR71XX_SOC_AR9331:
+               ar71xx_gpio_chip.ngpio = AR933X_GPIO_COUNT;
+               break;
+
+       case AR71XX_SOC_AR9341:
+       case AR71XX_SOC_AR9342:
+       case AR71XX_SOC_AR9344:
+               ar71xx_gpio_chip.ngpio = AR934X_GPIO_COUNT;
+               ar71xx_gpio_chip.direction_input = ar934x_gpio_direction_input;
+               ar71xx_gpio_chip.direction_output = ar934x_gpio_direction_output;
+               break;
+
        default:
                BUG();
        }
@@ -156,3 +288,15 @@ void __init ar71xx_gpio_init(void)
        if (err)
                panic("cannot add AR71xx GPIO chip, error=%d", err);
 }
+
+int gpio_to_irq(unsigned gpio)
+{
+       return AR71XX_GPIO_IRQ(gpio);
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned irq)
+{
+       return irq - AR71XX_GPIO_IRQ_BASE;
+}
+EXPORT_SYMBOL(irq_to_gpio);