diff options
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 61 |
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 | */ |
295 | struct smmu_device { | 295 | struct 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 | */ |
326 | static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) | 330 | static 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 | ||
340 | static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) | 345 | static 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) |