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 {   * Per SMMU device - IOMMU device   */  struct smmu_device { -	void __iomem	*regs[NUM_SMMU_REG_BANKS]; +	void __iomem	*regbase;	/* register offset base */ +	void __iomem	**regs;		/* register block start address array */ +	void __iomem	**rege;		/* register block end address array */ +	int		nregs;		/* number of register blocks */ +  	unsigned long	iovmm_base;	/* remappable base address */  	unsigned long	page_count;	/* total remappable size */  	spinlock_t	lock; @@ -325,35 +329,33 @@ static struct smmu_device *smmu_handle; /* unique for a system */   */  static inline u32 smmu_read(struct smmu_device *smmu, size_t offs)  { -	BUG_ON(offs < 0x10); -	if (offs < 0x3c) -		return readl(smmu->regs[0] + offs - 0x10); -	BUG_ON(offs < 0x1f0); -	if (offs < 0x200) -		return readl(smmu->regs[1] + offs - 0x1f0); -	BUG_ON(offs < 0x228); -	if (offs < 0x284) -		return readl(smmu->regs[2] + offs - 0x228); +	int i; + +	for (i = 0; i < smmu->nregs; i++) { +		void __iomem *addr = smmu->regbase + offs; + +		BUG_ON(addr < smmu->regs[i]); +		if (addr <= smmu->rege[i]) +			return readl(addr); +	} +  	BUG();  }  static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)  { -	BUG_ON(offs < 0x10); -	if (offs < 0x3c) { -		writel(val, smmu->regs[0] + offs - 0x10); -		return; -	} -	BUG_ON(offs < 0x1f0); -	if (offs < 0x200) { -		writel(val, smmu->regs[1] + offs - 0x1f0); -		return; -	} -	BUG_ON(offs < 0x228); -	if (offs < 0x284) { -		writel(val, smmu->regs[2] + offs - 0x228); -		return; +	int i; + +	for (i = 0; i < smmu->nregs; i++) { +		void __iomem *addr = smmu->regbase + offs; + +		BUG_ON(addr < smmu->regs[i]); +		if (addr <= smmu->rege[i]) { +			writel(val, addr); +			return; +		}  	} +  	BUG();  } @@ -1170,7 +1172,13 @@ static int tegra_smmu_probe(struct platform_device *pdev)  		return -ENOMEM;  	} -	for (i = 0; i < ARRAY_SIZE(smmu->regs); i++) { +	smmu->nregs = pdev->num_resources; +	smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs), +				  GFP_KERNEL); +	smmu->rege = smmu->regs + smmu->nregs; +	if (!smmu->regs) +		return -ENOMEM; +	for (i = 0; i < smmu->nregs; i++) {  		struct resource *res;  		res = platform_get_resource(pdev, IORESOURCE_MEM, i); @@ -1179,7 +1187,10 @@ static int tegra_smmu_probe(struct platform_device *pdev)  		smmu->regs[i] = devm_request_and_ioremap(&pdev->dev, res);  		if (!smmu->regs[i])  			return -EBUSY; +		smmu->rege[i] = smmu->regs[i] + resource_size(res) - 1;  	} +	/* Same as "mc" 1st regiter block start address */ +	smmu->regbase = (void __iomem *)((u32)smmu->regs[0] & ~PAGE_MASK);  	err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size);  	if (err) | 
