[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1335182340-17237-1-git-send-email-hdoyu@nvidia.com>
Date: Mon, 23 Apr 2012 14:58:53 +0300
From: Hiroshi DOYU <hdoyu@...dia.com>
To: hdoyu@...dia.com
Cc: linux-tegra@...r.kernel.org, Joerg Roedel <joerg.roedel@....com>,
Thierry Reding <thierry.reding@...onic-design.de>,
linux-kernel@...r.kernel.org
Subject: [PATCH 1/3] iommu/tegra: smmu: Reserve SMMU reg regions precisely
SMMU register regions are located into 3 blocks discontiguously.
Get them and reserve each region respectively. This allows other
module to use/reserve other register regions between SMMU register
blocks.
Signed-off-by: Hiroshi DOYU <hdoyu@...dia.com>
---
drivers/iommu/tegra-smmu.c | 44 ++++++++++++++++++++++++++++++++++++--------
1 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index de9fafe..90bbf07 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -173,6 +173,8 @@
#define SMMU_ASID_DISABLE 0
#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0))
+#define NUM_SMMU_REG_BLOCKS 3
+
#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1)
#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0)
#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1)
@@ -866,7 +868,7 @@ static int tegra_smmu_resume(struct device *dev)
static int tegra_smmu_probe(struct platform_device *pdev)
{
struct smmu_device *smmu;
- struct resource *regs, *window;
+ struct resource *res[NUM_SMMU_REG_BLOCKS], *window;
struct device *dev = &pdev->dev;
int i, err = 0;
@@ -875,9 +877,25 @@ static int tegra_smmu_probe(struct platform_device *pdev)
BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- window = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!regs || !window) {
+ for (i = 0; i < ARRAY_SIZE(res); i++) {
+ res[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res[i])
+ return -ENODEV;
+
+ res[i] = devm_request_mem_region(&pdev->dev, res[i]->start,
+ resource_size(res[i]),
+ dev_name(&pdev->dev));
+ if (res[i])
+ continue;
+
+ while (--i >= 0)
+ devm_release_mem_region(&pdev->dev, res[i]->start,
+ resource_size(res[i]));
+ return -EIO;
+ }
+
+ window = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ if (!window) {
dev_err(dev, "No SMMU resources\n");
return -ENODEV;
}
@@ -892,7 +910,8 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->num_as = SMMU_NUM_ASIDS;
smmu->iovmm_base = (unsigned long)window->start;
smmu->page_count = resource_size(window) >> SMMU_PAGE_SHIFT;
- smmu->regs = devm_ioremap(dev, regs->start, resource_size(regs));
+ smmu->regs = devm_ioremap(dev, res[0]->start,
+ res[2]->end - res[0]->start + 1);
if (!smmu->regs) {
dev_err(dev, "failed to remap SMMU registers\n");
err = -ENXIO;
@@ -905,7 +924,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
smmu->asid_security = 0;
smmu->as = devm_kzalloc(dev,
- sizeof(smmu->as[0]) * smmu->num_as, GFP_KERNEL);
+ sizeof(smmu->as[0]) * smmu->num_as, GFP_KERNEL);
if (!smmu->as) {
dev_err(dev, "failed to allocate smmu_as\n");
err = -ENOMEM;
@@ -950,6 +969,9 @@ fail:
devm_kfree(dev, smmu->as);
}
devm_kfree(dev, smmu);
+ for (i = 0; i < ARRAY_SIZE(res); i++)
+ devm_release_mem_region(&pdev->dev, res[i]->start,
+ resource_size(res[i]));
return err;
}
@@ -957,12 +979,11 @@ static int tegra_smmu_remove(struct platform_device *pdev)
{
struct smmu_device *smmu = platform_get_drvdata(pdev);
struct device *dev = smmu->dev;
+ int i;
smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG);
platform_set_drvdata(pdev, NULL);
if (smmu->as) {
- int i;
-
for (i = 0; i < smmu->num_as; i++)
free_pdir(&smmu->as[i]);
devm_kfree(dev, smmu->as);
@@ -973,6 +994,13 @@ static int tegra_smmu_remove(struct platform_device *pdev)
devm_iounmap(dev, smmu->regs);
devm_kfree(dev, smmu);
smmu_handle = NULL;
+ for (i = 0; i < NUM_SMMU_REG_BLOCKS; i++) {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ devm_release_mem_region(&pdev->dev, res->start,
+ resource_size(res));
+ }
return 0;
}
--
1.7.5.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists