mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 00:11:51 +01:00 
			
		
		
		
	Merge branch 'master' of git://git.denx.de/u-boot-blackfin
This commit is contained in:
		
						commit
						0d131ad9be
					
				| @ -8,6 +8,9 @@ | |||||||
| #include <config.h> | #include <config.h> | ||||||
| #include <asm/blackfin.h> | #include <asm/blackfin.h> | ||||||
| #include <asm/entry.h> | #include <asm/entry.h> | ||||||
|  | #include <asm/ptrace.h> | ||||||
|  | #include <asm/deferred.h> | ||||||
|  | #include <asm/mach-common/bits/core.h> | ||||||
| 
 | 
 | ||||||
| .text | .text | ||||||
| 
 | 
 | ||||||
| @ -19,10 +22,75 @@ ENTRY(_trap) | |||||||
| 	SAVE_ALL_SYS | 	SAVE_ALL_SYS | ||||||
| 
 | 
 | ||||||
| 	r0 = sp;	/* stack frame pt_regs pointer argument ==> r0 */
 | 	r0 = sp;	/* stack frame pt_regs pointer argument ==> r0 */
 | ||||||
|  | 	r1 = 3;		/* EVT3 space */
 | ||||||
| 	sp += -12;
 | 	sp += -12;
 | ||||||
| 	call _trap_c;
 | 	call _trap_c;
 | ||||||
| 	sp += 12;
 | 	sp += 12;
 | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_EXCEPTION_DEFER | ||||||
|  | 	CC = R0 == 0;
 | ||||||
|  | 	IF CC JUMP .Lexit_trap;
 | ||||||
|  | 
 | ||||||
|  | 	/* To avoid double faults, lower our priority to IRQ5 */ | ||||||
|  | 	p4.l = lo(COREMMR_BASE);
 | ||||||
|  | 	p4.h = hi(COREMMR_BASE);
 | ||||||
|  | 
 | ||||||
|  | 	r7.h = _exception_to_level5;
 | ||||||
|  | 	r7.l = _exception_to_level5;
 | ||||||
|  | 	[p4 + (EVT5 - COREMMR_BASE)] = r7;
 | ||||||
|  | 
 | ||||||
|  | 	/* | ||||||
|  | 	 * Save these registers, as they are only valid in exception context | ||||||
|  | 	 *  (where we are now - as soon as we defer to IRQ5, they can change) | ||||||
|  | 	 */ | ||||||
|  | 	p5.l = _deferred_regs;
 | ||||||
|  | 	p5.h = _deferred_regs;
 | ||||||
|  | 	r6 = [p4 + (DCPLB_FAULT_ADDR - COREMMR_BASE)];
 | ||||||
|  | 	[p5 + (deferred_regs_DCPLB_FAULT_ADDR * 4)] = r6;
 | ||||||
|  | 
 | ||||||
|  | 	r6 = [p4 + (ICPLB_FAULT_ADDR - COREMMR_BASE)];
 | ||||||
|  | 	[p5 + (deferred_regs_ICPLB_FAULT_ADDR * 4)] = r6;
 | ||||||
|  | 
 | ||||||
|  | 	/* Save the state of single stepping */ | ||||||
|  | 	r6 = SYSCFG;
 | ||||||
|  | 	[p5 + (deferred_regs_SYSCFG * 4)] = r6;
 | ||||||
|  | 	/* Clear it while we handle the exception in IRQ5 mode | ||||||
|  | 	 * RESTORE_ALL_SYS will load it, so all we need to do is store it | ||||||
|  | 	 * in the right place | ||||||
|  | 	 */ | ||||||
|  | 	BITCLR(r6, SYSCFG_SSSTEP_P);
 | ||||||
|  | 	[SP + PT_SYSCFG] = r6;
 | ||||||
|  | 
 | ||||||
|  | 	/* Since we are going to clobber RETX, we need to save it */ | ||||||
|  | 	r6 = retx;
 | ||||||
|  | 	[p5 + (deferred_regs_retx * 4)] = r6;
 | ||||||
|  | 
 | ||||||
|  | 	/* Save the current IMASK, since we change in order to jump to level 5 */ | ||||||
|  | 	cli r6;
 | ||||||
|  | 	[p5 + (deferred_regs_IMASK * 4)] = r6;
 | ||||||
|  | 
 | ||||||
|  | 	/* Disable all interrupts, but make sure level 5 is enabled so | ||||||
|  | 	 * we can switch to that level. | ||||||
|  | 	 */ | ||||||
|  | 	r6 = 0x3f;
 | ||||||
|  | 	sti r6;
 | ||||||
|  | 
 | ||||||
|  | 	/* Clobber RETX so we don't end up back at a faulting instruction */ | ||||||
|  | 	[sp + PT_RETX] = r7;
 | ||||||
|  | 
 | ||||||
|  | 	/* In case interrupts are disabled IPEND[4] (global interrupt disable bit) | ||||||
|  | 	 * clear it (re-enabling interrupts again) by the special sequence of pushing | ||||||
|  | 	 * RETI onto the stack.  This way we can lower ourselves to IVG5 even if the | ||||||
|  | 	 * exception was taken after the interrupt handler was called but before it | ||||||
|  | 	 * got a chance to enable global interrupts itself. | ||||||
|  | 	 */ | ||||||
|  | 	[--sp] = reti;
 | ||||||
|  | 	sp += 4;
 | ||||||
|  | 
 | ||||||
|  | 	RAISE 5;
 | ||||||
|  | .Lexit_trap: | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #if ANOMALY_05000257 | #if ANOMALY_05000257 | ||||||
| 	R7  = LC0;
 | 	R7  = LC0;
 | ||||||
| 	LC0 = R7;
 | 	LC0 = R7;
 | ||||||
| @ -35,6 +103,43 @@ ENTRY(_trap) | |||||||
| 	rtx;
 | 	rtx;
 | ||||||
| ENDPROC(_trap) | ENDPROC(_trap) | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_EXCEPTION_DEFER | ||||||
|  | /* Deferred (IRQ5) exceptions */ | ||||||
|  | ENTRY(_exception_to_level5) | ||||||
|  | 	SAVE_ALL_SYS | ||||||
|  | 
 | ||||||
|  | 	/* Now we have to fix things up */ | ||||||
|  | 	p4.l = lo(EVT5);
 | ||||||
|  | 	p4.h = hi(EVT5);
 | ||||||
|  | 	r0.l = _evt_default;
 | ||||||
|  | 	r0.h = _evt_default;
 | ||||||
|  | 	[p4] = r0;
 | ||||||
|  | 	csync;
 | ||||||
|  | 
 | ||||||
|  | 	p4.l = _deferred_regs;
 | ||||||
|  | 	p4.h = _deferred_regs;
 | ||||||
|  | 	r0 = [p4 + (deferred_regs_retx * 4)];
 | ||||||
|  | 	[sp + PT_PC] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	r0 = [p4 + (deferred_regs_SYSCFG * 4)];
 | ||||||
|  | 	[sp + PT_SYSCFG] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	r0 = sp;	/* stack frame pt_regs pointer argument ==> r0 */
 | ||||||
|  | 	r1 = 5;	/* EVT5 space */
 | ||||||
|  | 	sp += -12;
 | ||||||
|  | 	call _trap_c;
 | ||||||
|  | 	sp += 12;
 | ||||||
|  | 
 | ||||||
|  | 	/* Restore IMASK */ | ||||||
|  | 	r0 = [p4 + (deferred_regs_IMASK * 4)];
 | ||||||
|  | 	sti r0;
 | ||||||
|  | 
 | ||||||
|  | 	RESTORE_ALL_SYS | ||||||
|  | 
 | ||||||
|  | 	rti;
 | ||||||
|  | ENDPROC(_exception_to_level5) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /* default entry point for interrupts */ | /* default entry point for interrupts */ | ||||||
| ENTRY(_evt_default) | ENTRY(_evt_default) | ||||||
| 	SAVE_ALL_SYS | 	SAVE_ALL_SYS | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
|  | #include <kgdb.h> | ||||||
| #include <linux/types.h> | #include <linux/types.h> | ||||||
| #include <asm/traps.h> | #include <asm/traps.h> | ||||||
| #include <asm/cplb.h> | #include <asm/cplb.h> | ||||||
| @ -25,6 +26,7 @@ | |||||||
| #include <asm/mach-common/bits/core.h> | #include <asm/mach-common/bits/core.h> | ||||||
| #include <asm/mach-common/bits/mpu.h> | #include <asm/mach-common/bits/mpu.h> | ||||||
| #include <asm/mach-common/bits/trace.h> | #include <asm/mach-common/bits/trace.h> | ||||||
|  | #include <asm/deferred.h> | ||||||
| #include "cpu.h" | #include "cpu.h" | ||||||
| 
 | 
 | ||||||
| #define trace_buffer_save(x) \ | #define trace_buffer_save(x) \ | ||||||
| @ -69,8 +71,16 @@ const struct memory_map const bfin_memory_map[] = { | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void trap_c(struct pt_regs *regs) | #ifdef CONFIG_EXCEPTION_DEFER | ||||||
|  | unsigned int deferred_regs[deferred_regs_last]; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Handle all exceptions while running in EVT3 or EVT5 | ||||||
|  |  */ | ||||||
|  | int trap_c(struct pt_regs *regs, uint32_t level) | ||||||
| { | { | ||||||
|  | 	uint32_t ret = 0; | ||||||
| 	uint32_t trapnr = (regs->seqstat & EXCAUSE); | 	uint32_t trapnr = (regs->seqstat & EXCAUSE); | ||||||
| 	bool data = false; | 	bool data = false; | ||||||
| 
 | 
 | ||||||
| @ -87,7 +97,7 @@ void trap_c(struct pt_regs *regs) | |||||||
| 			 */ | 			 */ | ||||||
| 			if (last_cplb_fault_retx != regs->retx) { | 			if (last_cplb_fault_retx != regs->retx) { | ||||||
| 				last_cplb_fault_retx = regs->retx; | 				last_cplb_fault_retx = regs->retx; | ||||||
| 				return; | 				return ret; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -102,6 +112,12 @@ void trap_c(struct pt_regs *regs) | |||||||
| 		size_t i; | 		size_t i; | ||||||
| 		unsigned long tflags; | 		unsigned long tflags; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_EXCEPTION_DEFER | ||||||
|  | 		/* This should never happen */ | ||||||
|  | 		if (level == 5) | ||||||
|  | 			bfin_panic(regs); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Keep the trace buffer so that a miss here points people | 		 * Keep the trace buffer so that a miss here points people | ||||||
| 		 * to the right place (their code).  Crashes here rarely | 		 * to the right place (their code).  Crashes here rarely | ||||||
| @ -167,11 +183,40 @@ void trap_c(struct pt_regs *regs) | |||||||
| 		trace_buffer_restore(tflags); | 		trace_buffer_restore(tflags); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | #ifdef CONFIG_CMD_KGDB | ||||||
|  | 	/* Single step
 | ||||||
|  | 	 * if we are in IRQ5, just ignore, otherwise defer, and handle it in kgdb | ||||||
|  | 	 */ | ||||||
|  | 	case VEC_STEP: | ||||||
|  | 		if (level == 3) { | ||||||
|  | 			/* If we just returned from an interrupt, the single step
 | ||||||
|  | 			 * event is for the RTI instruction. | ||||||
|  | 			 */ | ||||||
|  | 			if (regs->retx == regs->pc) | ||||||
|  | 				break; | ||||||
|  | 			/* we just return if we are single stepping through IRQ5 */ | ||||||
|  | 			if (regs->ipend & 0x20) | ||||||
|  | 				break; | ||||||
|  | 			/* Otherwise, turn single stepping off & fall through,
 | ||||||
|  | 			 * which defers to IRQ5 | ||||||
|  | 			 */ | ||||||
|  | 			regs->syscfg &= ~1; | ||||||
|  | 		} | ||||||
|  | 		/* fall through */ | ||||||
|  | #endif | ||||||
| 	default: | 	default: | ||||||
| 		/* All traps come here */ | #ifdef CONFIG_CMD_KGDB | ||||||
|  | 		if (level == 3) { | ||||||
|  | 			/* We need to handle this at EVT5, so try again */ | ||||||
|  | 			ret = 1; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (debugger_exception_handler && (*debugger_exception_handler)(regs)) | ||||||
|  | 			return 0; | ||||||
|  | #endif | ||||||
| 		bfin_panic(regs); | 		bfin_panic(regs); | ||||||
| 	} | 	} | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_DEBUG_DUMP | #ifdef CONFIG_DEBUG_DUMP | ||||||
| @ -251,8 +296,10 @@ void dump(struct pt_regs *fp) | |||||||
| 	if (!ENABLE_DUMP) | 	if (!ENABLE_DUMP) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	/* fp->ipend is garbage, so load it ourself */ | #ifndef CONFIG_CMD_KGDB | ||||||
|  | 	/* fp->ipend is normally garbage, so load it ourself */ | ||||||
| 	fp->ipend = bfin_read_IPEND(); | 	fp->ipend = bfin_read_IPEND(); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 	hwerrcause = (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P; | 	hwerrcause = (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P; | ||||||
| 	excause = (fp->seqstat & EXCAUSE) >> EXCAUSE_P; | 	excause = (fp->seqstat & EXCAUSE) >> EXCAUSE_P; | ||||||
|  | |||||||
| @ -66,6 +66,11 @@ | |||||||
| # error CONFIG_PLL_BYPASS: Invalid value: must be 0 or 1 | # error CONFIG_PLL_BYPASS: Invalid value: must be 0 or 1 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | /* If we are using KGDB, make sure we defer exceptions */ | ||||||
|  | #ifdef CONFIG_CMD_KGDB | ||||||
|  | # define CONFIG_EXCEPTION_DEFER	1 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /* Using L1 scratch pad makes sense for everyone by default. */ | /* Using L1 scratch pad makes sense for everyone by default. */ | ||||||
| #ifndef CONFIG_LINUX_CMDLINE_ADDR | #ifndef CONFIG_LINUX_CMDLINE_ADDR | ||||||
| # define CONFIG_LINUX_CMDLINE_ADDR L1_SRAM_SCRATCH | # define CONFIG_LINUX_CMDLINE_ADDR L1_SRAM_SCRATCH | ||||||
| @ -138,6 +143,8 @@ | |||||||
| #endif | #endif | ||||||
| #ifndef CONFIG_SYS_CBSIZE | #ifndef CONFIG_SYS_CBSIZE | ||||||
| # define CONFIG_SYS_CBSIZE 1024 | # define CONFIG_SYS_CBSIZE 1024 | ||||||
|  | #elif defined(CONFIG_CMD_KGDB) && CONFIG_SYS_CBSIZE < 1024 | ||||||
|  | # error "kgdb needs cbsize to be >= 1024" | ||||||
| #endif | #endif | ||||||
| #ifndef CONFIG_SYS_BARGSIZE | #ifndef CONFIG_SYS_BARGSIZE | ||||||
| # define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE | # define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								include/asm-blackfin/deferred.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/asm-blackfin/deferred.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | /*
 | ||||||
|  |  * U-boot - deferred register layout | ||||||
|  |  * | ||||||
|  |  * Copyright 2004-2009 Analog Devices Inc. | ||||||
|  |  * | ||||||
|  |  * Licensed under the GPL-2 or later. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _BLACKFIN_DEFER_H | ||||||
|  | #define _BLACKFIN_DEFER_H | ||||||
|  | 
 | ||||||
|  | #define deferred_regs_DCPLB_FAULT_ADDR	0 | ||||||
|  | #define deferred_regs_ICPLB_FAULT_ADDR	1 | ||||||
|  | #define deferred_regs_retx		2 | ||||||
|  | #define deferred_regs_SEQSTAT		3 | ||||||
|  | #define deferred_regs_SYSCFG		4 | ||||||
|  | #define deferred_regs_IMASK		5 | ||||||
|  | #define deferred_regs_last		6 | ||||||
|  | 
 | ||||||
|  | #endif /* _BLACKFIN_DEFER_H */ | ||||||
| @ -86,6 +86,11 @@ | |||||||
| 	[--sp] = RETE; | 	[--sp] = RETE; | ||||||
| 	[--sp] = SEQSTAT; | 	[--sp] = SEQSTAT; | ||||||
| 	[--sp] = SYSCFG; | 	[--sp] = SYSCFG; | ||||||
|  | #ifdef CONFIG_CMD_KGDB | ||||||
|  | 	p0.l = lo(IPEND) | ||||||
|  | 	p0.h = hi(IPEND) | ||||||
|  | 	r0 = [p0]; | ||||||
|  | #endif | ||||||
| 	[--sp] = r0;	/* Skip IPEND as well. */ | 	[--sp] = r0;	/* Skip IPEND as well. */ | ||||||
| .endm | .endm | ||||||
| 
 | 
 | ||||||
| @ -137,6 +142,11 @@ | |||||||
| 	[--sp] = RETE; | 	[--sp] = RETE; | ||||||
| 	[--sp] = SEQSTAT; | 	[--sp] = SEQSTAT; | ||||||
| 	[--sp] = SYSCFG; | 	[--sp] = SYSCFG; | ||||||
|  | #ifdef CONFIG_CMD_KGDB | ||||||
|  | 	p0.l = lo(IPEND) | ||||||
|  | 	p0.h = hi(IPEND) | ||||||
|  | 	r0 = [p0]; | ||||||
|  | #endif | ||||||
| 	[--sp] = r0;	/* Skip IPEND as well. */ | 	[--sp] = r0;	/* Skip IPEND as well. */ | ||||||
| .endm | .endm | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -105,5 +105,8 @@ | |||||||
| #define SSSTEP			0x00000001	/* Supervisor Single Step */ | #define SSSTEP			0x00000001	/* Supervisor Single Step */ | ||||||
| #define CCEN			0x00000002	/* Cycle Counter Enable */ | #define CCEN			0x00000002	/* Cycle Counter Enable */ | ||||||
| #define SNEN			0x00000004	/* Self-Nesting Interrupt Enable */ | #define SNEN			0x00000004	/* Self-Nesting Interrupt Enable */ | ||||||
|  | #define SYSCFG_SSSTEP_P	0 | ||||||
|  | #define SYSCFG_CCEN_P	1 | ||||||
|  | #define SYSCFG_SCEN_P	2 | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								include/asm-blackfin/signal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								include/asm-blackfin/signal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | #include <asm-generic/signal.h> | ||||||
							
								
								
									
										101
									
								
								include/asm-generic/signal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								include/asm-generic/signal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | |||||||
|  | #ifndef __ASM_GENERIC_SIGNAL_H | ||||||
|  | #define __ASM_GENERIC_SIGNAL_H | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | 
 | ||||||
|  | #define _NSIG		64 | ||||||
|  | #define _NSIG_BPW	BITS_PER_LONG | ||||||
|  | #define _NSIG_WORDS	(_NSIG / _NSIG_BPW) | ||||||
|  | 
 | ||||||
|  | #define SIGHUP		 1 | ||||||
|  | #define SIGINT		 2 | ||||||
|  | #define SIGQUIT		 3 | ||||||
|  | #define SIGILL		 4 | ||||||
|  | #define SIGTRAP		 5 | ||||||
|  | #define SIGABRT		 6 | ||||||
|  | #define SIGIOT		 6 | ||||||
|  | #define SIGBUS		 7 | ||||||
|  | #define SIGFPE		 8 | ||||||
|  | #define SIGKILL		 9 | ||||||
|  | #define SIGUSR1		10 | ||||||
|  | #define SIGSEGV		11 | ||||||
|  | #define SIGUSR2		12 | ||||||
|  | #define SIGPIPE		13 | ||||||
|  | #define SIGALRM		14 | ||||||
|  | #define SIGTERM		15 | ||||||
|  | #define SIGSTKFLT	16 | ||||||
|  | #define SIGCHLD		17 | ||||||
|  | #define SIGCONT		18 | ||||||
|  | #define SIGSTOP		19 | ||||||
|  | #define SIGTSTP		20 | ||||||
|  | #define SIGTTIN		21 | ||||||
|  | #define SIGTTOU		22 | ||||||
|  | #define SIGURG		23 | ||||||
|  | #define SIGXCPU		24 | ||||||
|  | #define SIGXFSZ		25 | ||||||
|  | #define SIGVTALRM	26 | ||||||
|  | #define SIGPROF		27 | ||||||
|  | #define SIGWINCH	28 | ||||||
|  | #define SIGIO		29 | ||||||
|  | #define SIGPOLL		SIGIO | ||||||
|  | /*
 | ||||||
|  | #define SIGLOST		29 | ||||||
|  | */ | ||||||
|  | #define SIGPWR		30 | ||||||
|  | #define SIGSYS		31 | ||||||
|  | #define	SIGUNUSED	31 | ||||||
|  | 
 | ||||||
|  | /* These should not be considered constants from userland.  */ | ||||||
|  | #define SIGRTMIN	32 | ||||||
|  | #ifndef SIGRTMAX | ||||||
|  | #define SIGRTMAX	_NSIG | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * SA_FLAGS values: | ||||||
|  |  * | ||||||
|  |  * SA_ONSTACK indicates that a registered stack_t will be used. | ||||||
|  |  * SA_RESTART flag to get restarting signals (which were the default long ago) | ||||||
|  |  * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. | ||||||
|  |  * SA_RESETHAND clears the handler when the signal is delivered. | ||||||
|  |  * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. | ||||||
|  |  * SA_NODEFER prevents the current signal from being masked in the handler. | ||||||
|  |  * | ||||||
|  |  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single | ||||||
|  |  * Unix names RESETHAND and NODEFER respectively. | ||||||
|  |  */ | ||||||
|  | #define SA_NOCLDSTOP	0x00000001 | ||||||
|  | #define SA_NOCLDWAIT	0x00000002 | ||||||
|  | #define SA_SIGINFO	0x00000004 | ||||||
|  | #define SA_ONSTACK	0x08000000 | ||||||
|  | #define SA_RESTART	0x10000000 | ||||||
|  | #define SA_NODEFER	0x40000000 | ||||||
|  | #define SA_RESETHAND	0x80000000 | ||||||
|  | 
 | ||||||
|  | #define SA_NOMASK	SA_NODEFER | ||||||
|  | #define SA_ONESHOT	SA_RESETHAND | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * New architectures should not define the obsolete | ||||||
|  |  *	SA_RESTORER	0x04000000 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * sigaltstack controls | ||||||
|  |  */ | ||||||
|  | #define SS_ONSTACK	1 | ||||||
|  | #define SS_DISABLE	2 | ||||||
|  | 
 | ||||||
|  | #define MINSIGSTKSZ	2048 | ||||||
|  | #define SIGSTKSZ	8192 | ||||||
|  | 
 | ||||||
|  | #ifndef __ASSEMBLY__ | ||||||
|  | typedef struct { | ||||||
|  | 	unsigned long sig[_NSIG_WORDS]; | ||||||
|  | } sigset_t; | ||||||
|  | 
 | ||||||
|  | /* not actually used, but required for linux/syscalls.h */ | ||||||
|  | 
 | ||||||
|  | #endif /* __ASSEMBLY__ */ | ||||||
|  | 
 | ||||||
|  | #endif /* _ASM_GENERIC_SIGNAL_H */ | ||||||
| @ -83,6 +83,7 @@ | |||||||
| # define CONFIG_CMD_CPLBINFO | # define CONFIG_CMD_CPLBINFO | ||||||
| # define CONFIG_CMD_ELF | # define CONFIG_CMD_ELF | ||||||
| # define CONFIG_ELF_SIMPLE_LOAD | # define CONFIG_ELF_SIMPLE_LOAD | ||||||
|  | # define CONFIG_CMD_KGDB | ||||||
| # define CONFIG_CMD_REGINFO | # define CONFIG_CMD_REGINFO | ||||||
| # define CONFIG_CMD_STRINGS | # define CONFIG_CMD_STRINGS | ||||||
| # if defined(__ADSPBF51x__) || defined(__ADSPBF52x__) || defined(__ADSPBF54x__) | # if defined(__ADSPBF51x__) || defined(__ADSPBF52x__) || defined(__ADSPBF54x__) | ||||||
|  | |||||||
| @ -37,12 +37,14 @@ SOBJS-y	+= memcpy.o | |||||||
| SOBJS-y	+= memmove.o | SOBJS-y	+= memmove.o | ||||||
| SOBJS-y	+= memset.o | SOBJS-y	+= memset.o | ||||||
| SOBJS-y	+= outs.o | SOBJS-y	+= outs.o | ||||||
|  | SOBJS-$(CONFIG_CMD_KGDB) += __kgdb.o | ||||||
| 
 | 
 | ||||||
| COBJS-y	+= board.o | COBJS-y	+= board.o | ||||||
| COBJS-y	+= boot.o | COBJS-y	+= boot.o | ||||||
| COBJS-y	+= cache.o | COBJS-y	+= cache.o | ||||||
| COBJS-y	+= clocks.o | COBJS-y	+= clocks.o | ||||||
| COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o | COBJS-$(CONFIG_CMD_CACHE_DUMP) += cmd_cache_dump.o | ||||||
|  | COBJS-$(CONFIG_CMD_KGDB) += kgdb.o | ||||||
| COBJS-y	+= muldi3.o | COBJS-y	+= muldi3.o | ||||||
| COBJS-$(CONFIG_POST) += post.o tests.o | COBJS-$(CONFIG_POST) += post.o tests.o | ||||||
| COBJS-y	+= string.o | COBJS-y	+= string.o | ||||||
|  | |||||||
							
								
								
									
										155
									
								
								lib_blackfin/__kgdb.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								lib_blackfin/__kgdb.S
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | |||||||
|  | 
 | ||||||
|  | #include <asm/linkage.h> | ||||||
|  | 
 | ||||||
|  | /* save stack context for non-local goto | ||||||
|  |  * int kgdb_setjmp(long *buf) | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | ENTRY(_kgdb_setjmp) | ||||||
|  | 	[--SP] = p0; 	/* Save P0 */
 | ||||||
|  | 	p0 = r0;
 | ||||||
|  | 	r0 = [SP++];	/* Load P0 into R0 */
 | ||||||
|  | 
 | ||||||
|  | 	[p0 + 0x00] = r0;       /* GP address registers */
 | ||||||
|  | 	[p0 + 0x04] = p1;
 | ||||||
|  | 	[p0 + 0x08] = p2;
 | ||||||
|  | 	[p0 + 0x0C] = p3;
 | ||||||
|  | 	[p0 + 0x10] = p4;
 | ||||||
|  | 	[p0 + 0x14] = p5;
 | ||||||
|  | 	[p0 + 0x18] = FP;       /* frame pointer */
 | ||||||
|  | 	[p0 + 0x1C] = SP;       /* stack pointer */
 | ||||||
|  | 
 | ||||||
|  | 	[p0 + 0x20] = p0;       /* data regs */
 | ||||||
|  | 	[p0 + 0x24] = r1;
 | ||||||
|  | 	[p0 + 0x28] = r2;
 | ||||||
|  | 	[p0 + 0x2C] = r3;
 | ||||||
|  | 	[p0 + 0x30] = r4;
 | ||||||
|  | 	[p0 + 0x34] = r5;
 | ||||||
|  | 	[p0 + 0x38] = r6;
 | ||||||
|  | 	[p0 + 0x3C] = r7;
 | ||||||
|  | 
 | ||||||
|  | 	r0 = ASTAT;	[p0 + 0x40] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* loop counters */ | ||||||
|  | 	r0 = LC0;	[p0 + 0x44] = r0;
 | ||||||
|  | 	r0 = LC1;	[p0 + 0x48] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* Accumulator */ | ||||||
|  | 	r0 = A0.w;	[p0 + 0x4C] = r0;
 | ||||||
|  | 	r0.l = A0.x;	[p0 + 0x50] = r0;
 | ||||||
|  | 	r0 = A1.w;	[p0 + 0x54] = r0;
 | ||||||
|  | 	r0.l = A1.x;	[p0 + 0x58] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* index registers */ | ||||||
|  | 	r0 = i0;	[p0 + 0x5C] = r0;
 | ||||||
|  | 	r0 = i1;	[p0 + 0x60] = r0;
 | ||||||
|  | 	r0 = i2;	[p0 + 0x64] = r0;
 | ||||||
|  | 	r0 = i3;	[p0 + 0x68] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* modifier registers */ | ||||||
|  | 	r0 = m0;	[p0 + 0x6C] = r0;
 | ||||||
|  | 	r0 = m1;	[p0 + 0x70] = r0;
 | ||||||
|  | 	r0 = m2;	[p0 + 0x74] = r0;
 | ||||||
|  | 	r0 = m3;	[p0 + 0x78] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* length registers */ | ||||||
|  | 	r0 = l0;	[p0 + 0x7C] = r0;
 | ||||||
|  | 	r0 = l1;	[p0 + 0x80] = r0;
 | ||||||
|  | 	r0 = l2;	[p0 + 0x84] = r0;
 | ||||||
|  | 	r0 = l3;	[p0 + 0x88] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* base registers */ | ||||||
|  | 	r0 = b0;	[p0 + 0x8C] = r0;
 | ||||||
|  | 	r0 = b1;	[p0 + 0x90] = r0;
 | ||||||
|  | 	r0 = b2;	[p0 + 0x94] = r0;
 | ||||||
|  | 	r0 = b3;	[p0 + 0x98] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* store return address */ | ||||||
|  | 	r0 = RETS;	[p0 + 0x9C] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	R0 = 0;
 | ||||||
|  | 	RTS;
 | ||||||
|  | ENDPROC(_kgdb_setjmp) | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * non-local jump to a saved stack context | ||||||
|  |  * longjmp(long *buf, int val) | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | ENTRY(_kgdb_longjmp) | ||||||
|  | 	p0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x00];
 | ||||||
|  | 	[--sp] = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* GP address registers - skip p0 for now*/ | ||||||
|  | 	p1 = [p0 + 0x04];
 | ||||||
|  | 	p2 = [p0 + 0x08];
 | ||||||
|  | 	p3 = [p0 + 0x0C];
 | ||||||
|  | 	p4 = [p0 + 0x10];
 | ||||||
|  | 	p5 = [p0 + 0x14];
 | ||||||
|  | 	/* frame pointer */ | ||||||
|  | 	fp = [p0 + 0x18];
 | ||||||
|  | 	/* stack pointer */ | ||||||
|  | 	r0 = [sp++];
 | ||||||
|  | 	sp = [p0 + 0x1C];
 | ||||||
|  | 	[--sp] = r0;
 | ||||||
|  | 	[--sp] = r1;
 | ||||||
|  | 
 | ||||||
|  | 	/* data regs */ | ||||||
|  | 	r0 = [p0 + 0x20];
 | ||||||
|  | 	r1 = [p0 + 0x24];
 | ||||||
|  | 	r2 = [p0 + 0x28];
 | ||||||
|  | 	r3 = [p0 + 0x2C];
 | ||||||
|  | 	r4 = [p0 + 0x30];
 | ||||||
|  | 	r5 = [p0 + 0x34];
 | ||||||
|  | 	r6 = [p0 + 0x38];
 | ||||||
|  | 	r7 = [p0 + 0x3C];
 | ||||||
|  | 
 | ||||||
|  | 	r0 = [p0 + 0x40];	ASTAT = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* loop counters */ | ||||||
|  | 	r0 = [p0 + 0x44];	LC0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x48];	LC1 = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* Accumulator */ | ||||||
|  | 	r0 = [p0 + 0x4C];	A0.w = r0;
 | ||||||
|  | 	r0 = [p0 + 0x50];	A0.x = r0;
 | ||||||
|  | 	r0 = [p0 + 0x54];	A1.w = r0;
 | ||||||
|  | 	r0 = [p0 + 0x58];	A1.x = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* index registers */ | ||||||
|  | 	r0 = [p0 + 0x5C];	i0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x60];	i1 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x64];	i2 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x68];	i3 = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* modifier registers */ | ||||||
|  | 	r0 = [p0 + 0x6C];	m0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x70];	m1 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x74];	m2 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x78];	m3 = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* length registers */ | ||||||
|  | 	r0 = [p0 + 0x7C];	l0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x80];	l1 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x84];	l2 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x88];	l3 = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* base registers */ | ||||||
|  | 	r0 = [p0 + 0x8C];	b0 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x90];	b1 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x94];	b2 = r0;
 | ||||||
|  | 	r0 = [p0 + 0x98];	b3 = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* store return address */ | ||||||
|  | 	r0 = [p0 + 0x9C];	RETS = r0;
 | ||||||
|  | 
 | ||||||
|  | 	/* fixup R0 & P0 */ | ||||||
|  | 	r0 = [sp++];
 | ||||||
|  | 	p0 = [sp++];
 | ||||||
|  | 	CC = R0 == 0;
 | ||||||
|  | 	IF !CC JUMP .Lfinished;
 | ||||||
|  | 	R0 = 1;
 | ||||||
|  | .Lfinished: | ||||||
|  | 	RTS;
 | ||||||
|  | ENDPROC(_kgdb_longjmp) | ||||||
| @ -22,6 +22,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <asm/cplb.h> | #include <asm/cplb.h> | ||||||
| #include <asm/mach-common/bits/mpu.h> | #include <asm/mach-common/bits/mpu.h> | ||||||
|  | #include <kgdb.h> | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_CMD_NAND | #ifdef CONFIG_CMD_NAND | ||||||
| #include <nand.h>	/* cannot even include nand.h if it isnt configured */ | #include <nand.h>	/* cannot even include nand.h if it isnt configured */ | ||||||
| @ -356,6 +357,11 @@ void board_init_r(gd_t * id, ulong dest_addr) | |||||||
| 	/* Initialize the console (after the relocation and devices init) */ | 	/* Initialize the console (after the relocation and devices init) */ | ||||||
| 	console_init_r(); | 	console_init_r(); | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_CMD_KGDB | ||||||
|  | 	puts("KGDB:  "); | ||||||
|  | 	kgdb_init(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef CONFIG_STATUS_LED | #ifdef CONFIG_STATUS_LED | ||||||
| 	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); | 	status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); | ||||||
| 	status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF); | 	status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF); | ||||||
|  | |||||||
							
								
								
									
										423
									
								
								lib_blackfin/kgdb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								lib_blackfin/kgdb.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,423 @@ | |||||||
|  | /*
 | ||||||
|  |  * U-boot - architecture specific kgdb code | ||||||
|  |  * | ||||||
|  |  * Copyright 2009 Analog Devices Inc. | ||||||
|  |  * | ||||||
|  |  * Licensed under the GPL-2 or later. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <command.h> | ||||||
|  | 
 | ||||||
|  | #include <kgdb.h> | ||||||
|  | #include <asm/processor.h> | ||||||
|  | #include <asm/mach-common/bits/core.h> | ||||||
|  | #include "kgdb.h" | ||||||
|  | #include <asm/deferred.h> | ||||||
|  | #include <asm/traps.h> | ||||||
|  | #include <asm/signal.h> | ||||||
|  | 
 | ||||||
|  | void kgdb_enter(struct pt_regs *regs, kgdb_data *kdp) | ||||||
|  | { | ||||||
|  | 	/* disable interrupts */ | ||||||
|  | 	disable_interrupts(); | ||||||
|  | 
 | ||||||
|  | 	/* reply to host that an exception has occurred */ | ||||||
|  | 	kdp->sigval = kgdb_trap(regs); | ||||||
|  | 
 | ||||||
|  | 	/* send the PC and the Stack Pointer */ | ||||||
|  | 	kdp->nregs = 2; | ||||||
|  | 	kdp->regs[0].num = BFIN_PC; | ||||||
|  | 	kdp->regs[0].val = regs->pc; | ||||||
|  | 
 | ||||||
|  | 	kdp->regs[1].num = BFIN_SP; | ||||||
|  | 	kdp->regs[1].val = (unsigned long)regs; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void kgdb_exit(struct pt_regs *regs, kgdb_data *kdp) | ||||||
|  | { | ||||||
|  | 	if (kdp->extype & KGDBEXIT_WITHADDR) | ||||||
|  | 		printf("KGDBEXIT_WITHADDR\n"); | ||||||
|  | 
 | ||||||
|  | 	switch (kdp->extype & KGDBEXIT_TYPEMASK) { | ||||||
|  | 	case KGDBEXIT_KILL: | ||||||
|  | 		printf("KGDBEXIT_KILL:\n"); | ||||||
|  | 		break; | ||||||
|  | 	case KGDBEXIT_CONTINUE: | ||||||
|  | 		/* Make sure the supervisor single step bit is clear */ | ||||||
|  | 		regs->syscfg &= ~1; | ||||||
|  | 		break; | ||||||
|  | 	case KGDBEXIT_SINGLE: | ||||||
|  | 		/* set the supervisor single step bit */ | ||||||
|  | 		regs->syscfg |= 1; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		printf("KGDBEXIT : %d\n", kdp->extype); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* enable interrupts */ | ||||||
|  | 	enable_interrupts(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kgdb_trap(struct pt_regs *regs) | ||||||
|  | { | ||||||
|  | 	/* ipend doesn't get filled in properly */ | ||||||
|  | 	switch (regs->seqstat & EXCAUSE) { | ||||||
|  | 	case VEC_EXCPT01: | ||||||
|  | 		return SIGTRAP; | ||||||
|  | 	case VEC_EXCPT03: | ||||||
|  | 		return SIGSEGV; | ||||||
|  | 	case VEC_EXCPT02: | ||||||
|  | 		return SIGTRAP; | ||||||
|  | 	case VEC_EXCPT04 ... VEC_EXCPT15: | ||||||
|  | 		return SIGILL; | ||||||
|  | 	case VEC_STEP: | ||||||
|  | 		return SIGTRAP; | ||||||
|  | 	case VEC_OVFLOW: | ||||||
|  | 		return SIGTRAP; | ||||||
|  | 	case VEC_UNDEF_I: | ||||||
|  | 		return SIGILL; | ||||||
|  | 	case VEC_ILGAL_I: | ||||||
|  | 		return SIGILL; | ||||||
|  | 	case VEC_CPLB_VL: | ||||||
|  | 		return SIGSEGV; | ||||||
|  | 	case VEC_MISALI_D: | ||||||
|  | 		return SIGBUS; | ||||||
|  | 	case VEC_UNCOV: | ||||||
|  | 		return SIGILL; | ||||||
|  | 	case VEC_CPLB_MHIT: | ||||||
|  | 		return SIGSEGV; | ||||||
|  | 	case VEC_MISALI_I: | ||||||
|  | 		return SIGBUS; | ||||||
|  | 	case VEC_CPLB_I_VL: | ||||||
|  | 		return SIGBUS; | ||||||
|  | 	case VEC_CPLB_I_MHIT: | ||||||
|  | 		return SIGSEGV; | ||||||
|  | 	default: | ||||||
|  | 		return SIGBUS; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * getregs - gets the pt_regs, and gives them to kgdb's buffer | ||||||
|  |  */ | ||||||
|  | int kgdb_getregs(struct pt_regs *regs, char *buf, int max) | ||||||
|  | { | ||||||
|  | 	unsigned long *gdb_regs = (unsigned long *)buf; | ||||||
|  | 
 | ||||||
|  | 	if (max < NUMREGBYTES) | ||||||
|  | 		kgdb_error(KGDBERR_NOSPACE); | ||||||
|  | 
 | ||||||
|  | 	if ((unsigned long)gdb_regs & 3) | ||||||
|  | 		kgdb_error(KGDBERR_ALIGNFAULT); | ||||||
|  | 
 | ||||||
|  | 	gdb_regs[BFIN_R0] = regs->r0; | ||||||
|  | 	gdb_regs[BFIN_R1] = regs->r1; | ||||||
|  | 	gdb_regs[BFIN_R2] = regs->r2; | ||||||
|  | 	gdb_regs[BFIN_R3] = regs->r3; | ||||||
|  | 	gdb_regs[BFIN_R4] = regs->r4; | ||||||
|  | 	gdb_regs[BFIN_R5] = regs->r5; | ||||||
|  | 	gdb_regs[BFIN_R6] = regs->r6; | ||||||
|  | 	gdb_regs[BFIN_R7] = regs->r7; | ||||||
|  | 	gdb_regs[BFIN_P0] = regs->p0; | ||||||
|  | 	gdb_regs[BFIN_P1] = regs->p1; | ||||||
|  | 	gdb_regs[BFIN_P2] = regs->p2; | ||||||
|  | 	gdb_regs[BFIN_P3] = regs->p3; | ||||||
|  | 	gdb_regs[BFIN_P4] = regs->p4; | ||||||
|  | 	gdb_regs[BFIN_P5] = regs->p5; | ||||||
|  | 	gdb_regs[BFIN_SP] = (unsigned long)regs; | ||||||
|  | 	gdb_regs[BFIN_FP] = regs->fp; | ||||||
|  | 	gdb_regs[BFIN_I0] = regs->i0; | ||||||
|  | 	gdb_regs[BFIN_I1] = regs->i1; | ||||||
|  | 	gdb_regs[BFIN_I2] = regs->i2; | ||||||
|  | 	gdb_regs[BFIN_I3] = regs->i3; | ||||||
|  | 	gdb_regs[BFIN_M0] = regs->m0; | ||||||
|  | 	gdb_regs[BFIN_M1] = regs->m1; | ||||||
|  | 	gdb_regs[BFIN_M2] = regs->m2; | ||||||
|  | 	gdb_regs[BFIN_M3] = regs->m3; | ||||||
|  | 	gdb_regs[BFIN_B0] = regs->b0; | ||||||
|  | 	gdb_regs[BFIN_B1] = regs->b1; | ||||||
|  | 	gdb_regs[BFIN_B2] = regs->b2; | ||||||
|  | 	gdb_regs[BFIN_B3] = regs->b3; | ||||||
|  | 	gdb_regs[BFIN_L0] = regs->l0; | ||||||
|  | 	gdb_regs[BFIN_L1] = regs->l1; | ||||||
|  | 	gdb_regs[BFIN_L2] = regs->l2; | ||||||
|  | 	gdb_regs[BFIN_L3] = regs->l3; | ||||||
|  | 	gdb_regs[BFIN_A0_DOT_X] = regs->a0x; | ||||||
|  | 	gdb_regs[BFIN_A0_DOT_W] = regs->a0w; | ||||||
|  | 	gdb_regs[BFIN_A1_DOT_X] = regs->a1x; | ||||||
|  | 	gdb_regs[BFIN_A1_DOT_W] = regs->a1w; | ||||||
|  | 	gdb_regs[BFIN_ASTAT] = regs->astat; | ||||||
|  | 	gdb_regs[BFIN_RETS] = regs->rets; | ||||||
|  | 	gdb_regs[BFIN_LC0] = regs->lc0; | ||||||
|  | 	gdb_regs[BFIN_LT0] = regs->lt0; | ||||||
|  | 	gdb_regs[BFIN_LB0] = regs->lb0; | ||||||
|  | 	gdb_regs[BFIN_LC1] = regs->lc1; | ||||||
|  | 	gdb_regs[BFIN_LT1] = regs->lt1; | ||||||
|  | 	gdb_regs[BFIN_LB1] = regs->lb1; | ||||||
|  | 	gdb_regs[BFIN_CYCLES] = 0; | ||||||
|  | 	gdb_regs[BFIN_CYCLES2] = 0; | ||||||
|  | 	gdb_regs[BFIN_USP] = regs->usp; | ||||||
|  | 	gdb_regs[BFIN_SEQSTAT] = regs->seqstat; | ||||||
|  | 	gdb_regs[BFIN_SYSCFG] = regs->syscfg; | ||||||
|  | 	gdb_regs[BFIN_RETI] = regs->pc; | ||||||
|  | 	gdb_regs[BFIN_RETX] = regs->retx; | ||||||
|  | 	gdb_regs[BFIN_RETN] = regs->retn; | ||||||
|  | 	gdb_regs[BFIN_RETE] = regs->rete; | ||||||
|  | 	gdb_regs[BFIN_PC] = regs->pc; | ||||||
|  | 	gdb_regs[BFIN_CC] = 0; | ||||||
|  | 	gdb_regs[BFIN_EXTRA1] = 0; | ||||||
|  | 	gdb_regs[BFIN_EXTRA2] = 0; | ||||||
|  | 	gdb_regs[BFIN_EXTRA3] = 0; | ||||||
|  | 	gdb_regs[BFIN_IPEND] = regs->ipend; | ||||||
|  | 
 | ||||||
|  | 	return NUMREGBYTES; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * putreg - put kgdb's reg (regno) into the pt_regs | ||||||
|  |  */ | ||||||
|  | void kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length) | ||||||
|  | { | ||||||
|  | 	unsigned long *ptr = (unsigned long *)buf; | ||||||
|  | 
 | ||||||
|  | 	if (regno < 0 || regno > BFIN_NUM_REGS) | ||||||
|  | 		kgdb_error(KGDBERR_BADPARAMS); | ||||||
|  | 
 | ||||||
|  | 	if (length < 4) | ||||||
|  | 		kgdb_error(KGDBERR_NOSPACE); | ||||||
|  | 
 | ||||||
|  | 	if ((unsigned long)ptr & 3) | ||||||
|  | 		kgdb_error(KGDBERR_ALIGNFAULT); | ||||||
|  | 
 | ||||||
|  | 	switch (regno) { | ||||||
|  | 	case BFIN_R0: | ||||||
|  | 		regs->r0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R1: | ||||||
|  | 		regs->r1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R2: | ||||||
|  | 		regs->r2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R3: | ||||||
|  | 		regs->r3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R4: | ||||||
|  | 		regs->r4 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R5: | ||||||
|  | 		regs->r5 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R6: | ||||||
|  | 		regs->r6 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_R7: | ||||||
|  | 		regs->r7 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P0: | ||||||
|  | 		regs->p0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P1: | ||||||
|  | 		regs->p1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P2: | ||||||
|  | 		regs->p2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P3: | ||||||
|  | 		regs->p3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P4: | ||||||
|  | 		regs->p4 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_P5: | ||||||
|  | 		regs->p5 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_SP: | ||||||
|  | 		regs->reserved = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_FP: | ||||||
|  | 		regs->fp = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_I0: | ||||||
|  | 		regs->i0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_I1: | ||||||
|  | 		regs->i1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_I2: | ||||||
|  | 		regs->i2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_I3: | ||||||
|  | 		regs->i3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_M0: | ||||||
|  | 		regs->m0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_M1: | ||||||
|  | 		regs->m1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_M2: | ||||||
|  | 		regs->m2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_M3: | ||||||
|  | 		regs->m3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_B0: | ||||||
|  | 		regs->b0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_B1: | ||||||
|  | 		regs->b1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_B2: | ||||||
|  | 		regs->b2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_B3: | ||||||
|  | 		regs->b3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_L0: | ||||||
|  | 		regs->l0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_L1: | ||||||
|  | 		regs->l1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_L2: | ||||||
|  | 		regs->l2 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_L3: | ||||||
|  | 		regs->l3 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_A0_DOT_X: | ||||||
|  | 		regs->a0x = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_A0_DOT_W: | ||||||
|  | 		regs->a0w = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_A1_DOT_X: | ||||||
|  | 		regs->a1x = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_A1_DOT_W: | ||||||
|  | 		regs->a1w = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_ASTAT: | ||||||
|  | 		regs->astat = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_RETS: | ||||||
|  | 		regs->rets = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LC0: | ||||||
|  | 		regs->lc0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LT0: | ||||||
|  | 		regs->lt0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LB0: | ||||||
|  | 		regs->lb0 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LC1: | ||||||
|  | 		regs->lc1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LT1: | ||||||
|  | 		regs->lt1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_LB1: | ||||||
|  | 		regs->lb1 = *ptr; | ||||||
|  | 		break; | ||||||
|  | /*
 | ||||||
|  |   BFIN_CYCLES, | ||||||
|  |   BFIN_CYCLES2, | ||||||
|  |   BFIN_USP, | ||||||
|  |   BFIN_SEQSTAT, | ||||||
|  |   BFIN_SYSCFG, | ||||||
|  | */ | ||||||
|  | 	case BFIN_RETX: | ||||||
|  | 		regs->retx = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_RETN: | ||||||
|  | 		regs->retn = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_RETE: | ||||||
|  | 		regs->rete = *ptr; | ||||||
|  | 		break; | ||||||
|  | 	case BFIN_PC: | ||||||
|  | 		regs->pc = *ptr; | ||||||
|  | 		break; | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		kgdb_error(KGDBERR_BADPARAMS); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void kgdb_putregs(struct pt_regs *regs, char *buf, int length) | ||||||
|  | { | ||||||
|  | 	unsigned long *gdb_regs = (unsigned long *)buf; | ||||||
|  | 
 | ||||||
|  | 	if (length != BFIN_NUM_REGS) | ||||||
|  | 		kgdb_error(KGDBERR_NOSPACE); | ||||||
|  | 
 | ||||||
|  | 	if ((unsigned long)gdb_regs & 3) | ||||||
|  | 		kgdb_error(KGDBERR_ALIGNFAULT); | ||||||
|  | 
 | ||||||
|  | 	regs->r0 = gdb_regs[BFIN_R0]; | ||||||
|  | 	regs->r1 = gdb_regs[BFIN_R1]; | ||||||
|  | 	regs->r2 = gdb_regs[BFIN_R2]; | ||||||
|  | 	regs->r3 = gdb_regs[BFIN_R3]; | ||||||
|  | 	regs->r4 = gdb_regs[BFIN_R4]; | ||||||
|  | 	regs->r5 = gdb_regs[BFIN_R5]; | ||||||
|  | 	regs->r6 = gdb_regs[BFIN_R6]; | ||||||
|  | 	regs->r7 = gdb_regs[BFIN_R7]; | ||||||
|  | 	regs->p0 = gdb_regs[BFIN_P0]; | ||||||
|  | 	regs->p1 = gdb_regs[BFIN_P1]; | ||||||
|  | 	regs->p2 = gdb_regs[BFIN_P2]; | ||||||
|  | 	regs->p3 = gdb_regs[BFIN_P3]; | ||||||
|  | 	regs->p4 = gdb_regs[BFIN_P4]; | ||||||
|  | 	regs->p5 = gdb_regs[BFIN_P5]; | ||||||
|  | 	regs->fp = gdb_regs[BFIN_FP]; | ||||||
|  | /*	regs->sp = gdb_regs[BFIN_ ]; */ | ||||||
|  | 	regs->i0 = gdb_regs[BFIN_I0]; | ||||||
|  | 	regs->i1 = gdb_regs[BFIN_I1]; | ||||||
|  | 	regs->i2 = gdb_regs[BFIN_I2]; | ||||||
|  | 	regs->i3 = gdb_regs[BFIN_I3]; | ||||||
|  | 	regs->m0 = gdb_regs[BFIN_M0]; | ||||||
|  | 	regs->m1 = gdb_regs[BFIN_M1]; | ||||||
|  | 	regs->m2 = gdb_regs[BFIN_M2]; | ||||||
|  | 	regs->m3 = gdb_regs[BFIN_M3]; | ||||||
|  | 	regs->b0 = gdb_regs[BFIN_B0]; | ||||||
|  | 	regs->b1 = gdb_regs[BFIN_B1]; | ||||||
|  | 	regs->b2 = gdb_regs[BFIN_B2]; | ||||||
|  | 	regs->b3 = gdb_regs[BFIN_B3]; | ||||||
|  | 	regs->l0 = gdb_regs[BFIN_L0]; | ||||||
|  | 	regs->l1 = gdb_regs[BFIN_L1]; | ||||||
|  | 	regs->l2 = gdb_regs[BFIN_L2]; | ||||||
|  | 	regs->l3 = gdb_regs[BFIN_L3]; | ||||||
|  | 	regs->a0x = gdb_regs[BFIN_A0_DOT_X]; | ||||||
|  | 	regs->a0w = gdb_regs[BFIN_A0_DOT_W]; | ||||||
|  | 	regs->a1x = gdb_regs[BFIN_A1_DOT_X]; | ||||||
|  | 	regs->a1w = gdb_regs[BFIN_A1_DOT_W]; | ||||||
|  | 	regs->rets = gdb_regs[BFIN_RETS]; | ||||||
|  | 	regs->lc0 = gdb_regs[BFIN_LC0]; | ||||||
|  | 	regs->lt0 = gdb_regs[BFIN_LT0]; | ||||||
|  | 	regs->lb0 = gdb_regs[BFIN_LB0]; | ||||||
|  | 	regs->lc1 = gdb_regs[BFIN_LC1]; | ||||||
|  | 	regs->lt1 = gdb_regs[BFIN_LT1]; | ||||||
|  | 	regs->lb1 = gdb_regs[BFIN_LB1]; | ||||||
|  | 	regs->usp = gdb_regs[BFIN_USP]; | ||||||
|  | 	regs->syscfg = gdb_regs[BFIN_SYSCFG]; | ||||||
|  | 	regs->retx = gdb_regs[BFIN_PC]; | ||||||
|  | 	regs->retn = gdb_regs[BFIN_RETN]; | ||||||
|  | 	regs->rete = gdb_regs[BFIN_RETE]; | ||||||
|  | 	regs->pc = gdb_regs[BFIN_PC]; | ||||||
|  | 
 | ||||||
|  | #if 0	/* can't change these */
 | ||||||
|  | 	regs->astat = gdb_regs[BFIN_ASTAT]; | ||||||
|  | 	regs->seqstat = gdb_regs[BFIN_SEQSTAT]; | ||||||
|  | 	regs->ipend = gdb_regs[BFIN_IPEND]; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void kgdb_breakpoint(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	asm volatile ("excpt 0x1\n"); | ||||||
|  | } | ||||||
							
								
								
									
										160
									
								
								lib_blackfin/kgdb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								lib_blackfin/kgdb.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | |||||||
|  | /* Blackfin KGDB header
 | ||||||
|  |  * | ||||||
|  |  * Copyright 2005-2009 Analog Devices Inc. | ||||||
|  |  * | ||||||
|  |  * Licensed under the GPL-2 or later. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __ASM_BLACKFIN_KGDB_H__ | ||||||
|  | #define __ASM_BLACKFIN_KGDB_H__ | ||||||
|  | 
 | ||||||
|  | /* gdb locks */ | ||||||
|  | #define KGDB_MAX_NO_CPUS 8 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * BUFMAX defines the maximum number of characters in inbound/outbound buffers. | ||||||
|  |  * At least NUMREGBYTES*2 are needed for register packets. | ||||||
|  |  * Longer buffer is needed to list all threads. | ||||||
|  |  */ | ||||||
|  | #define BUFMAX 2048 | ||||||
|  | 
 | ||||||
|  | enum regnames { | ||||||
|  |   /* Core Registers */ | ||||||
|  |   BFIN_R0 = 0, | ||||||
|  |   BFIN_R1, | ||||||
|  |   BFIN_R2, | ||||||
|  |   BFIN_R3, | ||||||
|  |   BFIN_R4, | ||||||
|  |   BFIN_R5, | ||||||
|  |   BFIN_R6, | ||||||
|  |   BFIN_R7, | ||||||
|  |   BFIN_P0, | ||||||
|  |   BFIN_P1, | ||||||
|  |   BFIN_P2, | ||||||
|  |   BFIN_P3, | ||||||
|  |   BFIN_P4, | ||||||
|  |   BFIN_P5, | ||||||
|  |   BFIN_SP, | ||||||
|  |   BFIN_FP, | ||||||
|  |   BFIN_I0, | ||||||
|  |   BFIN_I1, | ||||||
|  |   BFIN_I2, | ||||||
|  |   BFIN_I3, | ||||||
|  |   BFIN_M0, | ||||||
|  |   BFIN_M1, | ||||||
|  |   BFIN_M2, | ||||||
|  |   BFIN_M3, | ||||||
|  |   BFIN_B0, | ||||||
|  |   BFIN_B1, | ||||||
|  |   BFIN_B2, | ||||||
|  |   BFIN_B3, | ||||||
|  |   BFIN_L0, | ||||||
|  |   BFIN_L1, | ||||||
|  |   BFIN_L2, | ||||||
|  |   BFIN_L3, | ||||||
|  |   BFIN_A0_DOT_X, | ||||||
|  |   BFIN_A0_DOT_W, | ||||||
|  |   BFIN_A1_DOT_X, | ||||||
|  |   BFIN_A1_DOT_W, | ||||||
|  |   BFIN_ASTAT, | ||||||
|  |   BFIN_RETS, | ||||||
|  |   BFIN_LC0, | ||||||
|  |   BFIN_LT0, | ||||||
|  |   BFIN_LB0, | ||||||
|  |   BFIN_LC1, | ||||||
|  |   BFIN_LT1, | ||||||
|  |   BFIN_LB1, | ||||||
|  |   BFIN_CYCLES, | ||||||
|  |   BFIN_CYCLES2, | ||||||
|  |   BFIN_USP, | ||||||
|  |   BFIN_SEQSTAT, | ||||||
|  |   BFIN_SYSCFG, | ||||||
|  |   BFIN_RETI, | ||||||
|  |   BFIN_RETX, | ||||||
|  |   BFIN_RETN, | ||||||
|  |   BFIN_RETE, | ||||||
|  | 
 | ||||||
|  |   /* Pseudo Registers */ | ||||||
|  |   BFIN_PC, | ||||||
|  |   BFIN_CC, | ||||||
|  |   BFIN_EXTRA1,		/* Address of .text section.  */ | ||||||
|  |   BFIN_EXTRA2,		/* Address of .data section.  */ | ||||||
|  |   BFIN_EXTRA3,		/* Address of .bss section.  */ | ||||||
|  |   BFIN_FDPIC_EXEC, | ||||||
|  |   BFIN_FDPIC_INTERP, | ||||||
|  | 
 | ||||||
|  |   /* MMRs */ | ||||||
|  |   BFIN_IPEND, | ||||||
|  | 
 | ||||||
|  |   /* LAST ENTRY SHOULD NOT BE CHANGED.  */ | ||||||
|  |   BFIN_NUM_REGS		/* The number of all registers.  */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Number of bytes of registers.  */ | ||||||
|  | #define NUMREGBYTES (BFIN_NUM_REGS * 4) | ||||||
|  | 
 | ||||||
|  | static inline void arch_kgdb_breakpoint(void) | ||||||
|  | { | ||||||
|  | 	asm volatile ("EXCPT 2;"); | ||||||
|  | } | ||||||
|  | #define BREAK_INSTR_SIZE	2 | ||||||
|  | #define CACHE_FLUSH_IS_SAFE	1 | ||||||
|  | #define GDB_ADJUSTS_BREAK_OFFSET | ||||||
|  | #define GDB_SKIP_HW_WATCH_TEST | ||||||
|  | #define HW_INST_WATCHPOINT_NUM	6 | ||||||
|  | #define HW_WATCHPOINT_NUM	8 | ||||||
|  | #define TYPE_INST_WATCHPOINT	0 | ||||||
|  | #define TYPE_DATA_WATCHPOINT	1 | ||||||
|  | 
 | ||||||
|  | /* Instruction watchpoint address control register bits mask */ | ||||||
|  | #define WPPWR		0x1 | ||||||
|  | #define WPIREN01	0x2 | ||||||
|  | #define WPIRINV01	0x4 | ||||||
|  | #define WPIAEN0		0x8 | ||||||
|  | #define WPIAEN1		0x10 | ||||||
|  | #define WPICNTEN0	0x20 | ||||||
|  | #define WPICNTEN1	0x40 | ||||||
|  | #define EMUSW0		0x80 | ||||||
|  | #define EMUSW1		0x100 | ||||||
|  | #define WPIREN23	0x200 | ||||||
|  | #define WPIRINV23	0x400 | ||||||
|  | #define WPIAEN2		0x800 | ||||||
|  | #define WPIAEN3		0x1000 | ||||||
|  | #define WPICNTEN2	0x2000 | ||||||
|  | #define WPICNTEN3	0x4000 | ||||||
|  | #define EMUSW2		0x8000 | ||||||
|  | #define EMUSW3		0x10000 | ||||||
|  | #define WPIREN45	0x20000 | ||||||
|  | #define WPIRINV45	0x40000 | ||||||
|  | #define WPIAEN4		0x80000 | ||||||
|  | #define WPIAEN5		0x100000 | ||||||
|  | #define WPICNTEN4	0x200000 | ||||||
|  | #define WPICNTEN5	0x400000 | ||||||
|  | #define EMUSW4		0x800000 | ||||||
|  | #define EMUSW5		0x1000000 | ||||||
|  | #define WPAND		0x2000000 | ||||||
|  | 
 | ||||||
|  | /* Data watchpoint address control register bits mask */ | ||||||
|  | #define WPDREN01	0x1 | ||||||
|  | #define WPDRINV01	0x2 | ||||||
|  | #define WPDAEN0		0x4 | ||||||
|  | #define WPDAEN1		0x8 | ||||||
|  | #define WPDCNTEN0	0x10 | ||||||
|  | #define WPDCNTEN1	0x20 | ||||||
|  | 
 | ||||||
|  | #define WPDSRC0		0xc0 | ||||||
|  | #define WPDACC0_OFFSET	8 | ||||||
|  | #define WPDSRC1		0xc00 | ||||||
|  | #define WPDACC1_OFFSET	12 | ||||||
|  | 
 | ||||||
|  | /* Watchpoint status register bits mask */ | ||||||
|  | #define STATIA0		0x1 | ||||||
|  | #define STATIA1		0x2 | ||||||
|  | #define STATIA2		0x4 | ||||||
|  | #define STATIA3		0x8 | ||||||
|  | #define STATIA4		0x10 | ||||||
|  | #define STATIA5		0x20 | ||||||
|  | #define STATDA0		0x40 | ||||||
|  | #define STATDA1		0x80 | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -230,15 +230,45 @@ void *memcpy(void *dst, const void *src, size_t count) | |||||||
| 	if (!count) | 	if (!count) | ||||||
| 		return dst; | 		return dst; | ||||||
| 
 | 
 | ||||||
| 	if (addr_bfin_on_chip_mem(dst)) { | #ifdef CONFIG_CMD_KGDB | ||||||
| 		/* L1 is the destination */ | 	if (src >= (void *)SYSMMR_BASE) { | ||||||
| 		return dma_memcpy(dst, src, count); | 		if (count == 2 && (unsigned long)src % 2 == 0) { | ||||||
|  | 			u16 mmr = bfin_read16(src); | ||||||
|  | 			memcpy(dst, &mmr, sizeof(mmr)); | ||||||
|  | 			return dst; | ||||||
|  | 		} | ||||||
|  | 		if (count == 4 && (unsigned long)src % 4 == 0) { | ||||||
|  | 			u32 mmr = bfin_read32(src); | ||||||
|  | 			memcpy(dst, &mmr, sizeof(mmr)); | ||||||
|  | 			return dst; | ||||||
|  | 		} | ||||||
|  | 		/* Failed for some reason */ | ||||||
|  | 		memset(dst, 0xad, count); | ||||||
|  | 		return dst; | ||||||
|  | 	} | ||||||
|  | 	if (dst >= (void *)SYSMMR_BASE) { | ||||||
|  | 		if (count == 2 && (unsigned long)dst % 2 == 0) { | ||||||
|  | 			u16 mmr; | ||||||
|  | 			memcpy(&mmr, src, sizeof(mmr)); | ||||||
|  | 			bfin_write16(dst, mmr); | ||||||
|  | 			return dst; | ||||||
|  | 		} | ||||||
|  | 		if (count == 4 && (unsigned long)dst % 4 == 0) { | ||||||
|  | 			u32 mmr; | ||||||
|  | 			memcpy(&mmr, src, sizeof(mmr)); | ||||||
|  | 			bfin_write32(dst, mmr); | ||||||
|  | 			return dst; | ||||||
|  | 		} | ||||||
|  | 		/* Failed for some reason */ | ||||||
|  | 		memset(dst, 0xad, count); | ||||||
|  | 		return dst; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 	} else if (addr_bfin_on_chip_mem(src)) { | 	/* if L1 is the source or dst, use DMA */ | ||||||
| 		/* L1 is the source */ | 	if (addr_bfin_on_chip_mem(dst) || addr_bfin_on_chip_mem(src)) | ||||||
| 		return dma_memcpy(dst, src, count); | 		return dma_memcpy(dst, src, count); | ||||||
| 
 | 	else | ||||||
| 	} else |  | ||||||
| 		/* No L1 is involved, so just call regular memcpy */ | 		/* No L1 is involved, so just call regular memcpy */ | ||||||
| 		return memcpy_ASM(dst, src, count); | 		return memcpy_ASM(dst, src, count); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user