diff options
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/pl330.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 6e6837214210..5208c6a80a39 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -29,6 +29,7 @@ #include <linux/err.h> #include <linux/pm_runtime.h> #include <linux/bug.h> +#include <linux/reset.h> #include "dmaengine.h" #define PL330_MAX_CHAN 8 @@ -500,6 +501,9 @@ struct pl330_dmac { unsigned int num_peripherals; struct dma_pl330_chan *peripherals; /* keep at end */ int quirks; + + struct reset_control *rstc; + struct reset_control *rstc_ocp; }; static struct pl330_of_quirks { @@ -3028,6 +3032,32 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) amba_set_drvdata(adev, pl330); + pl330->rstc = devm_reset_control_get_optional(&adev->dev, "dma"); + if (IS_ERR(pl330->rstc)) { + if (PTR_ERR(pl330->rstc) != -EPROBE_DEFER) + dev_err(&adev->dev, "Failed to get reset!\n"); + return PTR_ERR(pl330->rstc); + } else { + ret = reset_control_deassert(pl330->rstc); + if (ret) { + dev_err(&adev->dev, "Couldn't deassert the device from reset!\n"); + return ret; + } + } + + pl330->rstc_ocp = devm_reset_control_get_optional(&adev->dev, "dma-ocp"); + if (IS_ERR(pl330->rstc_ocp)) { + if (PTR_ERR(pl330->rstc_ocp) != -EPROBE_DEFER) + dev_err(&adev->dev, "Failed to get OCP reset!\n"); + return PTR_ERR(pl330->rstc_ocp); + } else { + ret = reset_control_deassert(pl330->rstc_ocp); + if (ret) { + dev_err(&adev->dev, "Couldn't deassert the device from OCP reset!\n"); + return ret; + } + } + for (i = 0; i < AMBA_NR_IRQS; i++) { irq = adev->irq[i]; if (irq) { @@ -3168,6 +3198,11 @@ probe_err3: probe_err2: pl330_del(pl330); + if (pl330->rstc_ocp) + reset_control_assert(pl330->rstc_ocp); + + if (pl330->rstc) + reset_control_assert(pl330->rstc); return ret; } @@ -3206,6 +3241,11 @@ static int pl330_remove(struct amba_device *adev) pl330_del(pl330); + if (pl330->rstc_ocp) + reset_control_assert(pl330->rstc_ocp); + + if (pl330->rstc) + reset_control_assert(pl330->rstc); return 0; } |