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
|
#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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue