Migrate UI cleanup phase 4 from MIPS into ARM
[tomato.git] / release / src-rt-6.x.4708 / shared / pcieinit_ca9.S
blobbe75e3c8a30aaf50ad62b33f9341d37aef888aa1
1 #include <arminc.h>
2 #include <hndsoc.h>
3 #include <sbchipc.h>
5 #ifndef __arm__
6 #error __arm__ is NOT defined
7 #endif
9 /* Routine begin/end macro */
10 #if defined(__thumb__)
11 #define FUNC(x) THUMBLEAF(x)
12 #else
13 #define FUNC(x) LEAF(x)
14 #endif  /* __thumb__ */
16 #ifdef BCMDBG
17 #define TRACE(x) \
18         ldr     r9,=(x); \
19         ldr     r10,=SI_ENUM_BASE; \
20         str     r9,[r10,#0x64]
22 #define TRACE1(x) \
23         mov     r9,x; \
24         ldr     r10,=SI_ENUM_BASE; \
25         str     r9,[r10,#0x68]
27 #define TRACE2(x) \
28         mov     r9,x; \
29         ldr     r10,=SI_ENUM_BASE; \
30         str     r9,[r10,#0x64]
31 #else
32 #define TRACE(x)
33 #define TRACE1(x)
34 #define TRACE2(x)
35 #endif
37         .text
39 FUNC(pcie_phy_init)
40         mov     r6,lr
41         /*
42          *    Sys Init code -- read OTP, program the H/W blocks
43          *    At completion, take a jump to __hw_init_done
44          */
45 __sys_init:
47         ldr     r0,=SI_ENUM_BASE                /* r0:  core regs SI base address */
48         ldr     r4,[r0,#CC_CAPABILITIES]        /* r4:  capabitilies */
49         and     r4,r4,#CC_CAP_OTPSIZE
50         cmp     r4,#0
51         beq     __hw_init_done
52         ldr     r1,[r0,#CC_CLKDIV]
53         mov     r2,#~CLKD_OTP
54         and     r2,r2,r1
55         mov     r1,#(0xe << CLKD_OTP_SHIFT)
56         orr     r2,r2,r1
57         str     r2,[r0,#CC_CLKDIV]              /* Update OtpClk in clkdiv with 14 */
58         ldr     r1,=200                         /* Wait for 200 cycles for stable OTP clock */
59 spinn:  sub     r1,r1,#0x1
60         cmp     r1,#0x0
61         bne     spinn
62         lsr     r2,r4,#CC_CAP_OTPSIZE_SHIFT     /* Get OTP size */
63         adrl    r1,otp_sizes
64         lsl     r2,r2,#0x2
65         ldr     r3,[r1,r2]                      /* Get the OTP size from otp_sizes table (in bytes) */
67         cmp     r3,#0x0                         /* skip zero size */
68         beq     __hw_init_done
69         ldr     r1,[r0,#CC_OTPST]
70         and     r1,r1,#OTPS_READY
71         cmp     r1,#0x0                         /* 0: OTP is not ready for whatever reason */
72         beq     __hw_init_done
73         add     r2,r3,r0                        /* Seek to the end of OTP region */
74         /* Scan entire OTP from END -> BEGIN to find first
75          * matching hwinit entry */
76         sub     r2,r2,#2
77 1:      
78         add     r4,r2,#CC_SROM_OTP
79         ldrh    r1,[r4]
80         lsl     r1,r1,#0x10
81         sub     r2,r2,#2
82         add     r4,r2,#CC_SROM_OTP
83         ldrh    r3,[r4]
84         orr     r1,r1,r3
85         ldr     r4,=0xeaeaeaea                  /* SID */
86         cmp     r1,r4
87         beq     1f
88         cmp     r0,r2
89         blt     1b
90         /* no hwinit data from OTP */
91         b       __hw_init_done
93         add     r0,r2,#CC_SROM_OTP
94         add     r0,r0,#4
95         mov     r1,#0x800       /* for the first delay */
96         
97 __init_next_cmd:
99         /*
100          *    delay for N cycles
101          *    read OTP : 32b entry comprise {16b loop count, 8b delay, 8b cmd}
102          *    execute OPT cmd.
103          *    Do_Next if any.
104          */
106         bl      __init_dly      /* inter-command delay */
107         
108         ldrh    r1,[r0],#2      /* {delay, Cmd} */
109         and     r2,r1,#0x0f     /* extract Cmd */
110         cmp     r2,#0x1         /* EID (end of init data) */
111         beq     __hw_init_done  /* jump to __hw_init_done on End of Init Data */
112         ldrh    r3,[r0],#2      /* Loop Count */
114         cmp     r2,#0           /* NOP */
115         beq     __init_next_cmd
116                 
117         /* load two 32b datum */
118         bl      __init_load64
119         mov     r7,r10          /* prepare indirect addr */
120         mov     r8,r12          /* prepare indirect data */
122         /*
123          * handle various cases
124          */ 
125         cmp     r2,#4
126         beq     __init_wr_dir
127         cmp     r2,#5
128         beq     __init_wr_indir
129         cmp     r2,#6
130         beq     __init_wr_indir_incaddr
131         cmp     r2,#7
132         beq     __init_wr_indir_incaddr
133         cmp     r2,#8
134         beq     __init_wr_dir_incaddr_data
135         cmp     r2,#9
136         beq     __init_wr_indir_incaddr_data    
137         cmp     r2,#10  
138         beq     __init_wr_dir_incaddr_incdata
139         cmp     r2,#11
140         beq     __init_wr_indir_incaddr_incdata 
141         
142         /* write direct (cmd=0x02) is a special case of
143          * write direct multiple (cmd=0x04), under loop count=1
145          * write indirect (cmd=0x03) is a special case of
146          * write indirect multiple (cmd=0x05), under loop count=1
147          */
149         /* write direct multiple (cmd=0x04) */
150 __init_wr_dir:
151         str     r12,[r10]               /* Mem[addr] = data */
152         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
153         beq     __init_next_cmd         /* loop cnt = 0 */
154         bl      __init_load64           /* load next pair of addr, data */
155         bl      __init_dly              /* inter-op delay */
156         b       __init_wr_dir
158         /* write indirect multiple (cmd=0x05) */
159 __init_wr_indir:
160         bl      __init_load64           /* load next pair of addr, data */
161         str     r10,[r7]                /* mem[indirect addr] = addr */
162         str     r12,[r8]                /* mem[indirect data] = data */
163         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
164         beq     __init_next_cmd         /* loop cnt = 0 */
165         bl      __init_dly              /* inter-op delay */    
166         b       __init_wr_indir
168         /* cmd=0x06 */
169         /* write direct, (post) auto-inc address */ 
170 __init_wr_dir_incaddr:
171         str     r12,[r10],#4            /* Mem[addr++] = data, auto-inc addr */
172         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
173         beq     __init_next_cmd         /* loop cnt = 0 */
174         bl      __init_load32           /* load next data */
175         bl      __init_dly              /* inter-op delay */
176         b       __init_wr_indir_incaddr
178         /* cmd=0x07 */
179         /* write indirect, (post) auto-inc address */
180 __init_wr_indir_incaddr:
181         bl      __init_load64           /* load first addr & data */
182 __next_d_0:
183         str     r10,[r7]                /* Mem[addr] = addr */
184         str     r12,[r8]                /* Mem[data] = data */
185         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
186         beq     __init_next_cmd         /* loop cnt = 0 */
187         add     r10,r10,#4              /* inc addr by 4 bytes */
188         bl      __init_load32           /* load next data */
189         bl      __init_dly              /* inter-op delay */
190         b       __next_d_0
192         /* cmd=0x08 */
193         /* write direct multiple, repeatedly the same data to (post) auto-inc address */
194 __init_wr_dir_incaddr_data:
195         str     r12,[r10],#4            /* Mem[addr] = data, auto_inc addr */
196         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
197         beq     __init_next_cmd         /* loop cnt = 0 */
198         bl      __init_dly              /* inter-op delay */
199         b       __init_wr_dir_incaddr_data
201         /* cmd=0x09 */
202         /* write inirect multiple, repeatedly the same data to (post) auto-inc address */
203 __init_wr_indir_incaddr_data:
204         bl      __init_load64           /* load first addr & data */
205 __next_d_1:
206         str     r10,[r7]                /* Mem[addr] = addr */
207         str     r12,[r8]                /* Mem[data] = data */
208         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
209         beq     __init_next_cmd         /* loop cnt = 0 */
210         add     r10,r10,#4              /* inc addr by 4 bytes */
211         bl      __init_dly              /* inter-op delay */
212         b       __next_d_1
214         /* cmd=0x0a */
215         /* write direct multiple, (post) auto-inc addr and data */
216 __init_wr_dir_incaddr_incdata:
217         str     r12,[r10],#4            /* Mem[addr] = data, inc addr */
218         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
219         beq     __init_next_cmd         /* loop cnt = 0 */
220         add     r12,r12,#1              /* inc data by 1 */
221         bl      __init_dly              /* inter-op delay */
222         b       __init_wr_dir_incaddr_incdata
223         
224         /* cmd=0x0b */
225         /* write indirect multiple, (post) auto-inc addr and data */    
226 __init_wr_indir_incaddr_incdata:
227         bl      __init_load64           /* load first addr & data */
228 __next_d_2:
229         str     r10,[r7]                /* Mem[addr] = addr */
230         str     r12,[r8]                /* Mem[data] = data */
231         subs    r3,r3,#1                /* loop cnt = loop cnt -1 */
232         beq     __init_next_cmd         /* loop cnt = 0 */
233         add     r10,r10,#4              /* inc addr by 4 bytes */
234         add     r12,r12,#1              /* inc data by 1 */
235         bl      __init_dly              /* inter-op delay */
236         b       __next_d_2
238         /*
239          * Define two Utilities to save the code space.
240          *
241          * load one or two 32b datum from current OTP position
242          * r10 = {r10, r9}
243          * r12 = {r12, r11}
244          */
245 __init_load64:
246         ldrh    r10,[r0],#2
247         ldrh    r9,[r0],#2
248         orr     r10,r9,r10,lsl #16
249 __init_load32:
250         ldrh    r12,[r0],#2
251         ldrh    r11,[r0],#2
252         orr     r12,r11,r12,lsl #16
253         bx      lr                       /* return */
255         /* impose some inter-op and inter-cmd delay
256          * delay count is passed thru reg. r1
257          */
258 __init_dly:
259         asr     r9,r1,#11       /* r1/8 cycles, effectively (r1&0x0000ff00) >> 3 */
260         cmp     r9,#0
261         beq     __no_dly
262 __dly_loop:
263         subs    r9,r9,#1        /* loop here */
264         bne     __dly_loop
265 __no_dly:       
266         bx      lr              /* return */
268         /*
269          * Hardware init. is done
270          */
271                 
272 __hw_init_done:
273         /* Continuing boot */
274         mov     lr,r6
275         mov     pc,lr
277 /* OTP sizes in bytes */
278 otp_sizes:
279         .word   0
280         .word   256     /* 2048 bits: 32X64 */
281         .word   512     /* 4096 bits: 2*32X64 */ 
282         .word   1024    /* 8192 bits: 4*32X64 */
283         .word   512     /* 4096 bits: 64X64 */
284         .word   768     /* 6144 bits: 5 32X64 */
285         .word   0       /* 512 bits: dont care */
286         .word   128     /* 1024 bits: 8X64 */
288 END(pcie_phy_init)