Add preliminary RouterBoard RB1xx support
[openwrt.git] / target / linux / rb1xx-2.6 / image / lzma-loader / src / head.S
1 /* Copyright 2007 Gabor Juhos                           */
2 /* keep original values of the a0,a1,a2,a3 registers    */
3 /* cache manipulation adapted from Broadcom code        */
4 /* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su)     */
5 /* cache manipulation adapted from Broadcom code        */
6 /* idea taken from original bunzip2 decompressor code   */
7 /* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org)  */
8 /* Licensed under the linux kernel's version of the GPL.*/
9
10 #include <asm/asm.h>
11 #include <asm/regdef.h>
12
13 #define KSEG0           0x80000000
14
15 #define C0_CONFIG       $16
16 #define C0_TAGLO        $28
17 #define C0_TAGHI        $29
18
19 #define CONF1_DA_SHIFT  7                       /* D$ associativity */
20 #define CONF1_DA_MASK   0x00000380
21 #define CONF1_DA_BASE   1
22 #define CONF1_DL_SHIFT  10                      /* D$ line size */
23 #define CONF1_DL_MASK   0x00001c00
24 #define CONF1_DL_BASE   2
25 #define CONF1_DS_SHIFT  13                      /* D$ sets/way */
26 #define CONF1_DS_MASK   0x0000e000
27 #define CONF1_DS_BASE   64
28 #define CONF1_IA_SHIFT  16                      /* I$ associativity */
29 #define CONF1_IA_MASK   0x00070000
30 #define CONF1_IA_BASE   1
31 #define CONF1_IL_SHIFT  19                      /* I$ line size */
32 #define CONF1_IL_MASK   0x00380000
33 #define CONF1_IL_BASE   2
34 #define CONF1_IS_SHIFT  22                      /* Instruction cache sets/way */
35 #define CONF1_IS_MASK   0x01c00000
36 #define CONF1_IS_BASE   64
37
38 #define Index_Invalidate_I      0x00
39 #define Index_Writeback_Inv_D   0x01
40
41         .text
42         LEAF(startup)
43         .set noreorder
44         
45         /* Copy decompressor code to the right place */
46         li      t0, BZ_TEXT_START
47
48         la      t1, code_start
49         la      t2, code_stop
50 $L1:
51         lw      t3, 0(t1)
52         sw      t3, 0(t0)
53         add     t1, 4
54         blt     t1, t2, $L1
55         add     t0, 4
56
57         /* At this point we need to invalidate dcache and */
58         /* icache before jumping to new code */
59
60 1:      /* Get cache sizes */
61         .set    mips32
62         mfc0    s0,C0_CONFIG,1
63         .set    mips0
64
65         li      s1,CONF1_DL_MASK
66         and     s1,s0
67         beq     s1,zero,nodc
68         nop
69
70         srl     s1,CONF1_DL_SHIFT
71         li      t0,CONF1_DL_BASE
72         sll     s1,t0,s1                /* s1 has D$ cache line size */
73
74         li      s2,CONF1_DA_MASK
75         and     s2,s0
76         srl     s2,CONF1_DA_SHIFT
77         addiu   s2,CONF1_DA_BASE        /* s2 now has D$ associativity */
78
79         li      t0,CONF1_DS_MASK
80         and     t0,s0
81         srl     t0,CONF1_DS_SHIFT
82         li      s3,CONF1_DS_BASE
83         sll     s3,s3,t0                /* s3 has D$ sets per way */
84
85         multu   s2,s3                   /* sets/way * associativity */
86         mflo    t0                      /* total cache lines */
87
88         multu   s1,t0                   /* D$ linesize * lines */
89         mflo    s2                      /* s2 is now D$ size in bytes */
90
91         /* Initilize the D$: */
92         mtc0    zero,C0_TAGLO
93         mtc0    zero,C0_TAGHI
94
95         li      t0,KSEG0                /* Just an address for the first $ line */
96         addu    t1,t0,s2                /*  + size of cache == end */
97
98         .set    mips3
99 1:      cache   Index_Writeback_Inv_D,0(t0)
100         .set    mips0
101         bne     t0,t1,1b
102         addu    t0,s1
103         
104 nodc:
105         /* Now we get to do it all again for the I$ */
106         
107         move    s3,zero                 /* just in case there is no icache */
108         move    s4,zero
109
110         li      t0,CONF1_IL_MASK
111         and     t0,s0
112         beq     t0,zero,noic
113         nop
114
115         srl     t0,CONF1_IL_SHIFT
116         li      s3,CONF1_IL_BASE
117         sll     s3,t0                   /* s3 has I$ cache line size */
118
119         li      t0,CONF1_IA_MASK
120         and     t0,s0
121         srl     t0,CONF1_IA_SHIFT
122         addiu   s4,t0,CONF1_IA_BASE     /* s4 now has I$ associativity */
123
124         li      t0,CONF1_IS_MASK
125         and     t0,s0
126         srl     t0,CONF1_IS_SHIFT
127         li      s5,CONF1_IS_BASE
128         sll     s5,t0                   /* s5 has I$ sets per way */
129
130         multu   s4,s5                   /* sets/way * associativity */
131         mflo    t0                      /* s4 is now total cache lines */
132
133         multu   s3,t0                   /* I$ linesize * lines */
134         mflo    s4                      /* s4 is cache size in bytes */
135
136         /* Initilize the I$: */
137         mtc0    zero,C0_TAGLO
138         mtc0    zero,C0_TAGHI
139
140         li      t0,KSEG0                /* Just an address for the first $ line */
141         addu    t1,t0,s4                /*  + size of cache == end */
142
143         .set    mips3
144 1:      cache   Index_Invalidate_I,0(t0)
145         .set    mips0
146         bne     t0,t1,1b
147         addu    t0,s3
148
149 noic:
150         li      t0, BZ_TEXT_START
151         
152         addiu   sp, -32                 /* reserve stack for parameters */
153 #if 0   
154         sw      a0, 0(sp)
155         sw      a1, 4(sp)
156         sw      a2, 8(sp)
157         sw      a3, 12(sp)
158 #endif  
159         sw      s3, 16(sp)              /* icache line size */
160         sw      s4, 20(sp)              /* icache size */
161         sw      s1, 24(sp)              /* dcache line size */
162         jr      t0
163         sw      s2, 28(sp)              /* dcache size */
164         
165         .set reorder
166         END(startup)