linux/arch/blackfin/mach-common/irqpanic.c
<<
>>
Prefs
   1/*
   2 * File:         arch/blackfin/mach-common/irqpanic.c
   3 * Based on:
   4 * Author:
   5 *
   6 * Created:      ?
   7 * Description:  panic kernel with dump information
   8 *
   9 * Modified:     rgetz - added cache checking code 14Feb06
  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_stat.h>
  32#include <linux/sched.h>
  33#include <asm/traps.h>
  34#include <asm/blackfin.h>
  35
  36#include "../oprofile/op_blackfin.h"
  37
  38#ifdef CONFIG_DEBUG_ICACHE_CHECK
  39#define L1_ICACHE_START 0xffa10000
  40#define L1_ICACHE_END   0xffa13fff
  41void irq_panic(int reason, struct pt_regs *regs) __attribute__ ((l1_text));
  42#endif
  43
  44/*
  45 * irq_panic - calls panic with string setup
  46 */
  47asmlinkage void irq_panic(int reason, struct pt_regs *regs)
  48{
  49#ifdef CONFIG_DEBUG_ICACHE_CHECK
  50        unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
  51        unsigned short i, j, die;
  52        unsigned int bad[10][6];
  53
  54        /* check entire cache for coherency
  55         * Since printk is in cacheable memory,
  56         * don't call it until you have checked everything
  57        */
  58
  59        die = 0;
  60        i = 0;
  61
  62        /* check icache */
  63
  64        for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) {
  65
  66                /* Grab various address bits for the itest_cmd fields                      */
  67                cmd = (((ca & 0x3000) << 4) |   /* ca[13:12] for SBNK[1:0]             */
  68                       ((ca & 0x0c00) << 16) |  /* ca[11:10] for WAYSEL[1:0]           */
  69                       ((ca & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0]  */
  70                       0);      /* Access Tag, Read access             */
  71
  72                SSYNC();
  73                bfin_write_ITEST_COMMAND(cmd);
  74                SSYNC();
  75                tag = bfin_read_ITEST_DATA0();
  76                SSYNC();
  77
  78                /* if tag is marked as valid, check it */
  79                if (tag & 1) {
  80                        /* The icache is arranged in 4 groups of 64-bits */
  81                        for (j = 0; j < 32; j += 8) {
  82                                cmd = ((((ca + j) & 0x3000) << 4) |     /* ca[13:12] for SBNK[1:0]             */
  83                                       (((ca + j) & 0x0c00) << 16) |    /* ca[11:10] for WAYSEL[1:0]           */
  84                                       (((ca + j) & 0x3f8)) |   /* ca[09:03] for SET[4:0] and DW[1:0]  */
  85                                       4);      /* Access Data, Read access             */
  86
  87                                SSYNC();
  88                                bfin_write_ITEST_COMMAND(cmd);
  89                                SSYNC();
  90
  91                                cache_hi = bfin_read_ITEST_DATA1();
  92                                cache_lo = bfin_read_ITEST_DATA0();
  93
  94                                pa = ((unsigned int *)((tag & 0xffffcc00) |
  95                                                       ((ca + j) & ~(0xffffcc00))));
  96
  97                                /*
  98                                 * Debugging this, enable
  99                                 *
 100                                 * printk("addr: %08x %08x%08x | %08x%08x\n",
 101                                 *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))),
 102                                 *   cache_hi, cache_lo, *(pa+1), *pa);
 103                                 */
 104
 105                                if (cache_hi != *(pa + 1) || cache_lo != *pa) {
 106                                        /* Since icache is not working, stay out of it, by not printing */
 107                                        die = 1;
 108                                        bad[i][0] = (ca + j);
 109                                        bad[i][1] = cache_hi;
 110                                        bad[i][2] = cache_lo;
 111                                        bad[i][3] = ((tag & 0xffffcc00) |
 112                                                ((ca + j) & ~(0xffffcc00)));
 113                                        bad[i][4] = *(pa + 1);
 114                                        bad[i][5] = *(pa);
 115                                        i++;
 116                                }
 117                        }
 118                }
 119        }
 120        if (die) {
 121                printk(KERN_EMERG "icache coherency error\n");
 122                for (j = 0; j <= i; j++) {
 123                        printk(KERN_EMERG
 124                            "cache address   : %08x  cache value : %08x%08x\n",
 125                             bad[j][0], bad[j][1], bad[j][2]);
 126                        printk(KERN_EMERG
 127                            "physical address: %08x  SDRAM value : %08x%08x\n",
 128                             bad[j][3], bad[j][4], bad[j][5]);
 129                }
 130                panic("icache coherency error");
 131        } else {
 132                printk(KERN_EMERG "icache checked, and OK\n");
 133        }
 134#endif
 135
 136}
 137
 138#ifdef CONFIG_HARDWARE_PM
 139/*
 140 * call the handler of Performance overflow
 141 */
 142asmlinkage void pm_overflow(int irq, struct pt_regs *regs)
 143{
 144        pm_overflow_handler(irq, regs);
 145}
 146#endif
 147