/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include "mtk-phy.h" #ifdef CONFIG_PROJECT_PHY /*#include */ #include #include #include "mtk-phy-asic.h" #include "mu3d_hal_osal.h" #ifdef CONFIG_MTK_UART_USB_SWITCH #include "mu3d_hal_usb_drv.h" #endif #include /* k414 FIXME */ //#include "mtk_spm_resource_req.h" //#include "mtk_idle.h" #//include "mtk_clk_id.h" #include "musb_core.h" #include #include #include #include #include #include #include #include #include #include #include "mtk_devinfo.h" static int usb20_phy_rev6; static struct clk *ssusb_clk; static struct clk *sys_ck; static DEFINE_SPINLOCK(mu3phy_clock_lock); bool sib_mode; static struct regulator *reg_vusb; static struct regulator *reg_va09; enum VA09_OP { VA09_OP_OFF = 0, VA09_OP_ON, }; static void VA09_operation(int op, bool force) { int ret = 0; static bool on; /* only musb_speed or force could pass it */ if (!musb_speed && !force) return; if (!reg_va09) return; if (op == VA09_OP_ON && !on) { ret = regulator_enable(reg_va09); if (ret < 0) { pr_notice("regulator_enable va09 failed: %d\n", ret); return; } on = true; } else if (op == VA09_OP_OFF && on) { ret = regulator_disable(reg_va09); if (ret < 0) { pr_notice("regulator_enable va09 failed: %d\n", ret); return; } on = false; } } static int dpidle_status = USB_DPIDLE_ALLOWED; /* k414 FIXME */ //static DEFINE_SPINLOCK(usb_hal_dpidle_lock); #define DPIDLE_TIMER_INTERVAL_MS 30 static void issue_dpidle_timer(void); static void dpidle_timer_wakeup_func(unsigned long data) { struct timer_list *timer = (struct timer_list *)data; { static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 1); static int skip_cnt; if (__ratelimit(&ratelimit)) { os_printk(K_INFO, "dpidle_timer<%p> alive, skip_cnt<%d>\n", timer, skip_cnt); skip_cnt = 0; } else skip_cnt++; } os_printk(K_DEBUG, "dpidle_timer<%p> alive...\n", timer); if (dpidle_status == USB_DPIDLE_TIMER) issue_dpidle_timer(); kfree(timer); } static void issue_dpidle_timer(void) { struct timer_list *timer; timer = kzalloc(sizeof(struct timer_list), GFP_ATOMIC); if (!timer) return; os_printk(K_DEBUG, "add dpidle_timer<%p>\n", timer); init_timer(timer); timer->function = dpidle_timer_wakeup_func; timer->data = (unsigned long)timer; timer->expires = jiffies + msecs_to_jiffies(DPIDLE_TIMER_INTERVAL_MS); add_timer(timer); } void usb_hal_dpidle_request(int mode) { /* k414 FIXME */ #if 0 unsigned long flags; #ifdef U3_COMPLIANCE os_printk(K_INFO, "%s, U3_COMPLIANCE, fake to USB_DPIDLE_FORBIDDEN\n", __func__); mode = USB_DPIDLE_FORBIDDEN; #endif spin_lock_irqsave(&usb_hal_dpidle_lock, flags); /* update dpidle_status */ dpidle_status = mode; switch (mode) { case USB_DPIDLE_ALLOWED: spm_resource_req(SPM_RESOURCE_USER_SSUSB, SPM_RESOURCE_RELEASE); os_printk(K_INFO, "USB_DPIDLE_ALLOWED\n"); break; case USB_DPIDLE_FORBIDDEN: spm_resource_req(SPM_RESOURCE_USER_SSUSB, SPM_RESOURCE_ALL); { static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 3); if (__ratelimit(&ratelimit)) os_printk(K_INFO, "USB_DPIDLE_FORBIDDEN\n"); } break; case USB_DPIDLE_SRAM: spm_resource_req(SPM_RESOURCE_USER_SSUSB, SPM_RESOURCE_CK_26M | SPM_RESOURCE_MAINPLL); { static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 3); static int skip_cnt; if (__ratelimit(&ratelimit)) { os_printk(K_INFO, "USB_DPIDLE_SRAM, skip_cnt<%d>\n", skip_cnt); skip_cnt = 0; } else skip_cnt++; } break; case USB_DPIDLE_TIMER: spm_resource_req(SPM_RESOURCE_USER_SSUSB, SPM_RESOURCE_CK_26M | SPM_RESOURCE_MAINPLL); os_printk(K_INFO, "USB_DPIDLE_TIMER\n"); issue_dpidle_timer(); break; default: os_printk(K_WARNIN, "[ERROR] Are you kidding!?!?\n"); break; } spin_unlock_irqrestore(&usb_hal_dpidle_lock, flags); #endif } static bool usb_enable_clock(bool enable) { static int count; unsigned long flags; if (!ssusb_clk || IS_ERR(ssusb_clk)) { pr_notice("clock not ready, ssusb_clk:%p", ssusb_clk); return -1; } if (!sys_ck || IS_ERR(sys_ck)) { pr_notice("clock not ready, sys_ck:%p", sys_ck); return -1; } spin_lock_irqsave(&mu3phy_clock_lock, flags); os_printk(K_INFO, "CG, enable<%d>, count<%d>\n", enable, count); if (enable && count == 0) { usb_hal_dpidle_request(USB_DPIDLE_FORBIDDEN); if (clk_enable(ssusb_clk) != 0) pr_notice("ssusb_ref_clk enable fail\n"); if (clk_enable(sys_ck) != 0) pr_notice("sys_ck enable fail\n"); } else if (!enable && count == 1) { clk_disable(ssusb_clk); clk_disable(sys_ck); usb_hal_dpidle_request(USB_DPIDLE_ALLOWED); } if (enable) count++; else count = (count == 0) ? 0 : (count - 1); spin_unlock_irqrestore(&mu3phy_clock_lock, flags); return 0; } void usb20_pll_settings(bool host, bool forceOn) { } void usb20_rev6_setting(int value, bool is_update) { if (is_update) usb20_phy_rev6 = value; U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_PHY_REV_6_OFST, RG_USB20_PHY_REV_6, value); } #ifdef CONFIG_MTK_UART_USB_SWITCH bool in_uart_mode; void uart_usb_switch_dump_register(void) { /* f_fusb30_ck:125MHz */ usb_enable_clock(true); udelay(250); # ifdef CONFIG_MTK_FPGA pr_debug("[MUSB]addr: 0x6B, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0 + 0x3)); pr_debug("[MUSB]addr: 0x6E, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM1 + 0x2)); pr_debug("[MUSB]addr: 0x22, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYACR4 + 0x2)); pr_debug("[MUSB]addr: 0x68, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0)); pr_debug("[MUSB]addr: 0x6A, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYDTM0 + 0x2)); pr_debug("[MUSB]addr: 0x1A, value: %x\n", USB_PHY_Read_Register8((phys_addr_t) (uintptr_t)U3D_U2PHYACR6 + 0x2)); #else #if 0 os_printk(K_INFO, "[MUSB]addr: 0x6B, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0 + 0x3)); os_printk(K_INFO, "[MUSB]addr: 0x6E, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM1 + 0x2)); os_printk(K_INFO, "[MUSB]addr: 0x22, value: %x\n", U3PhyReadReg8(U3D_U2PHYACR4 + 0x2)); os_printk(K_INFO, "[MUSB]addr: 0x68, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0)); os_printk(K_INFO, "[MUSB]addr: 0x6A, value: %x\n", U3PhyReadReg8(U3D_U2PHYDTM0 + 0x2)); os_printk(K_INFO, "[MUSB]addr: 0x1A, value: %x\n", U3PhyReadReg8(U3D_USBPHYACR6 + 0x2)); #else os_printk(K_INFO, "[MUSB]addr: 0x18, value: 0x%x\n", U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6)); os_printk(K_INFO, "[MUSB]addr: 0x20, value: 0x%x\n", U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4)); os_printk(K_INFO, "[MUSB]addr: 0x68, value: 0x%x\n", U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0)); os_printk(K_INFO, "[MUSB]addr: 0x6C, value: 0x%x\n", U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1)); #endif #endif /* f_fusb30_ck:125MHz */ usb_enable_clock(false); /*os_printk(K_INFO, "[MUSB]addr: 0x110020B0 (UART0), value: %x\n\n", */ /* DRV_Reg8(ap_uart0_base + 0xB0)); */ } bool usb_phy_check_in_uart_mode(void) { PHY_INT32 usb_port_mode; /* f_fusb30_ck:125MHz */ usb_enable_clock(true); udelay(250); usb_port_mode = U3PhyReadReg32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0) >> RG_UART_MODE_OFST; /* f_fusb30_ck:125MHz */ usb_enable_clock(false); os_printk(K_INFO, "%s+ usb_port_mode = %d\n", __func__, usb_port_mode); if (usb_port_mode == 0x1) return true; else return false; } void usb_phy_switch_to_uart(void) { if (usb_phy_check_in_uart_mode()) { os_printk(K_INFO, "%s+ UART_MODE\n", __func__); return; } os_printk(K_INFO, "%s+ USB_MODE\n", __func__); VA09_operation(VA09_OP_ON, false); /* f_fusb30_ck:125MHz */ usb_enable_clock(true); udelay(250); /* RG_USB20_BC11_SW_EN = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 0); /* RG_SUSPENDM to 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 1); /* force suspendm = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 1); /* rg_uart_mode = 2'b01 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_UART_MODE_OFST, RG_UART_MODE, 1); /* force_uart_i = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_I_OFST, FORCE_UART_I, 0); /* force_uart_bias_en = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_BIAS_EN_OFST, FORCE_UART_BIAS_EN, 1); /* force_uart_tx_oe = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_TX_OE_OFST, FORCE_UART_TX_OE, 1); /* force_uart_en = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 1); /* RG_UART_BIAS_EN = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_BIAS_EN_OFST, RG_UART_BIAS_EN, 1); /* RG_UART_TX_OE = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_TX_OE_OFST, RG_UART_TX_OE, 1); /* RG_UART_EN = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 1); /* RG_USB20_DM_100K_EN = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, RG_USB20_DM_100K_EN, 1); /* force_linestate = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_LINESTATE_OFST, FORCE_LINESTATE, 1); /* RG_LINESTATE = 2'b01 (J State) */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_LINESTATE_OFST, RG_LINESTATE, 0x1); /* f_fusb30_ck:125MHz */ usb_enable_clock(false); /* SET USB to UART GPIO to UART0 */ DRV_WriteReg32(ap_uart0_base + 0x6E0, (DRV_Reg32(ap_uart0_base + 0x6E0) | (1<<20))); in_uart_mode = true; } void usb_phy_switch_to_usb(void) { in_uart_mode = false; /* force_uart_i = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_I_OFST, FORCE_UART_I, 1); /* force_uart_en = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 1); /* RG_UART_EN = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); /* RG_USB20_DM_100K_EN = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, RG_USB20_DM_100K_EN, 0); /* rg_uart_mode = 2'b00 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_UART_MODE_OFST, RG_UART_MODE, 0); /* force_dp_pulldown 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DP_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DP_PULLDOWN_OFST, FORCE_DP_PULLDOWN, 0); /* force_dm_pulldown 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DM_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DM_PULLDOWN_OFST, FORCE_DM_PULLDOWN, 0); /* force_xcversel 1'b0 */ /* U3D_U2PHYDTM0 FORCE_XCVRSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_XCVRSEL_OFST, FORCE_XCVRSEL, 0); /* force_termsel 1'b0 */ /* U3D_U2PHYDTM0 FORCE_TERMSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_TERMSEL_OFST, FORCE_TERMSEL, 0); /* force_datain 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DATAIN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DATAIN_OFST, FORCE_DATAIN, 0); /* force_linestate = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_LINESTATE_OFST, FORCE_LINESTATE, 0); /* CLEAR USB to UART GPIO to UART0 */ DRV_WriteReg32(ap_uart0_base + 0x6E0, (DRV_Reg32(ap_uart0_base + 0x6E0) & ~(1<<20))); phy_init_soc(u3phy); /* f_fusb30_ck:125MHz */ usb_enable_clock(false); } #endif #ifdef CONFIG_U3_PHY_SMT_LOOP_BACK_SUPPORT #define USB30_PHYD_PIPE0 (SSUSB_SIFSLV_U3PHYD_BASE+0x40) #define USB30_PHYD_RX0 (SSUSB_SIFSLV_U3PHYD_BASE+0x2c) #define USB30_PHYD_MIX0 (SSUSB_SIFSLV_U3PHYD_BASE+0x0) #define USB30_PHYD_T2RLB (SSUSB_SIFSLV_U3PHYD_BASE+0x30) bool u3_loop_back_test(void) { int reg; bool loop_back_ret = false; VA09_operation(VA09_OP_ON, true); usb_enable_clock(true); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 1); /*SSUSB_IP_SW_RST = 0*/ writel(readl(U3D_SSUSB_IP_PW_CTRL0)&~(SSUSB_IP_SW_RST), U3D_SSUSB_IP_PW_CTRL0); /*SSUSB_IP_HOST_PDN = 0*/ writel(readl(U3D_SSUSB_IP_PW_CTRL1)&~(SSUSB_IP_HOST_PDN), U3D_SSUSB_IP_PW_CTRL1); /*SSUSB_IP_DEV_PDN = 0*/ writel(readl(U3D_SSUSB_IP_PW_CTRL2)&~(SSUSB_IP_DEV_PDN), U3D_SSUSB_IP_PW_CTRL2); /*SSUSB_IP_PCIE_PDN = 0*/ writel(readl(U3D_SSUSB_IP_PW_CTRL3)&~(SSUSB_IP_PCIE_PDN), U3D_SSUSB_IP_PW_CTRL3); /*SSUSB_U3_PORT_DIS/SSUSB_U3_PORT_PDN = 0*/ writel(readl(U3D_SSUSB_U3_CTRL_0P)&~(SSUSB_IP_PCIE_PDN | SSUSB_U3_PORT_PDN), U3D_SSUSB_U3_CTRL_0P); mdelay(10); writel((readl(USB30_PHYD_PIPE0)&~(0x01<<30))|0x01<<30, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x01<<28))|0x00<<28, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x03<<26))|0x01<<26, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x03<<24))|0x00<<24, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x01<<22))|0x00<<22, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x01<<21))|0x00<<21, USB30_PHYD_PIPE0); writel((readl(USB30_PHYD_PIPE0)&~(0x01<<20))|0x01<<20, USB30_PHYD_PIPE0); mdelay(10); /*T2R loop back disable*/ writel((readl(USB30_PHYD_RX0)&~(0x01<<15))|0x00<<15, USB30_PHYD_RX0); mdelay(10); /* TSEQ lock detect threshold */ writel((readl(USB30_PHYD_MIX0)&~(0x07<<24))|0x07<<24, USB30_PHYD_MIX0); /* set default TSEQ polarity check value = 1 */ writel((readl(USB30_PHYD_MIX0)&~(0x01<<28))|0x01<<28, USB30_PHYD_MIX0); /* TSEQ polarity check enable */ writel((readl(USB30_PHYD_MIX0)&~(0x01<<29))|0x01<<29, USB30_PHYD_MIX0); /* TSEQ decoder enable */ writel((readl(USB30_PHYD_MIX0)&~(0x01<<30))|0x01<<30, USB30_PHYD_MIX0); mdelay(10); /* set T2R loop back TSEQ length (x 16us) */ writel((readl(USB30_PHYD_T2RLB)&~(0xff<<0))|0xF0<<0, USB30_PHYD_T2RLB); /* set T2R loop back BDAT reset period (x 16us) */ writel((readl(USB30_PHYD_T2RLB)&~(0x0f<<12))|0x0F<<12, USB30_PHYD_T2RLB); /* T2R loop back pattern select */ writel((readl(USB30_PHYD_T2RLB)&~(0x03<<8))|0x00<<8, USB30_PHYD_T2RLB); mdelay(10); /* T2R loop back serial mode */ writel((readl(USB30_PHYD_RX0)&~(0x01<<13))|0x01<<13, USB30_PHYD_RX0); /* T2R loop back parallel mode = 0 */ writel((readl(USB30_PHYD_RX0)&~(0x01<<12))|0x00<<12, USB30_PHYD_RX0); /* T2R loop back mode enable */ writel((readl(USB30_PHYD_RX0)&~(0x01<<11))|0x01<<11, USB30_PHYD_RX0); /* T2R loop back enable */ writel((readl(USB30_PHYD_RX0)&~(0x01<<15))|0x01<<15, USB30_PHYD_RX0); mdelay(100); reg = U3PhyReadReg32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_U3PHYD_BASE+0xb4)); os_printk(K_INFO, "read back : 0x%x\n", reg); os_printk(K_INFO, "read back t2rlb_lock : %d\n", (reg>>2)&0x01); os_printk(K_INFO, "read back t2rlb_pass : %d\n", (reg>>3)&0x01); os_printk(K_INFO, "read back t2rlb_passth: %d\n", (reg>>4)&0x01); if ((reg&0x0E) == 0x0E) loop_back_ret = true; else loop_back_ret = false; return loop_back_ret; } #endif #ifdef CONFIG_MTK_SIB_USB_SWITCH #include static struct wake_lock sib_wakelock; void usb_phy_sib_enable_switch(bool enable) { static int inited; if (!inited) { os_printk(K_INFO, "%s wake_lock_init\n", __func__); wake_lock_init(&sib_wakelock, WAKE_LOCK_SUSPEND, "SIB.lock"); inited = 1; } VA09_operation(VA09_OP_ON, true); usb_enable_clock(true); udelay(250); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 1); /* SSUSB_IP_SW_RST = 0 */ U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_ippc_base + 0x0), 0x00031000); /* SSUSB_IP_HOST_PDN = 0 */ U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_ippc_base + 0x4), 0x00000000); /* SSUSB_IP_DEV_PDN = 0 */ U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_ippc_base + 0x8), 0x00000000); /* SSUSB_IP_PCIE_PDN = 0 */ U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_ippc_base + 0xC), 0x00000000); /* SSUSB_U3_PORT_DIS/SSUSB_U3_PORT_PDN = 0*/ U3PhyWriteReg32((phys_addr_t) (uintptr_t) (u3_ippc_base + 0x30), 0x0000000C); /* * USBMAC mode is 0x62910002 (bit 1) * MDSIB mode is 0x62910008 (bit 3) * 0x0629 just likes a signature. Can't be removed. */ if (enable) { U3PhyWriteReg32((phys_addr_t) (uintptr_t) SSUSB_SIFSLV_CHIP_BASE, 0x62910008); sib_mode = true; if (!wake_lock_active(&sib_wakelock)) wake_lock(&sib_wakelock); } else { U3PhyWriteReg32((phys_addr_t) (uintptr_t) SSUSB_SIFSLV_CHIP_BASE, 0x62910002); sib_mode = false; if (wake_lock_active(&sib_wakelock)) wake_unlock(&sib_wakelock); } } bool usb_phy_sib_enable_switch_status(void) { int reg; bool ret; VA09_operation(VA09_OP_ON, true); usb_enable_clock(true); udelay(250); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 1); reg = U3PhyReadReg32((phys_addr_t) (uintptr_t) SSUSB_SIFSLV_CHIP_BASE); if (reg == 0x62910008) ret = true; else ret = false; return ret; } #endif #ifdef CONFIG_MTK_USB2JTAG_SUPPORT int usb2jtag_usb_init(void) { struct device_node *node = NULL; void __iomem *usb3_sif2_base; u32 temp; node = of_find_compatible_node(NULL, NULL, "mediatek,usb3"); if (!node) { pr_notice("[USB2JTAG] map node @ mediatek,usb3 failed\n"); return -1; } usb3_sif2_base = of_iomap(node, 2); if (!usb3_sif2_base) { pr_notice("[USB2JTAG] iomap usb3_sif2_base failed\n"); return -1; } /* rg_usb20_gpio_ctl: bit[9] = 1 */ temp = readl(usb3_sif2_base + 0x320); writel(temp | (1 << 9), usb3_sif2_base + 0x320); /* RG_USB20_BC11_SW_EN: bit[23] = 0 */ temp = readl(usb3_sif2_base + 0x318); writel(temp & ~(1 << 23), usb3_sif2_base + 0x318); /* RG_USB20_BGR_EN: bit[0] = 1 */ temp = readl(usb3_sif2_base + 0x300); writel(temp | (1 << 0), usb3_sif2_base + 0x300); /* rg_sifslv_mac_bandgap_en: bit[17] = 0 */ temp = readl(usb3_sif2_base + 0x308); writel(temp & ~(1 << 17), usb3_sif2_base + 0x308); /* wait stable */ mdelay(1); iounmap(usb3_sif2_base); return 0; } #endif #define VAL_MAX_WIDTH_2 0x3 #define VAL_MAX_WIDTH_3 0x7 void usb_phy_tuning(void) { static bool inited; static s32 u2_vrt_ref, u2_term_ref, u2_enhance; static struct device_node *of_node; if (!inited) { u2_vrt_ref = u2_term_ref = u2_enhance = -1; of_node = of_find_compatible_node(NULL, NULL, "mediatek,phy_tuning"); if (of_node) { /* value won't be updated if property not being found */ of_property_read_u32(of_node, "u2_vrt_ref", (u32 *) &u2_vrt_ref); of_property_read_u32(of_node, "u2_term_ref", (u32 *) &u2_term_ref); of_property_read_u32(of_node, "u2_enhance", (u32 *) &u2_enhance); } inited = true; } else if (!of_node) return; if (u2_vrt_ref != -1) { if (u2_vrt_ref <= VAL_MAX_WIDTH_3) { U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_VRT_VREF_SEL_OFST, RG_USB20_VRT_VREF_SEL, u2_vrt_ref); } } if (u2_term_ref != -1) { if (u2_term_ref <= VAL_MAX_WIDTH_3) { U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_TERM_VREF_SEL_OFST, RG_USB20_TERM_VREF_SEL, u2_term_ref); } } if (u2_enhance != -1) { if (u2_enhance <= VAL_MAX_WIDTH_2) { U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_PHY_REV_6_OFST, RG_USB20_PHY_REV_6, u2_enhance); } } } PHY_INT32 phy_init_soc(struct u3phy_info *info) { os_printk(K_INFO, "%s+\n", __func__); /*This power on sequence refers to Sheet .1 of "6593_USB_PORT0_PWR Sequence 20130729.xls" */ VA09_operation(VA09_OP_ON, false); /* f_fusb30_ck:125MHz */ usb_enable_clock(true); /*Wait 50 usec */ udelay(250); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 1); #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) goto reg_done; #endif /*switch to USB function. (system register, force ip into usb mode) */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, 0); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); /*DP/DM BC1.1 path Disable */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 0); /*dp_100k disable */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DP_100K_MODE_OFST, RG_USB20_DP_100K_MODE, 1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_DP_100K_EN_OFST, USB20_DP_100K_EN, 0); /*dm_100k disable */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_DM_100K_EN_OFST, RG_USB20_DM_100K_EN, 0); /*OTG Enable */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, RG_USB20_OTG_VBUSCMP_EN, 1); /*Release force suspendm. (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 0); /*Wait 800 usec */ udelay(800); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_VBUSVALID_OFST, FORCE_VBUSVALID, 1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_AVALID_OFST, FORCE_AVALID, 1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, FORCE_SESSEND_OFST, FORCE_SESSEND, 1); /* USB PLL Force settings */ usb20_pll_settings(false, false); #ifdef CONFIG_MTK_UART_USB_SWITCH reg_done: #endif os_printk(K_DEBUG, "%s-\n", __func__); return PHY_TRUE; } PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info) { PHY_INT32 i = 0; PHY_INT32 fgRet = 0; PHY_INT32 u4FmOut = 0; PHY_INT32 u4Tmp = 0; os_printk(K_DEBUG, "%s\n", __func__); /* => RG_USB20_HSTX_SRCAL_EN = 1 */ /* enable USB ring oscillator */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 1); /* wait 1us */ udelay(1); /* => USBPHY base address + 0x110 = 1 */ /* Enable free run clock */ U3PhyWriteField32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE + 0x10) , RG_FRCK_EN_OFST, RG_FRCK_EN, 0x1); /* => USBPHY base address + 0x100 = 0x04 */ /* Setting cyclecnt */ U3PhyWriteField32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE) , RG_CYCLECNT_OFST, RG_CYCLECNT, 0x400); /* => USBPHY base address + 0x100 = 0x01 */ /* Enable frequency meter */ U3PhyWriteField32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE) , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0x1); /* USB_FM_VLD, should be 1'b1, Read frequency valid */ os_printk(K_DEBUG, "Freq_Valid=(0x%08X)\n", U3PhyReadReg32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE + 0x10))); mdelay(1); /* wait for FM detection done, set 10ms timeout */ for (i = 0; i < 10; i++) { /* => USBPHY base address + 0x10C = FM_OUT */ /* Read result */ u4FmOut = U3PhyReadReg32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE + 0xC)); os_printk(K_DEBUG, "FM_OUT value: u4FmOut = %d(0x%08X)\n", u4FmOut, u4FmOut); /* check if FM detection done */ if (u4FmOut != 0) { fgRet = 0; os_printk(K_DEBUG, "FM detection done! loop = %d\n", i); break; } fgRet = 1; mdelay(1); } /* => USBPHY base address + 0x100 = 0x00 */ /* Disable Frequency meter */ U3PhyWriteField32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE) , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0); /* => USBPHY base address + 0x110 = 0x00 */ /* Disable free run clock */ U3PhyWriteField32((phys_addr_t) (uintptr_t) (SSUSB_SIFSLV_FM_BASE + 0x10) , RG_FRCK_EN_OFST, RG_FRCK_EN, 0); /* RG_USB20_HSTX_SRCTRL[2:0] = (1024/FM_OUT) * reference clock frequency * 0.028 */ if (u4FmOut == 0) { U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, 0x4); fgRet = 1; } else { /* set reg = (1024/FM_OUT) * REF_CK * U2_SR_COEF_E60802 / 1000 (round to the nearest digits) */ /* u4Tmp = (((1024 * REF_CK * U2_SR_COEF_E60802) / u4FmOut) + 500) / 1000; */ u4Tmp = (1024 * REF_CK * U2_SR_COEF_E60802) / (u4FmOut * 1000); os_printk(K_DEBUG, "SR calibration value u1SrCalVal = %d\n", (PHY_UINT8) u4Tmp); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, u4Tmp); } /* => RG_USB20_HSTX_SRCAL_EN = 0 */ /* disable USB ring oscillator */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR5, RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 0); return fgRet; } void usb_phy_savecurrent(unsigned int clk_on) { os_printk(K_INFO, "%s clk_on=%d+\n", __func__, clk_on); if (sib_mode) { pr_notice("%s sib_mode can't savecurrent\n", __func__); return; } #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) goto reg_done; #endif /*switch to USB function. (system register, force ip into usb mode) */ /* force_uart_en 1'b0 */ /* U3D_U2PHYDTM0 FORCE_UART_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); /* RG_UART_EN 1'b0 */ /* U3D_U2PHYDTM1 RG_UART_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); /* rg_usb20_gpio_ctl 1'b0 */ /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, 0); /* usb20_gpio_mode 1'b0 */ /* U3D_U2PHYACR4 USB20_GPIO_MODE */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); /*DP/DM BC1.1 path Disable */ /* RG_USB20_BC11_SW_EN 1'b0 */ /* U3D_USBPHYACR6 RG_USB20_BC11_SW_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 0); /*OTG Disable */ /* RG_USB20_OTG_VBUSCMP_EN 1b0 */ /* U3D_USBPHYACR6 RG_USB20_OTG_VBUSCMP_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, RG_USB20_OTG_VBUSCMP_EN, 0); /*let suspendm=1, enable usb 480MHz pll */ /* RG_SUSPENDM 1'b1 */ /* U3D_U2PHYDTM0 RG_SUSPENDM */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 1); /*force_suspendm=1 */ /* force_suspendm 1'b1 */ /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 1); /*Wait USBPLL stable. */ /* Wait 2 ms. */ udelay(2000); /* RG_DPPULLDOWN 1'b1 */ /* U3D_U2PHYDTM0 RG_DPPULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DPPULLDOWN_OFST, RG_DPPULLDOWN, 1); /* RG_DMPULLDOWN 1'b1 */ /* U3D_U2PHYDTM0 RG_DMPULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DMPULLDOWN_OFST, RG_DMPULLDOWN, 1); /* RG_XCVRSEL[1:0] 2'b01 */ /* U3D_U2PHYDTM0 RG_XCVRSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_XCVRSEL_OFST, RG_XCVRSEL, 0x1); /* RG_TERMSEL 1'b1 */ /* U3D_U2PHYDTM0 RG_TERMSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_TERMSEL_OFST, RG_TERMSEL, 1); /* RG_DATAIN[3:0] 4'b0000 */ /* U3D_U2PHYDTM0 RG_DATAIN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DATAIN_OFST, RG_DATAIN, 0); /* force_dp_pulldown 1'b1 */ /* U3D_U2PHYDTM0 FORCE_DP_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DP_PULLDOWN_OFST, FORCE_DP_PULLDOWN, 1); /* force_dm_pulldown 1'b1 */ /* U3D_U2PHYDTM0 FORCE_DM_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DM_PULLDOWN_OFST, FORCE_DM_PULLDOWN, 1); /* force_xcversel 1'b1 */ /* U3D_U2PHYDTM0 FORCE_XCVRSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_XCVRSEL_OFST, FORCE_XCVRSEL, 1); /* force_termsel 1'b1 */ /* U3D_U2PHYDTM0 FORCE_TERMSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_TERMSEL_OFST, FORCE_TERMSEL, 1); /* force_datain 1'b1 */ /* U3D_U2PHYDTM0 FORCE_DATAIN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DATAIN_OFST, FORCE_DATAIN, 1); /* wait 800us */ udelay(800); /*let suspendm=0, set utmi into analog power down */ /* RG_SUSPENDM 1'b0 */ /* U3D_U2PHYDTM0 RG_SUSPENDM */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_SUSPENDM_OFST, RG_SUSPENDM, 0); /* wait 1us */ udelay(1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_VBUSVALID_OFST, RG_VBUSVALID, 0); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_AVALID_OFST, RG_AVALID, 0); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_SESSEND_OFST, RG_SESSEND, 1); /* USB PLL Force settings */ usb20_pll_settings(false, false); #ifdef CONFIG_MTK_UART_USB_SWITCH reg_done: #endif /* TODO: * Turn off internal 48Mhz PLL if there is no other hardware module is * using the 48Mhz clock -the control register is in clock document * Turn off SSUSB reference clock (26MHz) */ if (clk_on) { U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 0); /* Wait 10 usec. */ udelay(10); /* f_fusb30_ck:125MHz */ usb_enable_clock(false); VA09_operation(VA09_OP_OFF, false); } os_printk(K_INFO, "%s-\n", __func__); } void usb_phy_recover(unsigned int clk_on) { os_printk(K_INFO, "%s clk_on=%d+\n", __func__, clk_on); if (!clk_on) { VA09_operation(VA09_OP_ON, false); /* f_fusb30_ck:125MHz */ usb_enable_clock(true); /* Wait 50 usec. (PHY 3.3v & 1.8v power stable time) */ udelay(250); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG1, RG_SSUSB_VUSB09_ON_OFST, RG_SSUSB_VUSB09_ON, 1); } #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) goto reg_done; #endif /*switch to USB function. (system register, force ip into usb mode) */ /* force_uart_en 1'b0 */ /* U3D_U2PHYDTM0 FORCE_UART_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_UART_EN_OFST, FORCE_UART_EN, 0); /* RG_UART_EN 1'b0 */ /* U3D_U2PHYDTM1 RG_UART_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_UART_EN_OFST, RG_UART_EN, 0); /* rg_usb20_gpio_ctl 1'b0 */ /* U3D_U2PHYACR4 RG_USB20_GPIO_CTL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, RG_USB20_GPIO_CTL_OFST, RG_USB20_GPIO_CTL, 0); /* usb20_gpio_mode 1'b0 */ /* U3D_U2PHYACR4 USB20_GPIO_MODE */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYACR4, USB20_GPIO_MODE_OFST, USB20_GPIO_MODE, 0); /*Release force suspendm. (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ /*force_suspendm 1'b0 */ /* U3D_U2PHYDTM0 FORCE_SUSPENDM */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_SUSPENDM_OFST, FORCE_SUSPENDM, 0); /* RG_DPPULLDOWN 1'b0 */ /* U3D_U2PHYDTM0 RG_DPPULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DPPULLDOWN_OFST, RG_DPPULLDOWN, 0); /* RG_DMPULLDOWN 1'b0 */ /* U3D_U2PHYDTM0 RG_DMPULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DMPULLDOWN_OFST, RG_DMPULLDOWN, 0); /* RG_XCVRSEL[1:0] 2'b00 */ /* U3D_U2PHYDTM0 RG_XCVRSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_XCVRSEL_OFST, RG_XCVRSEL, 0); /* RG_TERMSEL 1'b0 */ /* U3D_U2PHYDTM0 RG_TERMSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_TERMSEL_OFST, RG_TERMSEL, 0); /* RG_DATAIN[3:0] 4'b0000 */ /* U3D_U2PHYDTM0 RG_DATAIN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, RG_DATAIN_OFST, RG_DATAIN, 0); /* force_dp_pulldown 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DP_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DP_PULLDOWN_OFST, FORCE_DP_PULLDOWN, 0); /* force_dm_pulldown 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DM_PULLDOWN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DM_PULLDOWN_OFST, FORCE_DM_PULLDOWN, 0); /* force_xcversel 1'b0 */ /* U3D_U2PHYDTM0 FORCE_XCVRSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_XCVRSEL_OFST, FORCE_XCVRSEL, 0); /* force_termsel 1'b0 */ /* U3D_U2PHYDTM0 FORCE_TERMSEL */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_TERMSEL_OFST, FORCE_TERMSEL, 0); /* force_datain 1'b0 */ /* U3D_U2PHYDTM0 FORCE_DATAIN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM0, FORCE_DATAIN_OFST, FORCE_DATAIN, 0); /*DP/DM BC1.1 path Disable */ /* RG_USB20_BC11_SW_EN 1'b0 */ /* U3D_USBPHYACR6 RG_USB20_BC11_SW_EN */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 0); /*OTG Enable */ /* RG_USB20_OTG_VBUSCMP_EN 1b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_OTG_VBUSCMP_EN_OFST, RG_USB20_OTG_VBUSCMP_EN, 1); /* Wait 800 usec */ udelay(800); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_VBUSVALID_OFST, RG_VBUSVALID, 1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_AVALID_OFST, RG_AVALID, 1); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_U2PHYDTM1, RG_SESSEND_OFST, RG_SESSEND, 0); /* EFUSE related sequence */ { u32 evalue; /* [4:0] => RG_USB20_INTR_CAL[4:0] */ evalue = (get_devinfo_with_index(108) & (0x1f<<0)) >> 0; if (evalue) { os_printk(K_INFO, "apply efuse setting, RG_USB20_INTR_CAL=0x%x\n", evalue); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR1, RG_USB20_INTR_CAL_OFST, RG_USB20_INTR_CAL, evalue); } else os_printk(K_DEBUG, "!evalue\n"); /* [21:16] (BGR_code) => RG_SSUSB_IEXT_INTR_CTRL[5:0] */ evalue = (get_devinfo_with_index(107) & (0x3f << 16)) >> 16; if (evalue) { os_printk(K_INFO, "apply efuse setting, RG_SSUSB_IEXT_INTR_CTRL=0x%x\n", evalue); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USB30_PHYA_REG0, 10, (0x3f<<10), evalue); } else os_printk(K_DEBUG, "!evalue\n"); /* [12:8] (RX_50_code) => RG_SSUSB_IEXT_RX_IMPSEL[4:0] */ evalue = (get_devinfo_with_index(107) & (0x1f << 8)) >> 8; if (evalue) { os_printk(K_INFO, "apply efuse setting, rg_ssusb_rx_impsel=0x%x\n", evalue); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYD_IMPCAL1, RG_SSUSB_RX_IMPSEL_OFST, RG_SSUSB_RX_IMPSEL, evalue); } else os_printk(K_DEBUG, "!evalue\n"); /* [4:0] (TX_50_code) => RG_SSUSB_IEXT_TX_IMPSEL[4:0], don't care : 0-bit */ evalue = (get_devinfo_with_index(107) & (0x1f << 0)) >> 0; if (evalue) { os_printk(K_INFO, "apply efuse setting, rg_ssusb_tx_impsel=0x%x\n", evalue); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_PHYD_IMPCAL0, RG_SSUSB_TX_IMPSEL_OFST, RG_SSUSB_TX_IMPSEL, evalue); } else os_printk(K_DEBUG, "!evalue\n"); } /* For host, disconnect threshold */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_DISCTH_OFST, RG_USB20_DISCTH, 0xF); U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_PHY_REV_6_OFST, RG_USB20_PHY_REV_6, usb20_phy_rev6); #ifdef MTK_USB_PHY_TUNING mtk_usb_phy_tuning(); #endif usb_phy_tuning(); /* USB PLL Force settings */ usb20_pll_settings(false, false); /* special request from DE */ { u32 val, offset; /* RG_SSUSB_TX_EIDLE_CM, 0x11F40B20[31:28], 4'b1000, ssusb_USB30_PHYA_regmap_T12FF_TPHY */ val = 0x8; offset = 0x20; U3PhyWriteField32((phys_addr_t) (uintptr_t) ((u3_sif2_base + 0xb00) + offset), 28, (0xf<<28), val); /* rg_ssusb_cdr_bir_ltr, 0x11F4095C[20:16] 5'b01101, ssusb_USB30_PHYD_regmap_T12FF_TPHY */ val = 0xd; offset = 0x5c; U3PhyWriteField32((phys_addr_t) (uintptr_t) ((u3_sif2_base + 0x900) + offset), 16, (0x1f<<16), val); } #ifdef CONFIG_MTK_UART_USB_SWITCH reg_done: #endif os_printk(K_INFO, "%s-\n", __func__); } /* * This function is to solve the condition described below. * The system boot has 3 situations. * 1. Booting without cable, so connection work called by musb_gadget_start() * would turn off pwr/clk by musb_stop(). [REF CNT = 0] * 2. Booting with normal cable, the pwr/clk has already turned on at initial stage. * and also set the flag (musb->is_clk_on=1). * So musb_start() would not turn on again. [REF CNT = 1] * 3. Booting with OTG cable, the pwr/clk would be turned on by host one more time.[REF CNT=2] * So device should turn off pwr/clk which are turned on during the initial stage. * However, does _NOT_ touch the PHY registers. So we need this fake function to keep the REF CNT correct. * NOT FOR TURN OFF PWR/CLK. */ void usb_fake_powerdown(unsigned int clk_on) { os_printk(K_INFO, "%s clk_on=%d+\n", __func__, clk_on); if (clk_on) { /* f_fusb30_ck:125MHz */ usb_enable_clock(false); } os_printk(K_INFO, "%s-\n", __func__); } #ifdef CONFIG_USBIF_COMPLIANCE static bool charger_det_en = true; void Charger_Detect_En(bool enable) { charger_det_en = enable; } #endif /* BC1.2 */ void Charger_Detect_Init(void) { os_printk(K_INFO, "%s+\n", __func__); #ifdef U3_COMPLIANCE os_printk(K_INFO, "%s, U3_COMPLIANCE, SKIP\n", __func__); return; #endif if (mu3d_force_on || !_mu3d_musb) { os_printk(K_INFO, "%s-, SKIP\n", __func__); return; } #ifdef CONFIG_USBIF_COMPLIANCE if (charger_det_en == true) { #endif /* turn on USB reference clock. */ usb_enable_clock(true); /* wait 50 usec. */ udelay(250); /* RG_USB20_BC11_SW_EN = 1'b1 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 1); udelay(1); /* 4 14. turn off internal 48Mhz PLL. */ usb_enable_clock(false); #ifdef CONFIG_USBIF_COMPLIANCE } else { os_printk(K_INFO, "%s do not init detection as charger_det_en is false\n", __func__); } #endif os_printk(K_INFO, "%s-\n", __func__); } void Charger_Detect_Release(void) { os_printk(K_INFO, "%s+\n", __func__); #ifdef U3_COMPLIANCE os_printk(K_INFO, "%s, U3_COMPLIANCE, SKIP\n", __func__); return; #endif if (mu3d_force_on || !_mu3d_musb) { os_printk(K_INFO, "%s-, SKIP\n", __func__); return; } #ifdef CONFIG_USBIF_COMPLIANCE if (charger_det_en == true) { #endif /* turn on USB reference clock. */ usb_enable_clock(true); /* wait 50 usec. */ udelay(250); /* RG_USB20_BC11_SW_EN = 1'b0 */ U3PhyWriteField32((phys_addr_t) (uintptr_t) U3D_USBPHYACR6, RG_USB20_BC11_SW_EN_OFST, RG_USB20_BC11_SW_EN, 0); udelay(1); /* 4 14. turn off internal 48Mhz PLL. */ usb_enable_clock(false); #ifdef CONFIG_USBIF_COMPLIANCE } else { os_printk(K_DEBUG, "%s do not release detection as charger_det_en is false\n", __func__); } #endif os_printk(K_INFO, "%s-\n", __func__); } static int mt_usb_dts_probe(struct platform_device *pdev) { int retval = 0; pr_notice("%s\n", __func__); /* POWER */ reg_vusb = regulator_get(&pdev->dev, "vusb"); if (!IS_ERR(reg_vusb)) { retval = regulator_enable(reg_vusb); if (retval < 0) { pr_notice("regulator_enable vusb failed: %d\n", retval); regulator_put(reg_vusb); } } else { pr_notice("regulator_get vusb failed\n"); reg_vusb = NULL; } reg_va09 = regulator_get(&pdev->dev, "va09"); if (IS_ERR(reg_va09)) { pr_notice("regulator_get va09 failed\n"); reg_va09 = NULL; } ssusb_clk = devm_clk_get(&pdev->dev, "ssusb_clk"); if (IS_ERR(ssusb_clk)) { pr_notice("ssusb_clk get ssusb_clk fail\n"); } else { retval = clk_prepare(ssusb_clk); if (retval == 0) pr_debug("ssusb_clk<%p> prepare done\n", ssusb_clk); else pr_notice("ssusb_clk prepare fail\n"); } sys_ck = devm_clk_get(&pdev->dev, "sys_ck"); if (IS_ERR(sys_ck)) { pr_notice("sys_ck get sys_ck fail\n"); } else { retval = clk_prepare(sys_ck); if (retval == 0) pr_debug("sys_ck<%p> prepare done\n", sys_ck); else pr_notice("sys_ck prepare fail\n"); } usb20_phy_rev6 = 1; pr_notice("%s, usb20_phy_rev6 to %d\n", __func__, usb20_phy_rev6); return retval; } static int mt_usb_dts_remove(struct platform_device *pdev) { if (!IS_ERR(ssusb_clk)) clk_unprepare(ssusb_clk); if (!IS_ERR(sys_ck)) clk_unprepare(sys_ck); /* POWER */ if (reg_vusb) regulator_put(reg_vusb); if (reg_va09) regulator_put(reg_va09); return 0; } static const struct of_device_id apusb_of_ids[] = { {.compatible = "mediatek,usb3_phy",}, {}, }; MODULE_DEVICE_TABLE(of, apusb_of_ids); static struct platform_driver mt_usb_dts_driver = { .remove = mt_usb_dts_remove, .probe = mt_usb_dts_probe, .driver = { .name = "mt_dts_mu3phy", .of_match_table = apusb_of_ids, }, }; MODULE_DESCRIPTION("mtu3phy MUSB PHY Layer"); MODULE_AUTHOR("MediaTek"); MODULE_LICENSE("GPL v2"); module_platform_driver(mt_usb_dts_driver); static int usb_ipsleep_irqnum; static int usb_ipsleep_init; void mask_ipsleep(void) { disable_irq(usb_ipsleep_irqnum); } void unmask_ipsleep(void) { enable_irq(usb_ipsleep_irqnum); } void enable_ipsleep_wakeup(void) { if (usb_ipsleep_init) unmask_ipsleep(); } void disable_ipsleep_wakeup(void) { } static irqreturn_t musb_ipsleep_eint_isr(int irqnum, void *data) { disable_irq_nosync(irqnum); return IRQ_HANDLED; } static int mtk_usb_ipsleep_eint_irq_en(struct platform_device *pdev) { int retval = 0; retval = request_irq(usb_ipsleep_irqnum, musb_ipsleep_eint_isr, IRQF_TRIGGER_NONE, "usbcd_eint", pdev); if (retval != 0) os_printk(K_ERR, "usbcd request_irq fail, ret %d, irqnum %d!!!\n", retval, usb_ipsleep_irqnum); else enable_irq_wake(usb_ipsleep_irqnum); return retval; } static int mt_usb_ipsleep_probe(struct platform_device *pdev) { int retval = 0; struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; usb_ipsleep_irqnum = irq_of_parse_and_map(node, 0); if (usb_ipsleep_irqnum < 0) return -ENODEV; retval = mtk_usb_ipsleep_eint_irq_en(pdev); if (retval != 0) goto irqfail; usb_ipsleep_init = 1; irqfail: os_printk(K_INFO, "mt_usb_ipsleep_probe done\n"); return retval; } static int mt_usb_ipsleep_remove(struct platform_device *pdev) { free_irq(usb_ipsleep_irqnum, pdev); return 0; } static const struct of_device_id usb_ipsleep_of_match[] = { {.compatible = "mediatek,usb_ipsleep"}, {}, }; MODULE_DEVICE_TABLE(of, usb_ipsleep_of_match); static struct platform_driver mt_usb_ipsleep_driver = { .remove = mt_usb_ipsleep_remove, .probe = mt_usb_ipsleep_probe, .driver = { .name = "usb_ipsleep", .of_match_table = usb_ipsleep_of_match, }, }; MODULE_DESCRIPTION("musb ipsleep eint"); MODULE_AUTHOR("MediaTek"); MODULE_LICENSE("GPL v2"); module_platform_driver(mt_usb_ipsleep_driver); #endif