Commit | Line | Data |
---|---|---|
51e02b02 ML |
1 | /* |
2 | * Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org> | |
ce1d43b9 | 3 | * GPIOLIB support for Alchemy chips. |
51e02b02 ML |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. | |
9 | * | |
10 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
11 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
12 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | |
13 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
14 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
15 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
16 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
17 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
19 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License along | |
22 | * with this program; if not, write to the Free Software Foundation, Inc., | |
23 | * 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | * | |
25 | * Notes : | |
ce1d43b9 ML |
26 | * This file must ONLY be built when CONFIG_GPIOLIB=y and |
27 | * CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail! | |
28 | * au1000 SoC have only one GPIO block : GPIO1 | |
29 | * Au1100, Au15x0, Au12x0 have a second one : GPIO2 | |
809f36c6 | 30 | * Au1300 is totally different: 1 block with up to 128 GPIOs |
51e02b02 ML |
31 | */ |
32 | ||
ce1d43b9 | 33 | #include <linux/init.h> |
51e02b02 ML |
34 | #include <linux/kernel.h> |
35 | #include <linux/module.h> | |
36 | #include <linux/types.h> | |
51e02b02 | 37 | #include <linux/gpio.h> |
ce1d43b9 | 38 | #include <asm/mach-au1x00/gpio-au1000.h> |
809f36c6 | 39 | #include <asm/mach-au1x00/gpio-au1300.h> |
51e02b02 | 40 | |
51e02b02 ML |
41 | static int gpio2_get(struct gpio_chip *chip, unsigned offset) |
42 | { | |
43 | return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE); | |
44 | } | |
45 | ||
46 | static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value) | |
47 | { | |
48 | alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value); | |
49 | } | |
50 | ||
51 | static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset) | |
52 | { | |
53 | return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE); | |
54 | } | |
55 | ||
56 | static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset, | |
57 | int value) | |
58 | { | |
59 | return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE, | |
60 | value); | |
61 | } | |
62 | ||
63 | static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset) | |
64 | { | |
65 | return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE); | |
66 | } | |
70f82f2c | 67 | |
51e02b02 ML |
68 | |
69 | static int gpio1_get(struct gpio_chip *chip, unsigned offset) | |
70 | { | |
71 | return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE); | |
72 | } | |
73 | ||
74 | static void gpio1_set(struct gpio_chip *chip, | |
75 | unsigned offset, int value) | |
76 | { | |
77 | alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value); | |
78 | } | |
79 | ||
80 | static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset) | |
81 | { | |
82 | return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE); | |
83 | } | |
84 | ||
85 | static int gpio1_direction_output(struct gpio_chip *chip, | |
86 | unsigned offset, int value) | |
87 | { | |
88 | return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE, | |
89 | value); | |
90 | } | |
91 | ||
92 | static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset) | |
93 | { | |
94 | return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE); | |
95 | } | |
96 | ||
97 | struct gpio_chip alchemy_gpio_chip[] = { | |
98 | [0] = { | |
99 | .label = "alchemy-gpio1", | |
100 | .direction_input = gpio1_direction_input, | |
101 | .direction_output = gpio1_direction_output, | |
102 | .get = gpio1_get, | |
103 | .set = gpio1_set, | |
104 | .to_irq = gpio1_to_irq, | |
105 | .base = ALCHEMY_GPIO1_BASE, | |
106 | .ngpio = ALCHEMY_GPIO1_NUM, | |
107 | }, | |
51e02b02 ML |
108 | [1] = { |
109 | .label = "alchemy-gpio2", | |
110 | .direction_input = gpio2_direction_input, | |
111 | .direction_output = gpio2_direction_output, | |
112 | .get = gpio2_get, | |
113 | .set = gpio2_set, | |
114 | .to_irq = gpio2_to_irq, | |
115 | .base = ALCHEMY_GPIO2_BASE, | |
116 | .ngpio = ALCHEMY_GPIO2_NUM, | |
117 | }, | |
51e02b02 ML |
118 | }; |
119 | ||
809f36c6 ML |
120 | static int alchemy_gpic_get(struct gpio_chip *chip, unsigned int off) |
121 | { | |
122 | return au1300_gpio_get_value(off + AU1300_GPIO_BASE); | |
123 | } | |
124 | ||
125 | static void alchemy_gpic_set(struct gpio_chip *chip, unsigned int off, int v) | |
126 | { | |
127 | au1300_gpio_set_value(off + AU1300_GPIO_BASE, v); | |
128 | } | |
129 | ||
130 | static int alchemy_gpic_dir_input(struct gpio_chip *chip, unsigned int off) | |
131 | { | |
132 | return au1300_gpio_direction_input(off + AU1300_GPIO_BASE); | |
133 | } | |
134 | ||
135 | static int alchemy_gpic_dir_output(struct gpio_chip *chip, unsigned int off, | |
136 | int v) | |
137 | { | |
138 | return au1300_gpio_direction_output(off + AU1300_GPIO_BASE, v); | |
139 | } | |
140 | ||
141 | static int alchemy_gpic_gpio_to_irq(struct gpio_chip *chip, unsigned int off) | |
142 | { | |
143 | return au1300_gpio_to_irq(off + AU1300_GPIO_BASE); | |
144 | } | |
145 | ||
146 | static struct gpio_chip au1300_gpiochip = { | |
147 | .label = "alchemy-gpic", | |
148 | .direction_input = alchemy_gpic_dir_input, | |
149 | .direction_output = alchemy_gpic_dir_output, | |
150 | .get = alchemy_gpic_get, | |
151 | .set = alchemy_gpic_set, | |
152 | .to_irq = alchemy_gpic_gpio_to_irq, | |
153 | .base = AU1300_GPIO_BASE, | |
154 | .ngpio = AU1300_GPIO_NUM, | |
155 | }; | |
156 | ||
ce1d43b9 | 157 | static int __init alchemy_gpiochip_init(void) |
51e02b02 | 158 | { |
ce1d43b9 ML |
159 | int ret = 0; |
160 | ||
161 | switch (alchemy_get_cputype()) { | |
162 | case ALCHEMY_CPU_AU1000: | |
163 | ret = gpiochip_add(&alchemy_gpio_chip[0]); | |
164 | break; | |
165 | case ALCHEMY_CPU_AU1500...ALCHEMY_CPU_AU1200: | |
166 | ret = gpiochip_add(&alchemy_gpio_chip[0]); | |
167 | ret |= gpiochip_add(&alchemy_gpio_chip[1]); | |
168 | break; | |
809f36c6 ML |
169 | case ALCHEMY_CPU_AU1300: |
170 | ret = gpiochip_add(&au1300_gpiochip); | |
171 | break; | |
ce1d43b9 ML |
172 | } |
173 | return ret; | |
51e02b02 | 174 | } |
ce1d43b9 | 175 | arch_initcall(alchemy_gpiochip_init); |