|
@@ -2882,7 +2882,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
{
|
|
|
struct dma_pl330_platdata *pdat;
|
|
|
struct dma_pl330_dmac *pdmac;
|
|
|
- struct dma_pl330_chan *pch;
|
|
|
+ struct dma_pl330_chan *pch, *_p;
|
|
|
struct pl330_info *pi;
|
|
|
struct dma_device *pd;
|
|
|
struct resource *res;
|
|
@@ -2984,7 +2984,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
ret = dma_async_device_register(pd);
|
|
|
if (ret) {
|
|
|
dev_err(&adev->dev, "unable to register DMAC\n");
|
|
|
- goto probe_err2;
|
|
|
+ goto probe_err3;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (adev->dev.of_node) {
|
|
|
+ ret = of_dma_controller_register(adev->dev.of_node,
|
|
|
+ of_dma_pl330_xlate, pdmac);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&adev->dev,
|
|
|
+ "unable to register DMA to the generic DT DMA helpers\n");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
dev_info(&adev->dev,
|
|
@@ -2995,16 +3004,21 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
|
|
|
pi->pcfg.num_peri, pi->pcfg.num_events);
|
|
|
|
|
|
- ret = of_dma_controller_register(adev->dev.of_node,
|
|
|
- of_dma_pl330_xlate, pdmac);
|
|
|
- if (ret) {
|
|
|
- dev_err(&adev->dev,
|
|
|
- "unable to register DMA to the generic DT DMA helpers\n");
|
|
|
- goto probe_err2;
|
|
|
- }
|
|
|
-
|
|
|
return 0;
|
|
|
+probe_err3:
|
|
|
+ amba_set_drvdata(adev, NULL);
|
|
|
|
|
|
+ /* Idle the DMAC */
|
|
|
+ list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
|
|
|
+ chan.device_node) {
|
|
|
+
|
|
|
+ /* Remove the channel */
|
|
|
+ list_del(&pch->chan.device_node);
|
|
|
+
|
|
|
+ /* Flush the channel */
|
|
|
+ pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0);
|
|
|
+ pl330_free_chan_resources(&pch->chan);
|
|
|
+ }
|
|
|
probe_err2:
|
|
|
pl330_del(pi);
|
|
|
probe_err1:
|
|
@@ -3023,8 +3037,10 @@ static int pl330_remove(struct amba_device *adev)
|
|
|
if (!pdmac)
|
|
|
return 0;
|
|
|
|
|
|
- of_dma_controller_free(adev->dev.of_node);
|
|
|
+ if (adev->dev.of_node)
|
|
|
+ of_dma_controller_free(adev->dev.of_node);
|
|
|
|
|
|
+ dma_async_device_unregister(&pdmac->ddma);
|
|
|
amba_set_drvdata(adev, NULL);
|
|
|
|
|
|
/* Idle the DMAC */
|