iommu: rockchip: disable fetch dte time limit

Master fetch data and cpu update page table may work in parallel, may
have the following procedure:

	master                  cpu
	fetch dte               update page tabl
	        |                       |
	(make dte invalid)  <-  zap iotlb entry
	        |                       |
	fetch dte again
	(make dte invalid)  <-  zap iotlb entry
	        |                       |
	fetch dte again
	(make dte invalid)  <-  zap iotlb entry
	        |                       |
	fetch dte again
	(make iommu block)  <-  zap iotlb entry

New iommu version has the above bug, if fetch dte consecutively four
times, then it will be blocked. Fortunately, we can set bit 31 of
register MMU_AUTO_GATING to 1 to make it work as old version which does
not have this issue.

This issue only appears on RV1126 so far, so make a workaround dedicated
to "rockchip,rv1126" machine type.

Change-Id: I808bf87898e2dfdd8ada5666234e4c2c3237ffde
Signed-off-by: Simon Xue <xxm@rock-chips.com>
This commit is contained in:
Simon Xue
2021-04-06 19:07:35 +08:00
committed by Tao Huang
parent bdbe1596d1
commit 7f8158fb41

View File

@@ -75,6 +75,8 @@
#define SPAGE_ORDER 12
#define SPAGE_SIZE (1 << SPAGE_ORDER)
#define DISABLE_FETCH_DTE_TIME_LIMIT BIT(31)
/*
* Support mapping any size that fits in one page table:
* 4 KiB to 4 MiB
@@ -134,6 +136,7 @@ struct rk_iommu {
bool reset_disabled;
bool skip_read; /* rk3126/rk3128 can't read vop iommu registers */
bool dlr_disable; /* avoid access iommu when runtime ops called */
bool fetch_dte_time_limit; /* if have fetch dte time limit */
struct iommu_device iommu;
struct list_head node; /* entry in rk_iommu_domain.iommus */
struct iommu_domain *domain; /* domain to which iommu is attached */
@@ -1233,6 +1236,7 @@ static int rk_iommu_enable(struct rk_iommu *iommu)
struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
int ret, i;
u32 dt_v2;
u32 auto_gate;
ret = clk_bulk_enable(iommu->num_clocks, iommu->clocks);
if (ret)
@@ -1257,6 +1261,12 @@ static int rk_iommu_enable(struct rk_iommu *iommu)
}
rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
if (iommu->fetch_dte_time_limit) {
auto_gate = rk_iommu_read(iommu->bases[i], RK_MMU_AUTO_GATING);
auto_gate |= DISABLE_FETCH_DTE_TIME_LIMIT;
rk_iommu_write(iommu->bases[i], RK_MMU_AUTO_GATING, auto_gate);
}
}
ret = rk_iommu_enable_paging(iommu);
@@ -1644,6 +1654,10 @@ static int rk_iommu_probe(struct platform_device *pdev)
iommu->dlr_disable = device_property_read_bool(dev,
"rockchip,disable-device-link-resume");
if (of_machine_is_compatible("rockchip,rv1126") ||
of_machine_is_compatible("rockchip,rv1109"))
iommu->fetch_dte_time_limit = true;
iommu->num_clocks = ARRAY_SIZE(rk_iommu_clocks);
iommu->clocks = devm_kcalloc(iommu->dev, iommu->num_clocks,
sizeof(*iommu->clocks), GFP_KERNEL);