aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2011-06-06 11:37:58 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-06-06 11:37:58 -0400
commit7b2fa5702059a03c11f934224724b2f712a749ce (patch)
tree42e9357b0925346fa2639f74e0bf9e13e58915ce /drivers/gpio
parent59c5f46fbe01a00eedf54a23789634438bb80603 (diff)
gpio/mxs: Move Freescale mxs gpio driver to drivers/gpio
GPIO drivers are getting moved to drivers/gpio for cleanup and consolidation. This patch moves the mxs driver. Follow up patches will clean it up and make it a fine upstanding example of a gpio driver. v2: Removed header file entirely and put struct definition directly into driver. The struct isn't used anywhere else in the kernel. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-mxs.c338
3 files changed, 343 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 4a7f63143455..48711749ffcf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -93,6 +93,10 @@ config GPIO_EXYNOS4
93 help 93 help
94 Say yes here to support Samsung Exynos4 series SoCs GPIO library 94 Say yes here to support Samsung Exynos4 series SoCs GPIO library
95 95
96config GPIO_MXS
97 def_bool y
98 depends on ARCH_MXS
99
96config GPIO_PLAT_SAMSUNG 100config GPIO_PLAT_SAMSUNG
97 bool "Samsung SoCs GPIO library support" 101 bool "Samsung SoCs GPIO library support"
98 default y if SAMSUNG_GPIOLIB_4BIT 102 default y if SAMSUNG_GPIOLIB_4BIT
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b605f8ec6fbe..f879cbe493d5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
9obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o 9obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o
10obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o 10obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
11obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o 11obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
12obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
12obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o 13obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
13obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o 14obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
14obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o 15obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
new file mode 100644
index 000000000000..e26bf309b214
--- /dev/null
+++ b/drivers/gpio/gpio-mxs.c
@@ -0,0 +1,338 @@
1/*
2 * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 *
5 * Based on code from Freescale,
6 * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 */
22
23#include <linux/init.h>
24#include <linux/interrupt.h>
25#include <linux/io.h>
26#include <linux/irq.h>
27#include <linux/gpio.h>
28#include <mach/mx23.h>
29#include <mach/mx28.h>
30#include <asm-generic/bug.h>
31
32static struct mxs_gpio_port *mxs_gpio_ports;
33static int gpio_table_size;
34
35#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
36#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
37#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
38#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
39#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
40#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
41#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
42#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
43
44#define GPIO_INT_FALL_EDGE 0x0
45#define GPIO_INT_LOW_LEV 0x1
46#define GPIO_INT_RISE_EDGE 0x2
47#define GPIO_INT_HIGH_LEV 0x3
48#define GPIO_INT_LEV_MASK (1 << 0)
49#define GPIO_INT_POL_MASK (1 << 1)
50
51struct mxs_gpio_port {
52 void __iomem *base;
53 int id;
54 int irq;
55 int irq_high;
56 int virtual_irq_start;
57 struct gpio_chip chip;
58};
59
60/* Note: This driver assumes 32 GPIOs are handled in one register */
61
62static void clear_gpio_irqstatus(struct mxs_gpio_port *port, u32 index)
63{
64 __mxs_clrl(1 << index, port->base + PINCTRL_IRQSTAT(port->id));
65}
66
67static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
68 int enable)
69{
70 if (enable) {
71 __mxs_setl(1 << index, port->base + PINCTRL_IRQEN(port->id));
72 __mxs_setl(1 << index, port->base + PINCTRL_PIN2IRQ(port->id));
73 } else {
74 __mxs_clrl(1 << index, port->base + PINCTRL_IRQEN(port->id));
75 }
76}
77
78static void mxs_gpio_ack_irq(struct irq_data *d)
79{
80 u32 gpio = irq_to_gpio(d->irq);
81 clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
82}
83
84static void mxs_gpio_mask_irq(struct irq_data *d)
85{
86 u32 gpio = irq_to_gpio(d->irq);
87 set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
88}
89
90static void mxs_gpio_unmask_irq(struct irq_data *d)
91{
92 u32 gpio = irq_to_gpio(d->irq);
93 set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
94}
95
96static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
97
98static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
99{
100 u32 gpio = irq_to_gpio(d->irq);
101 u32 pin_mask = 1 << (gpio & 31);
102 struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
103 void __iomem *pin_addr;
104 int edge;
105
106 switch (type) {
107 case IRQ_TYPE_EDGE_RISING:
108 edge = GPIO_INT_RISE_EDGE;
109 break;
110 case IRQ_TYPE_EDGE_FALLING:
111 edge = GPIO_INT_FALL_EDGE;
112 break;
113 case IRQ_TYPE_LEVEL_LOW:
114 edge = GPIO_INT_LOW_LEV;
115 break;
116 case IRQ_TYPE_LEVEL_HIGH:
117 edge = GPIO_INT_HIGH_LEV;
118 break;
119 default:
120 return -EINVAL;
121 }
122
123 /* set level or edge */
124 pin_addr = port->base + PINCTRL_IRQLEV(port->id);
125 if (edge & GPIO_INT_LEV_MASK)
126 __mxs_setl(pin_mask, pin_addr);
127 else
128 __mxs_clrl(pin_mask, pin_addr);
129
130 /* set polarity */
131 pin_addr = port->base + PINCTRL_IRQPOL(port->id);
132 if (edge & GPIO_INT_POL_MASK)
133 __mxs_setl(pin_mask, pin_addr);
134 else
135 __mxs_clrl(pin_mask, pin_addr);
136
137 clear_gpio_irqstatus(port, gpio & 0x1f);
138
139 return 0;
140}
141
142/* MXS has one interrupt *per* gpio port */
143static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
144{
145 u32 irq_stat;
146 struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
147 u32 gpio_irq_no_base = port->virtual_irq_start;
148
149 desc->irq_data.chip->irq_ack(&desc->irq_data);
150
151 irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) &
152 __raw_readl(port->base + PINCTRL_IRQEN(port->id));
153
154 while (irq_stat != 0) {
155 int irqoffset = fls(irq_stat) - 1;
156 generic_handle_irq(gpio_irq_no_base + irqoffset);
157 irq_stat &= ~(1 << irqoffset);
158 }
159}
160
161/*
162 * Set interrupt number "irq" in the GPIO as a wake-up source.
163 * While system is running, all registered GPIO interrupts need to have
164 * wake-up enabled. When system is suspended, only selected GPIO interrupts
165 * need to have wake-up enabled.
166 * @param irq interrupt source number
167 * @param enable enable as wake-up if equal to non-zero
168 * @return This function returns 0 on success.
169 */
170static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
171{
172 u32 gpio = irq_to_gpio(d->irq);
173 u32 gpio_idx = gpio & 0x1f;
174 struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
175
176 if (enable) {
177 if (port->irq_high && (gpio_idx >= 16))
178 enable_irq_wake(port->irq_high);
179 else
180 enable_irq_wake(port->irq);
181 } else {
182 if (port->irq_high && (gpio_idx >= 16))
183 disable_irq_wake(port->irq_high);
184 else
185 disable_irq_wake(port->irq);
186 }
187
188 return 0;
189}
190
191static struct irq_chip gpio_irq_chip = {
192 .name = "mxs gpio",
193 .irq_ack = mxs_gpio_ack_irq,
194 .irq_mask = mxs_gpio_mask_irq,
195 .irq_unmask = mxs_gpio_unmask_irq,
196 .irq_set_type = mxs_gpio_set_irq_type,
197 .irq_set_wake = mxs_gpio_set_wake_irq,
198};
199
200static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
201 int dir)
202{
203 struct mxs_gpio_port *port =
204 container_of(chip, struct mxs_gpio_port, chip);
205 void __iomem *pin_addr = port->base + PINCTRL_DOE(port->id);
206
207 if (dir)
208 __mxs_setl(1 << offset, pin_addr);
209 else
210 __mxs_clrl(1 << offset, pin_addr);
211}
212
213static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset)
214{
215 struct mxs_gpio_port *port =
216 container_of(chip, struct mxs_gpio_port, chip);
217
218 return (__raw_readl(port->base + PINCTRL_DIN(port->id)) >> offset) & 1;
219}
220
221static void mxs_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
222{
223 struct mxs_gpio_port *port =
224 container_of(chip, struct mxs_gpio_port, chip);
225 void __iomem *pin_addr = port->base + PINCTRL_DOUT(port->id);
226
227 if (value)
228 __mxs_setl(1 << offset, pin_addr);
229 else
230 __mxs_clrl(1 << offset, pin_addr);
231}
232
233static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
234{
235 struct mxs_gpio_port *port =
236 container_of(chip, struct mxs_gpio_port, chip);
237
238 return port->virtual_irq_start + offset;
239}
240
241static int mxs_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
242{
243 mxs_set_gpio_direction(chip, offset, 0);
244 return 0;
245}
246
247static int mxs_gpio_direction_output(struct gpio_chip *chip,
248 unsigned offset, int value)
249{
250 mxs_gpio_set(chip, offset, value);
251 mxs_set_gpio_direction(chip, offset, 1);
252 return 0;
253}
254
255int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
256{
257 int i, j;
258
259 /* save for local usage */
260 mxs_gpio_ports = port;
261 gpio_table_size = cnt;
262
263 pr_info("MXS GPIO hardware\n");
264
265 for (i = 0; i < cnt; i++) {
266 /* disable the interrupt and clear the status */
267 __raw_writel(0, port[i].base + PINCTRL_PIN2IRQ(i));
268 __raw_writel(0, port[i].base + PINCTRL_IRQEN(i));
269
270 /* clear address has to be used to clear IRQSTAT bits */
271 __mxs_clrl(~0U, port[i].base + PINCTRL_IRQSTAT(i));
272
273 for (j = port[i].virtual_irq_start;
274 j < port[i].virtual_irq_start + 32; j++) {
275 irq_set_chip_and_handler(j, &gpio_irq_chip,
276 handle_level_irq);
277 set_irq_flags(j, IRQF_VALID);
278 }
279
280 /* setup one handler for each entry */
281 irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
282 irq_set_handler_data(port[i].irq, &port[i]);
283
284 /* register gpio chip */
285 port[i].chip.direction_input = mxs_gpio_direction_input;
286 port[i].chip.direction_output = mxs_gpio_direction_output;
287 port[i].chip.get = mxs_gpio_get;
288 port[i].chip.set = mxs_gpio_set;
289 port[i].chip.to_irq = mxs_gpio_to_irq;
290 port[i].chip.base = i * 32;
291 port[i].chip.ngpio = 32;
292
293 /* its a serious configuration bug when it fails */
294 BUG_ON(gpiochip_add(&port[i].chip) < 0);
295 }
296
297 return 0;
298}
299
300#define MX23_GPIO_BASE MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
301#define MX28_GPIO_BASE MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
302
303#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id) \
304 { \
305 .chip.label = "gpio-" #_id, \
306 .id = _id, \
307 .irq = _irq, \
308 .base = _base, \
309 .virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32, \
310 }
311
312#ifdef CONFIG_SOC_IMX23
313static struct mxs_gpio_port mx23_gpio_ports[] = {
314 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
315 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
316 DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
317};
318
319int __init mx23_register_gpios(void)
320{
321 return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
322}
323#endif
324
325#ifdef CONFIG_SOC_IMX28
326static struct mxs_gpio_port mx28_gpio_ports[] = {
327 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
328 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
329 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
330 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
331 DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
332};
333
334int __init mx28_register_gpios(void)
335{
336 return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
337}
338#endif