[au1000] Convert au1000 to using gpiolib, fixes an oops on startup
[openwrt.git] / target / linux / au1000 / patches-2.6.27 / 007-gpiolib.patch
1 diff -urN linux-2.6.27.7/arch/mips/au1000/Kconfig linux-2.6.27.7.new/arch/mips/au1000/Kconfig
2 --- linux-2.6.27.7/arch/mips/au1000/Kconfig     2008-11-21 00:02:37.000000000 +0100
3 +++ linux-2.6.27.7.new/arch/mips/au1000/Kconfig 2008-12-08 11:44:09.000000000 +0100
4 @@ -134,3 +134,4 @@
5         select SYS_HAS_CPU_MIPS32_R1
6         select SYS_SUPPORTS_32BIT_KERNEL
7         select SYS_SUPPORTS_APM_EMULATION
8 +       select ARCH_REQUIRE_GPIOLIB
9 diff -urN linux-2.6.27.7/arch/mips/au1000/common/gpio.c linux-2.6.27.7.new/arch/mips/au1000/common/gpio.c
10 --- linux-2.6.27.7/arch/mips/au1000/common/gpio.c       2008-11-21 00:02:37.000000000 +0100
11 +++ linux-2.6.27.7.new/arch/mips/au1000/common/gpio.c   2008-12-08 11:58:30.000000000 +0100
12 @@ -1,5 +1,5 @@
13  /*
14 - *  Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
15 + *  Copyright (C) 2007-2008, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
16   *     Architecture specific GPIO support
17   *
18   *  This program is free software; you can redistribute         it and/or modify it
19 @@ -27,122 +27,222 @@
20   *     others have a second one : GPIO2
21   */
22  
23 +#include <linux/kernel.h>
24  #include <linux/module.h>
25 +#include <linux/types.h>
26 +#include <linux/platform_device.h>
27 +#include <linux/gpio.h>
28  
29  #include <asm/mach-au1x00/au1000.h>
30 -#include <asm/gpio.h>
31 +#include <asm/mach-au1x00/gpio.h>
32  
33 -#define gpio1 sys
34 -#if !defined(CONFIG_SOC_AU1000)
35 +struct au1000_gpio_chip {
36 +       struct gpio_chip        chip;
37 +       void __iomem            *regbase;
38 +};
39  
40 -static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
41 +#if !defined(CONFIG_SOC_AU1000)
42  #define GPIO2_OUTPUT_ENABLE_MASK       0x00010000
43  
44 -static int au1xxx_gpio2_read(unsigned gpio)
45 +/*
46 + * Return GPIO bank 2 level
47 + */
48 +static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset)
49  {
50 -       gpio -= AU1XXX_GPIO_BASE;
51 -       return ((gpio2->pinstate >> gpio) & 0x01);
52 +       u32 mask = 1 << offset;
53 +       struct au1000_gpio_chip *gpch;
54 +       
55 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
56 +       return readl(gpch->regbase + AU1000_GPIO2_ST) & mask;
57  }
58  
59 -static void au1xxx_gpio2_write(unsigned gpio, int value)
60 +/*
61 + * Set output GPIO bank 2 level
62 + */
63 +static void au1000_gpio2_set(struct gpio_chip *chip,
64 +                               unsigned offset, int value)
65  {
66 -       gpio -= AU1XXX_GPIO_BASE;
67 -
68 -       gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
69 +       u32                     mask = (!!value) << offset;
70 +       struct au1000_gpio_chip *gpch;
71 +       unsigned long           flags;
72 +
73 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
74 +       
75 +       local_irq_save(flags);
76 +       writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask,
77 +                               gpch->regbase + AU1000_GPIO2_OUT);
78 +       local_irq_restore(flags);
79  }
80  
81 -static int au1xxx_gpio2_direction_input(unsigned gpio)
82 +/*
83 + * Set GPIO bank 2 direction to input
84 + */
85 +static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
86  {
87 -       gpio -= AU1XXX_GPIO_BASE;
88 -       gpio2->dir &= ~(0x01 << gpio);
89 +       unsigned long           flags;
90 +       u32                     mask = 1 << offset;
91 +       u32                     value;
92 +       struct au1000_gpio_chip *gpch;
93 +       void __iomem            *gpdr;
94 +
95 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
96 +       gpdr = gpch->regbase + AU1000_GPIO2_DIR;
97 +
98 +       local_irq_save(flags);
99 +       value = readl(gpdr);
100 +       value &= ~mask;
101 +       writel(value, gpdr);
102 +       local_irq_restore(flags);
103 +
104         return 0;
105  }
106  
107 -static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
108 +/*
109 + * Set GPIO bank2 direction to output
110 + */
111 +static int au1000_gpio2_direction_output(struct gpio_chip *chip,
112 +                                       unsigned offset, int value)
113  {
114 -       gpio -= AU1XXX_GPIO_BASE;
115 -       gpio2->dir |= 0x01 << gpio;
116 -       gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
117 +       unsigned long           flags;
118 +       u32                     mask = 1 << offset;
119 +       u32                     tmp;
120 +       struct au1000_gpio_chip *gpch;
121 +       void __iomem            *gpdr;
122 +       
123 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
124 +       gpdr = gpch->regbase + AU1000_GPIO2_DIR;
125 +       
126 +       local_irq_save(flags);
127 +       tmp = readl(gpdr);
128 +       tmp |= mask;
129 +       writel(tmp, gpdr);
130 +       mask = (!!value) << offset;
131 +        writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask,
132 +                                       gpch->regbase + AU1000_GPIO2_OUT);
133 +       local_irq_restore(flags);
134 +
135         return 0;
136  }
137 -
138  #endif /* !defined(CONFIG_SOC_AU1000) */
139  
140 -static int au1xxx_gpio1_read(unsigned gpio)
141 +/*
142 + * Return GPIO bank 2 level
143 + */
144 +static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset)
145  {
146 -       return (gpio1->pinstaterd >> gpio) & 0x01;
147 +       u32                     mask = 1 << offset;
148 +       struct au1000_gpio_chip *gpch;
149 +
150 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
151 +       return readl(gpch->regbase + 0x0110) & mask;
152  }
153  
154 -static void au1xxx_gpio1_write(unsigned gpio, int value)
155 +/*
156 + * Set GPIO bank 1 level
157 + */
158 +static void au1000_gpio1_set(struct gpio_chip *chip,
159 +                               unsigned offset, int value)
160  {
161 +       unsigned long           flags;
162 +       u32                     mask = 1 << offset;
163 +       struct au1000_gpio_chip *gpch;
164 +
165 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
166 +       
167 +       local_irq_save(flags);
168         if (value)
169 -               gpio1->outputset = (0x01 << gpio);
170 +               writel(mask, gpch->regbase + 0x0108);   
171         else
172 -               /* Output a zero */
173 -               gpio1->outputclr = (0x01 << gpio);
174 +               writel(mask, gpch->regbase + 0x010C);
175 +       local_irq_restore(flags);
176  }
177  
178 -static int au1xxx_gpio1_direction_input(unsigned gpio)
179 +/*
180 + * Set GPIO bank 1 direction to input
181 + */
182 +static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
183  {
184 -       gpio1->pininputen = (0x01 << gpio);
185 -       return 0;
186 -}
187 +       unsigned long           flags;
188 +       u32                     mask = 1 << offset;
189 +       u32                     value;
190 +       struct au1000_gpio_chip *gpch;
191 +       void __iomem            *gpdr;
192 +
193 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
194 +       gpdr = gpch->regbase + 0x0110;
195 +       
196 +       local_irq_save(flags);
197 +       value = readl(gpdr);
198 +       value |= mask;
199 +       writel(mask, gpdr);
200 +       local_irq_restore(flags);
201  
202 -static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
203 -{
204 -       gpio1->trioutclr = (0x01 & gpio);
205 -       au1xxx_gpio1_write(gpio, value);
206         return 0;
207  }
208  
209 -int au1xxx_gpio_get_value(unsigned gpio)
210 +/*
211 + * Set GPIO bank 1 direction to output
212 + */
213 +static int au1000_gpio1_direction_output(struct gpio_chip *chip,
214 +                                       unsigned offset, int value)
215  {
216 -       if (gpio >= AU1XXX_GPIO_BASE)
217 -#if defined(CONFIG_SOC_AU1000)
218 -               return 0;
219 -#else
220 -               return au1xxx_gpio2_read(gpio);
221 -#endif
222 +       unsigned long           flags;
223 +       u32                     mask = 1 << offset;
224 +       u32                     tmp;
225 +       struct au1000_gpio_chip *gpch;
226 +       void __iomem            *gpdr;
227 +
228 +       gpch = container_of(chip, struct au1000_gpio_chip, chip);
229 +       gpdr = gpch->regbase + 0x0100;
230 +       
231 +       local_irq_save(flags);
232 +       tmp = readl(gpdr);
233 +       writel(tmp, gpdr);
234 +       if (value)
235 +               writel(mask, gpch->regbase + 0x0108);
236         else
237 -               return au1xxx_gpio1_read(gpio);
238 -}
239 -EXPORT_SYMBOL(au1xxx_gpio_get_value);
240 +               writel(mask, gpch->regbase + 0x0108);
241 +       local_irq_restore(flags);
242  
243 -void au1xxx_gpio_set_value(unsigned gpio, int value)
244 -{
245 -       if (gpio >= AU1XXX_GPIO_BASE)
246 -#if defined(CONFIG_SOC_AU1000)
247 -               ;
248 -#else
249 -               au1xxx_gpio2_write(gpio, value);
250 -#endif
251 -       else
252 -               au1xxx_gpio1_write(gpio, value);
253 +       return 0;
254  }
255 -EXPORT_SYMBOL(au1xxx_gpio_set_value);
256  
257 -int au1xxx_gpio_direction_input(unsigned gpio)
258 -{
259 -       if (gpio >= AU1XXX_GPIO_BASE)
260 -#if defined(CONFIG_SOC_AU1000)
261 -               return -ENODEV;
262 -#else
263 -               return au1xxx_gpio2_direction_input(gpio);
264 +struct au1000_gpio_chip au1000_gpio_chip[] = {
265 +       [0] = {
266 +               .regbase                        = (void __iomem *)SYS_BASE,
267 +               .chip = {
268 +                       .label                  = "au1000-gpio1",
269 +                       .direction_input        = au1000_gpio1_direction_input,
270 +                       .direction_output       = au1000_gpio1_direction_output,
271 +                       .get                    = au1000_gpio1_get,
272 +                       .set                    = au1000_gpio1_set,
273 +                       .base                   = 0,
274 +                       .ngpio                  = 32,
275 +               },
276 +       },
277 +#if !defined(CONFIG_SOC_AU1000)
278 +       [1] = {
279 +               .regbase                        = (void __iomem *)GPIO2_BASE,
280 +               .chip = {
281 +                       .label                  = "au1000-gpio2",
282 +                       .direction_input        = au1000_gpio2_direction_input,
283 +                       .direction_output       = au1000_gpio2_direction_output,
284 +                       .get                    = au1000_gpio2_get,
285 +                       .set                    = au1000_gpio2_set,
286 +                       .base                   = AU1XXX_GPIO_BASE,
287 +                       .ngpio                  = 32,
288 +               },
289 +       },
290  #endif
291 +};
292  
293 -       return au1xxx_gpio1_direction_input(gpio);
294 -}
295 -EXPORT_SYMBOL(au1xxx_gpio_direction_input);
296 -
297 -int au1xxx_gpio_direction_output(unsigned gpio, int value)
298 +int __init au1000_gpio_init(void)
299  {
300 -       if (gpio >= AU1XXX_GPIO_BASE)
301 -#if defined(CONFIG_SOC_AU1000)
302 -               return -ENODEV;
303 -#else
304 -               return au1xxx_gpio2_direction_output(gpio, value);
305 +       gpiochip_add(&au1000_gpio_chip[0].chip);
306 +#if !defined(CONFIG_SOC_AU1000)
307 +       gpiochip_add(&au1000_gpio_chip[1].chip);
308  #endif
309  
310 -       return au1xxx_gpio1_direction_output(gpio, value);
311 +       return 0;
312  }
313 -EXPORT_SYMBOL(au1xxx_gpio_direction_output);
314 +arch_initcall(au1000_gpio_init);
315 diff -urN linux-2.6.27.7/include/asm-mips/mach-au1x00/gpio.h linux-2.6.27.7.new/include/asm-mips/mach-au1x00/gpio.h
316 --- linux-2.6.27.7/include/asm-mips/mach-au1x00/gpio.h  2008-11-21 00:02:37.000000000 +0100
317 +++ linux-2.6.27.7.new/include/asm-mips/mach-au1x00/gpio.h      2008-12-08 11:43:37.000000000 +0100
318 @@ -1,69 +1,21 @@
319  #ifndef _AU1XXX_GPIO_H_
320  #define _AU1XXX_GPIO_H_
321  
322 -#include <linux/types.h>
323 -
324  #define AU1XXX_GPIO_BASE       200
325  
326 -struct au1x00_gpio2 {
327 -       u32     dir;
328 -       u32     reserved;
329 -       u32     output;
330 -       u32     pinstate;
331 -       u32     inten;
332 -       u32     enable;
333 -};
334 -
335 -extern int au1xxx_gpio_get_value(unsigned gpio);
336 -extern void au1xxx_gpio_set_value(unsigned gpio, int value);
337 -extern int au1xxx_gpio_direction_input(unsigned gpio);
338 -extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
339 -
340 -
341 -/* Wrappers for the arch-neutral GPIO API */
342 -
343 -static inline int gpio_request(unsigned gpio, const char *label)
344 -{
345 -       /* Not yet implemented */
346 -       return 0;
347 -}
348 -
349 -static inline void gpio_free(unsigned gpio)
350 -{
351 -       /* Not yet implemented */
352 -}
353 -
354 -static inline int gpio_direction_input(unsigned gpio)
355 -{
356 -       return au1xxx_gpio_direction_input(gpio);
357 -}
358 -
359 -static inline int gpio_direction_output(unsigned gpio, int value)
360 -{
361 -       return au1xxx_gpio_direction_output(gpio, value);
362 -}
363 -
364 -static inline int gpio_get_value(unsigned gpio)
365 -{
366 -       return au1xxx_gpio_get_value(gpio);
367 -}
368 -
369 -static inline void gpio_set_value(unsigned gpio, int value)
370 -{
371 -       au1xxx_gpio_set_value(gpio, value);
372 -}
373 -
374 -static inline int gpio_to_irq(unsigned gpio)
375 -{
376 -       return gpio;
377 -}
378 -
379 -static inline int irq_to_gpio(unsigned irq)
380 -{
381 -       return irq;
382 -}
383 +#define AU1000_GPIO2_DIR       0x00
384 +#define AU1000_GPIO2_RSVD      0x04
385 +#define AU1000_GPIO2_OUT       0x08
386 +#define AU1000_GPIO2_ST                0x0C
387 +#define AU1000_GPIO2_INT       0x10
388 +#define AU1000_GPIO2_EN                0x14
389 +
390 +#define gpio_get_value         __gpio_get_value
391 +#define gpio_set_value         __gpio_set_value
392 +
393 +#define gpio_to_irq(gpio)      NULL
394 +#define irq_to_gpio(irq)       NULL
395  
396 -/* For cansleep */
397  #include <asm-generic/gpio.h>
398  
399  #endif /* _AU1XXX_GPIO_H_ */