aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r--arch/blackfin/mach-common/Makefile3
-rw-r--r--arch/blackfin/mach-common/cplbhdlr.S130
-rw-r--r--arch/blackfin/mach-common/cplbinfo.c208
-rw-r--r--arch/blackfin/mach-common/cplbmgr.S619
-rw-r--r--arch/blackfin/mach-common/dpmc.S74
-rw-r--r--arch/blackfin/mach-common/entry.S26
-rw-r--r--arch/blackfin/mach-common/interrupt.S48
-rw-r--r--arch/blackfin/mach-common/ints-priority-dc.c10
-rw-r--r--arch/blackfin/mach-common/ints-priority-sc.c84
-rw-r--r--arch/blackfin/mach-common/irqpanic.c50
-rw-r--r--arch/blackfin/mach-common/pm.c16
11 files changed, 189 insertions, 1079 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index 4d7733dfd5de..8636d4284bdb 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -3,10 +3,9 @@
3# 3#
4 4
5obj-y := \ 5obj-y := \
6 cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \ 6 cache.o cacheinit.o entry.o \
7 interrupt.o lock.o irqpanic.o arch_checks.o 7 interrupt.o lock.o irqpanic.o arch_checks.o
8 8
9obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
10obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o 9obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o
11obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o 10obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o
12obj-$(CONFIG_PM) += pm.o dpmc.o 11obj-$(CONFIG_PM) += pm.o dpmc.o
diff --git a/arch/blackfin/mach-common/cplbhdlr.S b/arch/blackfin/mach-common/cplbhdlr.S
deleted file mode 100644
index 2788532de72b..000000000000
--- a/arch/blackfin/mach-common/cplbhdlr.S
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 * File: arch/blackfin/mach-common/cplbhdlr.S
3 * Based on:
4 * Author: LG Soft India
5 *
6 * Created: ?
7 * Description: CPLB exception handler
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/linkage.h>
31#include <asm/cplb.h>
32#include <asm/entry.h>
33
34#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
35.section .l1.text
36#else
37.text
38#endif
39
40.type _cplb_mgr, STT_FUNC;
41.type _panic_cplb_error, STT_FUNC;
42
43.align 2
44
45ENTRY(__cplb_hdr)
46 R2 = SEQSTAT;
47
48 /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */
49 R2 <<= 26;
50 R2 >>= 26;
51
52 R1 = 0x23; /* Data access CPLB protection violation */
53 CC = R2 == R1;
54 IF !CC JUMP .Lnot_data_write;
55 R0 = 2; /* is a write to data space*/
56 JUMP .Lis_icplb_miss;
57
58.Lnot_data_write:
59 R1 = 0x2C; /* CPLB miss on an instruction fetch */
60 CC = R2 == R1;
61 R0 = 0; /* is_data_miss == False*/
62 IF CC JUMP .Lis_icplb_miss;
63
64 R1 = 0x26;
65 CC = R2 == R1;
66 IF !CC JUMP .Lunknown;
67
68 R0 = 1; /* is_data_miss == True*/
69
70.Lis_icplb_miss:
71
72#if defined(CONFIG_BFIN_ICACHE) || defined(CONFIG_BFIN_DCACHE)
73# if defined(CONFIG_BFIN_ICACHE) && !defined(CONFIG_BFIN_DCACHE)
74 R1 = CPLB_ENABLE_ICACHE;
75# endif
76# if !defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
77 R1 = CPLB_ENABLE_DCACHE;
78# endif
79# if defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
80 R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE;
81# endif
82#else
83 R1 = 0;
84#endif
85
86 [--SP] = RETS;
87 CALL _cplb_mgr;
88 RETS = [SP++];
89 CC = R0 == 0;
90 IF !CC JUMP .Lnot_replaced;
91 RTS;
92
93/*
94 * Diagnostic exception handlers
95 */
96.Lunknown:
97 R0 = CPLB_UNKNOWN_ERR;
98 JUMP .Lcplb_error;
99
100.Lnot_replaced:
101 CC = R0 == CPLB_NO_UNLOCKED;
102 IF !CC JUMP .Lnext_check;
103 R0 = CPLB_NO_UNLOCKED;
104 JUMP .Lcplb_error;
105
106.Lnext_check:
107 CC = R0 == CPLB_NO_ADDR_MATCH;
108 IF !CC JUMP .Lnext_check2;
109 R0 = CPLB_NO_ADDR_MATCH;
110 JUMP .Lcplb_error;
111
112.Lnext_check2:
113 CC = R0 == CPLB_PROT_VIOL;
114 IF !CC JUMP .Lstrange_return_from_cplb_mgr;
115 R0 = CPLB_PROT_VIOL;
116 JUMP .Lcplb_error;
117
118.Lstrange_return_from_cplb_mgr:
119 IDLE;
120 CSYNC;
121 JUMP .Lstrange_return_from_cplb_mgr;
122
123.Lcplb_error:
124 R1 = sp;
125 SP += -12;
126 call _panic_cplb_error;
127 SP += 12;
128 JUMP _handle_bad_cplb;
129
130ENDPROC(__cplb_hdr)
diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c
deleted file mode 100644
index a4f0b428a34d..000000000000
--- a/arch/blackfin/mach-common/cplbinfo.c
+++ /dev/null
@@ -1,208 +0,0 @@
1/*
2 * File: arch/blackfin/mach-common/cplbinfo.c
3 * Based on:
4 * Author: Sonic Zhang <sonic.zhang@analog.com>
5 *
6 * Created: Jan. 2005
7 * Description: Display CPLB status
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/module.h>
31#include <linux/kernel.h>
32#include <linux/init.h>
33#include <linux/proc_fs.h>
34#include <linux/uaccess.h>
35
36#include <asm/current.h>
37#include <asm/system.h>
38#include <asm/cplb.h>
39#include <asm/blackfin.h>
40
41#define CPLB_I 1
42#define CPLB_D 2
43
44#define SYNC_SYS SSYNC()
45#define SYNC_CORE CSYNC()
46
47#define CPLB_BIT_PAGESIZE 0x30000
48
49static int page_size_table[4] = {
50 0x00000400, /* 1K */
51 0x00001000, /* 4K */
52 0x00100000, /* 1M */
53 0x00400000 /* 4M */
54};
55
56static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
57
58static int cplb_find_entry(unsigned long *cplb_addr,
59 unsigned long *cplb_data, unsigned long addr,
60 unsigned long data)
61{
62 int ii;
63
64 for (ii = 0; ii < 16; ii++)
65 if (addr >= cplb_addr[ii] && addr < cplb_addr[ii] +
66 page_size_table[(cplb_data[ii] & CPLB_BIT_PAGESIZE) >> 16]
67 && (cplb_data[ii] == data))
68 return ii;
69
70 return -1;
71}
72
73static char *cplb_print_entry(char *buf, int type)
74{
75 unsigned long *p_addr = dpdt_table;
76 unsigned long *p_data = dpdt_table + 1;
77 unsigned long *p_icount = dpdt_swapcount_table;
78 unsigned long *p_ocount = dpdt_swapcount_table + 1;
79 unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0;
80 unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0;
81 int entry = 0, used_cplb = 0;
82
83 if (type == CPLB_I) {
84 buf += sprintf(buf, "Instruction CPLB entry:\n");
85 p_addr = ipdt_table;
86 p_data = ipdt_table + 1;
87 p_icount = ipdt_swapcount_table;
88 p_ocount = ipdt_swapcount_table + 1;
89 cplb_addr = (unsigned long *)ICPLB_ADDR0;
90 cplb_data = (unsigned long *)ICPLB_DATA0;
91 } else
92 buf += sprintf(buf, "Data CPLB entry:\n");
93
94 buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\tiCount\toCount\n");
95
96 while (*p_addr != 0xffffffff) {
97 entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
98 if (entry >= 0)
99 used_cplb |= 1 << entry;
100
101 buf +=
102 sprintf(buf,
103 "0x%08lx\t0x%05lx\t%s\t%c\t%c\t%2d\t%ld\t%ld\n",
104 *p_addr, *p_data,
105 page_size_string_table[(*p_data & 0x30000) >> 16],
106 (*p_data & CPLB_VALID) ? 'Y' : 'N',
107 (*p_data & CPLB_LOCK) ? 'Y' : 'N', entry, *p_icount,
108 *p_ocount);
109
110 p_addr += 2;
111 p_data += 2;
112 p_icount += 2;
113 p_ocount += 2;
114 }
115
116 if (used_cplb != 0xffff) {
117 buf += sprintf(buf, "Unused/mismatched CPLBs:\n");
118
119 for (entry = 0; entry < 16; entry++)
120 if (0 == ((1 << entry) & used_cplb)) {
121 int flags = cplb_data[entry];
122 buf +=
123 sprintf(buf,
124 "%2d: 0x%08lx\t0x%05x\t%s\t%c\t%c\n",
125 entry, cplb_addr[entry], flags,
126 page_size_string_table[(flags &
127 0x30000) >>
128 16],
129 (flags & CPLB_VALID) ? 'Y' : 'N',
130 (flags & CPLB_LOCK) ? 'Y' : 'N');
131 }
132 }
133
134 buf += sprintf(buf, "\n");
135
136 return buf;
137}
138
139static int cplbinfo_proc_output(char *buf)
140{
141 char *p;
142
143 p = buf;
144
145 p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
146
147 if (bfin_read_IMEM_CONTROL() & ENICPLB)
148 p = cplb_print_entry(p, CPLB_I);
149 else
150 p += sprintf(p, "Instruction CPLB is disabled.\n\n");
151
152 if (bfin_read_DMEM_CONTROL() & ENDCPLB)
153 p = cplb_print_entry(p, CPLB_D);
154 else
155 p += sprintf(p, "Data CPLB is disabled.\n");
156
157 return p - buf;
158}
159
160static int cplbinfo_read_proc(char *page, char **start, off_t off,
161 int count, int *eof, void *data)
162{
163 int len;
164
165 len = cplbinfo_proc_output(page);
166 if (len <= off + count)
167 *eof = 1;
168 *start = page + off;
169 len -= off;
170 if (len > count)
171 len = count;
172 if (len < 0)
173 len = 0;
174 return len;
175}
176
177static int cplbinfo_write_proc(struct file *file, const char __user *buffer,
178 unsigned long count, void *data)
179{
180 printk(KERN_INFO "Reset the CPLB swap in/out counts.\n");
181 memset(ipdt_swapcount_table, 0, MAX_SWITCH_I_CPLBS * sizeof(unsigned long));
182 memset(dpdt_swapcount_table, 0, MAX_SWITCH_D_CPLBS * sizeof(unsigned long));
183
184 return count;
185}
186
187static int __init cplbinfo_init(void)
188{
189 struct proc_dir_entry *entry;
190
191 entry = create_proc_entry("cplbinfo", 0, NULL);
192 if (!entry)
193 return -ENOMEM;
194
195 entry->read_proc = cplbinfo_read_proc;
196 entry->write_proc = cplbinfo_write_proc;
197 entry->data = NULL;
198
199 return 0;
200}
201
202static void __exit cplbinfo_exit(void)
203{
204 remove_proc_entry("cplbinfo", NULL);
205}
206
207module_init(cplbinfo_init);
208module_exit(cplbinfo_exit);
diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S
deleted file mode 100644
index 6f909cbfac7b..000000000000
--- a/arch/blackfin/mach-common/cplbmgr.S
+++ /dev/null
@@ -1,619 +0,0 @@
1/*
2 * File: arch/blackfin/mach-common/cplbmgtr.S
3 * Based on:
4 * Author: LG Soft India
5 *
6 * Created: ?
7 * Description: CPLB replacement routine for CPLB mismatch
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/* Usage: int _cplb_mgr(is_data_miss,int enable_cache)
31 * is_data_miss==2 => Mark as Dirty, write to the clean data page
32 * is_data_miss==1 => Replace a data CPLB.
33 * is_data_miss==0 => Replace an instruction CPLB.
34 *
35 * Returns:
36 * CPLB_RELOADED => Successfully updated CPLB table.
37 * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted.
38 * This indicates that the CPLBs in the configuration
39 * tablei are badly configured, as this should never
40 * occur.
41 * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the
42 * exception, is not covered by any of the CPLBs in
43 * the configuration table. The application is
44 * presumably misbehaving.
45 * CPLB_PROT_VIOL => The address being accessed, that triggered the
46 * exception, was not a first-write to a clean Write
47 * Back Data page, and so presumably is a genuine
48 * violation of the page's protection attributes.
49 * The application is misbehaving.
50 */
51
52#include <linux/linkage.h>
53#include <asm/blackfin.h>
54#include <asm/cplb.h>
55
56#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
57.section .l1.text
58#else
59.text
60#endif
61
62.align 2;
63ENTRY(_cplb_mgr)
64
65 [--SP]=( R7:4,P5:3 );
66
67 CC = R0 == 2;
68 IF CC JUMP .Ldcplb_write;
69
70 CC = R0 == 0;
71 IF !CC JUMP .Ldcplb_miss_compare;
72
73 /* ICPLB Miss Exception. We need to choose one of the
74 * currently-installed CPLBs, and replace it with one
75 * from the configuration table.
76 */
77
78 P4.L = LO(ICPLB_FAULT_ADDR);
79 P4.H = HI(ICPLB_FAULT_ADDR);
80
81 P1 = 16;
82 P5.L = _page_size_table;
83 P5.H = _page_size_table;
84
85 P0.L = LO(ICPLB_DATA0);
86 P0.H = HI(ICPLB_DATA0);
87 R4 = [P4]; /* Get faulting address*/
88 R6 = 64; /* Advance past the fault address, which*/
89 R6 = R6 + R4; /* we'll use if we find a match*/
90 R3 = ((16 << 8) | 2); /* Extract mask, bits 16 and 17.*/
91
92 R5 = 0;
93.Lisearch:
94
95 R1 = [P0-0x100]; /* Address for this CPLB */
96
97 R0 = [P0++]; /* Info for this CPLB*/
98 CC = BITTST(R0,0); /* Is the CPLB valid?*/
99 IF !CC JUMP .Lnomatch; /* Skip it, if not.*/
100 CC = R4 < R1(IU); /* If fault address less than page start*/
101 IF CC JUMP .Lnomatch; /* then skip this one.*/
102 R2 = EXTRACT(R0,R3.L) (Z); /* Get page size*/
103 P1 = R2;
104 P1 = P5 + (P1<<2); /* index into page-size table*/
105 R2 = [P1]; /* Get the page size*/
106 R1 = R1 + R2; /* and add to page start, to get page end*/
107 CC = R4 < R1(IU); /* and see whether fault addr is in page.*/
108 IF !CC R4 = R6; /* If so, advance the address and finish loop.*/
109 IF !CC JUMP .Lisearch_done;
110.Lnomatch:
111 /* Go around again*/
112 R5 += 1;
113 CC = BITTST(R5, 4); /* i.e CC = R5 >= 16*/
114 IF !CC JUMP .Lisearch;
115
116.Lisearch_done:
117 I0 = R4; /* Fault address we'll search for*/
118
119 /* set up pointers */
120 P0.L = LO(ICPLB_DATA0);
121 P0.H = HI(ICPLB_DATA0);
122
123 /* The replacement procedure for ICPLBs */
124
125 P4.L = LO(IMEM_CONTROL);
126 P4.H = HI(IMEM_CONTROL);
127
128 /* disable cplbs */
129 R5 = [P4]; /* Control Register*/
130 BITCLR(R5,ENICPLB_P);
131 CLI R1;
132 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
133 .align 8;
134 [P4] = R5;
135 SSYNC;
136 STI R1;
137
138 R1 = -1; /* end point comparison */
139 R3 = 16; /* counter */
140
141 /* Search through CPLBs for first non-locked entry */
142 /* Overwrite it by moving everyone else up by 1 */
143.Licheck_lock:
144 R0 = [P0++];
145 R3 = R3 + R1;
146 CC = R3 == R1;
147 IF CC JUMP .Lall_locked;
148 CC = BITTST(R0, 0); /* an invalid entry is good */
149 IF !CC JUMP .Lifound_victim;
150 CC = BITTST(R0,1); /* but a locked entry isn't */
151 IF CC JUMP .Licheck_lock;
152
153.Lifound_victim:
154#ifdef CONFIG_CPLB_INFO
155 R7 = [P0 - 0x104];
156 P2.L = _ipdt_table;
157 P2.H = _ipdt_table;
158 P3.L = _ipdt_swapcount_table;
159 P3.H = _ipdt_swapcount_table;
160 P3 += -4;
161.Licount:
162 R2 = [P2]; /* address from config table */
163 P2 += 8;
164 P3 += 8;
165 CC = R2==-1;
166 IF CC JUMP .Licount_done;
167 CC = R7==R2;
168 IF !CC JUMP .Licount;
169 R7 = [P3];
170 R7 += 1;
171 [P3] = R7;
172 CSYNC;
173.Licount_done:
174#endif
175 LC0=R3;
176 LSETUP(.Lis_move,.Lie_move) LC0;
177.Lis_move:
178 R0 = [P0];
179 [P0 - 4] = R0;
180 R0 = [P0 - 0x100];
181 [P0-0x104] = R0;
182.Lie_move:P0+=4;
183
184 /* We've made space in the ICPLB table, so that ICPLB15
185 * is now free to be overwritten. Next, we have to determine
186 * which CPLB we need to install, from the configuration
187 * table. This is a matter of getting the start-of-page
188 * addresses and page-lengths from the config table, and
189 * determining whether the fault address falls within that
190 * range.
191 */
192
193 P2.L = _ipdt_table;
194 P2.H = _ipdt_table;
195#ifdef CONFIG_CPLB_INFO
196 P3.L = _ipdt_swapcount_table;
197 P3.H = _ipdt_swapcount_table;
198 P3 += -8;
199#endif
200 P0.L = _page_size_table;
201 P0.H = _page_size_table;
202
203 /* Retrieve our fault address (which may have been advanced
204 * because the faulting instruction crossed a page boundary).
205 */
206
207 R0 = I0;
208
209 /* An extraction pattern, to get the page-size bits from
210 * the CPLB data entry. Bits 16-17, so two bits at posn 16.
211 */
212
213 R1 = ((16<<8)|2);
214.Linext: R4 = [P2++]; /* address from config table */
215 R2 = [P2++]; /* data from config table */
216#ifdef CONFIG_CPLB_INFO
217 P3 += 8;
218#endif
219
220 CC = R4 == -1; /* End of config table*/
221 IF CC JUMP .Lno_page_in_table;
222
223 /* See if failed address > start address */
224 CC = R4 <= R0(IU);
225 IF !CC JUMP .Linext;
226
227 /* extract page size (17:16)*/
228 R3 = EXTRACT(R2, R1.L) (Z);
229
230 /* add page size to addr to get range */
231
232 P5 = R3;
233 P5 = P0 + (P5 << 2); /* scaled, for int access*/
234 R3 = [P5];
235 R3 = R3 + R4;
236
237 /* See if failed address < (start address + page size) */
238 CC = R0 < R3(IU);
239 IF !CC JUMP .Linext;
240
241 /* We've found a CPLB in the config table that covers
242 * the faulting address, so install this CPLB into the
243 * last entry of the table.
244 */
245
246 P1.L = LO(ICPLB_DATA15); /* ICPLB_DATA15 */
247 P1.H = HI(ICPLB_DATA15);
248 [P1] = R2;
249 [P1-0x100] = R4;
250#ifdef CONFIG_CPLB_INFO
251 R3 = [P3];
252 R3 += 1;
253 [P3] = R3;
254#endif
255
256 /* P4 points to IMEM_CONTROL, and R5 contains its old
257 * value, after we disabled ICPLBS. Re-enable them.
258 */
259
260 BITSET(R5,ENICPLB_P);
261 CLI R2;
262 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
263 .align 8;
264 [P4] = R5;
265 SSYNC;
266 STI R2;
267
268 ( R7:4,P5:3 ) = [SP++];
269 R0 = CPLB_RELOADED;
270 RTS;
271
272/* FAILED CASES*/
273.Lno_page_in_table:
274 R0 = CPLB_NO_ADDR_MATCH;
275 JUMP .Lfail_ret;
276
277.Lall_locked:
278 R0 = CPLB_NO_UNLOCKED;
279 JUMP .Lfail_ret;
280
281.Lprot_violation:
282 R0 = CPLB_PROT_VIOL;
283
284.Lfail_ret:
285 /* Make sure we turn protection/cache back on, even in the failing case */
286 BITSET(R5,ENICPLB_P);
287 CLI R2;
288 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
289 .align 8;
290 [P4] = R5;
291 SSYNC;
292 STI R2;
293
294 ( R7:4,P5:3 ) = [SP++];
295 RTS;
296
297.Ldcplb_write:
298
299 /* if a DCPLB is marked as write-back (CPLB_WT==0), and
300 * it is clean (CPLB_DIRTY==0), then a write to the
301 * CPLB's page triggers a protection violation. We have to
302 * mark the CPLB as dirty, to indicate that there are
303 * pending writes associated with the CPLB.
304 */
305
306 P4.L = LO(DCPLB_STATUS);
307 P4.H = HI(DCPLB_STATUS);
308 P3.L = LO(DCPLB_DATA0);
309 P3.H = HI(DCPLB_DATA0);
310 R5 = [P4];
311
312 /* A protection violation can be caused by more than just writes
313 * to a clean WB page, so we have to ensure that:
314 * - It's a write
315 * - to a clean WB page
316 * - and is allowed in the mode the access occurred.
317 */
318
319 CC = BITTST(R5, 16); /* ensure it was a write*/
320 IF !CC JUMP .Lprot_violation;
321
322 /* to check the rest, we have to retrieve the DCPLB.*/
323
324 /* The low half of DCPLB_STATUS is a bit mask*/
325
326 R2 = R5.L (Z); /* indicating which CPLB triggered the event.*/
327 R3 = 30; /* so we can use this to determine the offset*/
328 R2.L = SIGNBITS R2;
329 R2 = R2.L (Z); /* into the DCPLB table.*/
330 R3 = R3 - R2;
331 P4 = R3;
332 P3 = P3 + (P4<<2);
333 R3 = [P3]; /* Retrieve the CPLB*/
334
335 /* Now we can check whether it's a clean WB page*/
336
337 CC = BITTST(R3, 14); /* 0==WB, 1==WT*/
338 IF CC JUMP .Lprot_violation;
339 CC = BITTST(R3, 7); /* 0 == clean, 1 == dirty*/
340 IF CC JUMP .Lprot_violation;
341
342 /* Check whether the write is allowed in the mode that was active.*/
343
344 R2 = 1<<3; /* checking write in user mode*/
345 CC = BITTST(R5, 17); /* 0==was user, 1==was super*/
346 R5 = CC;
347 R2 <<= R5; /* if was super, check write in super mode*/
348 R2 = R3 & R2;
349 CC = R2 == 0;
350 IF CC JUMP .Lprot_violation;
351
352 /* It's a genuine write-to-clean-page.*/
353
354 BITSET(R3, 7); /* mark as dirty*/
355 [P3] = R3; /* and write back.*/
356 NOP;
357 CSYNC;
358 ( R7:4,P5:3 ) = [SP++];
359 R0 = CPLB_RELOADED;
360 RTS;
361
362.Ldcplb_miss_compare:
363
364 /* Data CPLB Miss event. We need to choose a CPLB to
365 * evict, and then locate a new CPLB to install from the
366 * config table, that covers the faulting address.
367 */
368
369 P1.L = LO(DCPLB_DATA15);
370 P1.H = HI(DCPLB_DATA15);
371
372 P4.L = LO(DCPLB_FAULT_ADDR);
373 P4.H = HI(DCPLB_FAULT_ADDR);
374 R4 = [P4];
375 I0 = R4;
376
377 /* The replacement procedure for DCPLBs*/
378
379 R6 = R1; /* Save for later*/
380
381 /* Turn off CPLBs while we work.*/
382 P4.L = LO(DMEM_CONTROL);
383 P4.H = HI(DMEM_CONTROL);
384 R5 = [P4];
385 BITCLR(R5,ENDCPLB_P);
386 CLI R0;
387 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
388 .align 8;
389 [P4] = R5;
390 SSYNC;
391 STI R0;
392
393 /* Start looking for a CPLB to evict. Our order of preference
394 * is: invalid CPLBs, clean CPLBs, dirty CPLBs. Locked CPLBs
395 * are no good.
396 */
397
398 I1.L = LO(DCPLB_DATA0);
399 I1.H = HI(DCPLB_DATA0);
400 P1 = 2;
401 P2 = 16;
402 I2.L = _dcplb_preference;
403 I2.H = _dcplb_preference;
404 LSETUP(.Lsdsearch1, .Ledsearch1) LC0 = P1;
405.Lsdsearch1:
406 R0 = [I2++]; /* Get the bits we're interested in*/
407 P0 = I1; /* Go back to start of table*/
408 LSETUP (.Lsdsearch2, .Ledsearch2) LC1 = P2;
409.Lsdsearch2:
410 R1 = [P0++]; /* Fetch each installed CPLB in turn*/
411 R2 = R1 & R0; /* and test for interesting bits.*/
412 CC = R2 == 0; /* If none are set, it'll do.*/
413 IF !CC JUMP .Lskip_stack_check;
414
415 R2 = [P0 - 0x104]; /* R2 - PageStart */
416 P3.L = _page_size_table; /* retrieve end address */
417 P3.H = _page_size_table; /* retrieve end address */
418 R3 = 0x1002; /* 16th - position, 2 bits -length */
419#if ANOMALY_05000209
420 nop; /* Anomaly 05000209 */
421#endif
422 R7 = EXTRACT(R1,R3.l);
423 R7 = R7 << 2; /* Page size index offset */
424 P5 = R7;
425 P3 = P3 + P5;
426 R7 = [P3]; /* page size in bytes */
427
428 R7 = R2 + R7; /* R7 - PageEnd */
429 R4 = SP; /* Test SP is in range */
430
431 CC = R7 < R4; /* if PageEnd < SP */
432 IF CC JUMP .Ldfound_victim;
433 R3 = 0x284; /* stack length from start of trap till
434 * the point.
435 * 20 stack locations for future modifications
436 */
437 R4 = R4 + R3;
438 CC = R4 < R2; /* if SP + stacklen < PageStart */
439 IF CC JUMP .Ldfound_victim;
440.Lskip_stack_check:
441
442.Ledsearch2: NOP;
443.Ledsearch1: NOP;
444
445 /* If we got here, we didn't find a DCPLB we considered
446 * replacable, which means all of them were locked.
447 */
448
449 JUMP .Lall_locked;
450.Ldfound_victim:
451
452#ifdef CONFIG_CPLB_INFO
453 R7 = [P0 - 0x104];
454 P2.L = _dpdt_table;
455 P2.H = _dpdt_table;
456 P3.L = _dpdt_swapcount_table;
457 P3.H = _dpdt_swapcount_table;
458 P3 += -4;
459.Ldicount:
460 R2 = [P2];
461 P2 += 8;
462 P3 += 8;
463 CC = R2==-1;
464 IF CC JUMP .Ldicount_done;
465 CC = R7==R2;
466 IF !CC JUMP .Ldicount;
467 R7 = [P3];
468 R7 += 1;
469 [P3] = R7;
470.Ldicount_done:
471#endif
472
473 /* Clean down the hardware loops*/
474 R2 = 0;
475 LC1 = R2;
476 LC0 = R2;
477
478 /* There's a suitable victim in [P0-4] (because we've
479 * advanced already).
480 */
481
482.LDdoverwrite:
483
484 /* [P0-4] is a suitable victim CPLB, so we want to
485 * overwrite it by moving all the following CPLBs
486 * one space closer to the start.
487 */
488
489 R1.L = LO(DCPLB_DATA16); /* DCPLB_DATA15 + 4 */
490 R1.H = HI(DCPLB_DATA16);
491 R0 = P0;
492
493 /* If the victim happens to be in DCPLB15,
494 * we don't need to move anything.
495 */
496
497 CC = R1 == R0;
498 IF CC JUMP .Lde_moved;
499 R1 = R1 - R0;
500 R1 >>= 2;
501 P1 = R1;
502 LSETUP(.Lds_move, .Lde_move) LC0=P1;
503.Lds_move:
504 R0 = [P0++]; /* move data */
505 [P0 - 8] = R0;
506 R0 = [P0-0x104] /* move address */
507.Lde_move: [P0-0x108] = R0;
508
509 /* We've now made space in DCPLB15 for the new CPLB to be
510 * installed. The next stage is to locate a CPLB in the
511 * config table that covers the faulting address.
512 */
513
514.Lde_moved:NOP;
515 R0 = I0; /* Our faulting address */
516
517 P2.L = _dpdt_table;
518 P2.H = _dpdt_table;
519#ifdef CONFIG_CPLB_INFO
520 P3.L = _dpdt_swapcount_table;
521 P3.H = _dpdt_swapcount_table;
522 P3 += -8;
523#endif
524
525 P1.L = _page_size_table;
526 P1.H = _page_size_table;
527
528 /* An extraction pattern, to retrieve bits 17:16.*/
529
530 R1 = (16<<8)|2;
531.Ldnext: R4 = [P2++]; /* address */
532 R2 = [P2++]; /* data */
533#ifdef CONFIG_CPLB_INFO
534 P3 += 8;
535#endif
536
537 CC = R4 == -1;
538 IF CC JUMP .Lno_page_in_table;
539
540 /* See if failed address > start address */
541 CC = R4 <= R0(IU);
542 IF !CC JUMP .Ldnext;
543
544 /* extract page size (17:16)*/
545 R3 = EXTRACT(R2, R1.L) (Z);
546
547 /* add page size to addr to get range */
548
549 P5 = R3;
550 P5 = P1 + (P5 << 2);
551 R3 = [P5];
552 R3 = R3 + R4;
553
554 /* See if failed address < (start address + page size) */
555 CC = R0 < R3(IU);
556 IF !CC JUMP .Ldnext;
557
558 /* We've found the CPLB that should be installed, so
559 * write it into CPLB15, masking off any caching bits
560 * if necessary.
561 */
562
563 P1.L = LO(DCPLB_DATA15);
564 P1.H = HI(DCPLB_DATA15);
565
566 /* If the DCPLB has cache bits set, but caching hasn't
567 * been enabled, then we want to mask off the cache-in-L1
568 * bit before installing. Moreover, if caching is off, we
569 * also want to ensure that the DCPLB has WT mode set, rather
570 * than WB, since WB pages still trigger first-write exceptions
571 * even when not caching is off, and the page isn't marked as
572 * cachable. Finally, we could mark the page as clean, not dirty,
573 * but we choose to leave that decision to the user; if the user
574 * chooses to have a CPLB pre-defined as dirty, then they always
575 * pay the cost of flushing during eviction, but don't pay the
576 * cost of first-write exceptions to mark the page as dirty.
577 */
578
579#ifdef CONFIG_BFIN_WT
580 BITSET(R6, 14); /* Set WT*/
581#endif
582
583 [P1] = R2;
584 [P1-0x100] = R4;
585#ifdef CONFIG_CPLB_INFO
586 R3 = [P3];
587 R3 += 1;
588 [P3] = R3;
589#endif
590
591 /* We've installed the CPLB, so re-enable CPLBs. P4
592 * points to DMEM_CONTROL, and R5 is the value we
593 * last wrote to it, when we were disabling CPLBs.
594 */
595
596 BITSET(R5,ENDCPLB_P);
597 CLI R2;
598 .align 8;
599 [P4] = R5;
600 SSYNC;
601 STI R2;
602
603 ( R7:4,P5:3 ) = [SP++];
604 R0 = CPLB_RELOADED;
605 RTS;
606ENDPROC(_cplb_mgr)
607
608.data
609.align 4;
610_page_size_table:
611.byte4 0x00000400; /* 1K */
612.byte4 0x00001000; /* 4K */
613.byte4 0x00100000; /* 1M */
614.byte4 0x00400000; /* 4M */
615
616.align 4;
617_dcplb_preference:
618.byte4 0x00000001; /* valid bit */
619.byte4 0x00000002; /* lock bit */
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S
index 39fbc2861107..b82c096e1980 100644
--- a/arch/blackfin/mach-common/dpmc.S
+++ b/arch/blackfin/mach-common/dpmc.S
@@ -38,6 +38,9 @@ ENTRY(_unmask_wdog_wakeup_evt)
38#if defined(CONFIG_BF561) 38#if defined(CONFIG_BF561)
39 P0.H = hi(SICA_IWR1); 39 P0.H = hi(SICA_IWR1);
40 P0.L = lo(SICA_IWR1); 40 P0.L = lo(SICA_IWR1);
41#elif defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
42 P0.h = HI(SIC_IWR0);
43 P0.l = LO(SIC_IWR0);
41#else 44#else
42 P0.h = HI(SIC_IWR); 45 P0.h = HI(SIC_IWR);
43 P0.l = LO(SIC_IWR); 46 P0.l = LO(SIC_IWR);
@@ -172,7 +175,7 @@ ENTRY(_sleep_mode)
172 call _set_sic_iwr; 175 call _set_sic_iwr;
173 176
174 R0 = 0xFFFF (Z); 177 R0 = 0xFFFF (Z);
175 call _set_rtc_istat 178 call _set_rtc_istat;
176 179
177 P0.H = hi(PLL_CTL); 180 P0.H = hi(PLL_CTL);
178 P0.L = lo(PLL_CTL); 181 P0.L = lo(PLL_CTL);
@@ -210,7 +213,7 @@ ENTRY(_hibernate_mode)
210 call _set_sic_iwr; 213 call _set_sic_iwr;
211 214
212 R0 = 0xFFFF (Z); 215 R0 = 0xFFFF (Z);
213 call _set_rtc_istat 216 call _set_rtc_istat;
214 217
215 P0.H = hi(VR_CTL); 218 P0.H = hi(VR_CTL);
216 P0.L = lo(VR_CTL); 219 P0.L = lo(VR_CTL);
@@ -236,7 +239,7 @@ ENTRY(_deep_sleep)
236 239
237 call _set_sic_iwr; 240 call _set_sic_iwr;
238 241
239 call _set_sdram_srfs; 242 call _set_dram_srfs;
240 243
241 /* Clear all the interrupts,bits sticky */ 244 /* Clear all the interrupts,bits sticky */
242 R0 = 0xFFFF (Z); 245 R0 = 0xFFFF (Z);
@@ -253,7 +256,7 @@ ENTRY(_deep_sleep)
253 SSYNC; 256 SSYNC;
254 IDLE; 257 IDLE;
255 258
256 call _unset_sdram_srfs; 259 call _unset_dram_srfs;
257 260
258 call _test_pll_locked; 261 call _test_pll_locked;
259 262
@@ -285,23 +288,22 @@ ENTRY(_sleep_deeper)
285 P3 = R0; 288 P3 = R0;
286 R0 = IWR_ENABLE(0); 289 R0 = IWR_ENABLE(0);
287 call _set_sic_iwr; 290 call _set_sic_iwr;
288 call _set_sdram_srfs; 291 call _set_dram_srfs; /* Set SDRAM Self Refresh */
289 292
290 /* Clear all the interrupts,bits sticky */ 293 /* Clear all the interrupts,bits sticky */
291 R0 = 0xFFFF (Z); 294 R0 = 0xFFFF (Z);
292 call _set_rtc_istat 295 call _set_rtc_istat;
293
294 P0.H = hi(PLL_DIV); 296 P0.H = hi(PLL_DIV);
295 P0.L = lo(PLL_DIV); 297 P0.L = lo(PLL_DIV);
296 R6 = W[P0](z); 298 R6 = W[P0](z);
297 R0.L = 0xF; 299 R0.L = 0xF;
298 W[P0] = R0.l; 300 W[P0] = R0.l; /* Set Max VCO to SCLK divider */
299 301
300 P0.H = hi(PLL_CTL); 302 P0.H = hi(PLL_CTL);
301 P0.L = lo(PLL_CTL); 303 P0.L = lo(PLL_CTL);
302 R5 = W[P0](z); 304 R5 = W[P0](z);
303 R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9; 305 R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
304 W[P0] = R0.l; 306 W[P0] = R0.l; /* Set Min CLKIN to VCO multiplier */
305 307
306 SSYNC; 308 SSYNC;
307 IDLE; 309 IDLE;
@@ -317,29 +319,28 @@ ENTRY(_sleep_deeper)
317 R1 = R1|R2; 319 R1 = R1|R2;
318 320
319 R2 = DEPOSIT(R7, R1); 321 R2 = DEPOSIT(R7, R1);
320 W[P0] = R2; 322 W[P0] = R2; /* Set Min Core Voltage */
321 323
322 SSYNC; 324 SSYNC;
323 IDLE; 325 IDLE;
324 326
325 call _test_pll_locked; 327 call _test_pll_locked;
326 328
329 R0 = P3;
330 call _set_sic_iwr; /* Set Awake from IDLE */
331
327 P0.H = hi(PLL_CTL); 332 P0.H = hi(PLL_CTL);
328 P0.L = lo(PLL_CTL); 333 P0.L = lo(PLL_CTL);
329 R0 = W[P0](z); 334 R0 = W[P0](z);
330 BITSET (R0, 3); 335 BITSET (R0, 3);
331 W[P0] = R0.L; 336 W[P0] = R0.L; /* Turn CCLK OFF */
332
333 R0 = P3;
334 call _set_sic_iwr;
335
336 SSYNC; 337 SSYNC;
337 IDLE; 338 IDLE;
338 339
339 call _test_pll_locked; 340 call _test_pll_locked;
340 341
341 R0 = IWR_ENABLE(0); 342 R0 = IWR_ENABLE(0);
342 call _set_sic_iwr; 343 call _set_sic_iwr; /* Set Awake from IDLE PLL */
343 344
344 P0.H = hi(VR_CTL); 345 P0.H = hi(VR_CTL);
345 P0.L = lo(VR_CTL); 346 P0.L = lo(VR_CTL);
@@ -352,15 +353,15 @@ ENTRY(_sleep_deeper)
352 353
353 P0.H = hi(PLL_DIV); 354 P0.H = hi(PLL_DIV);
354 P0.L = lo(PLL_DIV); 355 P0.L = lo(PLL_DIV);
355 W[P0]= R6; 356 W[P0]= R6; /* Restore CCLK and SCLK divider */
356 357
357 P0.H = hi(PLL_CTL); 358 P0.H = hi(PLL_CTL);
358 P0.L = lo(PLL_CTL); 359 P0.L = lo(PLL_CTL);
359 w[p0] = R5; 360 w[p0] = R5; /* Restore VCO multiplier */
360 IDLE; 361 IDLE;
361 call _test_pll_locked; 362 call _test_pll_locked;
362 363
363 call _unset_sdram_srfs; 364 call _unset_dram_srfs; /* SDRAM Self Refresh Off */
364 365
365 STI R4; 366 STI R4;
366 367
@@ -368,25 +369,47 @@ ENTRY(_sleep_deeper)
368 ( R7:0, P5:0 ) = [SP++]; 369 ( R7:0, P5:0 ) = [SP++];
369 RTS; 370 RTS;
370 371
371ENTRY(_set_sdram_srfs) 372ENTRY(_set_dram_srfs)
372 /* set the sdram to self refresh mode */ 373 /* set the dram to self refresh mode */
374#if defined(CONFIG_BF54x)
375 P0.H = hi(EBIU_RSTCTL);
376 P0.L = lo(EBIU_RSTCTL);
377 R2 = [P0];
378 R3.H = hi(SRREQ);
379 R3.L = lo(SRREQ);
380#else
373 P0.H = hi(EBIU_SDGCTL); 381 P0.H = hi(EBIU_SDGCTL);
374 P0.L = lo(EBIU_SDGCTL); 382 P0.L = lo(EBIU_SDGCTL);
375 R2 = [P0]; 383 R2 = [P0];
376 R3.H = hi(SRFS); 384 R3.H = hi(SRFS);
377 R3.L = lo(SRFS); 385 R3.L = lo(SRFS);
386#endif
378 R2 = R2|R3; 387 R2 = R2|R3;
379 [P0] = R2; 388 [P0] = R2;
380 ssync; 389 ssync;
390#if defined(CONFIG_BF54x)
391.LSRR_MODE:
392 R2 = [P0];
393 CC = BITTST(R2, 4);
394 if !CC JUMP .LSRR_MODE;
395#endif
381 RTS; 396 RTS;
382 397
383ENTRY(_unset_sdram_srfs) 398ENTRY(_unset_dram_srfs)
384 /* set the sdram out of self refresh mode */ 399 /* set the dram out of self refresh mode */
400#if defined(CONFIG_BF54x)
401 P0.H = hi(EBIU_RSTCTL);
402 P0.L = lo(EBIU_RSTCTL);
403 R2 = [P0];
404 R3.H = hi(SRREQ);
405 R3.L = lo(SRREQ);
406#else
385 P0.H = hi(EBIU_SDGCTL); 407 P0.H = hi(EBIU_SDGCTL);
386 P0.L = lo(EBIU_SDGCTL); 408 P0.L = lo(EBIU_SDGCTL);
387 R2 = [P0]; 409 R2 = [P0];
388 R3.H = hi(SRFS); 410 R3.H = hi(SRFS);
389 R3.L = lo(SRFS); 411 R3.L = lo(SRFS);
412#endif
390 R3 = ~R3; 413 R3 = ~R3;
391 R2 = R2&R3; 414 R2 = R2&R3;
392 [P0] = R2; 415 [P0] = R2;
@@ -394,8 +417,13 @@ ENTRY(_unset_sdram_srfs)
394 RTS; 417 RTS;
395 418
396ENTRY(_set_sic_iwr) 419ENTRY(_set_sic_iwr)
420#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
421 P0.H = hi(SIC_IWR0);
422 P0.L = lo(SIC_IWR0);
423#else
397 P0.H = hi(SIC_IWR); 424 P0.H = hi(SIC_IWR);
398 P0.L = lo(SIC_IWR); 425 P0.L = lo(SIC_IWR);
426#endif
399 [P0] = R0; 427 [P0] = R0;
400 SSYNC; 428 SSYNC;
401 RTS; 429 RTS;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index dc9d3ee2e691..56ff51bc8c21 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -95,6 +95,9 @@ ENTRY(_ex_workaround_261)
95 R6 = 0x26; /* Data CPLB Miss */ 95 R6 = 0x26; /* Data CPLB Miss */
96 cc = R6 == R7; 96 cc = R6 == R7;
97 if cc jump _ex_dcplb_miss (BP); 97 if cc jump _ex_dcplb_miss (BP);
98 R6 = 0x23; /* Data CPLB Miss */
99 cc = R6 == R7;
100 if cc jump _ex_dcplb_viol (BP);
98 /* Handle 0x23 Data CPLB Protection Violation 101 /* Handle 0x23 Data CPLB Protection Violation
99 * and Data CPLB Multiple Hits - Linux Trap Zero 102 * and Data CPLB Multiple Hits - Linux Trap Zero
100 */ 103 */
@@ -102,17 +105,33 @@ ENTRY(_ex_workaround_261)
102ENDPROC(_ex_workaround_261) 105ENDPROC(_ex_workaround_261)
103 106
104#else 107#else
108#ifdef CONFIG_MPU
109#define _ex_dviol _ex_dcplb_viol
110#else
105#define _ex_dviol _ex_trap_c 111#define _ex_dviol _ex_trap_c
112#endif
106#define _ex_dmiss _ex_dcplb_miss 113#define _ex_dmiss _ex_dcplb_miss
107#define _ex_dmult _ex_trap_c 114#define _ex_dmult _ex_trap_c
108#endif 115#endif
109 116
117
118ENTRY(_ex_dcplb_viol)
110ENTRY(_ex_dcplb_miss) 119ENTRY(_ex_dcplb_miss)
111ENTRY(_ex_icplb_miss) 120ENTRY(_ex_icplb_miss)
112 (R7:6,P5:4) = [sp++]; 121 (R7:6,P5:4) = [sp++];
113 ASTAT = [sp++]; 122 ASTAT = [sp++];
114 SAVE_ALL_SYS 123 SAVE_ALL_SYS
124#ifdef CONFIG_MPU
125 R0 = SEQSTAT;
126 R1 = SP;
127 sp += -12;
128 call _cplb_hdr;
129 sp += 12;
130 CC = R0 == 0;
131 IF !CC JUMP _handle_bad_cplb;
132#else
115 call __cplb_hdr; 133 call __cplb_hdr;
134#endif
116 DEBUG_START_HWTRACE(p5, r7) 135 DEBUG_START_HWTRACE(p5, r7)
117 RESTORE_ALL_SYS 136 RESTORE_ALL_SYS
118 SP = EX_SCRATCH_REG; 137 SP = EX_SCRATCH_REG;
@@ -329,7 +348,7 @@ ENTRY(_exception_to_level5)
329 R7 = R7 + R6; 348 R7 = R7 + R6;
330 P5 = R7; 349 P5 = R7;
331 R1 = [P5]; 350 R1 = [P5];
332 [SP + 8] = r1; 351 [SP + PT_SEQSTAT] = r1;
333 352
334 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ 353 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
335 SP += -12; 354 SP += -12;
@@ -633,9 +652,7 @@ ENTRY(_ret_from_exception)
633 [sp + PT_IPEND] = r0; 652 [sp + PT_IPEND] = r0;
634 653
6351: 6541:
636 r1 = 0x37(Z); 655 r2 = LO(~0x37) (Z);
637 r2 = ~r1;
638 r2.h = 0;
639 r0 = r2 & r0; 656 r0 = r2 & r0;
640 cc = r0 == 0; 657 cc = r0 == 0;
641 if !cc jump 4f; /* if not return to user mode, get out */ 658 if !cc jump 4f; /* if not return to user mode, get out */
@@ -1364,6 +1381,7 @@ ENTRY(_sys_call_table)
1364 .long _sys_set_robust_list 1381 .long _sys_set_robust_list
1365 .long _sys_get_robust_list /* 355 */ 1382 .long _sys_get_robust_list /* 355 */
1366 .long _sys_fallocate 1383 .long _sys_fallocate
1384 .long _sys_semtimedop
1367 .rept NR_syscalls-(.-_sys_call_table)/4 1385 .rept NR_syscalls-(.-_sys_call_table)/4
1368 .long _sys_ni_syscall 1386 .long _sys_ni_syscall
1369 .endr 1387 .endr
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 4de376418a18..7f752c87fe46 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -34,9 +34,13 @@
34#include <asm/entry.h> 34#include <asm/entry.h>
35#include <asm/asm-offsets.h> 35#include <asm/asm-offsets.h>
36#include <asm/trace.h> 36#include <asm/trace.h>
37#include <asm/traps.h>
38#include <asm/thread_info.h>
37 39
38#include <asm/mach-common/context.S> 40#include <asm/mach-common/context.S>
39 41
42.extern _ret_from_exception
43
40#ifdef CONFIG_I_ENTRY_L1 44#ifdef CONFIG_I_ENTRY_L1
41.section .l1.text 45.section .l1.text
42#else 46#else
@@ -117,8 +121,8 @@ __common_int_entry:
117 121
118#if ANOMALY_05000283 || ANOMALY_05000315 122#if ANOMALY_05000283 || ANOMALY_05000315
119 cc = r7 == r7; 123 cc = r7 == r7;
120 p5.h = 0xffc0; 124 p5.h = HI(CHIPID);
121 p5.l = 0x0014; 125 p5.l = LO(CHIPID);
122 if cc jump 1f; 126 if cc jump 1f;
123 r7.l = W[p5]; 127 r7.l = W[p5];
1241: 1281:
@@ -134,26 +138,22 @@ __common_int_entry:
134 138
135/* interrupt routine for ivhw - 5 */ 139/* interrupt routine for ivhw - 5 */
136ENTRY(_evt_ivhw) 140ENTRY(_evt_ivhw)
137 SAVE_CONTEXT 141 SAVE_ALL_SYS
138#ifdef CONFIG_FRAME_POINTER 142#ifdef CONFIG_FRAME_POINTER
139 fp = 0; 143 fp = 0;
140#endif 144#endif
145
141#if ANOMALY_05000283 146#if ANOMALY_05000283
142 cc = r7 == r7; 147 cc = r7 == r7;
143 p5.h = 0xffc0; 148 p5.h = HI(CHIPID);
144 p5.l = 0x0014; 149 p5.l = LO(CHIPID);
145 if cc jump 1f; 150 if cc jump 1f;
146 r7.l = W[p5]; 151 r7.l = W[p5];
1471: 1521:
148#endif 153#endif
149 154
150 trace_buffer_stop(p0, r0);
151
152 r0 = IRQ_HWERR;
153 r1 = sp;
154
155#ifdef CONFIG_HARDWARE_PM 155#ifdef CONFIG_HARDWARE_PM
156 r7 = SEQSTAT; 156 r7 = [sp + PT_SEQSTAT];
157 r7 = r7 >>> 0xe; 157 r7 = r7 >>> 0xe;
158 r6 = 0x1F; 158 r6 = 0x1F;
159 r7 = r7 & r6; 159 r7 = r7 & r6;
@@ -161,11 +161,29 @@ ENTRY(_evt_ivhw)
161 cc = r7 == r5; 161 cc = r7 == r5;
162 if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */ 162 if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */
163#endif 163#endif
164 164 # We are going to dump something out, so make sure we print IPEND properly
165 p2.l = lo(IPEND);
166 p2.h = hi(IPEND);
167 r0 = [p2];
168 [sp + PT_IPEND] = r0;
169
170 /* set the EXCAUSE to HWERR for trap_c */
171 r0 = [sp + PT_SEQSTAT];
172 R1.L = LO(VEC_HWERR);
173 R1.H = HI(VEC_HWERR);
174 R0 = R0 | R1;
175 [sp + PT_SEQSTAT] = R0;
176
177 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
165 SP += -12; 178 SP += -12;
166 call _irq_panic; 179 call _trap_c;
167 SP += 12; 180 SP += 12;
181
182 call _ret_from_exception;
183.Lcommon_restore_all_sys:
184 RESTORE_ALL_SYS
168 rti; 185 rti;
186
169#ifdef CONFIG_HARDWARE_PM 187#ifdef CONFIG_HARDWARE_PM
170.Lcall_do_ovf: 188.Lcall_do_ovf:
171 189
@@ -173,9 +191,11 @@ ENTRY(_evt_ivhw)
173 call _pm_overflow; 191 call _pm_overflow;
174 SP += 12; 192 SP += 12;
175 193
176 jump .Lcommon_restore_context; 194 jump .Lcommon_restore_all_sys;
177#endif 195#endif
178 196
197ENDPROC(_evt_ivhw)
198
179/* Interrupt routine for evt2 (NMI). 199/* Interrupt routine for evt2 (NMI).
180 * We don't actually use this, so just return. 200 * We don't actually use this, so just return.
181 * For inner circle type details, please see: 201 * For inner circle type details, please see:
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
index 4882f0e801a9..8d18d6b163bb 100644
--- a/arch/blackfin/mach-common/ints-priority-dc.c
+++ b/arch/blackfin/mach-common/ints-priority-dc.c
@@ -222,11 +222,12 @@ static void bf561_gpio_unmask_irq(unsigned int irq)
222static unsigned int bf561_gpio_irq_startup(unsigned int irq) 222static unsigned int bf561_gpio_irq_startup(unsigned int irq)
223{ 223{
224 unsigned int ret; 224 unsigned int ret;
225 char buf[8];
225 u16 gpionr = irq - IRQ_PF0; 226 u16 gpionr = irq - IRQ_PF0;
226 227
227 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 228 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
228 229 snprintf(buf, sizeof buf, "IRQ %d", irq);
229 ret = gpio_request(gpionr, "IRQ"); 230 ret = gpio_request(gpionr, buf);
230 if (ret) 231 if (ret)
231 return ret; 232 return ret;
232 233
@@ -250,6 +251,7 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
250{ 251{
251 252
252 unsigned int ret; 253 unsigned int ret;
254 char buf[8];
253 u16 gpionr = irq - IRQ_PF0; 255 u16 gpionr = irq - IRQ_PF0;
254 256
255 257
@@ -265,8 +267,8 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
265 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 267 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
266 268
267 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 269 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
268 270 snprintf(buf, sizeof buf, "IRQ %d", irq);
269 ret = gpio_request(gpionr, "IRQ"); 271 ret = gpio_request(gpionr, buf);
270 if (ret) 272 if (ret)
271 return ret; 273 return ret;
272 274
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c
index 147f0731087a..dec42acb5de0 100644
--- a/arch/blackfin/mach-common/ints-priority-sc.c
+++ b/arch/blackfin/mach-common/ints-priority-sc.c
@@ -313,6 +313,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
313static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; 313static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
314static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; 314static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
315 315
316
316static void bfin_gpio_ack_irq(unsigned int irq) 317static void bfin_gpio_ack_irq(unsigned int irq)
317{ 318{
318 u16 gpionr = irq - IRQ_PF0; 319 u16 gpionr = irq - IRQ_PF0;
@@ -352,9 +353,11 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
352{ 353{
353 unsigned int ret; 354 unsigned int ret;
354 u16 gpionr = irq - IRQ_PF0; 355 u16 gpionr = irq - IRQ_PF0;
356 char buf[8];
355 357
356 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 358 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
357 ret = gpio_request(gpionr, "IRQ"); 359 snprintf(buf, sizeof buf, "IRQ %d", irq);
360 ret = gpio_request(gpionr, buf);
358 if (ret) 361 if (ret)
359 return ret; 362 return ret;
360 } 363 }
@@ -376,6 +379,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
376{ 379{
377 380
378 unsigned int ret; 381 unsigned int ret;
382 char buf[8];
379 u16 gpionr = irq - IRQ_PF0; 383 u16 gpionr = irq - IRQ_PF0;
380 384
381 if (type == IRQ_TYPE_PROBE) { 385 if (type == IRQ_TYPE_PROBE) {
@@ -388,7 +392,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
388 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | 392 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
389 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 393 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
390 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 394 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
391 ret = gpio_request(gpionr, "IRQ"); 395 snprintf(buf, sizeof buf, "IRQ %d", irq);
396 ret = gpio_request(gpionr, buf);
392 if (ret) 397 if (ret)
393 return ret; 398 return ret;
394 } 399 }
@@ -478,6 +483,10 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq,
478static unsigned char irq2pint_lut[NR_PINTS]; 483static unsigned char irq2pint_lut[NR_PINTS];
479static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; 484static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
480 485
486static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS];
487static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
488
489
481struct pin_int_t { 490struct pin_int_t {
482 unsigned int mask_set; 491 unsigned int mask_set;
483 unsigned int mask_clear; 492 unsigned int mask_clear;
@@ -544,13 +553,20 @@ void init_pint_lut(void)
544 553
545} 554}
546 555
547static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
548
549static void bfin_gpio_ack_irq(unsigned int irq) 556static void bfin_gpio_ack_irq(unsigned int irq)
550{ 557{
551 u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; 558 u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
559 u32 pintbit = PINT_BIT(pint_val);
560 u8 bank = PINT_2_BANK(pint_val);
561
562 if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) {
563 if (pint[bank]->invert_set & pintbit)
564 pint[bank]->invert_clear = pintbit;
565 else
566 pint[bank]->invert_set = pintbit;
567 }
568 pint[bank]->request = pintbit;
552 569
553 pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val);
554 SSYNC(); 570 SSYNC();
555} 571}
556 572
@@ -560,6 +576,13 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
560 u32 pintbit = PINT_BIT(pint_val); 576 u32 pintbit = PINT_BIT(pint_val);
561 u8 bank = PINT_2_BANK(pint_val); 577 u8 bank = PINT_2_BANK(pint_val);
562 578
579 if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) {
580 if (pint[bank]->invert_set & pintbit)
581 pint[bank]->invert_clear = pintbit;
582 else
583 pint[bank]->invert_set = pintbit;
584 }
585
563 pint[bank]->request = pintbit; 586 pint[bank]->request = pintbit;
564 pint[bank]->mask_clear = pintbit; 587 pint[bank]->mask_clear = pintbit;
565 SSYNC(); 588 SSYNC();
@@ -587,7 +610,8 @@ static void bfin_gpio_unmask_irq(unsigned int irq)
587static unsigned int bfin_gpio_irq_startup(unsigned int irq) 610static unsigned int bfin_gpio_irq_startup(unsigned int irq)
588{ 611{
589 unsigned int ret; 612 unsigned int ret;
590 u16 gpionr = irq - IRQ_PA0; 613 char buf[8];
614 u16 gpionr = irq_to_gpio(irq);
591 u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; 615 u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
592 616
593 if (pint_val == IRQ_NOT_AVAIL) { 617 if (pint_val == IRQ_NOT_AVAIL) {
@@ -598,7 +622,8 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
598 } 622 }
599 623
600 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 624 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
601 ret = gpio_request(gpionr, "IRQ"); 625 snprintf(buf, sizeof buf, "IRQ %d", irq);
626 ret = gpio_request(gpionr, buf);
602 if (ret) 627 if (ret)
603 return ret; 628 return ret;
604 } 629 }
@@ -611,16 +636,19 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
611 636
612static void bfin_gpio_irq_shutdown(unsigned int irq) 637static void bfin_gpio_irq_shutdown(unsigned int irq)
613{ 638{
639 u16 gpionr = irq_to_gpio(irq);
640
614 bfin_gpio_mask_irq(irq); 641 bfin_gpio_mask_irq(irq);
615 gpio_free(irq - IRQ_PA0); 642 gpio_free(gpionr);
616 gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0); 643 gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
617} 644}
618 645
619static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) 646static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
620{ 647{
621 648
622 unsigned int ret; 649 unsigned int ret;
623 u16 gpionr = irq - IRQ_PA0; 650 char buf[8];
651 u16 gpionr = irq_to_gpio(irq);
624 u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; 652 u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
625 u32 pintbit = PINT_BIT(pint_val); 653 u32 pintbit = PINT_BIT(pint_val);
626 u8 bank = PINT_2_BANK(pint_val); 654 u8 bank = PINT_2_BANK(pint_val);
@@ -638,7 +666,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
638 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | 666 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
639 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 667 IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
640 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { 668 if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
641 ret = gpio_request(gpionr, "IRQ"); 669 snprintf(buf, sizeof buf, "IRQ %d", irq);
670 ret = gpio_request(gpionr, buf);
642 if (ret) 671 if (ret)
643 return ret; 672 return ret;
644 } 673 }
@@ -651,28 +680,33 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
651 680
652 gpio_direction_input(gpionr); 681 gpio_direction_input(gpionr);
653 682
654 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
655 pint[bank]->edge_set = pintbit;
656 } else {
657 pint[bank]->edge_clear = pintbit;
658 }
659
660 if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) 683 if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
661 pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ 684 pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
662 else 685 else
663 pint[bank]->invert_set = pintbit; /* high or rising edge denoted by zero */ 686 pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */
664 687
665 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) 688 if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
666 pint[bank]->invert_set = pintbit; 689 == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
667 else
668 pint[bank]->invert_set = pintbit;
669 690
670 SSYNC(); 691 gpio_both_edge_triggered[bank] |= pintbit;
671 692
672 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) 693 if (gpio_get_value(gpionr))
694 pint[bank]->invert_set = pintbit;
695 else
696 pint[bank]->invert_clear = pintbit;
697 } else {
698 gpio_both_edge_triggered[bank] &= ~pintbit;
699 }
700
701 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
702 pint[bank]->edge_set = pintbit;
673 set_irq_handler(irq, handle_edge_irq); 703 set_irq_handler(irq, handle_edge_irq);
674 else 704 } else {
705 pint[bank]->edge_clear = pintbit;
675 set_irq_handler(irq, handle_level_irq); 706 set_irq_handler(irq, handle_level_irq);
707 }
708
709 SSYNC();
676 710
677 return 0; 711 return 0;
678} 712}
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
index b22959b197e5..606ded9ff4e1 100644
--- a/arch/blackfin/mach-common/irqpanic.c
+++ b/arch/blackfin/mach-common/irqpanic.c
@@ -46,9 +46,6 @@ void irq_panic(int reason, struct pt_regs *regs) __attribute__ ((l1_text));
46 */ 46 */
47asmlinkage void irq_panic(int reason, struct pt_regs *regs) 47asmlinkage void irq_panic(int reason, struct pt_regs *regs)
48{ 48{
49 int sig = 0;
50 siginfo_t info;
51
52#ifdef CONFIG_DEBUG_ICACHE_CHECK 49#ifdef CONFIG_DEBUG_ICACHE_CHECK
53 unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa; 50 unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
54 unsigned short i, j, die; 51 unsigned short i, j, die;
@@ -136,53 +133,6 @@ asmlinkage void irq_panic(int reason, struct pt_regs *regs)
136 } 133 }
137#endif 134#endif
138 135
139 printk(KERN_EMERG "\n");
140 printk(KERN_EMERG "Exception: IRQ 0x%x entered\n", reason);
141 printk(KERN_EMERG " code=[0x%08lx], stack frame=0x%08lx, "
142 " bad PC=0x%08lx\n",
143 (unsigned long)regs->seqstat,
144 (unsigned long)regs,
145 (unsigned long)regs->pc);
146 if (reason == 0x5) {
147 printk(KERN_EMERG "----------- HARDWARE ERROR -----------\n");
148
149 /* There is only need to check for Hardware Errors, since other
150 * EXCEPTIONS are handled in TRAPS.c (MH)
151 */
152 switch (regs->seqstat & SEQSTAT_HWERRCAUSE) {
153 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): /* System MMR Error */
154 info.si_code = BUS_ADRALN;
155 sig = SIGBUS;
156 printk(KERN_EMERG HWC_x2(KERN_EMERG));
157 break;
158 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): /* External Memory Addressing Error */
159 info.si_code = BUS_ADRERR;
160 sig = SIGBUS;
161 printk(KERN_EMERG HWC_x3(KERN_EMERG));
162 break;
163 case (SEQSTAT_HWERRCAUSE_PERF_FLOW): /* Performance Monitor Overflow */
164 printk(KERN_EMERG HWC_x12(KERN_EMERG));
165 break;
166 case (SEQSTAT_HWERRCAUSE_RAISE_5): /* RAISE 5 instruction */
167 printk(KERN_EMERG HWC_x18(KERN_EMERG));
168 break;
169 default: /* Reserved */
170 printk(KERN_EMERG HWC_default(KERN_EMERG));
171 break;
172 }
173 }
174
175 regs->ipend = bfin_read_IPEND();
176 dump_bfin_process(regs);
177 dump_bfin_mem((void *)regs->pc);
178 show_regs(regs);
179 if (0 == (info.si_signo = sig) || 0 == user_mode(regs)) /* in kernelspace */
180 panic("Unhandled IRQ or exceptions!\n");
181 else { /* in userspace */
182 info.si_errno = 0;
183 info.si_addr = (void *)regs->pc;
184 force_sig_info(sig, &info, current);
185 }
186} 136}
187 137
188#ifdef CONFIG_HARDWARE_PM 138#ifdef CONFIG_HARDWARE_PM
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index dac51fb06f22..81930f7d06f1 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -77,7 +77,15 @@ void bfin_pm_suspend_standby_enter(void)
77 77
78 gpio_pm_restore(); 78 gpio_pm_restore();
79 79
80#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
81 bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
82 bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
83# ifdef CONFIG_BF54x
84 bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
85# endif
86#else
80 bfin_write_SIC_IWR(IWR_ENABLE_ALL); 87 bfin_write_SIC_IWR(IWR_ENABLE_ALL);
88#endif
81 89
82 local_irq_restore(flags); 90 local_irq_restore(flags);
83 } 91 }
@@ -85,7 +93,15 @@ void bfin_pm_suspend_standby_enter(void)
85 93
86#if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR) 94#if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR)
87 sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR); 95 sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR);
96# if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
97 bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
98 bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
99# ifdef CONFIG_BF54x
100 bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
101# endif
102# else
88 bfin_write_SIC_IWR(IWR_ENABLE_ALL); 103 bfin_write_SIC_IWR(IWR_ENABLE_ALL);
104# endif
89#endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */ 105#endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */
90} 106}
91 107