diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 81 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 549 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_ksyms.c | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/cacheinit.c | 5 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplbinit.c | 7 | ||||
-rw-r--r-- | arch/blackfin/kernel/early_printk.c | 214 | ||||
-rw-r--r-- | arch/blackfin/kernel/irqchip.c | 12 | ||||
-rw-r--r-- | arch/blackfin/kernel/process.c | 28 | ||||
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 24 | ||||
-rw-r--r-- | arch/blackfin/kernel/reboot.c | 78 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 90 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 110 | ||||
-rw-r--r-- | arch/blackfin/kernel/vmlinux.lds.S | 48 |
14 files changed, 1001 insertions, 251 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index f429ebc3a961..8aeb6066b19b 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -7,11 +7,10 @@ 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 | 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 |
17 | obj-$(CONFIG_KGDB) += kgdb.o | 15 | obj-$(CONFIG_KGDB) += kgdb.o |
16 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 7cf02f02a1db..e19164fb4cd1 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -73,6 +73,11 @@ static int __init blackfin_dma_init(void) | |||
73 | /* Mark MEMDMA Channel 0 as requested since we're using it internally */ | 73 | /* Mark MEMDMA Channel 0 as requested since we're using it internally */ |
74 | dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED; | 74 | dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED; |
75 | dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED; | 75 | dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED; |
76 | |||
77 | #if defined(CONFIG_DEB_DMA_URGENT) | ||
78 | bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE() | ||
79 | | DEB1_URGENT | DEB2_URGENT | DEB3_URGENT); | ||
80 | #endif | ||
76 | return 0; | 81 | return 0; |
77 | } | 82 | } |
78 | 83 | ||
@@ -265,10 +270,23 @@ void set_dma_next_desc_addr(unsigned int channel, unsigned long addr) | |||
265 | 270 | ||
266 | dma_ch[channel].regs->next_desc_ptr = addr; | 271 | dma_ch[channel].regs->next_desc_ptr = addr; |
267 | SSYNC(); | 272 | SSYNC(); |
268 | pr_debug("set_dma_start_addr() : END\n"); | 273 | pr_debug("set_dma_next_desc_addr() : END\n"); |
269 | } | 274 | } |
270 | EXPORT_SYMBOL(set_dma_next_desc_addr); | 275 | EXPORT_SYMBOL(set_dma_next_desc_addr); |
271 | 276 | ||
277 | void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr) | ||
278 | { | ||
279 | pr_debug("set_dma_curr_desc_addr() : BEGIN \n"); | ||
280 | |||
281 | BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE | ||
282 | && channel < MAX_BLACKFIN_DMA_CHANNEL)); | ||
283 | |||
284 | dma_ch[channel].regs->curr_desc_ptr = addr; | ||
285 | SSYNC(); | ||
286 | pr_debug("set_dma_curr_desc_addr() : END\n"); | ||
287 | } | ||
288 | EXPORT_SYMBOL(set_dma_curr_desc_addr); | ||
289 | |||
272 | void set_dma_x_count(unsigned int channel, unsigned short x_count) | 290 | void set_dma_x_count(unsigned int channel, unsigned short x_count) |
273 | { | 291 | { |
274 | BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE | 292 | BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE |
@@ -345,6 +363,16 @@ void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg) | |||
345 | } | 363 | } |
346 | EXPORT_SYMBOL(set_dma_sg); | 364 | EXPORT_SYMBOL(set_dma_sg); |
347 | 365 | ||
366 | void set_dma_curr_addr(unsigned int channel, unsigned long addr) | ||
367 | { | ||
368 | BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE | ||
369 | && channel < MAX_BLACKFIN_DMA_CHANNEL)); | ||
370 | |||
371 | dma_ch[channel].regs->curr_addr_ptr = addr; | ||
372 | SSYNC(); | ||
373 | } | ||
374 | EXPORT_SYMBOL(set_dma_curr_addr); | ||
375 | |||
348 | /*------------------------------------------------------------------------------ | 376 | /*------------------------------------------------------------------------------ |
349 | * Get the DMA status of a specific DMA channel from the system. | 377 | * Get the DMA status of a specific DMA channel from the system. |
350 | *-----------------------------------------------------------------------------*/ | 378 | *-----------------------------------------------------------------------------*/ |
@@ -408,6 +436,10 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
408 | blackfin_dcache_flush_range((unsigned int)src, | 436 | blackfin_dcache_flush_range((unsigned int)src, |
409 | (unsigned int)(src + size)); | 437 | (unsigned int)(src + size)); |
410 | 438 | ||
439 | if ((unsigned long)dest < memory_end) | ||
440 | blackfin_dcache_invalidate_range((unsigned int)dest, | ||
441 | (unsigned int)(dest + size)); | ||
442 | |||
411 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 443 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
412 | 444 | ||
413 | if ((unsigned long)src < (unsigned long)dest) | 445 | if ((unsigned long)src < (unsigned long)dest) |
@@ -515,6 +547,8 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
515 | } | 547 | } |
516 | } | 548 | } |
517 | 549 | ||
550 | SSYNC(); | ||
551 | |||
518 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) | 552 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) |
519 | ; | 553 | ; |
520 | 554 | ||
@@ -524,9 +558,6 @@ static void *__dma_memcpy(void *dest, const void *src, size_t size) | |||
524 | bfin_write_MDMA_S0_CONFIG(0); | 558 | bfin_write_MDMA_S0_CONFIG(0); |
525 | bfin_write_MDMA_D0_CONFIG(0); | 559 | bfin_write_MDMA_D0_CONFIG(0); |
526 | 560 | ||
527 | if ((unsigned long)dest < memory_end) | ||
528 | blackfin_dcache_invalidate_range((unsigned int)dest, | ||
529 | (unsigned int)(dest + size)); | ||
530 | local_irq_restore(flags); | 561 | local_irq_restore(flags); |
531 | 562 | ||
532 | return dest; | 563 | return dest; |
@@ -555,13 +586,14 @@ void *safe_dma_memcpy(void *dest, const void *src, size_t size) | |||
555 | } | 586 | } |
556 | EXPORT_SYMBOL(safe_dma_memcpy); | 587 | EXPORT_SYMBOL(safe_dma_memcpy); |
557 | 588 | ||
558 | void dma_outsb(void __iomem *addr, const void *buf, unsigned short len) | 589 | void dma_outsb(unsigned long addr, const void *buf, unsigned short len) |
559 | { | 590 | { |
560 | unsigned long flags; | 591 | unsigned long flags; |
561 | 592 | ||
562 | local_irq_save(flags); | 593 | local_irq_save(flags); |
563 | 594 | ||
564 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 595 | blackfin_dcache_flush_range((unsigned int)buf, |
596 | (unsigned int)(buf) + len); | ||
565 | 597 | ||
566 | bfin_write_MDMA_D0_START_ADDR(addr); | 598 | bfin_write_MDMA_D0_START_ADDR(addr); |
567 | bfin_write_MDMA_D0_X_COUNT(len); | 599 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -576,6 +608,8 @@ void dma_outsb(void __iomem *addr, const void *buf, unsigned short len) | |||
576 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); | 608 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); |
577 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); | 609 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); |
578 | 610 | ||
611 | SSYNC(); | ||
612 | |||
579 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 613 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
580 | 614 | ||
581 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 615 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -588,10 +622,13 @@ void dma_outsb(void __iomem *addr, const void *buf, unsigned short len) | |||
588 | EXPORT_SYMBOL(dma_outsb); | 622 | EXPORT_SYMBOL(dma_outsb); |
589 | 623 | ||
590 | 624 | ||
591 | void dma_insb(const void __iomem *addr, void *buf, unsigned short len) | 625 | void dma_insb(unsigned long addr, void *buf, unsigned short len) |
592 | { | 626 | { |
593 | unsigned long flags; | 627 | unsigned long flags; |
594 | 628 | ||
629 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
630 | (unsigned int)(buf) + len); | ||
631 | |||
595 | local_irq_save(flags); | 632 | local_irq_save(flags); |
596 | bfin_write_MDMA_D0_START_ADDR(buf); | 633 | bfin_write_MDMA_D0_START_ADDR(buf); |
597 | bfin_write_MDMA_D0_X_COUNT(len); | 634 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -606,7 +643,7 @@ void dma_insb(const void __iomem *addr, void *buf, unsigned short len) | |||
606 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); | 643 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8); |
607 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); | 644 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8); |
608 | 645 | ||
609 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 646 | SSYNC(); |
610 | 647 | ||
611 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 648 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
612 | 649 | ||
@@ -619,13 +656,14 @@ void dma_insb(const void __iomem *addr, void *buf, unsigned short len) | |||
619 | } | 656 | } |
620 | EXPORT_SYMBOL(dma_insb); | 657 | EXPORT_SYMBOL(dma_insb); |
621 | 658 | ||
622 | void dma_outsw(void __iomem *addr, const void *buf, unsigned short len) | 659 | void dma_outsw(unsigned long addr, const void *buf, unsigned short len) |
623 | { | 660 | { |
624 | unsigned long flags; | 661 | unsigned long flags; |
625 | 662 | ||
626 | local_irq_save(flags); | 663 | local_irq_save(flags); |
627 | 664 | ||
628 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 665 | blackfin_dcache_flush_range((unsigned int)buf, |
666 | (unsigned int)(buf) + len * sizeof(short)); | ||
629 | 667 | ||
630 | bfin_write_MDMA_D0_START_ADDR(addr); | 668 | bfin_write_MDMA_D0_START_ADDR(addr); |
631 | bfin_write_MDMA_D0_X_COUNT(len); | 669 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -640,6 +678,8 @@ void dma_outsw(void __iomem *addr, const void *buf, unsigned short len) | |||
640 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); | 678 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); |
641 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); | 679 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); |
642 | 680 | ||
681 | SSYNC(); | ||
682 | |||
643 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 683 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
644 | 684 | ||
645 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 685 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -651,10 +691,13 @@ void dma_outsw(void __iomem *addr, const void *buf, unsigned short len) | |||
651 | } | 691 | } |
652 | EXPORT_SYMBOL(dma_outsw); | 692 | EXPORT_SYMBOL(dma_outsw); |
653 | 693 | ||
654 | void dma_insw(const void __iomem *addr, void *buf, unsigned short len) | 694 | void dma_insw(unsigned long addr, void *buf, unsigned short len) |
655 | { | 695 | { |
656 | unsigned long flags; | 696 | unsigned long flags; |
657 | 697 | ||
698 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
699 | (unsigned int)(buf) + len * sizeof(short)); | ||
700 | |||
658 | local_irq_save(flags); | 701 | local_irq_save(flags); |
659 | 702 | ||
660 | bfin_write_MDMA_D0_START_ADDR(buf); | 703 | bfin_write_MDMA_D0_START_ADDR(buf); |
@@ -670,7 +713,7 @@ void dma_insw(const void __iomem *addr, void *buf, unsigned short len) | |||
670 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); | 713 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16); |
671 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); | 714 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16); |
672 | 715 | ||
673 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 716 | SSYNC(); |
674 | 717 | ||
675 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 718 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
676 | 719 | ||
@@ -683,13 +726,14 @@ void dma_insw(const void __iomem *addr, void *buf, unsigned short len) | |||
683 | } | 726 | } |
684 | EXPORT_SYMBOL(dma_insw); | 727 | EXPORT_SYMBOL(dma_insw); |
685 | 728 | ||
686 | void dma_outsl(void __iomem *addr, const void *buf, unsigned short len) | 729 | void dma_outsl(unsigned long addr, const void *buf, unsigned short len) |
687 | { | 730 | { |
688 | unsigned long flags; | 731 | unsigned long flags; |
689 | 732 | ||
690 | local_irq_save(flags); | 733 | local_irq_save(flags); |
691 | 734 | ||
692 | blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len); | 735 | blackfin_dcache_flush_range((unsigned int)buf, |
736 | (unsigned int)(buf) + len * sizeof(long)); | ||
693 | 737 | ||
694 | bfin_write_MDMA_D0_START_ADDR(addr); | 738 | bfin_write_MDMA_D0_START_ADDR(addr); |
695 | bfin_write_MDMA_D0_X_COUNT(len); | 739 | bfin_write_MDMA_D0_X_COUNT(len); |
@@ -704,6 +748,8 @@ void dma_outsl(void __iomem *addr, const void *buf, unsigned short len) | |||
704 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); | 748 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); |
705 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); | 749 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); |
706 | 750 | ||
751 | SSYNC(); | ||
752 | |||
707 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 753 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
708 | 754 | ||
709 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); | 755 | bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR); |
@@ -715,10 +761,13 @@ void dma_outsl(void __iomem *addr, const void *buf, unsigned short len) | |||
715 | } | 761 | } |
716 | EXPORT_SYMBOL(dma_outsl); | 762 | EXPORT_SYMBOL(dma_outsl); |
717 | 763 | ||
718 | void dma_insl(const void __iomem *addr, void *buf, unsigned short len) | 764 | void dma_insl(unsigned long addr, void *buf, unsigned short len) |
719 | { | 765 | { |
720 | unsigned long flags; | 766 | unsigned long flags; |
721 | 767 | ||
768 | blackfin_dcache_invalidate_range((unsigned int)buf, | ||
769 | (unsigned int)(buf) + len * sizeof(long)); | ||
770 | |||
722 | local_irq_save(flags); | 771 | local_irq_save(flags); |
723 | 772 | ||
724 | bfin_write_MDMA_D0_START_ADDR(buf); | 773 | bfin_write_MDMA_D0_START_ADDR(buf); |
@@ -734,7 +783,7 @@ void dma_insl(const void __iomem *addr, void *buf, unsigned short len) | |||
734 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); | 783 | bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32); |
735 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); | 784 | bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32); |
736 | 785 | ||
737 | blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len); | 786 | SSYNC(); |
738 | 787 | ||
739 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); | 788 | while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)); |
740 | 789 | ||
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 5d488ef965ce..3fe0cd49e8db 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 |
@@ -80,6 +80,7 @@ | |||
80 | * GPIO_47 PH15 PF47 | 80 | * GPIO_47 PH15 PF47 |
81 | */ | 81 | */ |
82 | 82 | ||
83 | #include <linux/delay.h> | ||
83 | #include <linux/module.h> | 84 | #include <linux/module.h> |
84 | #include <linux/err.h> | 85 | #include <linux/err.h> |
85 | #include <asm/blackfin.h> | 86 | #include <asm/blackfin.h> |
@@ -87,6 +88,36 @@ | |||
87 | #include <asm/portmux.h> | 88 | #include <asm/portmux.h> |
88 | #include <linux/irq.h> | 89 | #include <linux/irq.h> |
89 | 90 | ||
91 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
92 | enum { | ||
93 | AWA_data = SYSCR, | ||
94 | AWA_data_clear = SYSCR, | ||
95 | AWA_data_set = SYSCR, | ||
96 | AWA_toggle = SYSCR, | ||
97 | AWA_maska = UART_SCR, | ||
98 | AWA_maska_clear = UART_SCR, | ||
99 | AWA_maska_set = UART_SCR, | ||
100 | AWA_maska_toggle = UART_SCR, | ||
101 | AWA_maskb = UART_GCTL, | ||
102 | AWA_maskb_clear = UART_GCTL, | ||
103 | AWA_maskb_set = UART_GCTL, | ||
104 | AWA_maskb_toggle = UART_GCTL, | ||
105 | AWA_dir = SPORT1_STAT, | ||
106 | AWA_polar = SPORT1_STAT, | ||
107 | AWA_edge = SPORT1_STAT, | ||
108 | AWA_both = SPORT1_STAT, | ||
109 | #if ANOMALY_05000311 | ||
110 | AWA_inen = TIMER_ENABLE, | ||
111 | #elif ANOMALY_05000323 | ||
112 | AWA_inen = DMA1_1_CONFIG, | ||
113 | #endif | ||
114 | }; | ||
115 | /* Anomaly Workaround */ | ||
116 | #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) | ||
117 | #else | ||
118 | #define AWA_DUMMY_READ(...) do { } while (0) | ||
119 | #endif | ||
120 | |||
90 | #ifdef BF533_FAMILY | 121 | #ifdef BF533_FAMILY |
91 | static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | 122 | static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { |
92 | (struct gpio_port_t *) FIO_FLAG_D, | 123 | (struct gpio_port_t *) FIO_FLAG_D, |
@@ -116,11 +147,31 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | |||
116 | }; | 147 | }; |
117 | #endif | 148 | #endif |
118 | 149 | ||
150 | #ifdef BF548_FAMILY | ||
151 | static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = { | ||
152 | (struct gpio_port_t *)PORTA_FER, | ||
153 | (struct gpio_port_t *)PORTB_FER, | ||
154 | (struct gpio_port_t *)PORTC_FER, | ||
155 | (struct gpio_port_t *)PORTD_FER, | ||
156 | (struct gpio_port_t *)PORTE_FER, | ||
157 | (struct gpio_port_t *)PORTF_FER, | ||
158 | (struct gpio_port_t *)PORTG_FER, | ||
159 | (struct gpio_port_t *)PORTH_FER, | ||
160 | (struct gpio_port_t *)PORTI_FER, | ||
161 | (struct gpio_port_t *)PORTJ_FER, | ||
162 | }; | ||
163 | #endif | ||
164 | |||
119 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 165 | static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
120 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; | 166 | static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; |
121 | char *str_ident = NULL; | ||
122 | 167 | ||
123 | #define RESOURCE_LABEL_SIZE 16 | 168 | #define MAX_RESOURCES 256 |
169 | #define RESOURCE_LABEL_SIZE 16 | ||
170 | |||
171 | struct str_ident { | ||
172 | char name[RESOURCE_LABEL_SIZE]; | ||
173 | } *str_ident; | ||
174 | |||
124 | 175 | ||
125 | #ifdef CONFIG_PM | 176 | #ifdef CONFIG_PM |
126 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; | 177 | static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; |
@@ -141,21 +192,32 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INT | |||
141 | 192 | ||
142 | #endif /* CONFIG_PM */ | 193 | #endif /* CONFIG_PM */ |
143 | 194 | ||
195 | #if defined(BF548_FAMILY) | ||
196 | inline int check_gpio(unsigned short gpio) | ||
197 | { | ||
198 | if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 | ||
199 | || gpio == GPIO_PH14 || gpio == GPIO_PH15 | ||
200 | || gpio == GPIO_PJ14 || gpio == GPIO_PJ15 | ||
201 | || gpio > MAX_BLACKFIN_GPIOS) | ||
202 | return -EINVAL; | ||
203 | return 0; | ||
204 | } | ||
205 | #else | ||
144 | inline int check_gpio(unsigned short gpio) | 206 | inline int check_gpio(unsigned short gpio) |
145 | { | 207 | { |
146 | if (gpio >= MAX_BLACKFIN_GPIOS) | 208 | if (gpio >= MAX_BLACKFIN_GPIOS) |
147 | return -EINVAL; | 209 | return -EINVAL; |
148 | return 0; | 210 | return 0; |
149 | } | 211 | } |
212 | #endif | ||
150 | 213 | ||
151 | static void set_label(unsigned short ident, const char *label) | 214 | static void set_label(unsigned short ident, const char *label) |
152 | { | 215 | { |
153 | 216 | ||
154 | if (label && str_ident) { | 217 | if (label && str_ident) { |
155 | strncpy(str_ident + ident * RESOURCE_LABEL_SIZE, label, | 218 | strncpy(str_ident[ident].name, label, |
156 | RESOURCE_LABEL_SIZE); | 219 | RESOURCE_LABEL_SIZE); |
157 | str_ident[ident * RESOURCE_LABEL_SIZE + | 220 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; |
158 | RESOURCE_LABEL_SIZE - 1] = 0; | ||
159 | } | 221 | } |
160 | } | 222 | } |
161 | 223 | ||
@@ -164,14 +226,13 @@ static char *get_label(unsigned short ident) | |||
164 | if (!str_ident) | 226 | if (!str_ident) |
165 | return "UNKNOWN"; | 227 | return "UNKNOWN"; |
166 | 228 | ||
167 | return (str_ident[ident * RESOURCE_LABEL_SIZE] ? | 229 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); |
168 | (str_ident + ident * RESOURCE_LABEL_SIZE) : "UNKNOWN"); | ||
169 | } | 230 | } |
170 | 231 | ||
171 | static int cmp_label(unsigned short ident, const char *label) | 232 | static int cmp_label(unsigned short ident, const char *label) |
172 | { | 233 | { |
173 | if (label && str_ident) | 234 | if (label && str_ident) |
174 | return strncmp(str_ident + ident * RESOURCE_LABEL_SIZE, | 235 | return strncmp(str_ident[ident].name, |
175 | label, strlen(label)); | 236 | label, strlen(label)); |
176 | else | 237 | else |
177 | return -EINVAL; | 238 | return -EINVAL; |
@@ -181,50 +242,84 @@ static int cmp_label(unsigned short ident, const char *label) | |||
181 | static void port_setup(unsigned short gpio, unsigned short usage) | 242 | static void port_setup(unsigned short gpio, unsigned short usage) |
182 | { | 243 | { |
183 | if (!check_gpio(gpio)) { | 244 | if (!check_gpio(gpio)) { |
184 | if (usage == GPIO_USAGE) { | 245 | if (usage == GPIO_USAGE) |
185 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 246 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
186 | } else | 247 | else |
187 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); | 248 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
188 | SSYNC(); | 249 | SSYNC(); |
189 | } | 250 | } |
190 | } | 251 | } |
252 | #elif defined(BF548_FAMILY) | ||
253 | static void port_setup(unsigned short gpio, unsigned short usage) | ||
254 | { | ||
255 | if (usage == GPIO_USAGE) | ||
256 | gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); | ||
257 | else | ||
258 | gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); | ||
259 | SSYNC(); | ||
260 | } | ||
191 | #else | 261 | #else |
192 | # define port_setup(...) do { } while (0) | 262 | # define port_setup(...) do { } while (0) |
193 | #endif | 263 | #endif |
194 | 264 | ||
195 | #ifdef BF537_FAMILY | 265 | #ifdef BF537_FAMILY |
196 | 266 | static struct { | |
197 | #define PMUX_LUT_RES 0 | 267 | unsigned short res; |
198 | #define PMUX_LUT_OFFSET 1 | 268 | unsigned short offset; |
199 | #define PMUX_LUT_ENTRIES 41 | 269 | } port_mux_lut[] = { |
200 | #define PMUX_LUT_SIZE 2 | 270 | {.res = P_PPI0_D13, .offset = 11}, |
201 | 271 | {.res = P_PPI0_D14, .offset = 11}, | |
202 | static unsigned short port_mux_lut[PMUX_LUT_ENTRIES][PMUX_LUT_SIZE] = { | 272 | {.res = P_PPI0_D15, .offset = 11}, |
203 | {P_PPI0_D13, 11}, {P_PPI0_D14, 11}, {P_PPI0_D15, 11}, | 273 | {.res = P_SPORT1_TFS, .offset = 11}, |
204 | {P_SPORT1_TFS, 11}, {P_SPORT1_TSCLK, 11}, {P_SPORT1_DTPRI, 11}, | 274 | {.res = P_SPORT1_TSCLK, .offset = 11}, |
205 | {P_PPI0_D10, 10}, {P_PPI0_D11, 10}, {P_PPI0_D12, 10}, | 275 | {.res = P_SPORT1_DTPRI, .offset = 11}, |
206 | {P_SPORT1_RSCLK, 10}, {P_SPORT1_RFS, 10}, {P_SPORT1_DRPRI, 10}, | 276 | {.res = P_PPI0_D10, .offset = 10}, |
207 | {P_PPI0_D8, 9}, {P_PPI0_D9, 9}, {P_SPORT1_DRSEC, 9}, | 277 | {.res = P_PPI0_D11, .offset = 10}, |
208 | {P_SPORT1_DTSEC, 9}, {P_TMR2, 8}, {P_PPI0_FS3, 8}, {P_TMR3, 7}, | 278 | {.res = P_PPI0_D12, .offset = 10}, |
209 | {P_SPI0_SSEL4, 7}, {P_TMR4, 6}, {P_SPI0_SSEL5, 6}, {P_TMR5, 5}, | 279 | {.res = P_SPORT1_RSCLK, .offset = 10}, |
210 | {P_SPI0_SSEL6, 5}, {P_UART1_RX, 4}, {P_UART1_TX, 4}, {P_TMR6, 4}, | 280 | {.res = P_SPORT1_RFS, .offset = 10}, |
211 | {P_TMR7, 4}, {P_UART0_RX, 3}, {P_UART0_TX, 3}, {P_DMAR0, 3}, | 281 | {.res = P_SPORT1_DRPRI, .offset = 10}, |
212 | {P_DMAR1, 3}, {P_SPORT0_DTSEC, 1}, {P_SPORT0_DRSEC, 1}, | 282 | {.res = P_PPI0_D8, .offset = 9}, |
213 | {P_CAN0_RX, 1}, {P_CAN0_TX, 1}, {P_SPI0_SSEL7, 1}, | 283 | {.res = P_PPI0_D9, .offset = 9}, |
214 | {P_SPORT0_TFS, 0}, {P_SPORT0_DTPRI, 0}, {P_SPI0_SSEL2, 0}, | 284 | {.res = P_SPORT1_DRSEC, .offset = 9}, |
215 | {P_SPI0_SSEL3, 0} | 285 | {.res = P_SPORT1_DTSEC, .offset = 9}, |
286 | {.res = P_TMR2, .offset = 8}, | ||
287 | {.res = P_PPI0_FS3, .offset = 8}, | ||
288 | {.res = P_TMR3, .offset = 7}, | ||
289 | {.res = P_SPI0_SSEL4, .offset = 7}, | ||
290 | {.res = P_TMR4, .offset = 6}, | ||
291 | {.res = P_SPI0_SSEL5, .offset = 6}, | ||
292 | {.res = P_TMR5, .offset = 5}, | ||
293 | {.res = P_SPI0_SSEL6, .offset = 5}, | ||
294 | {.res = P_UART1_RX, .offset = 4}, | ||
295 | {.res = P_UART1_TX, .offset = 4}, | ||
296 | {.res = P_TMR6, .offset = 4}, | ||
297 | {.res = P_TMR7, .offset = 4}, | ||
298 | {.res = P_UART0_RX, .offset = 3}, | ||
299 | {.res = P_UART0_TX, .offset = 3}, | ||
300 | {.res = P_DMAR0, .offset = 3}, | ||
301 | {.res = P_DMAR1, .offset = 3}, | ||
302 | {.res = P_SPORT0_DTSEC, .offset = 1}, | ||
303 | {.res = P_SPORT0_DRSEC, .offset = 1}, | ||
304 | {.res = P_CAN0_RX, .offset = 1}, | ||
305 | {.res = P_CAN0_TX, .offset = 1}, | ||
306 | {.res = P_SPI0_SSEL7, .offset = 1}, | ||
307 | {.res = P_SPORT0_TFS, .offset = 0}, | ||
308 | {.res = P_SPORT0_DTPRI, .offset = 0}, | ||
309 | {.res = P_SPI0_SSEL2, .offset = 0}, | ||
310 | {.res = P_SPI0_SSEL3, .offset = 0}, | ||
216 | }; | 311 | }; |
217 | 312 | ||
218 | static void portmux_setup(unsigned short per, unsigned short function) | 313 | static void portmux_setup(unsigned short per, unsigned short function) |
219 | { | 314 | { |
220 | u16 y, muxreg, offset; | 315 | u16 y, offset, muxreg; |
221 | 316 | ||
222 | for (y = 0; y < PMUX_LUT_ENTRIES; y++) { | 317 | for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { |
223 | if (port_mux_lut[y][PMUX_LUT_RES] == per) { | 318 | if (port_mux_lut[y].res == per) { |
224 | 319 | ||
225 | /* SET PORTMUX REG */ | 320 | /* SET PORTMUX REG */ |
226 | 321 | ||
227 | offset = port_mux_lut[y][PMUX_LUT_OFFSET]; | 322 | offset = port_mux_lut[y].offset; |
228 | muxreg = bfin_read_PORT_MUX(); | 323 | muxreg = bfin_read_PORT_MUX(); |
229 | 324 | ||
230 | if (offset != 1) { | 325 | if (offset != 1) { |
@@ -238,18 +333,42 @@ static void portmux_setup(unsigned short per, unsigned short function) | |||
238 | } | 333 | } |
239 | } | 334 | } |
240 | } | 335 | } |
336 | #elif defined(BF548_FAMILY) | ||
337 | inline void portmux_setup(unsigned short portno, unsigned short function) | ||
338 | { | ||
339 | u32 pmux; | ||
340 | |||
341 | pmux = gpio_array[gpio_bank(portno)]->port_mux; | ||
342 | |||
343 | pmux &= ~(0x3 << (2 * gpio_sub_n(portno))); | ||
344 | pmux |= (function & 0x3) << (2 * gpio_sub_n(portno)); | ||
241 | 345 | ||
346 | gpio_array[gpio_bank(portno)]->port_mux = pmux; | ||
347 | } | ||
348 | |||
349 | inline u16 get_portmux(unsigned short portno) | ||
350 | { | ||
351 | u32 pmux; | ||
352 | |||
353 | pmux = gpio_array[gpio_bank(portno)]->port_mux; | ||
354 | |||
355 | return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); | ||
356 | } | ||
242 | #else | 357 | #else |
243 | # define portmux_setup(...) do { } while (0) | 358 | # define portmux_setup(...) do { } while (0) |
244 | #endif | 359 | #endif |
245 | 360 | ||
361 | #ifndef BF548_FAMILY | ||
246 | static void default_gpio(unsigned short gpio) | 362 | static void default_gpio(unsigned short gpio) |
247 | { | 363 | { |
248 | unsigned short bank, bitmask; | 364 | unsigned short bank, bitmask; |
365 | unsigned long flags; | ||
249 | 366 | ||
250 | bank = gpio_bank(gpio); | 367 | bank = gpio_bank(gpio); |
251 | bitmask = gpio_bit(gpio); | 368 | bitmask = gpio_bit(gpio); |
252 | 369 | ||
370 | local_irq_save(flags); | ||
371 | |||
253 | gpio_bankb[bank]->maska_clear = bitmask; | 372 | gpio_bankb[bank]->maska_clear = bitmask; |
254 | gpio_bankb[bank]->maskb_clear = bitmask; | 373 | gpio_bankb[bank]->maskb_clear = bitmask; |
255 | SSYNC(); | 374 | SSYNC(); |
@@ -258,24 +377,32 @@ static void default_gpio(unsigned short gpio) | |||
258 | gpio_bankb[bank]->polar &= ~bitmask; | 377 | gpio_bankb[bank]->polar &= ~bitmask; |
259 | gpio_bankb[bank]->both &= ~bitmask; | 378 | gpio_bankb[bank]->both &= ~bitmask; |
260 | gpio_bankb[bank]->edge &= ~bitmask; | 379 | gpio_bankb[bank]->edge &= ~bitmask; |
380 | AWA_DUMMY_READ(edge); | ||
381 | local_irq_restore(flags); | ||
382 | |||
261 | } | 383 | } |
384 | #else | ||
385 | # define default_gpio(...) do { } while (0) | ||
386 | #endif | ||
262 | 387 | ||
263 | static int __init bfin_gpio_init(void) | 388 | static int __init bfin_gpio_init(void) |
264 | { | 389 | { |
265 | 390 | str_ident = kcalloc(MAX_RESOURCES, | |
266 | str_ident = kzalloc(RESOURCE_LABEL_SIZE * 256, GFP_KERNEL); | 391 | sizeof(struct str_ident), GFP_KERNEL); |
267 | if (!str_ident) | 392 | if (str_ident == NULL) |
268 | return -ENOMEM; | 393 | return -ENOMEM; |
269 | 394 | ||
395 | memset(str_ident, 0, MAX_RESOURCES * sizeof(struct str_ident)); | ||
396 | |||
270 | printk(KERN_INFO "Blackfin GPIO Controller\n"); | 397 | printk(KERN_INFO "Blackfin GPIO Controller\n"); |
271 | 398 | ||
272 | return 0; | 399 | return 0; |
273 | 400 | ||
274 | } | 401 | } |
275 | |||
276 | arch_initcall(bfin_gpio_init); | 402 | arch_initcall(bfin_gpio_init); |
277 | 403 | ||
278 | 404 | ||
405 | #ifndef BF548_FAMILY | ||
279 | /*********************************************************** | 406 | /*********************************************************** |
280 | * | 407 | * |
281 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions | 408 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions |
@@ -305,6 +432,7 @@ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | |||
305 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ | 432 | gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
306 | else \ | 433 | else \ |
307 | gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ | 434 | gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ |
435 | AWA_DUMMY_READ(name); \ | ||
308 | local_irq_restore(flags); \ | 436 | local_irq_restore(flags); \ |
309 | } \ | 437 | } \ |
310 | EXPORT_SYMBOL(set_gpio_ ## name); | 438 | EXPORT_SYMBOL(set_gpio_ ## name); |
@@ -316,6 +444,22 @@ SET_GPIO(edge) | |||
316 | SET_GPIO(both) | 444 | SET_GPIO(both) |
317 | 445 | ||
318 | 446 | ||
447 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
448 | #define SET_GPIO_SC(name) \ | ||
449 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | ||
450 | { \ | ||
451 | unsigned long flags; \ | ||
452 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ | ||
453 | local_irq_save(flags); \ | ||
454 | if (arg) \ | ||
455 | gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ | ||
456 | else \ | ||
457 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | ||
458 | AWA_DUMMY_READ(name); \ | ||
459 | local_irq_restore(flags); \ | ||
460 | } \ | ||
461 | EXPORT_SYMBOL(set_gpio_ ## name); | ||
462 | #else | ||
319 | #define SET_GPIO_SC(name) \ | 463 | #define SET_GPIO_SC(name) \ |
320 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | 464 | void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ |
321 | { \ | 465 | { \ |
@@ -326,37 +470,20 @@ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ | |||
326 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ | 470 | gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ |
327 | } \ | 471 | } \ |
328 | EXPORT_SYMBOL(set_gpio_ ## name); | 472 | EXPORT_SYMBOL(set_gpio_ ## name); |
473 | #endif | ||
329 | 474 | ||
330 | SET_GPIO_SC(maska) | 475 | SET_GPIO_SC(maska) |
331 | SET_GPIO_SC(maskb) | 476 | SET_GPIO_SC(maskb) |
332 | |||
333 | #if defined(ANOMALY_05000311) | ||
334 | void set_gpio_data(unsigned short gpio, unsigned short arg) | ||
335 | { | ||
336 | unsigned long flags; | ||
337 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
338 | local_irq_save(flags); | ||
339 | if (arg) | ||
340 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | ||
341 | else | ||
342 | gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); | ||
343 | bfin_read_CHIPID(); | ||
344 | local_irq_restore(flags); | ||
345 | } | ||
346 | EXPORT_SYMBOL(set_gpio_data); | ||
347 | #else | ||
348 | SET_GPIO_SC(data) | 477 | SET_GPIO_SC(data) |
349 | #endif | ||
350 | |||
351 | 478 | ||
352 | #if defined(ANOMALY_05000311) | 479 | #if ANOMALY_05000311 || ANOMALY_05000323 |
353 | void set_gpio_toggle(unsigned short gpio) | 480 | void set_gpio_toggle(unsigned short gpio) |
354 | { | 481 | { |
355 | unsigned long flags; | 482 | unsigned long flags; |
356 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | 483 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); |
357 | local_irq_save(flags); | 484 | local_irq_save(flags); |
358 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); | 485 | gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
359 | bfin_read_CHIPID(); | 486 | AWA_DUMMY_READ(toggle); |
360 | local_irq_restore(flags); | 487 | local_irq_restore(flags); |
361 | } | 488 | } |
362 | #else | 489 | #else |
@@ -371,13 +498,27 @@ EXPORT_SYMBOL(set_gpio_toggle); | |||
371 | 498 | ||
372 | /*Set current PORT date (16-bit word)*/ | 499 | /*Set current PORT date (16-bit word)*/ |
373 | 500 | ||
501 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
374 | #define SET_GPIO_P(name) \ | 502 | #define SET_GPIO_P(name) \ |
375 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ | 503 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ |
376 | { \ | 504 | { \ |
505 | unsigned long flags; \ | ||
506 | local_irq_save(flags); \ | ||
377 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ | 507 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ |
508 | AWA_DUMMY_READ(name); \ | ||
509 | local_irq_restore(flags); \ | ||
378 | } \ | 510 | } \ |
379 | EXPORT_SYMBOL(set_gpiop_ ## name); | 511 | EXPORT_SYMBOL(set_gpiop_ ## name); |
512 | #else | ||
513 | #define SET_GPIO_P(name) \ | ||
514 | void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ | ||
515 | { \ | ||
516 | gpio_bankb[gpio_bank(gpio)]->name = arg; \ | ||
517 | } \ | ||
518 | EXPORT_SYMBOL(set_gpiop_ ## name); | ||
519 | #endif | ||
380 | 520 | ||
521 | SET_GPIO_P(data) | ||
381 | SET_GPIO_P(dir) | 522 | SET_GPIO_P(dir) |
382 | SET_GPIO_P(inen) | 523 | SET_GPIO_P(inen) |
383 | SET_GPIO_P(polar) | 524 | SET_GPIO_P(polar) |
@@ -387,31 +528,30 @@ SET_GPIO_P(maska) | |||
387 | SET_GPIO_P(maskb) | 528 | SET_GPIO_P(maskb) |
388 | 529 | ||
389 | 530 | ||
390 | #if defined(ANOMALY_05000311) | ||
391 | void set_gpiop_data(unsigned short gpio, unsigned short arg) | ||
392 | { | ||
393 | unsigned long flags; | ||
394 | local_irq_save(flags); | ||
395 | gpio_bankb[gpio_bank(gpio)]->data = arg; | ||
396 | bfin_read_CHIPID(); | ||
397 | local_irq_restore(flags); | ||
398 | } | ||
399 | EXPORT_SYMBOL(set_gpiop_data); | ||
400 | #else | ||
401 | SET_GPIO_P(data) | ||
402 | #endif | ||
403 | |||
404 | |||
405 | |||
406 | /* Get a specific bit */ | 531 | /* Get a specific bit */ |
407 | 532 | #if ANOMALY_05000311 || ANOMALY_05000323 | |
533 | #define GET_GPIO(name) \ | ||
534 | unsigned short get_gpio_ ## name(unsigned short gpio) \ | ||
535 | { \ | ||
536 | unsigned long flags; \ | ||
537 | unsigned short ret; \ | ||
538 | local_irq_save(flags); \ | ||
539 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ | ||
540 | AWA_DUMMY_READ(name); \ | ||
541 | local_irq_restore(flags); \ | ||
542 | return ret; \ | ||
543 | } \ | ||
544 | EXPORT_SYMBOL(get_gpio_ ## name); | ||
545 | #else | ||
408 | #define GET_GPIO(name) \ | 546 | #define GET_GPIO(name) \ |
409 | unsigned short get_gpio_ ## name(unsigned short gpio) \ | 547 | unsigned short get_gpio_ ## name(unsigned short gpio) \ |
410 | { \ | 548 | { \ |
411 | return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ | 549 | return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ |
412 | } \ | 550 | } \ |
413 | EXPORT_SYMBOL(get_gpio_ ## name); | 551 | EXPORT_SYMBOL(get_gpio_ ## name); |
552 | #endif | ||
414 | 553 | ||
554 | GET_GPIO(data) | ||
415 | GET_GPIO(dir) | 555 | GET_GPIO(dir) |
416 | GET_GPIO(inen) | 556 | GET_GPIO(inen) |
417 | GET_GPIO(polar) | 557 | GET_GPIO(polar) |
@@ -420,33 +560,31 @@ GET_GPIO(both) | |||
420 | GET_GPIO(maska) | 560 | GET_GPIO(maska) |
421 | GET_GPIO(maskb) | 561 | GET_GPIO(maskb) |
422 | 562 | ||
423 | |||
424 | #if defined(ANOMALY_05000311) | ||
425 | unsigned short get_gpio_data(unsigned short gpio) | ||
426 | { | ||
427 | unsigned long flags; | ||
428 | unsigned short ret; | ||
429 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
430 | local_irq_save(flags); | ||
431 | ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); | ||
432 | bfin_read_CHIPID(); | ||
433 | local_irq_restore(flags); | ||
434 | return ret; | ||
435 | } | ||
436 | EXPORT_SYMBOL(get_gpio_data); | ||
437 | #else | ||
438 | GET_GPIO(data) | ||
439 | #endif | ||
440 | |||
441 | /*Get current PORT date (16-bit word)*/ | 563 | /*Get current PORT date (16-bit word)*/ |
442 | 564 | ||
565 | #if ANOMALY_05000311 || ANOMALY_05000323 | ||
566 | #define GET_GPIO_P(name) \ | ||
567 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ | ||
568 | { \ | ||
569 | unsigned long flags; \ | ||
570 | unsigned short ret; \ | ||
571 | local_irq_save(flags); \ | ||
572 | ret = (gpio_bankb[gpio_bank(gpio)]->name); \ | ||
573 | AWA_DUMMY_READ(name); \ | ||
574 | local_irq_restore(flags); \ | ||
575 | return ret; \ | ||
576 | } \ | ||
577 | EXPORT_SYMBOL(get_gpiop_ ## name); | ||
578 | #else | ||
443 | #define GET_GPIO_P(name) \ | 579 | #define GET_GPIO_P(name) \ |
444 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ | 580 | unsigned short get_gpiop_ ## name(unsigned short gpio) \ |
445 | { \ | 581 | { \ |
446 | return (gpio_bankb[gpio_bank(gpio)]->name);\ | 582 | return (gpio_bankb[gpio_bank(gpio)]->name);\ |
447 | } \ | 583 | } \ |
448 | EXPORT_SYMBOL(get_gpiop_ ## name); | 584 | EXPORT_SYMBOL(get_gpiop_ ## name); |
585 | #endif | ||
449 | 586 | ||
587 | GET_GPIO_P(data) | ||
450 | GET_GPIO_P(dir) | 588 | GET_GPIO_P(dir) |
451 | GET_GPIO_P(inen) | 589 | GET_GPIO_P(inen) |
452 | GET_GPIO_P(polar) | 590 | GET_GPIO_P(polar) |
@@ -455,21 +593,6 @@ GET_GPIO_P(both) | |||
455 | GET_GPIO_P(maska) | 593 | GET_GPIO_P(maska) |
456 | GET_GPIO_P(maskb) | 594 | GET_GPIO_P(maskb) |
457 | 595 | ||
458 | #if defined(ANOMALY_05000311) | ||
459 | unsigned short get_gpiop_data(unsigned short gpio) | ||
460 | { | ||
461 | unsigned long flags; | ||
462 | unsigned short ret; | ||
463 | local_irq_save(flags); | ||
464 | ret = gpio_bankb[gpio_bank(gpio)]->data; | ||
465 | bfin_read_CHIPID(); | ||
466 | local_irq_restore(flags); | ||
467 | return ret; | ||
468 | } | ||
469 | EXPORT_SYMBOL(get_gpiop_data); | ||
470 | #else | ||
471 | GET_GPIO_P(data) | ||
472 | #endif | ||
473 | 596 | ||
474 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
475 | /*********************************************************** | 598 | /*********************************************************** |
@@ -593,6 +716,8 @@ u32 gpio_pm_setup(void) | |||
593 | } | 716 | } |
594 | } | 717 | } |
595 | 718 | ||
719 | AWA_DUMMY_READ(maskb_set); | ||
720 | |||
596 | if (sic_iwr) | 721 | if (sic_iwr) |
597 | return sic_iwr; | 722 | return sic_iwr; |
598 | else | 723 | else |
@@ -624,12 +749,99 @@ void gpio_pm_restore(void) | |||
624 | 749 | ||
625 | gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; | 750 | gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; |
626 | } | 751 | } |
752 | AWA_DUMMY_READ(maskb); | ||
627 | } | 753 | } |
628 | 754 | ||
629 | #endif | 755 | #endif |
756 | #endif /* BF548_FAMILY */ | ||
630 | 757 | ||
758 | /*********************************************************** | ||
759 | * | ||
760 | * FUNCTIONS: Blackfin Peripheral Resource Allocation | ||
761 | * and PortMux Setup | ||
762 | * | ||
763 | * INPUTS/OUTPUTS: | ||
764 | * per Peripheral Identifier | ||
765 | * label String | ||
766 | * | ||
767 | * DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API | ||
768 | * | ||
769 | * CAUTION: | ||
770 | ************************************************************* | ||
771 | * MODIFICATION HISTORY : | ||
772 | **************************************************************/ | ||
773 | |||
774 | #ifdef BF548_FAMILY | ||
775 | int peripheral_request(unsigned short per, const char *label) | ||
776 | { | ||
777 | unsigned long flags; | ||
778 | unsigned short ident = P_IDENT(per); | ||
779 | |||
780 | /* | ||
781 | * Don't cares are pins with only one dedicated function | ||
782 | */ | ||
783 | |||
784 | if (per & P_DONTCARE) | ||
785 | return 0; | ||
786 | |||
787 | if (!(per & P_DEFINED)) | ||
788 | return -ENODEV; | ||
789 | |||
790 | if (check_gpio(ident) < 0) | ||
791 | return -EINVAL; | ||
792 | |||
793 | local_irq_save(flags); | ||
794 | |||
795 | if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
796 | printk(KERN_ERR | ||
797 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", | ||
798 | __FUNCTION__, ident, get_label(ident)); | ||
799 | dump_stack(); | ||
800 | local_irq_restore(flags); | ||
801 | return -EBUSY; | ||
802 | } | ||
803 | |||
804 | if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) { | ||
805 | |||
806 | u16 funct = get_portmux(ident); | ||
807 | |||
808 | /* | ||
809 | * Pin functions like AMC address strobes my | ||
810 | * be requested and used by several drivers | ||
811 | */ | ||
812 | |||
813 | if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) { | ||
814 | |||
815 | /* | ||
816 | * Allow that the identical pin function can | ||
817 | * be requested from the same driver twice | ||
818 | */ | ||
819 | |||
820 | if (cmp_label(ident, label) == 0) | ||
821 | goto anyway; | ||
631 | 822 | ||
823 | printk(KERN_ERR | ||
824 | "%s: Peripheral %d function %d is already reserved by %s !\n", | ||
825 | __FUNCTION__, ident, P_FUNCT2MUX(per), get_label(ident)); | ||
826 | dump_stack(); | ||
827 | local_irq_restore(flags); | ||
828 | return -EBUSY; | ||
829 | } | ||
830 | } | ||
632 | 831 | ||
832 | anyway: | ||
833 | reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); | ||
834 | |||
835 | portmux_setup(ident, P_FUNCT2MUX(per)); | ||
836 | port_setup(ident, PERIPHERAL_USAGE); | ||
837 | |||
838 | local_irq_restore(flags); | ||
839 | set_label(ident, label); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | EXPORT_SYMBOL(peripheral_request); | ||
844 | #else | ||
633 | 845 | ||
634 | int peripheral_request(unsigned short per, const char *label) | 846 | int peripheral_request(unsigned short per, const char *label) |
635 | { | 847 | { |
@@ -680,7 +892,7 @@ int peripheral_request(unsigned short per, const char *label) | |||
680 | 892 | ||
681 | printk(KERN_ERR | 893 | printk(KERN_ERR |
682 | "%s: Peripheral %d function %d is already" | 894 | "%s: Peripheral %d function %d is already" |
683 | "reserved by %s !\n", | 895 | " reserved by %s !\n", |
684 | __FUNCTION__, ident, P_FUNCT2MUX(per), | 896 | __FUNCTION__, ident, P_FUNCT2MUX(per), |
685 | get_label(ident)); | 897 | get_label(ident)); |
686 | dump_stack(); | 898 | dump_stack(); |
@@ -691,8 +903,6 @@ int peripheral_request(unsigned short per, const char *label) | |||
691 | } | 903 | } |
692 | 904 | ||
693 | anyway: | 905 | anyway: |
694 | |||
695 | |||
696 | portmux_setup(per, P_FUNCT2MUX(per)); | 906 | portmux_setup(per, P_FUNCT2MUX(per)); |
697 | 907 | ||
698 | port_setup(ident, PERIPHERAL_USAGE); | 908 | port_setup(ident, PERIPHERAL_USAGE); |
@@ -704,6 +914,7 @@ anyway: | |||
704 | return 0; | 914 | return 0; |
705 | } | 915 | } |
706 | EXPORT_SYMBOL(peripheral_request); | 916 | EXPORT_SYMBOL(peripheral_request); |
917 | #endif | ||
707 | 918 | ||
708 | int peripheral_request_list(unsigned short per[], const char *label) | 919 | int peripheral_request_list(unsigned short per[], const char *label) |
709 | { | 920 | { |
@@ -711,9 +922,15 @@ int peripheral_request_list(unsigned short per[], const char *label) | |||
711 | int ret; | 922 | int ret; |
712 | 923 | ||
713 | for (cnt = 0; per[cnt] != 0; cnt++) { | 924 | for (cnt = 0; per[cnt] != 0; cnt++) { |
925 | |||
714 | ret = peripheral_request(per[cnt], label); | 926 | ret = peripheral_request(per[cnt], label); |
715 | if (ret < 0) | 927 | |
716 | return ret; | 928 | if (ret < 0) { |
929 | for ( ; cnt > 0; cnt--) { | ||
930 | peripheral_free(per[cnt - 1]); | ||
931 | } | ||
932 | return ret; | ||
933 | } | ||
717 | } | 934 | } |
718 | 935 | ||
719 | return 0; | 936 | return 0; |
@@ -748,6 +965,8 @@ void peripheral_free(unsigned short per) | |||
748 | 965 | ||
749 | reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); | 966 | reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident); |
750 | 967 | ||
968 | set_label(ident, "free"); | ||
969 | |||
751 | local_irq_restore(flags); | 970 | local_irq_restore(flags); |
752 | } | 971 | } |
753 | EXPORT_SYMBOL(peripheral_free); | 972 | EXPORT_SYMBOL(peripheral_free); |
@@ -768,8 +987,8 @@ EXPORT_SYMBOL(peripheral_free_list); | |||
768 | * FUNCTIONS: Blackfin GPIO Driver | 987 | * FUNCTIONS: Blackfin GPIO Driver |
769 | * | 988 | * |
770 | * INPUTS/OUTPUTS: | 989 | * INPUTS/OUTPUTS: |
771 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS | 990 | * gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS |
772 | * | 991 | * label String |
773 | * | 992 | * |
774 | * DESCRIPTION: Blackfin GPIO Driver API | 993 | * DESCRIPTION: Blackfin GPIO Driver API |
775 | * | 994 | * |
@@ -787,17 +1006,39 @@ int gpio_request(unsigned short gpio, const char *label) | |||
787 | 1006 | ||
788 | local_irq_save(flags); | 1007 | local_irq_save(flags); |
789 | 1008 | ||
1009 | /* | ||
1010 | * Allow that the identical GPIO can | ||
1011 | * be requested from the same driver twice | ||
1012 | * Do nothing and return - | ||
1013 | */ | ||
1014 | |||
1015 | if (cmp_label(gpio, label) == 0) { | ||
1016 | local_irq_restore(flags); | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
790 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | 1020 | if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { |
791 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio); | 1021 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
1022 | gpio, get_label(gpio)); | ||
792 | dump_stack(); | 1023 | dump_stack(); |
793 | local_irq_restore(flags); | 1024 | local_irq_restore(flags); |
794 | return -EBUSY; | 1025 | return -EBUSY; |
795 | } | 1026 | } |
1027 | if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) { | ||
1028 | printk(KERN_ERR | ||
1029 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", | ||
1030 | gpio, get_label(gpio)); | ||
1031 | dump_stack(); | ||
1032 | local_irq_restore(flags); | ||
1033 | return -EBUSY; | ||
1034 | } | ||
1035 | |||
796 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); | 1036 | reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); |
797 | 1037 | ||
798 | local_irq_restore(flags); | 1038 | local_irq_restore(flags); |
799 | 1039 | ||
800 | port_setup(gpio, GPIO_USAGE); | 1040 | port_setup(gpio, GPIO_USAGE); |
1041 | set_label(gpio, label); | ||
801 | 1042 | ||
802 | return 0; | 1043 | return 0; |
803 | } | 1044 | } |
@@ -823,10 +1064,57 @@ void gpio_free(unsigned short gpio) | |||
823 | 1064 | ||
824 | reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); | 1065 | reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
825 | 1066 | ||
1067 | set_label(gpio, "free"); | ||
1068 | |||
826 | local_irq_restore(flags); | 1069 | local_irq_restore(flags); |
827 | } | 1070 | } |
828 | EXPORT_SYMBOL(gpio_free); | 1071 | EXPORT_SYMBOL(gpio_free); |
829 | 1072 | ||
1073 | #ifdef BF548_FAMILY | ||
1074 | void gpio_direction_input(unsigned short gpio) | ||
1075 | { | ||
1076 | unsigned long flags; | ||
1077 | |||
1078 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
1079 | |||
1080 | local_irq_save(flags); | ||
1081 | gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); | ||
1082 | gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); | ||
1083 | local_irq_restore(flags); | ||
1084 | } | ||
1085 | EXPORT_SYMBOL(gpio_direction_input); | ||
1086 | |||
1087 | void gpio_direction_output(unsigned short gpio) | ||
1088 | { | ||
1089 | unsigned long flags; | ||
1090 | |||
1091 | BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); | ||
1092 | |||
1093 | local_irq_save(flags); | ||
1094 | gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); | ||
1095 | gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); | ||
1096 | local_irq_restore(flags); | ||
1097 | } | ||
1098 | EXPORT_SYMBOL(gpio_direction_output); | ||
1099 | |||
1100 | void gpio_set_value(unsigned short gpio, unsigned short arg) | ||
1101 | { | ||
1102 | if (arg) | ||
1103 | gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); | ||
1104 | else | ||
1105 | gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio); | ||
1106 | |||
1107 | } | ||
1108 | EXPORT_SYMBOL(gpio_set_value); | ||
1109 | |||
1110 | unsigned short gpio_get_value(unsigned short gpio) | ||
1111 | { | ||
1112 | return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); | ||
1113 | } | ||
1114 | EXPORT_SYMBOL(gpio_get_value); | ||
1115 | |||
1116 | #else | ||
1117 | |||
830 | void gpio_direction_input(unsigned short gpio) | 1118 | void gpio_direction_input(unsigned short gpio) |
831 | { | 1119 | { |
832 | unsigned long flags; | 1120 | unsigned long flags; |
@@ -836,6 +1124,7 @@ void gpio_direction_input(unsigned short gpio) | |||
836 | local_irq_save(flags); | 1124 | local_irq_save(flags); |
837 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); | 1125 | gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); |
838 | gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); | 1126 | gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); |
1127 | AWA_DUMMY_READ(inen); | ||
839 | local_irq_restore(flags); | 1128 | local_irq_restore(flags); |
840 | } | 1129 | } |
841 | EXPORT_SYMBOL(gpio_direction_input); | 1130 | EXPORT_SYMBOL(gpio_direction_input); |
@@ -849,6 +1138,28 @@ void gpio_direction_output(unsigned short gpio) | |||
849 | local_irq_save(flags); | 1138 | local_irq_save(flags); |
850 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); | 1139 | gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
851 | gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); | 1140 | gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); |
1141 | AWA_DUMMY_READ(dir); | ||
852 | local_irq_restore(flags); | 1142 | local_irq_restore(flags); |
853 | } | 1143 | } |
854 | EXPORT_SYMBOL(gpio_direction_output); | 1144 | EXPORT_SYMBOL(gpio_direction_output); |
1145 | |||
1146 | /* If we are booting from SPI and our board lacks a strong enough pull up, | ||
1147 | * the core can reset and execute the bootrom faster than the resistor can | ||
1148 | * pull the signal logically high. To work around this (common) error in | ||
1149 | * board design, we explicitly set the pin back to GPIO mode, force /CS | ||
1150 | * high, and wait for the electrons to do their thing. | ||
1151 | * | ||
1152 | * This function only makes sense to be called from reset code, but it | ||
1153 | * lives here as we need to force all the GPIO states w/out going through | ||
1154 | * BUG() checks and such. | ||
1155 | */ | ||
1156 | void bfin_gpio_reset_spi0_ssel1(void) | ||
1157 | { | ||
1158 | u16 gpio = P_IDENT(P_SPI0_SSEL1); | ||
1159 | |||
1160 | port_setup(gpio, GPIO_USAGE); | ||
1161 | gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); | ||
1162 | udelay(1); | ||
1163 | } | ||
1164 | |||
1165 | #endif /*BF548_FAMILY */ | ||
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 70455949cfd2..2198afe40f33 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c | |||
@@ -60,6 +60,7 @@ EXPORT_SYMBOL(csum_partial_copy); | |||
60 | * their interface isn't gonna change any time soon now, so | 60 | * their interface isn't gonna change any time soon now, so |
61 | * it's OK to leave it out of version control. | 61 | * it's OK to leave it out of version control. |
62 | */ | 62 | */ |
63 | EXPORT_SYMBOL(strcpy); | ||
63 | EXPORT_SYMBOL(memcpy); | 64 | EXPORT_SYMBOL(memcpy); |
64 | EXPORT_SYMBOL(memset); | 65 | EXPORT_SYMBOL(memset); |
65 | EXPORT_SYMBOL(memcmp); | 66 | EXPORT_SYMBOL(memcmp); |
diff --git a/arch/blackfin/kernel/cacheinit.c b/arch/blackfin/kernel/cacheinit.c index 4d41a40e8133..62cbba7364b0 100644 --- a/arch/blackfin/kernel/cacheinit.c +++ b/arch/blackfin/kernel/cacheinit.c | |||
@@ -21,9 +21,10 @@ | |||
21 | 21 | ||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/blackfin.h> | 23 | #include <asm/blackfin.h> |
24 | #include <asm/cplb.h> | ||
24 | #include <asm/cplbinit.h> | 25 | #include <asm/cplbinit.h> |
25 | 26 | ||
26 | #if defined(CONFIG_BLKFIN_CACHE) | 27 | #if defined(CONFIG_BFIN_ICACHE) |
27 | void bfin_icache_init(void) | 28 | void bfin_icache_init(void) |
28 | { | 29 | { |
29 | unsigned long *table = icplb_table; | 30 | unsigned long *table = icplb_table; |
@@ -44,7 +45,7 @@ void bfin_icache_init(void) | |||
44 | } | 45 | } |
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | #if defined(CONFIG_BLKFIN_DCACHE) | 48 | #if defined(CONFIG_BFIN_DCACHE) |
48 | void bfin_dcache_init(void) | 49 | void bfin_dcache_init(void) |
49 | { | 50 | { |
50 | unsigned long *table = dcplb_table; | 51 | unsigned long *table = dcplb_table; |
diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c index bbdb403fcb55..f2db6a5e2b5b 100644 --- a/arch/blackfin/kernel/cplbinit.c +++ b/arch/blackfin/kernel/cplbinit.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | 24 | ||
25 | #include <asm/blackfin.h> | 25 | #include <asm/blackfin.h> |
26 | #include <asm/cplb.h> | ||
26 | #include <asm/cplbinit.h> | 27 | #include <asm/cplbinit.h> |
27 | 28 | ||
28 | u_long icplb_table[MAX_CPLBS+1]; | 29 | u_long icplb_table[MAX_CPLBS+1]; |
@@ -56,7 +57,7 @@ struct s_cplb { | |||
56 | struct cplb_tab switch_d; | 57 | struct cplb_tab switch_d; |
57 | }; | 58 | }; |
58 | 59 | ||
59 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) | 60 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) |
60 | static struct cplb_desc cplb_data[] = { | 61 | static struct cplb_desc cplb_data[] = { |
61 | { | 62 | { |
62 | .start = 0, | 63 | .start = 0, |
@@ -230,8 +231,8 @@ static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_en | |||
230 | cplb_data[i].psize, | 231 | cplb_data[i].psize, |
231 | cplb_data[i].i_conf); | 232 | cplb_data[i].i_conf); |
232 | } else { | 233 | } else { |
233 | #if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263)) | 234 | #if defined(CONFIG_BFIN_ICACHE) |
234 | if (i == SDRAM_KERN) { | 235 | if (ANOMALY_05000263 && i == SDRAM_KERN) { |
235 | fill_cplbtab(t, | 236 | fill_cplbtab(t, |
236 | cplb_data[i].start, | 237 | cplb_data[i].start, |
237 | cplb_data[i].end, | 238 | cplb_data[i].end, |
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c new file mode 100644 index 000000000000..6ec518a81113 --- /dev/null +++ b/arch/blackfin/kernel/early_printk.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/kernel/early_printk.c | ||
3 | * Based on: arch/x86_64/kernel/early_printk.c | ||
4 | * Author: Robin Getz <rgetz@blackfin.uclinux.org | ||
5 | * | ||
6 | * Created: 14Aug2007 | ||
7 | * Description: allow a console to be used for early printk | ||
8 | * | ||
9 | * Modified: | ||
10 | * Copyright 2004-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 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/serial_core.h> | ||
28 | #include <linux/console.h> | ||
29 | #include <linux/string.h> | ||
30 | #include <asm/blackfin.h> | ||
31 | #include <asm/irq_handler.h> | ||
32 | #include <asm/early_printk.h> | ||
33 | |||
34 | #ifdef CONFIG_SERIAL_BFIN | ||
35 | extern struct console *bfin_earlyserial_init(unsigned int port, | ||
36 | unsigned int cflag); | ||
37 | #endif | ||
38 | |||
39 | static struct console *early_console; | ||
40 | |||
41 | /* Default console */ | ||
42 | #define DEFAULT_PORT 0 | ||
43 | #define DEFAULT_CFLAG CS8|B57600 | ||
44 | |||
45 | /* Default console for early crashes */ | ||
46 | #define DEFAULT_EARLY_PORT "serial,uart0,57600" | ||
47 | |||
48 | #ifdef CONFIG_SERIAL_CORE | ||
49 | /* What should get here is "0,57600" */ | ||
50 | static struct console * __init earlyserial_init(char *buf) | ||
51 | { | ||
52 | int baud, bit; | ||
53 | char parity; | ||
54 | unsigned int serial_port = DEFAULT_PORT; | ||
55 | unsigned int cflag = DEFAULT_CFLAG; | ||
56 | |||
57 | serial_port = simple_strtoul(buf, &buf, 10); | ||
58 | buf++; | ||
59 | |||
60 | cflag = 0; | ||
61 | baud = simple_strtoul(buf, &buf, 10); | ||
62 | switch (baud) { | ||
63 | case 1200: | ||
64 | cflag |= B1200; | ||
65 | break; | ||
66 | case 2400: | ||
67 | cflag |= B2400; | ||
68 | break; | ||
69 | case 4800: | ||
70 | cflag |= B4800; | ||
71 | break; | ||
72 | case 9600: | ||
73 | cflag |= B9600; | ||
74 | break; | ||
75 | case 19200: | ||
76 | cflag |= B19200; | ||
77 | break; | ||
78 | case 38400: | ||
79 | cflag |= B38400; | ||
80 | break; | ||
81 | case 115200: | ||
82 | cflag |= B115200; | ||
83 | break; | ||
84 | default: | ||
85 | cflag |= B57600; | ||
86 | } | ||
87 | |||
88 | parity = buf[0]; | ||
89 | buf++; | ||
90 | switch (parity) { | ||
91 | case 'e': | ||
92 | cflag |= PARENB; | ||
93 | break; | ||
94 | case 'o': | ||
95 | cflag |= PARODD; | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | bit = simple_strtoul(buf, &buf, 10); | ||
100 | switch (bit) { | ||
101 | case 5: | ||
102 | cflag |= CS5; | ||
103 | break; | ||
104 | case 6: | ||
105 | cflag |= CS5; | ||
106 | break; | ||
107 | case 7: | ||
108 | cflag |= CS5; | ||
109 | break; | ||
110 | default: | ||
111 | cflag |= CS8; | ||
112 | } | ||
113 | |||
114 | #ifdef CONFIG_SERIAL_BFIN | ||
115 | return bfin_earlyserial_init(serial_port, cflag); | ||
116 | #else | ||
117 | return NULL; | ||
118 | #endif | ||
119 | |||
120 | } | ||
121 | #endif | ||
122 | |||
123 | int __init setup_early_printk(char *buf) | ||
124 | { | ||
125 | |||
126 | /* Crashing in here would be really bad, so check both the var | ||
127 | and the pointer before we start using it | ||
128 | */ | ||
129 | if (!buf) | ||
130 | return 0; | ||
131 | |||
132 | if (!*buf) | ||
133 | return 0; | ||
134 | |||
135 | if (early_console != NULL) | ||
136 | return 0; | ||
137 | |||
138 | #ifdef CONFIG_SERIAL_BFIN | ||
139 | /* Check for Blackfin Serial */ | ||
140 | if (!strncmp(buf, "serial,uart", 11)) { | ||
141 | buf += 11; | ||
142 | early_console = earlyserial_init(buf); | ||
143 | } | ||
144 | #endif | ||
145 | #ifdef CONFIG_FB | ||
146 | /* TODO: add framebuffer console support */ | ||
147 | #endif | ||
148 | |||
149 | if (likely(early_console)) { | ||
150 | early_console->flags |= CON_BOOT; | ||
151 | |||
152 | register_console(early_console); | ||
153 | printk(KERN_INFO "early printk enabled on %s%d\n", | ||
154 | early_console->name, | ||
155 | early_console->index); | ||
156 | } | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Set up a temporary Event Vector Table, so if something bad happens before | ||
163 | * the kernel is fully started, it doesn't vector off into somewhere we don't | ||
164 | * know | ||
165 | */ | ||
166 | |||
167 | asmlinkage void __init init_early_exception_vectors(void) | ||
168 | { | ||
169 | SSYNC(); | ||
170 | |||
171 | /* cannot program in software: | ||
172 | * evt0 - emulation (jtag) | ||
173 | * evt1 - reset | ||
174 | */ | ||
175 | bfin_write_EVT2(early_trap); | ||
176 | bfin_write_EVT3(early_trap); | ||
177 | bfin_write_EVT5(early_trap); | ||
178 | bfin_write_EVT6(early_trap); | ||
179 | bfin_write_EVT7(early_trap); | ||
180 | bfin_write_EVT8(early_trap); | ||
181 | bfin_write_EVT9(early_trap); | ||
182 | bfin_write_EVT10(early_trap); | ||
183 | bfin_write_EVT11(early_trap); | ||
184 | bfin_write_EVT12(early_trap); | ||
185 | bfin_write_EVT13(early_trap); | ||
186 | bfin_write_EVT14(early_trap); | ||
187 | bfin_write_EVT15(early_trap); | ||
188 | CSYNC(); | ||
189 | |||
190 | /* Set all the return from interupt, exception, NMI to a known place | ||
191 | * so if we do a RETI, RETX or RETN by mistake - we go somewhere known | ||
192 | * Note - don't change RETS - we are in a subroutine, or | ||
193 | * RETE - since it might screw up if emulator is attached | ||
194 | */ | ||
195 | asm("\tRETI = %0; RETX = %0; RETN = %0;\n" | ||
196 | : : "p"(early_trap)); | ||
197 | |||
198 | } | ||
199 | |||
200 | asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) | ||
201 | { | ||
202 | /* This can happen before the uart is initialized, so initialize | ||
203 | * the UART now | ||
204 | */ | ||
205 | if (likely(early_console == NULL)) | ||
206 | setup_early_printk(DEFAULT_EARLY_PORT); | ||
207 | |||
208 | dump_bfin_regs(fp, retaddr); | ||
209 | dump_bfin_trace_buffer(); | ||
210 | |||
211 | panic("Died early"); | ||
212 | } | ||
213 | |||
214 | early_param("earlyprintk", setup_early_printk); | ||
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 1fc001c7abda..73647c158774 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/kallsyms.h> | 34 | #include <linux/kallsyms.h> |
35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
36 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
37 | #include <asm/trace.h> | ||
37 | 38 | ||
38 | static unsigned long irq_err_count; | 39 | static unsigned long irq_err_count; |
39 | static spinlock_t irq_controller_lock; | 40 | static spinlock_t irq_controller_lock; |
@@ -97,9 +98,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
97 | */ | 98 | */ |
98 | 99 | ||
99 | #ifdef CONFIG_DO_IRQ_L1 | 100 | #ifdef CONFIG_DO_IRQ_L1 |
100 | asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)__attribute__((l1_text)); | 101 | __attribute__((l1_text)) |
101 | #endif | 102 | #endif |
102 | |||
103 | asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) | 103 | asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) |
104 | { | 104 | { |
105 | struct pt_regs *old_regs; | 105 | struct pt_regs *old_regs; |
@@ -144,4 +144,12 @@ void __init init_IRQ(void) | |||
144 | } | 144 | } |
145 | 145 | ||
146 | init_arch_irq(); | 146 | init_arch_irq(); |
147 | |||
148 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND | ||
149 | /* Now that evt_ivhw is set up, turn this on */ | ||
150 | trace_buff_offset = 0; | ||
151 | bfin_write_TBUFCTL(BFIN_TRACE_ON); | ||
152 | printk(KERN_INFO "Hardware Trace expanded to %ik\n", | ||
153 | 1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN); | ||
154 | #endif | ||
147 | } | 155 | } |
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 6a7aefe48346..9124467651c4 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -134,31 +134,6 @@ void cpu_idle(void) | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | void machine_restart(char *__unused) | ||
138 | { | ||
139 | #if defined(CONFIG_BLKFIN_CACHE) | ||
140 | bfin_write_IMEM_CONTROL(0x01); | ||
141 | SSYNC(); | ||
142 | #endif | ||
143 | bfin_reset(); | ||
144 | /* Dont do anything till the reset occurs */ | ||
145 | while (1) { | ||
146 | SSYNC(); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | void machine_halt(void) | ||
151 | { | ||
152 | for (;;) | ||
153 | asm volatile ("idle"); | ||
154 | } | ||
155 | |||
156 | void machine_power_off(void) | ||
157 | { | ||
158 | for (;;) | ||
159 | asm volatile ("idle"); | ||
160 | } | ||
161 | |||
162 | void show_regs(struct pt_regs *regs) | 137 | void show_regs(struct pt_regs *regs) |
163 | { | 138 | { |
164 | printk(KERN_NOTICE "\n"); | 139 | printk(KERN_NOTICE "\n"); |
@@ -420,7 +395,8 @@ void finish_atomic_sections (struct pt_regs *regs) | |||
420 | #if defined(CONFIG_ACCESS_CHECK) | 395 | #if defined(CONFIG_ACCESS_CHECK) |
421 | int _access_ok(unsigned long addr, unsigned long size) | 396 | int _access_ok(unsigned long addr, unsigned long size) |
422 | { | 397 | { |
423 | 398 | if (size == 0) | |
399 | return 1; | ||
424 | if (addr > (addr + size)) | 400 | if (addr > (addr + size)) |
425 | return 0; | 401 | return 0; |
426 | if (segment_eq(get_fs(), KERNEL_DS)) | 402 | if (segment_eq(get_fs(), KERNEL_DS)) |
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index ed800c7456dd..64ce5fea8609 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/processor.h> | 44 | #include <asm/processor.h> |
45 | #include <asm/asm-offsets.h> | 45 | #include <asm/asm-offsets.h> |
46 | #include <asm/dma.h> | 46 | #include <asm/dma.h> |
47 | #include <asm/fixed_code.h> | ||
47 | 48 | ||
48 | #define MAX_SHARED_LIBS 3 | 49 | #define MAX_SHARED_LIBS 3 |
49 | #define TEXT_OFFSET 0 | 50 | #define TEXT_OFFSET 0 |
@@ -169,6 +170,9 @@ static inline int is_user_addr_valid(struct task_struct *child, | |||
169 | && start + len <= (unsigned long)sraml->addr + sraml->length) | 170 | && start + len <= (unsigned long)sraml->addr + sraml->length) |
170 | return 0; | 171 | return 0; |
171 | 172 | ||
173 | if (start >= FIXED_CODE_START && start + len <= FIXED_CODE_END) | ||
174 | return 0; | ||
175 | |||
172 | return -EIO; | 176 | return -EIO; |
173 | } | 177 | } |
174 | 178 | ||
@@ -215,9 +219,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
215 | copied = sizeof(tmp); | 219 | copied = sizeof(tmp); |
216 | } else | 220 | } else |
217 | #endif | 221 | #endif |
218 | copied = | 222 | if (addr + add >= FIXED_CODE_START |
219 | access_process_vm(child, addr + add, &tmp, | 223 | && addr + add + sizeof(tmp) <= FIXED_CODE_END) { |
220 | sizeof(tmp), 0); | 224 | memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); |
225 | copied = sizeof(tmp); | ||
226 | } else | ||
227 | copied = access_process_vm(child, addr + add, &tmp, | ||
228 | sizeof(tmp), 0); | ||
221 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); | 229 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); |
222 | if (copied != sizeof(tmp)) | 230 | if (copied != sizeof(tmp)) |
223 | break; | 231 | break; |
@@ -281,9 +289,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
281 | copied = sizeof(data); | 289 | copied = sizeof(data); |
282 | } else | 290 | } else |
283 | #endif | 291 | #endif |
284 | copied = | 292 | if (addr + add >= FIXED_CODE_START |
285 | access_process_vm(child, addr + add, &data, | 293 | && addr + add + sizeof(data) <= FIXED_CODE_END) { |
286 | sizeof(data), 1); | 294 | memcpy((void *)(addr + add), &data, sizeof(data)); |
295 | copied = sizeof(data); | ||
296 | } else | ||
297 | copied = access_process_vm(child, addr + add, &data, | ||
298 | sizeof(data), 1); | ||
287 | pr_debug("ptrace: copied size %d\n", copied); | 299 | pr_debug("ptrace: copied size %d\n", copied); |
288 | if (copied != sizeof(data)) | 300 | if (copied != sizeof(data)) |
289 | break; | 301 | break; |
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c new file mode 100644 index 000000000000..356078ec462b --- /dev/null +++ b/arch/blackfin/kernel/reboot.c | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * arch/blackfin/kernel/reboot.c - handle shutdown/reboot | ||
3 | * | ||
4 | * Copyright 2004-2007 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <asm/bfin-global.h> | ||
11 | #include <asm/reboot.h> | ||
12 | #include <asm/system.h> | ||
13 | |||
14 | #if defined(BF537_FAMILY) || defined(BF533_FAMILY) | ||
15 | #define SYSCR_VAL 0x0 | ||
16 | #elif defined(BF561_FAMILY) | ||
17 | #define SYSCR_VAL 0x20 | ||
18 | #elif defined(BF548_FAMILY) | ||
19 | #define SYSCR_VAL 0x10 | ||
20 | #endif | ||
21 | |||
22 | /* A system soft reset makes external memory unusable | ||
23 | * so force this function into L1. | ||
24 | */ | ||
25 | __attribute__((l1_text)) | ||
26 | void bfin_reset(void) | ||
27 | { | ||
28 | /* force BMODE and disable Core B (as needed) */ | ||
29 | bfin_write_SYSCR(SYSCR_VAL); | ||
30 | |||
31 | /* we use asm ssync here because it's save and we save some L1 */ | ||
32 | asm("ssync;"); | ||
33 | |||
34 | while (1) { | ||
35 | /* initiate system soft reset with magic 0x7 */ | ||
36 | bfin_write_SWRST(0x7); | ||
37 | asm("ssync;"); | ||
38 | /* clear system soft reset */ | ||
39 | bfin_write_SWRST(0); | ||
40 | asm("ssync;"); | ||
41 | /* issue core reset */ | ||
42 | asm("raise 1"); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | __attribute__((weak)) | ||
47 | void native_machine_restart(char *cmd) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | void machine_restart(char *cmd) | ||
52 | { | ||
53 | native_machine_restart(cmd); | ||
54 | local_irq_disable(); | ||
55 | bfin_reset(); | ||
56 | } | ||
57 | |||
58 | __attribute__((weak)) | ||
59 | void native_machine_halt(void) | ||
60 | { | ||
61 | idle_with_irq_disabled(); | ||
62 | } | ||
63 | |||
64 | void machine_halt(void) | ||
65 | { | ||
66 | native_machine_halt(); | ||
67 | } | ||
68 | |||
69 | __attribute__((weak)) | ||
70 | void native_machine_power_off(void) | ||
71 | { | ||
72 | idle_with_irq_disabled(); | ||
73 | } | ||
74 | |||
75 | void machine_power_off(void) | ||
76 | { | ||
77 | native_machine_power_off(); | ||
78 | } | ||
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 88f221b89b33..8dcd76e87ed5 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -39,10 +39,12 @@ | |||
39 | #include <linux/cramfs_fs.h> | 39 | #include <linux/cramfs_fs.h> |
40 | #include <linux/romfs_fs.h> | 40 | #include <linux/romfs_fs.h> |
41 | 41 | ||
42 | #include <asm/cplb.h> | ||
42 | #include <asm/cacheflush.h> | 43 | #include <asm/cacheflush.h> |
43 | #include <asm/blackfin.h> | 44 | #include <asm/blackfin.h> |
44 | #include <asm/cplbinit.h> | 45 | #include <asm/cplbinit.h> |
45 | #include <asm/fixed_code.h> | 46 | #include <asm/fixed_code.h> |
47 | #include <asm/early_printk.h> | ||
46 | 48 | ||
47 | u16 _bfin_swrst; | 49 | u16 _bfin_swrst; |
48 | 50 | ||
@@ -66,21 +68,21 @@ char __initdata command_line[COMMAND_LINE_SIZE]; | |||
66 | 68 | ||
67 | void __init bf53x_cache_init(void) | 69 | void __init bf53x_cache_init(void) |
68 | { | 70 | { |
69 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) | 71 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) |
70 | generate_cpl_tables(); | 72 | generate_cpl_tables(); |
71 | #endif | 73 | #endif |
72 | 74 | ||
73 | #ifdef CONFIG_BLKFIN_CACHE | 75 | #ifdef CONFIG_BFIN_ICACHE |
74 | bfin_icache_init(); | 76 | bfin_icache_init(); |
75 | printk(KERN_INFO "Instruction Cache Enabled\n"); | 77 | printk(KERN_INFO "Instruction Cache Enabled\n"); |
76 | #endif | 78 | #endif |
77 | 79 | ||
78 | #ifdef CONFIG_BLKFIN_DCACHE | 80 | #ifdef CONFIG_BFIN_DCACHE |
79 | bfin_dcache_init(); | 81 | bfin_dcache_init(); |
80 | printk(KERN_INFO "Data Cache Enabled" | 82 | printk(KERN_INFO "Data Cache Enabled" |
81 | # if defined CONFIG_BLKFIN_WB | 83 | # if defined CONFIG_BFIN_WB |
82 | " (write-back)" | 84 | " (write-back)" |
83 | # elif defined CONFIG_BLKFIN_WT | 85 | # elif defined CONFIG_BFIN_WT |
84 | " (write-through)" | 86 | " (write-through)" |
85 | # endif | 87 | # endif |
86 | "\n"); | 88 | "\n"); |
@@ -156,8 +158,10 @@ static __init void parse_cmdline_early(char *cmdline_p) | |||
156 | 1; | 158 | 1; |
157 | } | 159 | } |
158 | } | 160 | } |
161 | } else if (!memcmp(to, "earlyprintk=", 12)) { | ||
162 | to += 12; | ||
163 | setup_early_printk(to); | ||
159 | } | 164 | } |
160 | |||
161 | } | 165 | } |
162 | c = *(to++); | 166 | c = *(to++); |
163 | if (!c) | 167 | if (!c) |
@@ -176,22 +180,36 @@ void __init setup_arch(char **cmdline_p) | |||
176 | #ifdef CONFIG_DUMMY_CONSOLE | 180 | #ifdef CONFIG_DUMMY_CONSOLE |
177 | conswitchp = &dummy_con; | 181 | conswitchp = &dummy_con; |
178 | #endif | 182 | #endif |
183 | |||
184 | #if defined(CONFIG_CMDLINE_BOOL) | ||
185 | strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line)); | ||
186 | command_line[sizeof(command_line) - 1] = 0; | ||
187 | #endif | ||
188 | |||
189 | /* Keep a copy of command line */ | ||
190 | *cmdline_p = &command_line[0]; | ||
191 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
192 | boot_command_line[COMMAND_LINE_SIZE - 1] = '\0'; | ||
193 | |||
194 | /* setup memory defaults from the user config */ | ||
195 | physical_mem_end = 0; | ||
196 | _ramend = CONFIG_MEM_SIZE * 1024 * 1024; | ||
197 | |||
198 | parse_cmdline_early(&command_line[0]); | ||
199 | |||
179 | cclk = get_cclk(); | 200 | cclk = get_cclk(); |
180 | sclk = get_sclk(); | 201 | sclk = get_sclk(); |
181 | 202 | ||
182 | #if !defined(CONFIG_BFIN_KERNEL_CLOCK) && defined(ANOMALY_05000273) | 203 | #if !defined(CONFIG_BFIN_KERNEL_CLOCK) |
183 | if (cclk == sclk) | 204 | if (ANOMALY_05000273 && cclk == sclk) |
184 | panic("ANOMALY 05000273, SCLK can not be same as CCLK"); | 205 | panic("ANOMALY 05000273, SCLK can not be same as CCLK"); |
185 | #endif | 206 | #endif |
186 | 207 | ||
187 | #if defined(ANOMALY_05000266) | 208 | #ifdef BF561_FAMILY |
188 | bfin_read_IMDMA_D0_IRQ_STATUS(); | 209 | if (ANOMALY_05000266) { |
189 | bfin_read_IMDMA_D1_IRQ_STATUS(); | 210 | bfin_read_IMDMA_D0_IRQ_STATUS(); |
190 | #endif | 211 | bfin_read_IMDMA_D1_IRQ_STATUS(); |
191 | 212 | } | |
192 | #ifdef DEBUG_SERIAL_EARLY_INIT | ||
193 | bfin_console_init(); /* early console registration */ | ||
194 | /* this give a chance to get printk() working before crash. */ | ||
195 | #endif | 213 | #endif |
196 | 214 | ||
197 | printk(KERN_INFO "Hardware Trace "); | 215 | printk(KERN_INFO "Hardware Trace "); |
@@ -212,22 +230,6 @@ void __init setup_arch(char **cmdline_p) | |||
212 | flash_probe(); | 230 | flash_probe(); |
213 | #endif | 231 | #endif |
214 | 232 | ||
215 | #if defined(CONFIG_CMDLINE_BOOL) | ||
216 | strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line)); | ||
217 | command_line[sizeof(command_line) - 1] = 0; | ||
218 | #endif | ||
219 | |||
220 | /* Keep a copy of command line */ | ||
221 | *cmdline_p = &command_line[0]; | ||
222 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
223 | boot_command_line[COMMAND_LINE_SIZE - 1] = '\0'; | ||
224 | |||
225 | /* setup memory defaults from the user config */ | ||
226 | physical_mem_end = 0; | ||
227 | _ramend = CONFIG_MEM_SIZE * 1024 * 1024; | ||
228 | |||
229 | parse_cmdline_early(&command_line[0]); | ||
230 | |||
231 | if (physical_mem_end == 0) | 233 | if (physical_mem_end == 0) |
232 | physical_mem_end = _ramend; | 234 | physical_mem_end = _ramend; |
233 | 235 | ||
@@ -260,7 +262,7 @@ void __init setup_arch(char **cmdline_p) | |||
260 | && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) | 262 | && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1) |
261 | mtd_size = | 263 | mtd_size = |
262 | PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2])); | 264 | PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2])); |
263 | # if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263)) | 265 | # if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) |
264 | /* Due to a Hardware Anomaly we need to limit the size of usable | 266 | /* Due to a Hardware Anomaly we need to limit the size of usable |
265 | * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on | 267 | * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on |
266 | * 05000263 - Hardware loop corrupted when taking an ICPLB exception | 268 | * 05000263 - Hardware loop corrupted when taking an ICPLB exception |
@@ -289,7 +291,7 @@ void __init setup_arch(char **cmdline_p) | |||
289 | _ebss = memory_mtd_start; /* define _ebss for compatible */ | 291 | _ebss = memory_mtd_start; /* define _ebss for compatible */ |
290 | #endif /* CONFIG_MTD_UCLINUX */ | 292 | #endif /* CONFIG_MTD_UCLINUX */ |
291 | 293 | ||
292 | #if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263)) | 294 | #if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263) |
293 | /* Due to a Hardware Anomaly we need to limit the size of usable | 295 | /* Due to a Hardware Anomaly we need to limit the size of usable |
294 | * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on | 296 | * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on |
295 | * 05000263 - Hardware loop corrupted when taking an ICPLB exception | 297 | * 05000263 - Hardware loop corrupted when taking an ICPLB exception |
@@ -334,13 +336,11 @@ void __init setup_arch(char **cmdline_p) | |||
334 | CPU, bfin_revid()); | 336 | CPU, bfin_revid()); |
335 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); | 337 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); |
336 | 338 | ||
337 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu Mhz System Clock\n", | 339 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", |
338 | cclk / 1000000, sclk / 1000000); | 340 | cclk / 1000000, sclk / 1000000); |
339 | 341 | ||
340 | #if defined(ANOMALY_05000273) | 342 | if (ANOMALY_05000273 && (cclk >> 1) <= sclk) |
341 | if ((cclk >> 1) <= sclk) | ||
342 | printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); | 343 | printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n"); |
343 | #endif | ||
344 | 344 | ||
345 | printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20); | 345 | printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20); |
346 | printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); | 346 | printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); |
@@ -535,9 +535,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
535 | seq_printf(m, "I-CACHE:\tOFF\n"); | 535 | seq_printf(m, "I-CACHE:\tOFF\n"); |
536 | if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)) | 536 | if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)) |
537 | seq_printf(m, "D-CACHE:\tON" | 537 | seq_printf(m, "D-CACHE:\tON" |
538 | #if defined CONFIG_BLKFIN_WB | 538 | #if defined CONFIG_BFIN_WB |
539 | " (write-back)" | 539 | " (write-back)" |
540 | #elif defined CONFIG_BLKFIN_WT | 540 | #elif defined CONFIG_BFIN_WT |
541 | " (write-through)" | 541 | " (write-through)" |
542 | #endif | 542 | #endif |
543 | "\n"); | 543 | "\n"); |
@@ -566,15 +566,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
566 | } | 566 | } |
567 | 567 | ||
568 | 568 | ||
569 | seq_printf(m, "I-CACHE Size:\t%dKB\n", BLKFIN_ICACHESIZE / 1024); | 569 | seq_printf(m, "I-CACHE Size:\t%dKB\n", BFIN_ICACHESIZE / 1024); |
570 | seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size); | 570 | seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size); |
571 | seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n", | 571 | seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n", |
572 | BLKFIN_ISUBBANKS, BLKFIN_IWAYS, BLKFIN_ILINES); | 572 | BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES); |
573 | seq_printf(m, | 573 | seq_printf(m, |
574 | "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", | 574 | "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", |
575 | dsup_banks, BLKFIN_DSUBBANKS, BLKFIN_DWAYS, | 575 | dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, |
576 | BLKFIN_DLINES); | 576 | BFIN_DLINES); |
577 | #ifdef CONFIG_BLKFIN_CACHE_LOCK | 577 | #ifdef CONFIG_BFIN_ICACHE_LOCK |
578 | switch (read_iloc()) { | 578 | switch (read_iloc()) { |
579 | case WAY0_L: | 579 | case WAY0_L: |
580 | seq_printf(m, "Way0 Locked-Down\n"); | 580 | seq_printf(m, "Way0 Locked-Down\n"); |
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 792a8416fe10..8823e9ade584 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -51,10 +51,9 @@ void __init trap_init(void) | |||
51 | CSYNC(); | 51 | CSYNC(); |
52 | } | 52 | } |
53 | 53 | ||
54 | asmlinkage void trap_c(struct pt_regs *fp); | ||
55 | |||
56 | int kstack_depth_to_print = 48; | 54 | int kstack_depth_to_print = 48; |
57 | 55 | ||
56 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | ||
58 | static int printk_address(unsigned long address) | 57 | static int printk_address(unsigned long address) |
59 | { | 58 | { |
60 | struct vm_list_struct *vml; | 59 | struct vm_list_struct *vml; |
@@ -131,10 +130,22 @@ static int printk_address(unsigned long address) | |||
131 | /* we were unable to find this address anywhere */ | 130 | /* we were unable to find this address anywhere */ |
132 | return printk("[<0x%p>]", (void *)address); | 131 | return printk("[<0x%p>]", (void *)address); |
133 | } | 132 | } |
133 | #endif | ||
134 | |||
135 | asmlinkage void double_fault_c(struct pt_regs *fp) | ||
136 | { | ||
137 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); | ||
138 | dump_bfin_regs(fp, (void *)fp->retx); | ||
139 | panic("Double Fault - unrecoverable event\n"); | ||
140 | |||
141 | } | ||
134 | 142 | ||
135 | asmlinkage void trap_c(struct pt_regs *fp) | 143 | asmlinkage void trap_c(struct pt_regs *fp) |
136 | { | 144 | { |
137 | int j, sig = 0; | 145 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
146 | int j; | ||
147 | #endif | ||
148 | int sig = 0; | ||
138 | siginfo_t info; | 149 | siginfo_t info; |
139 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | 150 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; |
140 | 151 | ||
@@ -391,10 +402,6 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
391 | break; | 402 | break; |
392 | } | 403 | } |
393 | 404 | ||
394 | info.si_signo = sig; | ||
395 | info.si_errno = 0; | ||
396 | info.si_addr = (void *)fp->pc; | ||
397 | force_sig_info(sig, &info, current); | ||
398 | if (sig != 0 && sig != SIGTRAP) { | 405 | if (sig != 0 && sig != SIGTRAP) { |
399 | unsigned long stack; | 406 | unsigned long stack; |
400 | dump_bfin_regs(fp, (void *)fp->retx); | 407 | dump_bfin_regs(fp, (void *)fp->retx); |
@@ -403,6 +410,10 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
403 | if (current->mm == NULL) | 410 | if (current->mm == NULL) |
404 | panic("Kernel exception"); | 411 | panic("Kernel exception"); |
405 | } | 412 | } |
413 | info.si_signo = sig; | ||
414 | info.si_errno = 0; | ||
415 | info.si_addr = (void *)fp->pc; | ||
416 | force_sig_info(sig, &info, current); | ||
406 | 417 | ||
407 | /* if the address that we are about to return to is not valid, set it | 418 | /* if the address that we are about to return to is not valid, set it |
408 | * to a valid address, if we have a current application or panic | 419 | * to a valid address, if we have a current application or panic |
@@ -429,24 +440,56 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
429 | 440 | ||
430 | /* Typical exception handling routines */ | 441 | /* Typical exception handling routines */ |
431 | 442 | ||
443 | #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1) | ||
444 | |||
432 | void dump_bfin_trace_buffer(void) | 445 | void dump_bfin_trace_buffer(void) |
433 | { | 446 | { |
434 | int tflags; | 447 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
448 | int tflags, i = 0; | ||
449 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND | ||
450 | int j, index; | ||
451 | #endif | ||
452 | |||
435 | trace_buffer_save(tflags); | 453 | trace_buffer_save(tflags); |
436 | 454 | ||
455 | printk(KERN_EMERG "Hardware Trace:\n"); | ||
456 | |||
437 | if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { | 457 | if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { |
438 | int i; | 458 | for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { |
439 | printk(KERN_EMERG "Hardware Trace:\n"); | 459 | printk(KERN_EMERG "%4i Target : ", i); |
440 | for (i = 0; bfin_read_TBUFSTAT() & TBUFCNT; i++) { | ||
441 | printk(KERN_EMERG "%2i Target : ", i); | ||
442 | printk_address((unsigned long)bfin_read_TBUF()); | 460 | printk_address((unsigned long)bfin_read_TBUF()); |
443 | printk("\n" KERN_EMERG " Source : "); | 461 | printk("\n" KERN_EMERG " Source : "); |
444 | printk_address((unsigned long)bfin_read_TBUF()); | 462 | printk_address((unsigned long)bfin_read_TBUF()); |
445 | printk("\n"); | 463 | printk("\n"); |
446 | } | 464 | } |
447 | } | 465 | } |
448 | 466 | ||
467 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND | ||
468 | if (trace_buff_offset) | ||
469 | index = trace_buff_offset/4 - 1; | ||
470 | else | ||
471 | index = EXPAND_LEN; | ||
472 | |||
473 | j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128; | ||
474 | while (j) { | ||
475 | printk(KERN_EMERG "%4i Target : ", i); | ||
476 | printk_address(software_trace_buff[index]); | ||
477 | index -= 1; | ||
478 | if (index < 0 ) | ||
479 | index = EXPAND_LEN; | ||
480 | printk("\n" KERN_EMERG " Source : "); | ||
481 | printk_address(software_trace_buff[index]); | ||
482 | index -= 1; | ||
483 | if (index < 0) | ||
484 | index = EXPAND_LEN; | ||
485 | printk("\n"); | ||
486 | j--; | ||
487 | i++; | ||
488 | } | ||
489 | #endif | ||
490 | |||
449 | trace_buffer_restore(tflags); | 491 | trace_buffer_restore(tflags); |
492 | #endif | ||
450 | } | 493 | } |
451 | EXPORT_SYMBOL(dump_bfin_trace_buffer); | 494 | EXPORT_SYMBOL(dump_bfin_trace_buffer); |
452 | 495 | ||
@@ -510,7 +553,9 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
510 | void dump_stack(void) | 553 | void dump_stack(void) |
511 | { | 554 | { |
512 | unsigned long stack; | 555 | unsigned long stack; |
556 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | ||
513 | int tflags; | 557 | int tflags; |
558 | #endif | ||
514 | trace_buffer_save(tflags); | 559 | trace_buffer_save(tflags); |
515 | dump_bfin_trace_buffer(); | 560 | dump_bfin_trace_buffer(); |
516 | show_stack(current, &stack); | 561 | show_stack(current, &stack); |
@@ -559,8 +604,7 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | |||
559 | unsigned short x = 0; | 604 | unsigned short x = 0; |
560 | for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { | 605 | for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { |
561 | if (!(i & 0xF)) | 606 | if (!(i & 0xF)) |
562 | printk(KERN_EMERG "\n" KERN_EMERG | 607 | printk("\n" KERN_EMERG "0x%08x: ", i); |
563 | "0x%08x: ", i); | ||
564 | 608 | ||
565 | if (get_user(x, (unsigned short *)i)) | 609 | if (get_user(x, (unsigned short *)i)) |
566 | break; | 610 | break; |
@@ -655,6 +699,42 @@ asmlinkage int sys_bfin_spinlock(int *spinlock) | |||
655 | return ret; | 699 | return ret; |
656 | } | 700 | } |
657 | 701 | ||
702 | int bfin_request_exception(unsigned int exception, void (*handler)(void)) | ||
703 | { | ||
704 | void (*curr_handler)(void); | ||
705 | |||
706 | if (exception > 0x3F) | ||
707 | return -EINVAL; | ||
708 | |||
709 | curr_handler = ex_table[exception]; | ||
710 | |||
711 | if (curr_handler != ex_replaceable) | ||
712 | return -EBUSY; | ||
713 | |||
714 | ex_table[exception] = handler; | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | EXPORT_SYMBOL(bfin_request_exception); | ||
719 | |||
720 | int bfin_free_exception(unsigned int exception, void (*handler)(void)) | ||
721 | { | ||
722 | void (*curr_handler)(void); | ||
723 | |||
724 | if (exception > 0x3F) | ||
725 | return -EINVAL; | ||
726 | |||
727 | curr_handler = ex_table[exception]; | ||
728 | |||
729 | if (curr_handler != handler) | ||
730 | return -EBUSY; | ||
731 | |||
732 | ex_table[exception] = ex_replaceable; | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | EXPORT_SYMBOL(bfin_free_exception); | ||
737 | |||
658 | void panic_cplb_error(int cplb_panic, struct pt_regs *fp) | 738 | void panic_cplb_error(int cplb_panic, struct pt_regs *fp) |
659 | { | 739 | { |
660 | switch (cplb_panic) { | 740 | switch (cplb_panic) { |
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index fb53780247bc..eec43674a465 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S | |||
@@ -49,7 +49,8 @@ SECTIONS | |||
49 | TEXT_TEXT | 49 | TEXT_TEXT |
50 | SCHED_TEXT | 50 | SCHED_TEXT |
51 | LOCK_TEXT | 51 | LOCK_TEXT |
52 | *(.text.lock) | 52 | KPROBES_TEXT |
53 | *(.text.*) | ||
53 | *(.fixup) | 54 | *(.fixup) |
54 | 55 | ||
55 | . = ALIGN(16); | 56 | . = ALIGN(16); |
@@ -61,7 +62,7 @@ SECTIONS | |||
61 | __etext = .; | 62 | __etext = .; |
62 | } | 63 | } |
63 | 64 | ||
64 | RODATA | 65 | RO_DATA(PAGE_SIZE) |
65 | 66 | ||
66 | .data : | 67 | .data : |
67 | { | 68 | { |
@@ -72,50 +73,63 @@ SECTIONS | |||
72 | __sdata = .; | 73 | __sdata = .; |
73 | . = ALIGN(THREAD_SIZE); | 74 | . = ALIGN(THREAD_SIZE); |
74 | *(.data.init_task) | 75 | *(.data.init_task) |
75 | DATA_DATA | ||
76 | CONSTRUCTORS | ||
77 | 76 | ||
78 | . = ALIGN(32); | 77 | . = ALIGN(32); |
79 | *(.data.cacheline_aligned) | 78 | *(.data.cacheline_aligned) |
80 | 79 | ||
80 | DATA_DATA | ||
81 | *(.data.*) | ||
82 | CONSTRUCTORS | ||
83 | |||
81 | . = ALIGN(THREAD_SIZE); | 84 | . = ALIGN(THREAD_SIZE); |
82 | __edata = .; | 85 | __edata = .; |
83 | } | 86 | } |
84 | 87 | ||
85 | ___init_begin = .; | 88 | ___init_begin = .; |
86 | .init : | 89 | |
90 | .init.text : | ||
87 | { | 91 | { |
88 | . = ALIGN(PAGE_SIZE); | 92 | . = ALIGN(PAGE_SIZE); |
89 | __sinittext = .; | 93 | __sinittext = .; |
90 | *(.init.text) | 94 | *(.init.text) |
91 | __einittext = .; | 95 | __einittext = .; |
96 | } | ||
97 | .init.data : | ||
98 | { | ||
99 | . = ALIGN(16); | ||
92 | *(.init.data) | 100 | *(.init.data) |
101 | } | ||
102 | .init.setup : | ||
103 | { | ||
93 | . = ALIGN(16); | 104 | . = ALIGN(16); |
94 | ___setup_start = .; | 105 | ___setup_start = .; |
95 | *(.init.setup) | 106 | *(.init.setup) |
96 | ___setup_end = .; | 107 | ___setup_end = .; |
97 | ___start___param = .; | 108 | } |
98 | *(__param) | 109 | .initcall.init : |
99 | ___stop___param = .; | 110 | { |
100 | ___initcall_start = .; | 111 | ___initcall_start = .; |
101 | INITCALLS | 112 | INITCALLS |
102 | ___initcall_end = .; | 113 | ___initcall_end = .; |
114 | } | ||
115 | .con_initcall.init : | ||
116 | { | ||
103 | ___con_initcall_start = .; | 117 | ___con_initcall_start = .; |
104 | *(.con_initcall.init) | 118 | *(.con_initcall.init) |
105 | ___con_initcall_end = .; | 119 | ___con_initcall_end = .; |
106 | ___security_initcall_start = .; | 120 | } |
107 | *(.security_initcall.init) | 121 | SECURITY_INIT |
108 | ___security_initcall_end = .; | 122 | .init.ramfs : |
123 | { | ||
109 | . = ALIGN(4); | 124 | . = ALIGN(4); |
110 | ___initramfs_start = .; | 125 | ___initramfs_start = .; |
111 | *(.init.ramfs) | 126 | *(.init.ramfs) |
112 | ___initramfs_end = .; | 127 | ___initramfs_end = .; |
113 | . = ALIGN(4); | ||
114 | } | 128 | } |
115 | 129 | ||
116 | __l1_lma_start = .; | 130 | __l1_lma_start = .; |
117 | 131 | ||
118 | .text_l1 L1_CODE_START : AT(LOADADDR(.init) + SIZEOF(.init)) | 132 | .text_l1 L1_CODE_START : AT(LOADADDR(.init.ramfs) + SIZEOF(.init.ramfs)) |
119 | { | 133 | { |
120 | . = ALIGN(4); | 134 | . = ALIGN(4); |
121 | __stext_l1 = .; | 135 | __stext_l1 = .; |
@@ -164,13 +178,19 @@ SECTIONS | |||
164 | { | 178 | { |
165 | . = ALIGN(4); | 179 | . = ALIGN(4); |
166 | ___bss_start = .; | 180 | ___bss_start = .; |
167 | *(.bss) | 181 | *(.bss .bss.*) |
168 | *(COMMON) | 182 | *(COMMON) |
169 | . = ALIGN(4); | 183 | . = ALIGN(4); |
170 | ___bss_stop = .; | 184 | ___bss_stop = .; |
171 | __end = .; | 185 | __end = .; |
172 | } | 186 | } |
173 | 187 | ||
188 | STABS_DEBUG | ||
189 | |||
190 | DWARF_DEBUG | ||
191 | |||
192 | NOTES | ||
193 | |||
174 | /DISCARD/ : | 194 | /DISCARD/ : |
175 | { | 195 | { |
176 | *(.exit.text) | 196 | *(.exit.text) |