Skip to content
Snippets Groups Projects
interrupts.c 3.13 KiB
Newer Older
  • Learn to ignore specific revisions
  • Alexey Brodkin's avatar
    Alexey Brodkin committed
    /*
     * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <asm/arcregs.h>
    #include <asm/ptrace.h>
    
    /* Bit values in STATUS32 */
    #define E1_MASK		(1 << 1)	/* Level 1 interrupts enable */
    #define E2_MASK		(1 << 2)	/* Level 2 interrupts enable */
    
    int interrupt_init(void)
    {
    	return 0;
    }
    
    /*
     * returns true if interrupts had been enabled before we disabled them
     */
    int disable_interrupts(void)
    {
    	int status = read_aux_reg(ARC_AUX_STATUS32);
    
    	int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0;
    
    Alexey Brodkin's avatar
    Alexey Brodkin committed
    
    	status &= ~(E1_MASK | E2_MASK);
    	/* STATUS32 register is updated indirectly with "FLAG" instruction */
    	__asm__("flag %0" : : "r" (status));
    	return state;
    }
    
    void enable_interrupts(void)
    {
    	unsigned int status = read_aux_reg(ARC_AUX_STATUS32);
    
    	status |= E1_MASK | E2_MASK;
    	/* STATUS32 register is updated indirectly with "FLAG" instruction */
    	__asm__("flag %0" : : "r" (status));
    }
    
    static void print_reg_file(long *reg_rev, int start_num)
    {
    	unsigned int i;
    
    	/* Print 3 registers per line */
    	for (i = start_num; i < start_num + 25; i++) {
    		printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev);
    		if (((i + 1) % 3) == 0)
    			printf("\n");
    
    		/* Because pt_regs has registers reversed */
    		reg_rev--;
    	}
    
    	/* Add new-line if none was inserted in the end of loop above */
    	if (((i + 1) % 3) != 0)
    		printf("\n");
    }
    
    void show_regs(struct pt_regs *regs)
    {
    
    	printf("ECR:\t0x%08lx\n", regs->ecr);
    
    Alexey Brodkin's avatar
    Alexey Brodkin committed
    	printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n",
    	       regs->ret, regs->blink, regs->status32);
    	printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25);
    	printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta,
    	       regs->sp, regs->fp);
    	printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start,
    	       regs->lp_end, regs->lp_count);
    
    	print_reg_file(&(regs->r0), 0);
    }
    
    void bad_mode(struct pt_regs *regs)
    {
    	if (regs)
    		show_regs(regs);
    
    	panic("Resetting CPU ...\n");
    }
    
    void do_memory_error(unsigned long address, struct pt_regs *regs)
    {
    	printf("Memory error exception @ 0x%lx\n", address);
    	bad_mode(regs);
    }
    
    void do_instruction_error(unsigned long address, struct pt_regs *regs)
    {
    	printf("Instruction error exception @ 0x%lx\n", address);
    	bad_mode(regs);
    }
    
    void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
    {
    	printf("Machine check exception @ 0x%lx\n", address);
    	bad_mode(regs);
    }
    
    void do_interrupt_handler(void)
    {
    	printf("Interrupt fired\n");
    	bad_mode(0);
    }
    
    void do_itlb_miss(struct pt_regs *regs)
    {
    	printf("I TLB miss exception\n");
    	bad_mode(regs);
    }
    
    void do_dtlb_miss(struct pt_regs *regs)
    {
    	printf("D TLB miss exception\n");
    	bad_mode(regs);
    }
    
    void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs)
    {
    	printf("TLB protection violation or misaligned access @ 0x%lx\n",
    	       address);
    	bad_mode(regs);
    }
    
    void do_privilege_violation(struct pt_regs *regs)
    {
    	printf("Privilege violation exception\n");
    	bad_mode(regs);
    }
    
    void do_trap(struct pt_regs *regs)
    {
    	printf("Trap exception\n");
    	bad_mode(regs);
    }
    
    void do_extension(struct pt_regs *regs)
    {
    	printf("Extension instruction exception\n");
    	bad_mode(regs);
    }