iommu/msm: Refactor device tree parsing

Query SMT and SID mapping information at probe-time instead
of attach-time to allow this information to be
error-checked at an earlier time.

Change-Id: Ib2bbdc8374f9c86c3e6013d298fe8b279b53d83b
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
This commit is contained in:
Stepan Moskovchenko 2012-06-28 14:59:00 -07:00 committed by Stephen Boyd
parent 86407fd232
commit ec8bb175ee
4 changed files with 48 additions and 25 deletions

View file

@ -35,6 +35,9 @@ extern struct platform_device *msm_iommu_root_dev;
*/ */
#define MAX_NUM_MIDS 32 #define MAX_NUM_MIDS 32
/* Maximum number of SMT entries allowed by the system */
#define MAX_NUM_SMR 128
/** /**
* struct msm_iommu_dev - a single IOMMU hardware instance * struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance * name Human-readable name given to this IOMMU HW instance
@ -69,6 +72,9 @@ struct msm_iommu_ctx_dev {
* @irq: Interrupt number * @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance * @clk: The bus clock for this IOMMU hardware instance
* @pclk: The clock for the IOMMU bus interconnect * @pclk: The clock for the IOMMU bus interconnect
* @name: Human-readable name of this IOMMU device
* @gdsc: Regulator needed to power this HW block (v2 only)
* @nsmr: Size of the SMT on this HW block (v2 only)
* *
* A msm_iommu_drvdata holds the global driver data about a single piece * A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance. * of an IOMMU hardware instance.
@ -81,6 +87,7 @@ struct msm_iommu_drvdata {
struct clk *pclk; struct clk *pclk;
const char *name; const char *name;
struct regulator *gdsc; struct regulator *gdsc;
unsigned int nsmr;
}; };
/** /**
@ -89,6 +96,10 @@ struct msm_iommu_drvdata {
* @pdev: Platform device associated wit this HW instance * @pdev: Platform device associated wit this HW instance
* @attached_elm: List element for domains to track which devices are * @attached_elm: List element for domains to track which devices are
* attached to them * attached to them
* @attached_domain Domain currently attached to this context (if any)
* @name Human-readable name of this context device
* @sids List of Stream IDs mapped to this context (v2 only)
* @nsid Number of Stream IDs mapped to this context (v2 only)
* *
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
* within each IOMMU hardware instance * within each IOMMU hardware instance
@ -99,6 +110,8 @@ struct msm_iommu_ctx_drvdata {
struct list_head attached_elm; struct list_head attached_elm;
struct iommu_domain *attached_domain; struct iommu_domain *attached_domain;
const char *name; const char *name;
u32 sids[MAX_NUM_SMR];
unsigned int nsid;
}; };
/* /*

View file

@ -16,8 +16,6 @@
#define CTX_SHIFT 12 #define CTX_SHIFT 12
#define CTX_OFFSET 0x8000 #define CTX_OFFSET 0x8000
#define MAX_NUM_SMR 128
#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg))) #define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \ #define GET_CTX_REG(reg, base, ctx) \
(readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT))) (readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))

View file

@ -346,9 +346,7 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
struct msm_iommu_drvdata *iommu_drvdata; struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata; struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata; struct msm_iommu_ctx_drvdata *tmp_drvdata;
u32 sids[MAX_NUM_SMR]; int ret;
int len = 0, ret;
u32 smt_size;
mutex_lock(&msm_iommu_lock); mutex_lock(&msm_iommu_lock);
@ -376,21 +374,6 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
goto fail; goto fail;
} }
of_get_property(dev->of_node, "qcom,iommu-ctx-sids", &len);
BUG_ON(len >= sizeof(sids));
if (of_property_read_u32(dev->parent->of_node, "qcom,iommu-smt-size",
&smt_size)) {
ret = -EINVAL;
goto fail;
}
BUG_ON(smt_size > MAX_NUM_SMR);
if (of_property_read_u32_array(dev->of_node, "qcom,iommu-ctx-sids",
sids, len / sizeof(*sids))) {
ret = -EINVAL;
goto fail;
}
ret = regulator_enable(iommu_drvdata->gdsc); ret = regulator_enable(iommu_drvdata->gdsc);
if (ret) if (ret)
goto fail; goto fail;
@ -402,11 +385,12 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
} }
if (!msm_iommu_ctx_attached(dev->parent)) if (!msm_iommu_ctx_attached(dev->parent))
__program_iommu(iommu_drvdata->base, smt_size); __program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr);
__program_context(iommu_drvdata->base, ctx_drvdata->num, __program_context(iommu_drvdata->base, ctx_drvdata->num,
iommu_drvdata->ncb, __pa(priv->pt.fl_table), iommu_drvdata->ncb, __pa(priv->pt.fl_table),
priv->pt.redirect, sids, len, smt_size); priv->pt.redirect, ctx_drvdata->sids, ctx_drvdata->nsid,
iommu_drvdata->nsmr);
__disable_clocks(iommu_drvdata); __disable_clocks(iommu_drvdata);
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached); list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);

View file

@ -33,12 +33,25 @@ static int msm_iommu_parse_dt(struct platform_device *pdev,
struct msm_iommu_drvdata *drvdata) struct msm_iommu_drvdata *drvdata)
{ {
struct device_node *child; struct device_node *child;
int ret; int ret = 0;
u32 nsmr;
ret = device_move(&pdev->dev, &msm_iommu_root_dev->dev, DPM_ORDER_NONE); ret = device_move(&pdev->dev, &msm_iommu_root_dev->dev, DPM_ORDER_NONE);
if (ret) if (ret)
return ret; goto fail;
ret = of_property_read_u32(pdev->dev.of_node, "qcom,iommu-smt-size",
&nsmr);
if (ret)
goto fail;
if (nsmr > MAX_NUM_SMR) {
pr_err("Invalid SMT size: %d\n", nsmr);
ret = -EINVAL;
goto fail;
}
drvdata->nsmr = nsmr;
for_each_child_of_node(pdev->dev.of_node, child) { for_each_child_of_node(pdev->dev.of_node, child) {
drvdata->ncb++; drvdata->ncb++;
if (!of_platform_device_create(child, NULL, &pdev->dev)) if (!of_platform_device_create(child, NULL, &pdev->dev))
@ -46,7 +59,8 @@ static int msm_iommu_parse_dt(struct platform_device *pdev,
} }
drvdata->name = dev_name(&pdev->dev); drvdata->name = dev_name(&pdev->dev);
return 0; fail:
return ret;
} }
static atomic_t msm_iommu_next_id = ATOMIC_INIT(-1); static atomic_t msm_iommu_next_id = ATOMIC_INIT(-1);
@ -149,6 +163,7 @@ static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
{ {
struct resource *r, rp; struct resource *r, rp;
int irq, ret; int irq, ret;
u32 nsid;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq > 0) { if (irq > 0) {
@ -181,6 +196,19 @@ static int msm_iommu_ctx_parse_dt(struct platform_device *pdev,
&ctx_drvdata->name)) &ctx_drvdata->name))
ctx_drvdata->name = dev_name(&pdev->dev); ctx_drvdata->name = dev_name(&pdev->dev);
if (!of_get_property(pdev->dev.of_node, "qcom,iommu-ctx-sids", &nsid))
return -EINVAL;
if (nsid >= sizeof(ctx_drvdata->sids))
return -EINVAL;
if (of_property_read_u32_array(pdev->dev.of_node, "qcom,iommu-ctx-sids",
ctx_drvdata->sids,
nsid / sizeof(*ctx_drvdata->sids))) {
return -EINVAL;
}
ctx_drvdata->nsid = nsid;
return 0; return 0;
} }