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 | |
917 | |