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 
12 #include "ci_hdrc_imx.h"
13 
14 #define MX25_USB_PHY_CTRL_OFFSET	0x08
15 #define MX25_BM_EXTERNAL_VBUS_DIVIDER	BIT(23)
16 
17 #define MX25_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
18 #define MX25_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
19 #define MX25_EHCI_INTERFACE_MASK	(0xf)
20 
21 #define MX25_OTG_SIC_SHIFT		29
22 #define MX25_OTG_SIC_MASK		(0x3 << MX25_OTG_SIC_SHIFT)
23 #define MX25_OTG_PM_BIT			BIT(24)
24 #define MX25_OTG_PP_BIT			BIT(11)
25 #define MX25_OTG_OCPOL_BIT		BIT(3)
26 
27 #define MX25_H1_SIC_SHIFT		21
28 #define MX25_H1_SIC_MASK		(0x3 << MX25_H1_SIC_SHIFT)
29 #define MX25_H1_PP_BIT			BIT(18)
30 #define MX25_H1_PM_BIT			BIT(16)
31 #define MX25_H1_IPPUE_UP_BIT		BIT(7)
32 #define MX25_H1_IPPUE_DOWN_BIT		BIT(6)
33 #define MX25_H1_TLL_BIT			BIT(5)
34 #define MX25_H1_USBTE_BIT		BIT(4)
35 #define MX25_H1_OCPOL_BIT		BIT(2)
36 
37 #define MX27_H1_PM_BIT			BIT(8)
38 #define MX27_H2_PM_BIT			BIT(16)
39 #define MX27_OTG_PM_BIT			BIT(24)
40 
41 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET	0x08
42 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET	0x0c
43 #define MX53_USB_CTRL_1_OFFSET	        0x10
44 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
45 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
46 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
47 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
48 #define MX53_USB_UH2_CTRL_OFFSET	0x14
49 #define MX53_USB_UH3_CTRL_OFFSET	0x18
50 #define MX53_USB_CLKONOFF_CTRL_OFFSET	0x24
51 #define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
52 #define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
53 #define MX53_BM_OVER_CUR_DIS_H1		BIT(5)
54 #define MX53_BM_OVER_CUR_DIS_OTG	BIT(8)
55 #define MX53_BM_OVER_CUR_DIS_UHx	BIT(30)
56 #define MX53_USB_CTRL_1_UH2_ULPI_EN	BIT(26)
57 #define MX53_USB_CTRL_1_UH3_ULPI_EN	BIT(27)
58 #define MX53_USB_UHx_CTRL_WAKE_UP_EN	BIT(7)
59 #define MX53_USB_UHx_CTRL_ULPI_INT_EN	BIT(8)
60 #define MX53_USB_PHYCTRL1_PLLDIV_MASK	0x3
61 #define MX53_USB_PLL_DIV_24_MHZ		0x01
62 
63 #define MX6_BM_NON_BURST_SETTING	BIT(1)
64 #define MX6_BM_OVER_CUR_DIS		BIT(7)
65 #define MX6_BM_OVER_CUR_POLARITY	BIT(8)
66 #define MX6_BM_PWR_POLARITY		BIT(9)
67 #define MX6_BM_WAKEUP_ENABLE		BIT(10)
68 #define MX6_BM_UTMI_ON_CLOCK		BIT(13)
69 #define MX6_BM_ID_WAKEUP		BIT(16)
70 #define MX6_BM_VBUS_WAKEUP		BIT(17)
71 #define MX6SX_BM_DPDM_WAKEUP_EN		BIT(29)
72 #define MX6_BM_WAKEUP_INTR		BIT(31)
73 
74 #define MX6_USB_HSIC_CTRL_OFFSET	0x10
75 /* Send resume signal without 480Mhz PHY clock */
76 #define MX6SX_BM_HSIC_AUTO_RESUME	BIT(23)
77 /* set before portsc.suspendM = 1 */
78 #define MX6_BM_HSIC_DEV_CONN		BIT(21)
79 /* HSIC enable */
80 #define MX6_BM_HSIC_EN			BIT(12)
81 /* Force HSIC module 480M clock on, even when in Host is in suspend mode */
82 #define MX6_BM_HSIC_CLK_ON		BIT(11)
83 
84 #define MX6_USB_OTG1_PHY_CTRL		0x18
85 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
86 #define MX6_USB_OTG2_PHY_CTRL		0x1c
87 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v)	(v << 8)
88 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS	MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
89 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
90 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
91 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
92 
93 #define VF610_OVER_CUR_DIS		BIT(7)
94 
95 #define MX7D_USBNC_USB_CTRL2		0x4
96 #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK	0x3
97 #define MX7D_USB_VBUS_WAKEUP_SOURCE(v)		(v << 0)
98 #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS	MX7D_USB_VBUS_WAKEUP_SOURCE(0)
99 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(1)
100 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(2)
101 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX7D_USB_VBUS_WAKEUP_SOURCE(3)
102 
103 #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
104 				 MX6_BM_ID_WAKEUP)
105 
106 struct usbmisc_ops {
107 	/* It's called once when probe a usb device */
108 	int (*init)(struct imx_usbmisc_data *data);
109 	/* It's called once after adding a usb device */
110 	int (*post)(struct imx_usbmisc_data *data);
111 	/* It's called when we need to enable/disable usb wakeup */
112 	int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
113 	/* It's called before setting portsc.suspendM */
114 	int (*hsic_set_connect)(struct imx_usbmisc_data *data);
115 	/* It's called during suspend/resume */
116 	int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
117 };
118 
119 struct imx_usbmisc {
120 	void __iomem *base;
121 	spinlock_t lock;
122 	const struct usbmisc_ops *ops;
123 };
124 
125 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
126 
127 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
128 {
129 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
130 	unsigned long flags;
131 	u32 val = 0;
132 
133 	if (data->index > 1)
134 		return -EINVAL;
135 
136 	spin_lock_irqsave(&usbmisc->lock, flags);
137 	switch (data->index) {
138 	case 0:
139 		val = readl(usbmisc->base);
140 		val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
141 		val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
142 		val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
143 
144 		/*
145 		 * If the polarity is not configured assume active high for
146 		 * historical reasons.
147 		 */
148 		if (data->oc_pol_configured && data->oc_pol_active_low)
149 			val &= ~MX25_OTG_OCPOL_BIT;
150 
151 		writel(val, usbmisc->base);
152 		break;
153 	case 1:
154 		val = readl(usbmisc->base);
155 		val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
156 		val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
157 		val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
158 			MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
159 
160 		/*
161 		 * If the polarity is not configured assume active high for
162 		 * historical reasons.
163 		 */
164 		if (data->oc_pol_configured && data->oc_pol_active_low)
165 			val &= ~MX25_H1_OCPOL_BIT;
166 
167 		writel(val, usbmisc->base);
168 
169 		break;
170 	}
171 	spin_unlock_irqrestore(&usbmisc->lock, flags);
172 
173 	return 0;
174 }
175 
176 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
177 {
178 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
179 	void __iomem *reg;
180 	unsigned long flags;
181 	u32 val;
182 
183 	if (data->index > 2)
184 		return -EINVAL;
185 
186 	if (data->index)
187 		return 0;
188 
189 	spin_lock_irqsave(&usbmisc->lock, flags);
190 	reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
191 	val = readl(reg);
192 
193 	if (data->evdo)
194 		val |= MX25_BM_EXTERNAL_VBUS_DIVIDER;
195 	else
196 		val &= ~MX25_BM_EXTERNAL_VBUS_DIVIDER;
197 
198 	writel(val, reg);
199 	spin_unlock_irqrestore(&usbmisc->lock, flags);
200 	usleep_range(5000, 10000); /* needed to stabilize voltage */
201 
202 	return 0;
203 }
204 
205 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
206 {
207 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
208 	unsigned long flags;
209 	u32 val;
210 
211 	switch (data->index) {
212 	case 0:
213 		val = MX27_OTG_PM_BIT;
214 		break;
215 	case 1:
216 		val = MX27_H1_PM_BIT;
217 		break;
218 	case 2:
219 		val = MX27_H2_PM_BIT;
220 		break;
221 	default:
222 		return -EINVAL;
223 	}
224 
225 	spin_lock_irqsave(&usbmisc->lock, flags);
226 	if (data->disable_oc)
227 		val = readl(usbmisc->base) | val;
228 	else
229 		val = readl(usbmisc->base) & ~val;
230 	writel(val, usbmisc->base);
231 	spin_unlock_irqrestore(&usbmisc->lock, flags);
232 
233 	return 0;
234 }
235 
236 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
237 {
238 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
239 	void __iomem *reg = NULL;
240 	unsigned long flags;
241 	u32 val = 0;
242 
243 	if (data->index > 3)
244 		return -EINVAL;
245 
246 	/* Select a 24 MHz reference clock for the PHY  */
247 	val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
248 	val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
249 	val |= MX53_USB_PLL_DIV_24_MHZ;
250 	writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
251 
252 	spin_lock_irqsave(&usbmisc->lock, flags);
253 
254 	switch (data->index) {
255 	case 0:
256 		if (data->disable_oc) {
257 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
258 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
259 			writel(val, reg);
260 		}
261 		break;
262 	case 1:
263 		if (data->disable_oc) {
264 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
265 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
266 			writel(val, reg);
267 		}
268 		break;
269 	case 2:
270 		if (data->ulpi) {
271 			/* set USBH2 into ULPI-mode. */
272 			reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
273 			val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
274 			/* select ULPI clock */
275 			val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
276 			val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
277 			writel(val, reg);
278 			/* Set interrupt wake up enable */
279 			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
280 			val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
281 				| MX53_USB_UHx_CTRL_ULPI_INT_EN;
282 			writel(val, reg);
283 			if (is_imx53_usbmisc(data)) {
284 				/* Disable internal 60Mhz clock */
285 				reg = usbmisc->base +
286 					MX53_USB_CLKONOFF_CTRL_OFFSET;
287 				val = readl(reg) |
288 					MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
289 				writel(val, reg);
290 			}
291 
292 		}
293 		if (data->disable_oc) {
294 			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
295 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
296 			writel(val, reg);
297 		}
298 		break;
299 	case 3:
300 		if (data->ulpi) {
301 			/* set USBH3 into ULPI-mode. */
302 			reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
303 			val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
304 			/* select ULPI clock */
305 			val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
306 			val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
307 			writel(val, reg);
308 			/* Set interrupt wake up enable */
309 			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
310 			val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
311 				| MX53_USB_UHx_CTRL_ULPI_INT_EN;
312 			writel(val, reg);
313 
314 			if (is_imx53_usbmisc(data)) {
315 				/* Disable internal 60Mhz clock */
316 				reg = usbmisc->base +
317 					MX53_USB_CLKONOFF_CTRL_OFFSET;
318 				val = readl(reg) |
319 					MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
320 				writel(val, reg);
321 			}
322 		}
323 		if (data->disable_oc) {
324 			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
325 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
326 			writel(val, reg);
327 		}
328 		break;
329 	}
330 
331 	spin_unlock_irqrestore(&usbmisc->lock, flags);
332 
333 	return 0;
334 }
335 
336 static u32 usbmisc_wakeup_setting(struct imx_usbmisc_data *data)
337 {
338 	u32 wakeup_setting = MX6_USB_OTG_WAKEUP_BITS;
339 
340 	if (data->ext_id)
341 		wakeup_setting &= ~MX6_BM_ID_WAKEUP;
342 
343 	if (data->ext_vbus)
344 		wakeup_setting &= ~MX6_BM_VBUS_WAKEUP;
345 
346 	return wakeup_setting;
347 }
348 
349 static int usbmisc_imx6q_set_wakeup
350 	(struct imx_usbmisc_data *data, bool enabled)
351 {
352 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
353 	unsigned long flags;
354 	u32 val;
355 	int ret = 0;
356 
357 	if (data->index > 3)
358 		return -EINVAL;
359 
360 	spin_lock_irqsave(&usbmisc->lock, flags);
361 	val = readl(usbmisc->base + data->index * 4);
362 	if (enabled) {
363 		val &= ~MX6_USB_OTG_WAKEUP_BITS;
364 		val |= usbmisc_wakeup_setting(data);
365 	} else {
366 		if (val & MX6_BM_WAKEUP_INTR)
367 			pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
368 		val &= ~MX6_USB_OTG_WAKEUP_BITS;
369 	}
370 	writel(val, usbmisc->base + data->index * 4);
371 	spin_unlock_irqrestore(&usbmisc->lock, flags);
372 
373 	return ret;
374 }
375 
376 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
377 {
378 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
379 	unsigned long flags;
380 	u32 reg;
381 
382 	if (data->index > 3)
383 		return -EINVAL;
384 
385 	spin_lock_irqsave(&usbmisc->lock, flags);
386 
387 	reg = readl(usbmisc->base + data->index * 4);
388 	if (data->disable_oc) {
389 		reg |= MX6_BM_OVER_CUR_DIS;
390 	} else {
391 		reg &= ~MX6_BM_OVER_CUR_DIS;
392 
393 		/*
394 		 * If the polarity is not configured keep it as setup by the
395 		 * bootloader.
396 		 */
397 		if (data->oc_pol_configured && data->oc_pol_active_low)
398 			reg |= MX6_BM_OVER_CUR_POLARITY;
399 		else if (data->oc_pol_configured)
400 			reg &= ~MX6_BM_OVER_CUR_POLARITY;
401 	}
402 	/* If the polarity is not set keep it as setup by the bootlader */
403 	if (data->pwr_pol == 1)
404 		reg |= MX6_BM_PWR_POLARITY;
405 	writel(reg, usbmisc->base + data->index * 4);
406 
407 	/* SoC non-burst setting */
408 	reg = readl(usbmisc->base + data->index * 4);
409 	writel(reg | MX6_BM_NON_BURST_SETTING,
410 			usbmisc->base + data->index * 4);
411 
412 	/* For HSIC controller */
413 	if (data->hsic) {
414 		reg = readl(usbmisc->base + data->index * 4);
415 		writel(reg | MX6_BM_UTMI_ON_CLOCK,
416 			usbmisc->base + data->index * 4);
417 		reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
418 			+ (data->index - 2) * 4);
419 		reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
420 		writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
421 			+ (data->index - 2) * 4);
422 	}
423 
424 	spin_unlock_irqrestore(&usbmisc->lock, flags);
425 
426 	usbmisc_imx6q_set_wakeup(data, false);
427 
428 	return 0;
429 }
430 
431 static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data)
432 {
433 	int offset, ret = 0;
434 
435 	if (data->index == 2 || data->index == 3) {
436 		offset = (data->index - 2) * 4;
437 	} else if (data->index == 0) {
438 		/*
439 		 * For SoCs like i.MX7D and later, each USB controller has
440 		 * its own non-core register region. For SoCs before i.MX7D,
441 		 * the first two USB controllers are non-HSIC controllers.
442 		 */
443 		offset = 0;
444 	} else {
445 		dev_err(data->dev, "index is error for usbmisc\n");
446 		ret = -EINVAL;
447 	}
448 
449 	return ret ? ret : offset;
450 }
451 
452 static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
453 {
454 	unsigned long flags;
455 	u32 val;
456 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
457 	int offset;
458 
459 	spin_lock_irqsave(&usbmisc->lock, flags);
460 	offset = usbmisc_imx6_hsic_get_reg_offset(data);
461 	if (offset < 0) {
462 		spin_unlock_irqrestore(&usbmisc->lock, flags);
463 		return offset;
464 	}
465 
466 	val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
467 	if (!(val & MX6_BM_HSIC_DEV_CONN))
468 		writel(val | MX6_BM_HSIC_DEV_CONN,
469 			usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
470 
471 	spin_unlock_irqrestore(&usbmisc->lock, flags);
472 
473 	return 0;
474 }
475 
476 static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
477 {
478 	unsigned long flags;
479 	u32 val;
480 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
481 	int offset;
482 
483 	spin_lock_irqsave(&usbmisc->lock, flags);
484 	offset = usbmisc_imx6_hsic_get_reg_offset(data);
485 	if (offset < 0) {
486 		spin_unlock_irqrestore(&usbmisc->lock, flags);
487 		return offset;
488 	}
489 
490 	val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
491 	val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
492 	if (on)
493 		val |= MX6_BM_HSIC_CLK_ON;
494 	else
495 		val &= ~MX6_BM_HSIC_CLK_ON;
496 
497 	writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset);
498 	spin_unlock_irqrestore(&usbmisc->lock, flags);
499 
500 	return 0;
501 }
502 
503 
504 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
505 {
506 	void __iomem *reg = NULL;
507 	unsigned long flags;
508 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
509 	u32 val;
510 
511 	usbmisc_imx6q_init(data);
512 
513 	if (data->index == 0 || data->index == 1) {
514 		reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
515 		spin_lock_irqsave(&usbmisc->lock, flags);
516 		/* Set vbus wakeup source as bvalid */
517 		val = readl(reg);
518 		writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
519 		/*
520 		 * Disable dp/dm wakeup in device mode when vbus is
521 		 * not there.
522 		 */
523 		val = readl(usbmisc->base + data->index * 4);
524 		writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
525 			usbmisc->base + data->index * 4);
526 		spin_unlock_irqrestore(&usbmisc->lock, flags);
527 	}
528 
529 	/* For HSIC controller */
530 	if (data->hsic) {
531 		val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
532 		val |= MX6SX_BM_HSIC_AUTO_RESUME;
533 		writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET);
534 	}
535 
536 	return 0;
537 }
538 
539 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
540 {
541 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
542 	u32 reg;
543 
544 	/*
545 	 * Vybrid only has one misc register set, but in two different
546 	 * areas. These is reflected in two instances of this driver.
547 	 */
548 	if (data->index >= 1)
549 		return -EINVAL;
550 
551 	if (data->disable_oc) {
552 		reg = readl(usbmisc->base);
553 		writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
554 	}
555 
556 	return 0;
557 }
558 
559 static int usbmisc_imx7d_set_wakeup
560 	(struct imx_usbmisc_data *data, bool enabled)
561 {
562 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
563 	unsigned long flags;
564 	u32 val;
565 
566 	spin_lock_irqsave(&usbmisc->lock, flags);
567 	val = readl(usbmisc->base);
568 	if (enabled) {
569 		val &= ~MX6_USB_OTG_WAKEUP_BITS;
570 		val |= usbmisc_wakeup_setting(data);
571 		writel(val, usbmisc->base);
572 	} else {
573 		if (val & MX6_BM_WAKEUP_INTR)
574 			dev_dbg(data->dev, "wakeup int\n");
575 		writel(val & ~MX6_USB_OTG_WAKEUP_BITS, usbmisc->base);
576 	}
577 	spin_unlock_irqrestore(&usbmisc->lock, flags);
578 
579 	return 0;
580 }
581 
582 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
583 {
584 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
585 	unsigned long flags;
586 	u32 reg;
587 
588 	if (data->index >= 1)
589 		return -EINVAL;
590 
591 	spin_lock_irqsave(&usbmisc->lock, flags);
592 	reg = readl(usbmisc->base);
593 	if (data->disable_oc) {
594 		reg |= MX6_BM_OVER_CUR_DIS;
595 	} else {
596 		reg &= ~MX6_BM_OVER_CUR_DIS;
597 
598 		/*
599 		 * If the polarity is not configured keep it as setup by the
600 		 * bootloader.
601 		 */
602 		if (data->oc_pol_configured && data->oc_pol_active_low)
603 			reg |= MX6_BM_OVER_CUR_POLARITY;
604 		else if (data->oc_pol_configured)
605 			reg &= ~MX6_BM_OVER_CUR_POLARITY;
606 	}
607 	/* If the polarity is not set keep it as setup by the bootlader */
608 	if (data->pwr_pol == 1)
609 		reg |= MX6_BM_PWR_POLARITY;
610 	writel(reg, usbmisc->base);
611 
612 	reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
613 	reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
614 	writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
615 		 usbmisc->base + MX7D_USBNC_USB_CTRL2);
616 
617 	spin_unlock_irqrestore(&usbmisc->lock, flags);
618 
619 	usbmisc_imx7d_set_wakeup(data, false);
620 
621 	return 0;
622 }
623 
624 static const struct usbmisc_ops imx25_usbmisc_ops = {
625 	.init = usbmisc_imx25_init,
626 	.post = usbmisc_imx25_post,
627 };
628 
629 static const struct usbmisc_ops imx27_usbmisc_ops = {
630 	.init = usbmisc_imx27_init,
631 };
632 
633 static const struct usbmisc_ops imx51_usbmisc_ops = {
634 	.init = usbmisc_imx53_init,
635 };
636 
637 static const struct usbmisc_ops imx53_usbmisc_ops = {
638 	.init = usbmisc_imx53_init,
639 };
640 
641 static const struct usbmisc_ops imx6q_usbmisc_ops = {
642 	.set_wakeup = usbmisc_imx6q_set_wakeup,
643 	.init = usbmisc_imx6q_init,
644 	.hsic_set_connect = usbmisc_imx6_hsic_set_connect,
645 	.hsic_set_clk   = usbmisc_imx6_hsic_set_clk,
646 };
647 
648 static const struct usbmisc_ops vf610_usbmisc_ops = {
649 	.init = usbmisc_vf610_init,
650 };
651 
652 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
653 	.set_wakeup = usbmisc_imx6q_set_wakeup,
654 	.init = usbmisc_imx6sx_init,
655 	.hsic_set_connect = usbmisc_imx6_hsic_set_connect,
656 	.hsic_set_clk = usbmisc_imx6_hsic_set_clk,
657 };
658 
659 static const struct usbmisc_ops imx7d_usbmisc_ops = {
660 	.init = usbmisc_imx7d_init,
661 	.set_wakeup = usbmisc_imx7d_set_wakeup,
662 };
663 
664 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
665 {
666 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
667 
668 	return usbmisc->ops == &imx53_usbmisc_ops;
669 }
670 
671 int imx_usbmisc_init(struct imx_usbmisc_data *data)
672 {
673 	struct imx_usbmisc *usbmisc;
674 
675 	if (!data)
676 		return 0;
677 
678 	usbmisc = dev_get_drvdata(data->dev);
679 	if (!usbmisc->ops->init)
680 		return 0;
681 	return usbmisc->ops->init(data);
682 }
683 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
684 
685 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
686 {
687 	struct imx_usbmisc *usbmisc;
688 
689 	if (!data)
690 		return 0;
691 
692 	usbmisc = dev_get_drvdata(data->dev);
693 	if (!usbmisc->ops->post)
694 		return 0;
695 	return usbmisc->ops->post(data);
696 }
697 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
698 
699 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
700 {
701 	struct imx_usbmisc *usbmisc;
702 
703 	if (!data)
704 		return 0;
705 
706 	usbmisc = dev_get_drvdata(data->dev);
707 	if (!usbmisc->ops->set_wakeup)
708 		return 0;
709 	return usbmisc->ops->set_wakeup(data, enabled);
710 }
711 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
712 
713 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
714 {
715 	struct imx_usbmisc *usbmisc;
716 
717 	if (!data)
718 		return 0;
719 
720 	usbmisc = dev_get_drvdata(data->dev);
721 	if (!usbmisc->ops->hsic_set_connect || !data->hsic)
722 		return 0;
723 	return usbmisc->ops->hsic_set_connect(data);
724 }
725 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
726 
727 int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
728 {
729 	struct imx_usbmisc *usbmisc;
730 
731 	if (!data)
732 		return 0;
733 
734 	usbmisc = dev_get_drvdata(data->dev);
735 	if (!usbmisc->ops->hsic_set_clk || !data->hsic)
736 		return 0;
737 	return usbmisc->ops->hsic_set_clk(data, on);
738 }
739 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
740 static const struct of_device_id usbmisc_imx_dt_ids[] = {
741 	{
742 		.compatible = "fsl,imx25-usbmisc",
743 		.data = &imx25_usbmisc_ops,
744 	},
745 	{
746 		.compatible = "fsl,imx35-usbmisc",
747 		.data = &imx25_usbmisc_ops,
748 	},
749 	{
750 		.compatible = "fsl,imx27-usbmisc",
751 		.data = &imx27_usbmisc_ops,
752 	},
753 	{
754 		.compatible = "fsl,imx51-usbmisc",
755 		.data = &imx51_usbmisc_ops,
756 	},
757 	{
758 		.compatible = "fsl,imx53-usbmisc",
759 		.data = &imx53_usbmisc_ops,
760 	},
761 	{
762 		.compatible = "fsl,imx6q-usbmisc",
763 		.data = &imx6q_usbmisc_ops,
764 	},
765 	{
766 		.compatible = "fsl,vf610-usbmisc",
767 		.data = &vf610_usbmisc_ops,
768 	},
769 	{
770 		.compatible = "fsl,imx6sx-usbmisc",
771 		.data = &imx6sx_usbmisc_ops,
772 	},
773 	{
774 		.compatible = "fsl,imx6ul-usbmisc",
775 		.data = &imx6sx_usbmisc_ops,
776 	},
777 	{
778 		.compatible = "fsl,imx7d-usbmisc",
779 		.data = &imx7d_usbmisc_ops,
780 	},
781 	{
782 		.compatible = "fsl,imx7ulp-usbmisc",
783 		.data = &imx7d_usbmisc_ops,
784 	},
785 	{ /* sentinel */ }
786 };
787 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
788 
789 static int usbmisc_imx_probe(struct platform_device *pdev)
790 {
791 	struct imx_usbmisc *data;
792 	const struct of_device_id *of_id;
793 
794 	of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
795 	if (!of_id)
796 		return -ENODEV;
797 
798 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
799 	if (!data)
800 		return -ENOMEM;
801 
802 	spin_lock_init(&data->lock);
803 
804 	data->base = devm_platform_ioremap_resource(pdev, 0);
805 	if (IS_ERR(data->base))
806 		return PTR_ERR(data->base);
807 
808 	data->ops = (const struct usbmisc_ops *)of_id->data;
809 	platform_set_drvdata(pdev, data);
810 
811 	return 0;
812 }
813 
814 static int usbmisc_imx_remove(struct platform_device *pdev)
815 {
816 	return 0;
817 }
818 
819 static struct platform_driver usbmisc_imx_driver = {
820 	.probe = usbmisc_imx_probe,
821 	.remove = usbmisc_imx_remove,
822 	.driver = {
823 		.name = "usbmisc_imx",
824 		.of_match_table = usbmisc_imx_dt_ids,
825 	 },
826 };
827 
828 module_platform_driver(usbmisc_imx_driver);
829 
830 MODULE_ALIAS("platform:usbmisc-imx");
831 MODULE_LICENSE("GPL");
832 MODULE_DESCRIPTION("driver for imx usb non-core registers");
833 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
834