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 | * au1000 SoC have only one GPIO block : GPIO1 |
27 | * Au1100, Au15x0, Au12x0 have a second one : GPIO2 | |
809f36c6 | 28 | * Au1300 is totally different: 1 block with up to 128 GPIOs |
51e02b02 ML |
29 | */ |
30 | ||
ce1d43b9 | 31 | #include <linux/init.h> |
51e02b02 | 32 | #include <linux/kernel.h> |
51e02b02 | 33 | #include <linux/types.h> |
2a296157 | 34 | #include <linux/gpio/driver.h> |
ce1d43b9 | 35 | #include <asm/mach-au1x00/gpio-au1000.h> |
809f36c6 | 36 | #include <asm/mach-au1x00/gpio-au1300.h> |
51e02b02 | 37 | |
51e02b02 ML |
38 | static int gpio2_get(struct gpio_chip *chip, unsigned offset) |
39 | { | |
7b42c00a | 40 | return !!alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE); |
51e02b02 ML |
41 | } |
42 | ||
43 | static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value) | |
44 | { | |
45 | alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value); | |
46 | } | |
47 | ||
48 | static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset) | |
49 | { | |
50 | return alchemy_gpio2_direction_input(offset + ALCHEMY_GPIO2_BASE); | |
51 | } | |
52 | ||
53 | static int gpio2_direction_output(struct gpio_chip *chip, unsigned offset, | |
54 | int value) | |
55 | { | |
56 | return alchemy_gpio2_direction_output(offset + ALCHEMY_GPIO2_BASE, | |
57 | value); | |
58 | } | |
59 | ||
60 | static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset) | |
61 | { | |
62 | return alchemy_gpio2_to_irq(offset + ALCHEMY_GPIO2_BASE); | |
63 | } | |
70f82f2c | 64 | |
51e02b02 ML |
65 | |
66 | static int gpio1_get(struct gpio_chip *chip, unsigned offset) | |
67 | { | |
7b42c00a | 68 | return !!alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE); |
51e02b02 ML |
69 | } |
70 | ||
71 | static void gpio1_set(struct gpio_chip *chip, | |
72 | unsigned offset, int value) | |
73 | { | |
74 | alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value); | |
75 | } | |
76 | ||
77 | static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset) | |
78 | { | |
79 | return alchemy_gpio1_direction_input(offset + ALCHEMY_GPIO1_BASE); | |
80 | } | |
81 | ||
82 | static int gpio1_direction_output(struct gpio_chip *chip, | |
83 | unsigned offset, int value) | |
84 | { | |
85 | return alchemy_gpio1_direction_output(offset + ALCHEMY_GPIO1_BASE, | |
86 | value); | |
87 | } | |
88 | ||
89 | static int gpio1_to_irq(struct gpio_chip *chip, unsigned offset) | |
90 | { | |
91 | return alchemy_gpio1_to_irq(offset + ALCHEMY_GPIO1_BASE); | |
92 | } | |
93 | ||
94 | struct gpio_chip alchemy_gpio_chip[] = { | |
95 | [0] = { | |
96 | .label = "alchemy-gpio1", | |
97 | .direction_input = gpio1_direction_input, | |
98 | .direction_output = gpio1_direction_output, | |
99 | .get = gpio1_get, | |
100 | .set = gpio1_set, | |
101 | .to_irq = gpio1_to_irq, | |
102 | .base = ALCHEMY_GPIO1_BASE, | |
103 | .ngpio = ALCHEMY_GPIO1_NUM, | |
104 | }, | |
51e02b02 | 105 | [1] = { |
70342287 RB |
106 | .label = "alchemy-gpio2", |
107 | .direction_input = gpio2_direction_input, | |
108 | .direction_output = gpio2_direction_output, | |
109 | .get = gpio2_get, | |
110 | .set = gpio2_set, | |
51e02b02 | 111 | .to_irq = gpio2_to_irq, |
70342287 RB |
112 | .base = ALCHEMY_GPIO2_BASE, |
113 | .ngpio = ALCHEMY_GPIO2_NUM, | |
51e02b02 | 114 | }, |
51e02b02 ML |
115 | }; |
116 | ||
809f36c6 ML |
117 | static int alchemy_gpic_get(struct gpio_chip *chip, unsigned int off) |
118 | { | |
7b42c00a | 119 | return !!au1300_gpio_get_value(off + AU1300_GPIO_BASE); |
809f36c6 ML |
120 | } |
121 | ||
122 | static void alchemy_gpic_set(struct gpio_chip *chip, unsigned int off, int v) | |
123 | { | |
124 | au1300_gpio_set_value(off + AU1300_GPIO_BASE, v); | |
125 | } | |
126 | ||
127 | static int alchemy_gpic_dir_input(struct gpio_chip *chip, unsigned int off) | |
128 | { | |
129 | return au1300_gpio_direction_input(off + AU1300_GPIO_BASE); | |
130 | } | |
131 | ||
132 | static int alchemy_gpic_dir_output(struct gpio_chip *chip, unsigned int off, | |
133 | int v) | |
134 | { | |
135 | return au1300_gpio_direction_output(off + AU1300_GPIO_BASE, v); | |
136 | } | |
137 | ||
138 | static int alchemy_gpic_gpio_to_irq(struct gpio_chip *chip, unsigned int off) | |
139 | { | |
140 | return au1300_gpio_to_irq(off + AU1300_GPIO_BASE); | |
141 | } | |
142 | ||
143 | static struct gpio_chip au1300_gpiochip = { | |
144 | .label = "alchemy-gpic", | |
145 | .direction_input = alchemy_gpic_dir_input, | |
146 | .direction_output = alchemy_gpic_dir_output, | |
147 | .get = alchemy_gpic_get, | |
148 | .set = alchemy_gpic_set, | |
149 | .to_irq = alchemy_gpic_gpio_to_irq, | |
150 | .base = AU1300_GPIO_BASE, | |
151 | .ngpio = AU1300_GPIO_NUM, | |
152 | }; | |
153 | ||
ce1d43b9 | 154 | static int __init alchemy_gpiochip_init(void) |
51e02b02 | 155 | { |
ce1d43b9 ML |
156 | int ret = 0; |
157 | ||
158 | switch (alchemy_get_cputype()) { | |
159 | case ALCHEMY_CPU_AU1000: | |
948e0ed8 | 160 | ret = gpiochip_add_data(&alchemy_gpio_chip[0], NULL); |
ce1d43b9 ML |
161 | break; |
162 | case ALCHEMY_CPU_AU1500...ALCHEMY_CPU_AU1200: | |
948e0ed8 LW |
163 | ret = gpiochip_add_data(&alchemy_gpio_chip[0], NULL); |
164 | ret |= gpiochip_add_data(&alchemy_gpio_chip[1], NULL); | |
ce1d43b9 | 165 | break; |
809f36c6 | 166 | case ALCHEMY_CPU_AU1300: |
948e0ed8 | 167 | ret = gpiochip_add_data(&au1300_gpiochip, NULL); |
809f36c6 | 168 | break; |
ce1d43b9 ML |
169 | } |
170 | return ret; | |
51e02b02 | 171 | } |
ce1d43b9 | 172 | arch_initcall(alchemy_gpiochip_init); |