1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  *
4  * The code contained herein is licensed under the GNU General Public
5  * License. You may obtain a copy of the GNU General Public License
6  * Version 2 or later at the following locations:
7  *
8  * http://www.opensource.org/licenses/gpl-license.html
9  * http://www.gnu.org/copyleft/gpl.html
10  */
11 
12 #include <linux/module.h>
13 #include <linux/of_platform.h>
14 #include <linux/err.h>
15 #include <linux/io.h>
16 #include <linux/delay.h>
17 
18 #include "ci_hdrc_imx.h"
19 
20 #define MX25_USB_PHY_CTRL_OFFSET	0x08
21 #define MX25_BM_EXTERNAL_VBUS_DIVIDER	BIT(23)
22 
23 #define MX25_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
24 #define MX25_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
25 #define MX25_EHCI_INTERFACE_MASK	(0xf)
26 
27 #define MX25_OTG_SIC_SHIFT		29
28 #define MX25_OTG_SIC_MASK		(0x3 << MX25_OTG_SIC_SHIFT)
29 #define MX25_OTG_PM_BIT			BIT(24)
30 #define MX25_OTG_PP_BIT			BIT(11)
31 #define MX25_OTG_OCPOL_BIT		BIT(3)
32 
33 #define MX25_H1_SIC_SHIFT		21
34 #define MX25_H1_SIC_MASK		(0x3 << MX25_H1_SIC_SHIFT)
35 #define MX25_H1_PP_BIT			BIT(18)
36 #define MX25_H1_PM_BIT			BIT(16)
37 #define MX25_H1_IPPUE_UP_BIT		BIT(7)
38 #define MX25_H1_IPPUE_DOWN_BIT		BIT(6)
39 #define MX25_H1_TLL_BIT			BIT(5)
40 #define MX25_H1_USBTE_BIT		BIT(4)
41 #define MX25_H1_OCPOL_BIT		BIT(2)
42 
43 #define MX27_H1_PM_BIT			BIT(8)
44 #define MX27_H2_PM_BIT			BIT(16)
45 #define MX27_OTG_PM_BIT			BIT(24)
46 
47 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET	0x08
48 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET	0x0c
49 #define MX53_USB_CTRL_1_OFFSET	        0x10
50 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
51 #define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
52 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
53 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
54 #define MX53_USB_UH2_CTRL_OFFSET	0x14
55 #define MX53_USB_UH3_CTRL_OFFSET	0x18
56 #define MX53_USB_CLKONOFF_CTRL_OFFSET	0x24
57 #define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
58 #define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
59 #define MX53_BM_OVER_CUR_DIS_H1		BIT(5)
60 #define MX53_BM_OVER_CUR_DIS_OTG	BIT(8)
61 #define MX53_BM_OVER_CUR_DIS_UHx	BIT(30)
62 #define MX53_USB_CTRL_1_UH2_ULPI_EN	BIT(26)
63 #define MX53_USB_CTRL_1_UH3_ULPI_EN	BIT(27)
64 #define MX53_USB_UHx_CTRL_WAKE_UP_EN	BIT(7)
65 #define MX53_USB_UHx_CTRL_ULPI_INT_EN	BIT(8)
66 #define MX53_USB_PHYCTRL1_PLLDIV_MASK	0x3
67 #define MX53_USB_PLL_DIV_24_MHZ		0x01
68 
69 #define MX6_BM_NON_BURST_SETTING	BIT(1)
70 #define MX6_BM_OVER_CUR_DIS		BIT(7)
71 #define MX6_BM_OVER_CUR_POLARITY	BIT(8)
72 #define MX6_BM_WAKEUP_ENABLE		BIT(10)
73 #define MX6_BM_ID_WAKEUP		BIT(16)
74 #define MX6_BM_VBUS_WAKEUP		BIT(17)
75 #define MX6SX_BM_DPDM_WAKEUP_EN		BIT(29)
76 #define MX6_BM_WAKEUP_INTR		BIT(31)
77 #define MX6_USB_OTG1_PHY_CTRL		0x18
78 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
79 #define MX6_USB_OTG2_PHY_CTRL		0x1c
80 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v)	(v << 8)
81 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS	MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
82 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
83 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID	MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
84 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
85 
86 #define VF610_OVER_CUR_DIS		BIT(7)
87 
88 #define MX7D_USBNC_USB_CTRL2		0x4
89 #define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK	0x3
90 #define MX7D_USB_VBUS_WAKEUP_SOURCE(v)		(v << 0)
91 #define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS	MX7D_USB_VBUS_WAKEUP_SOURCE(0)
92 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(1)
93 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID	MX7D_USB_VBUS_WAKEUP_SOURCE(2)
94 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END	MX7D_USB_VBUS_WAKEUP_SOURCE(3)
95 
96 struct usbmisc_ops {
97 	/* It's called once when probe a usb device */
98 	int (*init)(struct imx_usbmisc_data *data);
99 	/* It's called once after adding a usb device */
100 	int (*post)(struct imx_usbmisc_data *data);
101 	/* It's called when we need to enable/disable usb wakeup */
102 	int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
103 };
104 
105 struct imx_usbmisc {
106 	void __iomem *base;
107 	spinlock_t lock;
108 	const struct usbmisc_ops *ops;
109 };
110 
111 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
112 {
113 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
114 	unsigned long flags;
115 	u32 val = 0;
116 
117 	if (data->index > 1)
118 		return -EINVAL;
119 
120 	spin_lock_irqsave(&usbmisc->lock, flags);
121 	switch (data->index) {
122 	case 0:
123 		val = readl(usbmisc->base);
124 		val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
125 		val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
126 		val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
127 		writel(val, usbmisc->base);
128 		break;
129 	case 1:
130 		val = readl(usbmisc->base);
131 		val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
132 		val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
133 		val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
134 			MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
135 
136 		writel(val, usbmisc->base);
137 
138 		break;
139 	}
140 	spin_unlock_irqrestore(&usbmisc->lock, flags);
141 
142 	return 0;
143 }
144 
145 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
146 {
147 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
148 	void __iomem *reg;
149 	unsigned long flags;
150 	u32 val;
151 
152 	if (data->index > 2)
153 		return -EINVAL;
154 
155 	if (data->evdo) {
156 		spin_lock_irqsave(&usbmisc->lock, flags);
157 		reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
158 		val = readl(reg);
159 		writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
160 		spin_unlock_irqrestore(&usbmisc->lock, flags);
161 		usleep_range(5000, 10000); /* needed to stabilize voltage */
162 	}
163 
164 	return 0;
165 }
166 
167 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
168 {
169 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
170 	unsigned long flags;
171 	u32 val;
172 
173 	switch (data->index) {
174 	case 0:
175 		val = MX27_OTG_PM_BIT;
176 		break;
177 	case 1:
178 		val = MX27_H1_PM_BIT;
179 		break;
180 	case 2:
181 		val = MX27_H2_PM_BIT;
182 		break;
183 	default:
184 		return -EINVAL;
185 	}
186 
187 	spin_lock_irqsave(&usbmisc->lock, flags);
188 	if (data->disable_oc)
189 		val = readl(usbmisc->base) | val;
190 	else
191 		val = readl(usbmisc->base) & ~val;
192 	writel(val, usbmisc->base);
193 	spin_unlock_irqrestore(&usbmisc->lock, flags);
194 
195 	return 0;
196 }
197 
198 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
199 {
200 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
201 	void __iomem *reg = NULL;
202 	unsigned long flags;
203 	u32 val = 0;
204 
205 	if (data->index > 3)
206 		return -EINVAL;
207 
208 	/* Select a 24 MHz reference clock for the PHY  */
209 	val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
210 	val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
211 	val |= MX53_USB_PLL_DIV_24_MHZ;
212 	writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
213 
214 	spin_lock_irqsave(&usbmisc->lock, flags);
215 
216 	switch (data->index) {
217 	case 0:
218 		if (data->disable_oc) {
219 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
220 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
221 			writel(val, reg);
222 		}
223 		break;
224 	case 1:
225 		if (data->disable_oc) {
226 			reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
227 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
228 			writel(val, reg);
229 		}
230 		break;
231 	case 2:
232 		if (data->ulpi) {
233 			/* set USBH2 into ULPI-mode. */
234 			reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
235 			val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
236 			/* select ULPI clock */
237 			val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
238 			val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
239 			writel(val, reg);
240 			/* Set interrupt wake up enable */
241 			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
242 			val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
243 				| MX53_USB_UHx_CTRL_ULPI_INT_EN;
244 			writel(val, reg);
245 			/* Disable internal 60Mhz clock */
246 			reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
247 			val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
248 			writel(val, reg);
249 		}
250 		if (data->disable_oc) {
251 			reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
252 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
253 			writel(val, reg);
254 		}
255 		break;
256 	case 3:
257 		if (data->ulpi) {
258 			/* set USBH3 into ULPI-mode. */
259 			reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
260 			val = readl(reg) | MX53_USB_CTRL_1_UH3_ULPI_EN;
261 			/* select ULPI clock */
262 			val &= ~MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK;
263 			val |= MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI;
264 			writel(val, reg);
265 			/* Set interrupt wake up enable */
266 			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
267 			val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
268 				| MX53_USB_UHx_CTRL_ULPI_INT_EN;
269 			writel(val, reg);
270 			/* Disable internal 60Mhz clock */
271 			reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
272 			val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
273 			writel(val, reg);
274 		}
275 		if (data->disable_oc) {
276 			reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
277 			val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
278 			writel(val, reg);
279 		}
280 		break;
281 	}
282 
283 	spin_unlock_irqrestore(&usbmisc->lock, flags);
284 
285 	return 0;
286 }
287 
288 static int usbmisc_imx6q_set_wakeup
289 	(struct imx_usbmisc_data *data, bool enabled)
290 {
291 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
292 	unsigned long flags;
293 	u32 val;
294 	u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
295 		MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
296 	int ret = 0;
297 
298 	if (data->index > 3)
299 		return -EINVAL;
300 
301 	spin_lock_irqsave(&usbmisc->lock, flags);
302 	val = readl(usbmisc->base + data->index * 4);
303 	if (enabled) {
304 		val |= wakeup_setting;
305 		writel(val, usbmisc->base + data->index * 4);
306 	} else {
307 		if (val & MX6_BM_WAKEUP_INTR)
308 			pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
309 		val &= ~wakeup_setting;
310 		writel(val, usbmisc->base + data->index * 4);
311 	}
312 	spin_unlock_irqrestore(&usbmisc->lock, flags);
313 
314 	return ret;
315 }
316 
317 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
318 {
319 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
320 	unsigned long flags;
321 	u32 reg;
322 
323 	if (data->index > 3)
324 		return -EINVAL;
325 
326 	spin_lock_irqsave(&usbmisc->lock, flags);
327 
328 	reg = readl(usbmisc->base + data->index * 4);
329 	if (data->disable_oc) {
330 		reg |= MX6_BM_OVER_CUR_DIS;
331 	} else if (data->oc_polarity == 1) {
332 		/* High active */
333 		reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY);
334 	}
335 	writel(reg, usbmisc->base + data->index * 4);
336 
337 	/* SoC non-burst setting */
338 	reg = readl(usbmisc->base + data->index * 4);
339 	writel(reg | MX6_BM_NON_BURST_SETTING,
340 			usbmisc->base + data->index * 4);
341 
342 	spin_unlock_irqrestore(&usbmisc->lock, flags);
343 
344 	usbmisc_imx6q_set_wakeup(data, false);
345 
346 	return 0;
347 }
348 
349 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
350 {
351 	void __iomem *reg = NULL;
352 	unsigned long flags;
353 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
354 	u32 val;
355 
356 	usbmisc_imx6q_init(data);
357 
358 	if (data->index == 0 || data->index == 1) {
359 		reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
360 		spin_lock_irqsave(&usbmisc->lock, flags);
361 		/* Set vbus wakeup source as bvalid */
362 		val = readl(reg);
363 		writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
364 		/*
365 		 * Disable dp/dm wakeup in device mode when vbus is
366 		 * not there.
367 		 */
368 		val = readl(usbmisc->base + data->index * 4);
369 		writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
370 			usbmisc->base + data->index * 4);
371 		spin_unlock_irqrestore(&usbmisc->lock, flags);
372 	}
373 
374 	return 0;
375 }
376 
377 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
378 {
379 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
380 	u32 reg;
381 
382 	/*
383 	 * Vybrid only has one misc register set, but in two different
384 	 * areas. These is reflected in two instances of this driver.
385 	 */
386 	if (data->index >= 1)
387 		return -EINVAL;
388 
389 	if (data->disable_oc) {
390 		reg = readl(usbmisc->base);
391 		writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
392 	}
393 
394 	return 0;
395 }
396 
397 static int usbmisc_imx7d_set_wakeup
398 	(struct imx_usbmisc_data *data, bool enabled)
399 {
400 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
401 	unsigned long flags;
402 	u32 val;
403 	u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
404 		MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
405 
406 	spin_lock_irqsave(&usbmisc->lock, flags);
407 	val = readl(usbmisc->base);
408 	if (enabled) {
409 		writel(val | wakeup_setting, usbmisc->base);
410 	} else {
411 		if (val & MX6_BM_WAKEUP_INTR)
412 			dev_dbg(data->dev, "wakeup int\n");
413 		writel(val & ~wakeup_setting, usbmisc->base);
414 	}
415 	spin_unlock_irqrestore(&usbmisc->lock, flags);
416 
417 	return 0;
418 }
419 
420 static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
421 {
422 	struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
423 	unsigned long flags;
424 	u32 reg;
425 
426 	if (data->index >= 1)
427 		return -EINVAL;
428 
429 	spin_lock_irqsave(&usbmisc->lock, flags);
430 	reg = readl(usbmisc->base);
431 	if (data->disable_oc) {
432 		reg |= MX6_BM_OVER_CUR_DIS;
433 	} else if (data->oc_polarity == 1) {
434 		/* High active */
435 		reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY);
436 	}
437 	writel(reg, usbmisc->base);
438 
439 	reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
440 	reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
441 	writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
442 		 usbmisc->base + MX7D_USBNC_USB_CTRL2);
443 	spin_unlock_irqrestore(&usbmisc->lock, flags);
444 
445 	usbmisc_imx7d_set_wakeup(data, false);
446 
447 	return 0;
448 }
449 
450 static const struct usbmisc_ops imx25_usbmisc_ops = {
451 	.init = usbmisc_imx25_init,
452 	.post = usbmisc_imx25_post,
453 };
454 
455 static const struct usbmisc_ops imx27_usbmisc_ops = {
456 	.init = usbmisc_imx27_init,
457 };
458 
459 static const struct usbmisc_ops imx53_usbmisc_ops = {
460 	.init = usbmisc_imx53_init,
461 };
462 
463 static const struct usbmisc_ops imx6q_usbmisc_ops = {
464 	.set_wakeup = usbmisc_imx6q_set_wakeup,
465 	.init = usbmisc_imx6q_init,
466 };
467 
468 static const struct usbmisc_ops vf610_usbmisc_ops = {
469 	.init = usbmisc_vf610_init,
470 };
471 
472 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
473 	.set_wakeup = usbmisc_imx6q_set_wakeup,
474 	.init = usbmisc_imx6sx_init,
475 };
476 
477 static const struct usbmisc_ops imx7d_usbmisc_ops = {
478 	.init = usbmisc_imx7d_init,
479 	.set_wakeup = usbmisc_imx7d_set_wakeup,
480 };
481 
482 int imx_usbmisc_init(struct imx_usbmisc_data *data)
483 {
484 	struct imx_usbmisc *usbmisc;
485 
486 	if (!data)
487 		return 0;
488 
489 	usbmisc = dev_get_drvdata(data->dev);
490 	if (!usbmisc->ops->init)
491 		return 0;
492 	return usbmisc->ops->init(data);
493 }
494 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
495 
496 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
497 {
498 	struct imx_usbmisc *usbmisc;
499 
500 	if (!data)
501 		return 0;
502 
503 	usbmisc = dev_get_drvdata(data->dev);
504 	if (!usbmisc->ops->post)
505 		return 0;
506 	return usbmisc->ops->post(data);
507 }
508 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
509 
510 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
511 {
512 	struct imx_usbmisc *usbmisc;
513 
514 	if (!data)
515 		return 0;
516 
517 	usbmisc = dev_get_drvdata(data->dev);
518 	if (!usbmisc->ops->set_wakeup)
519 		return 0;
520 	return usbmisc->ops->set_wakeup(data, enabled);
521 }
522 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
523 
524 static const struct of_device_id usbmisc_imx_dt_ids[] = {
525 	{
526 		.compatible = "fsl,imx25-usbmisc",
527 		.data = &imx25_usbmisc_ops,
528 	},
529 	{
530 		.compatible = "fsl,imx35-usbmisc",
531 		.data = &imx25_usbmisc_ops,
532 	},
533 	{
534 		.compatible = "fsl,imx27-usbmisc",
535 		.data = &imx27_usbmisc_ops,
536 	},
537 	{
538 		.compatible = "fsl,imx51-usbmisc",
539 		.data = &imx53_usbmisc_ops,
540 	},
541 	{
542 		.compatible = "fsl,imx53-usbmisc",
543 		.data = &imx53_usbmisc_ops,
544 	},
545 	{
546 		.compatible = "fsl,imx6q-usbmisc",
547 		.data = &imx6q_usbmisc_ops,
548 	},
549 	{
550 		.compatible = "fsl,vf610-usbmisc",
551 		.data = &vf610_usbmisc_ops,
552 	},
553 	{
554 		.compatible = "fsl,imx6sx-usbmisc",
555 		.data = &imx6sx_usbmisc_ops,
556 	},
557 	{
558 		.compatible = "fsl,imx6ul-usbmisc",
559 		.data = &imx6sx_usbmisc_ops,
560 	},
561 	{
562 		.compatible = "fsl,imx7d-usbmisc",
563 		.data = &imx7d_usbmisc_ops,
564 	},
565 	{ /* sentinel */ }
566 };
567 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
568 
569 static int usbmisc_imx_probe(struct platform_device *pdev)
570 {
571 	struct resource	*res;
572 	struct imx_usbmisc *data;
573 	const struct of_device_id *of_id;
574 
575 	of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
576 	if (!of_id)
577 		return -ENODEV;
578 
579 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
580 	if (!data)
581 		return -ENOMEM;
582 
583 	spin_lock_init(&data->lock);
584 
585 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
586 	data->base = devm_ioremap_resource(&pdev->dev, res);
587 	if (IS_ERR(data->base))
588 		return PTR_ERR(data->base);
589 
590 	data->ops = (const struct usbmisc_ops *)of_id->data;
591 	platform_set_drvdata(pdev, data);
592 
593 	return 0;
594 }
595 
596 static int usbmisc_imx_remove(struct platform_device *pdev)
597 {
598 	return 0;
599 }
600 
601 static struct platform_driver usbmisc_imx_driver = {
602 	.probe = usbmisc_imx_probe,
603 	.remove = usbmisc_imx_remove,
604 	.driver = {
605 		.name = "usbmisc_imx",
606 		.of_match_table = usbmisc_imx_dt_ids,
607 	 },
608 };
609 
610 module_platform_driver(usbmisc_imx_driver);
611 
612 MODULE_ALIAS("platform:usbmisc-imx");
613 MODULE_LICENSE("GPL v2");
614 MODULE_DESCRIPTION("driver for imx usb non-core registers");
615 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
616