usb: musb: cppi41: allow to defer probing if DMA isn't yet available
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Wed, 16 Oct 2013 10:50:08 +0000 (12:50 +0200)
committerFelipe Balbi <balbi@ti.com>
Thu, 17 Oct 2013 16:32:08 +0000 (11:32 -0500)
If everything (musb, cppi41, phy) is built-in then musb will start
without the dma engine printing only

|musb-hdrc musb-hdrc.0.auto: Falied to request rx1.

The reason for this is that the musb device structs are created & probed
before those of the cppi41 device. So the cppi41 device is probed too
late.
As a workaround for this allow the musb_cppi41 part to defer the probe
if everything is fine except for the missing DMA controller. In case of
another error we continue.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c

index 7fd213785d52489850e119a4b65131ca95382268..4db987f07f67fe0241c579b7daa39075e452e9ec 100644 (file)
@@ -1838,8 +1838,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        pm_runtime_get_sync(musb->controller);
 
-       if (use_dma && dev->dma_mask)
+       if (use_dma && dev->dma_mask) {
                musb->dma_controller = dma_controller_create(musb, musb->mregs);
+               if (IS_ERR(musb->dma_controller)) {
+                       status = PTR_ERR(musb->dma_controller);
+                       goto fail2_5;
+               }
+       }
 
        /* be sure interrupts are disabled before connecting ISR */
        musb_platform_disable(musb);
@@ -1932,6 +1937,7 @@ fail4:
 fail3:
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
+fail2_5:
        pm_runtime_put_sync(musb->controller);
 
 fail2:
index ae959746f77f04331a1d8dde9d1da57d90af24b8..ff9d6de2b7465c949d54ae4801108a3800f4be3f 100644 (file)
@@ -484,6 +484,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                if (ret)
                        goto err;
 
+               ret = -EINVAL;
                if (port > MUSB_DMA_NUM_CHANNELS || !port)
                        goto err;
                if (is_tx)
@@ -503,6 +504,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                dc = dma_request_slave_channel(dev, str);
                if (!dc) {
                        dev_err(dev, "Falied to request %s.\n", str);
+                       ret = -EPROBE_DEFER;
                        goto err;
                }
                cppi41_channel->dc = dc;
@@ -510,7 +512,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
        return 0;
 err:
        cppi41_release_all_dma_chans(controller);
-       return -EINVAL;
+       return ret;
 }
 
 void dma_controller_destroy(struct dma_controller *c)
@@ -526,7 +528,7 @@ struct dma_controller *dma_controller_create(struct musb *musb,
                                        void __iomem *base)
 {
        struct cppi41_dma_controller *controller;
-       int ret;
+       int ret = 0;
 
        if (!musb->controller->of_node) {
                dev_err(musb->controller, "Need DT for the DMA engine.\n");
@@ -553,5 +555,7 @@ struct dma_controller *dma_controller_create(struct musb *musb,
 plat_get_fail:
        kfree(controller);
 kzalloc_fail:
+       if (ret == -EPROBE_DEFER)
+               return ERR_PTR(ret);
        return NULL;
 }