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