diff options
Diffstat (limited to 'drivers/iommu/rockchip-iommu.c')
-rw-r--r-- | drivers/iommu/rockchip-iommu.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 9d991c2d8767..6a3719e118da 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1209,6 +1209,23 @@ static int rk_iommu_remove(struct platform_device *pdev) return 0; } +static void rk_iommu_shutdown(struct platform_device *pdev) +{ + struct rk_iommu *iommu = platform_get_drvdata(pdev); + + /* + * Be careful not to try to shutdown an otherwise unused + * IOMMU, as it is likely not to be clocked, and accessing it + * would just block. An IOMMU without a domain is likely to be + * unused, so let's use this as a (weak) guard. + */ + if (iommu && iommu->domain) { + rk_iommu_enable_stall(iommu); + rk_iommu_disable_paging(iommu); + rk_iommu_force_reset(iommu); + } +} + static const struct of_device_id rk_iommu_dt_ids[] = { { .compatible = "rockchip,iommu" }, { /* sentinel */ } @@ -1218,6 +1235,7 @@ MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids); static struct platform_driver rk_iommu_driver = { .probe = rk_iommu_probe, .remove = rk_iommu_remove, + .shutdown = rk_iommu_shutdown, .driver = { .name = "rk_iommu", .of_match_table = rk_iommu_dt_ids, |