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