aboutsummaryrefslogtreecommitdiffstats
path: root/package/uboot-xburst/files/cpu/mips/usb_boot.S
diff options
context:
space:
mode:
Diffstat (limited to 'package/uboot-xburst/files/cpu/mips/usb_boot.S')
-rw-r--r--package/uboot-xburst/files/cpu/mips/usb_boot.S880
1 files changed, 880 insertions, 0 deletions
diff --git a/package/uboot-xburst/files/cpu/mips/usb_boot.S b/package/uboot-xburst/files/cpu/mips/usb_boot.S
new file mode 100644
index 000000000..107b928c7
--- /dev/null
+++ b/package/uboot-xburst/files/cpu/mips/usb_boot.S
@@ -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