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
/* Maximum number of SMT entries allowed by the system */
#define MAX_NUM_SMR 128
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
@ -69,6 +72,9 @@ struct msm_iommu_ctx_dev {
* @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance
* @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
* of an IOMMU hardware instance.
@ -81,6 +87,7 @@ struct msm_iommu_drvdata {
struct clk *pclk;
const char *name;
struct regulator *gdsc;
unsigned int nsmr;
};
/**
@ -89,6 +96,10 @@ struct msm_iommu_drvdata {
* @pdev: Platform device associated wit this HW instance
* @attached_elm: List element for domains to track which devices are
* 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
* within each IOMMU hardware instance
@ -99,6 +110,8 @@ struct msm_iommu_ctx_drvdata {
struct list_head attached_elm;
struct iommu_domain *attached_domain;
const char *name;
u32 sids[MAX_NUM_SMR];
unsigned int nsid;
};
/*

View file

@ -16,8 +16,6 @@
#define CTX_SHIFT 12
#define CTX_OFFSET 0x8000
#define MAX_NUM_SMR 128
#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
#define GET_CTX_REG(reg, base, ctx) \
(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_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
u32 sids[MAX_NUM_SMR];
int len = 0, ret;
u32 smt_size;
int ret;
mutex_lock(&msm_iommu_lock);
@ -376,21 +374,6 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
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);
if (ret)
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))
__program_iommu(iommu_drvdata->base, smt_size);
__program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr);
__program_context(iommu_drvdata->base, ctx_drvdata->num,
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);
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 device_node *child;
int ret;
int ret = 0;
u32 nsmr;
ret = device_move(&pdev->dev, &msm_iommu_root_dev->dev, DPM_ORDER_NONE);
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) {
drvdata->ncb++;
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);
return 0;
fail:
return ret;
}
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;
int irq, ret;
u32 nsid;
irq = platform_get_irq(pdev, 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 = 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;
}