6 #error __arm__ is NOT defined
9 /* Routine begin/end macro */
10 #if defined(__thumb__)
11 #define FUNC(x) THUMBLEAF(x)
13 #define FUNC(x) LEAF(x)
14 #endif /* __thumb__ */
19 ldr r10,=SI_ENUM_BASE; \
24 ldr r10,=SI_ENUM_BASE; \
29 ldr r10,=SI_ENUM_BASE; \
42 * Sys Init code -- read OTP, program the H/W blocks
43 * At completion, take a jump to __hw_init_done
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
52 ldr r1,[r0,#CC_CLKDIV]
55 mov r1,#(0xe << CLKD_OTP_SHIFT)
57 str r2,[r0,#CC_CLKDIV] /* Update OtpClk in clkdiv with 14 */
58 ldr r1,=200 /* Wait for 200 cycles for stable OTP clock */
62 lsr r2,r4,#CC_CAP_OTPSIZE_SHIFT /* Get OTP size */
65 ldr r3,[r1,r2] /* Get the OTP size from otp_sizes table (in bytes) */
67 cmp r3,#0x0 /* skip zero size */
71 cmp r1,#0x0 /* 0: OTP is not ready for whatever reason */
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 */
78 add r4,r2,#CC_SROM_OTP
82 add r4,r2,#CC_SROM_OTP
85 ldr r4,=0xeaeaeaea /* SID */
90 /* no hwinit data from OTP */
93 add r0,r2,#CC_SROM_OTP
95 mov r1,#0x800 /* for the first delay */
101 * read OTP : 32b entry comprise {16b loop count, 8b delay, 8b cmd}
106 bl __init_dly /* inter-command delay */
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 */
117 /* load two 32b datum */
119 mov r7,r10 /* prepare indirect addr */
120 mov r8,r12 /* prepare indirect data */
123 * handle various cases
130 beq __init_wr_indir_incaddr
132 beq __init_wr_indir_incaddr
134 beq __init_wr_dir_incaddr_data
136 beq __init_wr_indir_incaddr_data
138 beq __init_wr_dir_incaddr_incdata
140 beq __init_wr_indir_incaddr_incdata
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
149 /* write direct multiple (cmd=0x04) */
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 */
158 /* write indirect multiple (cmd=0x05) */
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 */
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
179 /* write indirect, (post) auto-inc address */
180 __init_wr_indir_incaddr:
181 bl __init_load64 /* load first addr & data */
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 */
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
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 */
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 */
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
225 /* write indirect multiple, (post) auto-inc addr and data */
226 __init_wr_indir_incaddr_incdata:
227 bl __init_load64 /* load first addr & data */
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 */
239 * Define two Utilities to save the code space.
241 * load one or two 32b datum from current OTP position
248 orr r10,r9,r10,lsl #16
252 orr r12,r11,r12,lsl #16
255 /* impose some inter-op and inter-cmd delay
256 * delay count is passed thru reg. r1
259 asr r9,r1,#11 /* r1/8 cycles, effectively (r1&0x0000ff00) >> 3 */
263 subs r9,r9,#1 /* loop here */
269 * Hardware init. is done
273 /* Continuing boot */
277 /* OTP sizes in bytes */
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 */