^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2012-2014 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012 Marek Vasut <marex@denx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * on behalf of DENX Software Engineering GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/usb/otg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/stmp_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define DRIVER_NAME "mxs_phy"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Register Macro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define HW_USBPHY_PWD 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define HW_USBPHY_TX 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define HW_USBPHY_CTRL 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define HW_USBPHY_CTRL_SET 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define HW_USBPHY_CTRL_CLR 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define HW_USBPHY_DEBUG_SET 0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define HW_USBPHY_DEBUG_CLR 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define HW_USBPHY_IP 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define HW_USBPHY_IP_SET 0x94
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define HW_USBPHY_IP_CLR 0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define GM_USBPHY_TX_TXCAL45DP(x) (((x) & 0xf) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define GM_USBPHY_TX_TXCAL45DN(x) (((x) & 0xf) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define GM_USBPHY_TX_D_CAL(x) (((x) & 0xf) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* imx7ulp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define HW_USBPHY_PLL_SIC 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define HW_USBPHY_PLL_SIC_SET 0xa4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define HW_USBPHY_PLL_SIC_CLR 0xa8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define BM_USBPHY_CTRL_SFTRST BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define BM_USBPHY_CTRL_CLKGATE BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define BM_USBPHY_CTRL_ENVBUSCHG_WKUP BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define BM_USBPHY_CTRL_ENIDCHG_WKUP BIT(22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define BM_USBPHY_CTRL_ENDPDMCHG_WKUP BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define BM_USBPHY_IP_FIX (BIT(17) | BIT(18))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BM_USBPHY_DEBUG_CLKGATE BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* imx7ulp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BM_USBPHY_PLL_LOCK BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BM_USBPHY_PLL_REG_ENABLE BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BM_USBPHY_PLL_BYPASS BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BM_USBPHY_PLL_POWER BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define BM_USBPHY_PLL_EN_USB_CLKS BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Anatop Registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define ANADIG_ANA_MISC0 0x150
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define ANADIG_ANA_MISC0_SET 0x154
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define ANADIG_ANA_MISC0_CLR 0x158
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define ANADIG_USB1_CHRG_DETECT_SET 0x1b4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ANADIG_USB1_CHRG_DETECT_CLR 0x1b8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ANADIG_USB2_CHRG_DETECT_SET 0x214
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define ANADIG_USB1_CHRG_DETECT_EN_B BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define ANADIG_USB1_CHRG_DETECT_CHK_CONTACT BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define ANADIG_USB1_VBUS_DET_STAT 0x1c0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define ANADIG_USB1_CHRG_DET_STAT 0x1d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define ANADIG_USB1_CHRG_DET_STAT_DM_STATE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define ANADIG_USB2_VBUS_DET_STAT 0x220
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define ANADIG_USB1_LOOPBACK_SET 0x1e4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define ANADIG_USB1_LOOPBACK_CLR 0x1e8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define ANADIG_USB1_LOOPBACK_UTMI_TESTSTART BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define ANADIG_USB2_LOOPBACK_SET 0x244
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define ANADIG_USB2_LOOPBACK_CLR 0x248
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define ANADIG_USB1_MISC 0x1f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define ANADIG_USB2_MISC 0x250
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define BM_ANADIG_USB1_MISC_RX_VPIN_FS BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define BM_ANADIG_USB1_MISC_RX_VMIN_FS BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define BM_ANADIG_USB2_MISC_RX_VPIN_FS BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define BM_ANADIG_USB2_MISC_RX_VMIN_FS BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Do disconnection between PHY and controller without vbus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * The PHY will be in messy if there is a wakeup after putting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * bus to suspend (set portsc.suspendM) but before setting PHY to low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * power mode (set portsc.phcd).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define MXS_PHY_ABNORMAL_IN_SUSPEND BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The SOF sends too fast after resuming, it will cause disconnection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * between host and high speed device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define MXS_PHY_SENDING_SOF_TOO_FAST BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * IC has bug fixes logic, they include
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * MXS_PHY_ABNORMAL_IN_SUSPEND and MXS_PHY_SENDING_SOF_TOO_FAST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * which are described at above flags, the RTL will handle it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * according to different versions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define MXS_PHY_NEED_IP_FIX BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Minimum and maximum values for device tree entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define MXS_PHY_TX_CAL45_MIN 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define MXS_PHY_TX_CAL45_MAX 55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define MXS_PHY_TX_D_CAL_MIN 79
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define MXS_PHY_TX_D_CAL_MAX 119
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct mxs_phy_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static const struct mxs_phy_data imx23_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .flags = MXS_PHY_ABNORMAL_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const struct mxs_phy_data imx6q_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) MXS_PHY_NEED_IP_FIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct mxs_phy_data imx6sl_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) MXS_PHY_NEED_IP_FIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static const struct mxs_phy_data vf610_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) MXS_PHY_NEED_IP_FIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static const struct mxs_phy_data imx6sx_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static const struct mxs_phy_data imx6ul_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static const struct mxs_phy_data imx7ulp_phy_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const struct of_device_id mxs_phy_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { .compatible = "fsl,imx7ulp-usbphy", .data = &imx7ulp_phy_data, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct mxs_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct usb_phy phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) const struct mxs_phy_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct regmap *regmap_anatop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int port_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 tx_reg_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u32 tx_reg_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return mxs_phy->data == &imx6q_phy_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return mxs_phy->data == &imx6sl_phy_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static inline bool is_imx7ulp_phy(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return mxs_phy->data == &imx7ulp_phy_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * PHY needs some 32K cycles to switch from 32K clock to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * bus (such as AHB/AXI, etc) clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void mxs_phy_clock_switch_delay(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) usleep_range(300, 400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void mxs_phy_tx_init(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) void __iomem *base = mxs_phy->phy.io_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 phytx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* Update TX register if there is anything to write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (mxs_phy->tx_reg_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) phytx = readl(base + HW_USBPHY_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) phytx &= ~mxs_phy->tx_reg_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) phytx |= mxs_phy->tx_reg_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) writel(phytx, base + HW_USBPHY_TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int mxs_phy_pll_enable(void __iomem *base, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = readl_poll_timeout(base + HW_USBPHY_PLL_SIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) value, (value & BM_USBPHY_PLL_LOCK) != 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 100, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) HW_USBPHY_PLL_SIC_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) writel(BM_USBPHY_PLL_EN_USB_CLKS, base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) HW_USBPHY_PLL_SIC_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) writel(BM_USBPHY_PLL_POWER, base + HW_USBPHY_PLL_SIC_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) writel(BM_USBPHY_PLL_BYPASS, base + HW_USBPHY_PLL_SIC_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) writel(BM_USBPHY_PLL_REG_ENABLE, base + HW_USBPHY_PLL_SIC_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) void __iomem *base = mxs_phy->phy.io_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (is_imx7ulp_phy(mxs_phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = mxs_phy_pll_enable(base, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = stmp_reset_block(base + HW_USBPHY_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto disable_pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Power up the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) writel(0, base + HW_USBPHY_PWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * USB PHY Ctrl Setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * - Auto clock/power on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * - Enable full/low speed support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) writel(BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) BM_USBPHY_CTRL_ENAUTO_PWRON_PLL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) BM_USBPHY_CTRL_ENUTMILEVEL2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) BM_USBPHY_CTRL_ENUTMILEVEL3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) base + HW_USBPHY_CTRL_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (mxs_phy->data->flags & MXS_PHY_NEED_IP_FIX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (mxs_phy->regmap_anatop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned int reg = mxs_phy->port_id ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ANADIG_USB1_CHRG_DETECT_SET :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ANADIG_USB2_CHRG_DETECT_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * The external charger detector needs to be disabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * or the signal at DP will be poor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) regmap_write(mxs_phy->regmap_anatop, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ANADIG_USB1_CHRG_DETECT_EN_B |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mxs_phy_tx_init(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) disable_pll:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (is_imx7ulp_phy(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) mxs_phy_pll_enable(base, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Return true if the vbus is there */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned int vbus_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (!mxs_phy->regmap_anatop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (mxs_phy->port_id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) regmap_read(mxs_phy->regmap_anatop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ANADIG_USB1_VBUS_DET_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) &vbus_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) else if (mxs_phy->port_id == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) regmap_read(mxs_phy->regmap_anatop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ANADIG_USB2_VBUS_DET_STAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) &vbus_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) void __iomem *base = mxs_phy->phy.io_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (disconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) base + HW_USBPHY_DEBUG_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (mxs_phy->port_id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) reg = disconnect ? ANADIG_USB1_LOOPBACK_SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) : ANADIG_USB1_LOOPBACK_CLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) regmap_write(mxs_phy->regmap_anatop, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) } else if (mxs_phy->port_id == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) reg = disconnect ? ANADIG_USB2_LOOPBACK_SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) : ANADIG_USB2_LOOPBACK_CLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) regmap_write(mxs_phy->regmap_anatop, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (!disconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) base + HW_USBPHY_DEBUG_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* Delay some time, and let Linestate be SE0 for controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (disconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) void __iomem *base = mxs_phy->phy.io_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u32 phyctrl = readl(base + HW_USBPHY_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (IS_ENABLED(CONFIG_USB_OTG) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) bool vbus_is_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* If the SoCs don't need to disconnect line without vbus, quit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /* If the SoCs don't have anatop, quit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (!mxs_phy->regmap_anatop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) __mxs_phy_disconnect_line(mxs_phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) __mxs_phy_disconnect_line(mxs_phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int mxs_phy_init(struct usb_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct mxs_phy *mxs_phy = to_mxs_phy(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) mxs_phy_clock_switch_delay();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ret = clk_prepare_enable(mxs_phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return mxs_phy_hw_init(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static void mxs_phy_shutdown(struct usb_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct mxs_phy *mxs_phy = to_mxs_phy(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) BM_USBPHY_CTRL_ENIDCHG_WKUP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) BM_USBPHY_CTRL_ENAUTO_PWRON_PLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) writel(value, phy->io_priv + HW_USBPHY_CTRL_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) writel(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) writel(BM_USBPHY_CTRL_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) phy->io_priv + HW_USBPHY_CTRL_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (is_imx7ulp_phy(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mxs_phy_pll_enable(phy->io_priv, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) clk_disable_unprepare(mxs_phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) unsigned int line_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* bit definition is the same for all controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) unsigned int reg = ANADIG_USB1_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* If the SoCs don't have anatop, quit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!mxs_phy->regmap_anatop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (mxs_phy->port_id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) reg = ANADIG_USB1_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) else if (mxs_phy->port_id == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) reg = ANADIG_USB2_MISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if ((line_state & (dp_bit | dm_bit)) == dm_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int mxs_phy_suspend(struct usb_phy *x, int suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct mxs_phy *mxs_phy = to_mxs_phy(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) bool low_speed_connection, vbus_is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * FIXME: Do not power down RXPWD1PT1 bit for low speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * connect. The low speed connection will have problem at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * very rare cases during usb suspend and resume process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (low_speed_connection & vbus_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * If value to be set as pwd value is not 0xffffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * several 32Khz cycles are needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) mxs_phy_clock_switch_delay();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) writel(0xffbfffff, x->io_priv + HW_USBPHY_PWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) writel(BM_USBPHY_CTRL_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) x->io_priv + HW_USBPHY_CTRL_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) clk_disable_unprepare(mxs_phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mxs_phy_clock_switch_delay();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ret = clk_prepare_enable(mxs_phy->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) writel(BM_USBPHY_CTRL_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) x->io_priv + HW_USBPHY_CTRL_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) writel(0, x->io_priv + HW_USBPHY_PWD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct mxs_phy *mxs_phy = to_mxs_phy(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) BM_USBPHY_CTRL_ENIDCHG_WKUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mxs_phy_disconnect_line(mxs_phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) mxs_phy_disconnect_line(mxs_phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static int mxs_phy_on_connect(struct usb_phy *phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) enum usb_device_speed speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) dev_dbg(phy->dev, "%s device has connected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (speed == USB_SPEED_HIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) phy->io_priv + HW_USBPHY_CTRL_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int mxs_phy_on_disconnect(struct usb_phy *phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) enum usb_device_speed speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dev_dbg(phy->dev, "%s device has disconnected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* Sometimes, the speed is not high speed when the error occurs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (readl(phy->io_priv + HW_USBPHY_CTRL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) phy->io_priv + HW_USBPHY_CTRL_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) #define MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static int mxs_charger_data_contact_detect(struct mxs_phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct regmap *regmap = x->regmap_anatop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) int i, stable_contact_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Check if vbus is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) regmap_read(regmap, ANADIG_USB1_VBUS_DET_STAT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!(val & ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) dev_err(x->phy.dev, "vbus is not valid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* Enable charger detector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ANADIG_USB1_CHRG_DETECT_EN_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * - Do not check whether a charger is connected to the USB port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * - Check whether the USB plug has been in contact with each other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* Check if plug is connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) for (i = 0; i < MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (val & ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) stable_contact_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (stable_contact_count > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* Data pin makes contact */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) stable_contact_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) usleep_range(5000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (i == MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) dev_err(x->phy.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) "Data pin can't make good contact.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Disable charger detector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) ANADIG_USB1_CHRG_DETECT_EN_B |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static enum usb_charger_type mxs_charger_primary_detection(struct mxs_phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct regmap *regmap = x->regmap_anatop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) enum usb_charger_type chgr_type = UNKNOWN_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * - Do check whether a charger is connected to the USB port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * - Do not Check whether the USB plug has been in contact with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * each other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ANADIG_USB1_CHRG_DETECT_CHK_CONTACT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* Check if it is a charger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!(val & ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) chgr_type = SDP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) dev_dbg(x->phy.dev, "It is a standard downstream port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* Disable charger detector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ANADIG_USB1_CHRG_DETECT_EN_B |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return chgr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * It must be called after DP is pulled up, which is used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * differentiate DCP and CDP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static enum usb_charger_type mxs_charger_secondary_detection(struct mxs_phy *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct regmap *regmap = x->regmap_anatop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) msleep(80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (val & ANADIG_USB1_CHRG_DET_STAT_DM_STATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) dev_dbg(x->phy.dev, "It is a dedicate charging port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return DCP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) dev_dbg(x->phy.dev, "It is a charging downstream port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return CDP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct mxs_phy *mxs_phy = to_mxs_phy(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct regmap *regmap = mxs_phy->regmap_anatop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) void __iomem *base = phy->io_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) enum usb_charger_type chgr_type = UNKNOWN_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (!regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return UNKNOWN_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (mxs_charger_data_contact_detect(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return chgr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) chgr_type = mxs_charger_primary_detection(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (chgr_type != SDP_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Pull up DP via test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) base + HW_USBPHY_DEBUG_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) regmap_write(regmap, ANADIG_USB1_LOOPBACK_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) ANADIG_USB1_LOOPBACK_UTMI_TESTSTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) chgr_type = mxs_charger_secondary_detection(mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* Stop the test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) regmap_write(regmap, ANADIG_USB1_LOOPBACK_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ANADIG_USB1_LOOPBACK_UTMI_TESTSTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) base + HW_USBPHY_DEBUG_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return chgr_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static int mxs_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct mxs_phy *mxs_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (!of_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (IS_ERR(base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return PTR_ERR(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) "can't get the clock, err=%ld", PTR_ERR(clk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return PTR_ERR(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!mxs_phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /* Some SoCs don't have anatop registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (of_get_property(np, "fsl,anatop", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) (np, "fsl,anatop");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (IS_ERR(mxs_phy->regmap_anatop)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) dev_dbg(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) "failed to find regmap for anatop\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return PTR_ERR(mxs_phy->regmap_anatop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* Precompute which bits of the TX register are to be updated, if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!of_property_read_u32(np, "fsl,tx-cal-45-dn-ohms", &val) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* Scale to a 4-bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DN(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mxs_phy->tx_reg_set |= GM_USBPHY_TX_TXCAL45DN(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (!of_property_read_u32(np, "fsl,tx-cal-45-dp-ohms", &val) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /* Scale to a 4-bit value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DP(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) mxs_phy->tx_reg_set |= GM_USBPHY_TX_TXCAL45DP(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (!of_property_read_u32(np, "fsl,tx-d-cal", &val) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) val >= MXS_PHY_TX_D_CAL_MIN && val <= MXS_PHY_TX_D_CAL_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) /* Scale to a 4-bit value. Round up the values and heavily
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * weight the rounding by adding 2/3 of the denominator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) val = ((MXS_PHY_TX_D_CAL_MAX - val) * 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) + (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN) * 2/3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) / (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) mxs_phy->tx_reg_mask |= GM_USBPHY_TX_D_CAL(~0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) mxs_phy->tx_reg_set |= GM_USBPHY_TX_D_CAL(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) ret = of_alias_get_id(np, "usbphy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) mxs_phy->port_id = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) mxs_phy->phy.io_priv = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) mxs_phy->phy.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) mxs_phy->phy.label = DRIVER_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) mxs_phy->phy.init = mxs_phy_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) mxs_phy->phy.shutdown = mxs_phy_shutdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) mxs_phy->phy.set_suspend = mxs_phy_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) mxs_phy->phy.notify_connect = mxs_phy_on_connect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mxs_phy->phy.type = USB_PHY_TYPE_USB2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) mxs_phy->phy.set_wakeup = mxs_phy_set_wakeup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) mxs_phy->phy.charger_detect = mxs_phy_charger_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) mxs_phy->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) mxs_phy->data = of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) platform_set_drvdata(pdev, mxs_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) device_set_wakeup_capable(&pdev->dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return usb_add_phy_dev(&mxs_phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static int mxs_phy_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) usb_remove_phy(&mxs_phy->phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* If the SoCs don't have anatop, quit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (!mxs_phy->regmap_anatop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (is_imx6q_phy(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) regmap_write(mxs_phy->regmap_anatop, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) else if (is_imx6sl_phy(mxs_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) regmap_write(mxs_phy->regmap_anatop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static int mxs_phy_system_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (device_may_wakeup(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static int mxs_phy_system_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (device_may_wakeup(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) mxs_phy_system_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static struct platform_driver mxs_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .probe = mxs_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .remove = mxs_phy_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .of_match_table = mxs_phy_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .pm = &mxs_phy_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static int __init mxs_phy_module_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return platform_driver_register(&mxs_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) postcore_initcall(mxs_phy_module_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) static void __exit mxs_phy_module_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) platform_driver_unregister(&mxs_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) module_exit(mxs_phy_module_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) MODULE_ALIAS("platform:mxs-usb-phy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) MODULE_LICENSE("GPL");