aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2007-10-03 12:35:05 -0400
committerBryan Wu <bryan.wu@analog.com>2007-10-03 12:35:05 -0400
commitc58c2140f08de4ad0b0dbd48f6e78168dc321042 (patch)
treeee7381b9db76340295229c56350adcca44d218b1 /arch
parent0b95f22bd3b91c7114c6892bbfbb5a8576b27fbe (diff)
Blackfin arch: gpio pinmux and resource allocation API required by BF537 on chip ethernet mac driver
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c272
1 files changed, 241 insertions, 31 deletions
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index bafcfa52142b..9f3094800248 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -84,6 +84,7 @@
84#include <linux/err.h> 84#include <linux/err.h>
85#include <asm/blackfin.h> 85#include <asm/blackfin.h>
86#include <asm/gpio.h> 86#include <asm/gpio.h>
87#include <asm/portmux.h>
87#include <linux/irq.h> 88#include <linux/irq.h>
88 89
89#ifdef BF533_FAMILY 90#ifdef BF533_FAMILY
@@ -115,7 +116,11 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
115}; 116};
116#endif 117#endif
117 118
118static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 119static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
120static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)];
121char *str_ident = NULL;
122
123#define RESOURCE_LABEL_SIZE 16
119 124
120#ifdef CONFIG_PM 125#ifdef CONFIG_PM
121static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 126static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -143,13 +148,39 @@ inline int check_gpio(unsigned short gpio)
143 return 0; 148 return 0;
144} 149}
145 150
151static void set_label(unsigned short ident, const char *label)
152{
153
154 if (label && str_ident) {
155 strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label,
156 RESOURCE_LABEL_SIZE);
157 str_ident[ident * RESOURCE_LABEL_SIZE +
158 RESOURCE_LABEL_SIZE - 1] = 0;
159 }
160}
161
162static char *get_label(unsigned short ident)
163{
164 if (!str_ident)
165 return "UNKNOWN";
166
167 return (str_ident[ident * RESOURCE_LABEL_SIZE] ?
168 (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN");
169}
170
171static int cmp_label(unsigned short ident, const char *label)
172{
173 if (label && str_ident)
174 return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE,
175 label, strlen(label));
176 else
177 return -EINVAL;
178}
179
146#ifdef BF537_FAMILY 180#ifdef BF537_FAMILY
147static void port_setup(unsigned short gpio, unsigned short usage) 181static void port_setup(unsigned short gpio, unsigned short usage)
148{ 182{
149 if (usage == GPIO_USAGE) { 183 if (usage == GPIO_USAGE) {
150 if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio))
151 printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral "
152 "usage and GPIO %d detected!\n", gpio);
153 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); 184 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
154 } else 185 } else
155 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); 186 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
@@ -159,6 +190,56 @@ static void port_setup(unsigned short gpio, unsigned short usage)
159# define port_setup(...) do { } while (0) 190# define port_setup(...) do { } while (0)
160#endif 191#endif
161 192
193#ifdef BF537_FAMILY
194
195#define PMUX_LUT_RES 0
196#define PMUX_LUT_OFFSET 1
197#define PMUX_LUT_ENTRIES 41
198#define PMUX_LUT_SIZE 2
199
200static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = {
201 {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11},
202 {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11},
203 {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10},
204 {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10},
205 {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9},
206 {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7},
207 {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5},
208 {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4},
209 {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3},
210 {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1},
211 {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1},
212 {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0},
213 {P_SPI0_SSEL3, 0}
214};
215
216static void portmux_setup(unsigned short per, unsigned short function)
217{
218 u16 y, muxreg, offset;
219
220 for (y = 0; y < PMUX_LUT_ENTRIES; y++) {
221 if (port_mux_lut[y][PMUX_LUT_RES] == per) {
222
223 /* SET PORTMUX REG */
224
225 offset = port_mux_lut[y][PMUX_LUT_OFFSET];
226 muxreg = bfin_read_PORT_MUX();
227
228 if (offset != 1) {
229 muxreg &= ~(1 << offset);
230 } else {
231 muxreg &= ~(3 << 1);
232 }
233
234 muxreg |= (function << offset);
235 bfin_write_PORT_MUX(muxreg);
236 }
237 }
238}
239
240#else
241# define portmux_setup(...) do { } while (0)
242#endif
162 243
163static void default_gpio(unsigned short gpio) 244static void default_gpio(unsigned short gpio)
164{ 245{
@@ -179,22 +260,15 @@ static void default_gpio(unsigned short gpio)
179 260
180static int __init bfin_gpio_init(void) 261static int __init bfin_gpio_init(void)
181{ 262{
182 int i;
183
184 printk(KERN_INFO "Blackfin GPIO Controller\n");
185 263
186 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) 264 str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL);
187 reserved_map[gpio_bank(i)] = 0; 265 if (!str_ident)
266 return -ENOMEM;
188 267
189#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) 268 printk(KERN_INFO "Blackfin GPIO Controller\n");
190# if defined(CONFIG_BFIN_MAC_RMII)
191 reserved_map[gpio_bank(PORT_H)] = 0xC373;
192# else
193 reserved_map[gpio_bank(PORT_H)] = 0xFFFF;
194# endif
195#endif
196 269
197 return 0; 270 return 0;
271
198} 272}
199 273
200arch_initcall(bfin_gpio_init); 274arch_initcall(bfin_gpio_init);
@@ -223,7 +297,7 @@ arch_initcall(bfin_gpio_init);
223void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ 297void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
224{ \ 298{ \
225 unsigned long flags; \ 299 unsigned long flags; \
226 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ 300 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
227 local_irq_save(flags); \ 301 local_irq_save(flags); \
228 if (arg) \ 302 if (arg) \
229 gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ 303 gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
@@ -243,7 +317,7 @@ SET_GPIO(both)
243#define SET_GPIO_SC(name) \ 317#define SET_GPIO_SC(name) \
244void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ 318void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
245{ \ 319{ \
246 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ 320 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
247 if (arg) \ 321 if (arg) \
248 gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ 322 gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
249 else \ 323 else \
@@ -258,7 +332,7 @@ SET_GPIO_SC(maskb)
258void set_gpio_data(unsigned short gpio, unsigned short arg) 332void set_gpio_data(unsigned short gpio, unsigned short arg)
259{ 333{
260 unsigned long flags; 334 unsigned long flags;
261 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 335 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
262 local_irq_save(flags); 336 local_irq_save(flags);
263 if (arg) 337 if (arg)
264 gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); 338 gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
@@ -277,7 +351,7 @@ SET_GPIO_SC(data)
277void set_gpio_toggle(unsigned short gpio) 351void set_gpio_toggle(unsigned short gpio)
278{ 352{
279 unsigned long flags; 353 unsigned long flags;
280 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 354 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
281 local_irq_save(flags); 355 local_irq_save(flags);
282 gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); 356 gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
283 bfin_read_CHIPID(); 357 bfin_read_CHIPID();
@@ -286,7 +360,7 @@ void set_gpio_toggle(unsigned short gpio)
286#else 360#else
287void set_gpio_toggle(unsigned short gpio) 361void set_gpio_toggle(unsigned short gpio)
288{ 362{
289 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 363 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
290 gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); 364 gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
291} 365}
292#endif 366#endif
@@ -350,7 +424,7 @@ unsigned short get_gpio_data(unsigned short gpio)
350{ 424{
351 unsigned long flags; 425 unsigned long flags;
352 unsigned short ret; 426 unsigned short ret;
353 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 427 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
354 local_irq_save(flags); 428 local_irq_save(flags);
355 ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); 429 ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
356 bfin_read_CHIPID(); 430 bfin_read_CHIPID();
@@ -494,13 +568,14 @@ u32 gpio_pm_setup(void)
494 gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; 568 gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
495 gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; 569 gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
496 gpio_bank_saved[bank].both = gpio_bankb[bank]->both; 570 gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
497 gpio_bank_saved[bank].reserved = reserved_map[bank]; 571 gpio_bank_saved[bank].reserved =
572 reserved_gpio_map[bank];
498 573
499 gpio = i; 574 gpio = i;
500 575
501 while (mask) { 576 while (mask) {
502 if (mask & 1) { 577 if (mask & 1) {
503 reserved_map[gpio_bank(gpio)] |= 578 reserved_gpio_map[gpio_bank(gpio)] |=
504 gpio_bit(gpio); 579 gpio_bit(gpio);
505 bfin_gpio_wakeup_type(gpio, 580 bfin_gpio_wakeup_type(gpio,
506 wakeup_flags_map[gpio]); 581 wakeup_flags_map[gpio]);
@@ -540,7 +615,8 @@ void gpio_pm_restore(void)
540 gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; 615 gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
541 gpio_bankb[bank]->both = gpio_bank_saved[bank].both; 616 gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
542 617
543 reserved_map[bank] = gpio_bank_saved[bank].reserved; 618 reserved_gpio_map[bank] =
619 gpio_bank_saved[bank].reserved;
544 620
545 } 621 }
546 622
@@ -550,6 +626,140 @@ void gpio_pm_restore(void)
550 626
551#endif 627#endif
552 628
629
630
631
632int peripheral_request(unsigned short per, const char *label)
633{
634 unsigned long flags;
635 unsigned short ident = P_IDENT(per);
636
637 /*
638 * Don't cares are pins with only one dedicated function
639 */
640
641 if (per & P_DONTCARE)
642 return 0;
643
644 if (!(per & P_DEFINED))
645 return -ENODEV;
646
647 if (check_gpio(ident) < 0)
648 return -EINVAL;
649
650 local_irq_save(flags);
651
652 if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
653 printk(KERN_ERR
654 "%s: Peripheral %d is already reserved as GPIO by %s !\n",
655 __FUNCTION__, ident, get_label(ident));
656 dump_stack();
657 local_irq_restore(flags);
658 return -EBUSY;
659 }
660
661 if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
662
663 /*
664 * Pin functions like AMC address strobes my
665 * be requested and used by several drivers
666 */
667
668 if (!(per & P_MAYSHARE)) {
669
670 /*
671 * Allow that the identical pin function can
672 * be requested from the same driver twice
673 */
674
675 if (cmp_label(ident, label) == 0)
676 goto anyway;
677
678 printk(KERN_ERR
679 "%s: Peripheral %d function %d is already"
680 "reserved by %s !\n",
681 __FUNCTION__, ident, P_FUNCT2MUX(per),
682 get_label(ident));
683 dump_stack();
684 local_irq_restore(flags);
685 return -EBUSY;
686 }
687
688 }
689
690anyway:
691
692
693 portmux_setup(per, P_FUNCT2MUX(per));
694
695 port_setup(ident, PERIPHERAL_USAGE);
696
697 reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
698 local_irq_restore(flags);
699 set_label(ident, label);
700
701 return 0;
702}
703EXPORT_SYMBOL(peripheral_request);
704
705int peripheral_request_list(unsigned short per[], const char *label)
706{
707 u16 cnt;
708 int ret;
709
710 for (cnt = 0; per[cnt] != 0; cnt++) {
711 ret = peripheral_request(per[cnt], label);
712 if (ret < 0)
713 return ret;
714 }
715
716 return 0;
717}
718EXPORT_SYMBOL(peripheral_request_list);
719
720void peripheral_free(unsigned short per)
721{
722 unsigned long flags;
723 unsigned short ident = P_IDENT(per);
724
725 if (per & P_DONTCARE)
726 return;
727
728 if (!(per & P_DEFINED))
729 return;
730
731 if (check_gpio(ident) < 0)
732 return;
733
734 local_irq_save(flags);
735
736 if (unlikely(!(reserved_peri_map[gpio_bank(ident)]
737 & gpio_bit(ident)))) {
738 local_irq_restore(flags);
739 return;
740 }
741
742 if (!(per & P_MAYSHARE)) {
743 port_setup(ident, GPIO_USAGE);
744 }
745
746 reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
747
748 local_irq_restore(flags);
749}
750EXPORT_SYMBOL(peripheral_free);
751
752void peripheral_free_list(unsigned short per[])
753{
754 u16 cnt;
755
756 for (cnt = 0; per[cnt] != 0; cnt++) {
757 peripheral_free(per[cnt]);
758 }
759
760}
761EXPORT_SYMBOL(peripheral_free_list);
762
553/*********************************************************** 763/***********************************************************
554* 764*
555* FUNCTIONS: Blackfin GPIO Driver 765* FUNCTIONS: Blackfin GPIO Driver
@@ -574,13 +784,13 @@ int gpio_request(unsigned short gpio, const char *label)
574 784
575 local_irq_save(flags); 785 local_irq_save(flags);
576 786
577 if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) { 787 if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
578 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); 788 printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
579 dump_stack(); 789 dump_stack();
580 local_irq_restore(flags); 790 local_irq_restore(flags);
581 return -EBUSY; 791 return -EBUSY;
582 } 792 }
583 reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio); 793 reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
584 794
585 local_irq_restore(flags); 795 local_irq_restore(flags);
586 796
@@ -599,7 +809,7 @@ void gpio_free(unsigned short gpio)
599 809
600 local_irq_save(flags); 810 local_irq_save(flags);
601 811
602 if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { 812 if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
603 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); 813 printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
604 dump_stack(); 814 dump_stack();
605 local_irq_restore(flags); 815 local_irq_restore(flags);
@@ -608,7 +818,7 @@ void gpio_free(unsigned short gpio)
608 818
609 default_gpio(gpio); 819 default_gpio(gpio);
610 820
611 reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); 821 reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
612 822
613 local_irq_restore(flags); 823 local_irq_restore(flags);
614} 824}
@@ -618,7 +828,7 @@ void gpio_direction_input(unsigned short gpio)
618{ 828{
619 unsigned long flags; 829 unsigned long flags;
620 830
621 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 831 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
622 832
623 local_irq_save(flags); 833 local_irq_save(flags);
624 gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); 834 gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
@@ -631,7 +841,7 @@ void gpio_direction_output(unsigned short gpio)
631{ 841{
632 unsigned long flags; 842 unsigned long flags;
633 843
634 BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); 844 BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
635 845
636 local_irq_save(flags); 846 local_irq_save(flags);
637 gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); 847 gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);