aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/tegra-smmu.c61
1 files changed, 36 insertions, 25 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 87a719f4adfb..2fecbe7fd7fd 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -293,7 +293,11 @@ struct smmu_debugfs_info {
293 * Per SMMU device - IOMMU device 293 * Per SMMU device - IOMMU device
294 */ 294 */
295struct smmu_device { 295struct smmu_device {
296 void __iomem *regs[NUM_SMMU_REG_BANKS]; 296 void __iomem *regbase; /* register offset base */
297 void __iomem **regs; /* register block start address array */
298 void __iomem **rege; /* register block end address array */
299 int nregs; /* number of register blocks */
300
297 unsigned long iovmm_base; /* remappable base address */ 301 unsigned long iovmm_base; /* remappable base address */
298 unsigned long page_count; /* total remappable size */ 302 unsigned long page_count; /* total remappable size */
299 spinlock_t lock; 303 spinlock_t lock;
@@ -325,35 +329,33 @@ static struct smmu_device *smmu_handle; /* unique for a system */
325 */ 329 */
326static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) 330static inline u32 smmu_read(struct smmu_device *smmu, size_t offs)
327{ 331{
328 BUG_ON(offs < 0x10); 332 int i;
329 if (offs < 0x3c) 333
330 return readl(smmu->regs[0] + offs - 0x10); 334 for (i = 0; i < smmu->nregs; i++) {
331 BUG_ON(offs < 0x1f0); 335 void __iomem *addr = smmu->regbase + offs;
332 if (offs < 0x200) 336
333 return readl(smmu->regs[1] + offs - 0x1f0); 337 BUG_ON(addr < smmu->regs[i]);
334 BUG_ON(offs < 0x228); 338 if (addr <= smmu->rege[i])
335 if (offs < 0x284) 339 return readl(addr);
336 return readl(smmu->regs[2] + offs - 0x228); 340 }
341
337 BUG(); 342 BUG();
338} 343}
339 344
340static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) 345static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
341{ 346{
342 BUG_ON(offs < 0x10); 347 int i;
343 if (offs < 0x3c) { 348
344 writel(val, smmu->regs[0] + offs - 0x10); 349 for (i = 0; i < smmu->nregs; i++) {
345 return; 350 void __iomem *addr = smmu->regbase + offs;
346 } 351
347 BUG_ON(offs < 0x1f0); 352 BUG_ON(addr < smmu->regs[i]);
348 if (offs < 0x200) { 353 if (addr <= smmu->rege[i]) {
349 writel(val, smmu->regs[1] + offs - 0x1f0); 354 writel(val, addr);
350 return; 355 return;
351 } 356 }
352 BUG_ON(offs < 0x228);
353 if (offs < 0x284) {
354 writel(val, smmu->regs[2] + offs - 0x228);
355 return;
356 } 357 }
358
357 BUG(); 359 BUG();
358} 360}
359 361
@@ -1170,7 +1172,13 @@ static int tegra_smmu_probe(struct platform_device *pdev)
1170 return -ENOMEM; 1172 return -ENOMEM;
1171 } 1173 }
1172 1174
1173 for (i = 0; i < ARRAY_SIZE(smmu->regs); i++) { 1175 smmu->nregs = pdev->num_resources;
1176 smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs),
1177 GFP_KERNEL);
1178 smmu->rege = smmu->regs + smmu->nregs;
1179 if (!smmu->regs)
1180 return -ENOMEM;
1181 for (i = 0; i < smmu->nregs; i++) {
1174 struct resource *res; 1182 struct resource *res;
1175 1183
1176 res = platform_get_resource(pdev, IORESOURCE_MEM, i); 1184 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
@@ -1179,7 +1187,10 @@ static int tegra_smmu_probe(struct platform_device *pdev)
1179 smmu->regs[i] = devm_request_and_ioremap(&pdev->dev, res); 1187 smmu->regs[i] = devm_request_and_ioremap(&pdev->dev, res);
1180 if (!smmu->regs[i]) 1188 if (!smmu->regs[i])
1181 return -EBUSY; 1189 return -EBUSY;
1190 smmu->rege[i] = smmu->regs[i] + resource_size(res) - 1;
1182 } 1191 }
1192 /* Same as "mc" 1st regiter block start address */
1193 smmu->regbase = (void __iomem *)((u32)smmu->regs[0] & ~PAGE_MASK);
1183 1194
1184 err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size); 1195 err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size);
1185 if (err) 1196 if (err)