MODULE_DEVICE_TABLE(of, stm32_match);
 #endif
 
+static void stm32_usart_of_dma_rx_remove(struct stm32_port *stm32port,
+                                        struct platform_device *pdev)
+{
+       if (stm32port->rx_buf)
+               dma_free_coherent(&pdev->dev, RX_BUF_L, stm32port->rx_buf,
+                                 stm32port->rx_dma_buf);
+}
+
 static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
                                       struct platform_device *pdev)
 {
        if (uart_console(port))
                return -ENODEV;
 
-       /* Request DMA RX channel */
-       stm32port->rx_ch = dma_request_slave_channel(dev, "rx");
-       if (!stm32port->rx_ch) {
-               dev_info(dev, "rx dma alloc failed\n");
-               return -ENODEV;
-       }
        stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L,
                                               &stm32port->rx_dma_buf,
                                               GFP_KERNEL);
-       if (!stm32port->rx_buf) {
-               ret = -ENOMEM;
-               goto alloc_err;
-       }
+       if (!stm32port->rx_buf)
+               return -ENOMEM;
 
        /* Configure DMA channel */
        memset(&config, 0, sizeof(config));
        ret = dmaengine_slave_config(stm32port->rx_ch, &config);
        if (ret < 0) {
                dev_err(dev, "rx dma channel config failed\n");
-               ret = -ENODEV;
-               goto config_err;
+               stm32_usart_of_dma_rx_remove(stm32port, pdev);
+               return ret;
        }
 
        /* Prepare a DMA cyclic transaction */
                                         DMA_PREP_INTERRUPT);
        if (!desc) {
                dev_err(dev, "rx dma prep cyclic failed\n");
-               ret = -ENODEV;
-               goto config_err;
+               stm32_usart_of_dma_rx_remove(stm32port, pdev);
+               return -ENODEV;
        }
 
        /* No callback as dma buffer is drained on usart interrupt */
        ret = dma_submit_error(dmaengine_submit(desc));
        if (ret) {
                dmaengine_terminate_sync(stm32port->rx_ch);
-               goto config_err;
+               stm32_usart_of_dma_rx_remove(stm32port, pdev);
+               return ret;
        }
 
        /* Issue pending DMA requests */
        dma_async_issue_pending(stm32port->rx_ch);
 
        return 0;
+}
 
-config_err:
-       dma_free_coherent(&pdev->dev,
-                         RX_BUF_L, stm32port->rx_buf,
-                         stm32port->rx_dma_buf);
-
-alloc_err:
-       dma_release_channel(stm32port->rx_ch);
-       stm32port->rx_ch = NULL;
-
-       return ret;
+static void stm32_usart_of_dma_tx_remove(struct stm32_port *stm32port,
+                                        struct platform_device *pdev)
+{
+       if (stm32port->tx_buf)
+               dma_free_coherent(&pdev->dev, TX_BUF_L, stm32port->tx_buf,
+                                 stm32port->tx_dma_buf);
 }
 
 static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port,
 
        stm32port->tx_dma_busy = false;
 
-       /* Request DMA TX channel */
-       stm32port->tx_ch = dma_request_slave_channel(dev, "tx");
-       if (!stm32port->tx_ch) {
-               dev_info(dev, "tx dma alloc failed\n");
-               return -ENODEV;
-       }
        stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L,
                                               &stm32port->tx_dma_buf,
                                               GFP_KERNEL);
-       if (!stm32port->tx_buf) {
-               ret = -ENOMEM;
-               goto alloc_err;
-       }
+       if (!stm32port->tx_buf)
+               return -ENOMEM;
 
        /* Configure DMA channel */
        memset(&config, 0, sizeof(config));
        ret = dmaengine_slave_config(stm32port->tx_ch, &config);
        if (ret < 0) {
                dev_err(dev, "tx dma channel config failed\n");
-               ret = -ENODEV;
-               goto config_err;
+               stm32_usart_of_dma_tx_remove(stm32port, pdev);
+               return ret;
        }
 
        return 0;
-
-config_err:
-       dma_free_coherent(&pdev->dev,
-                         TX_BUF_L, stm32port->tx_buf,
-                         stm32port->tx_dma_buf);
-
-alloc_err:
-       dma_release_channel(stm32port->tx_ch);
-       stm32port->tx_ch = NULL;
-
-       return ret;
 }
 
 static int stm32_usart_serial_probe(struct platform_device *pdev)
                device_set_wakeup_capable(&pdev->dev, true);
                ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
                if (ret)
-                       goto err_nowup;
+                       goto err_deinit_port;
        }
 
-       ret = stm32_usart_of_dma_rx_probe(stm32port, pdev);
-       if (ret)
-               dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n");
+       stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx");
+       if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto err_wakeirq;
+       }
+       /* Fall back in interrupt mode for any non-deferral error */
+       if (IS_ERR(stm32port->rx_ch))
+               stm32port->rx_ch = NULL;
+
+       stm32port->tx_ch = dma_request_chan(&pdev->dev, "tx");
+       if (PTR_ERR(stm32port->tx_ch) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto err_dma_rx;
+       }
+       /* Fall back in interrupt mode for any non-deferral error */
+       if (IS_ERR(stm32port->tx_ch))
+               stm32port->tx_ch = NULL;
 
-       ret = stm32_usart_of_dma_tx_probe(stm32port, pdev);
-       if (ret)
-               dev_info(&pdev->dev, "interrupt mode used for tx (no dma)\n");
+       if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) {
+               /* Fall back in interrupt mode */
+               dma_release_channel(stm32port->rx_ch);
+               stm32port->rx_ch = NULL;
+       }
+
+       if (stm32port->tx_ch && stm32_usart_of_dma_tx_probe(stm32port, pdev)) {
+               /* Fall back in interrupt mode */
+               dma_release_channel(stm32port->tx_ch);
+               stm32port->tx_ch = NULL;
+       }
+
+       if (!stm32port->rx_ch)
+               dev_info(&pdev->dev, "interrupt mode for rx (no dma)\n");
+       if (!stm32port->tx_ch)
+               dev_info(&pdev->dev, "interrupt mode for tx (no dma)\n");
 
        platform_set_drvdata(pdev, &stm32port->port);
 
        pm_runtime_set_suspended(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
 
-       if (stm32port->rx_ch) {
-               dmaengine_terminate_async(stm32port->rx_ch);
-               dma_release_channel(stm32port->rx_ch);
-       }
-
-       if (stm32port->rx_dma_buf)
-               dma_free_coherent(&pdev->dev,
-                                 RX_BUF_L, stm32port->rx_buf,
-                                 stm32port->rx_dma_buf);
-
        if (stm32port->tx_ch) {
-               dmaengine_terminate_async(stm32port->tx_ch);
+               stm32_usart_of_dma_tx_remove(stm32port, pdev);
                dma_release_channel(stm32port->tx_ch);
        }
 
-       if (stm32port->tx_dma_buf)
-               dma_free_coherent(&pdev->dev,
-                                 TX_BUF_L, stm32port->tx_buf,
-                                 stm32port->tx_dma_buf);
+       if (stm32port->rx_ch)
+               stm32_usart_of_dma_rx_remove(stm32port, pdev);
 
+err_dma_rx:
+       if (stm32port->rx_ch)
+               dma_release_channel(stm32port->rx_ch);
+
+err_wakeirq:
        if (stm32port->wakeup_src)
                dev_pm_clear_wake_irq(&pdev->dev);
 
-err_nowup:
+err_deinit_port:
        if (stm32port->wakeup_src)
                device_set_wakeup_capable(&pdev->dev, false);
 
 
        stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
 
+       if (stm32_port->tx_ch) {
+               dmaengine_terminate_async(stm32_port->tx_ch);
+               stm32_usart_of_dma_tx_remove(stm32_port, pdev);
+               dma_release_channel(stm32_port->tx_ch);
+       }
+
        if (stm32_port->rx_ch) {
                dmaengine_terminate_async(stm32_port->rx_ch);
+               stm32_usart_of_dma_rx_remove(stm32_port, pdev);
                dma_release_channel(stm32_port->rx_ch);
        }
 
-       if (stm32_port->rx_dma_buf)
-               dma_free_coherent(&pdev->dev,
-                                 RX_BUF_L, stm32_port->rx_buf,
-                                 stm32_port->rx_dma_buf);
-
        stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
 
-       if (stm32_port->tx_ch) {
-               dmaengine_terminate_async(stm32_port->tx_ch);
-               dma_release_channel(stm32_port->tx_ch);
-       }
-
-       if (stm32_port->tx_dma_buf)
-               dma_free_coherent(&pdev->dev,
-                                 TX_BUF_L, stm32_port->tx_buf,
-                                 stm32_port->tx_dma_buf);
-
        if (stm32_port->wakeup_src) {
                dev_pm_clear_wake_irq(&pdev->dev);
                device_init_wakeup(&pdev->dev, false);