void enableAllClockPower() { int i; u32 temp; g_num_u3_port = SSUSB_U3_PORT_NUM(readl((const volatile void __iomem *)SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl((const volatile void __iomem *)SSUSB_IP_CAP)); //2. Enable xHC writel(readl((const volatile void __iomem *)SSUSB_IP_PW_CTRL) | (SSUSB_IP_SW_RST), (volatile void __iomem *)SSUSB_IP_PW_CTRL); writel(readl((const volatile void __iomem *)SSUSB_IP_PW_CTRL) & (~SSUSB_IP_SW_RST), (volatile void __iomem *)SSUSB_IP_PW_CTRL); writel(readl((const volatile void __iomem *)SSUSB_IP_PW_CTRL_1) & (~SSUSB_IP_PDN), (volatile void __iomem *)SSUSB_IP_PW_CTRL_1); //1. Enable target ports for(i=0; i<g_num_u3_port; i++){ temp = readl((const volatile void __iomem *)SSUSB_U3_CTRL(i)); temp = temp & (~SSUSB_U3_PORT_PDN) & (~SSUSB_U3_PORT_DIS); writel(temp, (volatile void __iomem *)SSUSB_U3_CTRL(i)); } for(i=0; i<g_num_u2_port; i++){ temp = readl((const volatile void __iomem *)SSUSB_U2_CTRL(i)); temp = temp & (~SSUSB_U2_PORT_PDN) & (~SSUSB_U2_PORT_DIS); writel(temp, (volatile void __iomem *)SSUSB_U2_CTRL(i)); } mdelay(100); }
void enableXhciAllPortPower(struct xhci_hcor *hcor) { int i; u32 port_id, temp; __le32 __iomem addr; g_num_u3_port = SSUSB_U3_PORT_NUM(readl((const volatile void __iomem *)SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl((const volatile void __iomem *)SSUSB_IP_CAP)); for (i = 1; i <= g_num_u3_port; i++) { port_id = i; addr = (__le32 __iomem)(&hcor->portregs); addr += NUM_PORT_REGS * ((port_id - 1) & 0xff) * sizeof(__le32); temp = xhci_readl((__le32 __iomem *)addr); temp = xhci_port_state_to_neutral(temp); temp |= PORT_POWER; xhci_writel((__le32 __iomem *)addr, temp); } for (i = 1; i <= g_num_u2_port; i++) { port_id=i+g_num_u3_port; addr = (__le32 __iomem)(&hcor->portregs); addr += NUM_PORT_REGS * ((port_id - 1) & 0xff) * sizeof(__le32); temp = xhci_readl((__le32 __iomem *)addr); temp = xhci_port_state_to_neutral(temp); temp |= PORT_POWER; xhci_writel((__le32 __iomem *)addr, temp); } }
void enableXhciAllPortPower(struct xhci_hcd *xhci){ int i; u32 port_id, temp; u32 __iomem *addr; g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); for(i=1; i<=g_num_u3_port; i++){ port_id=i; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = readl(addr); temp = xhci_port_state_to_neutral(temp); temp |= PORT_POWER; writel(temp, addr); } for(i=1; i<=g_num_u2_port; i++){ port_id=i+g_num_u3_port; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = readl(addr); temp = xhci_port_state_to_neutral(temp); temp |= PORT_POWER; writel(temp, addr); } }
void mtktest_enableAllClockPower(){ int i; u32 temp; int num_u3_port; int num_u2_port; num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); //usb_phy_recover(0) ; //2. Enable xHC #if TEST_OTG writel(readl(SSUSB_IP_PW_CTRL) & (~SSUSB_IP_SW_RST), SSUSB_IP_PW_CTRL); writel(readl(SSUSB_IP_PW_CTRL_1) & (~SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); #else writel(readl(SSUSB_IP_PW_CTRL) | (SSUSB_IP_SW_RST), SSUSB_IP_PW_CTRL); writel(readl(SSUSB_IP_PW_CTRL) & (~SSUSB_IP_SW_RST), SSUSB_IP_PW_CTRL); writel(readl(SSUSB_IP_PW_CTRL_1) & (~SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); #endif //1. Enable target ports for(i=0; i<num_u3_port; i++){ temp = readl(SSUSB_U3_CTRL(i)); #if CON_HOST_DEV if(temp & SSUSB_U3_PORT_HOST_SEL){ temp = temp & (~SSUSB_U3_PORT_PDN) & (~SSUSB_U3_PORT_DIS); } #else temp = temp & (~SSUSB_U3_PORT_PDN) & (~SSUSB_U3_PORT_DIS); #endif writel(temp, SSUSB_U3_CTRL(i)); } for(i=0; i<num_u2_port; i++){ temp = readl(SSUSB_U2_CTRL(i)); #if CON_HOST_DEV if(temp & SSUSB_U2_PORT_HOST_SEL){ temp = temp & (~SSUSB_U2_PORT_PDN) & (~SSUSB_U2_PORT_DIS); } #else #if TEST_OTG temp = temp & (~SSUSB_U2_PORT_PDN) & (~SSUSB_U2_PORT_DIS) & (~SSUSB_U2_PORT_HOST_SEL); temp = temp | SSUSB_U2_PORT_OTG_SEL | SSUSB_U2_PORT_OTG_MAC_AUTO_SEL | SSUSB_U2_PORT_HOST_SEL; #else temp = temp & (~SSUSB_U2_PORT_PDN) & (~SSUSB_U2_PORT_DIS); #endif #endif writel(temp, SSUSB_U2_CTRL(i)); #if 0 writel(0xf, 0xf00447b0); writel((readl(0xf00447b4) & ~(0xffff) | (0x0001)), 0xf00447b4); writel((readl(0xf00447bc) & ~(0xff) | (0x0f)), 0xf00447bc); #endif } msleep(100); }
/* set 1 to PORT_POWER of PORT_STATUS register of each port */ void mtktest_enableXhciAllPortPower(struct xhci_hcd *xhci){ int i; u32 port_id, temp; u32 __iomem *addr; //#ifdef CONFIG_MTK_OTG_PMIC_BOOST_5V /* FIXME, USB_IF workaround, change original flow*/ #if 0 mtk_enable_pmic_otg_mode() ; #else /* FIXME, USB_IF workaround, change original flow*/ #ifdef CONFIG_MTK_OTG_PMIC_BOOST_5V mtk_enable_pmic_otg_mode(); #endif #if CON_HOST_DEV g_num_u3_port = getU3PortNumber(); g_num_u2_port = getU2PortNumber(); #else g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); #endif printk(KERN_ERR "[OTG_H]mtktest_enableXhciAllPortPower g_num_u3_port: %d, g_num_u2_port: %d\n", g_num_u3_port, g_num_u2_port); for(i=1; i<=g_num_u3_port; i++){ port_id=i; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = xhci_readl(xhci, addr); temp = mtktest_xhci_port_state_to_neutral(temp); temp |= PORT_POWER; xhci_writel(xhci, temp, addr); } for(i=1; i<=g_num_u2_port; i++){ port_id=i+g_num_u3_port; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = xhci_readl(xhci, addr); printk(KERN_ERR "[OTG_H]mtktest_enableXhciAllPortPower , read port_status_base: %x\n", temp); temp = mtktest_xhci_port_state_to_neutral(temp); temp |= PORT_POWER; xhci_writel(xhci, temp, addr); } temp = xhci_readl(xhci, addr); #endif printk(KERN_ERR "[OTG_H]mtktest_enableXhciAllPortPower , read port_status_base: %x\n", temp); }
static void setLatchSel(struct xhci_hcd *xhci) { void __iomem *latch_sel_addr; u32 latch_sel_value; int num_u3_port; num_u3_port = SSUSB_U3_PORT_NUM(readl((void __iomem *)_SSUSB_IP_CAP(xhci->sif_regs))); if (num_u3_port <= 0) return; latch_sel_addr = (void __iomem *) _U3_PIPE_LATCH_SEL_ADD(xhci->base_regs); latch_sel_value = ((U3_PIPE_LATCH_TX) << 2) | (U3_PIPE_LATCH_RX); writel(latch_sel_value, latch_sel_addr); }
//filter those ports assigned to device int getU3PortNumber(){ int port_num; int real_port_num; int i, temp; //check if any port assigned to device port_num = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); real_port_num = port_num; for(i=0; i<port_num; i++){ temp = readl(SSUSB_U3_CTRL(i)); if(!(temp & SSUSB_U3_PORT_HOST_SEL)){ real_port_num--; } } return real_port_num; }
//(X)disable clock/power of a port //(X)if all ports are disabled, disable IP ctrl power //disable all ports and IP clock/power, this is just mention HW that the power/clock of port //and IP could be disable if suspended. //If doesn't not disable all ports at first, the IP clock/power will never be disabled //(some U2 and U3 ports are binded to the same connection, that is, they will never enter suspend at the same time //port_index: port number //port_rev: 0x2 - USB2.0, 0x3 - USB3.0 (SuperSpeed) void disablePortClockPower(void){ int i; u32 temp; g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); for(i=0; i<g_num_u3_port; i++){ temp = readl(SSUSB_U3_CTRL(i)); temp = temp | (SSUSB_U3_PORT_PDN); writel(temp, SSUSB_U3_CTRL(i)); } for(i=0; i<g_num_u2_port; i++){ temp = readl(SSUSB_U2_CTRL(i)); temp = temp | (SSUSB_U2_PORT_PDN); writel(temp, SSUSB_U2_CTRL(i)); } writel(readl(SSUSB_IP_PW_CTRL_1) | (SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); }
//called after HC initiated void mtktest_disableAllClockPower(){ int i; u32 temp; int num_u3_port; int num_u2_port; #if TEST_OTG return; #endif num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); //disable target ports for(i=0; i<num_u3_port; i++){ temp = readl(SSUSB_U3_CTRL(i)); #if CON_HOST_DEV if(temp & SSUSB_U3_PORT_HOST_SEL){ temp = temp | SSUSB_U3_PORT_PDN; } #else temp = temp | SSUSB_U3_PORT_PDN; #endif writel(temp, SSUSB_U3_CTRL(i)); } for(i=0; i<num_u2_port; i++){ temp = readl(SSUSB_U2_CTRL(i)); #if CON_HOST_DEV if(temp & SSUSB_U2_PORT_HOST_SEL){ temp = temp | SSUSB_U2_PORT_PDN; } #else temp = temp | SSUSB_U2_PORT_PDN; #endif writel(temp, SSUSB_U2_CTRL(i)); } msleep(100); }
/* set 0 to PORT_POWER of PORT_STATUS register of each port */ void mtktest_disableXhciAllPortPower(struct xhci_hcd *xhci){ int i; u32 port_id, temp; u32 __iomem *addr; #ifdef CONFIG_MTK_OTG_PMIC_BOOST_5V mtk_disable_pmic_otg_mode() ; #else #if CON_HOST_DEV g_num_u3_port = getU3PortNumber(); g_num_u2_port = getU2PortNumber(); #else g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); #endif for(i=1; i<=g_num_u3_port; i++){ port_id=i; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = xhci_readl(xhci, addr); temp = mtktest_xhci_port_state_to_neutral(temp); temp &= ~PORT_POWER; xhci_writel(xhci, temp, addr); while(xhci_readl(xhci, addr) & PORT_POWER); } for(i=1; i<=g_num_u2_port; i++){ port_id=i+g_num_u3_port; addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); temp = xhci_readl(xhci, addr); temp = mtktest_xhci_port_state_to_neutral(temp); temp &= ~PORT_POWER; xhci_writel(xhci, temp, addr); while(xhci_readl(xhci, addr) & PORT_POWER); } #endif }
int uphy_init(void) { u32 i, reg_val, check_val, num_port_u2, num_port_u3; if (atomic_inc_return(&uphy_init_instance) != 1) return 0; /* patch TxDetRx Timing for E1, from DR 20160421, Biker_20160516 */ reg_val = uphy_read32(ADDR_SIFSLV_PHYD_B2_BASE + 0x28); reg_val &= ~(0x1ff << 9); reg_val |= (0x010 << 9); uphy_write32(ADDR_SIFSLV_PHYD_B2_BASE + 0x28, reg_val); reg_val = uphy_read32(ADDR_SIFSLV_PHYD_B2_BASE + 0x2c); reg_val &= ~0x1ff; reg_val |= 0x010; uphy_write32(ADDR_SIFSLV_PHYD_B2_BASE + 0x2c, reg_val); /* patch LFPS Filter Threshold for E1, from DR 20160421, Biker_20160516 */ reg_val = uphy_read32(ADDR_SIFSLV_PHYD_BASE + 0x0c); reg_val &= ~(0x3f << 16); reg_val |= (0x34 << 16); uphy_write32(ADDR_SIFSLV_PHYD_BASE + 0x0c, reg_val); /* configure for XTAL 25MHz */ if (VPint(CR_AHB_HWCONF) & 0x01) { uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1c, 0x18); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1d, 0x18); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x1f, 0x18); uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x24, 0x18000000); uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x28, 0x18000000); uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x30, 0x18000000); uphy_write32(ADDR_SIFSLV_PHYA_DA_BASE + 0x38, 0x004a004a); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x3e, 0x4a); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x3f, 0x0); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x42, 0x48); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x43, 0x0); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x44, 0x48); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x45, 0x0); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x48, 0x48); uphy_write8(ADDR_SIFSLV_PHYA_DA_BASE + 0x49, 0x0); uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x24, 0x90); uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x25, 0x1); uphy_write32(ADDR_SIFSLV_PHYA_BASE + 0x10, 0x1c000000); uphy_write8(ADDR_SIFSLV_PHYA_BASE + 0x0b, 0xe); } reg_val = uphy_read32(REG_SSUSB_IP_CAP); num_port_u3 = SSUSB_U3_PORT_NUM(reg_val); num_port_u2 = SSUSB_U2_PORT_NUM(reg_val); if (isEN7513 || isEN7513G) { printk(KERN_INFO "%s USB PHY config\n", "EN7513 (BGA)"); uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0240008); /* enable port 0 */ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */ } else if (isEN7512) { printk(KERN_INFO "%s USB PHY config\n", "EN7512 (QFP)"); uphy_write32(ADDR_U2_PHY_P0_BASE + 0x1c, 0xC0241580); /* disable port 0 */ uphy_write32(ADDR_U2_PHY_P1_BASE + 0x1c, 0xC0240000); /* enable port 1 */ } /* calibrate UPHY */ u2_slew_rate_calibration(0, ADDR_U2_PHY_P0_BASE); u2_slew_rate_calibration(1, ADDR_U2_PHY_P1_BASE); /* soft reset xHCI HC */ reg_val = uphy_read32(REG_SSUSB_IP_PW_CTRL0); uphy_write32(REG_SSUSB_IP_PW_CTRL0, (reg_val | (SSUSB_IP_SW_RST))); uphy_write32(REG_SSUSB_IP_PW_CTRL0, (reg_val & (~SSUSB_IP_SW_RST))); /* enable xHCI HC power */ reg_val = uphy_read32(REG_SSUSB_IP_PW_CTRL1); reg_val &= ~SSUSB_IP_PDN; uphy_write32(REG_SSUSB_IP_PW_CTRL1, reg_val); /* enable target USB3 ports */ for (i = 0; i < num_port_u3; i++) { reg_val = uphy_read32(REG_SSUSB_U3_CTRL(i)); reg_val &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS); uphy_write32(REG_SSUSB_U3_CTRL(i), reg_val); } /* enable target USB2 ports */ for (i = 0; i < num_port_u2; i++) { reg_val = uphy_read32(REG_SSUSB_U2_CTRL(i)); reg_val &= ~(SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_DIS); uphy_write32(REG_SSUSB_U2_CTRL(i), reg_val); } /* wait for clocks to be stable */ check_val = SSUSB_STS1_SYSPLL_STABLE | SSUSB_STS1_REF_RST | SSUSB_STS1_SYS125_RST | SSUSB_STS1_XHCI_RST; if (num_port_u3 > 0) check_val |= SSUSB_STS1_U3_MAC_RST; for (i = 0; i < 10; i++) { msleep(50); reg_val = uphy_read32(REG_SSUSB_IP_PW_STS1); if ((reg_val & check_val) == check_val) return 0; } printk(KERN_ERR "xhci clocks are not stable (IP_PW_STS1: 0x%x)\n", reg_val); return -ENODEV; }
int mtk_xhci_get_port_num(void) { return SSUSB_U3_PORT_NUM(readl((void __iomem *)SSUSB_IP_CAP)) + SSUSB_U2_PORT_NUM(readl((void __iomem *)SSUSB_IP_CAP)); }
void mtk_xhci_ck_timer_init(struct xhci_hcd *xhci) { void __iomem *addr; u32 temp = 0; int num_u3_port; unsigned int hw_code = mt_get_chip_hw_code(); CHIP_SW_VER sw_code = mt_get_chip_sw_ver(); mtk_xhci_mtk_log("hw code(0x%x), sw_code(0x%x)\n", hw_code, sw_code); if (0x6595 == hw_code) { /* The sys125_ck = 1/2 sys_ck = 62.5MHz */ addr = (void __iomem *)_SSUSB_SYS_CK_CTRL(xhci->sif_regs); temp = readl(addr); temp |= SSUSB_SYS_CK_DIV2_EN; writel(temp, addr); mtk_xhci_mtk_log("mu3d sys_clk, addr 0x%p, value 0x%x\n", (void *)_SSUSB_SYS_CK_CTRL(xhci->sif_regs), readl((__u32 __iomem *)_SSUSB_SYS_CK_CTRL(xhci->sif_regs))); num_u3_port = SSUSB_U3_PORT_NUM(readl((void __iomem *)_SSUSB_IP_CAP(xhci->sif_regs))); if (num_u3_port) { #if 0 //set MAC reference clock speed addr = (void __iomem *) (_SSUSB_U3_MAC_BASE(xhci->base_regs) + U3_UX_EXIT_LFPS_TIMING_PAR); temp = readl(addr); temp &= ~(0xff << U3_RX_UX_EXIT_LFPS_REF_OFFSET); temp |= (U3_RX_UX_EXIT_LFPS_REF << U3_RX_UX_EXIT_LFPS_REF_OFFSET); writel(temp, addr); addr = (void __iomem *)(_SSUSB_U3_MAC_BASE(xhci->base_regs) + U3_REF_CK_PAR); temp = readl(addr); temp &= ~(0xff); temp |= U3_REF_CK_VAL; writel(temp, addr); #endif /* set U3 MAC SYS_CK */ addr = (void __iomem *)(_SSUSB_U3_SYS_BASE(xhci->base_regs) + U3_TIMING_PULSE_CTRL); temp = readl(addr); temp &= ~(0xff); temp |= MTK_CNT_1US_VALUE; writel(temp, addr); } /* set U2 MAC SYS_CK */ addr = (void __iomem *)(_SSUSB_U2_SYS_BASE(xhci->base_regs) + USB20_TIMING_PARAMETER); temp &= ~(0xff); temp |= MTK_TIME_VALUE_1US; writel(temp, addr); mtk_xhci_mtk_log("mu3d u2 mac sys_clk, addr 0x%p, value 0x%x\n", (void *)(_SSUSB_U2_SYS_BASE(xhci->base_regs) + USB20_TIMING_PARAMETER), readl((void __iomem *)(_SSUSB_U2_SYS_BASE(xhci->base_regs) + (unsigned long)USB20_TIMING_PARAMETER))); #if 0 if (num_u3_port) { //set LINK_PM_TIMER=3 addr = (void __iomem *)(_SSUSB_U3_SYS_BASE(xhci->base_regs) + LINK_PM_TIMER); temp = readl(addr); temp &= ~(0xf); temp |= MTK_PM_LC_TIMEOUT_VALUE; writel(temp, addr); } #endif } }