/* only port0 of U2/U3 supports device mode */ static int mtu3_device_enable(struct mtu3 *mtu) { void __iomem *ibase = mtu->ippc_base; u32 check_clk = 0; mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); if (mtu->is_u3_ip) { check_clk = SSUSB_U3_MAC_RST_B_STS; mtu3_clrbits(ibase, SSUSB_U3_CTRL(0), (SSUSB_U3_PORT_DIS | SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_HOST_SEL)); } mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), (SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN | SSUSB_U2_PORT_HOST_SEL)); if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) { mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); if (mtu->is_u3_ip) mtu3_setbits(ibase, SSUSB_U3_CTRL(0), SSUSB_U3_PORT_DUAL_MODE); } return ssusb_check_clocks(mtu->ssusb, check_clk); }
static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) { /* reset whole ip (xhci & u3d) */ mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); udelay(1); mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); }
/* reset: u2 - data toggle, u3 - SeqN, flow control status etc */ static void mtu3_ep_reset(struct mtu3_ep *mep) { struct mtu3 *mtu = mep->mtu; u32 rst_bit = EP_RST(mep->is_in, mep->epnum); mtu3_setbits(mtu->mac_base, U3D_EP_RST, rst_bit); mtu3_clrbits(mtu->mac_base, U3D_EP_RST, rst_bit); }
/* reset U3D's device module. */ static void mtu3_device_reset(struct mtu3 *mtu) { void __iomem *ibase = mtu->ippc_base; mtu3_setbits(ibase, U3D_SSUSB_DEV_RST_CTRL, SSUSB_DEV_SW_RST); udelay(1); mtu3_clrbits(ibase, U3D_SSUSB_DEV_RST_CTRL, SSUSB_DEV_SW_RST); }
/* enable/disable U3D SS function */ static inline void mtu3_ss_func_set(struct mtu3 *mtu, bool enable) { /* If usb3_en==0, LTSSM will go to SS.Disable state */ if (enable) mtu3_setbits(mtu->mac_base, U3D_USB3_CONFIG, USB3_EN); else mtu3_clrbits(mtu->mac_base, U3D_USB3_CONFIG, USB3_EN); dev_dbg(mtu->dev, "USB3_EN = %d\n", !!enable); }
/* set/clear U3D HS device soft connect */ static inline void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable) { if (enable) { mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN | SUSPENDM_ENABLE); } else { mtu3_clrbits(mtu->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN | SUSPENDM_ENABLE); } dev_dbg(mtu->dev, "SOFTCONN = %d\n", !!enable); }
void mtu3_start(struct mtu3 *mtu) { void __iomem *mbase = mtu->mac_base; dev_dbg(mtu->dev, "%s devctl 0x%x\n", __func__, mtu3_readl(mbase, U3D_DEVICE_CONTROL)); mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); /* * When disable U2 port, USB2_CSR's register will be reset to * default value after re-enable it again(HS is enabled by default). * So if force mac to work as FS, disable HS function. */ if (mtu->max_speed == USB_SPEED_FULL) mtu3_clrbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); /* Initialize the default interrupts */ mtu3_intr_enable(mtu); mtu->is_active = 1; if (mtu->softconnect) mtu3_dev_on_off(mtu, 1); }
static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) { /* reset whole ip (xhci & u3d) */ mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); udelay(1); mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); /* * device ip may be powered on in firmware/BROM stage before entering * kernel stage; * power down device ip, otherwise ip-sleep will fail when working as * host only mode */ mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); }
static void mtu3_device_disable(struct mtu3 *mtu) { void __iomem *ibase = mtu->ippc_base; if (mtu->is_u3_ip) mtu3_setbits(ibase, SSUSB_U3_CTRL(0), (SSUSB_U3_PORT_DIS | SSUSB_U3_PORT_PDN)); mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN); if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); }