📄 usb_phci.c
字号:
restore_flags(flags); dma_cnfg |= (DMA_ENABLE | DMA_WRITE_SELECT) ; /* Enable HC DMA */ phci_reg_write16(REG_DMA_CNFG, dma_cnfg); /* wait for End of transfer */ do { isp1362_udelay(1); phci_reg_read16(REG_IRQ, &int_reg); } while(!(int_reg&EOT_INT)); /* Disable HC dma */ dma_cnfg &= ~(DMA_ENABLE | DMA_WRITE_SELECT) ; phci_reg_write16(REG_DMA_CNFG, dma_cnfg); return;}void fnvPhciRamRead(phci_t *phci, __u32 length, __u32 direction, __u32 addr, __u8 *byte_data) { __u32 direct_addr_len; __u16 dma_cnfg = 0; __u32 int_reg; unsigned int flags; __u32 original_length; detail_debug(("fnvPhciRamRead(length = %d, direction = %d, addr = 0x%x, byte_data = 0x%p)\n",length, direction, addr, byte_data)) if(!length || !byte_data) return; /* If there is nothing to write , return back */ original_length = length; if(length & 0x01) length++; /* Align length to even number */ /* fill the direct address length register with len+dir+addr */ direct_addr_len = addr & 0x7FFF; direct_addr_len |= direction; direct_addr_len |= (length << 16); phci_reg_write32(REG_DIRECT_ADDR_LEN ,direct_addr_len); // writing the direct address length dma_cnfg = (DMA_BUFF_TYPE_DIR_ADDR | DMA_1CYCLE_BURST_LEN | DMA_COUNTER_ENABLE); /* Disable DMA */ phci_reg_write16(REG_DMA_CNFG, dma_cnfg); /* Clear EOT bit inthe interrupt register */ phci_reg_write16(REG_IRQ, EOT_INT); save_flags(flags); disable_dma(DMA4HC_CHNNL); clear_dma_ff(DMA4HC_CHNNL); set_dma_mode(DMA4HC_CHNNL,DMA_MODE_READ); set_dma_addr(DMA4HC_CHNNL,virt_to_bus(phci->dma_buff)); set_dma_count(DMA4HC_CHNNL, length); /* Enable PC DMA */ enable_dma(DMA4HC_CHNNL); restore_flags(flags); dma_cnfg |= (DMA_ENABLE) ; /* Enable HC DMA */ phci_reg_write16(REG_DMA_CNFG, dma_cnfg); /* wait for End of transfer */ do { isp1362_udelay(1); phci_reg_read16(REG_IRQ, &int_reg); } while(!(int_reg&EOT_INT)); /* Disable HC dma */ dma_cnfg &= ~(DMA_ENABLE) ; phci_reg_write16(REG_DMA_CNFG, dma_cnfg); memcpy(byte_data, phci->dma_buff, original_length); return;}#else /* CONFIG_USB_PHCD_DMA *//*--------------------------------------------------------------* * Host Controller ATL/INTL/ISTL buffer Write *--------------------------------------------------------------*/void fnvPhciRamWrite(phci_t *phci, __u32 length, __u32 direction, __u32 addr, __u8 *byte_data) { __u32 direct_addr_len, cnt; __u16 lower_dword, higher_dword = 0; __u32 *dword_buff = (__u32*)byte_data; __u32 original_length, rem_length; detail_debug(("fnvPhciRamWrite(length = %d, direction = %d, addr = 0x%x, byte_data = 0x%p)\n",length, direction, addr, byte_data)) if(!length || !byte_data) return; /* If there is nothing to write , return back */ original_length = length; rem_length = (length & (RAM_BUFF_ALIGNMENT-1)); /* 0, 1, 2, 3 */ /* Make length to RAM_BUFF_ALIGNMENT byte boundary */ while(length & (RAM_BUFF_ALIGNMENT-1)){ length++; } /* fill the direct address length register with len+dir+addr */ direct_addr_len = addr & 0x7FFF; direct_addr_len |= direction; direct_addr_len |= (length << 16); phci_reg_write32(REG_DIRECT_ADDR_LEN ,direct_addr_len); // writing the direct address length /* Receive data from direct address register on the data IO */ isp1362_command((REG_DIRECT_ADDR_DATA|0x80), isp1362_device); length = original_length; if(direction == HC_DIR_ADDR_INCREMENT) { length >>= 2; /* total number of double words = length/4 */ cnt = 0; while( cnt < length) { lower_dword = dword_buff[cnt]; /* convert dword to 2 words */ higher_dword = (dword_buff[cnt++] >> 16); isp1362_write16(lower_dword,isp1362_device); isp1362_write16(higher_dword,isp1362_device); } if(rem_length) { length <<= 2; lower_dword = byte_data[length]; if(rem_length > 1) lower_dword |= (byte_data[length+1] << 8); if(rem_length > 2) higher_dword = byte_data[length+2]; isp1362_write16(lower_dword,isp1362_device); isp1362_write16(higher_dword,isp1362_device); } } return;} /* End of fnvPhciRamWrite *//*--------------------------------------------------------------* * Host Controller ATL/INTL/ISTL buffer Read *--------------------------------------------------------------*/void fnvPhciRamRead(phci_t *phci, __u32 length, __u32 direction, __u32 addr, __u8 *byte_data) { __u32 direct_addr_len, cnt; __u16 lower_dword, higher_dword; __u32 *dword_buff = (__u32*)byte_data; __u32 original_length, rem_length, dword; detail_debug(("fnvPhciRamRead(length = %d, direction = %d, addr = 0x%x, byte_data = 0x%p)\n",length, direction, addr, byte_data)) if(!length || !byte_data) return; /* If there is nothing to read, return back */ original_length = length; rem_length = (length & (RAM_BUFF_ALIGNMENT-1)); /* 0, 1, 2, 3 */ /* Make length to RAM_BUFF_ALIGNMENT byte boundary */ while(length & (RAM_BUFF_ALIGNMENT-1)){ length++; }// ALIGN_RAM_BUFF_LENGTH(length); /* fill the direct address length register with len+dir+addr */ direct_addr_len = addr & 0x7FFF; direct_addr_len |= direction; direct_addr_len |= (length << 16); phci_reg_write32(REG_DIRECT_ADDR_LEN ,direct_addr_len); // writing the direct address length /* Receive data from direct address register on the data IO */ isp1362_command(REG_DIRECT_ADDR_DATA, isp1362_device); length = original_length; if(direction == HC_DIR_ADDR_INCREMENT) { length >>= 2; /* total number of double words = length/4 */ cnt = 0; while( cnt < length) { lower_dword = isp1362_read16(isp1362_device); higher_dword = isp1362_read16(isp1362_device); dword_buff[cnt++] = lower_dword | (higher_dword << 16) ; /* Combine lower and higher 16 bits and fill buffer */ } if(rem_length) { lower_dword = isp1362_read16(isp1362_device); higher_dword = isp1362_read16(isp1362_device); length <<= 2; dword = lower_dword | (higher_dword << 16) ; /* make the 32 bit double word */ byte_data[length] = (dword & 0xFF); /* Copy the first remaining byte */ cnt = 1; while(cnt < rem_length) { /* Based on reming bytes copy the 2nd, 3rd bytes */ dword >>= 8; byte_data[length+cnt] = (dword & 0xFF); cnt++; } } } return;} /* End of fnvPhciRamRead */#endif /* CONFIG_USB_PHCD_DMA *//*--------------------------------------------------------------* * Host Controller Ram buffer parameter initialization *--------------------------------------------------------------*/void fnvHcRamBufferInit( phci_t *phci) { __u8 ram_data[1024]; int i; __u32 data = 0; func_debug(("fnvHcRamBufferInit(phci = 0x%p)\n",phci)) /* Configure ISTL buffer */ phci_reg_write16(REG_ISTL_BUFF_LEN, HC_ISTL_BUFFER_LENGTH); /* Istl buffer length */ phci_reg_write16(REG_ISTL_TOGGLE_RATE, HC_ISTL_DEF_TOGGLE_RATE); /* Istl toggle rate */ /* Configure INTL buffer */ phci_reg_write16(REG_INTL_BUFF_LEN, HC_INTL_BUFFER_LENGTH); /* Intl buffer length */ phci_reg_write16(REG_INTL_BLK_PL_SIZE, HC_INTL_BLK_PL_SIZE); /* Intl payload block size */ /* Configure ATL buffer */ phci_reg_write16(REG_ATL_BUFF_LEN, HC_ATL_BUFFER_LENGTH); /* Atl buffer length */ phci_reg_write16(REG_ATL_BLK_PL_SIZE, HC_ATL_BLK_PL_SIZE); /* Atl payload block size */ data = 0x0001 << (TD_PTD_MAX_ATL_TDS); phci_reg_write32(REG_ATL_PTD_LAST_PTD,data); /* Set the last ATL ptd in HC */ data = (0x0001 << (TD_PTD_MAX_INTL_TDS)); phci_reg_write32(REG_INTL_PTD_LAST_PTD,data); /* Update the last INTL ptd in HC */ phci_reg_write16(REG_ATL_THRESHOLD_TIMEOUT,HC_DEF_ATL_THRESHOLD_TIMEOUT); /* set the atl threshold ptd timeout HC */ phci_reg_write32(REG_ATL_PTD_SKIP_MAP,0xFFFFFFFF); /* Set all ptds to skip */ phci_reg_write32(REG_INTL_PTD_SKIP_MAP,0xFFFFFFFF); /* Set all ptds to skip */ /* Initialize the RAM buffer with zeros */ for(i=0;i<1024;i++) { ram_data[i] = 0; } for(i=0; i<(HC_RAM_SIZE/1024);i++) { fnvPhciRamWrite( phci, 1024, HC_DIR_ADDR_INCREMENT, i*1024, ram_data); } return;} /* End of fnvHcRamBufferInit *//*--------------------------------------------------------------* * Host Controller Initialization functions *--------------------------------------------------------------*//*--------------------------------------------------------------* * Host Controller Reset *--------------------------------------------------------------*/__u32 fnvPhciHostReset(phci_t *phci) { __u32 uData; __u32 uI; __u32 uRetVal; func_debug(("fnuHostReset(phci = 0x%p)\n",phci)) /* Set the HostController Reset bit in command status register */ fnvPhciHcorRead(phci,uHcCommandStatus,&uData); uData = HC_COMMAND_STATUS_HCR; fnvPhciHcorWrite(phci,uHcCommandStatus, uData); /* wait some time for HC to be reset */ for(uI=0;uI<5000;uI++) { fnvPhciHcorRead(phci,uHcCommandStatus,&uData); if((uData & HC_COMMAND_STATUS_HCR) == 0) break; } uRetVal = uData & HC_COMMAND_STATUS_HCR; return uRetVal;} /* End of fnvPhciHostReset *//*--------------------------------------------------------------* * Host Controller hardware Interrupt Initialization *--------------------------------------------------------------*/void fnvHcIntEnable(phci_t *phci) { __u32 uData; func_debug(("fnvHcIntEnable(phci = 0x%p)\n",phci)) /* Clear all pending int. source */ uData = 0xFFFFFFFF; phci_reg_write16(REG_IRQ, uData); /* Enable int. according settings in host_conf.h */ uData = 0; /* All int. are initially disabled */ uData |= ATL_INT; /* Enable ATL interrupt */// uData |= SOF_INT; /* Enable ATL interrupt */ uData |= INTL_INT; /* Enable INTL interrupt */ uData |= ISTL_0_INT; /* Enable ITL interrupt */ uData |= ISTL_1_INT; /* Enable ITL interrupt */ phci_reg_write16(REG_IRQ_MASK, uData);} /* End of fnvHcIntEnable() *//*--------------------------------------------------------------* * Host Controller Control Register Initialization *--------------------------------------------------------------*/void fnvHcControlInit(phci_t *phci) { __u32 uData; __u32 uHostConfigData; func_debug(("fnvHcControlInit(phci = 0x%p)\n",phci)) uHostConfigData = 0; /* Fill the control register of HC */ /* (1) Set the sate to operational */ uData = HC_STATE; uHostConfigData &= (~HC_CONTROL_HCFS); uHostConfigData |= (uData << 6); /* (2) Enable remote wakeup connection if opted */ uData = REMOTE_WAKEUP_CONN; uHostConfigData &= (~HC_CONTROL_RWC); if (uData == YES) uHostConfigData |= HC_CONTROL_RWC; /* (3) Enable remote wakeup if opted */ uData = REMOTE_WAKEUP_ENABLE; uHostConfigData &= (~HC_CONTROL_RWE); if (uData == YES) uHostConfigData |= HC_CONTROL_RWE; fnvPhciHcorWrite(phci,uHcControl, uHostConfigData); /* Configure the HCD transfer control registers uHcHcdControl and uHcHcdCommandStatus */ uHostConfigData = 0; uData = PERIODIC_LIST_ENABLE; /* Periodic list Enable ? */ if (uData == YES) uHostConfigData |= HC_CONTROL_PLE; uData = ISO_ENABLE; /* Isochronous transfer enabled ? */ if (uData == YES) uHostConfigData |= HC_CONTROL_IE; uData = CONTROL_LIST_ENABLE; /* Control trasnfer enabled ? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -