MT6574 USB flow in LK
Mt_boot_init(){
if (g_boot_mode== FASTBOOT)
goto fastboot;
fastboot:
udc_init(&odin_udc_device);
if(boot_mode== MODE_RAMDUMP)
rdx_init(target_get_scratch_address(),target_get_max_flash_size());
else
odin_init(target_get_scratch_address(),target_get_max_flash_size());
udc_start();
}
## 两个init 两个handler ##
rdx_init(){
in= udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512); //mtk setup_ep here, while, qualcom,setup_ep in irq handle_setup(ep0)
out= udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
interrupt= udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
req= udc_request_alloc();
udc_register_gadget(&rdx_gadget)
thr= thread_create("rdx",rdx_handler,0, DEFAULT_PRIORITY, 4096);
}
rdx_handler(){
while(fastboot_state != STATE_ERROR)
process_rdx_packet();{
static char preamble[] ="PrEaMbLe";
static char ack[] ="AcKnOwLeDgMeNt";
static charpostamble[] = "PoStAmBlE";
static charpowerdown[] = "PoWeRdOwN";
static char dxfer[] ="DaTaXfEr";
static char probe[] ="PrObE";
r =usb_detect_read(rxbuff, 16);// udc_request_queue(out, req);read rdx cmd
deal with the cmd…
}
}
udc_init(){
/* allocate ep0 */
ep0out= _udc_endpoint_alloc(EP0, 0, EP0_MAX_PACKET_SIZE);//ep0 setup here
ep0in= _udc_endpoint_alloc(EP0, 1, EP0_MAX_PACKET_SIZE);
ep0req= udc_request_alloc();
ep0req->buf= malloc(4096);
desc =udc_descriptor_alloc(TYPE_STRING, EP0, 4); //string descriptor
}
The MOST Important udc_start()
udc_start(){
/**data is the struct
*usb_device_descriptor
*usb_config_descriptor,
*usb_interface_descriptor,
*usb_endpoint_descriptor,
*usb_string_descriptor.
*/
desc= udc_descriptor_alloc(TYPE_DEVICE, EP0, 18);
desc= udc_descriptor_alloc(TYPE_CONFIGURATION, EP0, size);
udc_ifc_desc_fill(the_gadget,data + 9); //config descriptor, then pc drivers can match it.
while(1)service_interrupts();
service_interrupts();{
/* pollinginterrupt status for incoming interrupts and service it */
intrtx= readb(INTRTX) & readb(INTRTXE);
intrrx= readb(INTRRX) & readb(INTRRXE);
intrusb= readb(INTRUSB) & readb(INTRUSBE);
mt_udc_ep0_handler(){ // 处理enumeration, 处理rdx/odin 传输命令
mt_udc_ep0_setup();
if(ep0_state == TX)
mt_udc_ep0_write();
if(ep0_state == TX)
mt_udc_ep0_read(); //read,write两个函数需要的时候再调用--ep0_state。
//继续分析ep0setup
mt_udc_ep0_setup(){
count = mt_read_fifo();//读ep0接收到的命令
ep0_standard_setup();//这里处理enumeration
ep0_class_setup();//这里处理rdx/odin命令
if(unknown_cmd)
udc_stall_ep(ep_num,dir);//STALL会重置CSR0,RXCSR,TXCSR寄存器
}
}
mt_udc_epx_handler(ep_num,dir){//处理udc_request_queue(ept)端点请求
if(dir == OUT){
count = mt_read_fifo(ept);//读ept端点数据
handle_ept_complete(ept);//读完调用complete,通知queue函数。
}
if(dir == IN){
count =mt_write_fifo(ept);//写数据到对应端点
handle_ept_complete(ept);//写完调用complete,通知queue函数。
}
}
}
}
udc_request_queue(out,req);
--add a rcv_uar or tx_urb, which will receive data from mt_read/write_fifo()
For Qualcom chip, in ENDPTCOMPLETE register,the corresponding bit will be set 1 after queue data transfered. then callhandle_ept_complete(). a request finished.
However, MTK has no complete regisrer. ForRX,MTK set a INTRRXE register, then call irq, call mt_udc_epx_handler(ep_num,dir).
STALL 对RxPkt TxPkt 位的影响:
STALL后,对应另一个位需要主动清零