1/*
2 * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
3 *
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * Some parts of this code was based on the OpenWrt specific lzma-loader
7 * for the BCM47xx and ADM5120 based boards:
8 *	Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
9 *	Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 */
15
16#include <asm/asm.h>
17#include <asm/regdef.h>
18#include "cp0regdef.h"
19#include "cacheops.h"
20#include "config.h"
21
22#define KSEG0		0x80000000
23
24	.macro	ehb
25	sll     zero, 3
26	.endm
27
28	.text
29
30LEAF(startup)
31	.set noreorder
32	.set mips32
33
34	mtc0	zero, CP0_WATCHLO	# clear watch registers
35	mtc0	zero, CP0_WATCHHI
36	mtc0	zero, CP0_CAUSE		# clear before writing status register
37
38	mfc0	t0, CP0_STATUS
39	li	t1, 0x1000001f
40	or	t0, t1
41	xori	t0, 0x1f
42	mtc0	t0, CP0_STATUS
43	ehb
44
45	mtc0	zero, CP0_COUNT
46	mtc0	zero, CP0_COMPARE
47	ehb
48
49	la	t0, __reloc_label	# get linked address of label
50	bal	__reloc_label		# branch and link to label to
51	nop				# get actual address
52__reloc_label:
53	subu	t0, ra, t0		# get reloc_delta
54
55	beqz	t0, __reloc_done         # if delta is 0 we are in the right place
56	nop
57
58	/* Copy our code to the right place */
59	la	t1, _code_start		# get linked address of _code_start
60	la	t2, _code_end		# get linked address of _code_end
61	addu	t0, t0, t1		# calculate actual address of _code_start
62
63__reloc_copy:
64	lw	t3, 0(t0)
65	sw	t3, 0(t1)
66	add	t1, 4
67	blt	t1, t2, __reloc_copy
68	add	t0, 4
69
70	/* flush cache */
71	la	t0, _code_start
72	la	t1, _code_end
73
74	li	t2, ~(CONFIG_CACHELINE_SIZE - 1)
75	and	t0, t2
76	and	t1, t2
77	li	t2, CONFIG_CACHELINE_SIZE
78
79	b	__flush_check
80	nop
81
82__flush_line:
83	cache	Hit_Writeback_Inv_D, 0(t0)
84	cache	Hit_Invalidate_I, 0(t0)
85	add	t0, t2
86
87__flush_check:
88	bne	t0, t1, __flush_line
89	nop
90
91	sync
92
93__reloc_done:
94
95	/* clear bss */
96	la	t0, _bss_start
97	la	t1, _bss_end
98	b	__bss_check
99	nop
100
101__bss_fill:
102	sw	zero, 0(t0)
103	addi	t0, 4
104
105__bss_check:
106	bne	t0, t1, __bss_fill
107	nop
108
109	/* Setup new "C" stack */
110	la	sp, _stack
111
112	/* reserve stack space for a0-a3 registers */
113	subu	sp, 16
114
115	/* jump to the decompressor routine */
116	la	t0, loader_main
117	jr	t0
118	nop
119
120	.set reorder
121END(startup)
122