aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/blackfin/kernel/Makefile4
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c225
-rw-r--r--arch/blackfin/mach-bf548/Makefile2
-rw-r--r--arch/blackfin/mach-bf548/gpio.c392
4 files changed, 216 insertions, 407 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index ae0a2203c3da..243883ec6de1 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,10 +7,8 @@ extra-y := init_task.o vmlinux.lds
7obj-y := \ 7obj-y := \
8 entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \ 8 entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
9 sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \ 9 sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
10 fixed_code.o cplbinit.o cacheinit.o reboot.o 10 fixed_code.o cplbinit.o cacheinit.o reboot.o bfin_gpio.o
11 11
12obj-$(CONFIG_BF53x) += bfin_gpio.o
13obj-$(CONFIG_BF561) += bfin_gpio.o
14obj-$(CONFIG_MODULES) += module.o 12obj-$(CONFIG_MODULES) += module.o
15obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o 13obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
16obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o 14obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 0d1e87b9c93d..78438d88d22a 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -7,7 +7,7 @@
7 * Description: GPIO Abstraction Layer 7 * Description: GPIO Abstraction Layer
8 * 8 *
9 * Modified: 9 * Modified:
10 * Copyright 2006 Analog Devices Inc. 10 * Copyright 2007 Analog Devices Inc.
11 * 11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 * 13 *
@@ -28,9 +28,9 @@
28 */ 28 */
29 29
30/* 30/*
31* Number BF537/6/4 BF561 BF533/2/1 31* Number BF537/6/4 BF561 BF533/2/1 BF549/8/4/2
32* 32*
33* GPIO_0 PF0 PF0 PF0 33* GPIO_0 PF0 PF0 PF0 PA0...PJ13
34* GPIO_1 PF1 PF1 PF1 34* GPIO_1 PF1 PF1 PF1
35* GPIO_2 PF2 PF2 PF2 35* GPIO_2 PF2 PF2 PF2
36* GPIO_3 PF3 PF3 PF3 36* GPIO_3 PF3 PF3 PF3
@@ -117,6 +117,21 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
117}; 117};
118#endif 118#endif
119 119
120#ifdef BF548_FAMILY
121static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
122 (struct gpio_port_t *)PORTA_FER,
123 (struct gpio_port_t *)PORTB_FER,
124 (struct gpio_port_t *)PORTC_FER,
125 (struct gpio_port_t *)PORTD_FER,
126 (struct gpio_port_t *)PORTE_FER,
127 (struct gpio_port_t *)PORTF_FER,
128 (struct gpio_port_t *)PORTG_FER,
129 (struct gpio_port_t *)PORTH_FER,
130 (struct gpio_port_t *)PORTI_FER,
131 (struct gpio_port_t *)PORTJ_FER,
132};
133#endif
134
120static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 135static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
121static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; 136static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)];
122 137
@@ -147,12 +162,24 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INT
147 162
148#endif /* CONFIG_PM */ 163#endif /* CONFIG_PM */
149 164
165#if defined(BF548_FAMILY)
166inline int check_gpio(unsigned short gpio)
167{
168 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
169 || gpio == GPIO_PH14 || gpio == GPIO_PH15
170 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
171 || gpio > MAX_BLACKFIN_GPIOS)
172 return -EINVAL;
173 return 0;
174}
175#else
150inline int check_gpio(unsigned short gpio) 176inline int check_gpio(unsigned short gpio)
151{ 177{
152 if (gpio >= MAX_BLACKFIN_GPIOS) 178 if (gpio >= MAX_BLACKFIN_GPIOS)
153 return -EINVAL; 179 return -EINVAL;
154 return 0; 180 return 0;
155} 181}
182#endif
156 183
157static void set_label(unsigned short ident, const char *label) 184static void set_label(unsigned short ident, const char *label)
158{ 185{
@@ -185,19 +212,27 @@ static int cmp_label(unsigned short ident, const char *label)
185static void port_setup(unsigned short gpio, unsigned short usage) 212static void port_setup(unsigned short gpio, unsigned short usage)
186{ 213{
187 if (!check_gpio(gpio)) { 214 if (!check_gpio(gpio)) {
188 if (usage == GPIO_USAGE) { 215 if (usage == GPIO_USAGE)
189 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); 216 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
190 } else 217 else
191 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); 218 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
192 SSYNC(); 219 SSYNC();
193 } 220 }
194} 221}
222#elif defined(BF548_FAMILY)
223static void port_setup(unsigned short gpio, unsigned short usage)
224{
225 if (usage == GPIO_USAGE)
226 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
227 else
228 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
229 SSYNC();
230}
195#else 231#else
196# define port_setup(...) do { } while (0) 232# define port_setup(...) do { } while (0)
197#endif 233#endif
198 234
199#ifdef BF537_FAMILY 235#ifdef BF537_FAMILY
200
201static struct { 236static struct {
202 unsigned short res; 237 unsigned short res;
203 unsigned short offset; 238 unsigned short offset;
@@ -268,11 +303,32 @@ static void portmux_setup(unsigned short per, unsigned short function)
268 } 303 }
269 } 304 }
270} 305}
306#elif defined(BF548_FAMILY)
307inline void portmux_setup(unsigned short portno, unsigned short function)
308{
309 u32 pmux;
310
311 pmux = gpio_array[gpio_bank(portno)]->port_mux;
312
313 pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
314 pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
315
316 gpio_array[gpio_bank(portno)]->port_mux = pmux;
317}
318
319inline u16 get_portmux(unsigned short portno)
320{
321 u32 pmux;
271 322
323 pmux = gpio_array[gpio_bank(portno)]->port_mux;
324
325 return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
326}
272#else 327#else
273# define portmux_setup(...) do { } while (0) 328# define portmux_setup(...) do { } while (0)
274#endif 329#endif
275 330
331#ifndef BF548_FAMILY
276static void default_gpio(unsigned short gpio) 332static void default_gpio(unsigned short gpio)
277{ 333{
278 unsigned short bank, bitmask; 334 unsigned short bank, bitmask;
@@ -289,6 +345,9 @@ static void default_gpio(unsigned short gpio)
289 gpio_bankb[bank]->both &= ~bitmask; 345 gpio_bankb[bank]->both &= ~bitmask;
290 gpio_bankb[bank]->edge &= ~bitmask; 346 gpio_bankb[bank]->edge &= ~bitmask;
291} 347}
348#else
349# define default_gpio(...) do { } while (0)
350#endif
292 351
293static int __init bfin_gpio_init(void) 352static int __init bfin_gpio_init(void)
294{ 353{
@@ -307,6 +366,7 @@ static int __init bfin_gpio_init(void)
307arch_initcall(bfin_gpio_init); 366arch_initcall(bfin_gpio_init);
308 367
309 368
369#ifndef BF548_FAMILY
310/*********************************************************** 370/***********************************************************
311* 371*
312* FUNCTIONS: Blackfin General Purpose Ports Access Functions 372* FUNCTIONS: Blackfin General Purpose Ports Access Functions
@@ -658,9 +718,95 @@ void gpio_pm_restore(void)
658} 718}
659 719
660#endif 720#endif
721#endif /* BF548_FAMILY */
661 722
723/***********************************************************
724*
725* FUNCTIONS: Blackfin Peripheral Resource Allocation
726* and PortMux Setup
727*
728* INPUTS/OUTPUTS:
729* per Peripheral Identifier
730* label String
731*
732* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
733*
734* CAUTION:
735*************************************************************
736* MODIFICATION HISTORY :
737**************************************************************/
738
739#ifdef BF548_FAMILY
740int peripheral_request(unsigned short per, const char *label)
741{
742 unsigned long flags;
743 unsigned short ident = P_IDENT(per);
744
745 /*
746 * Don't cares are pins with only one dedicated function
747 */
662 748
749 if (per & P_DONTCARE)
750 return 0;
751
752 if (!(per & P_DEFINED))
753 return -ENODEV;
754
755 if (check_gpio(ident) < 0)
756 return -EINVAL;
663 757
758 local_irq_save(flags);
759
760 if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
761 printk(KERN_ERR
762 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
763 __FUNCTION__, ident, get_label(ident));
764 dump_stack();
765 local_irq_restore(flags);
766 return -EBUSY;
767 }
768
769 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
770
771 u16 funct = get_portmux(ident);
772
773 /*
774 * Pin functions like AMC address strobes my
775 * be requested and used by several drivers
776 */
777
778 if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
779
780 /*
781 * Allow that the identical pin function can
782 * be requested from the same driver twice
783 */
784
785 if (cmp_label(ident, label) == 0)
786 goto anyway;
787
788 printk(KERN_ERR
789 "%s: Peripheral %d function %d is already reserved by %s !\n",
790 __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident));
791 dump_stack();
792 local_irq_restore(flags);
793 return -EBUSY;
794 }
795 }
796
797anyway:
798 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
799
800 portmux_setup(ident, P_FUNCT2MUX(per));
801 port_setup(ident, PERIPHERAL_USAGE);
802
803 local_irq_restore(flags);
804 set_label(ident, label);
805
806 return 0;
807}
808EXPORT_SYMBOL(peripheral_request);
809#else
664 810
665int peripheral_request(unsigned short per, const char *label) 811int peripheral_request(unsigned short per, const char *label)
666{ 812{
@@ -722,8 +868,6 @@ int peripheral_request(unsigned short per, const char *label)
722 } 868 }
723 869
724anyway: 870anyway:
725
726
727 portmux_setup(per, P_FUNCT2MUX(per)); 871 portmux_setup(per, P_FUNCT2MUX(per));
728 872
729 port_setup(ident, PERIPHERAL_USAGE); 873 port_setup(ident, PERIPHERAL_USAGE);
@@ -735,6 +879,7 @@ anyway:
735 return 0; 879 return 0;
736} 880}
737EXPORT_SYMBOL(peripheral_request); 881EXPORT_SYMBOL(peripheral_request);
882#endif
738 883
739int peripheral_request_list(unsigned short per[], const char *label) 884int peripheral_request_list(unsigned short per[], const char *label)
740{ 885{
@@ -805,8 +950,8 @@ EXPORT_SYMBOL(peripheral_free_list);
805* FUNCTIONS: Blackfin GPIO Driver 950* FUNCTIONS: Blackfin GPIO Driver
806* 951*
807* INPUTS/OUTPUTS: 952* INPUTS/OUTPUTS:
808* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS 953* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
809* 954* label String
810* 955*
811* DESCRIPTION: Blackfin GPIO Driver API 956* DESCRIPTION: Blackfin GPIO Driver API
812* 957*
@@ -825,16 +970,27 @@ int gpio_request(unsigned short gpio, const char *label)
825 local_irq_save(flags); 970 local_irq_save(flags);
826 971
827 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { 972 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
828 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); 973 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
974 gpio, get_label(gpio));
975 dump_stack();
976 local_irq_restore(flags);
977 return -EBUSY;
978 }
979 if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
980 printk(KERN_ERR
981 "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
982 gpio, get_label(gpio));
829 dump_stack(); 983 dump_stack();
830 local_irq_restore(flags); 984 local_irq_restore(flags);
831 return -EBUSY; 985 return -EBUSY;
832 } 986 }
987
833 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); 988 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
834 989
835 local_irq_restore(flags); 990 local_irq_restore(flags);
836 991
837 port_setup(gpio, GPIO_USAGE); 992 port_setup(gpio, GPIO_USAGE);
993 set_label(gpio, label);
838 994
839 return 0; 995 return 0;
840} 996}
@@ -864,6 +1020,51 @@ void gpio_free(unsigned short gpio)
864} 1020}
865EXPORT_SYMBOL(gpio_free); 1021EXPORT_SYMBOL(gpio_free);
866 1022
1023#ifdef BF548_FAMILY
1024void gpio_direction_input(unsigned short gpio)
1025{
1026 unsigned long flags;
1027
1028 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
1029
1030 local_irq_save(flags);
1031 gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
1032 gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
1033 local_irq_restore(flags);
1034}
1035EXPORT_SYMBOL(gpio_direction_input);
1036
1037void gpio_direction_output(unsigned short gpio)
1038{
1039 unsigned long flags;
1040
1041 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
1042
1043 local_irq_save(flags);
1044 gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
1045 gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
1046 local_irq_restore(flags);
1047}
1048EXPORT_SYMBOL(gpio_direction_output);
1049
1050void gpio_set_value(unsigned short gpio, unsigned short arg)
1051{
1052 if (arg)
1053 gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
1054 else
1055 gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
1056
1057}
1058EXPORT_SYMBOL(gpio_set_value);
1059
1060unsigned short gpio_get_value(unsigned short gpio)
1061{
1062 return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
1063}
1064EXPORT_SYMBOL(gpio_get_value);
1065
1066#else
1067
867void gpio_direction_input(unsigned short gpio) 1068void gpio_direction_input(unsigned short gpio)
868{ 1069{
869 unsigned long flags; 1070 unsigned long flags;
@@ -908,3 +1109,5 @@ void bfin_gpio_reset_spi0_ssel1(void)
908 gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); 1109 gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
909 udelay(1); 1110 udelay(1);
910} 1111}
1112
1113#endif /*BF548_FAMILY */
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);