xref: /openbmc/u-boot/arch/mips/lib/traps.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
26c593630SDaniel Schwierzeck /*
36c593630SDaniel Schwierzeck  * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle
46c593630SDaniel Schwierzeck  * Copyright (C) 1995, 1996 Paul M. Antoine
56c593630SDaniel Schwierzeck  * Copyright (C) 1998 Ulf Carlsson
66c593630SDaniel Schwierzeck  * Copyright (C) 1999 Silicon Graphics, Inc.
76c593630SDaniel Schwierzeck  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
86c593630SDaniel Schwierzeck  * Copyright (C) 2002, 2003, 2004, 2005, 2007  Maciej W. Rozycki
96c593630SDaniel Schwierzeck  * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
106c593630SDaniel Schwierzeck  * Copyright (C) 2014, Imagination Technologies Ltd.
116c593630SDaniel Schwierzeck  */
126c593630SDaniel Schwierzeck 
136c593630SDaniel Schwierzeck #include <common.h>
146c593630SDaniel Schwierzeck #include <asm/mipsregs.h>
156c593630SDaniel Schwierzeck #include <asm/addrspace.h>
166c593630SDaniel Schwierzeck #include <asm/system.h>
176c593630SDaniel Schwierzeck 
186c593630SDaniel Schwierzeck DECLARE_GLOBAL_DATA_PTR;
196c593630SDaniel Schwierzeck 
show_regs(const struct pt_regs * regs)206c593630SDaniel Schwierzeck static void show_regs(const struct pt_regs *regs)
216c593630SDaniel Schwierzeck {
226c593630SDaniel Schwierzeck 	const int field = 2 * sizeof(unsigned long);
236c593630SDaniel Schwierzeck 	unsigned int cause = regs->cp0_cause;
246c593630SDaniel Schwierzeck 	unsigned int exccode;
256c593630SDaniel Schwierzeck 	int i;
266c593630SDaniel Schwierzeck 
276c593630SDaniel Schwierzeck 	/*
286c593630SDaniel Schwierzeck 	 * Saved main processor registers
296c593630SDaniel Schwierzeck 	 */
306c593630SDaniel Schwierzeck 	for (i = 0; i < 32; ) {
316c593630SDaniel Schwierzeck 		if ((i % 4) == 0)
326c593630SDaniel Schwierzeck 			printf("$%2d   :", i);
336c593630SDaniel Schwierzeck 		if (i == 0)
346c593630SDaniel Schwierzeck 			printf(" %0*lx", field, 0UL);
356c593630SDaniel Schwierzeck 		else if (i == 26 || i == 27)
366c593630SDaniel Schwierzeck 			printf(" %*s", field, "");
376c593630SDaniel Schwierzeck 		else
386c593630SDaniel Schwierzeck 			printf(" %0*lx", field, regs->regs[i]);
396c593630SDaniel Schwierzeck 
406c593630SDaniel Schwierzeck 		i++;
416c593630SDaniel Schwierzeck 		if ((i % 4) == 0)
426c593630SDaniel Schwierzeck 			puts("\n");
436c593630SDaniel Schwierzeck 	}
446c593630SDaniel Schwierzeck 
456c593630SDaniel Schwierzeck 	printf("Hi    : %0*lx\n", field, regs->hi);
466c593630SDaniel Schwierzeck 	printf("Lo    : %0*lx\n", field, regs->lo);
476c593630SDaniel Schwierzeck 
486c593630SDaniel Schwierzeck 	/*
496c593630SDaniel Schwierzeck 	 * Saved cp0 registers
506c593630SDaniel Schwierzeck 	 */
516c593630SDaniel Schwierzeck 	printf("epc   : %0*lx (text %0*lx)\n", field, regs->cp0_epc,
526c593630SDaniel Schwierzeck 	       field, regs->cp0_epc - gd->reloc_off);
536c593630SDaniel Schwierzeck 	printf("ra    : %0*lx (text %0*lx)\n", field, regs->regs[31],
546c593630SDaniel Schwierzeck 	       field, regs->regs[31] - gd->reloc_off);
556c593630SDaniel Schwierzeck 
566c593630SDaniel Schwierzeck 	printf("Status: %08x\n", (uint32_t) regs->cp0_status);
576c593630SDaniel Schwierzeck 
586c593630SDaniel Schwierzeck 	exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
596c593630SDaniel Schwierzeck 	printf("Cause : %08x (ExcCode %02x)\n", cause, exccode);
606c593630SDaniel Schwierzeck 
616c593630SDaniel Schwierzeck 	if (1 <= exccode && exccode <= 5)
626c593630SDaniel Schwierzeck 		printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
636c593630SDaniel Schwierzeck 
646c593630SDaniel Schwierzeck 	printf("PrId  : %08x\n", read_c0_prid());
656c593630SDaniel Schwierzeck }
666c593630SDaniel Schwierzeck 
do_reserved(const struct pt_regs * regs)676c593630SDaniel Schwierzeck void do_reserved(const struct pt_regs *regs)
686c593630SDaniel Schwierzeck {
696c593630SDaniel Schwierzeck 	puts("\nOoops:\n");
706c593630SDaniel Schwierzeck 	show_regs(regs);
716c593630SDaniel Schwierzeck 	hang();
726c593630SDaniel Schwierzeck }
736c593630SDaniel Schwierzeck 
do_ejtag_debug(const struct pt_regs * regs)746c593630SDaniel Schwierzeck void do_ejtag_debug(const struct pt_regs *regs)
756c593630SDaniel Schwierzeck {
766c593630SDaniel Schwierzeck 	const int field = 2 * sizeof(unsigned long);
776c593630SDaniel Schwierzeck 	unsigned long depc;
786c593630SDaniel Schwierzeck 	unsigned int debug;
796c593630SDaniel Schwierzeck 
806c593630SDaniel Schwierzeck 	depc = read_c0_depc();
816c593630SDaniel Schwierzeck 	debug = read_c0_debug();
826c593630SDaniel Schwierzeck 
836c593630SDaniel Schwierzeck 	printf("SDBBP EJTAG debug exception: c0_depc = %0*lx, DEBUG = %08x\n",
846c593630SDaniel Schwierzeck 	       field, depc, debug);
856c593630SDaniel Schwierzeck }
866c593630SDaniel Schwierzeck 
set_handler(unsigned long offset,void * addr,unsigned long size)876c593630SDaniel Schwierzeck static void set_handler(unsigned long offset, void *addr, unsigned long size)
886c593630SDaniel Schwierzeck {
896c593630SDaniel Schwierzeck 	unsigned long ebase = gd->irq_sp;
906c593630SDaniel Schwierzeck 
916c593630SDaniel Schwierzeck 	memcpy((void *)(ebase + offset), addr, size);
926c593630SDaniel Schwierzeck 	flush_cache(ebase + offset, size);
936c593630SDaniel Schwierzeck }
946c593630SDaniel Schwierzeck 
trap_init(ulong reloc_addr)956c593630SDaniel Schwierzeck void trap_init(ulong reloc_addr)
966c593630SDaniel Schwierzeck {
976c593630SDaniel Schwierzeck 	unsigned long ebase = gd->irq_sp;
986c593630SDaniel Schwierzeck 
996c593630SDaniel Schwierzeck 	set_handler(0x180, &except_vec3_generic, 0x80);
1006c593630SDaniel Schwierzeck 	set_handler(0x280, &except_vec_ejtag_debug, 0x80);
1016c593630SDaniel Schwierzeck 
1026c593630SDaniel Schwierzeck 	write_c0_ebase(ebase);
1036c593630SDaniel Schwierzeck 	clear_c0_status(ST0_BEV);
1046c593630SDaniel Schwierzeck 	execution_hazard_barrier();
1056c593630SDaniel Schwierzeck }
106