diff options
author | Graf Yang <graf.yang@analog.com> | 2009-01-07 10:14:38 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 10:14:38 -0500 |
commit | 9570ff4af6920c5992eb91141d71fc94127d864b (patch) | |
tree | 8ab0887035ab00a655eb8f78b39ed0acbb0b3bed | |
parent | 94106e0fb6b863348a566617ca6bf431c37ddc5e (diff) |
Blackfin arch: Allow a gpio pin be requested both as gpio and irq.
[Mike Frysinger <vapier.adi@gmail.com>:
- use KERN_NOTICE when using gpios as both irq and non
rather than KERN_ERR
- embedded newlines in printk() does not fly]
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
-rw-r--r-- | arch/blackfin/include/asm/gpio.h | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 82 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 25 |
3 files changed, 91 insertions, 18 deletions
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index ec2ab465709e..4ee687f34fee 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h | |||
@@ -548,6 +548,8 @@ struct gpio_port_s { | |||
548 | 548 | ||
549 | int bfin_gpio_request(unsigned gpio, const char *label); | 549 | int bfin_gpio_request(unsigned gpio, const char *label); |
550 | void bfin_gpio_free(unsigned gpio); | 550 | void bfin_gpio_free(unsigned gpio); |
551 | int bfin_gpio_irq_request(unsigned gpio, const char *label); | ||
552 | void bfin_gpio_irq_free(unsigned gpio); | ||
551 | int bfin_gpio_direction_input(unsigned gpio); | 553 | int bfin_gpio_direction_input(unsigned gpio); |
552 | int bfin_gpio_direction_output(unsigned gpio, int value); | 554 | int bfin_gpio_direction_output(unsigned gpio, int value); |
553 | int bfin_gpio_get_value(unsigned gpio); | 555 | int bfin_gpio_get_value(unsigned gpio); |
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index de235b8f37a8..2c72b15b71b0 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
@@ -179,6 +179,7 @@ static struct gpio_port_t *gpio_array[] = { | |||
179 | 179 | ||
180 | static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; | 180 | static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; |
181 | static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; | 181 | static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; |
182 | static unsigned short reserved_gpio_irq_map[GPIO_BANK_NUM]; | ||
182 | 183 | ||
183 | #define RESOURCE_LABEL_SIZE 16 | 184 | #define RESOURCE_LABEL_SIZE 16 |
184 | 185 | ||
@@ -1043,7 +1044,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
1043 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | 1044 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { |
1044 | dump_stack(); | 1045 | dump_stack(); |
1045 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", | 1046 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
1046 | gpio, get_label(gpio)); | 1047 | gpio, get_label(gpio)); |
1047 | local_irq_restore(flags); | 1048 | local_irq_restore(flags); |
1048 | return -EBUSY; | 1049 | return -EBUSY; |
1049 | } | 1050 | } |
@@ -1055,13 +1056,16 @@ int bfin_gpio_request(unsigned gpio, const char *label) | |||
1055 | local_irq_restore(flags); | 1056 | local_irq_restore(flags); |
1056 | return -EBUSY; | 1057 | return -EBUSY; |
1057 | } | 1058 | } |
1059 | if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) | ||
1060 | printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" | ||
1061 | " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); | ||
1058 | 1062 | ||
1059 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); | 1063 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); |
1064 | set_label(gpio, label); | ||
1060 | 1065 | ||
1061 | local_irq_restore(flags); | 1066 | local_irq_restore(flags); |
1062 | 1067 | ||
1063 | port_setup(gpio, GPIO_USAGE); | 1068 | port_setup(gpio, GPIO_USAGE); |
1064 | set_label(gpio, label); | ||
1065 | 1069 | ||
1066 | return 0; | 1070 | return 0; |
1067 | } | 1071 | } |
@@ -1091,6 +1095,69 @@ void bfin_gpio_free(unsigned gpio) | |||
1091 | } | 1095 | } |
1092 | EXPORT_SYMBOL(bfin_gpio_free); | 1096 | EXPORT_SYMBOL(bfin_gpio_free); |
1093 | 1097 | ||
1098 | int bfin_gpio_irq_request(unsigned gpio, const char *label) | ||
1099 | { | ||
1100 | unsigned long flags; | ||
1101 | |||
1102 | if (check_gpio(gpio) < 0) | ||
1103 | return -EINVAL; | ||
1104 | |||
1105 | local_irq_save(flags); | ||
1106 | |||
1107 | if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | ||
1108 | dump_stack(); | ||
1109 | printk(KERN_ERR | ||
1110 | "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n", | ||
1111 | gpio); | ||
1112 | local_irq_restore(flags); | ||
1113 | return -EBUSY; | ||
1114 | } | ||
1115 | if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | ||
1116 | dump_stack(); | ||
1117 | printk(KERN_ERR | ||
1118 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | ||
1119 | gpio, get_label(gpio)); | ||
1120 | local_irq_restore(flags); | ||
1121 | return -EBUSY; | ||
1122 | } | ||
1123 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) | ||
1124 | printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! " | ||
1125 | "(Documentation/blackfin/bfin-gpio-notes.txt)\n", | ||
1126 | gpio, get_label(gpio)); | ||
1127 | |||
1128 | reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio); | ||
1129 | set_label(gpio, label); | ||
1130 | |||
1131 | local_irq_restore(flags); | ||
1132 | |||
1133 | port_setup(gpio, GPIO_USAGE); | ||
1134 | |||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | void bfin_gpio_irq_free(unsigned gpio) | ||
1139 | { | ||
1140 | unsigned long flags; | ||
1141 | |||
1142 | if (check_gpio(gpio) < 0) | ||
1143 | return; | ||
1144 | |||
1145 | local_irq_save(flags); | ||
1146 | |||
1147 | if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { | ||
1148 | dump_stack(); | ||
1149 | gpio_error(gpio); | ||
1150 | local_irq_restore(flags); | ||
1151 | return; | ||
1152 | } | ||
1153 | |||
1154 | reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); | ||
1155 | |||
1156 | set_label(gpio, "free"); | ||
1157 | |||
1158 | local_irq_restore(flags); | ||
1159 | } | ||
1160 | |||
1094 | 1161 | ||
1095 | #ifdef BF548_FAMILY | 1162 | #ifdef BF548_FAMILY |
1096 | int bfin_gpio_direction_input(unsigned gpio) | 1163 | int bfin_gpio_direction_input(unsigned gpio) |
@@ -1253,12 +1320,15 @@ void bfin_gpio_irq_prepare(unsigned gpio) | |||
1253 | static int gpio_proc_read(char *buf, char **start, off_t offset, | 1320 | static int gpio_proc_read(char *buf, char **start, off_t offset, |
1254 | int len, int *unused_i, void *unused_v) | 1321 | int len, int *unused_i, void *unused_v) |
1255 | { | 1322 | { |
1256 | int c, outlen = 0; | 1323 | int c, irq, gpio, outlen = 0; |
1257 | 1324 | ||
1258 | for (c = 0; c < MAX_RESOURCES; c++) { | 1325 | for (c = 0; c < MAX_RESOURCES; c++) { |
1259 | if (!check_gpio(c) && (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) | 1326 | irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c); |
1260 | len = sprintf(buf, "GPIO_%d: \t%s \t\tGPIO %s\n", c, | 1327 | gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c); |
1261 | get_label(c), get_gpio_dir(c) ? "OUTPUT" : "INPUT"); | 1328 | if (!check_gpio(c) && (gpio || irq)) |
1329 | len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, | ||
1330 | get_label(c), (gpio && irq) ? " *" : "", | ||
1331 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); | ||
1262 | else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c)) | 1332 | else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c)) |
1263 | len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); | 1333 | len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); |
1264 | else | 1334 | else |
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index a0bfca921712..7c1db775751b 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -432,7 +432,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) | |||
432 | 432 | ||
433 | bfin_gpio_mask_irq(irq); | 433 | bfin_gpio_mask_irq(irq); |
434 | __clear_bit(gpionr, gpio_enabled); | 434 | __clear_bit(gpionr, gpio_enabled); |
435 | bfin_gpio_free(gpionr); | 435 | bfin_gpio_irq_free(gpionr); |
436 | } | 436 | } |
437 | 437 | ||
438 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | 438 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) |
@@ -441,11 +441,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
441 | char buf[16]; | 441 | char buf[16]; |
442 | u32 gpionr = irq_to_gpio(irq); | 442 | u32 gpionr = irq_to_gpio(irq); |
443 | 443 | ||
444 | snprintf(buf, 16, "gpio-irq%d", irq); | ||
445 | ret = bfin_gpio_request(gpionr, buf); | ||
446 | if (ret) | ||
447 | return ret; | ||
448 | |||
449 | if (type == IRQ_TYPE_PROBE) { | 444 | if (type == IRQ_TYPE_PROBE) { |
450 | /* only probe unenabled GPIO interrupt lines */ | 445 | /* only probe unenabled GPIO interrupt lines */ |
451 | if (__test_bit(gpionr, gpio_enabled)) | 446 | if (__test_bit(gpionr, gpio_enabled)) |
@@ -456,6 +451,11 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
456 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | | 451 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | |
457 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | 452 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
458 | 453 | ||
454 | snprintf(buf, 16, "gpio-irq%d", irq); | ||
455 | ret = bfin_gpio_irq_request(gpionr, buf); | ||
456 | if (ret) | ||
457 | return ret; | ||
458 | |||
459 | if (__test_and_set_bit(gpionr, gpio_enabled)) | 459 | if (__test_and_set_bit(gpionr, gpio_enabled)) |
460 | bfin_gpio_irq_prepare(gpionr); | 460 | bfin_gpio_irq_prepare(gpionr); |
461 | 461 | ||
@@ -740,7 +740,7 @@ static void bfin_gpio_irq_shutdown(unsigned int irq) | |||
740 | 740 | ||
741 | bfin_gpio_mask_irq(irq); | 741 | bfin_gpio_mask_irq(irq); |
742 | __clear_bit(gpionr, gpio_enabled); | 742 | __clear_bit(gpionr, gpio_enabled); |
743 | bfin_gpio_free(gpionr); | 743 | bfin_gpio_irq_free(gpionr); |
744 | } | 744 | } |
745 | 745 | ||
746 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | 746 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) |
@@ -755,11 +755,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
755 | if (pint_val == IRQ_NOT_AVAIL) | 755 | if (pint_val == IRQ_NOT_AVAIL) |
756 | return -ENODEV; | 756 | return -ENODEV; |
757 | 757 | ||
758 | snprintf(buf, 16, "gpio-irq%d", irq); | ||
759 | ret = bfin_gpio_request(gpionr, buf); | ||
760 | if (ret) | ||
761 | return ret; | ||
762 | |||
763 | if (type == IRQ_TYPE_PROBE) { | 758 | if (type == IRQ_TYPE_PROBE) { |
764 | /* only probe unenabled GPIO interrupt lines */ | 759 | /* only probe unenabled GPIO interrupt lines */ |
765 | if (__test_bit(gpionr, gpio_enabled)) | 760 | if (__test_bit(gpionr, gpio_enabled)) |
@@ -769,6 +764,12 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
769 | 764 | ||
770 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | | 765 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | |
771 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | 766 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
767 | |||
768 | snprintf(buf, 16, "gpio-irq%d", irq); | ||
769 | ret = bfin_gpio_irq_request(gpionr, buf); | ||
770 | if (ret) | ||
771 | return ret; | ||
772 | |||
772 | if (__test_and_set_bit(gpionr, gpio_enabled)) | 773 | if (__test_and_set_bit(gpionr, gpio_enabled)) |
773 | bfin_gpio_irq_prepare(gpionr); | 774 | bfin_gpio_irq_prepare(gpionr); |
774 | 775 | ||