aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 16:23:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 16:23:17 -0400
commit7f268a2ba7c884a239713696238dd4207a57dd9a (patch)
treefdc02fecda32f5df8de3ddc2c01c29ba68e6a42b /arch/blackfin/kernel
parent689796a141cea79d745a4689c65dd01c39e5e100 (diff)
parent2d2009806dd843f3adc0cbbb5d2204980f28111a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6: (30 commits) Blackfin arch: If we double fault, rather than hang forever, reset Blackfin arch: When icache is off, make sure people know it Blackfin arch: Fix bug - skip single step in high priority interrupt handler instead of disabling all interrupts in single step debugging. Blackfin arch: cache the values of vco/sclk/cclk as the overhead of doing so (~24 bytes) is worth avoiding the software mult/div routines Blackfin arch: fix bug - IMDMA is not type struct dma_register Blackfin arch: check the EXTBANKS field of the DDRCTL1 register to see if we are using both memory banks Blackfin arch: Apply Bluetechnix CM-BF527 board support patch Blackfin arch: Add unwinding for stack info, and a little more detail on trace buffer Blackfin arch: Add ISP1760 board resources to BF548-EZKIT Blackfin arch: fix bug - detect 0.1 silicon revision BF527-EZKIT as 0.0 version Blackfin arch: add missing IORESOURCE_MEM flags to UART3 Blackfin arch: Add return value check in bfin_sir_probe(), remove SSYNC(). Blackfin arch: Extend sram malloc to handle L2 SRAM. Blackfin arch: Remove useless config option. Blackfin arch: change L1 malloc to base on slab cache and lists. Blackfin arch: use local labels and ENDPROC() markings Blackfin arch: Do not need this dualcore test module in kernel. Blackfin arch: Allow ptrace to peek and poke application data in L1 data SRAM. Blackfin arch: Add ANOMALY_05000368 workaround Blackfin arch: Functional power management support ...
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/Makefile1
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c34
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c118
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbhdlr.S2
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinit.c6
-rw-r--r--arch/blackfin/kernel/dualcore_test.c49
-rw-r--r--arch/blackfin/kernel/entry.S5
-rw-r--r--arch/blackfin/kernel/kgdb.c16
-rw-r--r--arch/blackfin/kernel/module.c74
-rw-r--r--arch/blackfin/kernel/ptrace.c28
-rw-r--r--arch/blackfin/kernel/setup.c90
-rw-r--r--arch/blackfin/kernel/traps.c296
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S40
13 files changed, 597 insertions, 162 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 6140cd69c782..606adc78aa85 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -18,6 +18,5 @@ endif
18obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o 18obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
19obj-$(CONFIG_MODULES) += module.o 19obj-$(CONFIG_MODULES) += module.o
20obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o 20obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
21obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o
22obj-$(CONFIG_KGDB) += kgdb.o 21obj-$(CONFIG_KGDB) += kgdb.o
23obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 22obj-$(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 d54f19085f37..93229b3d6e3e 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -472,6 +472,40 @@ unsigned long get_dma_curr_addr(unsigned int channel)
472} 472}
473EXPORT_SYMBOL(get_dma_curr_addr); 473EXPORT_SYMBOL(get_dma_curr_addr);
474 474
475#ifdef CONFIG_PM
476int blackfin_dma_suspend(void)
477{
478 int i;
479
480#ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
481 for (i = 0; i <= CH_MEM_STREAM3_SRC; i++) {
482#else
483 for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
484#endif
485 if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
486 printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
487 return -EBUSY;
488 }
489
490 dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
491 }
492
493 return 0;
494}
495
496void blackfin_dma_resume(void)
497{
498 int i;
499
500#ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
501 for (i = 0; i <= CH_MEM_STREAM3_SRC; i++)
502#else
503 for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
504#endif
505 dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
506}
507#endif
508
475static void *__dma_memcpy(void *dest, const void *src, size_t size) 509static void *__dma_memcpy(void *dest, const void *src, size_t size)
476{ 510{
477 int direction; /* 1 - address decrease, 0 - address increase */ 511 int direction; /* 1 - address decrease, 0 - address increase */
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index b6d89d1644cc..ecbd141e0ef2 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -186,7 +186,10 @@ static struct str_ident {
186 char name[RESOURCE_LABEL_SIZE]; 186 char name[RESOURCE_LABEL_SIZE];
187} str_ident[MAX_RESOURCES]; 187} str_ident[MAX_RESOURCES];
188 188
189#if defined(CONFIG_PM) && !defined(CONFIG_BF54x) 189#if defined(CONFIG_PM)
190#if defined(CONFIG_BF54x)
191static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
192#else
190static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; 193static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
191static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; 194static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
192static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)]; 195static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -206,7 +209,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INT
206#ifdef BF561_FAMILY 209#ifdef BF561_FAMILY
207static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; 210static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
208#endif 211#endif
209 212#endif
210#endif /* CONFIG_PM */ 213#endif /* CONFIG_PM */
211 214
212#if defined(BF548_FAMILY) 215#if defined(BF548_FAMILY)
@@ -667,7 +670,7 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
667 return 0; 670 return 0;
668} 671}
669 672
670u32 bfin_pm_setup(void) 673u32 bfin_pm_standby_setup(void)
671{ 674{
672 u16 bank, mask, i, gpio; 675 u16 bank, mask, i, gpio;
673 676
@@ -679,7 +682,7 @@ u32 bfin_pm_setup(void)
679 gpio_bankb[bank]->maskb = 0; 682 gpio_bankb[bank]->maskb = 0;
680 683
681 if (mask) { 684 if (mask) {
682#ifdef BF537_FAMILY 685#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
683 gpio_bank_saved[bank].fer = *port_fer[bank]; 686 gpio_bank_saved[bank].fer = *port_fer[bank];
684#endif 687#endif
685 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; 688 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
@@ -715,7 +718,7 @@ u32 bfin_pm_setup(void)
715 return 0; 718 return 0;
716} 719}
717 720
718void bfin_pm_restore(void) 721void bfin_pm_standby_restore(void)
719{ 722{
720 u16 bank, mask, i; 723 u16 bank, mask, i;
721 724
@@ -724,7 +727,7 @@ void bfin_pm_restore(void)
724 bank = gpio_bank(i); 727 bank = gpio_bank(i);
725 728
726 if (mask) { 729 if (mask) {
727#ifdef BF537_FAMILY 730#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
728 *port_fer[bank] = gpio_bank_saved[bank].fer; 731 *port_fer[bank] = gpio_bank_saved[bank].fer;
729#endif 732#endif
730 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; 733 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
@@ -743,8 +746,111 @@ void bfin_pm_restore(void)
743 AWA_DUMMY_READ(maskb); 746 AWA_DUMMY_READ(maskb);
744} 747}
745 748
749void bfin_gpio_pm_hibernate_suspend(void)
750{
751 int i, bank;
752
753 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
754 bank = gpio_bank(i);
755
756#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
757 gpio_bank_saved[bank].fer = *port_fer[bank];
758#ifdef BF527_FAMILY
759 gpio_bank_saved[bank].mux = *port_mux[bank];
760#else
761 if (bank == 0)
762 gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
763#endif
764#endif
765 gpio_bank_saved[bank].data = gpio_bankb[bank]->data;
766 gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
767 gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
768 gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
769 gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
770 gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
771 gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska;
772 }
773
774 AWA_DUMMY_READ(maska);
775}
776
777void bfin_gpio_pm_hibernate_restore(void)
778{
779 int i, bank;
780
781 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
782 bank = gpio_bank(i);
783
784#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
785#ifdef BF527_FAMILY
786 *port_mux[bank] = gpio_bank_saved[bank].mux;
787#else
788 if (bank == 0)
789 bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
790#endif
791 *port_fer[bank] = gpio_bank_saved[bank].fer;
792#endif
793 gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
794 gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
795 gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
796 gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
797 gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
798
799 gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
800 | gpio_bank_saved[bank].dir;
801
802 gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
803 }
804 AWA_DUMMY_READ(maska);
805}
806
807
746#endif 808#endif
747#else /* BF548_FAMILY */ 809#else /* BF548_FAMILY */
810#ifdef CONFIG_PM
811
812u32 bfin_pm_standby_setup(void)
813{
814 return 0;
815}
816
817void bfin_pm_standby_restore(void)
818{
819
820}
821
822void bfin_gpio_pm_hibernate_suspend(void)
823{
824 int i, bank;
825
826 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
827 bank = gpio_bank(i);
828
829 gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
830 gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
831 gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
832 gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
833 gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen;
834 gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set;
835 }
836}
837
838void bfin_gpio_pm_hibernate_restore(void)
839{
840 int i, bank;
841
842 for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
843 bank = gpio_bank(i);
844
845 gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
846 gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
847 gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen;
848 gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir;
849 gpio_array[bank]->port_set = gpio_bank_saved[bank].data
850 | gpio_bank_saved[bank].dir;
851 }
852}
853#endif
748 854
749unsigned short get_gpio_dir(unsigned gpio) 855unsigned short get_gpio_dir(unsigned gpio)
750{ 856{
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S b/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
index 2788532de72b..ecbabc0a1fed 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
+++ b/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
@@ -125,6 +125,6 @@ ENTRY(__cplb_hdr)
125 SP += -12; 125 SP += -12;
126 call _panic_cplb_error; 126 call _panic_cplb_error;
127 SP += 12; 127 SP += 12;
128 JUMP _handle_bad_cplb; 128 JUMP.L _handle_bad_cplb;
129 129
130ENDPROC(__cplb_hdr) 130ENDPROC(__cplb_hdr)
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 6be0c50122e8..224e7cc30bc5 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -26,11 +26,7 @@
26#include <asm/cplb.h> 26#include <asm/cplb.h>
27#include <asm/cplbinit.h> 27#include <asm/cplbinit.h>
28 28
29#ifdef CONFIG_MAX_MEM_SIZE 29#define CPLB_MEM CONFIG_MAX_MEM_SIZE
30# define CPLB_MEM CONFIG_MAX_MEM_SIZE
31#else
32# define CPLB_MEM CONFIG_MEM_SIZE
33#endif
34 30
35/* 31/*
36* Number of required data CPLB switchtable entries 32* Number of required data CPLB switchtable entries
diff --git a/arch/blackfin/kernel/dualcore_test.c b/arch/blackfin/kernel/dualcore_test.c
deleted file mode 100644
index 0fcba74840b7..000000000000
--- a/arch/blackfin/kernel/dualcore_test.c
+++ /dev/null
@@ -1,49 +0,0 @@
1/*
2 * File: arch/blackfin/kernel/dualcore_test.c
3 * Based on:
4 * Author:
5 *
6 * Created:
7 * Description: Small test code for CoreB on a BF561
8 *
9 * Modified:
10 * Copyright 2004-2006 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 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29
30#include <linux/init.h>
31#include <linux/module.h>
32
33static int *testarg = (int *)0xfeb00000;
34
35static int test_init(void)
36{
37 *testarg = 1;
38 printk(KERN_INFO "Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
39 *testarg, testarg);
40 return 0;
41}
42
43static void test_exit(void)
44{
45 printk(KERN_INFO "Dual core test module removed: testarg = [%d]\n", *testarg);
46}
47
48module_init(test_init);
49module_exit(test_exit);
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index 65f4e67a65c4..31bd9bf3efae 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -64,6 +64,11 @@ ENDPROC(_ret_from_fork)
64 64
65ENTRY(_sys_fork) 65ENTRY(_sys_fork)
66 r0 = -EINVAL; 66 r0 = -EINVAL;
67#if (ANOMALY_05000371)
68 nop;
69 nop;
70 nop;
71#endif
67 rts; 72 rts;
68ENDPROC(_sys_fork) 73ENDPROC(_sys_fork)
69 74
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index a9c15515bfd7..a1f9641a6425 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -203,6 +203,8 @@ struct hw_breakpoint {
203 203
204int kgdb_arch_init(void) 204int kgdb_arch_init(void)
205{ 205{
206 debugger_step = 0;
207
206 kgdb_remove_all_hw_break(); 208 kgdb_remove_all_hw_break();
207 return 0; 209 return 0;
208} 210}
@@ -368,6 +370,7 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
368 char *ptr; 370 char *ptr;
369 int newPC; 371 int newPC;
370 int wp_status; 372 int wp_status;
373 int i;
371 374
372 switch (remcom_in_buffer[0]) { 375 switch (remcom_in_buffer[0]) {
373 case 'c': 376 case 'c':
@@ -392,7 +395,18 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
392 /* set the trace bit if we're stepping */ 395 /* set the trace bit if we're stepping */
393 if (remcom_in_buffer[0] == 's') { 396 if (remcom_in_buffer[0] == 's') {
394 linux_regs->syscfg |= 0x1; 397 linux_regs->syscfg |= 0x1;
395 debugger_step = 1; 398 debugger_step = linux_regs->ipend;
399 debugger_step >>= 6;
400 for (i = 10; i > 0; i--, debugger_step >>= 1)
401 if (debugger_step & 1)
402 break;
403 /* i indicate event priority of current stopped instruction
404 * user space instruction is 0, IVG15 is 1, IVTMR is 10.
405 * debugger_step > 0 means in single step mode
406 */
407 debugger_step = i + 1;
408 } else {
409 debugger_step = 0;
396 } 410 }
397 411
398 wp_status = bfin_read_WPSTAT(); 412 wp_status = bfin_read_WPSTAT();
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 14a42848f37f..e1bebc80a5bf 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -173,7 +173,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
173 for (s = sechdrs; s < sechdrs_end; ++s) { 173 for (s = sechdrs; s < sechdrs_end; ++s) {
174 if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) || 174 if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
175 ((strcmp(".text", secstrings + s->sh_name) == 0) && 175 ((strcmp(".text", secstrings + s->sh_name) == 0) &&
176 (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) { 176 (hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) {
177 dest = l1_inst_sram_alloc(s->sh_size); 177 dest = l1_inst_sram_alloc(s->sh_size);
178 mod->arch.text_l1 = dest; 178 mod->arch.text_l1 = dest;
179 if (dest == NULL) { 179 if (dest == NULL) {
@@ -188,7 +188,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
188 } 188 }
189 if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) || 189 if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
190 ((strcmp(".data", secstrings + s->sh_name) == 0) && 190 ((strcmp(".data", secstrings + s->sh_name) == 0) &&
191 (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { 191 (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
192 dest = l1_data_sram_alloc(s->sh_size); 192 dest = l1_data_sram_alloc(s->sh_size);
193 mod->arch.data_a_l1 = dest; 193 mod->arch.data_a_l1 = dest;
194 if (dest == NULL) { 194 if (dest == NULL) {
@@ -203,7 +203,7 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
203 } 203 }
204 if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 || 204 if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
205 ((strcmp(".bss", secstrings + s->sh_name) == 0) && 205 ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
206 (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) { 206 (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) {
207 dest = l1_data_sram_alloc(s->sh_size); 207 dest = l1_data_sram_alloc(s->sh_size);
208 mod->arch.bss_a_l1 = dest; 208 mod->arch.bss_a_l1 = dest;
209 if (dest == NULL) { 209 if (dest == NULL) {
@@ -242,6 +242,51 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
242 s->sh_flags &= ~SHF_ALLOC; 242 s->sh_flags &= ~SHF_ALLOC;
243 s->sh_addr = (unsigned long)dest; 243 s->sh_addr = (unsigned long)dest;
244 } 244 }
245 if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) ||
246 ((strcmp(".text", secstrings + s->sh_name) == 0) &&
247 (hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) {
248 dest = l2_sram_alloc(s->sh_size);
249 mod->arch.text_l2 = dest;
250 if (dest == NULL) {
251 printk(KERN_ERR
252 "module %s: L2 SRAM allocation failed\n",
253 mod->name);
254 return -1;
255 }
256 memcpy(dest, (void *)s->sh_addr, s->sh_size);
257 s->sh_flags &= ~SHF_ALLOC;
258 s->sh_addr = (unsigned long)dest;
259 }
260 if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) ||
261 ((strcmp(".data", secstrings + s->sh_name) == 0) &&
262 (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
263 dest = l2_sram_alloc(s->sh_size);
264 mod->arch.data_l2 = dest;
265 if (dest == NULL) {
266 printk(KERN_ERR
267 "module %s: L2 SRAM allocation failed\n",
268 mod->name);
269 return -1;
270 }
271 memcpy(dest, (void *)s->sh_addr, s->sh_size);
272 s->sh_flags &= ~SHF_ALLOC;
273 s->sh_addr = (unsigned long)dest;
274 }
275 if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 ||
276 ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
277 (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) {
278 dest = l2_sram_alloc(s->sh_size);
279 mod->arch.bss_l2 = dest;
280 if (dest == NULL) {
281 printk(KERN_ERR
282 "module %s: L2 SRAM allocation failed\n",
283 mod->name);
284 return -1;
285 }
286 memset(dest, 0, s->sh_size);
287 s->sh_flags &= ~SHF_ALLOC;
288 s->sh_addr = (unsigned long)dest;
289 }
245 } 290 }
246 return 0; 291 return 0;
247} 292}
@@ -411,9 +456,10 @@ module_finalize(const Elf_Ehdr * hdr,
411 continue; 456 continue;
412 457
413 if ((sechdrs[i].sh_type == SHT_RELA) && 458 if ((sechdrs[i].sh_type == SHT_RELA) &&
414 ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || 459 ((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) ||
460 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
415 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && 461 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
416 (hdr->e_flags & FLG_CODE_IN_L1)))) { 462 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
417 apply_relocate_add((Elf_Shdr *) sechdrs, strtab, 463 apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
418 symindex, i, mod); 464 symindex, i, mod);
419 } 465 }
@@ -423,14 +469,12 @@ module_finalize(const Elf_Ehdr * hdr,
423 469
424void module_arch_cleanup(struct module *mod) 470void module_arch_cleanup(struct module *mod)
425{ 471{
426 if (mod->arch.text_l1) 472 l1_inst_sram_free(mod->arch.text_l1);
427 l1_inst_sram_free((void *)mod->arch.text_l1); 473 l1_data_A_sram_free(mod->arch.data_a_l1);
428 if (mod->arch.data_a_l1) 474 l1_data_A_sram_free(mod->arch.bss_a_l1);
429 l1_data_sram_free((void *)mod->arch.data_a_l1); 475 l1_data_B_sram_free(mod->arch.data_b_l1);
430 if (mod->arch.bss_a_l1) 476 l1_data_B_sram_free(mod->arch.bss_b_l1);
431 l1_data_sram_free((void *)mod->arch.bss_a_l1); 477 l2_sram_free(mod->arch.text_l2);
432 if (mod->arch.data_b_l1) 478 l2_sram_free(mod->arch.data_l2);
433 l1_data_B_sram_free((void *)mod->arch.data_b_l1); 479 l2_sram_free(mod->arch.bss_l2);
434 if (mod->arch.bss_b_l1)
435 l1_data_B_sram_free((void *)mod->arch.bss_b_l1);
436} 480}
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index f51ab088098e..bf1a51d8e608 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -220,6 +220,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
220 copied = sizeof(tmp); 220 copied = sizeof(tmp);
221 } else 221 } else
222#endif 222#endif
223#if L1_DATA_A_LENGTH != 0
224 if (addr + add >= L1_DATA_A_START
225 && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
226 memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
227 copied = sizeof(tmp);
228 } else
229#endif
230#if L1_DATA_B_LENGTH != 0
231 if (addr + add >= L1_DATA_B_START
232 && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
233 memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
234 copied = sizeof(tmp);
235 } else
236#endif
223 if (addr + add >= FIXED_CODE_START 237 if (addr + add >= FIXED_CODE_START
224 && addr + add + sizeof(tmp) <= FIXED_CODE_END) { 238 && addr + add + sizeof(tmp) <= FIXED_CODE_END) {
225 memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); 239 memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
@@ -290,6 +304,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
290 copied = sizeof(data); 304 copied = sizeof(data);
291 } else 305 } else
292#endif 306#endif
307#if L1_DATA_A_LENGTH != 0
308 if (addr + add >= L1_DATA_A_START
309 && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
310 memcpy((void *)(addr + add), &data, sizeof(data));
311 copied = sizeof(data);
312 } else
313#endif
314#if L1_DATA_B_LENGTH != 0
315 if (addr + add >= L1_DATA_B_START
316 && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
317 memcpy((void *)(addr + add), &data, sizeof(data));
318 copied = sizeof(data);
319 } else
320#endif
293 if (addr + add >= FIXED_CODE_START 321 if (addr + add >= FIXED_CODE_START
294 && addr + add + sizeof(data) <= FIXED_CODE_END) { 322 && addr + add + sizeof(data) <= FIXED_CODE_END) {
295 memcpy((void *)(addr + add), &data, sizeof(data)); 323 memcpy((void *)(addr + add), &data, sizeof(data));
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 8efea004aecb..23e637eb78da 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -104,6 +104,7 @@ void __init bf53x_relocate_l1_mem(void)
104 unsigned long l1_code_length; 104 unsigned long l1_code_length;
105 unsigned long l1_data_a_length; 105 unsigned long l1_data_a_length;
106 unsigned long l1_data_b_length; 106 unsigned long l1_data_b_length;
107 unsigned long l2_length;
107 108
108 l1_code_length = _etext_l1 - _stext_l1; 109 l1_code_length = _etext_l1 - _stext_l1;
109 if (l1_code_length > L1_CODE_LENGTH) 110 if (l1_code_length > L1_CODE_LENGTH)
@@ -129,6 +130,15 @@ void __init bf53x_relocate_l1_mem(void)
129 /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */ 130 /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
130 dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length + 131 dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
131 l1_data_a_length, l1_data_b_length); 132 l1_data_a_length, l1_data_b_length);
133
134#ifdef L2_LENGTH
135 l2_length = _ebss_l2 - _stext_l2;
136 if (l2_length > L2_LENGTH)
137 panic("L2 SRAM Overflow\n");
138
139 /* Copy _stext_l2 to _edata_l2 to L2 SRAM */
140 dma_memcpy(_stext_l2, _l2_lma_start, l2_length);
141#endif
132} 142}
133 143
134/* add_memory_region to memmap */ 144/* add_memory_region to memmap */
@@ -664,11 +674,8 @@ static __init void setup_bootmem_allocator(void)
664}) 674})
665static inline int __init get_mem_size(void) 675static inline int __init get_mem_size(void)
666{ 676{
667#ifdef CONFIG_MEM_SIZE 677#if defined(EBIU_SDBCTL)
668 return CONFIG_MEM_SIZE; 678# if defined(BF561_FAMILY)
669#else
670# if defined(EBIU_SDBCTL)
671# if defined(BF561_FAMILY)
672 int ret = 0; 679 int ret = 0;
673 u32 sdbctl = bfin_read_EBIU_SDBCTL(); 680 u32 sdbctl = bfin_read_EBIU_SDBCTL();
674 ret += EBSZ_TO_MEG(sdbctl >> 0); 681 ret += EBSZ_TO_MEG(sdbctl >> 0);
@@ -676,10 +683,10 @@ static inline int __init get_mem_size(void)
676 ret += EBSZ_TO_MEG(sdbctl >> 16); 683 ret += EBSZ_TO_MEG(sdbctl >> 16);
677 ret += EBSZ_TO_MEG(sdbctl >> 24); 684 ret += EBSZ_TO_MEG(sdbctl >> 24);
678 return ret; 685 return ret;
679# else 686# else
680 return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL()); 687 return EBSZ_TO_MEG(bfin_read_EBIU_SDBCTL());
681# endif 688# endif
682# elif defined(EBIU_DDRCTL1) 689#elif defined(EBIU_DDRCTL1)
683 u32 ddrctl = bfin_read_EBIU_DDRCTL1(); 690 u32 ddrctl = bfin_read_EBIU_DDRCTL1();
684 int ret = 0; 691 int ret = 0;
685 switch (ddrctl & 0xc0000) { 692 switch (ddrctl & 0xc0000) {
@@ -693,8 +700,9 @@ static inline int __init get_mem_size(void)
693 case DEVWD_8: ret *= 2; 700 case DEVWD_8: ret *= 2;
694 case DEVWD_16: break; 701 case DEVWD_16: break;
695 } 702 }
703 if ((ddrctl & 0xc000) == 0x4000)
704 ret *= 2;
696 return ret; 705 return ret;
697# endif
698#endif 706#endif
699 BUG(); 707 BUG();
700} 708}
@@ -763,6 +771,9 @@ void __init setup_arch(char **cmdline_p)
763 771
764 _bfin_swrst = bfin_read_SWRST(); 772 _bfin_swrst = bfin_read_SWRST();
765 773
774 /* If we double fault, reset the system - otherwise we hang forever */
775 bfin_write_SWRST(DOUBLE_FAULT);
776
766 if (_bfin_swrst & RESET_DOUBLE) 777 if (_bfin_swrst & RESET_DOUBLE)
767 printk(KERN_INFO "Recovering from Double Fault event\n"); 778 printk(KERN_INFO "Recovering from Double Fault event\n");
768 else if (_bfin_swrst & RESET_WDOG) 779 else if (_bfin_swrst & RESET_WDOG)
@@ -842,38 +853,55 @@ static int __init topology_init(void)
842 853
843subsys_initcall(topology_init); 854subsys_initcall(topology_init);
844 855
856/* Get the voltage input multiplier */
857static u_long cached_vco_pll_ctl, cached_vco;
845static u_long get_vco(void) 858static u_long get_vco(void)
846{ 859{
847 u_long msel; 860 u_long msel;
848 u_long vco;
849 861
850 msel = (bfin_read_PLL_CTL() >> 9) & 0x3F; 862 u_long pll_ctl = bfin_read_PLL_CTL();
863 if (pll_ctl == cached_vco_pll_ctl)
864 return cached_vco;
865 else
866 cached_vco_pll_ctl = pll_ctl;
867
868 msel = (pll_ctl >> 9) & 0x3F;
851 if (0 == msel) 869 if (0 == msel)
852 msel = 64; 870 msel = 64;
853 871
854 vco = CONFIG_CLKIN_HZ; 872 cached_vco = CONFIG_CLKIN_HZ;
855 vco >>= (1 & bfin_read_PLL_CTL()); /* DF bit */ 873 cached_vco >>= (1 & pll_ctl); /* DF bit */
856 vco = msel * vco; 874 cached_vco *= msel;
857 return vco; 875 return cached_vco;
858} 876}
859 877
860/* Get the Core clock */ 878/* Get the Core clock */
879static u_long cached_cclk_pll_div, cached_cclk;
861u_long get_cclk(void) 880u_long get_cclk(void)
862{ 881{
863 u_long csel, ssel; 882 u_long csel, ssel;
883
864 if (bfin_read_PLL_STAT() & 0x1) 884 if (bfin_read_PLL_STAT() & 0x1)
865 return CONFIG_CLKIN_HZ; 885 return CONFIG_CLKIN_HZ;
866 886
867 ssel = bfin_read_PLL_DIV(); 887 ssel = bfin_read_PLL_DIV();
888 if (ssel == cached_cclk_pll_div)
889 return cached_cclk;
890 else
891 cached_cclk_pll_div = ssel;
892
868 csel = ((ssel >> 4) & 0x03); 893 csel = ((ssel >> 4) & 0x03);
869 ssel &= 0xf; 894 ssel &= 0xf;
870 if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ 895 if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
871 return get_vco() / ssel; 896 cached_cclk = get_vco() / ssel;
872 return get_vco() >> csel; 897 else
898 cached_cclk = get_vco() >> csel;
899 return cached_cclk;
873} 900}
874EXPORT_SYMBOL(get_cclk); 901EXPORT_SYMBOL(get_cclk);
875 902
876/* Get the System clock */ 903/* Get the System clock */
904static u_long cached_sclk_pll_div, cached_sclk;
877u_long get_sclk(void) 905u_long get_sclk(void)
878{ 906{
879 u_long ssel; 907 u_long ssel;
@@ -881,13 +909,20 @@ u_long get_sclk(void)
881 if (bfin_read_PLL_STAT() & 0x1) 909 if (bfin_read_PLL_STAT() & 0x1)
882 return CONFIG_CLKIN_HZ; 910 return CONFIG_CLKIN_HZ;
883 911
884 ssel = (bfin_read_PLL_DIV() & 0xf); 912 ssel = bfin_read_PLL_DIV();
913 if (ssel == cached_sclk_pll_div)
914 return cached_sclk;
915 else
916 cached_sclk_pll_div = ssel;
917
918 ssel &= 0xf;
885 if (0 == ssel) { 919 if (0 == ssel) {
886 printk(KERN_WARNING "Invalid System Clock\n"); 920 printk(KERN_WARNING "Invalid System Clock\n");
887 ssel = 1; 921 ssel = 1;
888 } 922 }
889 923
890 return get_vco() / ssel; 924 cached_sclk = get_vco() / ssel;
925 return cached_sclk;
891} 926}
892EXPORT_SYMBOL(get_sclk); 927EXPORT_SYMBOL(get_sclk);
893 928
@@ -916,7 +951,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
916 uint32_t revid; 951 uint32_t revid;
917 952
918 u_long cclk = 0, sclk = 0; 953 u_long cclk = 0, sclk = 0;
919 u_int dcache_size = 0, dsup_banks = 0; 954 u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0;
920 955
921 cpu = CPU; 956 cpu = CPU;
922 mmu = "none"; 957 mmu = "none";
@@ -985,12 +1020,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
985 } 1020 }
986 1021
987 /* Is it turned on? */ 1022 /* Is it turned on? */
988 if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))) 1023 if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
989 dcache_size = 0; 1024 dcache_size = 0;
990 1025
1026 if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB))
1027 icache_size = 0;
1028
991 seq_printf(m, "cache size\t: %d KB(L1 icache) " 1029 seq_printf(m, "cache size\t: %d KB(L1 icache) "
992 "%d KB(L1 dcache-%s) %d KB(L2 cache)\n", 1030 "%d KB(L1 dcache-%s) %d KB(L2 cache)\n",
993 BFIN_ICACHESIZE / 1024, dcache_size, 1031 icache_size, dcache_size,
994#if defined CONFIG_BFIN_WB 1032#if defined CONFIG_BFIN_WB
995 "wb" 1033 "wb"
996#elif defined CONFIG_BFIN_WT 1034#elif defined CONFIG_BFIN_WT
@@ -1000,8 +1038,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
1000 1038
1001 seq_printf(m, "%s\n", cache); 1039 seq_printf(m, "%s\n", cache);
1002 1040
1003 seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n", 1041 if (icache_size)
1004 BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES); 1042 seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n",
1043 BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES);
1044 else
1045 seq_printf(m, "icache setup\t: off\n");
1046
1005 seq_printf(m, 1047 seq_printf(m,
1006 "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", 1048 "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
1007 dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, 1049 dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index f061f5181623..ad922ab91543 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -69,8 +69,6 @@ void __init trap_init(void)
69 69
70unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr; 70unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr;
71 71
72int kstack_depth_to_print = 48;
73
74static void decode_address(char *buf, unsigned long address) 72static void decode_address(char *buf, unsigned long address)
75{ 73{
76 struct vm_list_struct *vml; 74 struct vm_list_struct *vml;
@@ -163,6 +161,9 @@ static void decode_address(char *buf, unsigned long address)
163 if (!in_atomic) 161 if (!in_atomic)
164 mmput(mm); 162 mmput(mm);
165 163
164 if (!strlen(buf))
165 sprintf(buf, "<0x%p> [ %s ] dynamic memory", (void *)address, name);
166
166 goto done; 167 goto done;
167 } 168 }
168 169
@@ -173,7 +174,7 @@ static void decode_address(char *buf, unsigned long address)
173 } 174 }
174 175
175 /* we were unable to find this address anywhere */ 176 /* we were unable to find this address anywhere */
176 sprintf(buf, "<0x%p> /* unknown address */", (void *)address); 177 sprintf(buf, "<0x%p> /* kernel dynamic memory */", (void *)address);
177 178
178done: 179done:
179 write_unlock_irqrestore(&tasklist_lock, flags); 180 write_unlock_irqrestore(&tasklist_lock, flags);
@@ -494,7 +495,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
494 BUG_ON(sig == 0); 495 BUG_ON(sig == 0);
495 496
496 if (sig != SIGTRAP) { 497 if (sig != SIGTRAP) {
497 unsigned long stack; 498 unsigned long *stack;
498 dump_bfin_process(fp); 499 dump_bfin_process(fp);
499 dump_bfin_mem(fp); 500 dump_bfin_mem(fp);
500 show_regs(fp); 501 show_regs(fp);
@@ -508,14 +509,23 @@ asmlinkage void trap_c(struct pt_regs *fp)
508 else 509 else
509#endif 510#endif
510 dump_bfin_trace_buffer(); 511 dump_bfin_trace_buffer();
511 show_stack(current, &stack); 512
512 if (oops_in_progress) { 513 if (oops_in_progress) {
514 /* Dump the current kernel stack */
515 printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
516 show_stack(current, NULL);
517
513 print_modules(); 518 print_modules();
514#ifndef CONFIG_ACCESS_CHECK 519#ifndef CONFIG_ACCESS_CHECK
515 printk(KERN_EMERG "Please turn on " 520 printk(KERN_EMERG "Please turn on "
516 "CONFIG_ACCESS_CHECK\n"); 521 "CONFIG_ACCESS_CHECK\n");
517#endif 522#endif
518 panic("Kernel exception"); 523 panic("Kernel exception");
524 } else {
525 /* Dump the user space stack */
526 stack = (unsigned long *)rdusp();
527 printk(KERN_NOTICE "Userspace Stack\n");
528 show_stack(NULL, stack);
519 } 529 }
520 } 530 }
521 531
@@ -532,11 +542,71 @@ asmlinkage void trap_c(struct pt_regs *fp)
532 542
533#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1) 543#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)
534 544
545/*
546 * Similar to get_user, do some address checking, then dereference
547 * Return true on sucess, false on bad address
548 */
549bool get_instruction(unsigned short *val, unsigned short *address)
550{
551
552 unsigned long addr;
553
554 addr = (unsigned long)address;
555
556 /* Check for odd addresses */
557 if (addr & 0x1)
558 return false;
559
560 /* Check that things do not wrap around */
561 if (addr > (addr + 2))
562 return false;
563
564 /*
565 * Since we are in exception context, we need to do a little address checking
566 * We need to make sure we are only accessing valid memory, and
567 * we don't read something in the async space that can hang forever
568 */
569 if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) ||
570#ifdef L2_START
571 (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) ||
572#endif
573 (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) ||
574#if L1_DATA_A_LENGTH != 0
575 (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) ||
576#endif
577#if L1_DATA_B_LENGTH != 0
578 (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
579#endif
580 (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
581 (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
582 addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
583 (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
584 addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
585 (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
586 addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
587 (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
588 addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
589 *val = *address;
590 return true;
591 }
592
593#if L1_CODE_LENGTH != 0
594 if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
595 dma_memcpy(val, address, 2);
596 return true;
597 }
598#endif
599
600
601 return false;
602}
603
535void dump_bfin_trace_buffer(void) 604void dump_bfin_trace_buffer(void)
536{ 605{
537#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 606#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
538 int tflags, i = 0; 607 int tflags, i = 0;
539 char buf[150]; 608 char buf[150];
609 unsigned short val = 0, *addr;
540#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND 610#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
541 int j, index; 611 int j, index;
542#endif 612#endif
@@ -549,8 +619,42 @@ void dump_bfin_trace_buffer(void)
549 for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { 619 for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
550 decode_address(buf, (unsigned long)bfin_read_TBUF()); 620 decode_address(buf, (unsigned long)bfin_read_TBUF());
551 printk(KERN_NOTICE "%4i Target : %s\n", i, buf); 621 printk(KERN_NOTICE "%4i Target : %s\n", i, buf);
552 decode_address(buf, (unsigned long)bfin_read_TBUF()); 622 addr = (unsigned short *)bfin_read_TBUF();
553 printk(KERN_NOTICE " Source : %s\n", buf); 623 decode_address(buf, (unsigned long)addr);
624 printk(KERN_NOTICE " Source : %s ", buf);
625 if (get_instruction(&val, addr)) {
626 if (val == 0x0010)
627 printk("RTS");
628 else if (val == 0x0011)
629 printk("RTI");
630 else if (val == 0x0012)
631 printk("RTX");
632 else if (val >= 0x0050 && val <= 0x0057)
633 printk("JUMP (P%i)", val & 7);
634 else if (val >= 0x0060 && val <= 0x0067)
635 printk("CALL (P%i)", val & 7);
636 else if (val >= 0x0070 && val <= 0x0077)
637 printk("CALL (PC+P%i)", val & 7);
638 else if (val >= 0x0080 && val <= 0x0087)
639 printk("JUMP (PC+P%i)", val & 7);
640 else if ((val >= 0x1000 && val <= 0x13FF) ||
641 (val >= 0x1800 && val <= 0x1BFF))
642 printk("IF !CC JUMP");
643 else if ((val >= 0x1400 && val <= 0x17ff) ||
644 (val >= 0x1c00 && val <= 0x1fff))
645 printk("IF CC JUMP");
646 else if (val >= 0x2000 && val <= 0x2fff)
647 printk("JUMP.S");
648 else if (val >= 0xe080 && val <= 0xe0ff)
649 printk("LSETUP");
650 else if (val >= 0xe200 && val <= 0xe2ff)
651 printk("JUMP.L");
652 else if (val >= 0xe300 && val <= 0xe3ff)
653 printk("CALL pcrel");
654 else
655 printk("0x%04x", val);
656 }
657 printk("\n");
554 } 658 }
555 } 659 }
556 660
@@ -582,59 +686,151 @@ void dump_bfin_trace_buffer(void)
582} 686}
583EXPORT_SYMBOL(dump_bfin_trace_buffer); 687EXPORT_SYMBOL(dump_bfin_trace_buffer);
584 688
585static void show_trace(struct task_struct *tsk, unsigned long *sp) 689/*
690 * Checks to see if the address pointed to is either a
691 * 16-bit CALL instruction, or a 32-bit CALL instruction
692 */
693bool is_bfin_call(unsigned short *addr)
586{ 694{
587 unsigned long addr; 695 unsigned short opcode = 0, *ins_addr;
696 ins_addr = (unsigned short *)addr;
588 697
589 printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n"); 698 if (!get_instruction(&opcode, ins_addr))
590 699 return false;
591 while (!kstack_end(sp)) {
592 addr = *sp++;
593 /*
594 * If the address is either in the text segment of the
595 * kernel, or in the region which contains vmalloc'ed
596 * memory, it *may* be the address of a calling
597 * routine; if so, print it so that someone tracing
598 * down the cause of the crash will be able to figure
599 * out the call path that was taken.
600 */
601 if (kernel_text_address(addr))
602 print_ip_sym(addr);
603 }
604 700
605 printk(KERN_NOTICE "\n"); 701 if ((opcode >= 0x0060 && opcode <= 0x0067) ||
606} 702 (opcode >= 0x0070 && opcode <= 0x0077))
703 return true;
704
705 ins_addr--;
706 if (!get_instruction(&opcode, ins_addr))
707 return false;
607 708
709 if (opcode >= 0xE300 && opcode <= 0xE3FF)
710 return true;
711
712 return false;
713
714}
608void show_stack(struct task_struct *task, unsigned long *stack) 715void show_stack(struct task_struct *task, unsigned long *stack)
609{ 716{
610 unsigned long *endstack, addr; 717 unsigned int *addr, *endstack, *fp = 0, *frame;
611 int i; 718 unsigned short *ins_addr;
719 char buf[150];
720 unsigned int i, j, ret_addr, frame_no = 0;
612 721
613 /* Cannot call dump_bfin_trace_buffer() here as show_stack() is 722 /*
614 * called externally in some places in the kernel. 723 * If we have been passed a specific stack, use that one otherwise
724 * if we have been passed a task structure, use that, otherwise
725 * use the stack of where the variable "stack" exists
615 */ 726 */
616 727
617 if (!stack) { 728 if (stack == NULL) {
618 if (task) 729 if (task) {
730 /* We know this is a kernel stack, so this is the start/end */
619 stack = (unsigned long *)task->thread.ksp; 731 stack = (unsigned long *)task->thread.ksp;
620 else 732 endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
733 } else {
734 /* print out the existing stack info */
621 stack = (unsigned long *)&stack; 735 stack = (unsigned long *)&stack;
736 endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
737 }
738 } else
739 endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
740
741 decode_address(buf, (unsigned int)stack);
742 printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
743 addr = (unsigned int *)((unsigned int)stack & ~0x3F);
744
745 /* First thing is to look for a frame pointer */
746 for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
747 addr < endstack; addr++, i++) {
748 if (*addr & 0x1)
749 continue;
750 ins_addr = (unsigned short *)*addr;
751 ins_addr--;
752 if (is_bfin_call(ins_addr))
753 fp = addr - 1;
754
755 if (fp) {
756 /* Let's check to see if it is a frame pointer */
757 while (fp >= (addr - 1) && fp < endstack && fp)
758 fp = (unsigned int *)*fp;
759 if (fp == 0 || fp == endstack) {
760 fp = addr - 1;
761 break;
762 }
763 fp = 0;
764 }
622 } 765 }
766 if (fp) {
767 frame = fp;
768 printk(" FP: (0x%p)\n", fp);
769 } else
770 frame = 0;
623 771
624 addr = (unsigned long)stack; 772 /*
625 endstack = (unsigned long *)PAGE_ALIGN(addr); 773 * Now that we think we know where things are, we
774 * walk the stack again, this time printing things out
775 * incase there is no frame pointer, we still look for
776 * valid return addresses
777 */
626 778
627 printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack); 779 /* First time print out data, next time, print out symbols */
628 for (i = 0; i < kstack_depth_to_print; i++) { 780 for (j = 0; j <= 1; j++) {
629 if (stack + 1 > endstack) 781 if (j)
630 break; 782 printk(KERN_NOTICE "Return addresses in stack:\n");
631 if (i % 8 == 0) 783 else
632 printk("\n" KERN_NOTICE " "); 784 printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
633 printk(" %08lx", *stack++); 785
786 fp = frame;
787 frame_no = 0;
788
789 for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
790 addr <= endstack; addr++, i++) {
791
792 ret_addr = 0;
793 if (!j && i % 8 == 0)
794 printk("\n" KERN_NOTICE "%p:",addr);
795
796 /* if it is an odd address, or zero, just skip it */
797 if (*addr & 0x1 || !*addr)
798 goto print;
799
800 ins_addr = (unsigned short *)*addr;
801
802 /* Go back one instruction, and see if it is a CALL */
803 ins_addr--;
804 ret_addr = is_bfin_call(ins_addr);
805 print:
806 if (!j && stack == (unsigned long *)addr)
807 printk("[%08x]", *addr);
808 else if (ret_addr)
809 if (j) {
810 decode_address(buf, (unsigned int)*addr);
811 if (frame == addr) {
812 printk(KERN_NOTICE " frame %2i : %s\n", frame_no, buf);
813 continue;
814 }
815 printk(KERN_NOTICE " address : %s\n", buf);
816 } else
817 printk("<%08x>", *addr);
818 else if (fp == addr) {
819 if (j)
820 frame = addr+1;
821 else
822 printk("(%08x)", *addr);
823
824 fp = (unsigned int *)*addr;
825 frame_no++;
826
827 } else if (!j)
828 printk(" %08x ", *addr);
829 }
830 if (!j)
831 printk("\n");
634 } 832 }
635 printk("\n");
636 833
637 show_trace(task, stack);
638} 834}
639 835
640void dump_stack(void) 836void dump_stack(void)
@@ -715,19 +911,9 @@ void dump_bfin_mem(struct pt_regs *fp)
715 if (!((unsigned long)addr & 0xF)) 911 if (!((unsigned long)addr & 0xF))
716 printk("\n" KERN_NOTICE "0x%p: ", addr); 912 printk("\n" KERN_NOTICE "0x%p: ", addr);
717 913
718 if (get_user(val, addr)) { 914 if (get_instruction(&val, addr)) {
719 if (addr >= (unsigned short *)L1_CODE_START &&
720 addr < (unsigned short *)(L1_CODE_START + L1_CODE_LENGTH)) {
721 dma_memcpy(&val, addr, sizeof(val));
722 sprintf(buf, "%04x", val);
723 } else if (addr >= (unsigned short *)FIXED_CODE_START &&
724 addr <= (unsigned short *)memory_start) {
725 val = bfin_read16(addr);
726 sprintf(buf, "%04x", val);
727 } else {
728 val = 0; 915 val = 0;
729 sprintf(buf, "????"); 916 sprintf(buf, "????");
730 }
731 } else 917 } else
732 sprintf(buf, "%04x", val); 918 sprintf(buf, "%04x", val);
733 919
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 3ecc64cab3be..0896e38d6108 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -101,6 +101,11 @@ SECTIONS
101#if !L1_DATA_B_LENGTH 101#if !L1_DATA_B_LENGTH
102 *(.l1.data.B) 102 *(.l1.data.B)
103#endif 103#endif
104#ifndef L2_LENGTH
105 . = ALIGN(32);
106 *(.data_l2.cacheline_aligned)
107 *(.l2.data)
108#endif
104 109
105 DATA_DATA 110 DATA_DATA
106 *(.data.*) 111 *(.data.*)
@@ -182,14 +187,13 @@ SECTIONS
182 *(.l1.data) 187 *(.l1.data)
183 __edata_l1 = .; 188 __edata_l1 = .;
184 189
185 . = ALIGN(4);
186 __sbss_l1 = .;
187 *(.l1.bss)
188
189 . = ALIGN(32); 190 . = ALIGN(32);
190 *(.data_l1.cacheline_aligned) 191 *(.data_l1.cacheline_aligned)
191 192
192 . = ALIGN(4); 193 . = ALIGN(4);
194 __sbss_l1 = .;
195 *(.l1.bss)
196 . = ALIGN(4);
193 __ebss_l1 = .; 197 __ebss_l1 = .;
194 } 198 }
195 199
@@ -203,11 +207,37 @@ SECTIONS
203 . = ALIGN(4); 207 . = ALIGN(4);
204 __sbss_b_l1 = .; 208 __sbss_b_l1 = .;
205 *(.l1.bss.B) 209 *(.l1.bss.B)
206
207 . = ALIGN(4); 210 . = ALIGN(4);
208 __ebss_b_l1 = .; 211 __ebss_b_l1 = .;
209 } 212 }
210 213
214#ifdef L2_LENGTH
215 __l2_lma_start = .;
216
217 .text_data_l2 L2_START : AT(LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1))
218 {
219 . = ALIGN(4);
220 __stext_l2 = .;
221 *(.l1.text)
222 . = ALIGN(4);
223 __etext_l2 = .;
224
225 . = ALIGN(4);
226 __sdata_l2 = .;
227 *(.l1.data)
228 __edata_l2 = .;
229
230 . = ALIGN(32);
231 *(.data_l2.cacheline_aligned)
232
233 . = ALIGN(4);
234 __sbss_l2 = .;
235 *(.l1.bss)
236 . = ALIGN(4);
237 __ebss_l2 = .;
238 }
239#endif
240
211 /* Force trailing alignment of our init section so that when we 241 /* Force trailing alignment of our init section so that when we
212 * free our init memory, we don't leave behind a partial page. 242 * free our init memory, we don't leave behind a partial page.
213 */ 243 */