From 539e70084bc2d9e4848cf7c3920a2145a44a67bb Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Wed, 25 Oct 2017 17:10:04 +0800 Subject: [PATCH] iommu/rockchip: skip read vop iommu registers on rk3128 and rk3126 RK3128 and RK3126 failed to read vop iommu register, it is SoC bug. Add this patch as a workaround for this bug, make SoC work as normal Change-Id: I44d4ef7f6e15f85a466563b0b3e8e091db23fba0 Signed-off-by: Simon Xue --- drivers/iommu/rockchip-iommu.c | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 9ac9829d00a9..5c42b2a08aaf 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -96,6 +96,7 @@ struct rk_iommu { int *irq; int num_irq; bool reset_disabled; /* isp iommu reset operation would failed */ + bool skip_read; /* rk3126/rk3128 can't read vop iommu registers */ struct list_head node; /* entry in rk_iommu_domain.iommus */ struct iommu_domain *domain; /* domain to which iommu is attached */ struct clk *aclk; /* aclock belong to master */ @@ -371,6 +372,9 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu) { int ret, i; + if (iommu->skip_read) + goto read_wa; + if (rk_iommu_is_stall_active(iommu)) return 0; @@ -378,7 +382,10 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu) if (!rk_iommu_is_paging_enabled(iommu)) return 0; +read_wa: rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL); + if (iommu->skip_read) + return 0; ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1); if (ret) @@ -393,10 +400,16 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu) { int ret, i; + if (iommu->skip_read) + goto read_wa; + if (!rk_iommu_is_stall_active(iommu)) return 0; +read_wa: rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_STALL); + if (iommu->skip_read) + return 0; ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1); if (ret) @@ -411,10 +424,16 @@ static int rk_iommu_enable_paging(struct rk_iommu *iommu) { int ret, i; + if (iommu->skip_read) + goto read_wa; + if (rk_iommu_is_paging_enabled(iommu)) return 0; +read_wa: rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_PAGING); + if (iommu->skip_read) + return 0; ret = rk_wait_for(rk_iommu_is_paging_enabled(iommu), 1); if (ret) @@ -429,10 +448,16 @@ static int rk_iommu_disable_paging(struct rk_iommu *iommu) { int ret, i; + if (iommu->skip_read) + goto read_wa; + if (!rk_iommu_is_paging_enabled(iommu)) return 0; +read_wa: rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_PAGING); + if (iommu->skip_read) + return 0; ret = rk_wait_for(!rk_iommu_is_paging_enabled(iommu), 1); if (ret) @@ -452,6 +477,8 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu) if (iommu->reset_disabled) return 0; + if (iommu->skip_read) + goto read_wa; /* * Check if register DTE_ADDR is working by writing DTE_ADDR_DUMMY * and verifying that upper 5 nybbles are read back. @@ -466,7 +493,10 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu) } } +read_wa: rk_iommu_command(iommu, RK_MMU_CMD_FORCE_RESET); + if (iommu->skip_read) + return 0; for (i = 0; i < iommu->num_mmu; i++) { ret = rk_wait_for(rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0x00000000, @@ -865,6 +895,9 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, iommu->domain = domain; + if (iommu->skip_read) + goto skip_request_irq; + for (i = 0; i < iommu->num_irq; i++) { ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq, IRQF_SHARED, dev_name(dev), iommu); @@ -872,6 +905,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, return ret; } +skip_request_irq: for (i = 0; i < iommu->num_mmu; i++) { rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, rk_domain->dt_dma); @@ -919,10 +953,14 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, } rk_iommu_disable_stall(iommu); + if (iommu->skip_read) + goto read_wa; + for (i = 0; i < iommu->num_irq; i++) { devm_free_irq(iommu->dev, iommu->irq[i], iommu); } +read_wa: iommu->domain = NULL; rk_iommu_power_off(iommu); @@ -1210,6 +1248,13 @@ static int rk_iommu_probe(struct platform_device *pdev) iommu->reset_disabled = device_property_read_bool(dev, "rk_iommu,disable_reset_quirk"); + /* Follow upstream */ + iommu->reset_disabled |= device_property_read_bool(dev, + "rockchip,disable-mmu-reset"); + + iommu->skip_read = device_property_read_bool(dev, + "rockchip,skip-mmu-read"); + iommu->aclk = devm_clk_get(dev, "aclk"); if (IS_ERR(iommu->aclk)) { dev_info(dev, "can't get aclk\n");