Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at c9a28fa7b9ac19b676deefa0a171ce7df8755c08 121 lines 3.8 kB view raw
1/* 2 * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM 3 * on Midas lab RTE-CB series of evaluation boards 4 * 5 * Copyright (C) 2001,02,03 NEC Electronics Corporation 6 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> 7 * 8 * This file is subject to the terms and conditions of the GNU General 9 * Public License. See the file COPYING in the main directory of this 10 * archive for more details. 11 * 12 * Written by Miles Bader <miles@gnu.org> 13 */ 14 15#include <linux/init.h> 16 17#include <asm/machdep.h> 18 19#define IRQ_ADDR(irq) (0x80 + (irq) * 0x10) 20 21/* A table of which interrupt vectors to install, since blindly 22 installing all of them makes the debugger stop working. This is a 23 list of offsets in the interrupt vector area; each entry means to 24 copy that particular 16-byte vector. An entry less than zero ends 25 the table. */ 26static long multi_intv_install_table[] = { 27 /* Trap vectors */ 28 0x40, 0x50, 29 30#ifdef CONFIG_RTE_CB_MULTI_DBTRAP 31 /* Illegal insn / dbtrap. These are used by multi, so only handle 32 them if configured to do so. */ 33 0x60, 34#endif 35 36 /* GINT1 - GINT3 (note, not GINT0!) */ 37 IRQ_ADDR (IRQ_GINT(1)), 38 IRQ_ADDR (IRQ_GINT(2)), 39 IRQ_ADDR (IRQ_GINT(3)), 40 41 /* Timer D interrupts (up to 4 timers) */ 42 IRQ_ADDR (IRQ_INTCMD(0)), 43#if IRQ_INTCMD_NUM > 1 44 IRQ_ADDR (IRQ_INTCMD(1)), 45#if IRQ_INTCMD_NUM > 2 46 IRQ_ADDR (IRQ_INTCMD(2)), 47#if IRQ_INTCMD_NUM > 3 48 IRQ_ADDR (IRQ_INTCMD(3)), 49#endif 50#endif 51#endif 52 53 /* UART interrupts (up to 3 channels) */ 54 IRQ_ADDR (IRQ_INTSER (0)), /* err */ 55 IRQ_ADDR (IRQ_INTSR (0)), /* rx */ 56 IRQ_ADDR (IRQ_INTST (0)), /* tx */ 57#if IRQ_INTSR_NUM > 1 58 IRQ_ADDR (IRQ_INTSER (1)), /* err */ 59 IRQ_ADDR (IRQ_INTSR (1)), /* rx */ 60 IRQ_ADDR (IRQ_INTST (1)), /* tx */ 61#if IRQ_INTSR_NUM > 2 62 IRQ_ADDR (IRQ_INTSER (2)), /* err */ 63 IRQ_ADDR (IRQ_INTSR (2)), /* rx */ 64 IRQ_ADDR (IRQ_INTST (2)), /* tx */ 65#endif 66#endif 67 68 -1 69}; 70 71/* Early initialization for kernel using Multi debugger ROM monitor. */ 72void __init multi_init (void) 73{ 74 /* We're using the Multi debugger monitor, so we have to install 75 the interrupt vectors. The monitor doesn't allow them to be 76 initially downloaded into their final destination because 77 it's in the monitor's scratch-RAM area. Unfortunately, Multi 78 also doesn't deal correctly with ELF sections where the LMA 79 and VMA differ -- it just ignores the LMA -- so we can't use 80 that feature to work around the problem. What we do instead 81 is just put the interrupt vectors into a normal section, and 82 do the necessary copying and relocation here. Since the 83 interrupt vector basically only contains `jr' instructions 84 and no-ops, it's not that hard. */ 85 extern unsigned long _intv_load_start, _intv_start; 86 register unsigned long *src = &_intv_load_start; 87 register unsigned long *dst = (unsigned long *)INTV_BASE; 88 register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst; 89 register long *ii; 90 91 /* Copy interrupt vectors as instructed by multi_intv_install_table. */ 92 for (ii = multi_intv_install_table; *ii >= 0; ii++) { 93 /* Copy 16-byte interrupt vector at offset *ii. */ 94 int boffs; 95 for (boffs = 0; boffs < 0x10; boffs += sizeof *src) { 96 /* Copy a single word, fixing up the jump offs 97 if it's a `jr' instruction. */ 98 int woffs = (*ii + boffs) / sizeof *src; 99 unsigned long word = src[woffs]; 100 101 if ((word & 0xFC0) == 0x780) { 102 /* A `jr' insn, fix up its offset (and yes, the 103 weird half-word swapping is intentional). */ 104 unsigned short hi = word & 0xFFFF; 105 unsigned short lo = word >> 16; 106 unsigned long udisp22 107 = lo + ((hi & 0x3F) << 16); 108 long disp22 = (long)(udisp22 << 10) >> 10; 109 110 disp22 += jr_fixup; 111 112 hi = ((disp22 >> 16) & 0x3F) | 0x780; 113 lo = disp22 & 0xFFFF; 114 115 word = hi + (lo << 16); 116 } 117 118 dst[woffs] = word; 119 } 120 } 121}