/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #ifdef CONFIG_MTK_CLKMGR #include #else #include #endif #include #include #include #include #include #include #include "usb20.h" #include "mtk_devinfo.h" #include #ifdef CONFIG_OF #include #endif #ifdef CONFIG_MTK_AEE_FEATURE #include #endif #include #define FRA (48) #define PARA (28) #ifdef CONFIG_OF extern struct musb *mtk_musb; #ifdef USB2_PHY_V2 #define USB_PHY_OFFSET 0x300 #else #define USB_PHY_OFFSET 0x800 #endif #define USBPHY_READ8(offset) \ readb((void __iomem *)\ (((unsigned long)\ mtk_musb->xceiv->io_priv)+USB_PHY_OFFSET+offset)) #define USBPHY_WRITE8(offset, value) writeb(value, (void __iomem *)\ (((unsigned long)mtk_musb->xceiv->io_priv)+USB_PHY_OFFSET+offset)) #define USBPHY_SET8(offset, mask) \ USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask)) #define USBPHY_CLR8(offset, mask) \ USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~(mask))) #define USBPHY_READ32(offset) \ readl((void __iomem *)(((unsigned long)\ mtk_musb->xceiv->io_priv)+USB_PHY_OFFSET+offset)) #define USBPHY_WRITE32(offset, value) \ writel(value, (void __iomem *)\ (((unsigned long)mtk_musb->xceiv->io_priv)+USB_PHY_OFFSET+offset)) #define USBPHY_SET32(offset, mask) \ USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) | (mask)) #define USBPHY_CLR32(offset, mask) \ USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) & (~(mask))) #ifdef MTK_UART_USB_SWITCH #define UART2_BASE 0x11003000 #endif #else #include #define USBPHY_READ8(offset) \ readb((void __iomem *)(USB_SIF_BASE+USB_PHY_OFFSET+offset)) #define USBPHY_WRITE8(offset, value) \ writeb(value, (void __iomem *)(USB_SIF_BASE+USB_PHY_OFFSET+offset)) #define USBPHY_SET8(offset, mask) \ USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask)) #define USBPHY_CLR8(offset, mask) \ USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~mask)) #define USBPHY_READ32(offset) \ readl((void __iomem *)(USB_SIF_BASE+USB_PHY_OFFSET+offset)) #define USBPHY_WRITE32(offset, value) \ writel(value, (void __iomem *)(USB_SIF_BASE+USB_PHY_OFFSET+offset)) #define USBPHY_SET32(offset, mask) \ USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) | (mask)) #define USBPHY_CLR32(offset, mask) \ USBPHY_WRITE32(offset, (USBPHY_READ32(offset)) & (~mask)) #endif #ifdef FPGA_PLATFORM bool usb_enable_clock(bool enable) { return true; } bool usb_prepare_clock(bool enable) { return true; } void usb_prepare_enable_clock(bool enable) { } void usb_phy_poweron(void) { } void usb_phy_savecurrent(void) { } void usb_phy_recover(void) { } /* BC1.2 */ void Charger_Detect_Init(void) { } void Charger_Detect_Release(void) { } void usb_phy_context_save(void) { } void usb_phy_context_restore(void) { } #ifdef CONFIG_MTK_UART_USB_SWITCH bool usb_phy_check_in_uart_mode(void) { return false; } void usb_phy_switch_to_uart(void) { } void usb_phy_switch_to_usb(void) { } #endif #else #include #include #define VAL_MAX_WIDTH_2 0x3 #define VAL_MAX_WIDTH_3 0x7 #define OFFSET_RG_USB20_VRT_VREF_SEL 0x4 #define SHFT_RG_USB20_VRT_VREF_SEL 12 #define OFFSET_RG_USB20_TERM_VREF_SEL 0x4 #define SHFT_RG_USB20_TERM_VREF_SEL 8 #define OFFSET_RG_USB20_PHY_REV6 0x18 #define SHFT_RG_USB20_PHY_REV6 30 void usb_phy_tuning(void) { static bool inited; static s32 u2_vrt_ref, u2_term_ref, u2_enhance; struct device_node *of_node; if (!inited) { /* apply default value */ u2_vrt_ref = 5; u2_term_ref = 5; 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; } if (u2_vrt_ref != -1) { if (u2_vrt_ref <= VAL_MAX_WIDTH_3) { USBPHY_CLR32(OFFSET_RG_USB20_VRT_VREF_SEL, VAL_MAX_WIDTH_3 << SHFT_RG_USB20_VRT_VREF_SEL); USBPHY_SET32(OFFSET_RG_USB20_VRT_VREF_SEL, u2_vrt_ref << SHFT_RG_USB20_VRT_VREF_SEL); } } if (u2_term_ref != -1) { if (u2_term_ref <= VAL_MAX_WIDTH_3) { USBPHY_CLR32(OFFSET_RG_USB20_TERM_VREF_SEL, VAL_MAX_WIDTH_3 << SHFT_RG_USB20_TERM_VREF_SEL); USBPHY_SET32(OFFSET_RG_USB20_TERM_VREF_SEL, u2_term_ref << SHFT_RG_USB20_TERM_VREF_SEL); } } if (u2_enhance != -1) { if (u2_enhance <= VAL_MAX_WIDTH_2) { USBPHY_CLR32(OFFSET_RG_USB20_PHY_REV6, VAL_MAX_WIDTH_2 << SHFT_RG_USB20_PHY_REV6); USBPHY_SET32(OFFSET_RG_USB20_PHY_REV6, u2_enhance<\n", enable, count, virt_enable, virt_disable, real_enable, real_disable); spin_lock_irqsave(&musb_reg_clock_lock, flags); if (unlikely(atomic_read(&clk_prepare_cnt) <= 0)) { DBG_LIMIT(1, "clock not prepare"); goto exit; } if (enable && count == 0) { if (clk_enable(musb_clk_top_sel)) { DBG(0, "musb_clk_top_sel enable fail\n"); goto exit; } if (clk_enable(musb_clk)) { DBG(0, "musb_clk enable fail\n"); clk_disable(musb_clk_top_sel); goto exit; } if (clk_enable(musb_ref_clk)) { DBG(0, "musb_ref_clk enable fail\n"); clk_disable(musb_clk); clk_disable(musb_clk_top_sel); goto exit; } usb_hal_dpidle_request(USB_DPIDLE_FORBIDDEN); real_enable++; } else if (!enable && count == 1) { clk_disable(musb_clk); clk_disable(musb_ref_clk); clk_disable(musb_clk_top_sel); usb_hal_dpidle_request(USB_DPIDLE_ALLOWED); real_disable++; } if (enable) count++; else count = (count == 0) ? 0 : (count - 1); exit: if (enable) virt_enable++; else virt_disable++; spin_unlock_irqrestore(&musb_reg_clock_lock, flags); DBG(1, "enable(%d),count(%d), <%d,%d,%d,%d>\n", enable, count, virt_enable, virt_disable, real_enable, real_disable); return 1; } EXPORT_SYMBOL(usb_enable_clock); #ifdef CONFIG_MTK_UART_USB_SWITCH bool usb_phy_check_in_uart_mode(void) { u32 usb_port_mode; usb_enable_clock(true); udelay(50); usb_port_mode = USBPHY_READ32(0x68); usb_enable_clock(false); if (((usb_port_mode >> 30) & 0x3) == 1) { DBG(0, "%s:%d - IN UART MODE : 0x%x\n", __func__, __LINE__, usb_port_mode); in_uart_mode = true; } else { DBG(0, "%s:%d - NOT IN UART MODE : 0x%x\n", __func__, __LINE__, usb_port_mode); in_uart_mode = false; } return in_uart_mode; } void usb_phy_switch_to_uart(void) { unsigned int val = 0; if (usb_phy_check_in_uart_mode()) { DBG(0, "Already in UART mode.\n"); return; } udelay(50); /* RG_USB20_BC11_SW_EN 0x11F4_0818[23] = 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 23)); /* Set RG_SUSPENDM 0x11F4_0868[3] to 1 */ USBPHY_SET32(0x68, (0x1 << 3)); /* force suspendm 0x11F4_0868[18] = 1 */ USBPHY_SET32(0x68, (0x1 << 18)); /* Set rg_uart_mode 0x11F4_0868[31:30] to 2'b01 */ USBPHY_CLR32(0x68, (0x3 << 30)); USBPHY_SET32(0x68, (0x1 << 30)); /* force_uart_i 0x11F4_0868[29] = 0*/ USBPHY_CLR32(0x68, (0x1 << 29)); /* force_uart_bias_en 0x11F4_0868[28] = 1 */ USBPHY_SET32(0x68, (0x1 << 28)); /* force_uart_tx_oe 0x11F4_0868[27] = 1 */ USBPHY_SET32(0x68, (0x1 << 27)); /* force_uart_en 0x11F4_0868[26] = 1 */ USBPHY_SET32(0x68, (0x1 << 26)); /* RG_UART_BIAS_EN 0x11F4_086c[18] = 1 */ USBPHY_SET32(0x6C, (0x1 << 18)); /* RG_UART_TX_OE 0x11F4_086c[17] = 1 */ USBPHY_SET32(0x6C, (0x1 << 17)); /* Set RG_UART_EN to 1 */ USBPHY_SET32(0x6C, (0x1 << 16)); /* Set RG_USB20_DM_100K_EN to 1 */ USBPHY_SET32(0x20, (0x1 << 17)); /* RG_DPPULLDOWN, 1'b0, RG_DMPULLDOWN, 1'b0 */ USBPHY_CLR32(0x68, ((0x1 << 6) | (0x1 << 7))); /* GPIO Selection */ val = readl(ap_gpio_base); writel(val & (~(GPIO_SEL_MASK)), ap_gpio_base); val = readl(ap_gpio_base); writel(val | (GPIO_SEL_UART0), ap_gpio_base); in_uart_mode = true; } void usb_phy_switch_to_usb(void) { unsigned int val = 0; /* GPIO Selection */ val = readl(ap_gpio_base); writel(val & (~(GPIO_SEL_MASK)), ap_gpio_base); /* clear force_uart_en */ USBPHY_CLR32(0x68, (0x1 << 26)); /* Set rg_uart_mode 0x11F4_0868[31:30] to 2'b00 */ USBPHY_CLR32(0x68, (0x3 << 30)); in_uart_mode = false; usb_phy_poweron(); } #endif void set_usb_phy_mode(int mode) { switch (mode) { case PHY_MODE_USB_DEVICE: /* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=1, IDPULLUP=1 */ USBPHY_CLR32(0x6C, (0x10<<0)); USBPHY_SET32(0x6C, (0x2F<<0)); USBPHY_SET32(0x6C, (0x3F<<8)); break; case PHY_MODE_USB_HOST: /* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0, IDPULLUP=1 */ USBPHY_CLR32(0x6c, (0x12<<0)); USBPHY_SET32(0x6c, (0x2d<<0)); USBPHY_SET32(0x6c, (0x3f<<8)); break; case PHY_MODE_INVALID: /* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=0, IDPULLUP=1 */ USBPHY_SET32(0x6c, (0x11<<0)); USBPHY_CLR32(0x6c, (0x2e<<0)); USBPHY_SET32(0x6c, (0x3f<<8)); break; default: DBG(0, "mode error %d\n", mode); } DBG(0, "force PHY to mode %d, 0x6c=%x\n", mode, USBPHY_READ32(0x6c)); } void usb_rev6_setting(int value) { static int direct_return; if (direct_return) return; /* RG_USB20_PHY_REV[7:0] = 8'b01000000 */ USBPHY_CLR32(0x18, (0xFF << 24)); if (value) USBPHY_SET32(0x18, (value << 24)); else direct_return = 1; } /* M17_USB_PWR Sequence 20160603.xls */ void usb_phy_poweron(void) { #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) { DBG(0, "At UART mode. No %s\n", __func__); return; } #endif /* wait 50 usec for PHY3.3v/1.8v stable. */ udelay(50); /* RG_USB20_PLL_PREDIV[1:0]=2'b00 */ USBPHY_CLR32(0x00, (0x3 << 6)); /* RG_USB20_PLL_FBDIV[21:0]=22'd1814843 */ USBPHY_CLR32(0x30, (0x3fffff << 0)); USBPHY_SET32(0x30, (0x1bb13b << 0)); /* RG_USB20_PLL_FRA_EN=1'b1 */ USBPHY_SET32(0x44, (0x1 << 3)); /* RG_USB20_PLL_ REFCLK_SEL=1'b1 */ USBPHY_SET32(0x44, (0x1 << 5)); /* RG_USB20_PLL_BW[2:0]=3'b011 */ USBPHY_CLR32(0x08, (0x7 << 19)); USBPHY_SET32(0x08, (0x3 << 19)); /* * force_uart_en 1'b0 0x68 26 * RG_UART_EN 1'b0 0x6c 16 * rg_usb20_gpio_ctl 1'b0 0x20 09 * usb20_gpio_mode 1'b0 0x20 08 * RG_USB20_BC11_SW_EN 1'b0 0x18 23 * rg_usb20_dp_100k_mode 1'b1 0x20 18 * USB20_DP_100K_EN 1'b0 0x20 16 * RG_USB20_DM_100K_EN 1'b0 0x20 17 * RG_USB20_OTG_VBUSCMP_EN 1'b1 0x18 20 * force_suspendm 1'b0 0x68 18 */ /* force_uart_en, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 26)); /* RG_UART_EN, 1'b0 */ USBPHY_CLR32(0x6c, (0x1 << 16)); /* rg_usb20_gpio_ctl, 1'b0, usb20_gpio_mode, 1'b0 */ USBPHY_CLR32(0x20, ((0x1 << 9) | (0x1 << 8))); /* RG_USB20_BC11_SW_EN, 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 23)); /* rg_usb20_dp_100k_mode, 1'b1 */ USBPHY_SET32(0x20, (0x1 << 18)); /* USB20_DP_100K_EN 1'b0, RG_USB20_DM_100K_EN, 1'b0 */ USBPHY_CLR32(0x20, ((0x1 << 16) | (0x1 << 17))); /* RG_USB20_OTG_VBUSCMP_EN, 1'b1 */ USBPHY_SET32(0x18, (0x1 << 20)); /* force_suspendm, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 18)); /* RG_USB20_PHY_REV[7:0] = 8'b01000000 */ USBPHY_CLR32(0x18, (0xFF << 24)); USBPHY_SET32(0x18, (0x40 << 24)); /* wait for 800 usec. */ udelay(800); DBG(0, "usb power on success\n"); } /* M17_USB_PWR Sequence 20160603.xls */ void usb_phy_savecurrent_internal(void) { #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) { DBG(0, "At UART mode. No %s\n", __func__); return; } #endif /* * force_uart_en 1'b0 0x68 26 * RG_UART_EN 1'b0 0x6c 16 * rg_usb20_gpio_ctl 1'b0 0x20 09 * usb20_gpio_mode 1'b0 0x20 08 * RG_USB20_BC11_SW_EN 1'b0 0x18 23 * RG_USB20_OTG_VBUSCMP_EN 1'b0 0x18 20 * RG_SUSPENDM 1'b1 0x68 03 * force_suspendm 1'b1 0x68 18 * RG_DPPULLDOWN 1'b1 0x68 06 * RG_DMPULLDOWN 1'b1 0x68 07 * RG_XCVRSEL[1:0] 2'b01 0x68 [04-05] * RG_TERMSEL 1'b1 0x68 02 * RG_DATAIN[3:0] 4'b0000 0x68 [10-13] * force_dp_pulldown 1'b1 0x68 20 * force_dm_pulldown 1'b1 0x68 21 * force_xcversel 1'b1 0x68 19 * force_termsel 1'b1 0x68 17 * force_datain 1'b1 0x68 23 * RG_SUSPENDM 1'b0 0x68 03 */ /* force_uart_en, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 26)); /* RG_UART_EN, 1'b0 */ USBPHY_CLR32(0x6c, (0x1 << 16)); /* rg_usb20_gpio_ctl, 1'b0, usb20_gpio_mode, 1'b0 */ USBPHY_CLR32(0x20, (0x1 << 9)); USBPHY_CLR32(0x20, (0x1 << 8)); /* RG_USB20_BC11_SW_EN, 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 23)); /* RG_USB20_OTG_VBUSCMP_EN, 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 20)); /* RG_SUSPENDM, 1'b1 */ USBPHY_SET32(0x68, (0x1 << 3)); /* force_suspendm, 1'b1 */ USBPHY_SET32(0x68, (0x1 << 18)); /* RG_DPPULLDOWN, 1'b1, RG_DMPULLDOWN, 1'b1 */ USBPHY_SET32(0x68, ((0x1 << 6) | (0x1 << 7))); /* RG_XCVRSEL[1:0], 2'b01. */ USBPHY_CLR32(0x68, (0x3 << 4)); USBPHY_SET32(0x68, (0x1 << 4)); /* RG_TERMSEL, 1'b1 */ USBPHY_SET32(0x68, (0x1 << 2)); /* RG_DATAIN[3:0], 4'b0000 */ USBPHY_CLR32(0x68, (0xF << 10)); /* force_dp_pulldown, 1'b1, force_dm_pulldown, 1'b1, * force_xcversel, 1'b1, force_termsel, 1'b1, force_datain, 1'b1 */ USBPHY_SET32(0x68, ((0x1 << 20) | (0x1 << 21) | (0x1 << 19) | (0x1 << 17) | (0x1 << 23))); udelay(800); /* RG_SUSPENDM, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 3)); udelay(1); set_usb_phy_mode(PHY_MODE_INVALID); } void usb_phy_savecurrent(void) { usb_phy_savecurrent_internal(); DBG(0, "usb save current success\n"); } EXPORT_SYMBOL(usb_phy_savecurrent); /* M17_USB_PWR Sequence 20160603.xls */ void usb_phy_recover(void) { unsigned int efuse_val = 0; #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) { DBG(0, "At UART mode. No %s\n", __func__); return; } #endif /* wait 50 usec. */ udelay(50); /* RG_USB20_PLL_PREDIV[1:0]=2'b00 */ USBPHY_CLR32(0x00, (0x3 << 6)); /* RG_USB20_PLL_FBDIV[21:0]=22'd1814843 */ USBPHY_CLR32(0x30, (0x3fffff << 0)); USBPHY_SET32(0x30, (0x1bb13b << 0)); /* RG_USB20_PLL_FRA_EN=1'b1 */ USBPHY_SET32(0x44, (0x1 << 3)); /* RG_USB20_PLL_ REFCLK_SEL=1'b1 */ USBPHY_SET32(0x44, (0x1 << 5)); /* RG_USB20_PLL_BW[2:0]=3'b011 */ USBPHY_CLR32(0x08, (0x7 << 19)); USBPHY_SET32(0x08, (0x3 << 19)); /* * 04.force_uart_en 1'b0 0x68 26 * 04.RG_UART_EN 1'b0 0x6C 16 * 04.rg_usb20_gpio_ctl 1'b0 0x20 09 * 04.usb20_gpio_mode 1'b0 0x20 08 * 05.force_suspendm 1'b0 0x68 18 * 06.RG_DPPULLDOWN 1'b0 0x68 06 * 07.RG_DMPULLDOWN 1'b0 0x68 07 * 08.RG_XCVRSEL[1:0] 2'b00 0x68 [04:05] * 09.RG_TERMSEL 1'b0 0x68 02 * 10.RG_DATAIN[3:0] 4'b0000 0x68 [10:13] * 11.force_dp_pulldown 1'b0 0x68 20 * 12.force_dm_pulldown 1'b0 0x68 21 * 13.force_xcversel 1'b0 0x68 19 * 14.force_termsel 1'b0 0x68 17 * 15.force_datain 1'b0 0x68 23 * 16.RG_USB20_BC11_SW_EN 1'b0 0x18 23 * 17.RG_USB20_OTG_VBUSCMP_EN 1'b1 0x18 20 */ /* clean PUPD_BIST_EN */ /* PUPD_BIST_EN = 1'b0 */ /* PMIC will use it to detect charger type */ /* NEED?? USBPHY_CLR8(0x1d, 0x10);*/ USBPHY_CLR32(0x1c, (0x1 << 12)); /* force_uart_en, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 26)); /* RG_UART_EN, 1'b0 */ USBPHY_CLR32(0x6C, (0x1 << 16)); /* rg_usb20_gpio_ctl, 1'b0, usb20_gpio_mode, 1'b0 */ USBPHY_CLR32(0x20, (0x1 << 9)); USBPHY_CLR32(0x20, (0x1 << 8)); /* force_suspendm, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 18)); /* RG_DPPULLDOWN, 1'b0, RG_DMPULLDOWN, 1'b0 */ USBPHY_CLR32(0x68, ((0x1 << 6) | (0x1 << 7))); /* RG_XCVRSEL[1:0], 2'b00. */ USBPHY_CLR32(0x68, (0x3 << 4)); /* RG_TERMSEL, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 2)); /* RG_DATAIN[3:0], 4'b0000 */ USBPHY_CLR32(0x68, (0xF << 10)); /* force_dp_pulldown, 1'b0, force_dm_pulldown, 1'b0, * force_xcversel, 1'b0, force_termsel, 1'b0, force_datain, 1'b0 */ USBPHY_CLR32(0x68, ((0x1 << 20) | (0x1 << 21) | (0x1 << 19) | (0x1 << 17) | (0x1 << 23))); /* RG_USB20_BC11_SW_EN, 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 23)); /* RG_USB20_OTG_VBUSCMP_EN, 1'b1 */ USBPHY_SET32(0x18, (0x1 << 20)); /* RG_USB20_PHY_REV[7:0] = 8'b01000000 */ usb_rev6_setting(0x40); /* wait 800 usec. */ udelay(800); /* force enter device mode */ set_usb_phy_mode(PHY_DEV_ACTIVE); /* M_ANALOG8[4:0] => RG_USB20_INTR_CAL[4:0] */ efuse_val = (get_devinfo_with_index(107) & (0x1f<<0)) >> 0; if (efuse_val) { DBG(0, "apply efuse setting, RG_USB20_INTR_CAL=0x%x\n", efuse_val); USBPHY_CLR32(0x04, (0x1F<<19)); USBPHY_SET32(0x04, (efuse_val<<19)); } /* RG_USB20_DISCTH[7:4], 4'b0111 for 700 mV */ USBPHY_CLR32(0x18, (0xf0<<0)); USBPHY_SET32(0x18, (0x70<<0)); USBPHY_SET32(0x18, (0x1<<28)); USBPHY_CLR32(0x18, (0xf<<0)); USBPHY_SET32(0x18, (0x5<<0)); usb_phy_tuning(); DBG(0, "usb recovery success\n"); } EXPORT_SYMBOL(usb_phy_recover); /* BC1.2 */ void Charger_Detect_Init(void) { #if 0 if ((get_boot_mode() == META_BOOT) || (get_boot_mode() == ADVMETA_BOOT) || !mtk_musb) { DBG(0, "%s Skip, musb<%p>\n", __func__, mtk_musb); return; } #endif usb_prepare_enable_clock(true); /* wait 50 usec. */ udelay(50); /* RG_USB20_BC11_SW_EN = 1'b1 */ USBPHY_SET32(0x18, (0x1 << 23)); usb_prepare_enable_clock(false); DBG(0, "%s\n", __func__); } EXPORT_SYMBOL(Charger_Detect_Init); void Charger_Detect_Release(void) { #if 0 if ((get_boot_mode() == META_BOOT) || (get_boot_mode() == ADVMETA_BOOT) || !mtk_musb) { DBG(0, "%s Skip, musb<%p>\n", __func__, mtk_musb); return; } #endif usb_prepare_enable_clock(true); /* RG_USB20_BC11_SW_EN = 1'b0 */ USBPHY_CLR32(0x18, (0x1 << 23)); udelay(1); usb_prepare_enable_clock(false); DBG(0, "%s\n", __func__); } EXPORT_SYMBOL(Charger_Detect_Release); void usb_phy_context_save(void) { #ifdef CONFIG_MTK_UART_USB_SWITCH in_uart_mode = usb_phy_check_in_uart_mode(); #endif } void usb_phy_context_restore(void) { #ifdef CONFIG_MTK_UART_USB_SWITCH if (in_uart_mode) usb_phy_switch_to_uart(); #endif } void usb_dpdm_pulldown(bool enable) { DBG(0, "%s: enable=%d\n", __func__, enable); usb_prepare_enable_clock(true); /* wait 50 usec. */ udelay(50); if (enable) { /* RG_DPPULLDOWN, 1'b1, RG_DMPULLDOWN, 1'b1 */ USBPHY_SET32(0x68, (0x1 << 6) | (0x1 << 7)); /* RG_USB20_PHY_REV */ USBPHY_CLR32(0x18, (0x2 << 24)); } else { /* RG_DPPULLDOWN, 1'b0, RG_DMPULLDOWN, 1'b0 */ USBPHY_CLR32(0x68, (0x1 << 6) | (0x1 << 7)); /* RG_USB20_PHY_REV */ USBPHY_SET32(0x18, (0x2 << 24)); } usb_prepare_enable_clock(false); DBG(0, "%s\n", __func__); } #endif