diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2007-08-28 04:47:46 -0400 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2007-08-28 04:47:46 -0400 |
commit | d2b11a468a49716debd96532552a72b6078f1cf5 (patch) | |
tree | b30d94732f9d01b823e60975147b284aead495d9 /arch/blackfin/kernel | |
parent | 2296fb7ff04531dd8d50394da24f49302ecf103b (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/Makefile | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 225 |
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 | |||
7 | obj-y := \ | 7 | obj-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 | ||
12 | obj-$(CONFIG_BF53x) += bfin_gpio.o | ||
13 | obj-$(CONFIG_BF561) += bfin_gpio.o | ||
14 | obj-$(CONFIG_MODULES) += module.o | 12 | obj-$(CONFIG_MODULES) += module.o |
15 | obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o | 13 | obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o |
16 | obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o | 14 | obj-$(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 | ||
121 | static 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 | |||
120 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 135 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
121 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; | 136 | static 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) | ||
166 | inline 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 | ||
150 | inline int check_gpio(unsigned short gpio) | 176 | inline 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 | ||
157 | static void set_label(unsigned short ident, const char *label) | 184 | static 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) | |||
185 | static void port_setup(unsigned short gpio, unsigned short usage) | 212 | static 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) | ||
223 | static 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 | |||
201 | static struct { | 236 | static 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) | ||
307 | inline 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 | |||
319 | inline 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 | ||
276 | static void default_gpio(unsigned short gpio) | 332 | static 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 | ||
293 | static int __init bfin_gpio_init(void) | 352 | static int __init bfin_gpio_init(void) |
294 | { | 353 | { |
@@ -307,6 +366,7 @@ static int __init bfin_gpio_init(void) | |||
307 | arch_initcall(bfin_gpio_init); | 366 | arch_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 | ||
740 | int 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 | |||
797 | anyway: | ||
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 | } | ||
808 | EXPORT_SYMBOL(peripheral_request); | ||
809 | #else | ||
664 | 810 | ||
665 | int peripheral_request(unsigned short per, const char *label) | 811 | int 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 | ||
724 | anyway: | 870 | anyway: |
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 | } |
737 | EXPORT_SYMBOL(peripheral_request); | 881 | EXPORT_SYMBOL(peripheral_request); |
882 | #endif | ||
738 | 883 | ||
739 | int peripheral_request_list(unsigned short per[], const char *label) | 884 | int 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 | } |
865 | EXPORT_SYMBOL(gpio_free); | 1021 | EXPORT_SYMBOL(gpio_free); |
866 | 1022 | ||
1023 | #ifdef BF548_FAMILY | ||
1024 | void 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 | } | ||
1035 | EXPORT_SYMBOL(gpio_direction_input); | ||
1036 | |||
1037 | void 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 | } | ||
1048 | EXPORT_SYMBOL(gpio_direction_output); | ||
1049 | |||
1050 | void 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 | } | ||
1058 | EXPORT_SYMBOL(gpio_set_value); | ||
1059 | |||
1060 | unsigned short gpio_get_value(unsigned short gpio) | ||
1061 | { | ||
1062 | return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); | ||
1063 | } | ||
1064 | EXPORT_SYMBOL(gpio_get_value); | ||
1065 | |||
1066 | #else | ||
1067 | |||
867 | void gpio_direction_input(unsigned short gpio) | 1068 | void 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 */ | ||