^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 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/usb/otg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "ci_hdrc_imx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define MX25_USB_PHY_CTRL_OFFSET 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MX25_EHCI_INTERFACE_SINGLE_UNI (2 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MX25_EHCI_INTERFACE_DIFF_UNI (0 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MX25_EHCI_INTERFACE_MASK (0xf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MX25_OTG_SIC_SHIFT 29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MX25_OTG_PM_BIT BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MX25_OTG_PP_BIT BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MX25_OTG_OCPOL_BIT BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MX25_H1_SIC_SHIFT 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MX25_H1_PP_BIT BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MX25_H1_PM_BIT BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MX25_H1_IPPUE_UP_BIT BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MX25_H1_IPPUE_DOWN_BIT BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MX25_H1_TLL_BIT BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MX25_H1_USBTE_BIT BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MX25_H1_OCPOL_BIT BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MX27_H1_PM_BIT BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MX27_H2_PM_BIT BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MX27_OTG_PM_BIT BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MX53_USB_CTRL_1_OFFSET 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MX53_USB_UH2_CTRL_OFFSET 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define MX53_USB_UH3_CTRL_OFFSET 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define MX53_USB_CLKONOFF_CTRL_OFFSET 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define MX53_BM_OVER_CUR_DIS_H1 BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MX53_BM_OVER_CUR_DIS_OTG BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define MX53_USB_CTRL_1_UH2_ULPI_EN BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MX53_USB_CTRL_1_UH3_ULPI_EN BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MX53_USB_UHx_CTRL_WAKE_UP_EN BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MX53_USB_UHx_CTRL_ULPI_INT_EN BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define MX53_USB_PLL_DIV_24_MHZ 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define MX6_BM_NON_BURST_SETTING BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MX6_BM_OVER_CUR_DIS BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define MX6_BM_OVER_CUR_POLARITY BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MX6_BM_PWR_POLARITY BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MX6_BM_WAKEUP_ENABLE BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MX6_BM_UTMI_ON_CLOCK BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MX6_BM_ID_WAKEUP BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define MX6_BM_VBUS_WAKEUP BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define MX6_BM_WAKEUP_INTR BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MX6_USB_HSIC_CTRL_OFFSET 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Send resume signal without 480Mhz PHY clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define MX6SX_BM_HSIC_AUTO_RESUME BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* set before portsc.suspendM = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MX6_BM_HSIC_DEV_CONN BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* HSIC enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MX6_BM_HSIC_EN BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Force HSIC module 480M clock on, even when in Host is in suspend mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define MX6_BM_HSIC_CLK_ON BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define MX6_USB_OTG1_PHY_CTRL 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define MX6_USB_OTG2_PHY_CTRL 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define VF610_OVER_CUR_DIS BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define MX7D_USBNC_USB_CTRL2 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MX7D_USBNC_AUTO_RESUME BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* The default DM/DP value is pull-down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) BIT(14) | BIT(15))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define MX7D_USB_OTG_PHY_CFG1 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0 BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define MX7D_USB_OTG_PHY_CFG2 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define MX7D_USB_OTG_PHY_STATUS 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define MX7D_USB_OTG_PHY_CFG1 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define TXPREEMPAMPTUNE0_BIT 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define TXPREEMPAMPTUNE0_MASK (3 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define TXVREFTUNE0_BIT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define TXVREFTUNE0_MASK (0xf << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) MX6_BM_ID_WAKEUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct usbmisc_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* It's called once when probe a usb device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int (*init)(struct imx_usbmisc_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* It's called once after adding a usb device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int (*post)(struct imx_usbmisc_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* It's called when we need to enable/disable usb wakeup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* It's called before setting portsc.suspendM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int (*hsic_set_connect)(struct imx_usbmisc_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* It's called during suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* usb charger detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int (*charger_detection)(struct imx_usbmisc_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct imx_usbmisc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) const struct usbmisc_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (data->index > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) switch (data->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) val = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * If the polarity is not configured assume active high for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * historical reasons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (data->oc_pol_configured && data->oc_pol_active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) val &= ~MX25_OTG_OCPOL_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) writel(val, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) val = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT | MX25_H1_IPPUE_UP_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * If the polarity is not configured assume active high for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * historical reasons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (data->oc_pol_configured && data->oc_pol_active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) val &= ~MX25_H1_OCPOL_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) writel(val, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (data->index > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (data->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (data->evdo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) usleep_range(5000, 10000); /* needed to stabilize voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) switch (data->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) val = MX27_OTG_PM_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) val = MX27_H1_PM_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) val = MX27_H2_PM_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (data->disable_oc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) val = readl(usbmisc->base) | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) val = readl(usbmisc->base) & ~val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) writel(val, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void __iomem *reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u32 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (data->index > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* Select a 24 MHz reference clock for the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) val |= MX53_USB_PLL_DIV_24_MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) switch (data->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (data->ulpi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* set USBH2 into ULPI-mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* select ULPI clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Set interrupt wake up enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) | MX53_USB_UHx_CTRL_ULPI_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (is_imx53_usbmisc(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* Disable internal 60Mhz clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) reg = usbmisc->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) MX53_USB_CLKONOFF_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val = readl(reg) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (data->ulpi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* set USBH3 into ULPI-mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* select ULPI clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* Set interrupt wake up enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) | MX53_USB_UHx_CTRL_ULPI_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (is_imx53_usbmisc(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* Disable internal 60Mhz clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) reg = usbmisc->base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) MX53_USB_CLKONOFF_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) val = readl(reg) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) writel(val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) wakeup_setting &= ~MX6_BM_ID_WAKEUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return wakeup_setting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int usbmisc_imx6q_set_wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) (struct imx_usbmisc_data *data, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (data->index > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) val = readl(usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) val &= ~MX6_USB_OTG_WAKEUP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) val |= usbmisc_wakeup_setting(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (val & MX6_BM_WAKEUP_INTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) val &= ~MX6_USB_OTG_WAKEUP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) writel(val, usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (data->index > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) reg = readl(usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) reg |= MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) reg &= ~MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * If the polarity is not configured keep it as setup by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * bootloader.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (data->oc_pol_configured && data->oc_pol_active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) reg |= MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) else if (data->oc_pol_configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) reg &= ~MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* If the polarity is not set keep it as setup by the bootlader */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (data->pwr_pol == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) reg |= MX6_BM_PWR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) writel(reg, usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* SoC non-burst setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) reg = readl(usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) writel(reg | MX6_BM_NON_BURST_SETTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* For HSIC controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (data->hsic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) reg = readl(usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) writel(reg | MX6_BM_UTMI_ON_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) + (data->index - 2) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) + (data->index - 2) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) usbmisc_imx6q_set_wakeup(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int offset, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (data->index == 2 || data->index == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) offset = (data->index - 2) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) } else if (data->index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * For SoCs like i.MX7D and later, each USB controller has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * its own non-core register region. For SoCs before i.MX7D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * the first two USB controllers are non-HSIC controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dev_err(data->dev, "index is error for usbmisc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return ret ? ret : offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) offset = usbmisc_imx6_hsic_get_reg_offset(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (offset < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!(val & MX6_BM_HSIC_DEV_CONN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) writel(val | MX6_BM_HSIC_DEV_CONN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) offset = usbmisc_imx6_hsic_get_reg_offset(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (offset < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) val |= MX6_BM_HSIC_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) val &= ~MX6_BM_HSIC_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) void __iomem *reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) usbmisc_imx6q_init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (data->index == 0 || data->index == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* Set vbus wakeup source as bvalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) val = readl(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * Disable dp/dm wakeup in device mode when vbus is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * not there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) val = readl(usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) usbmisc->base + data->index * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* For HSIC controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (data->hsic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) val |= MX6SX_BM_HSIC_AUTO_RESUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * Vybrid only has one misc register set, but in two different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * areas. These is reflected in two instances of this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (data->index >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static int usbmisc_imx7d_set_wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) (struct imx_usbmisc_data *data, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) val = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) val &= ~MX6_USB_OTG_WAKEUP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) val |= usbmisc_wakeup_setting(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) writel(val, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (val & MX6_BM_WAKEUP_INTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dev_dbg(data->dev, "wakeup int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (data->index >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) reg |= MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) reg &= ~MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * If the polarity is not configured keep it as setup by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * bootloader.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (data->oc_pol_configured && data->oc_pol_active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) reg |= MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) else if (data->oc_pol_configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) reg &= ~MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* If the polarity is not set keep it as setup by the bootlader */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (data->pwr_pol == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) reg |= MX6_BM_PWR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) writel(reg, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* SoC non-burst setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (!data->hsic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) | MX7D_USBNC_AUTO_RESUME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /* PHY tuning for signal quality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (data->emp_curr_control && data->emp_curr_control <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) reg &= ~TXPREEMPAMPTUNE0_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) reg &= ~TXVREFTUNE0_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) usbmisc_imx7d_set_wakeup(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct usb_phy *usb_phy = data->usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* Clear VDATSRCENB0 to disable VDP_SRC and IDM_SNK required by BC 1.2 spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* TVDMSRC_DIS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /* TVDMSRC_ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) msleep(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * Per BC 1.2, check voltage of D+:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * DCP: if greater than VDAT_REF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * CDP: if less than VDAT_REF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) dev_dbg(data->dev, "It is a dedicate charging port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) usb_phy->chg_type = DCP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) dev_dbg(data->dev, "It is a charging downstream port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) usb_phy->chg_type = CDP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static void imx7_disable_charger_detector(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* Set OPMODE to be 2'b00 and disable its override */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int i, data_pin_contact_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) for (i = 0; i < 100; i = i + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (data_pin_contact_count++ > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* Data pin makes contact */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) data_pin_contact_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) usleep_range(5000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /* Disable DCD after finished data contact check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (i == 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) dev_err(data->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) "VBUS is coming from a dedicated power supply.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct usb_phy *usb_phy = data->usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* TVDPSRC_ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) msleep(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) dev_dbg(data->dev, "It is a standard downstream port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) usb_phy->chg_type = SDP_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * Whole charger detection process:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * 1. OPMODE override to be non-driving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * 2. Data contact check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * 3. Primary detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * 4. Secondary detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * 5. Disable charger detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int imx7d_charger_detection(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct usb_phy *usb_phy = data->usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Check if vbus is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) dev_err(data->dev, "vbus is error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * Keep OPMODE to be non-driving mode during the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * charger detection process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ret = imx7d_charger_data_contact_detect(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ret = imx7d_charger_primary_detection(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (!ret && usb_phy->chg_type != SDP_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) ret = imx7d_charger_secondary_detection(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) imx7_disable_charger_detector(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (data->index >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) spin_lock_irqsave(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (data->disable_oc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) reg |= MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) reg &= ~MX6_BM_OVER_CUR_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * If the polarity is not configured keep it as setup by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * bootloader.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (data->oc_pol_configured && data->oc_pol_active_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) reg |= MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) else if (data->oc_pol_configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) reg &= ~MX6_BM_OVER_CUR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* If the polarity is not set keep it as setup by the bootlader */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (data->pwr_pol == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) reg |= MX6_BM_PWR_POLARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) writel(reg, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* SoC non-burst setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (data->hsic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) reg = readl(usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * For non-HSIC controller, the autoresume is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * at MXS PHY driver (usbphy_ctrl bit18).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) writel(reg | MX7D_USBNC_AUTO_RESUME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) usbmisc->base + MX7D_USBNC_USB_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) spin_unlock_irqrestore(&usbmisc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) usbmisc_imx7d_set_wakeup(data, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static const struct usbmisc_ops imx25_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) .init = usbmisc_imx25_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) .post = usbmisc_imx25_post,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static const struct usbmisc_ops imx27_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) .init = usbmisc_imx27_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static const struct usbmisc_ops imx51_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .init = usbmisc_imx53_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) static const struct usbmisc_ops imx53_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) .init = usbmisc_imx53_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) static const struct usbmisc_ops imx6q_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) .set_wakeup = usbmisc_imx6q_set_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) .init = usbmisc_imx6q_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) static const struct usbmisc_ops vf610_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) .init = usbmisc_vf610_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static const struct usbmisc_ops imx6sx_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) .set_wakeup = usbmisc_imx6q_set_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) .init = usbmisc_imx6sx_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static const struct usbmisc_ops imx7d_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .init = usbmisc_imx7d_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .set_wakeup = usbmisc_imx7d_set_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .charger_detection = imx7d_charger_detection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .init = usbmisc_imx7ulp_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .set_wakeup = usbmisc_imx7d_set_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return usbmisc->ops == &imx53_usbmisc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) int imx_usbmisc_init(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!usbmisc->ops->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return usbmisc->ops->init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) EXPORT_SYMBOL_GPL(imx_usbmisc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (!usbmisc->ops->post)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return usbmisc->ops->post(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (!usbmisc->ops->set_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return usbmisc->ops->set_wakeup(data, enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!usbmisc->ops->hsic_set_connect || !data->hsic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return usbmisc->ops->hsic_set_connect(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (!usbmisc->ops->hsic_set_clk || !data->hsic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return usbmisc->ops->hsic_set_clk(data, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct imx_usbmisc *usbmisc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct usb_phy *usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) usbmisc = dev_get_drvdata(data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) usb_phy = data->usb_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!usbmisc->ops->charger_detection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (connect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) ret = usbmisc->ops->charger_detection(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) dev_err(data->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) "Error occurs during detection: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) usb_phy->chg_state = USB_CHARGER_ABSENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) usb_phy->chg_state = USB_CHARGER_PRESENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) usb_phy->chg_state = USB_CHARGER_ABSENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) usb_phy->chg_type = UNKNOWN_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) static const struct of_device_id usbmisc_imx_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) .compatible = "fsl,imx25-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) .data = &imx25_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) .compatible = "fsl,imx35-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) .data = &imx25_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) .compatible = "fsl,imx27-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) .data = &imx27_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .compatible = "fsl,imx51-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) .data = &imx51_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) .compatible = "fsl,imx53-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) .data = &imx53_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) .compatible = "fsl,imx6q-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) .data = &imx6q_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .compatible = "fsl,vf610-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .data = &vf610_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) .compatible = "fsl,imx6sx-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) .data = &imx6sx_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) .compatible = "fsl,imx6ul-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) .data = &imx6sx_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) .compatible = "fsl,imx7d-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) .data = &imx7d_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .compatible = "fsl,imx7ulp-usbmisc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .data = &imx7ulp_usbmisc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static int usbmisc_imx_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) struct imx_usbmisc *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (!of_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) spin_lock_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) data->base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (IS_ERR(data->base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return PTR_ERR(data->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) data->ops = (const struct usbmisc_ops *)of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) static int usbmisc_imx_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static struct platform_driver usbmisc_imx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) .probe = usbmisc_imx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) .remove = usbmisc_imx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .name = "usbmisc_imx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .of_match_table = usbmisc_imx_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) module_platform_driver(usbmisc_imx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) MODULE_ALIAS("platform:usbmisc-imx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) MODULE_DESCRIPTION("driver for imx usb non-core registers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");