This patch updates uboot-xburst from 2009.11 to 2012.10-rc2 - Ingenic SoC support...
[15.05/openwrt.git] / package / boot / uboot-xburst / patches / 0002-qi_lb60-add-software-usbboot-support.patch
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