static __u32 USBC_Phy_TpWrite(__u32 usbc_no, __u32 addr, __u32 data, __u32 len) { __u32 temp = 0, dtmp = 0; __u32 j=0; dtmp = data; for(j = 0; j < len; j++) { /* set the bit address to be write */ temp = USBC_Readl(USBC_Phy_GetCsr(usbc_no)); temp &= ~(0xff << 8); temp |= ((addr + j) << 8); USBC_Writel(temp, USBC_Phy_GetCsr(usbc_no)); temp = USBC_Readb(USBC_Phy_GetCsr(usbc_no)); temp &= ~(0x1 << 7); temp |= (dtmp & 0x1) << 7; temp &= ~(0x1 << (usbc_no << 1)); USBC_Writeb(temp, USBC_Phy_GetCsr(usbc_no)); temp = USBC_Readb(USBC_Phy_GetCsr(usbc_no)); temp |= (0x1 << (usbc_no << 1)); USBC_Writeb( temp, USBC_Phy_GetCsr(usbc_no)); temp = USBC_Readb(USBC_Phy_GetCsr(usbc_no)); temp &= ~(0x1 << (usbc_no <<1 )); USBC_Writeb(temp, USBC_Phy_GetCsr(usbc_no)); dtmp >>= 1; } return data; }
/* ******************************************************************************* * sw_hcd_port_suspend * * Description: * suspend USB port * * Parameters: * sw_hcd : input. USB¿ØÖÆÆ÷ * do_suspend : input. flag. is suspend USB port or not? * * Return value: * void * * note: * void * ******************************************************************************* */ static void sw_hcd_port_suspend(struct sw_hcd *sw_hcd, bool do_suspend) { u8 power = 0; void __iomem *usbc_base = sw_hcd->mregs; if (!is_host_active(sw_hcd)){ DMSG_PANIC("ERR: usb host is not active\n"); return; } /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and * sw_hcd_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect * SE0 changing to connect (J) or wakeup (K) states. */ power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if (do_suspend) { int retries = 10000; DMSG_INFO("[sw_hcd]: suspend port.\n"); power &= ~(1 << USBC_BP_POWER_H_RESUME); power |= (1 << USBC_BP_POWER_H_SUSPEND); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); /* Needed for OPT A tests */ power = USBC_Readb(USBC_REG_PCTL(usbc_base)); while (power & (1 << USBC_BP_POWER_H_SUSPEND)) { power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if (retries-- < 1) break; } DMSG_DBG_HCD("DBG: Root port suspended, power %02x\n", power); sw_hcd->port1_status |= USB_PORT_STAT_SUSPEND; }else if (power & (1 << USBC_BP_POWER_H_SUSPEND)){ DMSG_INFO("[sw_hcd]: suspend portend, resume port.\n"); power &= ~(1 << USBC_BP_POWER_H_SUSPEND); power |= (1 << USBC_BP_POWER_H_RESUME); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); DMSG_DBG_HCD("DBG: Root port resuming, power %02x\n", power); /* later, GetPortStatus will stop RESUME signaling */ sw_hcd->port1_status |= SW_HCD_PORT_STAT_RESUME; sw_hcd->rh_timer = jiffies + msecs_to_jiffies(20); }else{ DMSG_PANIC("WRN: sw_hcd_port_suspend nothing to do\n"); } return ; }
static void __USBC_Host_Tx_ClearEpDma(__u32 usbc_base_addr) { __u16 ep_csr = 0; //auto_set, dma_tx_en, mode1 ep_csr = USBC_Readb(USBC_REG_TXCSR(usbc_base_addr) + 1); ep_csr &= ~((1 << USBC_BP_TXCSR_H_AUTOSET) >> 8); ep_csr &= ~((1 << USBC_BP_TXCSR_H_DMA_REQ_EN) >> 8); USBC_Writeb(ep_csr, (USBC_REG_TXCSR(usbc_base_addr) + 1)); //DMA_REQ_EN和DMA_REQ_MODE不能在同一个cycle中清除 ep_csr = USBC_Readb(USBC_REG_TXCSR(usbc_base_addr) + 1); ep_csr &= ~((1 << USBC_BP_TXCSR_H_DMA_REQ_MODE) >> 8); USBC_Writeb(ep_csr, (USBC_REG_TXCSR(usbc_base_addr) + 1)); }
__u32 USBC_Host_QueryPowerStatus(__hdle hUSB) { __usbc_otg_t *usbc_otg = (__usbc_otg_t *)hUSB; if(usbc_otg == NULL){ return 0; } return USBC_Readb(USBC_REG_PCTL(usbc_otg->base_addr)); }
static void __USBC_Dev_Rx_ClearEpDma(ulong usbc_base_addr) { __u16 ep_csr = 0; //auto_clear, dma_rx_en, mode0 ep_csr = USBC_Readb(USBC_REG_RXCSR(usbc_base_addr) + 1); ep_csr &= ~((1 << USBC_BP_RXCSR_D_AUTO_CLEAR) >> 8); ep_csr &= ~((1 << USBC_BP_RXCSR_D_DMA_REQ_MODE) >> 8); ep_csr &= ~((1 << USBC_BP_RXCSR_D_DMA_REQ_EN) >> 8); USBC_Writeb(ep_csr, (USBC_REG_RXCSR(usbc_base_addr) + 1)); }
static void __USBC_Host_Tx_ConfigEpDma(__u32 usbc_base_addr) { __u16 ep_csr = 0; //auto_set, tx_mode, dma_tx_en, mode1 ep_csr = USBC_Readb(USBC_REG_TXCSR(usbc_base_addr) + 1); ep_csr |= (1 << USBC_BP_TXCSR_H_AUTOSET) >> 8; ep_csr |= (1 << USBC_BP_TXCSR_H_MODE) >> 8; ep_csr |= (1 << USBC_BP_TXCSR_H_DMA_REQ_EN) >> 8; ep_csr |= (1 << USBC_BP_TXCSR_H_DMA_REQ_MODE) >> 8; USBC_Writeb(ep_csr, (USBC_REG_TXCSR(usbc_base_addr) + 1)); }
static void __USBC_Host_Rx_ConfigEpDma(__u32 usbc_base_addr) { __u16 ep_csr = 0; //配置dma, auto_clear, dma_rx_en, mode1, ep_csr = USBC_Readb(USBC_REG_RXCSR(usbc_base_addr) + 1); ep_csr |= (1 << USBC_BP_RXCSR_H_AUTO_CLEAR) >> 8; ep_csr |= (1 << USBC_BP_RXCSR_H_AUTO_REQ) >> 8; // ep_csr &= ~((1 << USBC_BP_RXCSR_H_DMA_REQ_MODE) >> 8); ep_csr |= ((1 << USBC_BP_RXCSR_H_DMA_REQ_MODE) >> 8); ep_csr |= (1 << USBC_BP_RXCSR_H_DMA_REQ_EN) >> 8; USBC_Writeb(ep_csr, (USBC_REG_RXCSR(usbc_base_addr) + 1)); }
/* *************************************************************************** * * read out one bit of USB PHY register * *************************************************************************** */ static __u32 __USBC_PHY_REG_READ(__u32 usbc_base_addr, __u32 usbc_phy_reg_addr) { __u32 reg_val = 0; __u32 i = 0; USBC_Writeb(usbc_phy_reg_addr, USBC_REG_PHYCTL(USBC0_REGS_BASE) + 1); for(i=0; i<0x4; i++); reg_val = USBC_Readb(USBC_REG_PHYCTL(USBC0_REGS_BASE) + 2); if(usbc_base_addr == USBC0_REGS_BASE) return (reg_val & 0x1); else return ((reg_val >> 1) & 0x1); }
static __u32 usb_phy0_write(__u32 addr, __u32 data, __u32 dmask, __u32 usbc_base_addr) { __u32 i=0; data = data & 0x0f; addr = addr & 0x0f; dmask = dmask & 0x0f; USBC_Writeb((dmask<<4)|data, usbc_base_addr + 0x404 + 2); USBC_Writeb(addr|0x10, usbc_base_addr + 0x404); for(i=0;i<5;i++); USBC_Writeb(addr|0x30, usbc_base_addr + 0x404); for(i=0;i<5;i++); USBC_Writeb(addr|0x10, usbc_base_addr + 0x404); for(i=0;i<5;i++); return (USBC_Readb(usbc_base_addr + 0x404 + 3) & 0x0f); }
/* *********************************************************************************** * USBC_Host_PeripheralType * * Description: * 外部设备的速度类型 * * Arguments: * hUSB : input. USBC_open_otg获得的句柄, 记录了USBC所需要的一些关键数据 * * Returns: * * * note: * 无 * *********************************************************************************** */ __u32 USBC_Host_PeripheralType(__hdle hUSB) { __usbc_otg_t *usbc_otg = (__usbc_otg_t *)hUSB; __u8 reg_val = 0; if(usbc_otg == NULL){ return 0; } reg_val = USBC_Readb(USBC_REG_DEVCTL(usbc_otg->base_addr)); if(reg_val & (1 << USBC_BP_DEVCTL_FS_DEV)){ return USBC_DEVICE_FSDEV; }else if(reg_val & (1 << USBC_BP_DEVCTL_LS_DEV)){ return USBC_DEVICE_LSDEV; }else{ return USBC_DEVICE_LSDEV; } }
/* *************************************************************************** * * Write one bit of USB PHY register * *************************************************************************** */ static void __USBC_PHY_REG_WRITE(__u32 usbc_base_addr, __u32 usbc_phy_reg_addr, __u32 usbc_phy_reg_data) { __u32 reg_val = 0; USBC_Writeb(usbc_phy_reg_addr, USBC_REG_PHYCTL(USBC0_REGS_BASE) + 1); reg_val = USBC_Readb(USBC_REG_PHYCTL(USBC0_REGS_BASE)); reg_val &= ~(0x1 << 7); reg_val |= (usbc_phy_reg_data & 0x1) << 7; if(usbc_base_addr == USBC0_REGS_BASE){ reg_val &= ~0x1; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); reg_val |= 0x1; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); reg_val &= ~0x1; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); }else{ reg_val &= ~0x2; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); reg_val |= 0x2; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); reg_val &= ~0x2; USBC_Writeb(reg_val, USBC_REG_PHYCTL(USBC0_REGS_BASE)); } }
void print_usb_reg_by_ep(spinlock_t *lock, __u32 usbc_base, __s32 ep_index, char *str) { __u32 old_ep_index = 0; DMSG_INFO("\n"); DMSG_INFO("--------------------------ep%d: %s--------------------------\n", ep_index, str); if (ep_index >= 0) { old_ep_index = USBC_Readw(usbc_base + USBC_REG_o_EPIND); USBC_Writew(ep_index, (usbc_base + USBC_REG_o_EPIND)); DMSG_INFO("old_ep_index = %d, ep_index = %d\n", old_ep_index, ep_index); } DMSG_INFO("USBC_REG_o_FADDR = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_FADDR)); DMSG_INFO("USBC_REG_o_PCTL = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_PCTL)); DMSG_INFO("USBC_REG_o_INTTx = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_INTTx)); DMSG_INFO("USBC_REG_o_INTRx = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_INTRx)); DMSG_INFO("USBC_REG_o_INTTxE = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_INTTxE)); DMSG_INFO("USBC_REG_o_INTRxE = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_INTRxE)); DMSG_INFO("USBC_REG_o_INTUSB = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_INTUSB)); DMSG_INFO("USBC_REG_o_INTUSBE = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_INTUSBE)); DMSG_INFO("USBC_REG_o_EPIND = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_EPIND)); DMSG_INFO("USBC_REG_o_TXMAXP = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_TXMAXP)); DMSG_INFO("USBC_REG_o_CSR0 = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_CSR0)); DMSG_INFO("USBC_REG_o_TXCSR = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_TXCSR)); DMSG_INFO("USBC_REG_o_RXMAXP = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_RXMAXP)); DMSG_INFO("USBC_REG_o_RXCSR = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_RXCSR)); DMSG_INFO("USBC_REG_o_COUNT0 = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_COUNT0)); DMSG_INFO("USBC_REG_o_RXCOUNT = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_RXCOUNT)); DMSG_INFO("USBC_REG_o_TXTYPE = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_TXTYPE)); DMSG_INFO("USBC_REG_o_NAKLIMIT0 = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_NAKLIMIT0)); DMSG_INFO("USBC_REG_o_TXINTERVAL = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_TXINTERVAL)); DMSG_INFO("USBC_REG_o_RXTYPE = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_RXTYPE)); DMSG_INFO("USBC_REG_o_RXINTERVAL = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_RXINTERVAL)); DMSG_INFO("USBC_REG_o_CONFIGDATA = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_CONFIGDATA)); DMSG_INFO("USBC_REG_o_DEVCTL = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_DEVCTL)); DMSG_INFO("USBC_REG_o_TXFIFOSZ = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_TXFIFOSZ)); DMSG_INFO("USBC_REG_o_RXFIFOSZ = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_RXFIFOSZ)); DMSG_INFO("USBC_REG_o_TXFIFOAD = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_TXFIFOAD)); DMSG_INFO("USBC_REG_o_RXFIFOAD = 0x%x\n", USBC_Readw(usbc_base + USBC_REG_o_RXFIFOAD)); DMSG_INFO("USBC_REG_o_VEND0 = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_VEND0)); DMSG_INFO("USBC_REG_o_VEND1 = 0x%x\n", USBC_Readb(usbc_base + USBC_REG_o_VEND1)); DMSG_INFO("TXFADDRx(%d) = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_TXFADDRx)); DMSG_INFO("TXHADDRx(%d = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_TXHADDRx)); DMSG_INFO("TXHPORTx(%d) = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_TXHPORTx)); DMSG_INFO("RXFADDRx(%d) = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_RXFADDRx)); DMSG_INFO("RXHADDRx(%d) = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_RXHADDRx)); DMSG_INFO("RXHPORTx(%d) = 0x%x\n", ep_index, USBC_Readb(usbc_base + USBC_REG_o_RXHPORTx)); DMSG_INFO("RPCOUNTx(%d) = 0x%x\n", ep_index, (u32)USBC_Readl(usbc_base + USBC_REG_o_RPCOUNT)); DMSG_INFO("USBC_REG_o_ISCR = 0x%x\n", (u32)USBC_Readl(usbc_base + USBC_REG_o_ISCR)); DMSG_INFO("USBC_REG_o_PHYCTL = 0x%x\n", (u32)USBC_Readl(usbc_base + USBC_REG_o_PHYCTL)); DMSG_INFO("USBC_REG_o_PHYBIST = 0x%x\n", (u32)USBC_Readl(usbc_base + USBC_REG_o_PHYBIST)); if (ep_index >= 0) { USBC_Writew(old_ep_index, (usbc_base + USBC_REG_o_EPIND)); } DMSG_INFO("---------------------------------------------------------------------------\n"); DMSG_INFO("\n"); return; }
/* ******************************************************************************* * sw_hcd_hub_control * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ int sw_hcd_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct sw_hcd *sw_hcd = hcd_to_sw_hcd(hcd); u32 temp = 0; int retval = 0; unsigned long flags = 0; void __iomem *usbc_base = sw_hcd->mregs; if(hcd == NULL){ DMSG_PANIC("ERR: invalid argment\n"); return -ESHUTDOWN; } spin_lock_irqsave(&sw_hcd->lock, flags); if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { spin_unlock_irqrestore(&sw_hcd->lock, flags); return -ESHUTDOWN; } DMSG_DBG_HCD("sw_hcd_hub_control: typeReq = %x, wValue = 0x%x, wIndex = 0x%x\n", typeReq, wValue, wIndex); /* hub features: always zero, setting is a NOP * port features: reported, sometimes updated when host is active * no indicators */ switch (typeReq) { case ClearHubFeature: case SetHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: break; default: goto error; } break; case ClearPortFeature: if ((wIndex & 0xff) != 1){ goto error; } switch (wValue) { case USB_PORT_FEAT_ENABLE: break; case USB_PORT_FEAT_SUSPEND: sw_hcd_port_suspend(sw_hcd, false); break; case USB_PORT_FEAT_POWER: /* fixme */ sw_hcd_set_vbus(sw_hcd, 0); break; case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_SUSPEND: break; default: goto error; } DMSG_DBG_HCD("DBG: clear feature %d\n", wValue); sw_hcd->port1_status &= ~(1 << wValue); break; case GetHubDescriptor: { struct usb_hub_descriptor *desc = (void *)buf; desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; desc->wHubCharacteristics = cpu_to_le16( 0x0001 /* per-port power switching */ | 0x0010 /* no overcurrent reporting */ ); desc->bPwrOn2PwrGood = 5; /* msec/2 */ desc->bHubContrCurrent = 0; /* workaround bogus struct definition */ desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ desc->u.hs.DeviceRemovable[1] = 0xff; } break; case GetHubStatus: temp = 0; *(__le32 *) buf = cpu_to_le32(temp); break; case GetPortStatus: { if (wIndex != 1){ DMSG_PANIC("ERR: GetPortStatus parameter wIndex is not 1.\n"); goto error; } /* finish RESET signaling? */ if ((sw_hcd->port1_status & USB_PORT_STAT_RESET) && time_after_eq(jiffies, sw_hcd->rh_timer)){ sw_hcd_port_reset(sw_hcd, false); } /* finish RESUME signaling? */ if ((sw_hcd->port1_status & SW_HCD_PORT_STAT_RESUME) && time_after_eq(jiffies, sw_hcd->rh_timer)) { u8 power = 0; power = USBC_Readb(USBC_REG_PCTL(usbc_base)); power &= ~(1 << USBC_BP_POWER_H_RESUME); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); DMSG_DBG_HCD("DBG: root port resume stopped, power %02x\n", power); /* ISSUE: DaVinci (RTL 1.300) disconnects after * resume of high speed peripherals (but not full * speed ones). */ sw_hcd->is_active = 1; sw_hcd->port1_status &= ~(USB_PORT_STAT_SUSPEND | SW_HCD_PORT_STAT_RESUME); sw_hcd->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; usb_hcd_poll_rh_status(sw_hcd_to_hcd(sw_hcd)); } put_unaligned(cpu_to_le32(sw_hcd->port1_status & ~SW_HCD_PORT_STAT_RESUME), (__le32 *) buf); /* port change status is more interesting */ DMSG_DBG_HCD("DBG: port status %08x\n", sw_hcd->port1_status); } break; case SetPortFeature: { if ((wIndex & 0xff) != 1){ goto error; } switch (wValue) { case USB_PORT_FEAT_POWER: /* NOTE: this controller has a strange state machine * that involves "requesting sessions" according to * magic side effects from incompletely-described * rules about startup... * * This call is what really starts the host mode; be * very careful about side effects if you reorder any * initialization logic, e.g. for OTG, or change any * logic relating to VBUS power-up. */ sw_hcd_start(sw_hcd); break; case USB_PORT_FEAT_RESET: sw_hcd_port_reset(sw_hcd, true); break; case USB_PORT_FEAT_SUSPEND: sw_hcd_port_suspend(sw_hcd, true); break; case USB_PORT_FEAT_TEST: { if (unlikely(is_host_active(sw_hcd))){ DMSG_PANIC("ERR: usb host is not active\n"); goto error; } wIndex >>= 8; switch (wIndex) { case 1: DMSG_DBG_HCD("TEST_J\n"); temp = 1 << USBC_BP_TMCTL_TEST_J; break; case 2: DMSG_DBG_HCD("TEST_K\n"); temp = 1 << USBC_BP_TMCTL_TEST_K; break; case 3: DMSG_DBG_HCD("TEST_SE0_NAK\n"); temp = 1 << USBC_BP_TMCTL_TEST_SE0_NAK; break; case 4: DMSG_DBG_HCD("TEST_PACKET\n"); temp = 1 << USBC_BP_TMCTL_TEST_PACKET; sw_hcd_load_testpacket(sw_hcd); break; case 5: DMSG_DBG_HCD("TEST_FORCE_ENABLE\n"); temp = (1 << USBC_BP_TMCTL_FORCE_HOST) | (1 << USBC_BP_TMCTL_FORCE_HS); USBC_REG_set_bit_b(USBC_BP_DEVCTL_SESSION, USBC_REG_DEVCTL(usbc_base)); break; case 6: DMSG_DBG_HCD("TEST_FIFO_ACCESS\n"); temp = 1 << USBC_BP_TMCTL_FIFO_ACCESS; break; default: DMSG_PANIC("ERR: unkown SetPortFeature USB_PORT_FEAT_TEST wIndex(%d)\n", wIndex); goto error; } USBC_Writeb(temp, USBC_REG_TMCTL(usbc_base)); } break; default:{ DMSG_PANIC("ERR: unkown SetPortFeature wValue(%d)\n", wValue); goto error; } } DMSG_DBG_HCD("DBG: set feature %d\n", wValue); sw_hcd->port1_status |= 1 << wValue; } break; default: error: DMSG_PANIC("ERR: protocol stall on error\n"); /* "protocol stall" on error */ retval = -EPIPE; } spin_unlock_irqrestore(&sw_hcd->lock, flags); return retval; }
/* ******************************************************************************* * sw_hcd_port_reset * * Description: * reset USB port * * Parameters: * sw_hcd : input. USB¿ØÖÆÆ÷ * do_reset : input. flag. is reset USB port or not? * * Return value: * void * * note: * void * ******************************************************************************* */ static void sw_hcd_port_reset(struct sw_hcd *sw_hcd, bool do_reset) { u8 power = 0; void __iomem *usbc_base = sw_hcd->mregs; if (!is_host_active(sw_hcd)){ DMSG_PANIC("ERR: usb host is not active\n"); return; } /* NOTE: caller guarantees it will turn off the reset when * the appropriate amount of time has passed */ power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if (do_reset) { DMSG_INFO("[sw_hcd]: reset port. \n"); /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let sw_hcd start * generating SOFs. If we don't do this, OPT HS A 6.8 tests * fail with "Error! Did not receive an SOF before suspend * detected". */ if (power & (1 << USBC_BP_POWER_H_RESUME)) { while (time_before(jiffies, sw_hcd->rh_timer)){ msleep(1); } power &= ~(1 << USBC_BP_POWER_H_RESUME); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); msleep(1); } sw_hcd->ignore_disconnect = true; power &= 0xf0; power |= (1 << USBC_BP_POWER_H_RESET); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); sw_hcd->port1_status |= USB_PORT_STAT_RESET; sw_hcd->port1_status &= ~USB_PORT_STAT_ENABLE; sw_hcd->rh_timer = jiffies + msecs_to_jiffies(50); USBC_Host_SetFunctionAddress_Deafult(sw_hcd->sw_hcd_io->usb_bsp_hdle, USBC_EP_TYPE_TX, 0); //set address ep0 { __u32 i = 1; __u8 old_ep_index = 0; old_ep_index = USBC_GetActiveEp(sw_hcd->sw_hcd_io->usb_bsp_hdle); USBC_SelectActiveEp(sw_hcd->sw_hcd_io->usb_bsp_hdle, 0); USBC_Host_SetFunctionAddress_Deafult(sw_hcd->sw_hcd_io->usb_bsp_hdle, USBC_EP_TYPE_TX, 0); for( i = 1 ; i <= 5; i++){ USBC_SelectActiveEp(sw_hcd->sw_hcd_io->usb_bsp_hdle, i); USBC_Host_SetFunctionAddress_Deafult(sw_hcd->sw_hcd_io->usb_bsp_hdle, USBC_EP_TYPE_TX, i); USBC_Host_SetFunctionAddress_Deafult(sw_hcd->sw_hcd_io->usb_bsp_hdle, USBC_EP_TYPE_RX, i); } USBC_SelectActiveEp(sw_hcd->sw_hcd_io->usb_bsp_hdle, old_ep_index); } }else{ DMSG_INFO("[sw_hcd]: reset port stopped.\n"); UsbPhyEndReset(0); power &= ~(1 << USBC_BP_POWER_H_RESET); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); sw_hcd->ignore_disconnect = false; power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if(power & (1 << USBC_BP_POWER_H_HIGH_SPEED_FLAG)){ DMSG_DBG_HCD("high-speed device connected\n"); sw_hcd->port1_status |= USB_PORT_STAT_HIGH_SPEED; } sw_hcd->port1_status &= ~USB_PORT_STAT_RESET; sw_hcd->port1_status |= USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET << 16) | (USB_PORT_STAT_C_ENABLE << 16); usb_hcd_poll_rh_status(sw_hcd_to_hcd(sw_hcd)); sw_hcd->vbuserr_retry = VBUSERR_RETRY_COUNT; } return ; }