mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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:
parent
86407fd232
commit
ec8bb175ee
4 changed files with 48 additions and 25 deletions
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue