aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-bf548
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2007-08-28 04:47:46 -0400
committerBryan Wu <bryan.wu@analog.com>2007-08-28 04:47:46 -0400
commitd2b11a468a49716debd96532552a72b6078f1cf5 (patch)
treeb30d94732f9d01b823e60975147b284aead495d9 /arch/blackfin/mach-bf548
parent2296fb7ff04531dd8d50394da24f49302ecf103b (diff)
Blackfin arch: Merge GPIO/Peripheral Resource Allocation back into a single file
Signed-off-by: Michael Hennerich <michale.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/mach-bf548')
-rw-r--r--arch/blackfin/mach-bf548/Makefile2
-rw-r--r--arch/blackfin/mach-bf548/gpio.c392
2 files changed, 1 insertions, 393 deletions
diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
index 060ad78ebf1d..7e7c9c8ac5b2 100644
--- a/arch/blackfin/mach-bf548/Makefile
+++ b/arch/blackfin/mach-bf548/Makefile
@@ -4,6 +4,6 @@
4 4
5extra-y := head.o 5extra-y := head.o
6 6
7obj-y := ints-priority.o dma.o gpio.o 7obj-y := ints-priority.o dma.o
8 8
9obj-$(CONFIG_CPU_FREQ) += cpu.o 9obj-$(CONFIG_CPU_FREQ) += cpu.o
diff --git a/arch/blackfin/mach-bf548/gpio.c b/arch/blackfin/mach-bf548/gpio.c
deleted file mode 100644
index 390dd8c12430..000000000000
--- a/arch/blackfin/mach-bf548/gpio.c
+++ /dev/null
@@ -1,392 +0,0 @@
1/*
2 * File: arch/blackfin/mach-bf548/gpio.c
3 * Based on:
4 * Author: Michael Hennerich (hennerich@blackfin.uclinux.org)
5 *
6 * Created:
7 * Description: GPIO Abstraction Layer
8 *
9 * Modified:
10 * Copyright 2007 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <linux/module.h>
31#include <linux/err.h>
32#include <asm/blackfin.h>
33#include <asm/gpio.h>
34#include <asm/portmux.h>
35#include <linux/irq.h>
36
37static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
38 (struct gpio_port_t *)PORTA_FER,
39 (struct gpio_port_t *)PORTB_FER,
40 (struct gpio_port_t *)PORTC_FER,
41 (struct gpio_port_t *)PORTD_FER,
42 (struct gpio_port_t *)PORTE_FER,
43 (struct gpio_port_t *)PORTF_FER,
44 (struct gpio_port_t *)PORTG_FER,
45 (struct gpio_port_t *)PORTH_FER,
46 (struct gpio_port_t *)PORTI_FER,
47 (struct gpio_port_t *)PORTJ_FER,
48};
49
50static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
51static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
52
53#define MAX_RESOURCES 256
54#define RESOURCE_LABEL_SIZE 16
55
56struct str_ident {
57 char name[RESOURCE_LABEL_SIZE];
58} *str_ident;
59
60inline int check_gpio(unsigned short gpio)
61{
62 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
63 || gpio == GPIO_PH14 || gpio == GPIO_PH15
64 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
65 || gpio > MAX_BLACKFIN_GPIOS)
66 return -EINVAL;
67 return 0;
68}
69
70inline void portmux_setup(unsigned short portno, unsigned short function)
71{
72 u32 pmux;
73
74 pmux = gpio_array[gpio_bank(portno)]->port_mux;
75
76 pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
77 pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
78
79 gpio_array[gpio_bank(portno)]->port_mux = pmux;
80}
81
82inline u16 get_portmux(unsigned short portno)
83{
84 u32 pmux;
85
86 pmux = gpio_array[gpio_bank(portno)]->port_mux;
87
88 return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
89}
90
91static void port_setup(unsigned short gpio, unsigned short usage)
92{
93 if (usage == GPIO_USAGE) {
94 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
95 } else
96 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
97 SSYNC();
98}
99
100static int __init bfin_gpio_init(void)
101{
102
103 str_ident = kcalloc(MAX_RESOURCES,
104 sizeof(struct str_ident), GFP_KERNEL);
105 if (str_ident == NULL)
106 return -ENOMEM;
107
108 memset(str_ident, 0, MAX_RESOURCES * sizeof(struct str_ident));
109
110 printk(KERN_INFO "Blackfin GPIO Controller\n");
111
112 return 0;
113}
114
115arch_initcall(bfin_gpio_init);
116
117static void set_label(unsigned short ident, const char *label)
118{
119
120 if (label && str_ident) {
121 strncpy(str_ident[ident].name, label,
122 RESOURCE_LABEL_SIZE);
123 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
124 }
125}
126
127static char *get_label(unsigned short ident)
128{
129 if (!str_ident)
130 return "UNKNOWN";
131
132 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
133}
134
135static int cmp_label(unsigned short ident, const char *label)
136{
137 if (label && str_ident)
138 return strncmp(str_ident[ident].name,
139 label, strlen(label));
140 else
141 return -EINVAL;
142}
143
144int peripheral_request(unsigned short per, const char *label)
145{
146 unsigned long flags;
147 unsigned short ident = P_IDENT(per);
148
149 /*
150 * Don't cares are pins with only one dedicated function
151 */
152
153 if (per & P_DONTCARE)
154 return 0;
155
156 if (!(per & P_DEFINED))
157 return -ENODEV;
158
159 if (check_gpio(ident) < 0)
160 return -EINVAL;
161
162 local_irq_save(flags);
163
164 if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
165 printk(KERN_ERR
166 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
167 __FUNCTION__, ident, get_label(ident));
168 dump_stack();
169 local_irq_restore(flags);
170 return -EBUSY;
171 }
172
173 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
174
175 u16 funct = get_portmux(ident);
176
177 /*
178 * Pin functions like AMC address strobes my
179 * be requested and used by several drivers
180 */
181
182 if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
183
184 /*
185 * Allow that the identical pin function can
186 * be requested from the same driver twice
187 */
188
189 if (cmp_label(ident, label) == 0)
190 goto anyway;
191
192 printk(KERN_ERR
193 "%s: Peripheral %d function %d is already reserved by %s !\n",
194 __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
195 dump_stack();
196 local_irq_restore(flags);
197 return -EBUSY;
198 }
199 }
200
201anyway:
202 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
203
204 portmux_setup(ident, P_FUNCT2MUX(per));
205 port_setup(ident, PERIPHERAL_USAGE);
206
207 local_irq_restore(flags);
208 set_label(ident, label);
209
210 return 0;
211}
212EXPORT_SYMBOL(peripheral_request);
213
214int peripheral_request_list(unsigned short per[], const char *label)
215{
216 u16 cnt;
217 int ret;
218
219 for (cnt = 0; per[cnt] != 0; cnt++) {
220
221 ret = peripheral_request(per[cnt], label);
222
223 if (ret < 0) {
224 for ( ; cnt > 0; cnt--) {
225 peripheral_free(per[cnt - 1]);
226 }
227 return ret;
228 }
229 }
230
231
232 return 0;
233}
234EXPORT_SYMBOL(peripheral_request_list);
235
236void peripheral_free(unsigned short per)
237{
238 unsigned long flags;
239 unsigned short ident = P_IDENT(per);
240
241 if (per & P_DONTCARE)
242 return;
243
244 if (!(per & P_DEFINED))
245 return;
246
247 if (check_gpio(ident) < 0)
248 return;
249
250 local_irq_save(flags);
251
252 if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
253 local_irq_restore(flags);
254 return;
255 }
256
257 if (!(per & P_MAYSHARE)) {
258 port_setup(ident, GPIO_USAGE);
259 }
260
261 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
262
263 local_irq_restore(flags);
264}
265EXPORT_SYMBOL(peripheral_free);
266
267void peripheral_free_list(unsigned short per[])
268{
269 u16 cnt;
270
271 for (cnt = 0; per[cnt] != 0; cnt++) {
272 peripheral_free(per[cnt]);
273 }
274
275}
276EXPORT_SYMBOL(peripheral_free_list);
277
278/***********************************************************
279*
280* FUNCTIONS: Blackfin GPIO Driver
281*
282* INPUTS/OUTPUTS:
283* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
284*
285*
286* DESCRIPTION: Blackfin GPIO Driver API
287*
288* CAUTION:
289*************************************************************
290* MODIFICATION HISTORY :
291**************************************************************/
292
293int gpio_request(unsigned short gpio, const char *label)
294{
295 unsigned long flags;
296
297 if (check_gpio(gpio) < 0)
298 return -EINVAL;
299
300 local_irq_save(flags);
301
302 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
303 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
304 gpio, get_label(gpio));
305 dump_stack();
306 local_irq_restore(flags);
307 return -EBUSY;
308 }
309
310 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
311 printk(KERN_ERR
312 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
313 gpio, get_label(gpio));
314 dump_stack();
315 local_irq_restore(flags);
316 return -EBUSY;
317 }
318
319 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
320
321 local_irq_restore(flags);
322
323 port_setup(gpio, GPIO_USAGE);
324 set_label(gpio, label);
325
326 return 0;
327}
328EXPORT_SYMBOL(gpio_request);
329
330void gpio_free(unsigned short gpio)
331{
332 unsigned long flags;
333
334 if (check_gpio(gpio) < 0)
335 return;
336
337 local_irq_save(flags);
338
339 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
340 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
341 dump_stack();
342 local_irq_restore(flags);
343 return;
344 }
345
346 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
347
348 local_irq_restore(flags);
349}
350EXPORT_SYMBOL(gpio_free);
351
352void gpio_direction_input(unsigned short gpio)
353{
354 unsigned long flags;
355
356 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
357
358 local_irq_save(flags);
359 gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
360 gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
361 local_irq_restore(flags);
362}
363EXPORT_SYMBOL(gpio_direction_input);
364
365void gpio_direction_output(unsigned short gpio)
366{
367 unsigned long flags;
368
369 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
370
371 local_irq_save(flags);
372 gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
373 gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
374 local_irq_restore(flags);
375}
376EXPORT_SYMBOL(gpio_direction_output);
377
378void gpio_set_value(unsigned short gpio, unsigned short arg)
379{
380 if (arg)
381 gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
382 else
383 gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
384
385}
386EXPORT_SYMBOL(gpio_set_value);
387
388unsigned short gpio_get_value(unsigned short gpio)
389{
390 return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
391}
392EXPORT_SYMBOL(gpio_get_value);