4 * Copyright (c) 2009 Xiangfu Liu <xiangfu.z@gmail.com>
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 //----------------------------------------------------------------------
29 // Both NAND and USB boot load data to D-Cache first, then transfer
30 // data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
31 // So init caches first and then dispatch to a proper boot routine.
32 //----------------------------------------------------------------------
34 .macro load_addr reg addr
36 addiu \reg, \reg, \addr
42 //--------------------------------------------------------------
43 // Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
44 //--------------------------------------------------------------
45 la $9, 0xB0000000 // CPCCR: Clock Control Register
46 la $8, 0x42041110 // I:S:M:P=1:2:2:2
49 la $9, 0xB0000010 // CPPCR: PLL Control Register
50 la $8, 0x06000120 // M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
53 mtc0 $0, $26 // CP0_ERRCTL, restore WST reset state
56 mtc0 $0, $16 // CP0_CONFIG
59 // Relocate code to beginning of the ram
74 addiu $3, $3, usbboot_end
80 cache 0x0, 0($2) // Index_Invalidate_I
81 cache 0x1, 0($2) // Index_Writeback_Inv_D
87 load_addr $3, usb_boot_return
94 li $2, 3 // cacheable for kseg0 access
95 mtc0 $2, $16 // CP0_CONFIG
98 li $2, 0x20000000 // enable idx-store-data cache insn
99 mtc0 $2, $26 // CP0_ERRCTL
101 ori $2, $28, 0 // start address
102 ori $3, $2, 0x3fe0 // end address, total 16KB
103 mtc0 $0, $28, 0 // CP0_TAGLO
104 mtc0 $0, $28, 1 // CP0_DATALO
106 cache 0x8, 0($2) // Index_Store_Tag_I
107 cache 0x9, 0($2) // Index_Store_Tag_D
108 bne $2, $3, cache_clear_a_line
109 addiu $2, $2, 32 // increment CACHE_LINE_SIZE
111 ori $2, $28, 0 // start address
112 ori $3, $2, 0x3fe0 // end address, total 16KB
113 la $4, 0x1ffff000 // physical address and 4KB page mask
116 ori $5, $5, 1 // V bit of the physical tag
117 mtc0 $5, $28, 0 // CP0_TAGLO
118 cache 0x8, 0($2) // Index_Store_Tag_I
119 cache 0x9, 0($2) // Index_Store_Tag_D
120 bne $2, $3, cache_alloc_a_line
121 addiu $2, $2, 32 // increment CACHE_LINE_SIZE
126 //--------------------------------------------------------------
127 // Transfer data from dcache to icache, then jump to icache.
131 // $19: data length in bytes
132 // $20: jump target address
133 //--------------------------------------------------------------
137 addu $9, $8, $19 // total 16KB
140 cache 0x0, 0($8) // Index_Invalidate_I
141 cache 0x1, 0($8) // Index_Writeback_Inv_D
145 // flush write-buffer
149 mfc0 $8, $16, 7 // CP0_CONFIG
155 // Overwrite config to disable ram initalisation
163 //--------------------------------------------------------------
164 // User code can return to here after executing itself in
165 // icache, by jumping to $31.
166 //--------------------------------------------------------------
172 //--------------------------------------------------------------
173 // Enable the USB PHY
174 //--------------------------------------------------------------
175 la $9, 0xB0000024 // CPM_SCR
177 ori $8, 0x40 // USBPHY_ENABLE
180 //--------------------------------------------------------------
181 // Initialize USB registers
182 //--------------------------------------------------------------
183 la $27, 0xb3040000 // USB registers base address
185 sb $0, 0x0b($27) // INTRUSBE: disable common USB interrupts
186 sh $0, 0x06($27) // INTRINE: disable EPIN interrutps
187 sh $0, 0x08($27) // INTROUTE: disable EPOUT interrutps
190 sb $9, 0x01($27) // POWER: HSENAB | SUSPENDM | SOFTCONN
192 //--------------------------------------------------------------
193 // Initialize USB states
194 //--------------------------------------------------------------
195 li $22, 0 // set EP0 to IDLE state
196 li $23, 1 // no data stage
198 //--------------------------------------------------------------
199 // Main loop of polling the usb commands
200 //--------------------------------------------------------------
202 lbu $9, 0x0a($27) // read INTRUSB
203 andi $9, 0x04 // check USB_INTR_RESET
204 beqz $9, check_intr_ep0in
207 //--------------------------------------------------------------
208 // 1. Handle USB reset interrupt
209 //--------------------------------------------------------------
211 lbu $9, 0x01($27) // read POWER
212 andi $9, 0x10 // test HS_MODE
213 bnez $9, _usb_set_maxpktsize
214 li $9, 512 // max packet size of HS mode
215 li $9, 64 // max packet size of FS mode
219 sb $8, 0x0e($27) // set INDEX 1
221 sh $9, 0x10($27) // INMAXP
222 sb $0, 0x13($27) // INCSRH
223 sh $9, 0x14($27) // OUTMAXP
224 sb $0, 0x17($27) // OUTCSRH
227 li $8, 0x48 // INCSR_CDT && INCSR_FF
228 sb $8, 0x12($27) // INCSR
229 li $8, 0x90 // OUTCSR_CDT && OUTCSR_FF
230 sb $8, 0x16($27) // OUTCSR
232 li $22, 0 // set EP0 to IDLE state
233 li $23, 1 // no data stage
235 //--------------------------------------------------------------
236 // 2. Check and handle EP0 interrupt
237 //--------------------------------------------------------------
239 lhu $10, 0x02($27) // read INTRIN
240 andi $9, $10, 0x1 // check EP0 interrupt
241 beqz $9, check_intr_ep1in
245 sb $0, 0x0e($27) // set INDEX 0
246 lbu $11, 0x12($27) // read CSR0
248 andi $9, $11, 0x04 // check SENTSTALL
249 beqz $9, _ep0_setupend
254 sb $9, 0x12($27) // clear SENDSTALL and SENTSTALL
255 li $22, 0 // set EP0 to IDLE state
258 andi $9, $11, 0x10 // check SETUPEND
259 beqz $9, ep0_idle_state
263 sb $9, 0x12($27) // set SVDSETUPEND
264 li $22, 0 // set EP0 to IDLE state
267 bnez $22, ep0_tx_state
270 //--------------------------------------------------------------
271 // 2.1 Handle EP0 IDLE state interrupt
272 //--------------------------------------------------------------
273 andi $9, $11, 0x01 // check OUTPKTRDY
274 beqz $9, check_intr_ep1in
277 //--------------------------------------------------------------
278 // Read 8-bytes setup packet from the FIFO
279 //--------------------------------------------------------------
280 lw $25, 0x20($27) // first word of setup packet
281 lw $26, 0x20($27) // second word of setup packet
283 andi $9, $25, 0x60 // bRequestType & USB_TYPE_MASK
284 beqz $9, _ep0_std_req
287 //--------------------------------------------------------------
288 // 2.1.1 Vendor-specific setup request
289 //--------------------------------------------------------------
291 li $22, 0 // set EP0 to IDLE state
292 li $23, 1 // NoData = 1
294 andi $9, $25, 0xff00 // check bRequest
296 beqz $9, __ep0_get_cpu_info
298 beqz $8, __ep0_set_data_address
300 beqz $8, __ep0_set_data_length
302 beqz $8, __ep0_flush_caches
304 beqz $8, __ep0_prog_start1
306 beqz $8, __ep0_prog_start2
308 b _ep0_idle_state_fini // invalid request
312 load_addr $20, cpu_info_data // data pointer to transfer
313 li $21, 8 // bytes left to transfer
314 li $22, 1 // set EP0 to TX state
315 li $23, 0 // NoData = 0
317 b _ep0_idle_state_fini
320 __ep0_set_data_address:
324 or $20, $9, $8 // data address of next transfer
326 b _ep0_idle_state_fini
329 __ep0_set_data_length:
333 or $21, $9, $8 // data length of next transfer
335 li $9, 0x48 // SVDOUTPKTRDY and DATAEND
336 sb $9, 0x12($27) // CSR0
338 // We must write packet to FIFO before EP1-IN interrupt here.
343 // Flush dcache and invalidate icache.
345 addi $9, $8, 0x3fe0 // total 16KB
348 cache 0x0, 0($8) // Index_Invalidate_I
349 cache 0x1, 0($8) // Index_Writeback_Inv_D
353 // flush write-buffer
357 mfc0 $8, $16, 7 // CP0_CONFIG
363 b _ep0_idle_state_fini
367 li $9, 0x48 // SVDOUTPKTRDY and DATAEND
368 sb $9, 0x12($27) // CSR0
373 or $20, $9, $8 // target address
376 li $19, 0x2000 // 16KB data length
379 li $9, 0x48 // SVDOUTPKTRDY and DATAEND
380 sb $9, 0x12($27) // CSR0
385 or $20, $9, $8 // target address
387 jalr $20 // jump, and place the return address in $31
390 __ep0_prog_start2_return:
391 // User code can return to here after executing itself, by jumping to $31.
395 //--------------------------------------------------------------
396 // 2.1.2 Standard setup request
397 //--------------------------------------------------------------
399 andi $12, $25, 0xff00 // check bRequest
401 sub $9, $12, 0x05 // check USB_REQ_SET_ADDRESS
402 bnez $9, __ep0_req_set_config
405 //--------------------------------------------------------------
406 // Handle USB_REQ_SET_ADDRESS
407 //--------------------------------------------------------------
409 srl $9, $25, 16 // get wValue
410 sb $9, 0x0($27) // set FADDR
411 li $23, 1 // NoData = 1
412 b _ep0_idle_state_fini
415 __ep0_req_set_config:
416 sub $9, $12, 0x09 // check USB_REQ_SET_CONFIGURATION
417 bnez $9, __ep0_req_get_desc
420 //--------------------------------------------------------------
421 // Handle USB_REQ_SET_CONFIGURATION
422 //--------------------------------------------------------------
423 li $23, 1 // NoData = 1
424 b _ep0_idle_state_fini
428 sub $9, $12, 0x06 // check USB_REQ_GET_DESCRIPTOR
429 bnez $9, _ep0_idle_state_fini
430 li $23, 1 // NoData = 1
432 //--------------------------------------------------------------
433 // Handle USB_REQ_GET_DESCRIPTOR
434 //--------------------------------------------------------------
435 li $23, 0 // NoData = 0
437 srl $9, $25, 24 // wValue >> 8
438 sub $8, $9, 0x01 // check USB_DT_DEVICE
439 beqz $8, ___ep0_get_dev_desc
440 srl $21, $26, 16 // get wLength
441 sub $8, $9, 0x02 // check USB_DT_CONFIG
442 beqz $8, ___ep0_get_conf_desc
443 sub $8, $9, 0x03 // check USB_DT_STRING
444 beqz $8, ___ep0_get_string_desc
445 sub $8, $9, 0x06 // check USB_DT_DEVICE_QUALIFIER
446 beqz $8, ___ep0_get_dev_qualifier
448 b _ep0_idle_state_fini
452 load_addr $20, device_desc // data pointer
453 li $22, 1 // set EP0 to TX state
455 blez $8, _ep0_idle_state_fini // wLength <= 18
457 li $21, 18 // max length of device_desc
458 b _ep0_idle_state_fini
461 ___ep0_get_dev_qualifier:
462 load_addr $20, dev_qualifier // data pointer
463 li $22, 1 // set EP0 to TX state
465 blez $8, _ep0_idle_state_fini // wLength <= 10
467 li $21, 10 // max length of dev_qualifier
468 b _ep0_idle_state_fini
471 ___ep0_get_conf_desc:
472 load_addr $20, config_desc_fs // data pointer of FS mode
473 lbu $8, 0x01($27) // read POWER
474 andi $8, 0x10 // test HS_MODE
475 beqz $8, ___ep0_get_conf_desc2
477 load_addr $20, config_desc_hs // data pointer of HS mode
479 ___ep0_get_conf_desc2:
480 li $22, 1 // set EP0 to TX state
482 blez $8, _ep0_idle_state_fini // wLength <= 32
484 li $21, 32 // max length of config_desc
485 b _ep0_idle_state_fini
488 ___ep0_get_string_desc:
489 li $22, 1 // set EP0 to TX state
491 srl $9, $25, 16 // wValue & 0xff
495 beqz $8, ___ep0_get_string_manufacture
497 beqz $8, ___ep0_get_string_product
500 ___ep0_get_string_lang_ids:
501 load_addr $20, string_lang_ids // data pointer
502 b _ep0_idle_state_fini
503 li $21, 4 // data length
505 ___ep0_get_string_manufacture:
506 load_addr $20, string_manufacture // data pointer
507 b _ep0_idle_state_fini
508 li $21, 16 // data length
510 ___ep0_get_string_product:
511 load_addr $20, string_product // data pointer
512 b _ep0_idle_state_fini
513 li $21, 46 // data length
515 _ep0_idle_state_fini:
516 li $9, 0x40 // SVDOUTPKTRDY
517 beqz $23, _ep0_idle_state_fini2
519 ori $9, $9, 0x08 // DATAEND
520 _ep0_idle_state_fini2:
521 sb $9, 0x12($27) // CSR0
522 beqz $22, check_intr_ep1in
525 //--------------------------------------------------------------
526 // 2.2 Handle EP0 TX state interrupt
527 //--------------------------------------------------------------
530 bnez $9, check_intr_ep1in
533 sub $9, $21, 64 // max packetsize
534 blez $9, _ep0_tx_state2 // data count <= 64
539 beqz $19, _ep0_tx_state3 // send ZLP
540 ori $18, $19, 0 // record bytes to be transferred
541 sub $21, $21, $19 // decrement data count
543 _ep0_fifo_write_loop:
544 lbu $9, 0($20) // read data
545 sb $9, 0x20($27) // load FIFO
546 sub $19, $19, 1 // decrement counter
547 bnez $19, _ep0_fifo_write_loop
548 addi $20, $20, 1 // increment data pointer
550 sub $9, $18, 64 // max packetsize
551 beqz $9, _ep0_tx_state4
555 // transferred bytes < max packetsize
556 li $9, 0x0a // set INPKTRDY and DATAEND
557 sb $9, 0x12($27) // CSR0
558 li $22, 0 // set EP0 to IDLE state
563 // transferred bytes == max packetsize
564 li $9, 0x02 // set INPKTRDY
565 sb $9, 0x12($27) // CSR0
569 //--------------------------------------------------------------
570 // 3. Check and handle EP1 BULK-IN interrupt
571 //--------------------------------------------------------------
573 andi $9, $10, 0x2 // check EP1 IN interrupt
574 beqz $9, check_intr_ep1out
579 sb $9, 0x0e($27) // set INDEX 1
580 lbu $9, 0x12($27) // read INCSR
582 andi $8, $9, 0x2 // check INCSR_FFNOTEMPT
583 bnez $8, _epin1_tx_state4
587 lhu $9, 0x10($27) // get INMAXP
589 blez $8, _epin1_tx_state1 // bytes left <= INMAXP
594 beqz $19, _epin1_tx_state4 // No data
597 sub $21, $21, $19 // decrement data count
599 srl $5, $19, 2 // # of word
600 andi $6, $19, 0x3 // # of byte
601 beqz $5, _epin1_tx_state2
604 _epin1_fifo_write_word:
605 lw $9, 0($20) // read data from source address
606 sw $9, 0x24($27) // write FIFO
607 sub $5, $5, 1 // decrement counter
608 bnez $5, _epin1_fifo_write_word
609 addiu $20, $20, 4 // increment dest address
612 beqz $6, _epin1_tx_state3
615 _epin1_fifo_write_byte:
616 lbu $9, 0($20) // read data from source address
617 sb $9, 0x24($27) // write FIFO
618 sub $6, $6, 1 // decrement counter
619 bnez $6, _epin1_fifo_write_byte
620 addiu $20, $20, 1 // increment dest address
624 sb $9, 0x12($27) // INCSR, set INPKTRDY
629 //--------------------------------------------------------------
630 // 4. Check and handle EP1 BULK-OUT interrupt
631 //--------------------------------------------------------------
633 lhu $9, 0x04($27) // read INTROUT
635 beqz $9, check_status_next
640 sb $9, 0x0e($27) // set INDEX 1
642 lbu $9, 0x16($27) // read OUTCSR
643 andi $9, 0x1 // check OUTPKTRDY
644 beqz $9, check_status_next
648 lhu $19, 0x18($27) // read OUTCOUNT
649 srl $5, $19, 2 // # of word
650 andi $6, $19, 0x3 // # of byte
651 beqz $5, _epout1_rx_state1
654 _epout1_fifo_read_word:
655 lw $9, 0x24($27) // read FIFO
656 sw $9, 0($20) // store to dest address
657 sub $5, $5, 1 // decrement counter
658 bnez $5, _epout1_fifo_read_word
659 addiu $20, $20, 4 // increment dest address
662 beqz $6, _epout1_rx_state2
665 _epout1_fifo_read_byte:
666 lbu $9, 0x24($27) // read FIFO
667 sb $9, 0($20) // store to dest address
668 sub $6, $6, 1 // decrement counter
669 bnez $6, _epout1_fifo_read_byte
670 addiu $20, $20, 1 // increment dest address
673 sb $0, 0x16($27) // clear OUTPKTRDY
679 //--------------------------------------------------------------
680 // Device/Configuration/Interface/Endpoint/String Descriptors
681 //--------------------------------------------------------------
685 .byte 0x12 // bLength
686 .byte 0x01 // bDescriptorType
689 .byte 0x00 // bDeviceClass
690 .byte 0x00 // bDeviceSubClass
691 .byte 0x00 // bDeviceProtocol
692 .byte 0x40 // bMaxPacketSize0
693 .byte 0x1a // idVendor
694 .byte 0x60 // idVendor
695 .byte 0x40 // idProduct
696 .byte 0x47 // idProduct
697 .byte 0x00 // bcdDevice
698 .byte 0x01 // bcdDevice
699 .byte 0x01 // iManufacturer
700 .byte 0x02 // iProduct
701 .byte 0x00 // iSerialNumber
702 .byte 0x01 // bNumConfigurations
706 .byte 0x0a // bLength
707 .byte 0x06 // bDescriptorType
710 .byte 0x00 // bDeviceClass
711 .byte 0x00 // bDeviceSubClass
712 .byte 0x00 // bDeviceProtocol
713 .byte 0x40 // bMaxPacketSize0
714 .byte 0x01 // bNumConfigurations
715 .byte 0x00 // bRESERVED
719 .byte 0x09 // bLength
720 .byte 0x02 // bDescriptorType
721 .byte 0x20 // wTotalLength
722 .byte 0x00 // wTotalLength
723 .byte 0x01 // bNumInterfaces
724 .byte 0x01 // bConfigurationValue
725 .byte 0x00 // iConfiguration
726 .byte 0xc0 // bmAttributes
727 .byte 0x01 // MaxPower
729 .byte 0x09 // bLength
730 .byte 0x04 // bDescriptorType
731 .byte 0x00 // bInterfaceNumber
732 .byte 0x00 // bAlternateSetting
733 .byte 0x02 // bNumEndpoints
734 .byte 0xff // bInterfaceClass
735 .byte 0x00 // bInterfaceSubClass
736 .byte 0x50 // bInterfaceProtocol
737 .byte 0x00 // iInterface
739 .byte 0x07 // bLength
740 .byte 0x05 // bDescriptorType
741 .byte 0x01 // bEndpointAddress
742 .byte 0x02 // bmAttributes
743 .byte 0x00 // wMaxPacketSize
744 .byte 0x02 // wMaxPacketSize
745 .byte 0x00 // bInterval
747 .byte 0x07 // bLength
748 .byte 0x05 // bDescriptorType
749 .byte 0x81 // bEndpointAddress
750 .byte 0x02 // bmAttributes
751 .byte 0x00 // wMaxPacketSize
752 .byte 0x02 // wMaxPacketSize
753 .byte 0x00 // bInterval
757 .byte 0x09 // bLength
758 .byte 0x02 // bDescriptorType
759 .byte 0x20 // wTotalLength
760 .byte 0x00 // wTotalLength
761 .byte 0x01 // bNumInterfaces
762 .byte 0x01 // bConfigurationValue
763 .byte 0x00 // iConfiguration
764 .byte 0xc0 // bmAttributes
765 .byte 0x01 // MaxPower
767 .byte 0x09 // bLength
768 .byte 0x04 // bDescriptorType
769 .byte 0x00 // bInterfaceNumber
770 .byte 0x00 // bAlternateSetting
771 .byte 0x02 // bNumEndpoints
772 .byte 0xff // bInterfaceClass
773 .byte 0x00 // bInterfaceSubClass
774 .byte 0x50 // bInterfaceProtocol
775 .byte 0x00 // iInterface
777 .byte 0x07 // bLength
778 .byte 0x05 // bDescriptorType
779 .byte 0x01 // bEndpointAddress
780 .byte 0x02 // bmAttributes
781 .byte 0x40 // wMaxPacketSize
782 .byte 0x00 // wMaxPacketSize
783 .byte 0x00 // bInterval
785 .byte 0x07 // bLength
786 .byte 0x05 // bDescriptorType
787 .byte 0x81 // bEndpointAddress
788 .byte 0x02 // bmAttributes
789 .byte 0x40 // wMaxPacketSize
790 .byte 0x00 // wMaxPacketSize
791 .byte 0x00 // bInterval