]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/usb/chipidea/usbmisc_imx.c
ENGR00299939-3 USB: imx6x: Add dummy LDO2p5 regulator for VBUS wakeup
[karo-tx-linux.git] / drivers / usb / chipidea / usbmisc_imx.c
1 /*
2  * Copyright 2012-2015 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 #include <linux/regmap.h>
18 #include <linux/regulator/consumer.h>
19
20 #include "ci_hdrc_imx.h"
21
22 #define MX25_USB_PHY_CTRL_OFFSET        0x08
23 #define MX25_BM_EXTERNAL_VBUS_DIVIDER   BIT(23)
24
25 #define MX25_EHCI_INTERFACE_SINGLE_UNI  (2 << 0)
26 #define MX25_EHCI_INTERFACE_DIFF_UNI    (0 << 0)
27 #define MX25_EHCI_INTERFACE_MASK        (0xf)
28
29 #define MX25_OTG_SIC_SHIFT              29
30 #define MX25_OTG_SIC_MASK               (0x3 << MX25_OTG_SIC_SHIFT)
31 #define MX25_OTG_PM_BIT                 BIT(24)
32 #define MX25_OTG_PP_BIT                 BIT(11)
33 #define MX25_OTG_OCPOL_BIT              BIT(3)
34
35 #define MX25_H1_SIC_SHIFT               21
36 #define MX25_H1_SIC_MASK                (0x3 << MX25_H1_SIC_SHIFT)
37 #define MX25_H1_PP_BIT                  BIT(18)
38 #define MX25_H1_PM_BIT                  BIT(16)
39 #define MX25_H1_IPPUE_UP_BIT            BIT(7)
40 #define MX25_H1_IPPUE_DOWN_BIT          BIT(6)
41 #define MX25_H1_TLL_BIT                 BIT(5)
42 #define MX25_H1_USBTE_BIT               BIT(4)
43 #define MX25_H1_OCPOL_BIT               BIT(2)
44
45 #define MX27_H1_PM_BIT                  BIT(8)
46 #define MX27_H2_PM_BIT                  BIT(16)
47 #define MX27_OTG_PM_BIT                 BIT(24)
48
49 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET  0x08
50 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET  0x0c
51 #define MX53_USB_UH2_CTRL_OFFSET        0x14
52 #define MX53_USB_UH3_CTRL_OFFSET        0x18
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_PHYCTRL1_PLLDIV_MASK   0x3
57 #define MX53_USB_PLL_DIV_24_MHZ         0x01
58
59 #define MX6_BM_UNBURST_SETTING          BIT(1)
60 #define MX6_BM_OVER_CUR_DIS             BIT(7)
61 #define MX6_BM_WAKEUP_ENABLE            BIT(10)
62 #define MX6_BM_UTMI_ON_CLOCK            BIT(13)
63 #define MX6_BM_ID_WAKEUP                BIT(16)
64 #define MX6_BM_VBUS_WAKEUP              BIT(17)
65 #define MX6SX_BM_DPDM_WAKEUP_EN         BIT(29)
66 #define MX6_BM_WAKEUP_INTR              BIT(31)
67
68 #define MX6_USB_HSIC_CTRL_OFFSET        0x10
69 /* Send resume signal without 480Mhz PHY clock */
70 #define MX6SX_BM_HSIC_AUTO_RESUME       BIT(23)
71 /* set before portsc.suspendM = 1 */
72 #define MX6_BM_HSIC_DEV_CONN            BIT(21)
73 /* HSIC enable */
74 #define MX6_BM_HSIC_EN                  BIT(12)
75 /* Force HSIC module 480M clock on, even when in Host is in suspend mode */
76 #define MX6_BM_HSIC_CLK_ON              BIT(11)
77
78 #define MX6_USB_OTG1_PHY_CTRL           0x18
79 /* For imx6dql, it is host-only controller, for later imx6, it is otg's */
80 #define MX6_USB_OTG2_PHY_CTRL           0x1c
81 #define MX6SX_USB_VBUS_WAKEUP_SOURCE(v) (v << 8)
82 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_VBUS       MX6SX_USB_VBUS_WAKEUP_SOURCE(0)
83 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_AVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(1)
84 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID     MX6SX_USB_VBUS_WAKEUP_SOURCE(2)
85 #define MX6SX_USB_VBUS_WAKEUP_SOURCE_SESS_END   MX6SX_USB_VBUS_WAKEUP_SOURCE(3)
86
87 #define VF610_OVER_CUR_DIS              BIT(7)
88
89 #define ANADIG_ANA_MISC0                0x150
90 #define ANADIG_ANA_MISC0_SET            0x154
91 #define ANADIG_ANA_MISC0_CLK_DELAY(x)   ((x >> 26) & 0x7)
92
93 struct usbmisc_ops {
94         /* It's called once when probe a usb device */
95         int (*init)(struct imx_usbmisc_data *data);
96         /* It's called once after adding a usb device */
97         int (*post)(struct imx_usbmisc_data *data);
98         /* It's called when we need to enable/disable usb wakeup */
99         int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
100         /* It's called when system resume from usb power lost */
101         int (*power_lost_check)(struct imx_usbmisc_data *data);
102         /* It's called before setting portsc.suspendM */
103         int (*hsic_set_connect)(struct imx_usbmisc_data *data);
104         /* It's called during suspend/resume */
105         int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
106 };
107
108 struct imx_usbmisc {
109         void __iomem *base;
110         spinlock_t lock;
111         const struct usbmisc_ops *ops;
112 };
113
114 static struct regulator *vbus_wakeup_reg;
115
116 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
117 {
118         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
119         unsigned long flags;
120         u32 val = 0;
121
122         if (data->index > 1)
123                 return -EINVAL;
124
125         spin_lock_irqsave(&usbmisc->lock, flags);
126         switch (data->index) {
127         case 0:
128                 val = readl(usbmisc->base);
129                 val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
130                 val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
131                 val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
132                 writel(val, usbmisc->base);
133                 break;
134         case 1:
135                 val = readl(usbmisc->base);
136                 val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT |  MX25_H1_IPPUE_UP_BIT);
137                 val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
138                 val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
139                         MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
140
141                 writel(val, usbmisc->base);
142
143                 break;
144         }
145         spin_unlock_irqrestore(&usbmisc->lock, flags);
146
147         return 0;
148 }
149
150 static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
151 {
152         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
153         void __iomem *reg;
154         unsigned long flags;
155         u32 val;
156
157         if (data->index > 2)
158                 return -EINVAL;
159
160         if (data->evdo) {
161                 spin_lock_irqsave(&usbmisc->lock, flags);
162                 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
163                 val = readl(reg);
164                 writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
165                 spin_unlock_irqrestore(&usbmisc->lock, flags);
166                 usleep_range(5000, 10000); /* needed to stabilize voltage */
167         }
168
169         return 0;
170 }
171
172 static int usbmisc_imx27_init(struct imx_usbmisc_data *data)
173 {
174         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
175         unsigned long flags;
176         u32 val;
177
178         switch (data->index) {
179         case 0:
180                 val = MX27_OTG_PM_BIT;
181                 break;
182         case 1:
183                 val = MX27_H1_PM_BIT;
184                 break;
185         case 2:
186                 val = MX27_H2_PM_BIT;
187                 break;
188         default:
189                 return -EINVAL;
190         };
191
192         spin_lock_irqsave(&usbmisc->lock, flags);
193         if (data->disable_oc)
194                 val = readl(usbmisc->base) | val;
195         else
196                 val = readl(usbmisc->base) & ~val;
197         writel(val, usbmisc->base);
198         spin_unlock_irqrestore(&usbmisc->lock, flags);
199
200         return 0;
201 }
202
203 static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
204 {
205         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
206         void __iomem *reg = NULL;
207         unsigned long flags;
208         u32 val = 0;
209
210         if (data->index > 3)
211                 return -EINVAL;
212
213         /* Select a 24 MHz reference clock for the PHY  */
214         val = readl(usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
215         val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
216         val |= MX53_USB_PLL_DIV_24_MHZ;
217         writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
218
219         if (data->disable_oc) {
220                 spin_lock_irqsave(&usbmisc->lock, flags);
221                 switch (data->index) {
222                 case 0:
223                         reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
224                         val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
225                         break;
226                 case 1:
227                         reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
228                         val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
229                         break;
230                 case 2:
231                         reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
232                         val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
233                         break;
234                 case 3:
235                         reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
236                         val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
237                         break;
238                 }
239                 if (reg && val)
240                         writel(val, reg);
241                 spin_unlock_irqrestore(&usbmisc->lock, flags);
242         }
243
244         return 0;
245 }
246
247 static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data)
248 {
249         unsigned long flags;
250         u32 val;
251         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
252
253         spin_lock_irqsave(&usbmisc->lock, flags);
254         if (data->index == 2 || data->index == 3) {
255                 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
256                                                 + (data->index - 2) * 4);
257                 if (!(val & MX6_BM_HSIC_DEV_CONN))
258                         writel(val | MX6_BM_HSIC_DEV_CONN,
259                                 usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
260                                                 + (data->index - 2) * 4);
261         }
262         spin_unlock_irqrestore(&usbmisc->lock, flags);
263
264         return 0;
265 }
266
267 static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
268 {
269         unsigned long flags;
270         u32 val;
271         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
272
273         spin_lock_irqsave(&usbmisc->lock, flags);
274         if (data->index == 2 || data->index == 3) {
275                 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
276                                                 + (data->index - 2) * 4);
277                 val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON;
278                 if (on)
279                         val |= MX6_BM_HSIC_CLK_ON;
280                 else
281                         val &= ~MX6_BM_HSIC_CLK_ON;
282                 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
283                                                 + (data->index - 2) * 4);
284         }
285         spin_unlock_irqrestore(&usbmisc->lock, flags);
286
287         return 0;
288 }
289
290 static u32 imx6q_finalize_wakeup_setting(struct imx_usbmisc_data *data)
291 {
292         if (data->available_role == USB_DR_MODE_PERIPHERAL)
293                 return MX6_BM_VBUS_WAKEUP;
294         else if (data->available_role == USB_DR_MODE_OTG)
295                 return MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
296
297         return 0;
298 }
299
300 static int usbmisc_imx6q_set_wakeup
301         (struct imx_usbmisc_data *data, bool enabled)
302 {
303         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
304         unsigned long flags;
305         u32 val;
306         u32 wakeup_setting = MX6_BM_WAKEUP_ENABLE;
307         int ret = 0;
308
309         if (data->index > 3)
310                 return -EINVAL;
311
312         spin_lock_irqsave(&usbmisc->lock, flags);
313         val = readl(usbmisc->base + data->index * 4);
314         if (enabled) {
315                 wakeup_setting |= imx6q_finalize_wakeup_setting(data);
316                 writel(val | wakeup_setting, usbmisc->base + data->index * 4);
317                 spin_unlock_irqrestore(&usbmisc->lock, flags);
318                 if (vbus_wakeup_reg)
319                         ret = regulator_enable(vbus_wakeup_reg);
320         } else {
321                 if (val & MX6_BM_WAKEUP_INTR)
322                         pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
323                 wakeup_setting |= MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP;
324                 writel(val & ~wakeup_setting, usbmisc->base + data->index * 4);
325                 spin_unlock_irqrestore(&usbmisc->lock, flags);
326                 if (vbus_wakeup_reg && regulator_is_enabled(vbus_wakeup_reg))
327                         regulator_disable(vbus_wakeup_reg);
328         }
329
330         return ret;
331 }
332
333 static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
334 {
335         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
336         unsigned long flags;
337         u32 reg;
338
339         if (data->index > 3)
340                 return -EINVAL;
341
342         spin_lock_irqsave(&usbmisc->lock, flags);
343
344         if (data->disable_oc) {
345                 reg = readl(usbmisc->base + data->index * 4);
346                 writel(reg | MX6_BM_OVER_CUR_DIS,
347                         usbmisc->base + data->index * 4);
348         }
349
350         /* SoC unburst setting */
351         reg = readl(usbmisc->base + data->index * 4);
352         writel(reg | MX6_BM_UNBURST_SETTING,
353                         usbmisc->base + data->index * 4);
354
355         spin_unlock_irqrestore(&usbmisc->lock, flags);
356
357         usbmisc_imx6q_set_wakeup(data, false);
358
359         return 0;
360 }
361
362 static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
363 {
364         void __iomem *reg = NULL;
365         unsigned long flags;
366         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
367         u32 val;
368         int ret = 0;
369
370         usbmisc_imx6q_init(data);
371
372         if (data->index == 0 || data->index == 1) {
373                 reg = usbmisc->base + MX6_USB_OTG1_PHY_CTRL + data->index * 4;
374                 spin_lock_irqsave(&usbmisc->lock, flags);
375                 /* Set vbus wakeup source as bvalid */
376                 val = readl(reg);
377                 writel(val | MX6SX_USB_VBUS_WAKEUP_SOURCE_BVALID, reg);
378                 /*
379                  * Disable dp/dm wakeup in device mode when vbus is
380                  * not there.
381                  */
382                 val = readl(usbmisc->base + data->index * 4);
383                 writel(val & ~MX6SX_BM_DPDM_WAKEUP_EN,
384                         usbmisc->base + data->index * 4);
385                 spin_unlock_irqrestore(&usbmisc->lock, flags);
386         }
387
388         /* For HSIC controller */
389         if (data->index == 2) {
390                 spin_lock_irqsave(&usbmisc->lock, flags);
391                 val = readl(usbmisc->base + data->index * 4);
392                 writel(val | MX6_BM_UTMI_ON_CLOCK,
393                         usbmisc->base + data->index * 4);
394                 val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
395                                                 + (data->index - 2) * 4);
396                 val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON |
397                                         MX6SX_BM_HSIC_AUTO_RESUME;
398                 writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET
399                                                 + (data->index - 2) * 4);
400                 spin_unlock_irqrestore(&usbmisc->lock, flags);
401
402                 /*
403                  * Need to add delay to wait 24M OSC to be stable,
404                  * it's board specific.
405                  */
406                 regmap_read(data->anatop, ANADIG_ANA_MISC0, &val);
407                 /* 0 <= data->osc_clkgate_delay <= 7 */
408                 if (data->osc_clkgate_delay > ANADIG_ANA_MISC0_CLK_DELAY(val))
409                         regmap_write(data->anatop, ANADIG_ANA_MISC0_SET,
410                                         (data->osc_clkgate_delay) << 26);
411         }
412
413         return ret;
414 }
415
416 static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
417 {
418         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
419         u32 reg;
420
421         /*
422          * Vybrid only has one misc register set, but in two different
423          * areas. These is reflected in two instances of this driver.
424          */
425         if (data->index >= 1)
426                 return -EINVAL;
427
428         if (data->disable_oc) {
429                 reg = readl(usbmisc->base);
430                 writel(reg | VF610_OVER_CUR_DIS, usbmisc->base);
431         }
432
433         return 0;
434 }
435
436 static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
437 {
438         struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
439         unsigned long flags;
440         u32 val;
441
442         spin_lock_irqsave(&usbmisc->lock, flags);
443         val = readl(usbmisc->base + data->index * 4);
444         spin_unlock_irqrestore(&usbmisc->lock, flags);
445         /*
446          * Here use a power on reset value to judge
447          * if the controller experienced a power lost
448          */
449         if (val == 0x30001000)
450                 return 1;
451         else
452                 return 0;
453 }
454
455 static const struct usbmisc_ops imx25_usbmisc_ops = {
456         .init = usbmisc_imx25_init,
457         .post = usbmisc_imx25_post,
458 };
459
460 static const struct usbmisc_ops imx27_usbmisc_ops = {
461         .init = usbmisc_imx27_init,
462 };
463
464 static const struct usbmisc_ops imx53_usbmisc_ops = {
465         .init = usbmisc_imx53_init,
466 };
467
468 static const struct usbmisc_ops imx6q_usbmisc_ops = {
469         .set_wakeup = usbmisc_imx6q_set_wakeup,
470         .init = usbmisc_imx6q_init,
471         .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
472         .hsic_set_clk   = usbmisc_imx6_hsic_set_clk,
473 };
474
475 static const struct usbmisc_ops vf610_usbmisc_ops = {
476         .init = usbmisc_vf610_init,
477 };
478
479 static const struct usbmisc_ops imx6sx_usbmisc_ops = {
480         .set_wakeup = usbmisc_imx6q_set_wakeup,
481         .init = usbmisc_imx6sx_init,
482         .power_lost_check = usbmisc_imx6sx_power_lost_check,
483         .hsic_set_connect = usbmisc_imx6_hsic_set_connect,
484         .hsic_set_clk = usbmisc_imx6_hsic_set_clk,
485 };
486
487 int imx_usbmisc_init(struct imx_usbmisc_data *data)
488 {
489         struct imx_usbmisc *usbmisc;
490
491         if (!data)
492                 return 0;
493
494         usbmisc = dev_get_drvdata(data->dev);
495         if (!usbmisc->ops->init)
496                 return 0;
497         return usbmisc->ops->init(data);
498 }
499 EXPORT_SYMBOL_GPL(imx_usbmisc_init);
500
501 int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
502 {
503         struct imx_usbmisc *usbmisc;
504
505         if (!data)
506                 return 0;
507
508         usbmisc = dev_get_drvdata(data->dev);
509         if (!usbmisc->ops->post)
510                 return 0;
511         return usbmisc->ops->post(data);
512 }
513 EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
514
515 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
516 {
517         struct imx_usbmisc *usbmisc;
518
519         if (!data)
520                 return 0;
521
522         usbmisc = dev_get_drvdata(data->dev);
523         if (!usbmisc->ops->set_wakeup)
524                 return 0;
525         return usbmisc->ops->set_wakeup(data, enabled);
526 }
527 EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
528
529 int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *data)
530 {
531         struct imx_usbmisc *usbmisc;
532
533         if (!data)
534                 return 0;
535
536         usbmisc = dev_get_drvdata(data->dev);
537         if (!usbmisc->ops->power_lost_check)
538                 return 0;
539         return usbmisc->ops->power_lost_check(data);
540 }
541 EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check);
542
543 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data)
544 {
545         struct imx_usbmisc *usbmisc;
546
547         if (!data)
548                 return 0;
549
550         usbmisc = dev_get_drvdata(data->dev);
551         if (!usbmisc->ops->hsic_set_connect)
552                 return 0;
553         return usbmisc->ops->hsic_set_connect(data);
554 }
555 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect);
556
557 int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
558 {
559         struct imx_usbmisc *usbmisc;
560
561         if (!data)
562                 return 0;
563
564         usbmisc = dev_get_drvdata(data->dev);
565         if (!usbmisc->ops->hsic_set_clk)
566                 return 0;
567         return usbmisc->ops->hsic_set_clk(data, on);
568 }
569 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
570
571 static const struct of_device_id usbmisc_imx_dt_ids[] = {
572         {
573                 .compatible = "fsl,imx25-usbmisc",
574                 .data = &imx25_usbmisc_ops,
575         },
576         {
577                 .compatible = "fsl,imx35-usbmisc",
578                 .data = &imx25_usbmisc_ops,
579         },
580         {
581                 .compatible = "fsl,imx27-usbmisc",
582                 .data = &imx27_usbmisc_ops,
583         },
584         {
585                 .compatible = "fsl,imx51-usbmisc",
586                 .data = &imx53_usbmisc_ops,
587         },
588         {
589                 .compatible = "fsl,imx53-usbmisc",
590                 .data = &imx53_usbmisc_ops,
591         },
592         {
593                 .compatible = "fsl,imx6q-usbmisc",
594                 .data = &imx6q_usbmisc_ops,
595         },
596         {
597                 .compatible = "fsl,vf610-usbmisc",
598                 .data = &vf610_usbmisc_ops,
599         },
600         {
601                 .compatible = "fsl,imx6sx-usbmisc",
602                 .data = &imx6sx_usbmisc_ops,
603         },
604         { /* sentinel */ }
605 };
606 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
607
608 static int usbmisc_imx_probe(struct platform_device *pdev)
609 {
610         struct resource *res;
611         struct imx_usbmisc *data;
612         struct of_device_id *tmp_dev;
613
614         data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
615         if (!data)
616                 return -ENOMEM;
617
618         spin_lock_init(&data->lock);
619
620         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
621         data->base = devm_ioremap_resource(&pdev->dev, res);
622         if (IS_ERR(data->base))
623                 return PTR_ERR(data->base);
624
625         tmp_dev = (struct of_device_id *)
626                 of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
627         data->ops = (const struct usbmisc_ops *)tmp_dev->data;
628         platform_set_drvdata(pdev, data);
629
630         vbus_wakeup_reg = devm_regulator_get(&pdev->dev, "vbus-wakeup");
631         if (PTR_ERR(vbus_wakeup_reg) == -EPROBE_DEFER)
632                 return -EPROBE_DEFER;
633         else if (PTR_ERR(vbus_wakeup_reg) == -ENODEV)
634                 /* no vbus regualator is needed */
635                 vbus_wakeup_reg = NULL;
636         else if (IS_ERR(vbus_wakeup_reg)) {
637                 dev_err(&pdev->dev, "Getting regulator error: %ld\n",
638                         PTR_ERR(vbus_wakeup_reg));
639                 return PTR_ERR(vbus_wakeup_reg);
640         }
641
642         return 0;
643 }
644
645 static int usbmisc_imx_remove(struct platform_device *pdev)
646 {
647         return 0;
648 }
649
650 static struct platform_driver usbmisc_imx_driver = {
651         .probe = usbmisc_imx_probe,
652         .remove = usbmisc_imx_remove,
653         .driver = {
654                 .name = "usbmisc_imx",
655                 .owner = THIS_MODULE,
656                 .of_match_table = usbmisc_imx_dt_ids,
657          },
658 };
659
660 module_platform_driver(usbmisc_imx_driver);
661
662 MODULE_ALIAS("platform:usbmisc-imx");
663 MODULE_LICENSE("GPL v2");
664 MODULE_DESCRIPTION("driver for imx usb non-core registers");
665 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");