OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From fa51192b912d296b8eec10f7d44c6c17eb1dd368 Mon Sep 17 00:00:00 2001 |
2 | From: Xiangfu <xiangfu@openmobilefree.net> |
||
3 | Date: Fri, 12 Oct 2012 09:47:39 +0800 |
||
4 | Subject: [PATCH 2/6] qi_lb60: add software usbboot support |
||
5 | |||
6 | JZ4740 CPU have a internal ROM have such kind of code, that make |
||
7 | JZ4740 can boot from USB |
||
8 | |||
9 | usbboot.S can downloads user program from the USB port to internal |
||
10 | SRAM and branches to the internal SRAM to execute the program |
||
11 | |||
12 | Signed-off-by: Xiangfu <xiangfu@openmobilefree.net> |
||
13 | --- |
||
14 | board/qi/qi_lb60/Makefile | 1 + |
||
15 | board/qi/qi_lb60/qi_lb60-spl.c | 20 + |
||
16 | board/qi/qi_lb60/usbboot.S | 838 ++++++++++++++++++++++++++++++++++++++++ |
||
17 | 3 files changed, 859 insertions(+) |
||
18 | create mode 100644 board/qi/qi_lb60/usbboot.S |
||
19 | |||
20 | diff --git a/board/qi/qi_lb60/Makefile b/board/qi/qi_lb60/Makefile |
||
21 | index e399246..6dd8c6f 100644 |
||
22 | --- a/board/qi/qi_lb60/Makefile |
||
23 | +++ b/board/qi/qi_lb60/Makefile |
||
24 | @@ -23,6 +23,7 @@ include $(TOPDIR)/config.mk |
||
25 | LIB = $(obj)lib$(BOARD).o |
||
26 | |||
27 | ifeq ($(CONFIG_SPL_BUILD),y) |
||
28 | +SOBJS := usbboot.o |
||
29 | COBJS := $(BOARD)-spl.o |
||
30 | else |
||
31 | COBJS := $(BOARD).o |
||
32 | diff --git a/board/qi/qi_lb60/qi_lb60-spl.c b/board/qi/qi_lb60/qi_lb60-spl.c |
||
33 | index 3fe3fa3..aea459c 100644 |
||
34 | --- a/board/qi/qi_lb60/qi_lb60-spl.c |
||
35 | +++ b/board/qi/qi_lb60/qi_lb60-spl.c |
||
36 | @@ -12,6 +12,24 @@ |
||
37 | #include <asm/io.h> |
||
38 | #include <asm/jz4740.h> |
||
39 | |||
40 | +#define KEY_U_OUT (32 * 2 + 16) |
||
41 | +#define KEY_U_IN (32 * 3 + 19) |
||
42 | + |
||
43 | +extern void usb_boot(void); |
||
44 | + |
||
45 | +static void check_usb_boot(void) |
||
46 | +{ |
||
47 | + __gpio_as_input(KEY_U_IN); |
||
48 | + __gpio_enable_pull(KEY_U_IN); |
||
49 | + __gpio_as_output(KEY_U_OUT); |
||
50 | + __gpio_clear_pin(KEY_U_OUT); |
||
51 | + |
||
52 | + if (!__gpio_get_pin(KEY_U_IN)) { |
||
53 | + puts("[U] pressed, goto USBBOOT mode\n"); |
||
54 | + usb_boot(); |
||
55 | + } |
||
56 | +} |
||
57 | + |
||
58 | void nand_spl_boot(void) |
||
59 | { |
||
60 | __gpio_as_sdram_16bit_4720(); |
||
61 | @@ -23,6 +41,8 @@ void nand_spl_boot(void) |
||
62 | pll_init(); |
||
63 | sdram_init(); |
||
64 | |||
65 | + check_usb_boot(); |
||
66 | + |
||
67 | nand_init(); |
||
68 | |||
69 | puts("\nQi LB60 SPL: Starting U-Boot ...\n"); |
||
70 | diff --git a/board/qi/qi_lb60/usbboot.S b/board/qi/qi_lb60/usbboot.S |
||
71 | new file mode 100644 |
||
72 | index 0000000..c872266 |
||
73 | --- /dev/null |
||
74 | +++ b/board/qi/qi_lb60/usbboot.S |
||
75 | @@ -0,0 +1,838 @@ |
||
76 | +/* |
||
77 | + * for jz4740 usb boot |
||
78 | + * |
||
79 | + * Copyright (c) 2009 Author: <jlwei@ingenic.cn> |
||
80 | + * |
||
81 | + * See file CREDITS for list of people who contributed to this |
||
82 | + * project. |
||
83 | + * |
||
84 | + * This program is free software; you can redistribute it and/or |
||
85 | + * modify it under the terms of the GNU General Public License as |
||
86 | + * published by the Free Software Foundation; either version 2 of |
||
87 | + * the License, or (at your option) any later version. |
||
88 | + * |
||
89 | + * This program is distributed in the hope that it will be useful, |
||
90 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
91 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
92 | + * GNU General Public License for more details. |
||
93 | + * |
||
94 | + * You should have received a copy of the GNU General Public License |
||
95 | + * along with this program; if not, write to the Free Software |
||
96 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||
97 | + * MA 02111-1307 USA |
||
98 | + */ |
||
99 | + .set noreorder |
||
100 | + .globl usb_boot |
||
101 | + .text |
||
102 | + |
||
103 | +/* |
||
104 | + * Both NAND and USB boot load data to D-Cache first, then transfer |
||
105 | + * data from D-Cache to I-Cache, and jump to execute the code in I-Cache. |
||
106 | + * So init caches first and then dispatch to a proper boot routine. |
||
107 | + */ |
||
108 | + |
||
109 | +.macro load_addr reg addr |
||
110 | + li \reg, 0x80000000 |
||
111 | + addiu \reg, \reg, \addr |
||
112 | + la $2, usbboot_begin |
||
113 | + subu \reg, \reg, $2 |
||
114 | +.endm |
||
115 | + |
||
116 | +usb_boot: |
||
117 | + /* Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz. */ |
||
118 | + la $9, 0xB0000000 /* CPCCR: Clock Control Register */ |
||
119 | + la $8, 0x42041110 /* I:S:M:P=1:2:2:2 */ |
||
120 | + sw $8, 0($9) |
||
121 | + |
||
122 | + la $9, 0xB0000010 /* CPPCR: PLL Control Register */ |
||
123 | + la $8, 0x06000120 /* M=12 N=0 D=0 CLK=12*(M+2)/(N+2) */ |
||
124 | + sw $8, 0($9) |
||
125 | + |
||
126 | + mtc0 $0, $26 /* CP0_ERRCTL, restore WST reset state */ |
||
127 | + nop |
||
128 | + |
||
129 | + mtc0 $0, $16 /* CP0_CONFIG */ |
||
130 | + nop |
||
131 | + |
||
132 | + /* Relocate code to beginning of the ram */ |
||
133 | + |
||
134 | + la $2, usbboot_begin |
||
135 | + la $3, usbboot_end |
||
136 | + li $4, 0x80000000 |
||
137 | + |
||
138 | +1: |
||
139 | + lw $5, 0($2) |
||
140 | + sw $5, 0($4) |
||
141 | + addiu $2, $2, 4 |
||
142 | + bne $2, $3, 1b |
||
143 | + addiu $4, $4, 4 |
||
144 | + |
||
145 | + li $2, 0x80000000 |
||
146 | + ori $3, $2, 0 |
||
147 | + addiu $3, $3, usbboot_end |
||
148 | + la $4, usbboot_begin |
||
149 | + subu $3, $3, $4 |
||
150 | + |
||
151 | + |
||
152 | +2: |
||
153 | + cache 0x0, 0($2) /* Index_Invalidate_I */ |
||
154 | + cache 0x1, 0($2) /* Index_Writeback_Inv_D */ |
||
155 | + addiu $2, $2, 32 |
||
156 | + subu $4, $3, $2 |
||
157 | + bgtz $4, 2b |
||
158 | + nop |
||
159 | + |
||
160 | + load_addr $3, usb_boot_return |
||
161 | + |
||
162 | + jr $3 |
||
163 | + |
||
164 | +usbboot_begin: |
||
165 | + |
||
166 | +init_caches: |
||
167 | + li $2, 3 /* cacheable for kseg0 access */ |
||
168 | + mtc0 $2, $16 /* CP0_CONFIG */ |
||
169 | + nop |
||
170 | + |
||
171 | + li $2, 0x20000000 /* enable idx-store-data cache insn */ |
||
172 | + mtc0 $2, $26 /* CP0_ERRCTL */ |
||
173 | + |
||
174 | + ori $2, $28, 0 /* start address */ |
||
175 | + ori $3, $2, 0x3fe0 /* end address, total 16KB */ |
||
176 | + mtc0 $0, $28, 0 /* CP0_TAGLO */ |
||
177 | + mtc0 $0, $28, 1 /* CP0_DATALO */ |
||
178 | +cache_clear_a_line: |
||
179 | + cache 0x8, 0($2) /* Index_Store_Tag_I */ |
||
180 | + cache 0x9, 0($2) /* Index_Store_Tag_D */ |
||
181 | + bne $2, $3, cache_clear_a_line |
||
182 | + addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */ |
||
183 | + |
||
184 | + ori $2, $28, 0 /* start address */ |
||
185 | + ori $3, $2, 0x3fe0 /* end address, total 16KB */ |
||
186 | + la $4, 0x1ffff000 /* physical address and 4KB page mask */ |
||
187 | +cache_alloc_a_line: |
||
188 | + and $5, $2, $4 |
||
189 | + ori $5, $5, 1 /* V bit of the physical tag */ |
||
190 | + mtc0 $5, $28, 0 /* CP0_TAGLO */ |
||
191 | + cache 0x8, 0($2) /* Index_Store_Tag_I */ |
||
192 | + cache 0x9, 0($2) /* Index_Store_Tag_D */ |
||
193 | + bne $2, $3, cache_alloc_a_line |
||
194 | + addiu $2, $2, 32 /* increment CACHE_LINE_SIZE */ |
||
195 | + |
||
196 | + nop |
||
197 | + nop |
||
198 | + nop |
||
199 | + /* |
||
200 | + * Transfer data from dcache to icache, then jump to icache. |
||
201 | + * Input parameters: |
||
202 | + * $19: data length in bytes |
||
203 | + * $20: jump target address |
||
204 | + */ |
||
205 | +xfer_d2i: |
||
206 | + |
||
207 | + ori $8, $20, 0 |
||
208 | + addu $9, $8, $19 /* total 16KB */ |
||
209 | + |
||
210 | +1: |
||
211 | + cache 0x0, 0($8) /* Index_Invalidate_I */ |
||
212 | + cache 0x1, 0($8) /* Index_Writeback_Inv_D */ |
||
213 | + bne $8, $9, 1b |
||
214 | + addiu $8, $8, 32 |
||
215 | + |
||
216 | + /* flush write-buffer */ |
||
217 | + sync |
||
218 | + |
||
219 | + /* Invalidate BTB */ |
||
220 | + mfc0 $8, $16, 7 /* CP0_CONFIG */ |
||
221 | + nop |
||
222 | + ori $8, 2 |
||
223 | + mtc0 $8, $16, 7 |
||
224 | + nop |
||
225 | + |
||
226 | + /* Overwrite config to disable ram initalisation */ |
||
227 | + li $2, 0xff |
||
228 | + sb $2, 20($20) |
||
229 | + |
||
230 | + jalr $20 |
||
231 | + nop |
||
232 | + |
||
233 | +icache_return: |
||
234 | + /* User code can return to here after executing itself in |
||
235 | + icache, by jumping to $31. */ |
||
236 | + b usb_boot_return |
||
237 | + nop |
||
238 | + |
||
239 | + |
||
240 | +usb_boot_return: |
||
241 | + /* Enable the USB PHY */ |
||
242 | + la $9, 0xB0000024 /* CPM_SCR */ |
||
243 | + lw $8, 0($9) |
||
244 | + ori $8, 0x40 /* USBPHY_ENABLE */ |
||
245 | + sw $8, 0($9) |
||
246 | + |
||
247 | + /* Initialize USB registers */ |
||
248 | + la $27, 0xb3040000 /* USB registers base address */ |
||
249 | + |
||
250 | + sb $0, 0x0b($27) /* INTRUSBE: disable common USB interrupts */ |
||
251 | + sh $0, 0x06($27) /* INTRINE: disable EPIN interrutps */ |
||
252 | + sh $0, 0x08($27) /* INTROUTE: disable EPOUT interrutps */ |
||
253 | + |
||
254 | + li $9, 0x61 |
||
255 | + sb $9, 0x01($27) /* POWER: HSENAB | SUSPENDM | SOFTCONN */ |
||
256 | + |
||
257 | + /* Initialize USB states */ |
||
258 | + li $22, 0 /* set EP0 to IDLE state */ |
||
259 | + li $23, 1 /* no data stage */ |
||
260 | + |
||
261 | + /* Main loop of polling the usb commands */ |
||
262 | +usb_command_loop: |
||
263 | + lbu $9, 0x0a($27) /* read INTRUSB */ |
||
264 | + andi $9, 0x04 /* check USB_INTR_RESET */ |
||
265 | + beqz $9, check_intr_ep0in |
||
266 | + nop |
||
267 | + |
||
268 | + /* 1. Handle USB reset interrupt */ |
||
269 | +handle_reset_intr: |
||
270 | + lbu $9, 0x01($27) /* read POWER */ |
||
271 | + andi $9, 0x10 /* test HS_MODE */ |
||
272 | + bnez $9, _usb_set_maxpktsize |
||
273 | + li $9, 512 /* max packet size of HS mode */ |
||
274 | + li $9, 64 /* max packet size of FS mode */ |
||
275 | + |
||
276 | +_usb_set_maxpktsize: |
||
277 | + li $8, 1 |
||
278 | + sb $8, 0x0e($27) /* set INDEX 1 */ |
||
279 | + |
||
280 | + sh $9, 0x10($27) /* INMAXP */ |
||
281 | + sb $0, 0x13($27) /* INCSRH */ |
||
282 | + sh $9, 0x14($27) /* OUTMAXP */ |
||
283 | + sb $0, 0x17($27) /* OUTCSRH */ |
||
284 | + |
||
285 | +_usb_flush_fifo: |
||
286 | + li $8, 0x48 /* INCSR_CDT && INCSR_FF */ |
||
287 | + sb $8, 0x12($27) /* INCSR */ |
||
288 | + li $8, 0x90 /* OUTCSR_CDT && OUTCSR_FF */ |
||
289 | + sb $8, 0x16($27) /* OUTCSR */ |
||
290 | + |
||
291 | + li $22, 0 /* set EP0 to IDLE state */ |
||
292 | + li $23, 1 /* no data stage */ |
||
293 | + |
||
294 | + /* 2. Check and handle EP0 interrupt */ |
||
295 | +check_intr_ep0in: |
||
296 | + lhu $10, 0x02($27) /* read INTRIN */ |
||
297 | + andi $9, $10, 0x1 /* check EP0 interrupt */ |
||
298 | + beqz $9, check_intr_ep1in |
||
299 | + nop |
||
300 | + |
||
301 | +handle_ep0_intr: |
||
302 | + sb $0, 0x0e($27) /* set INDEX 0 */ |
||
303 | + lbu $11, 0x12($27) /* read CSR0 */ |
||
304 | + |
||
305 | + andi $9, $11, 0x04 /* check SENTSTALL */ |
||
306 | + beqz $9, _ep0_setupend |
||
307 | + nop |
||
308 | + |
||
309 | +_ep0_sentstall: |
||
310 | + andi $9, $11, 0xdb |
||
311 | + sb $9, 0x12($27) /* clear SENDSTALL and SENTSTALL */ |
||
312 | + li $22, 0 /* set EP0 to IDLE state */ |
||
313 | + |
||
314 | +_ep0_setupend: |
||
315 | + andi $9, $11, 0x10 /* check SETUPEND */ |
||
316 | + beqz $9, ep0_idle_state |
||
317 | + nop |
||
318 | + |
||
319 | + ori $9, $11, 0x80 |
||
320 | + sb $9, 0x12($27) /* set SVDSETUPEND */ |
||
321 | + li $22, 0 /* set EP0 to IDLE state */ |
||
322 | + |
||
323 | +ep0_idle_state: |
||
324 | + bnez $22, ep0_tx_state |
||
325 | + nop |
||
326 | + |
||
327 | + /* 2.1 Handle EP0 IDLE state interrupt */ |
||
328 | + andi $9, $11, 0x01 /* check OUTPKTRDY */ |
||
329 | + beqz $9, check_intr_ep1in |
||
330 | + nop |
||
331 | + |
||
332 | + /* Read 8-bytes setup packet from the FIFO */ |
||
333 | + lw $25, 0x20($27) /* first word of setup packet */ |
||
334 | + lw $26, 0x20($27) /* second word of setup packet */ |
||
335 | + |
||
336 | + andi $9, $25, 0x60 /* bRequestType & USB_TYPE_MASK */ |
||
337 | + beqz $9, _ep0_std_req |
||
338 | + nop |
||
339 | + |
||
340 | + /* 2.1.1 Vendor-specific setup request */ |
||
341 | +_ep0_vend_req: |
||
342 | + li $22, 0 /* set EP0 to IDLE state */ |
||
343 | + li $23, 1 /* NoData = 1 */ |
||
344 | + |
||
345 | + andi $9, $25, 0xff00 /* check bRequest */ |
||
346 | + srl $9, $9, 8 |
||
347 | + beqz $9, __ep0_get_cpu_info |
||
348 | + sub $8, $9, 0x1 |
||
349 | + beqz $8, __ep0_set_data_address |
||
350 | + sub $8, $9, 0x2 |
||
351 | + beqz $8, __ep0_set_data_length |
||
352 | + sub $8, $9, 0x3 |
||
353 | + beqz $8, __ep0_flush_caches |
||
354 | + sub $8, $9, 0x4 |
||
355 | + beqz $8, __ep0_prog_start1 |
||
356 | + sub $8, $9, 0x5 |
||
357 | + beqz $8, __ep0_prog_start2 |
||
358 | + nop |
||
359 | + b _ep0_idle_state_fini /* invalid request */ |
||
360 | + nop |
||
361 | + |
||
362 | +__ep0_get_cpu_info: |
||
363 | + load_addr $20, cpu_info_data /* data pointer to transfer */ |
||
364 | + li $21, 8 /* bytes left to transfer */ |
||
365 | + li $22, 1 /* set EP0 to TX state */ |
||
366 | + li $23, 0 /* NoData = 0 */ |
||
367 | + |
||
368 | + b _ep0_idle_state_fini |
||
369 | + nop |
||
370 | + |
||
371 | +__ep0_set_data_address: |
||
372 | + li $9, 0xffff0000 |
||
373 | + and $9, $25, $9 |
||
374 | + andi $8, $26, 0xffff |
||
375 | + or $20, $9, $8 /* data address of next transfer */ |
||
376 | + |
||
377 | + b _ep0_idle_state_fini |
||
378 | + nop |
||
379 | + |
||
380 | +__ep0_set_data_length: |
||
381 | + li $9, 0xffff0000 |
||
382 | + and $9, $25, $9 |
||
383 | + andi $8, $26, 0xffff |
||
384 | + or $21, $9, $8 /* data length of next transfer */ |
||
385 | + |
||
386 | + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */ |
||
387 | + sb $9, 0x12($27) /* CSR0 */ |
||
388 | + |
||
389 | + /* We must write packet to FIFO before EP1-IN interrupt here. */ |
||
390 | + b handle_epin1_intr |
||
391 | + nop |
||
392 | + |
||
393 | +__ep0_flush_caches: |
||
394 | + /* Flush dcache and invalidate icache. */ |
||
395 | + li $8, 0x80000000 |
||
396 | + addi $9, $8, 0x3fe0 /* total 16KB */ |
||
397 | + |
||
398 | +1: |
||
399 | + cache 0x0, 0($8) /* Index_Invalidate_I */ |
||
400 | + cache 0x1, 0($8) /* Index_Writeback_Inv_D */ |
||
401 | + bne $8, $9, 1b |
||
402 | + addiu $8, $8, 32 |
||
403 | + |
||
404 | + /* flush write-buffer */ |
||
405 | + sync |
||
406 | + |
||
407 | + /* Invalidate BTB */ |
||
408 | + mfc0 $8, $16, 7 /* CP0_CONFIG */ |
||
409 | + nop |
||
410 | + ori $8, 2 |
||
411 | + mtc0 $8, $16, 7 |
||
412 | + nop |
||
413 | + |
||
414 | + b _ep0_idle_state_fini |
||
415 | + nop |
||
416 | + |
||
417 | +__ep0_prog_start1: |
||
418 | + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */ |
||
419 | + sb $9, 0x12($27) /* CSR0 */ |
||
420 | + |
||
421 | + li $9, 0xffff0000 |
||
422 | + and $9, $25, $9 |
||
423 | + andi $8, $26, 0xffff |
||
424 | + or $20, $9, $8 /* target address */ |
||
425 | + |
||
426 | + b xfer_d2i |
||
427 | + li $19, 0x2000 /* 16KB data length */ |
||
428 | + |
||
429 | +__ep0_prog_start2: |
||
430 | + li $9, 0x48 /* SVDOUTPKTRDY and DATAEND */ |
||
431 | + sb $9, 0x12($27) /* CSR0 */ |
||
432 | + |
||
433 | + li $9, 0xffff0000 |
||
434 | + and $9, $25, $9 |
||
435 | + andi $8, $26, 0xffff |
||
436 | + or $20, $9, $8 /* target address */ |
||
437 | + |
||
438 | + jalr $20 /* jump, and place the return address in $31 */ |
||
439 | + nop |
||
440 | + |
||
441 | +__ep0_prog_start2_return: |
||
442 | +/* User code can return to here after executing itself, by jumping to $31 */ |
||
443 | + b usb_boot_return |
||
444 | + nop |
||
445 | + |
||
446 | + /* 2.1.2 Standard setup request */ |
||
447 | +_ep0_std_req: |
||
448 | + andi $12, $25, 0xff00 /* check bRequest */ |
||
449 | + srl $12, $12, 8 |
||
450 | + sub $9, $12, 0x05 /* check USB_REQ_SET_ADDRESS */ |
||
451 | + bnez $9, __ep0_req_set_config |
||
452 | + nop |
||
453 | + |
||
454 | + /* Handle USB_REQ_SET_ADDRESS */ |
||
455 | +__ep0_req_set_addr: |
||
456 | + srl $9, $25, 16 /* get wValue */ |
||
457 | + sb $9, 0x0($27) /* set FADDR */ |
||
458 | + li $23, 1 /* NoData = 1 */ |
||
459 | + b _ep0_idle_state_fini |
||
460 | + nop |
||
461 | + |
||
462 | +__ep0_req_set_config: |
||
463 | + sub $9, $12, 0x09 /* check USB_REQ_SET_CONFIGURATION */ |
||
464 | + bnez $9, __ep0_req_get_desc |
||
465 | + nop |
||
466 | + |
||
467 | + /* Handle USB_REQ_SET_CONFIGURATION */ |
||
468 | + li $23, 1 /* NoData = 1 */ |
||
469 | + b _ep0_idle_state_fini |
||
470 | + nop |
||
471 | + |
||
472 | +__ep0_req_get_desc: |
||
473 | + sub $9, $12, 0x06 /* check USB_REQ_GET_DESCRIPTOR */ |
||
474 | + bnez $9, _ep0_idle_state_fini |
||
475 | + li $23, 1 /* NoData = 1 */ |
||
476 | + |
||
477 | + /* Handle USB_REQ_GET_DESCRIPTOR */ |
||
478 | + li $23, 0 /* NoData = 0 */ |
||
479 | + |
||
480 | + srl $9, $25, 24 /* wValue >> 8 */ |
||
481 | + sub $8, $9, 0x01 /* check USB_DT_DEVICE */ |
||
482 | + beqz $8, ___ep0_get_dev_desc |
||
483 | + srl $21, $26, 16 /* get wLength */ |
||
484 | + sub $8, $9, 0x02 /* check USB_DT_CONFIG */ |
||
485 | + beqz $8, ___ep0_get_conf_desc |
||
486 | + sub $8, $9, 0x03 /* check USB_DT_STRING */ |
||
487 | + beqz $8, ___ep0_get_string_desc |
||
488 | + sub $8, $9, 0x06 /* check USB_DT_DEVICE_QUALIFIER */ |
||
489 | + beqz $8, ___ep0_get_dev_qualifier |
||
490 | + nop |
||
491 | + b _ep0_idle_state_fini |
||
492 | + nop |
||
493 | + |
||
494 | +___ep0_get_dev_desc: |
||
495 | + load_addr $20, device_desc /* data pointer */ |
||
496 | + li $22, 1 /* set EP0 to TX state */ |
||
497 | + sub $8, $21, 18 |
||
498 | + blez $8, _ep0_idle_state_fini /* wLength <= 18 */ |
||
499 | + nop |
||
500 | + li $21, 18 /* max length of device_desc */ |
||
501 | + b _ep0_idle_state_fini |
||
502 | + nop |
||
503 | + |
||
504 | +___ep0_get_dev_qualifier: |
||
505 | + load_addr $20, dev_qualifier /* data pointer */ |
||
506 | + li $22, 1 /* set EP0 to TX state */ |
||
507 | + sub $8, $21, 10 |
||
508 | + blez $8, _ep0_idle_state_fini /* wLength <= 10 */ |
||
509 | + nop |
||
510 | + li $21, 10 /* max length of dev_qualifier */ |
||
511 | + b _ep0_idle_state_fini |
||
512 | + nop |
||
513 | + |
||
514 | +___ep0_get_conf_desc: |
||
515 | + load_addr $20, config_desc_fs /* data pointer of FS mode */ |
||
516 | + lbu $8, 0x01($27) /* read POWER */ |
||
517 | + andi $8, 0x10 /* test HS_MODE */ |
||
518 | + beqz $8, ___ep0_get_conf_desc2 |
||
519 | + nop |
||
520 | + load_addr $20, config_desc_hs /* data pointer of HS mode */ |
||
521 | + |
||
522 | +___ep0_get_conf_desc2: |
||
523 | + li $22, 1 /* set EP0 to TX state */ |
||
524 | + sub $8, $21, 32 |
||
525 | + blez $8, _ep0_idle_state_fini /* wLength <= 32 */ |
||
526 | + nop |
||
527 | + li $21, 32 /* max length of config_desc */ |
||
528 | + b _ep0_idle_state_fini |
||
529 | + nop |
||
530 | + |
||
531 | +___ep0_get_string_desc: |
||
532 | + li $22, 1 /* set EP0 to TX state */ |
||
533 | + |
||
534 | + srl $9, $25, 16 /* wValue & 0xff */ |
||
535 | + andi $9, 0xff |
||
536 | + |
||
537 | + sub $8, $9, 1 |
||
538 | + beqz $8, ___ep0_get_string_manufacture |
||
539 | + sub $8, $9, 2 |
||
540 | + beqz $8, ___ep0_get_string_product |
||
541 | + nop |
||
542 | + |
||
543 | +___ep0_get_string_lang_ids: |
||
544 | + load_addr $20, string_lang_ids /* data pointer */ |
||
545 | + b _ep0_idle_state_fini |
||
546 | + li $21, 4 /* data length */ |
||
547 | + |
||
548 | +___ep0_get_string_manufacture: |
||
549 | + load_addr $20, string_manufacture /* data pointer */ |
||
550 | + b _ep0_idle_state_fini |
||
551 | + li $21, 16 /* data length */ |
||
552 | + |
||
553 | +___ep0_get_string_product: |
||
554 | + load_addr $20, string_product /* data pointer */ |
||
555 | + b _ep0_idle_state_fini |
||
556 | + li $21, 46 /* data length */ |
||
557 | + |
||
558 | +_ep0_idle_state_fini: |
||
559 | + li $9, 0x40 /* SVDOUTPKTRDY */ |
||
560 | + beqz $23, _ep0_idle_state_fini2 |
||
561 | + nop |
||
562 | + ori $9, $9, 0x08 /* DATAEND */ |
||
563 | +_ep0_idle_state_fini2: |
||
564 | + sb $9, 0x12($27) /* CSR0 */ |
||
565 | + beqz $22, check_intr_ep1in |
||
566 | + nop |
||
567 | + |
||
568 | + /* 2.2 Handle EP0 TX state interrupt */ |
||
569 | +ep0_tx_state: |
||
570 | + sub $9, $22, 1 |
||
571 | + bnez $9, check_intr_ep1in |
||
572 | + nop |
||
573 | + |
||
574 | + sub $9, $21, 64 /* max packetsize */ |
||
575 | + blez $9, _ep0_tx_state2 /* data count <= 64 */ |
||
576 | + ori $19, $21, 0 |
||
577 | + li $19, 64 |
||
578 | + |
||
579 | +_ep0_tx_state2: |
||
580 | + beqz $19, _ep0_tx_state3 /* send ZLP */ |
||
581 | + ori $18, $19, 0 /* record bytes to be transferred */ |
||
582 | + sub $21, $21, $19 /* decrement data count */ |
||
583 | + |
||
584 | +_ep0_fifo_write_loop: |
||
585 | + lbu $9, 0($20) /* read data */ |
||
586 | + sb $9, 0x20($27) /* load FIFO */ |
||
587 | + sub $19, $19, 1 /* decrement counter */ |
||
588 | + bnez $19, _ep0_fifo_write_loop |
||
589 | + addi $20, $20, 1 /* increment data pointer */ |
||
590 | + |
||
591 | + sub $9, $18, 64 /* max packetsize */ |
||
592 | + beqz $9, _ep0_tx_state4 |
||
593 | + nop |
||
594 | + |
||
595 | +_ep0_tx_state3: |
||
596 | + /* transferred bytes < max packetsize */ |
||
597 | + li $9, 0x0a /* set INPKTRDY and DATAEND */ |
||
598 | + sb $9, 0x12($27) /* CSR0 */ |
||
599 | + li $22, 0 /* set EP0 to IDLE state */ |
||
600 | + b check_intr_ep1in |
||
601 | + nop |
||
602 | + |
||
603 | +_ep0_tx_state4: |
||
604 | + /* transferred bytes == max packetsize */ |
||
605 | + li $9, 0x02 /* set INPKTRDY */ |
||
606 | + sb $9, 0x12($27) /* CSR0 */ |
||
607 | + b check_intr_ep1in |
||
608 | + nop |
||
609 | + |
||
610 | + /* 3. Check and handle EP1 BULK-IN interrupt */ |
||
611 | +check_intr_ep1in: |
||
612 | + andi $9, $10, 0x2 /* check EP1 IN interrupt */ |
||
613 | + beqz $9, check_intr_ep1out |
||
614 | + nop |
||
615 | + |
||
616 | +handle_epin1_intr: |
||
617 | + li $9, 1 |
||
618 | + sb $9, 0x0e($27) /* set INDEX 1 */ |
||
619 | + lbu $9, 0x12($27) /* read INCSR */ |
||
620 | + |
||
621 | + andi $8, $9, 0x2 /* check INCSR_FFNOTEMPT */ |
||
622 | + bnez $8, _epin1_tx_state4 |
||
623 | + nop |
||
624 | + |
||
625 | +_epin1_write_fifo: |
||
626 | + lhu $9, 0x10($27) /* get INMAXP */ |
||
627 | + sub $8, $21, $9 |
||
628 | + blez $8, _epin1_tx_state1 /* bytes left <= INMAXP */ |
||
629 | + ori $19, $21, 0 |
||
630 | + ori $19, $9, 0 |
||
631 | + |
||
632 | +_epin1_tx_state1: |
||
633 | + beqz $19, _epin1_tx_state4 /* No data */ |
||
634 | + nop |
||
635 | + |
||
636 | + sub $21, $21, $19 /* decrement data count */ |
||
637 | + |
||
638 | + srl $5, $19, 2 /* # of word */ |
||
639 | + andi $6, $19, 0x3 /* # of byte */ |
||
640 | + beqz $5, _epin1_tx_state2 |
||
641 | + nop |
||
642 | + |
||
643 | +_epin1_fifo_write_word: |
||
644 | + lw $9, 0($20) /* read data from source address */ |
||
645 | + sw $9, 0x24($27) /* write FIFO */ |
||
646 | + sub $5, $5, 1 /* decrement counter */ |
||
647 | + bnez $5, _epin1_fifo_write_word |
||
648 | + addiu $20, $20, 4 /* increment dest address */ |
||
649 | + |
||
650 | +_epin1_tx_state2: |
||
651 | + beqz $6, _epin1_tx_state3 |
||
652 | + nop |
||
653 | + |
||
654 | +_epin1_fifo_write_byte: |
||
655 | + lbu $9, 0($20) /* read data from source address */ |
||
656 | + sb $9, 0x24($27) /* write FIFO */ |
||
657 | + sub $6, $6, 1 /* decrement counter */ |
||
658 | + bnez $6, _epin1_fifo_write_byte |
||
659 | + addiu $20, $20, 1 /* increment dest address */ |
||
660 | + |
||
661 | +_epin1_tx_state3: |
||
662 | + li $9, 0x1 |
||
663 | + sb $9, 0x12($27) /* INCSR, set INPKTRDY */ |
||
664 | + |
||
665 | +_epin1_tx_state4: |
||
666 | + /* 4. Check and handle EP1 BULK-OUT interrupt */ |
||
667 | +check_intr_ep1out: |
||
668 | + lhu $9, 0x04($27) /* read INTROUT */ |
||
669 | + andi $9, 0x2 |
||
670 | + beqz $9, check_status_next |
||
671 | + nop |
||
672 | + |
||
673 | +handle_epout1_intr: |
||
674 | + li $9, 1 |
||
675 | + sb $9, 0x0e($27) /* set INDEX 1 */ |
||
676 | + |
||
677 | + lbu $9, 0x16($27) /* read OUTCSR */ |
||
678 | + andi $9, 0x1 /* check OUTPKTRDY */ |
||
679 | + beqz $9, check_status_next |
||
680 | + nop |
||
681 | + |
||
682 | +_epout1_read_fifo: |
||
683 | + lhu $19, 0x18($27) /* read OUTCOUNT */ |
||
684 | + srl $5, $19, 2 /* # of word */ |
||
685 | + andi $6, $19, 0x3 /* # of byte */ |
||
686 | + beqz $5, _epout1_rx_state1 |
||
687 | + nop |
||
688 | + |
||
689 | +_epout1_fifo_read_word: |
||
690 | + lw $9, 0x24($27) /* read FIFO */ |
||
691 | + sw $9, 0($20) /* store to dest address */ |
||
692 | + sub $5, $5, 1 /* decrement counter */ |
||
693 | + bnez $5, _epout1_fifo_read_word |
||
694 | + addiu $20, $20, 4 /* increment dest address */ |
||
695 | + |
||
696 | +_epout1_rx_state1: |
||
697 | + beqz $6, _epout1_rx_state2 |
||
698 | + nop |
||
699 | + |
||
700 | +_epout1_fifo_read_byte: |
||
701 | + lbu $9, 0x24($27) /* read FIFO */ |
||
702 | + sb $9, 0($20) /* store to dest address */ |
||
703 | + sub $6, $6, 1 /* decrement counter */ |
||
704 | + bnez $6, _epout1_fifo_read_byte |
||
705 | + addiu $20, $20, 1 /* increment dest address */ |
||
706 | + |
||
707 | +_epout1_rx_state2: |
||
708 | + sb $0, 0x16($27) /* clear OUTPKTRDY */ |
||
709 | + |
||
710 | +check_status_next: |
||
711 | + b usb_command_loop |
||
712 | + nop |
||
713 | + |
||
714 | +/* Device/Configuration/Interface/Endpoint/String Descriptors */ |
||
715 | + |
||
716 | + .align 2 |
||
717 | +device_desc: |
||
718 | + .byte 0x12 /* bLength */ |
||
719 | + .byte 0x01 /* bDescriptorType */ |
||
720 | + .byte 0x00 /* bcdUSB */ |
||
721 | + .byte 0x02 /* bcdUSB */ |
||
722 | + .byte 0x00 /* bDeviceClass */ |
||
723 | + .byte 0x00 /* bDeviceSubClass */ |
||
724 | + .byte 0x00 /* bDeviceProtocol */ |
||
725 | + .byte 0x40 /* bMaxPacketSize0 */ |
||
726 | + .byte 0x1a /* idVendor */ |
||
727 | + .byte 0x60 /* idVendor */ |
||
728 | + .byte 0x40 /* idProduct */ |
||
729 | + .byte 0x47 /* idProduct */ |
||
730 | + .byte 0x00 /* bcdDevice */ |
||
731 | + .byte 0x01 /* bcdDevice */ |
||
732 | + .byte 0x01 /* iManufacturer */ |
||
733 | + .byte 0x02 /* iProduct */ |
||
734 | + .byte 0x00 /* iSerialNumber */ |
||
735 | + .byte 0x01 /* bNumConfigurations */ |
||
736 | + |
||
737 | + .align 2 |
||
738 | +dev_qualifier: |
||
739 | + .byte 0x0a /* bLength */ |
||
740 | + .byte 0x06 /* bDescriptorType */ |
||
741 | + .byte 0x00 /* bcdUSB */ |
||
742 | + .byte 0x02 /* bcdUSB */ |
||
743 | + .byte 0x00 /* bDeviceClass */ |
||
744 | + .byte 0x00 /* bDeviceSubClass */ |
||
745 | + .byte 0x00 /* bDeviceProtocol */ |
||
746 | + .byte 0x40 /* bMaxPacketSize0 */ |
||
747 | + .byte 0x01 /* bNumConfigurations */ |
||
748 | + .byte 0x00 /* bRESERVED */ |
||
749 | + |
||
750 | + .align 2 |
||
751 | +config_desc_hs: |
||
752 | + .byte 0x09 /* bLength */ |
||
753 | + .byte 0x02 /* bDescriptorType */ |
||
754 | + .byte 0x20 /* wTotalLength */ |
||
755 | + .byte 0x00 /* wTotalLength */ |
||
756 | + .byte 0x01 /* bNumInterfaces */ |
||
757 | + .byte 0x01 /* bConfigurationValue */ |
||
758 | + .byte 0x00 /* iConfiguration */ |
||
759 | + .byte 0xc0 /* bmAttributes */ |
||
760 | + .byte 0x01 /* MaxPower */ |
||
761 | +intf_desc_hs: |
||
762 | + .byte 0x09 /* bLength */ |
||
763 | + .byte 0x04 /* bDescriptorType */ |
||
764 | + .byte 0x00 /* bInterfaceNumber */ |
||
765 | + .byte 0x00 /* bAlternateSetting */ |
||
766 | + .byte 0x02 /* bNumEndpoints */ |
||
767 | + .byte 0xff /* bInterfaceClass */ |
||
768 | + .byte 0x00 /* bInterfaceSubClass */ |
||
769 | + .byte 0x50 /* bInterfaceProtocol */ |
||
770 | + .byte 0x00 /* iInterface */ |
||
771 | +ep1_desc_hs: |
||
772 | + .byte 0x07 /* bLength */ |
||
773 | + .byte 0x05 /* bDescriptorType */ |
||
774 | + .byte 0x01 /* bEndpointAddress */ |
||
775 | + .byte 0x02 /* bmAttributes */ |
||
776 | + .byte 0x00 /* wMaxPacketSize */ |
||
777 | + .byte 0x02 /* wMaxPacketSize */ |
||
778 | + .byte 0x00 /* bInterval */ |
||
779 | +ep2_desc_hs: |
||
780 | + .byte 0x07 /* bLength */ |
||
781 | + .byte 0x05 /* bDescriptorType */ |
||
782 | + .byte 0x81 /* bEndpointAddress */ |
||
783 | + .byte 0x02 /* bmAttributes */ |
||
784 | + .byte 0x00 /* wMaxPacketSize */ |
||
785 | + .byte 0x02 /* wMaxPacketSize */ |
||
786 | + .byte 0x00 /* bInterval */ |
||
787 | + |
||
788 | + .align 2 |
||
789 | +config_desc_fs: |
||
790 | + .byte 0x09 /* bLength */ |
||
791 | + .byte 0x02 /* bDescriptorType */ |
||
792 | + .byte 0x20 /* wTotalLength */ |
||
793 | + .byte 0x00 /* wTotalLength */ |
||
794 | + .byte 0x01 /* bNumInterfaces */ |
||
795 | + .byte 0x01 /* bConfigurationValue */ |
||
796 | + .byte 0x00 /* iConfiguration */ |
||
797 | + .byte 0xc0 /* bmAttributes */ |
||
798 | + .byte 0x01 /* MaxPower */ |
||
799 | +intf_desc_fs: |
||
800 | + .byte 0x09 /* bLength */ |
||
801 | + .byte 0x04 /* bDescriptorType */ |
||
802 | + .byte 0x00 /* bInterfaceNumber */ |
||
803 | + .byte 0x00 /* bAlternateSetting */ |
||
804 | + .byte 0x02 /* bNumEndpoints */ |
||
805 | + .byte 0xff /* bInterfaceClass */ |
||
806 | + .byte 0x00 /* bInterfaceSubClass */ |
||
807 | + .byte 0x50 /* bInterfaceProtocol */ |
||
808 | + .byte 0x00 /* iInterface */ |
||
809 | +ep1_desc_fs: |
||
810 | + .byte 0x07 /* bLength */ |
||
811 | + .byte 0x05 /* bDescriptorType */ |
||
812 | + .byte 0x01 /* bEndpointAddress */ |
||
813 | + .byte 0x02 /* bmAttributes */ |
||
814 | + .byte 0x40 /* wMaxPacketSize */ |
||
815 | + .byte 0x00 /* wMaxPacketSize */ |
||
816 | + .byte 0x00 /* bInterval */ |
||
817 | +ep2_desc_fs: |
||
818 | + .byte 0x07 /* bLength */ |
||
819 | + .byte 0x05 /* bDescriptorType */ |
||
820 | + .byte 0x81 /* bEndpointAddress */ |
||
821 | + .byte 0x02 /* bmAttributes */ |
||
822 | + .byte 0x40 /* wMaxPacketSize */ |
||
823 | + .byte 0x00 /* wMaxPacketSize */ |
||
824 | + .byte 0x00 /* bInterval */ |
||
825 | + |
||
826 | + .align 2 |
||
827 | +string_lang_ids: |
||
828 | + .byte 0x04 |
||
829 | + .byte 0x03 |
||
830 | + .byte 0x09 |
||
831 | + .byte 0x04 |
||
832 | + |
||
833 | + .align 2 |
||
834 | +string_manufacture: |
||
835 | + .byte 0x10 |
||
836 | + .byte 0x03 |
||
837 | + .byte 0x49 |
||
838 | + .byte 0x00 |
||
839 | + .byte 0x6e |
||
840 | + .byte 0x00 |
||
841 | + .byte 0x67 |
||
842 | + .byte 0x00 |
||
843 | + .byte 0x65 |
||
844 | + .byte 0x00 |
||
845 | + .byte 0x6e |
||
846 | + .byte 0x00 |
||
847 | + .byte 0x69 |
||
848 | + .byte 0x00 |
||
849 | + .byte 0x63 |
||
850 | + .byte 0x00 |
||
851 | + |
||
852 | + .align 2 |
||
853 | +string_product: |
||
854 | + .byte 0x2e |
||
855 | + .byte 0x03 |
||
856 | + .byte 0x4a |
||
857 | + .byte 0x00 |
||
858 | + .byte 0x5a |
||
859 | + .byte 0x00 |
||
860 | + .byte 0x34 |
||
861 | + .byte 0x00 |
||
862 | + .byte 0x37 |
||
863 | + .byte 0x00 |
||
864 | + .byte 0x34 |
||
865 | + .byte 0x00 |
||
866 | + .byte 0x30 |
||
867 | + .byte 0x00 |
||
868 | + .byte 0x20 |
||
869 | + .byte 0x00 |
||
870 | + .byte 0x55 |
||
871 | + .byte 0x00 |
||
872 | + .byte 0x53 |
||
873 | + .byte 0x00 |
||
874 | + .byte 0x42 |
||
875 | + .byte 0x00 |
||
876 | + .byte 0x20 |
||
877 | + .byte 0x00 |
||
878 | + .byte 0x42 |
||
879 | + .byte 0x00 |
||
880 | + .byte 0x6f |
||
881 | + .byte 0x00 |
||
882 | + .byte 0x6f |
||
883 | + .byte 0x00 |
||
884 | + .byte 0x74 |
||
885 | + .byte 0x00 |
||
886 | + .byte 0x20 |
||
887 | + .byte 0x00 |
||
888 | + .byte 0x44 |
||
889 | + .byte 0x00 |
||
890 | + .byte 0x65 |
||
891 | + .byte 0x00 |
||
892 | + .byte 0x76 |
||
893 | + .byte 0x00 |
||
894 | + .byte 0x69 |
||
895 | + .byte 0x00 |
||
896 | + .byte 0x63 |
||
897 | + .byte 0x00 |
||
898 | + .byte 0x65 |
||
899 | + .byte 0x00 |
||
900 | + |
||
901 | + .align 2 |
||
902 | +cpu_info_data: |
||
903 | + .byte 0x4a |
||
904 | + .byte 0x5a |
||
905 | + .byte 0x34 |
||
906 | + .byte 0x37 |
||
907 | + .byte 0x34 |
||
908 | + .byte 0x30 |
||
909 | + .byte 0x56 |
||
910 | + .byte 0x31 |
||
911 | +usbboot_end: |
||
912 | + |
||
913 | + .set reorder |
||
914 | -- |
||
915 | 1.7.9.5 |
||
916 |