int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { u3phy_init(); mt7621_phy_init(u3phy); reinitIP(); u2_slew_rate_calibration(u3phy); u2_slew_rate_calibration(u3phy_p1); *hccr = (uint32_t)XHC_IO_START; *hcor = (struct xhci_hcor *)((uint32_t) *hccr + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); debug("mtk-xhci: init hccr %x and hcor %x hc_length %d\n", (uint32_t)*hccr, (uint32_t)*hcor, (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); return 0; }
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; }