move boot related packages to their own folder
[openwrt/openwrt.git] / package / boot / uboot-xburst / files / cpu / mips / usb_boot.S
diff --git a/package/boot/uboot-xburst/files/cpu/mips/usb_boot.S b/package/boot/uboot-xburst/files/cpu/mips/usb_boot.S
new file mode 100644 (file)
index 0000000..107b928
--- /dev/null
@@ -0,0 +1,880 @@
+/*
+ *  for jz4740 usb boot
+ *
+ *  Copyright (c) 2009 Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+    .set noreorder
+    .globl usb_boot
+    .text
+
+//----------------------------------------------------------------------
+// Both NAND and USB boot load data to D-Cache first, then transfer
+// data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
+// So init caches first and then dispatch to a proper boot routine.
+//----------------------------------------------------------------------
+
+.macro load_addr reg addr
+       li \reg, 0x80000000
+       addiu \reg, \reg, \addr
+       la $2, usbboot_begin
+       subu \reg, \reg, $2
+.endm
+
+usb_boot:
+       //--------------------------------------------------------------
+       // Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
+       //--------------------------------------------------------------
+       la      $9, 0xB0000000          // CPCCR: Clock Control Register
+       la      $8, 0x42041110          // I:S:M:P=1:2:2:2
+       sw      $8, 0($9)
+
+       la      $9, 0xB0000010          // CPPCR: PLL Control Register
+       la      $8, 0x06000120          // M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
+       sw      $8, 0($9)
+
+       mtc0    $0, $26                 // CP0_ERRCTL, restore WST reset state
+       nop
+
+       mtc0    $0, $16                 // CP0_CONFIG
+       nop
+
+       // Relocate code to beginning of the ram
+
+       la $2, usbboot_begin
+       la $3, usbboot_end
+       li $4, 0x80000000
+
+1:
+       lw $5, 0($2)
+       sw $5, 0($4)
+       addiu $2, $2, 4
+       bne $2, $3, 1b
+       addiu $4, $4, 4
+
+       li $2, 0x80000000
+       ori $3, $2, 0
+       addiu $3, $3, usbboot_end
+       la $4, usbboot_begin
+       subu $3, $3, $4
+
+
+2:
+       cache   0x0, 0($2)              // Index_Invalidate_I
+       cache   0x1, 0($2)              // Index_Writeback_Inv_D
+       addiu   $2, $2, 32
+       subu $4, $3, $2
+       bgtz    $4, 2b
+       nop
+
+       load_addr $3, usb_boot_return
+
+       jr $3
+
+usbboot_begin:
+
+init_caches:
+       li      $2, 3                   // cacheable for kseg0 access
+       mtc0    $2, $16                 // CP0_CONFIG
+       nop
+
+       li      $2, 0x20000000          // enable idx-store-data cache insn
+       mtc0    $2, $26                 // CP0_ERRCTL
+
+       ori     $2, $28, 0              // start address
+       ori     $3, $2, 0x3fe0          // end address, total 16KB
+       mtc0    $0, $28, 0              // CP0_TAGLO
+       mtc0    $0, $28, 1              // CP0_DATALO
+cache_clear_a_line:
+       cache   0x8, 0($2)              // Index_Store_Tag_I
+       cache   0x9, 0($2)              // Index_Store_Tag_D
+       bne     $2, $3, cache_clear_a_line
+       addiu   $2, $2, 32              // increment CACHE_LINE_SIZE
+
+       ori     $2, $28, 0              // start address
+       ori     $3, $2, 0x3fe0          // end address, total 16KB
+       la      $4, 0x1ffff000          // physical address and 4KB page mask
+cache_alloc_a_line:
+       and     $5, $2, $4
+       ori     $5, $5, 1               // V bit of the physical tag
+       mtc0    $5, $28, 0              // CP0_TAGLO
+       cache   0x8, 0($2)              // Index_Store_Tag_I
+       cache   0x9, 0($2)              // Index_Store_Tag_D
+       bne     $2, $3, cache_alloc_a_line
+       addiu   $2, $2, 32              // increment CACHE_LINE_SIZE
+
+       nop
+       nop
+       nop
+       //--------------------------------------------------------------
+       // Transfer data from dcache to icache, then jump to icache.
+       //
+       // Input parameters:
+       //
+       // $19: data length in bytes
+       // $20: jump target address
+       //--------------------------------------------------------------
+xfer_d2i:
+
+       ori     $8, $20, 0
+       addu    $9, $8, $19             // total 16KB
+
+1:
+       cache   0x0, 0($8)              // Index_Invalidate_I
+       cache   0x1, 0($8)              // Index_Writeback_Inv_D
+       bne     $8, $9, 1b
+       addiu   $8, $8, 32
+
+       // flush write-buffer
+       sync
+
+       // Invalidate BTB
+       mfc0    $8, $16, 7              // CP0_CONFIG
+       nop
+       ori     $8, 2
+       mtc0    $8, $16, 7
+       nop
+
+       // Overwrite config to disable ram initalisation
+       li $2, 0xff
+       sb $2, 20($20)
+
+       jalr    $20
+       nop
+
+icache_return:
+       //--------------------------------------------------------------
+       // User code can return to here after executing itself in 
+       // icache, by jumping to $31.
+       //--------------------------------------------------------------
+       b       usb_boot_return
+       nop
+
+
+usb_boot_return:
+       //--------------------------------------------------------------
+       // Enable the USB PHY
+       //--------------------------------------------------------------
+       la      $9, 0xB0000024          // CPM_SCR
+       lw      $8, 0($9)
+       ori     $8, 0x40                // USBPHY_ENABLE
+       sw      $8, 0($9)
+
+       //--------------------------------------------------------------
+       // Initialize USB registers
+       //--------------------------------------------------------------
+       la      $27, 0xb3040000         // USB registers base address
+
+       sb      $0, 0x0b($27)           // INTRUSBE: disable common USB interrupts
+       sh      $0, 0x06($27)           // INTRINE: disable EPIN interrutps
+       sh      $0, 0x08($27)           // INTROUTE: disable EPOUT interrutps
+
+       li      $9, 0x61
+       sb      $9, 0x01($27)           // POWER: HSENAB | SUSPENDM | SOFTCONN
+
+       //--------------------------------------------------------------
+       // Initialize USB states
+       //--------------------------------------------------------------
+       li      $22, 0                  // set EP0 to IDLE state
+       li      $23, 1                  // no data stage
+
+       //--------------------------------------------------------------
+       // Main loop of polling the usb commands
+       //--------------------------------------------------------------
+usb_command_loop:
+       lbu     $9, 0x0a($27)           // read INTRUSB
+       andi    $9, 0x04                // check USB_INTR_RESET
+       beqz    $9, check_intr_ep0in
+       nop
+
+       //--------------------------------------------------------------
+       // 1. Handle USB reset interrupt
+       //--------------------------------------------------------------
+handle_reset_intr:
+       lbu     $9, 0x01($27)           // read POWER
+       andi    $9, 0x10                // test HS_MODE
+       bnez    $9, _usb_set_maxpktsize
+       li      $9, 512                 // max packet size of HS mode
+       li      $9, 64                  // max packet size of FS mode
+
+_usb_set_maxpktsize:
+       li      $8, 1
+       sb      $8, 0x0e($27)           // set INDEX 1
+
+       sh      $9, 0x10($27)           // INMAXP
+       sb      $0, 0x13($27)           // INCSRH
+       sh      $9, 0x14($27)           // OUTMAXP
+       sb      $0, 0x17($27)           // OUTCSRH
+
+_usb_flush_fifo:
+       li      $8, 0x48                // INCSR_CDT && INCSR_FF
+       sb      $8, 0x12($27)           // INCSR
+       li      $8, 0x90                // OUTCSR_CDT && OUTCSR_FF
+       sb      $8, 0x16($27)           // OUTCSR
+
+       li      $22, 0                  // set EP0 to IDLE state
+       li      $23, 1                  // no data stage
+
+       //--------------------------------------------------------------
+       // 2. Check and handle EP0 interrupt
+       //--------------------------------------------------------------
+check_intr_ep0in:
+       lhu     $10, 0x02($27)          // read INTRIN
+       andi    $9, $10, 0x1            // check EP0 interrupt
+       beqz    $9, check_intr_ep1in
+       nop
+
+handle_ep0_intr:
+       sb      $0, 0x0e($27)           // set INDEX 0
+       lbu     $11, 0x12($27)          // read CSR0
+
+       andi    $9, $11, 0x04           // check SENTSTALL
+       beqz    $9, _ep0_setupend
+       nop
+
+_ep0_sentstall:
+       andi    $9, $11, 0xdb
+       sb      $9, 0x12($27)           // clear SENDSTALL and SENTSTALL
+       li      $22, 0                  // set EP0 to IDLE state
+
+_ep0_setupend:
+       andi    $9, $11, 0x10           // check SETUPEND
+       beqz    $9, ep0_idle_state
+       nop
+
+       ori     $9, $11, 0x80
+       sb      $9, 0x12($27)           // set SVDSETUPEND
+       li      $22, 0                  // set EP0 to IDLE state
+
+ep0_idle_state:
+       bnez    $22, ep0_tx_state
+       nop
+
+       //--------------------------------------------------------------
+       // 2.1 Handle EP0 IDLE state interrupt
+       //--------------------------------------------------------------
+       andi    $9, $11, 0x01           // check OUTPKTRDY
+       beqz    $9, check_intr_ep1in
+       nop
+
+       //--------------------------------------------------------------
+       // Read 8-bytes setup packet from the FIFO
+       //--------------------------------------------------------------
+       lw      $25, 0x20($27)          // first word of setup packet
+       lw      $26, 0x20($27)          // second word of setup packet
+
+       andi    $9, $25, 0x60           // bRequestType & USB_TYPE_MASK
+       beqz    $9, _ep0_std_req
+       nop
+
+       //--------------------------------------------------------------
+       // 2.1.1 Vendor-specific setup request
+       //--------------------------------------------------------------
+_ep0_vend_req:
+       li      $22, 0                  // set EP0 to IDLE state
+       li      $23, 1                  // NoData = 1
+
+       andi    $9, $25, 0xff00         // check bRequest
+       srl     $9, $9, 8
+       beqz    $9, __ep0_get_cpu_info
+       sub     $8, $9, 0x1
+       beqz    $8, __ep0_set_data_address
+       sub     $8, $9, 0x2
+       beqz    $8, __ep0_set_data_length
+       sub     $8, $9, 0x3
+       beqz    $8, __ep0_flush_caches
+       sub     $8, $9, 0x4
+       beqz    $8, __ep0_prog_start1
+       sub     $8, $9, 0x5
+       beqz    $8, __ep0_prog_start2
+       nop
+       b       _ep0_idle_state_fini    // invalid request
+       nop
+
+__ep0_get_cpu_info:
+       load_addr $20, cpu_info_data    // data pointer to transfer
+       li      $21, 8                  // bytes left to transfer
+       li      $22, 1                  // set EP0 to TX state
+       li      $23, 0                  // NoData = 0
+
+       b       _ep0_idle_state_fini
+       nop
+
+__ep0_set_data_address:
+       li      $9, 0xffff0000
+       and     $9, $25, $9
+       andi    $8, $26, 0xffff
+       or      $20, $9, $8             // data address of next transfer
+
+       b       _ep0_idle_state_fini
+       nop
+
+__ep0_set_data_length:
+       li      $9, 0xffff0000
+       and     $9, $25, $9
+       andi    $8, $26, 0xffff
+       or      $21, $9, $8             // data length of next transfer
+
+       li      $9, 0x48                // SVDOUTPKTRDY and DATAEND
+       sb      $9, 0x12($27)           // CSR0
+
+       // We must write packet to FIFO before EP1-IN interrupt here.
+       b       handle_epin1_intr
+       nop
+
+__ep0_flush_caches:
+       // Flush dcache and invalidate icache.
+       li      $8, 0x80000000
+       addi    $9, $8, 0x3fe0          // total 16KB
+
+1:
+       cache   0x0, 0($8)              // Index_Invalidate_I
+       cache   0x1, 0($8)              // Index_Writeback_Inv_D
+       bne     $8, $9, 1b
+       addiu   $8, $8, 32
+
+       // flush write-buffer
+       sync
+
+       // Invalidate BTB
+       mfc0    $8, $16, 7              // CP0_CONFIG
+       nop
+       ori     $8, 2
+       mtc0    $8, $16, 7
+       nop
+
+       b       _ep0_idle_state_fini
+       nop
+
+__ep0_prog_start1:
+       li      $9, 0x48                // SVDOUTPKTRDY and DATAEND
+       sb      $9, 0x12($27)           // CSR0
+
+       li      $9, 0xffff0000
+       and     $9, $25, $9
+       andi    $8, $26, 0xffff
+       or      $20, $9, $8             // target address
+
+       b       xfer_d2i
+       li      $19, 0x2000             // 16KB data length
+
+__ep0_prog_start2:
+       li      $9, 0x48                // SVDOUTPKTRDY and DATAEND
+       sb      $9, 0x12($27)           // CSR0
+
+       li      $9, 0xffff0000
+       and     $9, $25, $9
+       andi    $8, $26, 0xffff
+       or      $20, $9, $8             // target address
+
+       jalr    $20                     // jump, and place the return address in $31
+       nop
+
+__ep0_prog_start2_return:
+       // User code can return to here after executing itself, by jumping to $31.
+       b       usb_boot_return
+       nop
+
+       //--------------------------------------------------------------
+       // 2.1.2 Standard setup request
+       //--------------------------------------------------------------
+_ep0_std_req:
+       andi    $12, $25, 0xff00        // check bRequest
+       srl     $12, $12, 8
+       sub     $9, $12, 0x05           // check USB_REQ_SET_ADDRESS
+       bnez    $9, __ep0_req_set_config
+       nop
+
+       //--------------------------------------------------------------
+       // Handle USB_REQ_SET_ADDRESS
+       //--------------------------------------------------------------
+__ep0_req_set_addr:
+       srl     $9, $25, 16             // get wValue
+       sb      $9, 0x0($27)            // set FADDR
+       li      $23, 1                  // NoData = 1
+       b       _ep0_idle_state_fini
+       nop
+
+__ep0_req_set_config:
+       sub     $9, $12, 0x09           // check USB_REQ_SET_CONFIGURATION
+       bnez    $9, __ep0_req_get_desc
+       nop
+
+       //--------------------------------------------------------------
+       // Handle USB_REQ_SET_CONFIGURATION
+       //--------------------------------------------------------------
+       li      $23, 1                  // NoData = 1
+       b       _ep0_idle_state_fini
+       nop
+
+__ep0_req_get_desc:
+       sub     $9, $12, 0x06           // check USB_REQ_GET_DESCRIPTOR
+       bnez    $9, _ep0_idle_state_fini
+       li      $23, 1                  // NoData = 1
+
+       //--------------------------------------------------------------
+       // Handle USB_REQ_GET_DESCRIPTOR
+       //--------------------------------------------------------------
+       li      $23, 0                  // NoData = 0
+
+       srl     $9, $25, 24             // wValue >> 8
+       sub     $8, $9, 0x01            // check USB_DT_DEVICE
+       beqz    $8, ___ep0_get_dev_desc
+       srl     $21, $26, 16            // get wLength
+       sub     $8, $9, 0x02            // check USB_DT_CONFIG
+       beqz    $8, ___ep0_get_conf_desc
+       sub     $8, $9, 0x03            // check USB_DT_STRING
+       beqz    $8, ___ep0_get_string_desc
+       sub     $8, $9, 0x06            // check USB_DT_DEVICE_QUALIFIER
+       beqz    $8, ___ep0_get_dev_qualifier
+       nop
+       b       _ep0_idle_state_fini
+       nop
+
+___ep0_get_dev_desc:
+       load_addr       $20, device_desc        // data pointer
+       li      $22, 1                  // set EP0 to TX state
+       sub     $8, $21, 18
+       blez    $8, _ep0_idle_state_fini // wLength <= 18
+       nop
+       li      $21, 18                 // max length of device_desc
+       b       _ep0_idle_state_fini
+       nop
+
+___ep0_get_dev_qualifier:
+       load_addr       $20, dev_qualifier      // data pointer
+       li      $22, 1                  // set EP0 to TX state
+       sub     $8, $21, 10
+       blez    $8, _ep0_idle_state_fini // wLength <= 10
+       nop
+       li      $21, 10                 // max length of dev_qualifier
+       b       _ep0_idle_state_fini
+       nop
+
+___ep0_get_conf_desc:
+       load_addr       $20, config_desc_fs     // data pointer of FS mode
+       lbu     $8, 0x01($27)           // read POWER
+       andi    $8, 0x10                // test HS_MODE
+       beqz    $8, ___ep0_get_conf_desc2
+       nop
+       load_addr $20, config_desc_hs   // data pointer of HS mode
+
+___ep0_get_conf_desc2:
+       li      $22, 1                  // set EP0 to TX state
+       sub     $8, $21, 32
+       blez    $8, _ep0_idle_state_fini // wLength <= 32
+       nop
+       li      $21, 32                 // max length of config_desc
+       b       _ep0_idle_state_fini
+       nop
+
+___ep0_get_string_desc:
+       li      $22, 1                  // set EP0 to TX state
+
+       srl     $9, $25, 16             // wValue & 0xff
+       andi    $9, 0xff
+
+       sub     $8, $9, 1
+       beqz    $8, ___ep0_get_string_manufacture
+       sub     $8, $9, 2
+       beqz    $8, ___ep0_get_string_product
+       nop
+
+___ep0_get_string_lang_ids:
+       load_addr       $20, string_lang_ids    // data pointer
+       b       _ep0_idle_state_fini
+       li      $21, 4                  // data length
+
+___ep0_get_string_manufacture:
+       load_addr       $20, string_manufacture // data pointer
+       b       _ep0_idle_state_fini
+       li      $21, 16                 // data length
+
+___ep0_get_string_product:
+       load_addr       $20, string_product     // data pointer
+       b       _ep0_idle_state_fini
+       li      $21, 46                 // data length
+
+_ep0_idle_state_fini:
+       li      $9, 0x40                // SVDOUTPKTRDY
+       beqz    $23, _ep0_idle_state_fini2
+       nop
+       ori     $9, $9, 0x08            // DATAEND
+_ep0_idle_state_fini2:
+       sb      $9, 0x12($27)           // CSR0
+       beqz    $22, check_intr_ep1in
+       nop
+
+       //--------------------------------------------------------------
+       // 2.2 Handle EP0 TX state interrupt
+       //--------------------------------------------------------------
+ep0_tx_state:
+       sub     $9, $22, 1
+       bnez    $9, check_intr_ep1in
+       nop
+
+       sub     $9, $21, 64             // max packetsize
+       blez    $9, _ep0_tx_state2      // data count <= 64
+       ori     $19, $21, 0
+       li      $19, 64
+
+_ep0_tx_state2:
+       beqz    $19, _ep0_tx_state3     // send ZLP
+       ori     $18, $19, 0             // record bytes to be transferred
+       sub     $21, $21, $19           // decrement data count
+
+_ep0_fifo_write_loop:
+       lbu     $9, 0($20)              // read data
+       sb      $9, 0x20($27)           // load FIFO
+       sub     $19, $19, 1             // decrement counter
+       bnez    $19, _ep0_fifo_write_loop
+       addi    $20, $20, 1             // increment data pointer
+
+       sub     $9, $18, 64             // max packetsize
+       beqz    $9, _ep0_tx_state4
+       nop
+
+_ep0_tx_state3:
+       // transferred bytes < max packetsize
+       li      $9, 0x0a                // set INPKTRDY and DATAEND
+       sb      $9, 0x12($27)           // CSR0
+       li      $22, 0                  // set EP0 to IDLE state
+       b       check_intr_ep1in
+       nop
+
+_ep0_tx_state4:
+       // transferred bytes == max packetsize
+       li      $9, 0x02                // set INPKTRDY
+       sb      $9, 0x12($27)           // CSR0
+       b       check_intr_ep1in
+       nop
+
+       //--------------------------------------------------------------
+       // 3. Check and handle EP1 BULK-IN interrupt
+       //--------------------------------------------------------------
+check_intr_ep1in:
+       andi    $9, $10, 0x2            // check EP1 IN interrupt
+       beqz    $9, check_intr_ep1out
+       nop
+
+handle_epin1_intr:
+       li      $9, 1
+       sb      $9, 0x0e($27)           // set INDEX 1
+       lbu     $9, 0x12($27)           // read INCSR
+
+       andi    $8, $9, 0x2             // check INCSR_FFNOTEMPT
+       bnez    $8, _epin1_tx_state4
+       nop
+
+_epin1_write_fifo:
+       lhu     $9, 0x10($27)           // get INMAXP
+       sub     $8, $21, $9
+       blez    $8, _epin1_tx_state1    // bytes left <= INMAXP
+       ori     $19, $21, 0
+       ori     $19, $9, 0
+
+_epin1_tx_state1:
+       beqz    $19, _epin1_tx_state4   // No data
+       nop
+
+       sub     $21, $21, $19           // decrement data count
+
+       srl     $5, $19, 2              // # of word
+       andi    $6, $19, 0x3            // # of byte
+       beqz    $5, _epin1_tx_state2
+       nop
+
+_epin1_fifo_write_word:
+       lw      $9, 0($20)              // read data from source address
+       sw      $9, 0x24($27)           // write FIFO
+       sub     $5, $5, 1               // decrement counter
+       bnez    $5, _epin1_fifo_write_word
+       addiu   $20, $20, 4             // increment dest address
+
+_epin1_tx_state2:
+       beqz    $6, _epin1_tx_state3
+       nop
+
+_epin1_fifo_write_byte:
+       lbu     $9, 0($20)              // read data from source address
+       sb      $9, 0x24($27)           // write FIFO
+       sub     $6, $6, 1               // decrement counter
+       bnez    $6, _epin1_fifo_write_byte
+       addiu   $20, $20, 1             // increment dest address
+
+_epin1_tx_state3:
+       li      $9, 0x1
+       sb      $9, 0x12($27)           // INCSR, set INPKTRDY
+
+_epin1_tx_state4:
+       // nop
+
+       //--------------------------------------------------------------
+       // 4. Check and handle EP1 BULK-OUT interrupt
+       //--------------------------------------------------------------
+check_intr_ep1out:
+       lhu     $9, 0x04($27)           // read INTROUT
+       andi    $9, 0x2
+       beqz    $9, check_status_next
+       nop
+
+handle_epout1_intr:
+       li      $9, 1
+       sb      $9, 0x0e($27)           // set INDEX 1
+
+       lbu     $9, 0x16($27)           // read OUTCSR
+       andi    $9, 0x1                 // check OUTPKTRDY
+       beqz    $9, check_status_next
+       nop
+
+_epout1_read_fifo:
+       lhu     $19, 0x18($27)          // read OUTCOUNT
+       srl     $5, $19, 2              // # of word
+       andi    $6, $19, 0x3            // # of byte
+       beqz    $5, _epout1_rx_state1
+       nop
+
+_epout1_fifo_read_word:
+       lw      $9, 0x24($27)           // read FIFO
+       sw      $9, 0($20)              // store to dest address
+       sub     $5, $5, 1               // decrement counter
+       bnez    $5, _epout1_fifo_read_word
+       addiu   $20, $20, 4             // increment dest address
+
+_epout1_rx_state1:
+       beqz    $6, _epout1_rx_state2
+       nop
+
+_epout1_fifo_read_byte:
+       lbu     $9, 0x24($27)           // read FIFO
+       sb      $9, 0($20)              // store to dest address
+       sub     $6, $6, 1               // decrement counter
+       bnez    $6, _epout1_fifo_read_byte
+       addiu   $20, $20, 1             // increment dest address
+
+_epout1_rx_state2:
+       sb      $0, 0x16($27)           // clear OUTPKTRDY
+
+check_status_next:
+       b       usb_command_loop
+       nop
+
+//--------------------------------------------------------------
+// Device/Configuration/Interface/Endpoint/String Descriptors
+//--------------------------------------------------------------
+
+       .align  2
+device_desc:
+       .byte   0x12            // bLength
+       .byte   0x01            // bDescriptorType
+       .byte   0x00            // bcdUSB
+       .byte   0x02            // bcdUSB
+       .byte   0x00            // bDeviceClass
+       .byte   0x00            // bDeviceSubClass
+       .byte   0x00            // bDeviceProtocol
+       .byte   0x40            // bMaxPacketSize0
+       .byte   0x1a            // idVendor
+       .byte   0x60            // idVendor
+       .byte   0x40            // idProduct
+       .byte   0x47            // idProduct
+       .byte   0x00            // bcdDevice
+       .byte   0x01            // bcdDevice
+       .byte   0x01            // iManufacturer
+       .byte   0x02            // iProduct
+       .byte   0x00            // iSerialNumber
+       .byte   0x01            // bNumConfigurations
+
+       .align  2
+dev_qualifier:
+       .byte   0x0a            // bLength
+       .byte   0x06            // bDescriptorType
+       .byte   0x00            // bcdUSB
+       .byte   0x02            // bcdUSB
+       .byte   0x00            // bDeviceClass
+       .byte   0x00            // bDeviceSubClass
+       .byte   0x00            // bDeviceProtocol
+       .byte   0x40            // bMaxPacketSize0
+       .byte   0x01            // bNumConfigurations
+       .byte   0x00            // bRESERVED
+
+       .align  2
+config_desc_hs:
+       .byte   0x09            // bLength
+       .byte   0x02            // bDescriptorType
+       .byte   0x20            // wTotalLength
+       .byte   0x00            // wTotalLength
+       .byte   0x01            // bNumInterfaces
+       .byte   0x01            // bConfigurationValue
+       .byte   0x00            // iConfiguration
+       .byte   0xc0            // bmAttributes
+       .byte   0x01            // MaxPower
+intf_desc_hs:
+       .byte   0x09            // bLength
+       .byte   0x04            // bDescriptorType
+       .byte   0x00            // bInterfaceNumber
+       .byte   0x00            // bAlternateSetting
+       .byte   0x02            // bNumEndpoints
+       .byte   0xff            // bInterfaceClass
+       .byte   0x00            // bInterfaceSubClass
+       .byte   0x50            // bInterfaceProtocol
+       .byte   0x00            // iInterface
+ep1_desc_hs:
+       .byte   0x07            // bLength
+       .byte   0x05            // bDescriptorType
+       .byte   0x01            // bEndpointAddress
+       .byte   0x02            // bmAttributes
+       .byte   0x00            // wMaxPacketSize
+       .byte   0x02            // wMaxPacketSize
+       .byte   0x00            // bInterval
+ep2_desc_hs:
+       .byte   0x07            // bLength
+       .byte   0x05            // bDescriptorType
+       .byte   0x81            // bEndpointAddress
+       .byte   0x02            // bmAttributes
+       .byte   0x00            // wMaxPacketSize
+       .byte   0x02            // wMaxPacketSize
+       .byte   0x00            // bInterval
+
+       .align  2
+config_desc_fs:
+       .byte   0x09            // bLength
+       .byte   0x02            // bDescriptorType
+       .byte   0x20            // wTotalLength
+       .byte   0x00            // wTotalLength
+       .byte   0x01            // bNumInterfaces
+       .byte   0x01            // bConfigurationValue
+       .byte   0x00            // iConfiguration
+       .byte   0xc0            // bmAttributes
+       .byte   0x01            // MaxPower
+intf_desc_fs:
+       .byte   0x09            // bLength
+       .byte   0x04            // bDescriptorType
+       .byte   0x00            // bInterfaceNumber
+       .byte   0x00            // bAlternateSetting
+       .byte   0x02            // bNumEndpoints
+       .byte   0xff            // bInterfaceClass
+       .byte   0x00            // bInterfaceSubClass
+       .byte   0x50            // bInterfaceProtocol
+       .byte   0x00            // iInterface
+ep1_desc_fs:
+       .byte   0x07            // bLength
+       .byte   0x05            // bDescriptorType
+       .byte   0x01            // bEndpointAddress
+       .byte   0x02            // bmAttributes
+       .byte   0x40            // wMaxPacketSize
+       .byte   0x00            // wMaxPacketSize
+       .byte   0x00            // bInterval
+ep2_desc_fs:
+       .byte   0x07            // bLength
+       .byte   0x05            // bDescriptorType
+       .byte   0x81            // bEndpointAddress
+       .byte   0x02            // bmAttributes
+       .byte   0x40            // wMaxPacketSize
+       .byte   0x00            // wMaxPacketSize
+       .byte   0x00            // bInterval
+
+       .align  2
+string_lang_ids:
+       .byte   0x04
+       .byte   0x03
+       .byte   0x09
+       .byte   0x04
+
+       .align  2
+string_manufacture:
+       .byte   0x10
+       .byte   0x03
+       .byte   0x49
+       .byte   0x00
+       .byte   0x6e
+       .byte   0x00
+       .byte   0x67
+       .byte   0x00
+       .byte   0x65
+       .byte   0x00
+       .byte   0x6e
+       .byte   0x00
+       .byte   0x69
+       .byte   0x00
+       .byte   0x63
+       .byte   0x00
+
+       .align  2
+string_product:
+       .byte   0x2e
+       .byte   0x03
+       .byte   0x4a
+       .byte   0x00
+       .byte   0x5a
+       .byte   0x00
+       .byte   0x34
+       .byte   0x00
+       .byte   0x37
+       .byte   0x00
+       .byte   0x34
+       .byte   0x00
+       .byte   0x30
+       .byte   0x00
+       .byte   0x20
+       .byte   0x00
+       .byte   0x55
+       .byte   0x00
+       .byte   0x53
+       .byte   0x00
+       .byte   0x42
+       .byte   0x00
+       .byte   0x20
+       .byte   0x00
+       .byte   0x42
+       .byte   0x00
+       .byte   0x6f
+       .byte   0x00
+       .byte   0x6f
+       .byte   0x00
+       .byte   0x74
+       .byte   0x00
+       .byte   0x20
+       .byte   0x00
+       .byte   0x44
+       .byte   0x00
+       .byte   0x65
+       .byte   0x00
+       .byte   0x76
+       .byte   0x00
+       .byte   0x69
+       .byte   0x00
+       .byte   0x63
+       .byte   0x00
+       .byte   0x65
+       .byte   0x00
+
+       .align  2
+cpu_info_data:
+       .byte   0x4a
+       .byte   0x5a
+       .byte   0x34
+       .byte   0x37
+       .byte   0x34
+       .byte   0x30
+       .byte   0x56
+       .byte   0x31
+usbboot_end:
+
+    .set reorder