aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
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/kernel
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/kernel')
-rw-r--r--arch/blackfin/kernel/Makefile4
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c225
2 files changed, 215 insertions, 14 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 */