Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[wrt350n-kernel.git] / arch / arm / mach-ns9xxx / gpio.c
blobf9581f25f46ec7c9627912ff6fdfe6f55bf99292
1 /*
2 * arch/arm/mach-ns9xxx/gpio.c
4 * Copyright (C) 2006 by Digi International Inc.
5 * All rights reserved.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 #include <linux/compiler.h>
12 #include <linux/init.h>
13 #include <linux/spinlock.h>
14 #include <linux/module.h>
16 #include <asm/arch-ns9xxx/gpio.h>
17 #include <asm/arch-ns9xxx/processor.h>
18 #include <asm/arch-ns9xxx/regs-bbu.h>
19 #include <asm/io.h>
20 #include <asm/bug.h>
21 #include <asm/types.h>
22 #include <asm/bitops.h>
24 #if defined(CONFIG_PROCESSOR_NS9360)
25 #define GPIO_MAX 72
26 #elif defined(CONFIG_PROCESSOR_NS9750)
27 #define GPIO_MAX 49
28 #endif
30 /* protects BBU_GCONFx and BBU_GCTRLx */
31 static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);
33 /* only access gpiores with atomic ops */
34 <<<<<<< HEAD:arch/arm/mach-ns9xxx/gpio.c
35 static DECLARE_BITMAP(gpiores, GPIO_MAX);
36 =======
37 static DECLARE_BITMAP(gpiores, GPIO_MAX + 1);
38 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:arch/arm/mach-ns9xxx/gpio.c
40 static inline int ns9xxx_valid_gpio(unsigned gpio)
42 #if defined(CONFIG_PROCESSOR_NS9360)
43 if (processor_is_ns9360())
44 return gpio <= 72;
45 else
46 #endif
47 #if defined(CONFIG_PROCESSOR_NS9750)
48 if (processor_is_ns9750())
49 return gpio <= 49;
50 else
51 #endif
52 BUG();
55 static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
57 if (gpio < 56)
58 return BBU_GCONFb1(gpio / 8);
59 else
61 * this could be optimised away on
62 * ns9750 only builds, but it isn't ...
64 return BBU_GCONFb2((gpio - 56) / 8);
67 static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
69 if (gpio < 32)
70 return BBU_GCTRL1;
71 else if (gpio < 64)
72 return BBU_GCTRL2;
73 else
74 /* this could be optimised away on ns9750 only builds */
75 return BBU_GCTRL3;
78 static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
80 if (gpio < 32)
81 return BBU_GSTAT1;
82 else if (gpio < 64)
83 return BBU_GSTAT2;
84 else
85 /* this could be optimised away on ns9750 only builds */
86 return BBU_GSTAT3;
89 int gpio_request(unsigned gpio, const char *label)
91 if (likely(ns9xxx_valid_gpio(gpio)))
92 return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
93 else
94 return -EINVAL;
96 EXPORT_SYMBOL(gpio_request);
98 void gpio_free(unsigned gpio)
100 clear_bit(gpio, gpiores);
101 return;
103 EXPORT_SYMBOL(gpio_free);
106 * each gpio can serve for 4 different purposes [0..3]. These are called
107 * "functions" and passed in the parameter func. Functions 0-2 are always some
108 * special things, function 3 is GPIO. If func == 3 dir specifies input or
109 * output, and with inv you can enable an inverter (independent of func).
111 static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
113 void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
114 u32 confval;
115 unsigned long flags;
117 spin_lock_irqsave(&gpio_lock, flags);
119 confval = __raw_readl(conf);
120 REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
121 REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
122 REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
123 __raw_writel(confval, conf);
125 spin_unlock_irqrestore(&gpio_lock, flags);
127 return 0;
130 int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
132 if (likely(ns9xxx_valid_gpio(gpio))) {
133 if (func == 3) {
134 printk(KERN_WARNING "use gpio_direction_input "
135 "or gpio_direction_output\n");
136 return -EINVAL;
137 } else
138 return __ns9xxx_gpio_configure(gpio, 0, inv, func);
139 } else
140 return -EINVAL;
142 EXPORT_SYMBOL(ns9xxx_gpio_configure);
144 int gpio_direction_input(unsigned gpio)
146 if (likely(ns9xxx_valid_gpio(gpio))) {
147 return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
148 } else
149 return -EINVAL;
151 EXPORT_SYMBOL(gpio_direction_input);
153 int gpio_direction_output(unsigned gpio, int value)
155 if (likely(ns9xxx_valid_gpio(gpio))) {
156 gpio_set_value(gpio, value);
158 return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
159 } else
160 return -EINVAL;
162 EXPORT_SYMBOL(gpio_direction_output);
164 int gpio_get_value(unsigned gpio)
166 void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
167 int ret;
169 ret = 1 & (__raw_readl(stat) >> (gpio & 31));
171 return ret;
173 EXPORT_SYMBOL(gpio_get_value);
175 void gpio_set_value(unsigned gpio, int value)
177 void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
178 u32 ctrlval;
179 unsigned long flags;
181 spin_lock_irqsave(&gpio_lock, flags);
183 ctrlval = __raw_readl(ctrl);
185 if (value)
186 ctrlval |= 1 << (gpio & 31);
187 else
188 ctrlval &= ~(1 << (gpio & 31));
190 __raw_writel(ctrlval, ctrl);
192 spin_unlock_irqrestore(&gpio_lock, flags);
194 EXPORT_SYMBOL(gpio_set_value);