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