diff options
Diffstat (limited to 'drivers/usb/musb/omap2430.c')
-rw-r--r-- | drivers/usb/musb/omap2430.c | 257 |
1 files changed, 89 insertions, 168 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index c84e0322c108..0b4cec940386 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -49,97 +49,14 @@ struct omap2430_glue { | |||
49 | enum musb_vbus_id_status status; | 49 | enum musb_vbus_id_status status; |
50 | struct work_struct omap_musb_mailbox_work; | 50 | struct work_struct omap_musb_mailbox_work; |
51 | struct device *control_otghs; | 51 | struct device *control_otghs; |
52 | bool cable_connected; | ||
53 | bool enabled; | ||
54 | bool powered; | ||
52 | }; | 55 | }; |
53 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | 56 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
54 | 57 | ||
55 | static struct omap2430_glue *_glue; | 58 | static struct omap2430_glue *_glue; |
56 | 59 | ||
57 | static struct timer_list musb_idle_timer; | ||
58 | |||
59 | static void musb_do_idle(unsigned long _musb) | ||
60 | { | ||
61 | struct musb *musb = (void *)_musb; | ||
62 | unsigned long flags; | ||
63 | u8 power; | ||
64 | u8 devctl; | ||
65 | |||
66 | spin_lock_irqsave(&musb->lock, flags); | ||
67 | |||
68 | switch (musb->xceiv->otg->state) { | ||
69 | case OTG_STATE_A_WAIT_BCON: | ||
70 | |||
71 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
72 | if (devctl & MUSB_DEVCTL_BDEVICE) { | ||
73 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | ||
74 | MUSB_DEV_MODE(musb); | ||
75 | } else { | ||
76 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | ||
77 | MUSB_HST_MODE(musb); | ||
78 | } | ||
79 | break; | ||
80 | case OTG_STATE_A_SUSPEND: | ||
81 | /* finish RESUME signaling? */ | ||
82 | if (musb->port1_status & MUSB_PORT_STAT_RESUME) { | ||
83 | power = musb_readb(musb->mregs, MUSB_POWER); | ||
84 | power &= ~MUSB_POWER_RESUME; | ||
85 | dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power); | ||
86 | musb_writeb(musb->mregs, MUSB_POWER, power); | ||
87 | musb->is_active = 1; | ||
88 | musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | ||
89 | | MUSB_PORT_STAT_RESUME); | ||
90 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; | ||
91 | usb_hcd_poll_rh_status(musb->hcd); | ||
92 | /* NOTE: it might really be A_WAIT_BCON ... */ | ||
93 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
94 | } | ||
95 | break; | ||
96 | case OTG_STATE_A_HOST: | ||
97 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
98 | if (devctl & MUSB_DEVCTL_BDEVICE) | ||
99 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | ||
100 | else | ||
101 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; | ||
102 | default: | ||
103 | break; | ||
104 | } | ||
105 | spin_unlock_irqrestore(&musb->lock, flags); | ||
106 | } | ||
107 | |||
108 | |||
109 | static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) | ||
110 | { | ||
111 | unsigned long default_timeout = jiffies + msecs_to_jiffies(3); | ||
112 | static unsigned long last_timer; | ||
113 | |||
114 | if (timeout == 0) | ||
115 | timeout = default_timeout; | ||
116 | |||
117 | /* Never idle if active, or when VBUS timeout is not set as host */ | ||
118 | if (musb->is_active || ((musb->a_wait_bcon == 0) | ||
119 | && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) { | ||
120 | dev_dbg(musb->controller, "%s active, deleting timer\n", | ||
121 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
122 | del_timer(&musb_idle_timer); | ||
123 | last_timer = jiffies; | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | if (time_after(last_timer, timeout)) { | ||
128 | if (!timer_pending(&musb_idle_timer)) | ||
129 | last_timer = timeout; | ||
130 | else { | ||
131 | dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n"); | ||
132 | return; | ||
133 | } | ||
134 | } | ||
135 | last_timer = timeout; | ||
136 | |||
137 | dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", | ||
138 | usb_otg_state_string(musb->xceiv->otg->state), | ||
139 | (unsigned long)jiffies_to_msecs(timeout - jiffies)); | ||
140 | mod_timer(&musb_idle_timer, timeout); | ||
141 | } | ||
142 | |||
143 | static void omap2430_musb_set_vbus(struct musb *musb, int is_on) | 60 | static void omap2430_musb_set_vbus(struct musb *musb, int is_on) |
144 | { | 61 | { |
145 | struct usb_otg *otg = musb->xceiv->otg; | 62 | struct usb_otg *otg = musb->xceiv->otg; |
@@ -205,16 +122,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) | |||
205 | musb_readb(musb->mregs, MUSB_DEVCTL)); | 122 | musb_readb(musb->mregs, MUSB_DEVCTL)); |
206 | } | 123 | } |
207 | 124 | ||
208 | static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode) | ||
209 | { | ||
210 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
211 | |||
212 | devctl |= MUSB_DEVCTL_SESSION; | ||
213 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static inline void omap2430_low_level_exit(struct musb *musb) | 125 | static inline void omap2430_low_level_exit(struct musb *musb) |
219 | { | 126 | { |
220 | u32 l; | 127 | u32 l; |
@@ -234,22 +141,63 @@ static inline void omap2430_low_level_init(struct musb *musb) | |||
234 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | 141 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); |
235 | } | 142 | } |
236 | 143 | ||
237 | static void omap2430_musb_mailbox(enum musb_vbus_id_status status) | 144 | /* |
145 | * We can get multiple cable events so we need to keep track | ||
146 | * of the power state. Only keep power enabled if USB cable is | ||
147 | * connected and a gadget is started. | ||
148 | */ | ||
149 | static void omap2430_set_power(struct musb *musb, bool enabled, bool cable) | ||
150 | { | ||
151 | struct device *dev = musb->controller; | ||
152 | struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | ||
153 | bool power_up; | ||
154 | int res; | ||
155 | |||
156 | if (glue->enabled != enabled) | ||
157 | glue->enabled = enabled; | ||
158 | |||
159 | if (glue->cable_connected != cable) | ||
160 | glue->cable_connected = cable; | ||
161 | |||
162 | power_up = glue->enabled && glue->cable_connected; | ||
163 | if (power_up == glue->powered) { | ||
164 | dev_warn(musb->controller, "power state already %i\n", | ||
165 | power_up); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | glue->powered = power_up; | ||
170 | |||
171 | if (power_up) { | ||
172 | res = pm_runtime_get_sync(musb->controller); | ||
173 | if (res < 0) { | ||
174 | dev_err(musb->controller, "could not enable: %i", res); | ||
175 | glue->powered = false; | ||
176 | } | ||
177 | } else { | ||
178 | pm_runtime_mark_last_busy(musb->controller); | ||
179 | pm_runtime_put_autosuspend(musb->controller); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | static int omap2430_musb_mailbox(enum musb_vbus_id_status status) | ||
238 | { | 184 | { |
239 | struct omap2430_glue *glue = _glue; | 185 | struct omap2430_glue *glue = _glue; |
240 | 186 | ||
241 | if (!glue) { | 187 | if (!glue) { |
242 | pr_err("%s: musb core is not yet initialized\n", __func__); | 188 | pr_err("%s: musb core is not yet initialized\n", __func__); |
243 | return; | 189 | return -EPROBE_DEFER; |
244 | } | 190 | } |
245 | glue->status = status; | 191 | glue->status = status; |
246 | 192 | ||
247 | if (!glue_to_musb(glue)) { | 193 | if (!glue_to_musb(glue)) { |
248 | pr_err("%s: musb core is not yet ready\n", __func__); | 194 | pr_err("%s: musb core is not yet ready\n", __func__); |
249 | return; | 195 | return -EPROBE_DEFER; |
250 | } | 196 | } |
251 | 197 | ||
252 | schedule_work(&glue->omap_musb_mailbox_work); | 198 | schedule_work(&glue->omap_musb_mailbox_work); |
199 | |||
200 | return 0; | ||
253 | } | 201 | } |
254 | 202 | ||
255 | static void omap_musb_set_mailbox(struct omap2430_glue *glue) | 203 | static void omap_musb_set_mailbox(struct omap2430_glue *glue) |
@@ -259,6 +207,13 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
259 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); | 207 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); |
260 | struct omap_musb_board_data *data = pdata->board_data; | 208 | struct omap_musb_board_data *data = pdata->board_data; |
261 | struct usb_otg *otg = musb->xceiv->otg; | 209 | struct usb_otg *otg = musb->xceiv->otg; |
210 | bool cable_connected; | ||
211 | |||
212 | cable_connected = ((glue->status == MUSB_ID_GROUND) || | ||
213 | (glue->status == MUSB_VBUS_VALID)); | ||
214 | |||
215 | if (cable_connected) | ||
216 | omap2430_set_power(musb, glue->enabled, cable_connected); | ||
262 | 217 | ||
263 | switch (glue->status) { | 218 | switch (glue->status) { |
264 | case MUSB_ID_GROUND: | 219 | case MUSB_ID_GROUND: |
@@ -268,7 +223,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
268 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | 223 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; |
269 | musb->xceiv->last_event = USB_EVENT_ID; | 224 | musb->xceiv->last_event = USB_EVENT_ID; |
270 | if (musb->gadget_driver) { | 225 | if (musb->gadget_driver) { |
271 | pm_runtime_get_sync(dev); | ||
272 | omap_control_usb_set_mode(glue->control_otghs, | 226 | omap_control_usb_set_mode(glue->control_otghs, |
273 | USB_MODE_HOST); | 227 | USB_MODE_HOST); |
274 | omap2430_musb_set_vbus(musb, 1); | 228 | omap2430_musb_set_vbus(musb, 1); |
@@ -281,8 +235,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
281 | otg->default_a = false; | 235 | otg->default_a = false; |
282 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 236 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
283 | musb->xceiv->last_event = USB_EVENT_VBUS; | 237 | musb->xceiv->last_event = USB_EVENT_VBUS; |
284 | if (musb->gadget_driver) | ||
285 | pm_runtime_get_sync(dev); | ||
286 | omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); | 238 | omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); |
287 | break; | 239 | break; |
288 | 240 | ||
@@ -291,11 +243,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
291 | dev_dbg(dev, "VBUS Disconnect\n"); | 243 | dev_dbg(dev, "VBUS Disconnect\n"); |
292 | 244 | ||
293 | musb->xceiv->last_event = USB_EVENT_NONE; | 245 | musb->xceiv->last_event = USB_EVENT_NONE; |
294 | if (musb->gadget_driver) { | 246 | if (musb->gadget_driver) |
295 | omap2430_musb_set_vbus(musb, 0); | 247 | omap2430_musb_set_vbus(musb, 0); |
296 | pm_runtime_mark_last_busy(dev); | ||
297 | pm_runtime_put_autosuspend(dev); | ||
298 | } | ||
299 | 248 | ||
300 | if (data->interface_type == MUSB_INTERFACE_UTMI) | 249 | if (data->interface_type == MUSB_INTERFACE_UTMI) |
301 | otg_set_vbus(musb->xceiv->otg, 0); | 250 | otg_set_vbus(musb->xceiv->otg, 0); |
@@ -307,6 +256,9 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
307 | dev_dbg(dev, "ID float\n"); | 256 | dev_dbg(dev, "ID float\n"); |
308 | } | 257 | } |
309 | 258 | ||
259 | if (!cable_connected) | ||
260 | omap2430_set_power(musb, glue->enabled, cable_connected); | ||
261 | |||
310 | atomic_notifier_call_chain(&musb->xceiv->notifier, | 262 | atomic_notifier_call_chain(&musb->xceiv->notifier, |
311 | musb->xceiv->last_event, NULL); | 263 | musb->xceiv->last_event, NULL); |
312 | } | 264 | } |
@@ -316,13 +268,8 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work) | |||
316 | { | 268 | { |
317 | struct omap2430_glue *glue = container_of(mailbox_work, | 269 | struct omap2430_glue *glue = container_of(mailbox_work, |
318 | struct omap2430_glue, omap_musb_mailbox_work); | 270 | struct omap2430_glue, omap_musb_mailbox_work); |
319 | struct musb *musb = glue_to_musb(glue); | ||
320 | struct device *dev = musb->controller; | ||
321 | 271 | ||
322 | pm_runtime_get_sync(dev); | ||
323 | omap_musb_set_mailbox(glue); | 272 | omap_musb_set_mailbox(glue); |
324 | pm_runtime_mark_last_busy(dev); | ||
325 | pm_runtime_put_autosuspend(dev); | ||
326 | } | 273 | } |
327 | 274 | ||
328 | static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) | 275 | static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) |
@@ -389,23 +336,7 @@ static int omap2430_musb_init(struct musb *musb) | |||
389 | return PTR_ERR(musb->phy); | 336 | return PTR_ERR(musb->phy); |
390 | } | 337 | } |
391 | musb->isr = omap2430_musb_interrupt; | 338 | musb->isr = omap2430_musb_interrupt; |
392 | 339 | phy_init(musb->phy); | |
393 | /* | ||
394 | * Enable runtime PM for musb parent (this driver). We can't | ||
395 | * do it earlier as struct musb is not yet allocated and we | ||
396 | * need to touch the musb registers for runtime PM. | ||
397 | */ | ||
398 | pm_runtime_enable(glue->dev); | ||
399 | status = pm_runtime_get_sync(glue->dev); | ||
400 | if (status < 0) | ||
401 | goto err1; | ||
402 | |||
403 | status = pm_runtime_get_sync(dev); | ||
404 | if (status < 0) { | ||
405 | dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); | ||
406 | pm_runtime_put_sync(glue->dev); | ||
407 | goto err1; | ||
408 | } | ||
409 | 340 | ||
410 | l = musb_readl(musb->mregs, OTG_INTERFSEL); | 341 | l = musb_readl(musb->mregs, OTG_INTERFSEL); |
411 | 342 | ||
@@ -427,20 +358,10 @@ static int omap2430_musb_init(struct musb *musb) | |||
427 | musb_readl(musb->mregs, OTG_INTERFSEL), | 358 | musb_readl(musb->mregs, OTG_INTERFSEL), |
428 | musb_readl(musb->mregs, OTG_SIMENABLE)); | 359 | musb_readl(musb->mregs, OTG_SIMENABLE)); |
429 | 360 | ||
430 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | ||
431 | |||
432 | if (glue->status != MUSB_UNKNOWN) | 361 | if (glue->status != MUSB_UNKNOWN) |
433 | omap_musb_set_mailbox(glue); | 362 | omap_musb_set_mailbox(glue); |
434 | 363 | ||
435 | phy_init(musb->phy); | ||
436 | phy_power_on(musb->phy); | ||
437 | |||
438 | pm_runtime_put_noidle(musb->controller); | ||
439 | pm_runtime_put_noidle(glue->dev); | ||
440 | return 0; | 364 | return 0; |
441 | |||
442 | err1: | ||
443 | return status; | ||
444 | } | 365 | } |
445 | 366 | ||
446 | static void omap2430_musb_enable(struct musb *musb) | 367 | static void omap2430_musb_enable(struct musb *musb) |
@@ -452,6 +373,11 @@ static void omap2430_musb_enable(struct musb *musb) | |||
452 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); | 373 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); |
453 | struct omap_musb_board_data *data = pdata->board_data; | 374 | struct omap_musb_board_data *data = pdata->board_data; |
454 | 375 | ||
376 | if (!WARN_ON(!musb->phy)) | ||
377 | phy_power_on(musb->phy); | ||
378 | |||
379 | omap2430_set_power(musb, true, glue->cable_connected); | ||
380 | |||
455 | switch (glue->status) { | 381 | switch (glue->status) { |
456 | 382 | ||
457 | case MUSB_ID_GROUND: | 383 | case MUSB_ID_GROUND: |
@@ -487,18 +413,25 @@ static void omap2430_musb_disable(struct musb *musb) | |||
487 | struct device *dev = musb->controller; | 413 | struct device *dev = musb->controller; |
488 | struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | 414 | struct omap2430_glue *glue = dev_get_drvdata(dev->parent); |
489 | 415 | ||
416 | if (!WARN_ON(!musb->phy)) | ||
417 | phy_power_off(musb->phy); | ||
418 | |||
490 | if (glue->status != MUSB_UNKNOWN) | 419 | if (glue->status != MUSB_UNKNOWN) |
491 | omap_control_usb_set_mode(glue->control_otghs, | 420 | omap_control_usb_set_mode(glue->control_otghs, |
492 | USB_MODE_DISCONNECT); | 421 | USB_MODE_DISCONNECT); |
422 | |||
423 | omap2430_set_power(musb, false, glue->cable_connected); | ||
493 | } | 424 | } |
494 | 425 | ||
495 | static int omap2430_musb_exit(struct musb *musb) | 426 | static int omap2430_musb_exit(struct musb *musb) |
496 | { | 427 | { |
497 | del_timer_sync(&musb_idle_timer); | 428 | struct device *dev = musb->controller; |
429 | struct omap2430_glue *glue = dev_get_drvdata(dev->parent); | ||
498 | 430 | ||
499 | omap2430_low_level_exit(musb); | 431 | omap2430_low_level_exit(musb); |
500 | phy_power_off(musb->phy); | ||
501 | phy_exit(musb->phy); | 432 | phy_exit(musb->phy); |
433 | musb->phy = NULL; | ||
434 | cancel_work_sync(&glue->omap_musb_mailbox_work); | ||
502 | 435 | ||
503 | return 0; | 436 | return 0; |
504 | } | 437 | } |
@@ -512,9 +445,6 @@ static const struct musb_platform_ops omap2430_ops = { | |||
512 | .init = omap2430_musb_init, | 445 | .init = omap2430_musb_init, |
513 | .exit = omap2430_musb_exit, | 446 | .exit = omap2430_musb_exit, |
514 | 447 | ||
515 | .set_mode = omap2430_musb_set_mode, | ||
516 | .try_idle = omap2430_musb_try_idle, | ||
517 | |||
518 | .set_vbus = omap2430_musb_set_vbus, | 448 | .set_vbus = omap2430_musb_set_vbus, |
519 | 449 | ||
520 | .enable = omap2430_musb_enable, | 450 | .enable = omap2430_musb_enable, |
@@ -639,11 +569,9 @@ static int omap2430_probe(struct platform_device *pdev) | |||
639 | goto err2; | 569 | goto err2; |
640 | } | 570 | } |
641 | 571 | ||
642 | /* | 572 | pm_runtime_enable(glue->dev); |
643 | * Note that we cannot enable PM runtime yet for this | 573 | pm_runtime_use_autosuspend(glue->dev); |
644 | * driver as we need struct musb initialized first. | 574 | pm_runtime_set_autosuspend_delay(glue->dev, 500); |
645 | * See omap2430_musb_init above. | ||
646 | */ | ||
647 | 575 | ||
648 | ret = platform_device_add(musb); | 576 | ret = platform_device_add(musb); |
649 | if (ret) { | 577 | if (ret) { |
@@ -662,12 +590,14 @@ err0: | |||
662 | 590 | ||
663 | static int omap2430_remove(struct platform_device *pdev) | 591 | static int omap2430_remove(struct platform_device *pdev) |
664 | { | 592 | { |
665 | struct omap2430_glue *glue = platform_get_drvdata(pdev); | 593 | struct omap2430_glue *glue = platform_get_drvdata(pdev); |
594 | struct musb *musb = glue_to_musb(glue); | ||
666 | 595 | ||
667 | pm_runtime_get_sync(glue->dev); | 596 | pm_runtime_get_sync(glue->dev); |
668 | cancel_work_sync(&glue->omap_musb_mailbox_work); | ||
669 | platform_device_unregister(glue->musb); | 597 | platform_device_unregister(glue->musb); |
598 | omap2430_set_power(musb, false, false); | ||
670 | pm_runtime_put_sync(glue->dev); | 599 | pm_runtime_put_sync(glue->dev); |
600 | pm_runtime_dont_use_autosuspend(glue->dev); | ||
671 | pm_runtime_disable(glue->dev); | 601 | pm_runtime_disable(glue->dev); |
672 | 602 | ||
673 | return 0; | 603 | return 0; |
@@ -680,12 +610,13 @@ static int omap2430_runtime_suspend(struct device *dev) | |||
680 | struct omap2430_glue *glue = dev_get_drvdata(dev); | 610 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
681 | struct musb *musb = glue_to_musb(glue); | 611 | struct musb *musb = glue_to_musb(glue); |
682 | 612 | ||
683 | if (musb) { | 613 | if (!musb) |
684 | musb->context.otg_interfsel = musb_readl(musb->mregs, | 614 | return 0; |
685 | OTG_INTERFSEL); | ||
686 | 615 | ||
687 | omap2430_low_level_exit(musb); | 616 | musb->context.otg_interfsel = musb_readl(musb->mregs, |
688 | } | 617 | OTG_INTERFSEL); |
618 | |||
619 | omap2430_low_level_exit(musb); | ||
689 | 620 | ||
690 | return 0; | 621 | return 0; |
691 | } | 622 | } |
@@ -696,7 +627,7 @@ static int omap2430_runtime_resume(struct device *dev) | |||
696 | struct musb *musb = glue_to_musb(glue); | 627 | struct musb *musb = glue_to_musb(glue); |
697 | 628 | ||
698 | if (!musb) | 629 | if (!musb) |
699 | return -EPROBE_DEFER; | 630 | return 0; |
700 | 631 | ||
701 | omap2430_low_level_init(musb); | 632 | omap2430_low_level_init(musb); |
702 | musb_writel(musb->mregs, OTG_INTERFSEL, | 633 | musb_writel(musb->mregs, OTG_INTERFSEL, |
@@ -738,18 +669,8 @@ static struct platform_driver omap2430_driver = { | |||
738 | }, | 669 | }, |
739 | }; | 670 | }; |
740 | 671 | ||
672 | module_platform_driver(omap2430_driver); | ||
673 | |||
741 | MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer"); | 674 | MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer"); |
742 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | 675 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); |
743 | MODULE_LICENSE("GPL v2"); | 676 | MODULE_LICENSE("GPL v2"); |
744 | |||
745 | static int __init omap2430_init(void) | ||
746 | { | ||
747 | return platform_driver_register(&omap2430_driver); | ||
748 | } | ||
749 | subsys_initcall(omap2430_init); | ||
750 | |||
751 | static void __exit omap2430_exit(void) | ||
752 | { | ||
753 | platform_driver_unregister(&omap2430_driver); | ||
754 | } | ||
755 | module_exit(omap2430_exit); | ||