| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 1 | /* | 
| Robin Getz | 96f1050 | 2009-09-24 14:11:24 +0000 | [diff] [blame] | 2 |  * panic kernel with dump information | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 3 |  * | 
| Robin Getz | 96f1050 | 2009-09-24 14:11:24 +0000 | [diff] [blame] | 4 |  * Copyright 2005-2009 Analog Devices Inc. | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 5 |  * | 
| Robin Getz | 96f1050 | 2009-09-24 14:11:24 +0000 | [diff] [blame] | 6 |  * Licensed under the GPL-2 or later. | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 7 |  */ | 
 | 8 |  | 
 | 9 | #include <linux/module.h> | 
 | 10 | #include <linux/kernel_stat.h> | 
 | 11 | #include <linux/sched.h> | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 12 | #include <asm/blackfin.h> | 
 | 13 |  | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 14 | #define L1_ICACHE_START 0xffa10000 | 
 | 15 | #define L1_ICACHE_END   0xffa13fff | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 16 |  | 
 | 17 | /* | 
 | 18 |  * irq_panic - calls panic with string setup | 
 | 19 |  */ | 
| Mike Frysinger | cf8d943 | 2009-06-13 10:14:24 -0400 | [diff] [blame] | 20 | __attribute__ ((l1_text)) | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 21 | asmlinkage void irq_panic(int reason, struct pt_regs *regs) | 
 | 22 | { | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 23 | 	unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa; | 
 | 24 | 	unsigned short i, j, die; | 
 | 25 | 	unsigned int bad[10][6]; | 
 | 26 |  | 
 | 27 | 	/* check entire cache for coherency | 
 | 28 | 	 * Since printk is in cacheable memory, | 
 | 29 | 	 * don't call it until you have checked everything | 
 | 30 | 	*/ | 
 | 31 |  | 
 | 32 | 	die = 0; | 
 | 33 | 	i = 0; | 
 | 34 |  | 
 | 35 | 	/* check icache */ | 
 | 36 |  | 
 | 37 | 	for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) { | 
 | 38 |  | 
 | 39 | 		/* Grab various address bits for the itest_cmd fields                      */ | 
 | 40 | 		cmd = (((ca & 0x3000) << 4) |	/* ca[13:12] for SBNK[1:0]             */ | 
 | 41 | 		       ((ca & 0x0c00) << 16) |	/* ca[11:10] for WAYSEL[1:0]           */ | 
 | 42 | 		       ((ca & 0x3f8)) |	/* ca[09:03] for SET[4:0] and DW[1:0]  */ | 
 | 43 | 		       0);	/* Access Tag, Read access             */ | 
 | 44 |  | 
 | 45 | 		SSYNC(); | 
 | 46 | 		bfin_write_ITEST_COMMAND(cmd); | 
 | 47 | 		SSYNC(); | 
 | 48 | 		tag = bfin_read_ITEST_DATA0(); | 
 | 49 | 		SSYNC(); | 
 | 50 |  | 
 | 51 | 		/* if tag is marked as valid, check it */ | 
 | 52 | 		if (tag & 1) { | 
 | 53 | 			/* The icache is arranged in 4 groups of 64-bits */ | 
 | 54 | 			for (j = 0; j < 32; j += 8) { | 
 | 55 | 				cmd = ((((ca + j) & 0x3000) << 4) |	/* ca[13:12] for SBNK[1:0]             */ | 
 | 56 | 				       (((ca + j) & 0x0c00) << 16) |	/* ca[11:10] for WAYSEL[1:0]           */ | 
 | 57 | 				       (((ca + j) & 0x3f8)) |	/* ca[09:03] for SET[4:0] and DW[1:0]  */ | 
 | 58 | 				       4);	/* Access Data, Read access             */ | 
 | 59 |  | 
 | 60 | 				SSYNC(); | 
 | 61 | 				bfin_write_ITEST_COMMAND(cmd); | 
 | 62 | 				SSYNC(); | 
 | 63 |  | 
 | 64 | 				cache_hi = bfin_read_ITEST_DATA1(); | 
 | 65 | 				cache_lo = bfin_read_ITEST_DATA0(); | 
 | 66 |  | 
 | 67 | 				pa = ((unsigned int *)((tag & 0xffffcc00) | | 
 | 68 | 						       ((ca + j) & ~(0xffffcc00)))); | 
 | 69 |  | 
 | 70 | 				/* | 
 | 71 | 				 * Debugging this, enable | 
 | 72 | 				 * | 
 | 73 | 				 * printk("addr: %08x %08x%08x | %08x%08x\n", | 
 | 74 | 				 *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))), | 
 | 75 | 				 *   cache_hi, cache_lo, *(pa+1), *pa); | 
 | 76 | 				 */ | 
 | 77 |  | 
 | 78 | 				if (cache_hi != *(pa + 1) || cache_lo != *pa) { | 
 | 79 | 					/* Since icache is not working, stay out of it, by not printing */ | 
 | 80 | 					die = 1; | 
 | 81 | 					bad[i][0] = (ca + j); | 
 | 82 | 					bad[i][1] = cache_hi; | 
 | 83 | 					bad[i][2] = cache_lo; | 
 | 84 | 					bad[i][3] = ((tag & 0xffffcc00) | | 
 | 85 | 					     	((ca + j) & ~(0xffffcc00))); | 
 | 86 | 					bad[i][4] = *(pa + 1); | 
 | 87 | 					bad[i][5] = *(pa); | 
 | 88 | 					i++; | 
 | 89 | 				} | 
 | 90 | 			} | 
 | 91 | 		} | 
 | 92 | 	} | 
 | 93 | 	if (die) { | 
 | 94 | 		printk(KERN_EMERG "icache coherency error\n"); | 
 | 95 | 		for (j = 0; j <= i; j++) { | 
 | 96 | 			printk(KERN_EMERG | 
 | 97 | 			    "cache address   : %08x  cache value : %08x%08x\n", | 
 | 98 | 			     bad[j][0], bad[j][1], bad[j][2]); | 
 | 99 | 			printk(KERN_EMERG | 
 | 100 | 			    "physical address: %08x  SDRAM value : %08x%08x\n", | 
 | 101 | 			     bad[j][3], bad[j][4], bad[j][5]); | 
 | 102 | 		} | 
 | 103 | 		panic("icache coherency error"); | 
| Mike Frysinger | cf8d943 | 2009-06-13 10:14:24 -0400 | [diff] [blame] | 104 | 	} else | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 105 | 		printk(KERN_EMERG "icache checked, and OK\n"); | 
| Bryan Wu | 1394f03 | 2007-05-06 14:50:22 -0700 | [diff] [blame] | 106 | } |