ebaaa4df7d5d53a0dfc63619290b407047c93e17
[openwrt.git] / target / linux / cns3xxx / patches-3.3 / 104-cns3xxx_gpio.patch
1 --- a/arch/arm/mach-cns3xxx/cns3420vb.c
2 +++ b/arch/arm/mach-cns3xxx/cns3420vb.c
3 @@ -216,7 +216,7 @@ static struct map_desc cns3420_io_desc[]
4  
5  static void __init cns3420_map_io(void)
6  {
7 -       cns3xxx_map_io();
8 +       cns3xxx_common_init();
9         iotable_init(cns3420_io_desc, ARRAY_SIZE(cns3420_io_desc));
10  
11         cns3420_early_serial_setup();
12 --- a/arch/arm/mach-cns3xxx/core.c
13 +++ b/arch/arm/mach-cns3xxx/core.c
14 @@ -21,6 +21,7 @@
15  #include <asm/hardware/gic.h>
16  #include <asm/smp_twd.h>
17  #include <asm/hardware/cache-l2x0.h>
18 +#include <asm/gpio.h>
19  #include <mach/cns3xxx.h>
20  #include "core.h"
21  
22 @@ -72,12 +73,73 @@ static struct map_desc cns3xxx_io_desc[]
23         },
24  };
25  
26 -void __init cns3xxx_map_io(void)
27 +static inline void gpio_line_config(u8 line, u32 direction)
28 +{
29 +       u32 reg;
30 +       if (direction) {
31 +               if (line < 32) {
32 +                       reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
33 +                       reg |= (1 << line);
34 +                       __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
35 +               } else {
36 +                       reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
37 +                       reg |= (1 << (line - 32));
38 +                       __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
39 +               }
40 +       } else {
41 +               if (line < 32) {
42 +                       reg = __raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
43 +                       reg &= ~(1 << line);
44 +                       __raw_writel(reg, CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_DIR);
45 +               } else {
46 +                       reg = __raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
47 +                       reg &= ~(1 << (line - 32));
48 +                       __raw_writel(reg, CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_DIR);
49 +               }
50 +       }
51 +}
52 +
53 +static int cns3xxx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
54 +{
55 +       gpio_line_config(gpio, CNS3XXX_GPIO_IN);
56 +       return 0;
57 +}
58 +
59 +static int cns3xxx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
60 +{
61 +       gpio_line_set(gpio, level);
62 +       gpio_line_config(gpio, CNS3XXX_GPIO_OUT);
63 +       return 0;
64 +}
65 +
66 +static int cns3xxx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
67 +{
68 +       return gpio_get_value(gpio);
69 +}
70 +
71 +static void cns3xxx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
72 +{
73 +       gpio_set_value(gpio, value);
74 +}
75 +
76 +static struct gpio_chip cns3xxx_gpio_chip = {
77 +       .label                  = "CNS3XXX_GPIO_CHIP",
78 +       .direction_input        = cns3xxx_gpio_direction_input,
79 +       .direction_output       = cns3xxx_gpio_direction_output,
80 +       .get                    = cns3xxx_gpio_get_value,
81 +       .set                    = cns3xxx_gpio_set_value,
82 +       .base                   = 0,
83 +       .ngpio                  = 64,
84 +};
85 +
86 +void __init cns3xxx_common_init(void)
87  {
88  #ifdef CONFIG_LOCAL_TIMERS
89         twd_base = (void __iomem *) CNS3XXX_TC11MP_TWD_BASE_VIRT;
90  #endif
91         iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc));
92 +
93 +       gpiochip_add(&cns3xxx_gpio_chip);
94  }
95  
96  /* used by entry-macro.S */
97 --- a/arch/arm/mach-cns3xxx/core.h
98 +++ b/arch/arm/mach-cns3xxx/core.h
99 @@ -21,7 +21,7 @@ void __init cns3xxx_l2x0_init(void);
100  static inline void cns3xxx_l2x0_init(void) {}
101  #endif /* CONFIG_CACHE_L2X0 */
102  
103 -void __init cns3xxx_map_io(void);
104 +void __init cns3xxx_common_init(void);
105  void __init cns3xxx_init_irq(void);
106  void cns3xxx_power_off(void);
107  void cns3xxx_restart(char, const char *);
108 --- a/arch/arm/Kconfig
109 +++ b/arch/arm/Kconfig
110 @@ -366,6 +366,7 @@ config ARCH_CLPS711X
111  config ARCH_CNS3XXX
112         bool "Cavium Networks CNS3XXX family"
113         select CPU_V6K
114 +       select ARCH_WANT_OPTIONAL_GPIOLIB
115         select GENERIC_CLOCKEVENTS
116         select ARM_GIC
117         select CLKDEV_LOOKUP
118 --- /dev/null
119 +++ b/arch/arm/mach-cns3xxx/include/mach/gpio.h
120 @@ -0,0 +1,98 @@
121 +/*
122 + * arch/arm/mach-cns3xxx/include/mach/gpio.h
123 + *
124 + * CNS3xxx GPIO wrappers for arch-neutral GPIO calls
125 + *
126 + * Copyright 2011 Gateworks Corporation
127 + *               Chris Lang <clang@gateworks.com>
128 + *
129 + * Based on IXP implementation by Milan Svoboda <msvoboda@ra.rockwell.com>
130 + * Based on PXA implementation by Philipp Zabel <philipp.zabel@gmail.com>
131 + *
132 + * This program is free software; you can redistribute it and/or modify
133 + * it under the terms of the GNU General Public License as published by
134 + * the Free Software Foundation; either version 2 of the License, or
135 + * (at your option) any later version.
136 + *
137 + * This program is distributed in the hope that it will be useful,
138 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
139 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
140 + * GNU General Public License for more details.
141 + *
142 + * You should have received a copy of the GNU General Public License
143 + * along with this program; if not, write to the Free Software
144 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
145 + *
146 + */
147 +
148 +#ifndef __ASM_ARCH_CNS3XXX_GPIO_H
149 +#define __ASM_ARCH_CNS3XXX_GPIO_H
150 +
151 +#include <linux/kernel.h>
152 +#include <linux/io.h>
153 +#include <mach/platform.h>
154 +#include <asm-generic/gpio.h>                  /* cansleep wrappers */
155 +
156 +#define NR_BUILTIN_GPIO 64
157 +
158 +#define CNS3XXX_GPIO_IN    0x0
159 +#define CNS3XXX_GPIO_OUT   0x1
160 +
161 +#define CNS3XXX_GPIO_LO   0
162 +#define CNS3XXX_GPIO_HI   1
163 +
164 +#define CNS3XXX_GPIO_OUTPUT         0x00
165 +#define CNS3XXX_GPIO_INPUT          0x04
166 +#define CNS3XXX_GPIO_DIR            0x08
167 +#define CNS3XXX_GPIO_SET            0x10
168 +#define CNS3XXX_GPIO_CLEAR          0x14
169 +
170 +static inline void gpio_line_get(u8 line, int *value)
171 +{
172 +       if (line < 32)
173 +               *value = ((__raw_readl(CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> line) & 0x1);
174 +       else
175 +               *value = ((__raw_readl(CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_INPUT) >> (line - 32)) & 0x1);
176 +}
177 +
178 +static inline void gpio_line_set(u8 line, int value)
179 +{
180 +       if (line < 32) {
181 +               if (value)
182 +                       __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_SET);
183 +               else
184 +                       __raw_writel((1 << line), CNS3XXX_GPIOA_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
185 +       } else {
186 +               if (value)
187 +                       __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_SET);
188 +               else
189 +                       __raw_writel((1 << line), CNS3XXX_GPIOB_BASE_VIRT + CNS3XXX_GPIO_CLEAR);
190 +       }
191 +}
192 +
193 +static inline int gpio_get_value(unsigned gpio)
194 +{
195 +       if (gpio < NR_BUILTIN_GPIO)
196 +       {
197 +               int value;
198 +               gpio_line_get(gpio, &value);
199 +               return value;
200 +       }
201 +       else
202 +               return __gpio_get_value(gpio);
203 +}
204 +
205 +static inline void gpio_set_value(unsigned gpio, int value)
206 +{
207 +       if (gpio < NR_BUILTIN_GPIO)
208 +               gpio_line_set(gpio, value);
209 +       else
210 +               __gpio_set_value(gpio, value);
211 +}
212 +
213 +#define gpio_cansleep __gpio_cansleep
214 +
215 +extern int gpio_to_irq(int gpio);
216 +extern int irq_to_gpio(int gpio);
217 +
218 +#endif