📄 usb_phci.c
字号:
} /* 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;
__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 read, return back */
original_length = length;
if(length%2) 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
isp1362_buff_read(isp1362_device, REG_DIRECT_ADDR_DATA, byte_data,original_length);
return;
} /* End of fnvPhciRamRead */
/*--------------------------------------------------------------*
* 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 */
/* set the atl threshold ptd count */
phci_reg_write16(REG_ATL_THRESHOLD_COUNT,1);
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 |= OPR_INT; /* Enable OPRational Reg interrupt */
// uData |= SOF_INT; /* Enable SOF 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 ? */
if (uData == YES)
uHostConfigData |= HC_CONTROL_CLE;
uData = BULK_LIST_ENABLE; /* Bulk Transfer Enabled ? */
if (uData == YES)
uHostConfigData |= HC_CONTROL_BLE;
/* Note: HC_CONTROL_TIP (Transfer In Progress) is alreday set to 0 */
phci->hc_control = (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_PLE | OHCI_USB_OPER ;
fnvPhciHcorWrite(phci,uHcHcdControl, uHostConfigData);
} /* End of fnvHcControlInit() */
/*--------------------------------------------------------------*
* Host Controller Interrupt Register Initialization
*--------------------------------------------------------------*/
void fnvHcInterruptInit(phci_t *phci) {
__u32 uHostConfigData;
func_debug(("fnvHcInterruptInit(phci = 0x%p)\n",phci))
/* First of all, disable all interrupts */
uHostConfigData = HC_INTERRUPT_ALL;
fnvPhciHcorWrite(phci,uHcInterruptDisable, uHostConfigData);
uHostConfigData = 0;
/* Master Interrupt Enable */
uHostConfigData |= HC_INTERRUPT_MIE;
uHostConfigData |= HC_INTERRUPT_RHSC;
/* Write the configuration to uHcInterruptEnable register */
fnvPhciHcorWrite(phci,uHcInterruptEnable, uHostConfigData);
} /* End of fnvHcInterruptInit() */
/*--------------------------------------------------------------*
* Host Controller Frame Number interval Initialization
*--------------------------------------------------------------*/
void fnvHcFmIntervalInit(phci_t *phci) {
__u32 uHostConfigData;
func_debug(("fnvHcFmIntervalInit(phci = 0x%p)\n",phci))
/* Determine the fram interval and the largest data size */
uHostConfigData = FRAME_INTERVAL | (FS_LARGEST_DATA << 16);
/* Write the configuration to uHcFmInterval register */
fnvPhciHcorWrite(phci,uHcFmInterval, uHostConfigData);
} /* End of fnvHcFmIntervalInit() */
/*--------------------------------------------------------------*
* Host Controller Roothub registers Initialization
*--------------------------------------------------------------*/
void fnvHcRhPower(phci_t *phci) {
__u32 uData;
__u32 uHostConfigData;
func_debug(("fnvHcRhPower(phci = 0x%p)\n",phci))
/* Initialize the configuration data */
uHostConfigData = 0;
/* Enable or disable power switching */
uData = PORT_POWER_SWITCHING;
if (uData == NO) /* No power switching; ports are always powered on when the HC is powered on */
uHostConfigData |= HC_RH_DESCRIPTORA_NPS;
else {
/********************************************************/
/* Power switching is enabled */
/* Program root hub in per-port switching mode */
/********************************************************/
uHostConfigData |= HC_RH_DESCRIPTORA_PSM;
} /* else */
/* Port over current protection */
uData = OVER_CURRENT_PROTECTION;
if (uData == NO) /* No over current protection */
uHostConfigData |= HC_RH_DESCRIPTORA_NOCP;
else
uData = PER_PORT_OVER_CURRENT_REPORT;
if (uData == YES)
uHostConfigData |= HC_RH_DESCRIPTORA_OCPM;
/* Set the power on to power good time */
uHostConfigData |= ((POWER_ON_TO_POWER_GOOD_TIME / 2) << 24); /* Divided by 2, then move it into position */
fnvPhciHcorWrite(phci,uHcRhDescriptorA, uHostConfigData);
/* Set the global power to all the ports */
uHostConfigData = RH_HS_LPSC;
fnvPhciHcorWrite(phci,uHcRhStatus, uHostConfigData);
/* Wait till the POWER ON TO POWER GOOD time */
isp1362_mdelay(POWER_ON_TO_POWER_GOOD_TIME);
/* Set the HcRhDescriptorB register (13h) */
uHostConfigData = DEVICE_REMOVABLE;
if (PORT_POWER_SWITCHING == YES)
uHostConfigData |= 0xFFFF0000; /* Set PPCM bits 31..16 to disable gang-mode power switching */
fnvPhciHcorWrite(phci,uHcRhDescriptorB, uHostConfigData);
} /* End of fnvHcRhPower() */
/*--------------------------------------------------------------*
* Host Controller Initialization
*--------------------------------------------------------------*/
int fnuPhciHostInit(phci_t *phci) {
struct usb_device *usb_dev;
func_debug(("fnuPhciHostInit(phci = 0x%p)\n",phci))
/* 1. Host Controller Extended Registers Initialization */
isp1362_set_hw_config(phci->phci_dev);
fnvHcIntEnable(phci);
fnvHcRamBufferInit(phci);
phci_init_map_buffers(phci);
fnvHcControlInit(phci); /* Initialize HcControl register */
phci->disabled = 0;
fnvHcInterruptInit(phci); /* Initialize HcInterruptEnable/Disable registers */
fnvHcFmIntervalInit(phci); /* Initialize HcFmInterval Register */
fnvHcRhPower(phci); /* Root hub port power switching mode */
phci->rh.devnum = 0; /* No root hub yet */
phci->p_ed_controlhead = NULL; /* Initialize control & bulk list heads */
phci->p_ed_bulkhead = NULL;
/* Allocate data structure for root hub */
usb_dev = usb_alloc_dev ( NULL, phci->bus) ;
if( !usb_dev ) {
phci->disabled = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -