ar71xx: enable GPIO support for the AR934x SoCs
[openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / gpio.c
1 /*
2  *  Atheros AR71xx SoC GPIO API support
3  *
4  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify it
8  *  under the terms of the GNU General Public License version 2 as published
9  *  by the Free Software Foundation.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/spinlock.h>
17 #include <linux/io.h>
18 #include <linux/ioport.h>
19 #include <linux/gpio.h>
20
21 #include <asm/mach-ar71xx/ar71xx.h>
22
23 static DEFINE_SPINLOCK(ar71xx_gpio_lock);
24
25 unsigned long ar71xx_gpio_count;
26 EXPORT_SYMBOL(ar71xx_gpio_count);
27
28 void __ar71xx_gpio_set_value(unsigned gpio, int value)
29 {
30         void __iomem *base = ar71xx_gpio_base;
31
32         if (value)
33                 __raw_writel(1 << gpio, base + GPIO_REG_SET);
34         else
35                 __raw_writel(1 << gpio, base + GPIO_REG_CLEAR);
36 }
37 EXPORT_SYMBOL(__ar71xx_gpio_set_value);
38
39 int __ar71xx_gpio_get_value(unsigned gpio)
40 {
41         return (__raw_readl(ar71xx_gpio_base + GPIO_REG_IN) >> gpio) & 1;
42 }
43 EXPORT_SYMBOL(__ar71xx_gpio_get_value);
44
45 static int ar71xx_gpio_get_value(struct gpio_chip *chip, unsigned offset)
46 {
47         return __ar71xx_gpio_get_value(offset);
48 }
49
50 static void ar71xx_gpio_set_value(struct gpio_chip *chip,
51                                   unsigned offset, int value)
52 {
53         __ar71xx_gpio_set_value(offset, value);
54 }
55
56 static int ar71xx_gpio_direction_input(struct gpio_chip *chip,
57                                        unsigned offset)
58 {
59         void __iomem *base = ar71xx_gpio_base;
60         unsigned long flags;
61
62         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
63
64         __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(1 << offset),
65                      base + GPIO_REG_OE);
66
67         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
68
69         return 0;
70 }
71
72 static int ar71xx_gpio_direction_output(struct gpio_chip *chip,
73                                         unsigned offset, int value)
74 {
75         void __iomem *base = ar71xx_gpio_base;
76         unsigned long flags;
77
78         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
79
80         if (value)
81                 __raw_writel(1 << offset, base + GPIO_REG_SET);
82         else
83                 __raw_writel(1 << offset, base + GPIO_REG_CLEAR);
84
85         __raw_writel(__raw_readl(base + GPIO_REG_OE) | (1 << offset),
86                      base + GPIO_REG_OE);
87
88         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
89
90         return 0;
91 }
92
93 static struct gpio_chip ar71xx_gpio_chip = {
94         .label                  = "ar71xx",
95         .get                    = ar71xx_gpio_get_value,
96         .set                    = ar71xx_gpio_set_value,
97         .direction_input        = ar71xx_gpio_direction_input,
98         .direction_output       = ar71xx_gpio_direction_output,
99         .base                   = 0,
100         .ngpio                  = AR71XX_GPIO_COUNT,
101 };
102
103 void ar71xx_gpio_function_enable(u32 mask)
104 {
105         void __iomem *base = ar71xx_gpio_base;
106         unsigned long flags;
107
108         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
109
110         __raw_writel(__raw_readl(base + GPIO_REG_FUNC) | mask,
111                      base + GPIO_REG_FUNC);
112         /* flush write */
113         (void) __raw_readl(base + GPIO_REG_FUNC);
114
115         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
116 }
117
118 void ar71xx_gpio_function_disable(u32 mask)
119 {
120         void __iomem *base = ar71xx_gpio_base;
121         unsigned long flags;
122
123         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
124
125         __raw_writel(__raw_readl(base + GPIO_REG_FUNC) & ~mask,
126                      base + GPIO_REG_FUNC);
127         /* flush write */
128         (void) __raw_readl(base + GPIO_REG_FUNC);
129
130         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
131 }
132
133 void ar71xx_gpio_function_setup(u32 set, u32 clear)
134 {
135         void __iomem *base = ar71xx_gpio_base;
136         unsigned long flags;
137
138         spin_lock_irqsave(&ar71xx_gpio_lock, flags);
139
140         __raw_writel((__raw_readl(base + GPIO_REG_FUNC) & ~clear) | set,
141                      base + GPIO_REG_FUNC);
142         /* flush write */
143         (void) __raw_readl(base + GPIO_REG_FUNC);
144
145         spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
146 }
147 EXPORT_SYMBOL(ar71xx_gpio_function_setup);
148
149 void __init ar71xx_gpio_init(void)
150 {
151         int err;
152
153         if (!request_mem_region(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
154                                 "AR71xx GPIO controller"))
155                 panic("cannot allocate AR71xx GPIO registers page");
156
157         switch (ar71xx_soc) {
158         case AR71XX_SOC_AR7130:
159         case AR71XX_SOC_AR7141:
160         case AR71XX_SOC_AR7161:
161                 ar71xx_gpio_chip.ngpio = AR71XX_GPIO_COUNT;
162                 break;
163
164         case AR71XX_SOC_AR7240:
165         case AR71XX_SOC_AR7241:
166         case AR71XX_SOC_AR7242:
167                 ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT;
168                 break;
169
170         case AR71XX_SOC_AR9130:
171         case AR71XX_SOC_AR9132:
172                 ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT;
173                 break;
174
175         case AR71XX_SOC_AR9341:
176         case AR71XX_SOC_AR9342:
177         case AR71XX_SOC_AR9344:
178                 ar71xx_gpio_chip.ngpio = AR934X_GPIO_COUNT;
179                 break;
180
181         default:
182                 BUG();
183         }
184
185         err = gpiochip_add(&ar71xx_gpio_chip);
186         if (err)
187                 panic("cannot add AR71xx GPIO chip, error=%d", err);
188 }