blob: 380204781f843cea4a66834c95ac5f7788f6bcdc [file] [log] [blame]
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001/*
2 * Generic GPIO driver for logic cells found in the Nomadik SoC
3 *
4 * Copyright (C) 2008,2009 STMicroelectronics
5 * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
6 * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/device.h>
Rabin Vincent3e3c62c2010-03-03 04:52:34 +010016#include <linux/platform_device.h>
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010017#include <linux/io.h>
Rabin Vincentaf7dc222010-05-06 11:14:17 +010018#include <linux/clk.h>
19#include <linux/err.h>
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010020#include <linux/gpio.h>
21#include <linux/spinlock.h>
22#include <linux/interrupt.h>
23#include <linux/irq.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010025
Will Deaconadfed152011-02-28 10:12:29 +000026#include <asm/mach/irq.h>
27
Rabin Vincent378be062010-06-02 06:06:29 +010028#include <plat/pincfg.h>
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010029#include <mach/hardware.h>
30#include <mach/gpio.h>
31
32/*
33 * The GPIO module in the Nomadik family of Systems-on-Chip is an
34 * AMBA device, managing 32 pins and alternate functions. The logic block
Jonas Aaberg9c66ee62010-10-13 13:14:17 +020035 * is currently used in the Nomadik and ux500.
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010036 *
37 * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
38 */
39
Rabin Vincent01727e62010-12-13 12:02:40 +053040#define NMK_GPIO_PER_CHIP 32
41
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010042struct nmk_gpio_chip {
43 struct gpio_chip chip;
44 void __iomem *addr;
Rabin Vincentaf7dc222010-05-06 11:14:17 +010045 struct clk *clk;
Rabin Vincent33b744b2010-10-14 10:38:03 +053046 unsigned int bank;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010047 unsigned int parent_irq;
Virupax Sadashivpetimath2c8bb0e2010-11-11 14:10:38 +053048 int secondary_parent_irq;
Rabin Vincent33b744b2010-10-14 10:38:03 +053049 u32 (*get_secondary_status)(unsigned int bank);
Rabin Vincent01727e62010-12-13 12:02:40 +053050 void (*set_ioforce)(bool enable);
Rabin Vincentc0fcb8d2010-03-03 04:48:54 +010051 spinlock_t lock;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010052 /* Keep track of configured edges */
53 u32 edge_rising;
54 u32 edge_falling;
Rabin Vincentb9df4682011-02-10 11:45:58 +053055 u32 real_wake;
56 u32 rwimsc;
57 u32 fwimsc;
58 u32 slpm;
Thomas Gleixnerd1118f62011-03-24 12:38:50 +010059 u32 enabled;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +010060};
61
Rabin Vincent01727e62010-12-13 12:02:40 +053062static struct nmk_gpio_chip *
63nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
64
65static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
66
67#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
68
Rabin Vincent6f9a9742010-06-02 05:50:28 +010069static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
70 unsigned offset, int gpio_mode)
71{
72 u32 bit = 1 << offset;
73 u32 afunc, bfunc;
74
75 afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
76 bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
77 if (gpio_mode & NMK_GPIO_ALT_A)
78 afunc |= bit;
79 if (gpio_mode & NMK_GPIO_ALT_B)
80 bfunc |= bit;
81 writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
82 writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
83}
84
Rabin Vincent81a3c292010-05-27 12:39:23 +010085static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
86 unsigned offset, enum nmk_gpio_slpm mode)
87{
88 u32 bit = 1 << offset;
89 u32 slpm;
90
91 slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
92 if (mode == NMK_GPIO_SLPM_NOCHANGE)
93 slpm |= bit;
94 else
95 slpm &= ~bit;
96 writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
97}
98
Rabin Vincent5b327ed2010-05-27 12:29:50 +010099static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
100 unsigned offset, enum nmk_gpio_pull pull)
101{
102 u32 bit = 1 << offset;
103 u32 pdis;
104
105 pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
106 if (pull == NMK_GPIO_PULL_NONE)
107 pdis |= bit;
108 else
109 pdis &= ~bit;
110 writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
111
Rabin Vincent5317e4d12011-02-10 09:29:53 +0530112 if (pull == NMK_GPIO_PULL_UP)
Rabin Vincent5b327ed2010-05-27 12:29:50 +0100113 writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
Rabin Vincent5317e4d12011-02-10 09:29:53 +0530114 else if (pull == NMK_GPIO_PULL_DOWN)
Rabin Vincent5b327ed2010-05-27 12:29:50 +0100115 writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
116}
117
Rabin Vincent378be062010-06-02 06:06:29 +0100118static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
119 unsigned offset)
120{
121 writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
122}
123
Rabin Vincent6720db72010-09-02 11:28:48 +0100124static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
125 unsigned offset, int val)
126{
127 if (val)
128 writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
129 else
130 writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
131}
132
133static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
134 unsigned offset, int val)
135{
136 writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
137 __nmk_gpio_set_output(nmk_chip, offset, val);
138}
139
Rabin Vincent01727e62010-12-13 12:02:40 +0530140static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
141 unsigned offset, int gpio_mode,
142 bool glitch)
143{
Linus Walleij3c4bee02011-02-16 10:37:52 +0100144 u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
145 u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
Rabin Vincent01727e62010-12-13 12:02:40 +0530146
147 if (glitch && nmk_chip->set_ioforce) {
148 u32 bit = BIT(offset);
149
Rabin Vincent01727e62010-12-13 12:02:40 +0530150 /* Prevent spurious wakeups */
151 writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
152 writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
153
154 nmk_chip->set_ioforce(true);
155 }
156
157 __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
158
159 if (glitch && nmk_chip->set_ioforce) {
160 nmk_chip->set_ioforce(false);
161
162 writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
163 writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
164 }
165}
166
Rabin Vincent378be062010-06-02 06:06:29 +0100167static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
Rabin Vincent01727e62010-12-13 12:02:40 +0530168 pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
Rabin Vincent378be062010-06-02 06:06:29 +0100169{
170 static const char *afnames[] = {
171 [NMK_GPIO_ALT_GPIO] = "GPIO",
172 [NMK_GPIO_ALT_A] = "A",
173 [NMK_GPIO_ALT_B] = "B",
174 [NMK_GPIO_ALT_C] = "C"
175 };
176 static const char *pullnames[] = {
177 [NMK_GPIO_PULL_NONE] = "none",
178 [NMK_GPIO_PULL_UP] = "up",
179 [NMK_GPIO_PULL_DOWN] = "down",
180 [3] /* illegal */ = "??"
181 };
182 static const char *slpmnames[] = {
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100183 [NMK_GPIO_SLPM_INPUT] = "input/wakeup",
184 [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup",
Rabin Vincent378be062010-06-02 06:06:29 +0100185 };
186
187 int pin = PIN_NUM(cfg);
188 int pull = PIN_PULL(cfg);
189 int af = PIN_ALT(cfg);
190 int slpm = PIN_SLPM(cfg);
Rabin Vincent6720db72010-09-02 11:28:48 +0100191 int output = PIN_DIR(cfg);
192 int val = PIN_VAL(cfg);
Rabin Vincent01727e62010-12-13 12:02:40 +0530193 bool glitch = af == NMK_GPIO_ALT_C;
Rabin Vincent378be062010-06-02 06:06:29 +0100194
Rabin Vincentdacdc962010-12-03 20:35:37 +0530195 dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
196 pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
Rabin Vincent6720db72010-09-02 11:28:48 +0100197 output ? "output " : "input",
198 output ? (val ? "high" : "low") : "");
Rabin Vincent378be062010-06-02 06:06:29 +0100199
Rabin Vincentdacdc962010-12-03 20:35:37 +0530200 if (sleep) {
201 int slpm_pull = PIN_SLPM_PULL(cfg);
202 int slpm_output = PIN_SLPM_DIR(cfg);
203 int slpm_val = PIN_SLPM_VAL(cfg);
204
Rabin Vincent3546d152010-11-25 11:38:27 +0530205 af = NMK_GPIO_ALT_GPIO;
206
Rabin Vincentdacdc962010-12-03 20:35:37 +0530207 /*
208 * The SLPM_* values are normal values + 1 to allow zero to
209 * mean "same as normal".
210 */
211 if (slpm_pull)
212 pull = slpm_pull - 1;
213 if (slpm_output)
214 output = slpm_output - 1;
215 if (slpm_val)
216 val = slpm_val - 1;
217
218 dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
219 pin,
220 slpm_pull ? pullnames[pull] : "same",
221 slpm_output ? (output ? "output" : "input") : "same",
222 slpm_val ? (val ? "high" : "low") : "same");
223 }
224
Rabin Vincent6720db72010-09-02 11:28:48 +0100225 if (output)
226 __nmk_gpio_make_output(nmk_chip, offset, val);
227 else {
228 __nmk_gpio_make_input(nmk_chip, offset);
229 __nmk_gpio_set_pull(nmk_chip, offset, pull);
230 }
231
Rabin Vincent01727e62010-12-13 12:02:40 +0530232 /*
233 * If we've backed up the SLPM registers (glitch workaround), modify
234 * the backups since they will be restored.
235 */
236 if (slpmregs) {
237 if (slpm == NMK_GPIO_SLPM_NOCHANGE)
238 slpmregs[nmk_chip->bank] |= BIT(offset);
239 else
240 slpmregs[nmk_chip->bank] &= ~BIT(offset);
241 } else
242 __nmk_gpio_set_slpm(nmk_chip, offset, slpm);
243
244 __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
245}
246
247/*
248 * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
249 * - Save SLPM registers
250 * - Set SLPM=0 for the IOs you want to switch and others to 1
251 * - Configure the GPIO registers for the IOs that are being switched
252 * - Set IOFORCE=1
253 * - Modify the AFLSA/B registers for the IOs that are being switched
254 * - Set IOFORCE=0
255 * - Restore SLPM registers
256 * - Any spurious wake up event during switch sequence to be ignored and
257 * cleared
258 */
259static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
260{
261 int i;
262
263 for (i = 0; i < NUM_BANKS; i++) {
264 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
265 unsigned int temp = slpm[i];
266
267 if (!chip)
268 break;
269
270 slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
271 writel(temp, chip->addr + NMK_GPIO_SLPC);
272 }
273}
274
275static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
276{
277 int i;
278
279 for (i = 0; i < NUM_BANKS; i++) {
280 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
281
282 if (!chip)
283 break;
284
285 writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
286 }
287}
288
289static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
290{
291 static unsigned int slpm[NUM_BANKS];
292 unsigned long flags;
293 bool glitch = false;
294 int ret = 0;
295 int i;
296
297 for (i = 0; i < num; i++) {
298 if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
299 glitch = true;
300 break;
301 }
302 }
303
304 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
305
306 if (glitch) {
307 memset(slpm, 0xff, sizeof(slpm));
308
309 for (i = 0; i < num; i++) {
310 int pin = PIN_NUM(cfgs[i]);
311 int offset = pin % NMK_GPIO_PER_CHIP;
312
313 if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
314 slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
315 }
316
317 nmk_gpio_glitch_slpm_init(slpm);
318 }
319
320 for (i = 0; i < num; i++) {
321 struct nmk_gpio_chip *nmk_chip;
322 int pin = PIN_NUM(cfgs[i]);
323
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100324 nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
Rabin Vincent01727e62010-12-13 12:02:40 +0530325 if (!nmk_chip) {
326 ret = -EINVAL;
327 break;
328 }
329
330 spin_lock(&nmk_chip->lock);
331 __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
332 cfgs[i], sleep, glitch ? slpm : NULL);
333 spin_unlock(&nmk_chip->lock);
334 }
335
336 if (glitch)
337 nmk_gpio_glitch_slpm_restore(slpm);
338
339 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
340
341 return ret;
Rabin Vincent378be062010-06-02 06:06:29 +0100342}
343
344/**
345 * nmk_config_pin - configure a pin's mux attributes
346 * @cfg: pin confguration
347 *
348 * Configures a pin's mode (alternate function or GPIO), its pull up status,
349 * and its sleep mode based on the specified configuration. The @cfg is
350 * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These
351 * are constructed using, and can be further enhanced with, the macros in
352 * plat/pincfg.h.
353 *
354 * If a pin's mode is set to GPIO, it is configured as an input to avoid
355 * side-effects. The gpio can be manipulated later using standard GPIO API
356 * calls.
357 */
Rabin Vincentdacdc962010-12-03 20:35:37 +0530358int nmk_config_pin(pin_cfg_t cfg, bool sleep)
Rabin Vincent378be062010-06-02 06:06:29 +0100359{
Rabin Vincent01727e62010-12-13 12:02:40 +0530360 return __nmk_config_pins(&cfg, 1, sleep);
Rabin Vincent378be062010-06-02 06:06:29 +0100361}
362EXPORT_SYMBOL(nmk_config_pin);
363
364/**
365 * nmk_config_pins - configure several pins at once
366 * @cfgs: array of pin configurations
367 * @num: number of elments in the array
368 *
369 * Configures several pins using nmk_config_pin(). Refer to that function for
370 * further information.
371 */
372int nmk_config_pins(pin_cfg_t *cfgs, int num)
373{
Rabin Vincent01727e62010-12-13 12:02:40 +0530374 return __nmk_config_pins(cfgs, num, false);
Rabin Vincent378be062010-06-02 06:06:29 +0100375}
376EXPORT_SYMBOL(nmk_config_pins);
377
Rabin Vincentdacdc962010-12-03 20:35:37 +0530378int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
379{
Rabin Vincent01727e62010-12-13 12:02:40 +0530380 return __nmk_config_pins(cfgs, num, true);
Rabin Vincentdacdc962010-12-03 20:35:37 +0530381}
382EXPORT_SYMBOL(nmk_config_pins_sleep);
383
Rabin Vincent5b327ed2010-05-27 12:29:50 +0100384/**
Rabin Vincent81a3c292010-05-27 12:39:23 +0100385 * nmk_gpio_set_slpm() - configure the sleep mode of a pin
386 * @gpio: pin number
387 * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE,
388 *
389 * Sets the sleep mode of a pin. If @mode is NMK_GPIO_SLPM_INPUT, the pin is
390 * changed to an input (with pullup/down enabled) in sleep and deep sleep. If
391 * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
392 * configured even when in sleep and deep sleep.
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100393 *
394 * On DB8500v2 onwards, this setting loses the previous meaning and instead
395 * indicates if wakeup detection is enabled on the pin. Note that
396 * enable_irq_wake() will automatically enable wakeup detection.
Rabin Vincent81a3c292010-05-27 12:39:23 +0100397 */
398int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
399{
400 struct nmk_gpio_chip *nmk_chip;
401 unsigned long flags;
402
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100403 nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
Rabin Vincent81a3c292010-05-27 12:39:23 +0100404 if (!nmk_chip)
405 return -EINVAL;
406
Rabin Vincent01727e62010-12-13 12:02:40 +0530407 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
408 spin_lock(&nmk_chip->lock);
409
Rabin Vincent81a3c292010-05-27 12:39:23 +0100410 __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
Rabin Vincent01727e62010-12-13 12:02:40 +0530411
412 spin_unlock(&nmk_chip->lock);
413 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
Rabin Vincent81a3c292010-05-27 12:39:23 +0100414
415 return 0;
416}
417
418/**
Rabin Vincent5b327ed2010-05-27 12:29:50 +0100419 * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio
420 * @gpio: pin number
421 * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE
422 *
423 * Enables/disables pull up/down on a specified pin. This only takes effect if
424 * the pin is configured as an input (either explicitly or by the alternate
425 * function).
426 *
427 * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
428 * configured as an input. Otherwise, due to the way the controller registers
429 * work, this function will change the value output on the pin.
430 */
431int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
432{
433 struct nmk_gpio_chip *nmk_chip;
434 unsigned long flags;
435
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100436 nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
Rabin Vincent5b327ed2010-05-27 12:29:50 +0100437 if (!nmk_chip)
438 return -EINVAL;
439
440 spin_lock_irqsave(&nmk_chip->lock, flags);
441 __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
442 spin_unlock_irqrestore(&nmk_chip->lock, flags);
443
444 return 0;
445}
446
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100447/* Mode functions */
Jonas Aaberg9c66ee62010-10-13 13:14:17 +0200448/**
449 * nmk_gpio_set_mode() - set the mux mode of a gpio pin
450 * @gpio: pin number
451 * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
452 * NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
453 *
454 * Sets the mode of the specified pin to one of the alternate functions or
455 * plain GPIO.
456 */
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100457int nmk_gpio_set_mode(int gpio, int gpio_mode)
458{
459 struct nmk_gpio_chip *nmk_chip;
460 unsigned long flags;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100461
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100462 nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100463 if (!nmk_chip)
464 return -EINVAL;
465
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100466 spin_lock_irqsave(&nmk_chip->lock, flags);
Rabin Vincent6f9a9742010-06-02 05:50:28 +0100467 __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100468 spin_unlock_irqrestore(&nmk_chip->lock, flags);
469
470 return 0;
471}
472EXPORT_SYMBOL(nmk_gpio_set_mode);
473
474int nmk_gpio_get_mode(int gpio)
475{
476 struct nmk_gpio_chip *nmk_chip;
477 u32 afunc, bfunc, bit;
478
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100479 nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100480 if (!nmk_chip)
481 return -EINVAL;
482
483 bit = 1 << (gpio - nmk_chip->chip.base);
484
485 afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
486 bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
487
488 return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
489}
490EXPORT_SYMBOL(nmk_gpio_get_mode);
491
492
493/* IRQ functions */
494static inline int nmk_gpio_get_bitmask(int gpio)
495{
496 return 1 << (gpio % 32);
497}
498
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100499static void nmk_gpio_irq_ack(struct irq_data *d)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100500{
501 int gpio;
502 struct nmk_gpio_chip *nmk_chip;
503
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100504 gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
505 nmk_chip = irq_data_get_irq_chip_data(d);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100506 if (!nmk_chip)
507 return;
508 writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
509}
510
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100511enum nmk_gpio_irq_type {
512 NORMAL,
513 WAKE,
514};
515
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100516static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100517 int gpio, enum nmk_gpio_irq_type which,
518 bool enable)
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100519{
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100520 u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC;
521 u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC;
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100522 u32 bitmask = nmk_gpio_get_bitmask(gpio);
523 u32 reg;
524
525 /* we must individually set/clear the two edges */
526 if (nmk_chip->edge_rising & bitmask) {
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100527 reg = readl(nmk_chip->addr + rimsc);
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100528 if (enable)
529 reg |= bitmask;
530 else
531 reg &= ~bitmask;
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100532 writel(reg, nmk_chip->addr + rimsc);
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100533 }
534 if (nmk_chip->edge_falling & bitmask) {
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100535 reg = readl(nmk_chip->addr + fimsc);
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100536 if (enable)
537 reg |= bitmask;
538 else
539 reg &= ~bitmask;
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100540 writel(reg, nmk_chip->addr + fimsc);
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100541 }
542}
543
Rabin Vincentb9df4682011-02-10 11:45:58 +0530544static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
545 int gpio, bool on)
546{
Rabin Vincentb9df4682011-02-10 11:45:58 +0530547 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
548}
549
550static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100551{
552 int gpio;
553 struct nmk_gpio_chip *nmk_chip;
554 unsigned long flags;
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100555 u32 bitmask;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100556
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100557 gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
558 nmk_chip = irq_data_get_irq_chip_data(d);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100559 bitmask = nmk_gpio_get_bitmask(gpio);
560 if (!nmk_chip)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100561 return -EINVAL;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100562
Thomas Gleixnerd1118f62011-03-24 12:38:50 +0100563 if (enable)
564 nmk_chip->enabled |= bitmask;
565 else
566 nmk_chip->enabled &= ~bitmask;
567
Rabin Vincentb9df4682011-02-10 11:45:58 +0530568 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
569 spin_lock(&nmk_chip->lock);
570
571 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
572
573 if (!(nmk_chip->real_wake & bitmask))
574 __nmk_gpio_set_wake(nmk_chip, gpio, enable);
575
576 spin_unlock(&nmk_chip->lock);
577 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100578
579 return 0;
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100580}
581
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100582static void nmk_gpio_irq_mask(struct irq_data *d)
Rabin Vincent040e5ec2010-05-06 10:42:42 +0100583{
Rabin Vincentb9df4682011-02-10 11:45:58 +0530584 nmk_gpio_irq_maskunmask(d, false);
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100585}
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100586
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100587static void nmk_gpio_irq_unmask(struct irq_data *d)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100588{
Rabin Vincentb9df4682011-02-10 11:45:58 +0530589 nmk_gpio_irq_maskunmask(d, true);
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100590}
591
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100592static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100593{
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100594 struct nmk_gpio_chip *nmk_chip;
595 unsigned long flags;
Rabin Vincentb9df4682011-02-10 11:45:58 +0530596 u32 bitmask;
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100597 int gpio;
598
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100599 gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
600 nmk_chip = irq_data_get_irq_chip_data(d);
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100601 if (!nmk_chip)
602 return -EINVAL;
Rabin Vincentb9df4682011-02-10 11:45:58 +0530603 bitmask = nmk_gpio_get_bitmask(gpio);
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100604
Rabin Vincent01727e62010-12-13 12:02:40 +0530605 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
606 spin_lock(&nmk_chip->lock);
607
Thomas Gleixnerd1118f62011-03-24 12:38:50 +0100608 if (!(nmk_chip->enabled & bitmask))
Rabin Vincentb9df4682011-02-10 11:45:58 +0530609 __nmk_gpio_set_wake(nmk_chip, gpio, on);
610
611 if (on)
612 nmk_chip->real_wake |= bitmask;
613 else
614 nmk_chip->real_wake &= ~bitmask;
Rabin Vincent01727e62010-12-13 12:02:40 +0530615
616 spin_unlock(&nmk_chip->lock);
617 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
Rabin Vincent7e3f7e52010-09-02 11:28:05 +0100618
619 return 0;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100620}
621
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100622static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100623{
Thomas Gleixnerd1118f62011-03-24 12:38:50 +0100624 bool enabled, wake = irqd_is_wakeup_set(d);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100625 int gpio;
626 struct nmk_gpio_chip *nmk_chip;
627 unsigned long flags;
628 u32 bitmask;
629
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100630 gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
631 nmk_chip = irq_data_get_irq_chip_data(d);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100632 bitmask = nmk_gpio_get_bitmask(gpio);
633 if (!nmk_chip)
634 return -EINVAL;
635
636 if (type & IRQ_TYPE_LEVEL_HIGH)
637 return -EINVAL;
638 if (type & IRQ_TYPE_LEVEL_LOW)
639 return -EINVAL;
640
Thomas Gleixnerd1118f62011-03-24 12:38:50 +0100641 enabled = nmk_chip->enabled & bitmask;
642
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100643 spin_lock_irqsave(&nmk_chip->lock, flags);
644
Rabin Vincent7a852d82010-05-06 10:43:55 +0100645 if (enabled)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100646 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
647
Rabin Vincentb9df4682011-02-10 11:45:58 +0530648 if (enabled || wake)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100649 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
Rabin Vincent7a852d82010-05-06 10:43:55 +0100650
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100651 nmk_chip->edge_rising &= ~bitmask;
652 if (type & IRQ_TYPE_EDGE_RISING)
653 nmk_chip->edge_rising |= bitmask;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100654
655 nmk_chip->edge_falling &= ~bitmask;
656 if (type & IRQ_TYPE_EDGE_FALLING)
657 nmk_chip->edge_falling |= bitmask;
Rabin Vincent7a852d82010-05-06 10:43:55 +0100658
659 if (enabled)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100660 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
661
Rabin Vincentb9df4682011-02-10 11:45:58 +0530662 if (enabled || wake)
Rabin Vincent4d4e20f2010-06-16 06:09:34 +0100663 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100664
665 spin_unlock_irqrestore(&nmk_chip->lock, flags);
666
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100667 return 0;
668}
669
670static struct irq_chip nmk_gpio_irq_chip = {
671 .name = "Nomadik-GPIO",
Lennert Buytenhekf272c002010-11-29 11:16:48 +0100672 .irq_ack = nmk_gpio_irq_ack,
673 .irq_mask = nmk_gpio_irq_mask,
674 .irq_unmask = nmk_gpio_irq_unmask,
675 .irq_set_type = nmk_gpio_irq_set_type,
676 .irq_set_wake = nmk_gpio_irq_set_wake,
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100677};
678
Rabin Vincent33b744b2010-10-14 10:38:03 +0530679static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
680 u32 status)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100681{
682 struct nmk_gpio_chip *nmk_chip;
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100683 struct irq_chip *host_chip = irq_get_chip(irq);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100684 unsigned int first_irq;
685
Will Deaconadfed152011-02-28 10:12:29 +0000686 chained_irq_enter(host_chip, desc);
Rabin Vincentaaedaa22010-03-03 04:50:27 +0100687
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100688 nmk_chip = irq_get_handler_data(irq);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100689 first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
Rabin Vincent33b744b2010-10-14 10:38:03 +0530690 while (status) {
691 int bit = __ffs(status);
692
693 generic_handle_irq(first_irq + bit);
694 status &= ~BIT(bit);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100695 }
Rabin Vincentaaedaa22010-03-03 04:50:27 +0100696
Will Deaconadfed152011-02-28 10:12:29 +0000697 chained_irq_exit(host_chip, desc);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100698}
699
Rabin Vincent33b744b2010-10-14 10:38:03 +0530700static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
701{
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100702 struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
Rabin Vincent33b744b2010-10-14 10:38:03 +0530703 u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
704
705 __nmk_gpio_irq_handler(irq, desc, status);
706}
707
708static void nmk_gpio_secondary_irq_handler(unsigned int irq,
709 struct irq_desc *desc)
710{
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100711 struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
Rabin Vincent33b744b2010-10-14 10:38:03 +0530712 u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
713
714 __nmk_gpio_irq_handler(irq, desc, status);
715}
716
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100717static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
718{
719 unsigned int first_irq;
720 int i;
721
722 first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
Rabin Vincente493e062010-03-18 12:35:22 +0530723 for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
Thomas Gleixnerf38c02f2011-03-24 13:35:09 +0100724 irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
725 handle_edge_irq);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100726 set_irq_flags(i, IRQF_VALID);
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100727 irq_set_chip_data(i, nmk_chip);
728 irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100729 }
Rabin Vincent33b744b2010-10-14 10:38:03 +0530730
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100731 irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
732 irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
Rabin Vincent33b744b2010-10-14 10:38:03 +0530733
734 if (nmk_chip->secondary_parent_irq >= 0) {
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100735 irq_set_chained_handler(nmk_chip->secondary_parent_irq,
Rabin Vincent33b744b2010-10-14 10:38:03 +0530736 nmk_gpio_secondary_irq_handler);
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100737 irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
Rabin Vincent33b744b2010-10-14 10:38:03 +0530738 }
739
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100740 return 0;
741}
742
743/* I/O Functions */
744static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
745{
746 struct nmk_gpio_chip *nmk_chip =
747 container_of(chip, struct nmk_gpio_chip, chip);
748
749 writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
750 return 0;
751}
752
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100753static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
754{
755 struct nmk_gpio_chip *nmk_chip =
756 container_of(chip, struct nmk_gpio_chip, chip);
757 u32 bit = 1 << offset;
758
759 return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
760}
761
762static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
763 int val)
764{
765 struct nmk_gpio_chip *nmk_chip =
766 container_of(chip, struct nmk_gpio_chip, chip);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100767
Rabin Vincent6720db72010-09-02 11:28:48 +0100768 __nmk_gpio_set_output(nmk_chip, offset, val);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100769}
770
Rabin Vincent6647c6c2010-05-27 12:22:42 +0100771static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
772 int val)
773{
774 struct nmk_gpio_chip *nmk_chip =
775 container_of(chip, struct nmk_gpio_chip, chip);
776
Rabin Vincent6720db72010-09-02 11:28:48 +0100777 __nmk_gpio_make_output(nmk_chip, offset, val);
Rabin Vincent6647c6c2010-05-27 12:22:42 +0100778
779 return 0;
780}
781
Rabin Vincent0d2aec92010-06-16 06:10:43 +0100782static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
783{
784 struct nmk_gpio_chip *nmk_chip =
785 container_of(chip, struct nmk_gpio_chip, chip);
786
787 return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
788}
789
Rabin Vincentd0b543c2010-03-04 17:39:05 +0530790#ifdef CONFIG_DEBUG_FS
791
792#include <linux/seq_file.h>
793
794static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
795{
796 int mode;
797 unsigned i;
798 unsigned gpio = chip->base;
799 int is_out;
800 struct nmk_gpio_chip *nmk_chip =
801 container_of(chip, struct nmk_gpio_chip, chip);
802 const char *modes[] = {
803 [NMK_GPIO_ALT_GPIO] = "gpio",
804 [NMK_GPIO_ALT_A] = "altA",
805 [NMK_GPIO_ALT_B] = "altB",
806 [NMK_GPIO_ALT_C] = "altC",
807 };
808
809 for (i = 0; i < chip->ngpio; i++, gpio++) {
810 const char *label = gpiochip_is_requested(chip, i);
811 bool pull;
812 u32 bit = 1 << i;
813
Rabin Vincentd0b543c2010-03-04 17:39:05 +0530814 is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
815 pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
816 mode = nmk_gpio_get_mode(gpio);
817 seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
Rabin Vincent8ea72a32011-05-24 23:07:09 +0200818 gpio, label ?: "(none)",
Rabin Vincentd0b543c2010-03-04 17:39:05 +0530819 is_out ? "out" : "in ",
820 chip->get
821 ? (chip->get(chip, i) ? "hi" : "lo")
822 : "? ",
823 (mode < 0) ? "unknown" : modes[mode],
824 pull ? "pull" : "none");
Rabin Vincent8ea72a32011-05-24 23:07:09 +0200825
826 if (label && !is_out) {
827 int irq = gpio_to_irq(gpio);
828 struct irq_desc *desc = irq_to_desc(irq);
829
830 /* This races with request_irq(), set_irq_type(),
831 * and set_irq_wake() ... but those are "rare".
832 */
833 if (irq >= 0 && desc->action) {
834 char *trigger;
835 u32 bitmask = nmk_gpio_get_bitmask(gpio);
836
837 if (nmk_chip->edge_rising & bitmask)
838 trigger = "edge-rising";
839 else if (nmk_chip->edge_falling & bitmask)
840 trigger = "edge-falling";
841 else
842 trigger = "edge-undefined";
843
844 seq_printf(s, " irq-%d %s%s",
845 irq, trigger,
846 irqd_is_wakeup_set(&desc->irq_data)
847 ? " wakeup" : "");
848 }
849 }
850
Rabin Vincentd0b543c2010-03-04 17:39:05 +0530851 seq_printf(s, "\n");
852 }
853}
854
855#else
856#define nmk_gpio_dbg_show NULL
857#endif
858
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100859/* This structure is replicated for each GPIO block allocated at probe time */
860static struct gpio_chip nmk_gpio_template = {
861 .direction_input = nmk_gpio_make_input,
862 .get = nmk_gpio_get_input,
863 .direction_output = nmk_gpio_make_output,
864 .set = nmk_gpio_set_output,
Rabin Vincent0d2aec92010-06-16 06:10:43 +0100865 .to_irq = nmk_gpio_to_irq,
Rabin Vincentd0b543c2010-03-04 17:39:05 +0530866 .dbg_show = nmk_gpio_dbg_show,
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100867 .can_sleep = 0,
868};
869
Rabin Vincentb9df4682011-02-10 11:45:58 +0530870/*
871 * Called from the suspend/resume path to only keep the real wakeup interrupts
872 * (those that have had set_irq_wake() called on them) as wakeup interrupts,
873 * and not the rest of the interrupts which we needed to have as wakeups for
874 * cpuidle.
875 *
876 * PM ops are not used since this needs to be done at the end, after all the
877 * other drivers are done with their suspend callbacks.
878 */
879void nmk_gpio_wakeups_suspend(void)
880{
881 int i;
882
883 for (i = 0; i < NUM_BANKS; i++) {
884 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
885
886 if (!chip)
887 break;
888
889 chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
890 chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
891
892 writel(chip->rwimsc & chip->real_wake,
893 chip->addr + NMK_GPIO_RWIMSC);
894 writel(chip->fwimsc & chip->real_wake,
895 chip->addr + NMK_GPIO_FWIMSC);
896
897 if (cpu_is_u8500v2()) {
898 chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
899
900 /* 0 -> wakeup enable */
901 writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
902 }
903 }
904}
905
906void nmk_gpio_wakeups_resume(void)
907{
908 int i;
909
910 for (i = 0; i < NUM_BANKS; i++) {
911 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
912
913 if (!chip)
914 break;
915
916 writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
917 writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
918
919 if (cpu_is_u8500v2())
920 writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
921 }
922}
923
Uwe Kleine-Königfd0d67d2010-09-02 16:13:35 +0100924static int __devinit nmk_gpio_probe(struct platform_device *dev)
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100925{
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100926 struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100927 struct nmk_gpio_chip *nmk_chip;
928 struct gpio_chip *chip;
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100929 struct resource *res;
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100930 struct clk *clk;
Rabin Vincent33b744b2010-10-14 10:38:03 +0530931 int secondary_irq;
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100932 int irq;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100933 int ret;
934
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100935 if (!pdata)
936 return -ENODEV;
937
938 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
939 if (!res) {
940 ret = -ENOENT;
941 goto out;
942 }
943
944 irq = platform_get_irq(dev, 0);
945 if (irq < 0) {
946 ret = irq;
947 goto out;
948 }
949
Rabin Vincent33b744b2010-10-14 10:38:03 +0530950 secondary_irq = platform_get_irq(dev, 1);
951 if (secondary_irq >= 0 && !pdata->get_secondary_status) {
952 ret = -EINVAL;
953 goto out;
954 }
955
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100956 if (request_mem_region(res->start, resource_size(res),
957 dev_name(&dev->dev)) == NULL) {
958 ret = -EBUSY;
959 goto out;
960 }
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100961
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100962 clk = clk_get(&dev->dev, NULL);
963 if (IS_ERR(clk)) {
964 ret = PTR_ERR(clk);
965 goto out_release;
966 }
967
968 clk_enable(clk);
969
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100970 nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
971 if (!nmk_chip) {
972 ret = -ENOMEM;
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100973 goto out_clk;
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100974 }
975 /*
976 * The virt address in nmk_chip->addr is in the nomadik register space,
977 * so we can simply convert the resource address, without remapping
978 */
Rabin Vincent33b744b2010-10-14 10:38:03 +0530979 nmk_chip->bank = dev->id;
Rabin Vincentaf7dc222010-05-06 11:14:17 +0100980 nmk_chip->clk = clk;
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100981 nmk_chip->addr = io_p2v(res->start);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100982 nmk_chip->chip = nmk_gpio_template;
Rabin Vincent3e3c62c2010-03-03 04:52:34 +0100983 nmk_chip->parent_irq = irq;
Rabin Vincent33b744b2010-10-14 10:38:03 +0530984 nmk_chip->secondary_parent_irq = secondary_irq;
985 nmk_chip->get_secondary_status = pdata->get_secondary_status;
Rabin Vincent01727e62010-12-13 12:02:40 +0530986 nmk_chip->set_ioforce = pdata->set_ioforce;
Rabin Vincentc0fcb8d2010-03-03 04:48:54 +0100987 spin_lock_init(&nmk_chip->lock);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100988
989 chip = &nmk_chip->chip;
990 chip->base = pdata->first_gpio;
Rabin Vincente493e062010-03-18 12:35:22 +0530991 chip->ngpio = pdata->num_gpio;
Rabin Vincent8d568ae2010-12-08 11:07:54 +0530992 chip->label = pdata->name ?: dev_name(&dev->dev);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +0100993 chip->dev = &dev->dev;
994 chip->owner = THIS_MODULE;
995
996 ret = gpiochip_add(&nmk_chip->chip);
997 if (ret)
998 goto out_free;
999
Rabin Vincent01727e62010-12-13 12:02:40 +05301000 BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
1001
1002 nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
Rabin Vincent3e3c62c2010-03-03 04:52:34 +01001003 platform_set_drvdata(dev, nmk_chip);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001004
1005 nmk_gpio_init_irq(nmk_chip);
1006
1007 dev_info(&dev->dev, "Bits %i-%i at address %p\n",
1008 nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr);
1009 return 0;
1010
Rabin Vincent3e3c62c2010-03-03 04:52:34 +01001011out_free:
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001012 kfree(nmk_chip);
Rabin Vincentaf7dc222010-05-06 11:14:17 +01001013out_clk:
1014 clk_disable(clk);
1015 clk_put(clk);
Rabin Vincent3e3c62c2010-03-03 04:52:34 +01001016out_release:
1017 release_mem_region(res->start, resource_size(res));
1018out:
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001019 dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
1020 pdata->first_gpio, pdata->first_gpio+31);
1021 return ret;
1022}
1023
Rabin Vincent3e3c62c2010-03-03 04:52:34 +01001024static struct platform_driver nmk_gpio_driver = {
1025 .driver = {
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001026 .owner = THIS_MODULE,
1027 .name = "gpio",
Rabin Vincent5317e4d12011-02-10 09:29:53 +05301028 },
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001029 .probe = nmk_gpio_probe,
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001030};
1031
1032static int __init nmk_gpio_init(void)
1033{
Rabin Vincent3e3c62c2010-03-03 04:52:34 +01001034 return platform_driver_register(&nmk_gpio_driver);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001035}
1036
Rabin Vincent33f45ea2010-06-02 06:09:52 +01001037core_initcall(nmk_gpio_init);
Alessandro Rubini2ec1d352009-07-02 15:29:12 +01001038
1039MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
1040MODULE_DESCRIPTION("Nomadik GPIO Driver");
1041MODULE_LICENSE("GPL");
1042
1043