cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usbmisc_imx.c (32618B)


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