Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92bbe1b9 authored by Florian Fainelli's avatar Florian Fainelli Committed by Ralf Baechle
Browse files

MIPS: Deal with larger physical offsets



AR7 has a larger physical offset than other MIPS based systems and therefore
needs to setup its handlers beyond the usual KSEG0 range. When running the
kernel in mapped mode this modification is also required. Remove function
comment which is now incorrect.

Signed-off-by: default avatarDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: default avatarEugene Konev <ejka@imfi.kspu.ru>
Signed-off-by: default avatarFlorian Fainelli <florian@openwrt.org>
To: linux-mips@linux-mips.org
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/889/
Patchwork: http://patchwork.linux-mips.org/patch/932/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 2d1b6e95
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
#include <asm/types.h>
#include <asm/stacktrace.h>
#include <asm/irq.h>
#include <asm/uasm.h>

extern void check_wait(void);
extern asmlinkage void r4k_wait(void);
@@ -1271,11 +1272,6 @@ unsigned long ebase;
unsigned long exception_handlers[32];
unsigned long vi_handlers[64];

/*
 * As a side effect of the way this is implemented we're limited
 * to interrupt handlers in the address range from
 * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
 */
void __init *set_except_vector(int n, void *addr)
{
	unsigned long handler = (unsigned long) addr;
@@ -1283,9 +1279,18 @@ void __init *set_except_vector(int n, void *addr)

	exception_handlers[n] = handler;
	if (n == 0 && cpu_has_divec) {
		*(u32 *)(ebase + 0x200) = 0x08000000 |
					  (0x03ffffff & (handler >> 2));
		local_flush_icache_range(ebase + 0x200, ebase + 0x204);
		unsigned long jump_mask = ~((1 << 28) - 1);
		u32 *buf = (u32 *)(ebase + 0x200);
		unsigned int k0 = 26;
		if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
			uasm_i_j(&buf, handler & ~jump_mask);
			uasm_i_nop(&buf);
		} else {
			UASM_i_LA(&buf, k0, handler);
			uasm_i_jr(&buf, k0);
			uasm_i_nop(&buf);
		}
		local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
	}
	return (void *)old_handler;
}