diff options
Diffstat (limited to 'drivers/usb/musb/am35x.c')
-rw-r--r-- | drivers/usb/musb/am35x.c | 410 |
1 files changed, 270 insertions, 140 deletions
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index b0aabf3a606f..d5a3da37c90c 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c | |||
@@ -29,8 +29,9 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/dma-mapping.h> | ||
32 | 34 | ||
33 | #include <plat/control.h> | ||
34 | #include <plat/usb.h> | 35 | #include <plat/usb.h> |
35 | 36 | ||
36 | #include "musb_core.h" | 37 | #include "musb_core.h" |
@@ -80,51 +81,18 @@ | |||
80 | 81 | ||
81 | #define USB_MENTOR_CORE_OFFSET 0x400 | 82 | #define USB_MENTOR_CORE_OFFSET 0x400 |
82 | 83 | ||
83 | static inline void phy_on(void) | 84 | struct am35x_glue { |
84 | { | 85 | struct device *dev; |
85 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | 86 | struct platform_device *musb; |
86 | u32 devconf2; | 87 | struct clk *phy_clk; |
87 | 88 | struct clk *clk; | |
88 | /* | 89 | }; |
89 | * Start the on-chip PHY and its PLL. | 90 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
90 | */ | ||
91 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
92 | |||
93 | devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); | ||
94 | devconf2 |= CONF2_PHY_PLLON; | ||
95 | |||
96 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
97 | |||
98 | DBG(1, "Waiting for PHY clock good...\n"); | ||
99 | while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) | ||
100 | & CONF2_PHYCLKGD)) { | ||
101 | cpu_relax(); | ||
102 | |||
103 | if (time_after(jiffies, timeout)) { | ||
104 | DBG(1, "musb PHY clock good timed out\n"); | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static inline void phy_off(void) | ||
111 | { | ||
112 | u32 devconf2; | ||
113 | |||
114 | /* | ||
115 | * Power down the on-chip PHY. | ||
116 | */ | ||
117 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
118 | |||
119 | devconf2 &= ~CONF2_PHY_PLLON; | ||
120 | devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; | ||
121 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
122 | } | ||
123 | 91 | ||
124 | /* | 92 | /* |
125 | * musb_platform_enable - enable interrupts | 93 | * am35x_musb_enable - enable interrupts |
126 | */ | 94 | */ |
127 | void musb_platform_enable(struct musb *musb) | 95 | static void am35x_musb_enable(struct musb *musb) |
128 | { | 96 | { |
129 | void __iomem *reg_base = musb->ctrl_base; | 97 | void __iomem *reg_base = musb->ctrl_base; |
130 | u32 epmask; | 98 | u32 epmask; |
@@ -143,9 +111,9 @@ void musb_platform_enable(struct musb *musb) | |||
143 | } | 111 | } |
144 | 112 | ||
145 | /* | 113 | /* |
146 | * musb_platform_disable - disable HDRC and flush interrupts | 114 | * am35x_musb_disable - disable HDRC and flush interrupts |
147 | */ | 115 | */ |
148 | void musb_platform_disable(struct musb *musb) | 116 | static void am35x_musb_disable(struct musb *musb) |
149 | { | 117 | { |
150 | void __iomem *reg_base = musb->ctrl_base; | 118 | void __iomem *reg_base = musb->ctrl_base; |
151 | 119 | ||
@@ -162,7 +130,7 @@ void musb_platform_disable(struct musb *musb) | |||
162 | #define portstate(stmt) | 130 | #define portstate(stmt) |
163 | #endif | 131 | #endif |
164 | 132 | ||
165 | static void am35x_set_vbus(struct musb *musb, int is_on) | 133 | static void am35x_musb_set_vbus(struct musb *musb, int is_on) |
166 | { | 134 | { |
167 | WARN_ON(is_on && is_peripheral_active(musb)); | 135 | WARN_ON(is_on && is_peripheral_active(musb)); |
168 | } | 136 | } |
@@ -221,7 +189,7 @@ static void otg_timer(unsigned long _musb) | |||
221 | spin_unlock_irqrestore(&musb->lock, flags); | 189 | spin_unlock_irqrestore(&musb->lock, flags); |
222 | } | 190 | } |
223 | 191 | ||
224 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | 192 | static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) |
225 | { | 193 | { |
226 | static unsigned long last_timer; | 194 | static unsigned long last_timer; |
227 | 195 | ||
@@ -251,13 +219,16 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | |||
251 | mod_timer(&otg_workaround, timeout); | 219 | mod_timer(&otg_workaround, timeout); |
252 | } | 220 | } |
253 | 221 | ||
254 | static irqreturn_t am35x_interrupt(int irq, void *hci) | 222 | static irqreturn_t am35x_musb_interrupt(int irq, void *hci) |
255 | { | 223 | { |
256 | struct musb *musb = hci; | 224 | struct musb *musb = hci; |
257 | void __iomem *reg_base = musb->ctrl_base; | 225 | void __iomem *reg_base = musb->ctrl_base; |
226 | struct device *dev = musb->controller; | ||
227 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
228 | struct omap_musb_board_data *data = plat->board_data; | ||
258 | unsigned long flags; | 229 | unsigned long flags; |
259 | irqreturn_t ret = IRQ_NONE; | 230 | irqreturn_t ret = IRQ_NONE; |
260 | u32 epintr, usbintr, lvl_intr; | 231 | u32 epintr, usbintr; |
261 | 232 | ||
262 | spin_lock_irqsave(&musb->lock, flags); | 233 | spin_lock_irqsave(&musb->lock, flags); |
263 | 234 | ||
@@ -346,9 +317,8 @@ eoi: | |||
346 | /* EOI needs to be written for the IRQ to be re-asserted. */ | 317 | /* EOI needs to be written for the IRQ to be re-asserted. */ |
347 | if (ret == IRQ_HANDLED || epintr || usbintr) { | 318 | if (ret == IRQ_HANDLED || epintr || usbintr) { |
348 | /* clear level interrupt */ | 319 | /* clear level interrupt */ |
349 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 320 | if (data->clear_irq) |
350 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 321 | data->clear_irq(); |
351 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
352 | /* write EOI */ | 322 | /* write EOI */ |
353 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); | 323 | musb_writel(reg_base, USB_END_OF_INTR_REG, 0); |
354 | } | 324 | } |
@@ -362,137 +332,85 @@ eoi: | |||
362 | return ret; | 332 | return ret; |
363 | } | 333 | } |
364 | 334 | ||
365 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 335 | static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) |
366 | { | 336 | { |
367 | u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | 337 | struct device *dev = musb->controller; |
338 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
339 | struct omap_musb_board_data *data = plat->board_data; | ||
340 | int retval = 0; | ||
368 | 341 | ||
369 | devconf2 &= ~CONF2_OTGMODE; | 342 | if (data->set_mode) |
370 | switch (musb_mode) { | 343 | data->set_mode(musb_mode); |
371 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 344 | else |
372 | case MUSB_HOST: /* Force VBUS valid, ID = 0 */ | 345 | retval = -EIO; |
373 | devconf2 |= CONF2_FORCE_HOST; | ||
374 | break; | ||
375 | #endif | ||
376 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
377 | case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ | ||
378 | devconf2 |= CONF2_FORCE_DEVICE; | ||
379 | break; | ||
380 | #endif | ||
381 | #ifdef CONFIG_USB_MUSB_OTG | ||
382 | case MUSB_OTG: /* Don't override the VBUS/ID comparators */ | ||
383 | devconf2 |= CONF2_NO_OVERRIDE; | ||
384 | break; | ||
385 | #endif | ||
386 | default: | ||
387 | DBG(2, "Trying to set unsupported mode %u\n", musb_mode); | ||
388 | } | ||
389 | 346 | ||
390 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | 347 | return retval; |
391 | return 0; | ||
392 | } | 348 | } |
393 | 349 | ||
394 | int __init musb_platform_init(struct musb *musb, void *board_data) | 350 | static int am35x_musb_init(struct musb *musb) |
395 | { | 351 | { |
352 | struct device *dev = musb->controller; | ||
353 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
354 | struct omap_musb_board_data *data = plat->board_data; | ||
396 | void __iomem *reg_base = musb->ctrl_base; | 355 | void __iomem *reg_base = musb->ctrl_base; |
397 | u32 rev, lvl_intr, sw_reset; | 356 | u32 rev; |
398 | int status; | ||
399 | 357 | ||
400 | musb->mregs += USB_MENTOR_CORE_OFFSET; | 358 | musb->mregs += USB_MENTOR_CORE_OFFSET; |
401 | 359 | ||
402 | clk_enable(musb->clock); | ||
403 | DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock)); | ||
404 | |||
405 | musb->phy_clock = clk_get(musb->controller, "fck"); | ||
406 | if (IS_ERR(musb->phy_clock)) { | ||
407 | status = PTR_ERR(musb->phy_clock); | ||
408 | goto exit0; | ||
409 | } | ||
410 | clk_enable(musb->phy_clock); | ||
411 | DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock)); | ||
412 | |||
413 | /* Returns zero if e.g. not clocked */ | 360 | /* Returns zero if e.g. not clocked */ |
414 | rev = musb_readl(reg_base, USB_REVISION_REG); | 361 | rev = musb_readl(reg_base, USB_REVISION_REG); |
415 | if (!rev) { | 362 | if (!rev) |
416 | status = -ENODEV; | 363 | return -ENODEV; |
417 | goto exit1; | ||
418 | } | ||
419 | 364 | ||
420 | usb_nop_xceiv_register(); | 365 | usb_nop_xceiv_register(); |
421 | musb->xceiv = otg_get_transceiver(); | 366 | musb->xceiv = otg_get_transceiver(); |
422 | if (!musb->xceiv) { | 367 | if (!musb->xceiv) |
423 | status = -ENODEV; | 368 | return -ENODEV; |
424 | goto exit1; | ||
425 | } | ||
426 | 369 | ||
427 | if (is_host_enabled(musb)) | 370 | if (is_host_enabled(musb)) |
428 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | 371 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); |
429 | 372 | ||
430 | musb->board_set_vbus = am35x_set_vbus; | 373 | /* Reset the musb */ |
431 | 374 | if (data->reset) | |
432 | /* Global reset */ | 375 | data->reset(); |
433 | sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | ||
434 | |||
435 | sw_reset |= AM35XX_USBOTGSS_SW_RST; | ||
436 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
437 | |||
438 | sw_reset &= ~AM35XX_USBOTGSS_SW_RST; | ||
439 | omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET); | ||
440 | 376 | ||
441 | /* Reset the controller */ | 377 | /* Reset the controller */ |
442 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); | 378 | musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); |
443 | 379 | ||
444 | /* Start the on-chip PHY and its PLL. */ | 380 | /* Start the on-chip PHY and its PLL. */ |
445 | phy_on(); | 381 | if (data->set_phy_power) |
382 | data->set_phy_power(1); | ||
446 | 383 | ||
447 | msleep(5); | 384 | msleep(5); |
448 | 385 | ||
449 | musb->isr = am35x_interrupt; | 386 | musb->isr = am35x_musb_interrupt; |
450 | 387 | ||
451 | /* clear level interrupt */ | 388 | /* clear level interrupt */ |
452 | lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | 389 | if (data->clear_irq) |
453 | lvl_intr |= AM35XX_USBOTGSS_INT_CLR; | 390 | data->clear_irq(); |
454 | omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR); | 391 | |
455 | return 0; | 392 | return 0; |
456 | exit1: | ||
457 | clk_disable(musb->phy_clock); | ||
458 | clk_put(musb->phy_clock); | ||
459 | exit0: | ||
460 | clk_disable(musb->clock); | ||
461 | return status; | ||
462 | } | 393 | } |
463 | 394 | ||
464 | int musb_platform_exit(struct musb *musb) | 395 | static int am35x_musb_exit(struct musb *musb) |
465 | { | 396 | { |
397 | struct device *dev = musb->controller; | ||
398 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
399 | struct omap_musb_board_data *data = plat->board_data; | ||
400 | |||
466 | if (is_host_enabled(musb)) | 401 | if (is_host_enabled(musb)) |
467 | del_timer_sync(&otg_workaround); | 402 | del_timer_sync(&otg_workaround); |
468 | 403 | ||
469 | phy_off(); | 404 | /* Shutdown the on-chip PHY and its PLL. */ |
405 | if (data->set_phy_power) | ||
406 | data->set_phy_power(0); | ||
470 | 407 | ||
471 | otg_put_transceiver(musb->xceiv); | 408 | otg_put_transceiver(musb->xceiv); |
472 | usb_nop_xceiv_unregister(); | 409 | usb_nop_xceiv_unregister(); |
473 | 410 | ||
474 | clk_disable(musb->clock); | ||
475 | |||
476 | clk_disable(musb->phy_clock); | ||
477 | clk_put(musb->phy_clock); | ||
478 | |||
479 | return 0; | 411 | return 0; |
480 | } | 412 | } |
481 | 413 | ||
482 | #ifdef CONFIG_PM | ||
483 | void musb_platform_save_context(struct musb *musb, | ||
484 | struct musb_context_registers *musb_context) | ||
485 | { | ||
486 | phy_off(); | ||
487 | } | ||
488 | |||
489 | void musb_platform_restore_context(struct musb *musb, | ||
490 | struct musb_context_registers *musb_context) | ||
491 | { | ||
492 | phy_on(); | ||
493 | } | ||
494 | #endif | ||
495 | |||
496 | /* AM35x supports only 32bit read operation */ | 414 | /* AM35x supports only 32bit read operation */ |
497 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | 415 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) |
498 | { | 416 | { |
@@ -522,3 +440,215 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | |||
522 | memcpy(dst, &val, len); | 440 | memcpy(dst, &val, len); |
523 | } | 441 | } |
524 | } | 442 | } |
443 | |||
444 | static const struct musb_platform_ops am35x_ops = { | ||
445 | .init = am35x_musb_init, | ||
446 | .exit = am35x_musb_exit, | ||
447 | |||
448 | .enable = am35x_musb_enable, | ||
449 | .disable = am35x_musb_disable, | ||
450 | |||
451 | .set_mode = am35x_musb_set_mode, | ||
452 | .try_idle = am35x_musb_try_idle, | ||
453 | |||
454 | .set_vbus = am35x_musb_set_vbus, | ||
455 | }; | ||
456 | |||
457 | static u64 am35x_dmamask = DMA_BIT_MASK(32); | ||
458 | |||
459 | static int __init am35x_probe(struct platform_device *pdev) | ||
460 | { | ||
461 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | ||
462 | struct platform_device *musb; | ||
463 | struct am35x_glue *glue; | ||
464 | |||
465 | struct clk *phy_clk; | ||
466 | struct clk *clk; | ||
467 | |||
468 | int ret = -ENOMEM; | ||
469 | |||
470 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
471 | if (!glue) { | ||
472 | dev_err(&pdev->dev, "failed to allocate glue context\n"); | ||
473 | goto err0; | ||
474 | } | ||
475 | |||
476 | musb = platform_device_alloc("musb-hdrc", -1); | ||
477 | if (!musb) { | ||
478 | dev_err(&pdev->dev, "failed to allocate musb device\n"); | ||
479 | goto err1; | ||
480 | } | ||
481 | |||
482 | phy_clk = clk_get(&pdev->dev, "fck"); | ||
483 | if (IS_ERR(phy_clk)) { | ||
484 | dev_err(&pdev->dev, "failed to get PHY clock\n"); | ||
485 | ret = PTR_ERR(phy_clk); | ||
486 | goto err2; | ||
487 | } | ||
488 | |||
489 | clk = clk_get(&pdev->dev, "ick"); | ||
490 | if (IS_ERR(clk)) { | ||
491 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
492 | ret = PTR_ERR(clk); | ||
493 | goto err3; | ||
494 | } | ||
495 | |||
496 | ret = clk_enable(phy_clk); | ||
497 | if (ret) { | ||
498 | dev_err(&pdev->dev, "failed to enable PHY clock\n"); | ||
499 | goto err4; | ||
500 | } | ||
501 | |||
502 | ret = clk_enable(clk); | ||
503 | if (ret) { | ||
504 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
505 | goto err5; | ||
506 | } | ||
507 | |||
508 | musb->dev.parent = &pdev->dev; | ||
509 | musb->dev.dma_mask = &am35x_dmamask; | ||
510 | musb->dev.coherent_dma_mask = am35x_dmamask; | ||
511 | |||
512 | glue->dev = &pdev->dev; | ||
513 | glue->musb = musb; | ||
514 | glue->phy_clk = phy_clk; | ||
515 | glue->clk = clk; | ||
516 | |||
517 | pdata->platform_ops = &am35x_ops; | ||
518 | |||
519 | platform_set_drvdata(pdev, glue); | ||
520 | |||
521 | ret = platform_device_add_resources(musb, pdev->resource, | ||
522 | pdev->num_resources); | ||
523 | if (ret) { | ||
524 | dev_err(&pdev->dev, "failed to add resources\n"); | ||
525 | goto err6; | ||
526 | } | ||
527 | |||
528 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | ||
529 | if (ret) { | ||
530 | dev_err(&pdev->dev, "failed to add platform_data\n"); | ||
531 | goto err6; | ||
532 | } | ||
533 | |||
534 | ret = platform_device_add(musb); | ||
535 | if (ret) { | ||
536 | dev_err(&pdev->dev, "failed to register musb device\n"); | ||
537 | goto err6; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | |||
542 | err6: | ||
543 | clk_disable(clk); | ||
544 | |||
545 | err5: | ||
546 | clk_disable(phy_clk); | ||
547 | |||
548 | err4: | ||
549 | clk_put(clk); | ||
550 | |||
551 | err3: | ||
552 | clk_put(phy_clk); | ||
553 | |||
554 | err2: | ||
555 | platform_device_put(musb); | ||
556 | |||
557 | err1: | ||
558 | kfree(glue); | ||
559 | |||
560 | err0: | ||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int __exit am35x_remove(struct platform_device *pdev) | ||
565 | { | ||
566 | struct am35x_glue *glue = platform_get_drvdata(pdev); | ||
567 | |||
568 | platform_device_del(glue->musb); | ||
569 | platform_device_put(glue->musb); | ||
570 | clk_disable(glue->clk); | ||
571 | clk_disable(glue->phy_clk); | ||
572 | clk_put(glue->clk); | ||
573 | clk_put(glue->phy_clk); | ||
574 | kfree(glue); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | #ifdef CONFIG_PM | ||
580 | static int am35x_suspend(struct device *dev) | ||
581 | { | ||
582 | struct am35x_glue *glue = dev_get_drvdata(dev); | ||
583 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
584 | struct omap_musb_board_data *data = plat->board_data; | ||
585 | |||
586 | /* Shutdown the on-chip PHY and its PLL. */ | ||
587 | if (data->set_phy_power) | ||
588 | data->set_phy_power(0); | ||
589 | |||
590 | clk_disable(glue->phy_clk); | ||
591 | clk_disable(glue->clk); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int am35x_resume(struct device *dev) | ||
597 | { | ||
598 | struct am35x_glue *glue = dev_get_drvdata(dev); | ||
599 | struct musb_hdrc_platform_data *plat = dev->platform_data; | ||
600 | struct omap_musb_board_data *data = plat->board_data; | ||
601 | int ret; | ||
602 | |||
603 | /* Start the on-chip PHY and its PLL. */ | ||
604 | if (data->set_phy_power) | ||
605 | data->set_phy_power(1); | ||
606 | |||
607 | ret = clk_enable(glue->phy_clk); | ||
608 | if (ret) { | ||
609 | dev_err(dev, "failed to enable PHY clock\n"); | ||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | ret = clk_enable(glue->clk); | ||
614 | if (ret) { | ||
615 | dev_err(dev, "failed to enable clock\n"); | ||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static struct dev_pm_ops am35x_pm_ops = { | ||
623 | .suspend = am35x_suspend, | ||
624 | .resume = am35x_resume, | ||
625 | }; | ||
626 | |||
627 | #define DEV_PM_OPS &am35x_pm_ops | ||
628 | #else | ||
629 | #define DEV_PM_OPS NULL | ||
630 | #endif | ||
631 | |||
632 | static struct platform_driver am35x_driver = { | ||
633 | .remove = __exit_p(am35x_remove), | ||
634 | .driver = { | ||
635 | .name = "musb-am35x", | ||
636 | .pm = DEV_PM_OPS, | ||
637 | }, | ||
638 | }; | ||
639 | |||
640 | MODULE_DESCRIPTION("AM35x MUSB Glue Layer"); | ||
641 | MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); | ||
642 | MODULE_LICENSE("GPL v2"); | ||
643 | |||
644 | static int __init am35x_init(void) | ||
645 | { | ||
646 | return platform_driver_probe(&am35x_driver, am35x_probe); | ||
647 | } | ||
648 | subsys_initcall(am35x_init); | ||
649 | |||
650 | static void __exit am35x_exit(void) | ||
651 | { | ||
652 | platform_driver_unregister(&am35x_driver); | ||
653 | } | ||
654 | module_exit(am35x_exit); | ||