[PATCH 19/20 v2] msm: Platform initialization for the IOMMU driver
Daniel Walker
dwalker at codeaurora.org
Wed Oct 6 10:28:17 EDT 2010
On Wed, 2010-10-06 at 00:42 -0700, Jeff Ohlstein wrote:
> From: Stepan Moskovchenko <stepanm at codeaurora.org>
>
> Register a driver for the MSM IOMMU devices and a driver
> for the translation context devices. Set up the global
> IOMMU registers and initialize the context banks.
>
> Signed-off-by: Stepan Moskovchenko <stepanm at codeaurora.org>
> ---
> arch/arm/mach-msm/Makefile | 2 +-
> arch/arm/mach-msm/iommu_dev.c | 364 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 365 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-msm/iommu_dev.c
>
> diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
> index 6a0b92e..56b1db9 100644
> --- a/arch/arm/mach-msm/Makefile
> +++ b/arch/arm/mach-msm/Makefile
> @@ -12,7 +12,7 @@ obj-y += irq.o
> endif
> endif
>
> -obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o
> +obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o
> obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
> obj-$(CONFIG_MSM_PROC_COMM) += clock.o gpio.c
> obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
> diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
> new file mode 100644
> index 0000000..59ac7e5
> --- /dev/null
> +++ b/arch/arm/mach-msm/iommu_dev.c
> @@ -0,0 +1,364 @@
> +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> + * 02110-1301, USA.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/iommu.h>
> +#include <linux/interrupt.h>
> +#include <linux/err.h>
> +#include <linux/slab.h>
> +
> +#include <mach/iommu_hw-8xxx.h>
> +#include <mach/iommu.h>
> +
> +struct iommu_ctx_iter_data {
> + /* input */
> + const char *name;
> +
> + /* output */
> + struct device *dev;
> +};
> +
> +static struct platform_device *msm_iommu_root_dev;
> +
> +static int each_iommu_ctx(struct device *dev, void *data)
> +{
> + struct iommu_ctx_iter_data *res = data;
> + struct msm_iommu_ctx_dev *c = dev->platform_data;
> +
> + if (!res || !c || !c->name || !res->name)
> + return -EINVAL;
> +
> + if (!strcmp(res->name, c->name)) {
> + res->dev = dev;
> + return 1;
> + }
> + return 0;
> +}
> +
> +static int each_iommu(struct device *dev, void *data)
> +{
> + return device_for_each_child(dev, data, each_iommu_ctx);
> +}
> +
> +struct device *msm_iommu_get_ctx(const char *ctx_name)
> +{
> + struct iommu_ctx_iter_data r;
> + int found;
> +
> + if (!msm_iommu_root_dev) {
> + pr_err("No root IOMMU device.\n");
> + goto fail;
> + }
> +
> + r.name = ctx_name;
> + found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
> +
> + if (!found) {
> + pr_err("Could not find context <%s>\n", ctx_name);
> + goto fail;
> + }
> +
> + return r.dev;
> +fail:
> + return NULL;
> +}
> +EXPORT_SYMBOL(msm_iommu_get_ctx);
> +
> +static void msm_iommu_reset(void __iomem *base)
> +{
> + int ctx, ncb;
> +
> + SET_RPUE(base, 0);
> + SET_RPUEIE(base, 0);
> + SET_ESRRESTORE(base, 0);
> + SET_TBE(base, 0);
> + SET_CR(base, 0);
> + SET_SPDMBE(base, 0);
> + SET_TESTBUSCR(base, 0);
> + SET_TLBRSW(base, 0);
> + SET_GLOBAL_TLBIALL(base, 0);
> + SET_RPU_ACR(base, 0);
> + SET_TLBLKCRWE(base, 1);
> + ncb = GET_NCB(base)+1;
> +
> + for (ctx = 0; ctx < ncb; ctx++) {
> + SET_BPRCOSH(base, ctx, 0);
> + SET_BPRCISH(base, ctx, 0);
> + SET_BPRCNSH(base, ctx, 0);
> + SET_BPSHCFG(base, ctx, 0);
> + SET_BPMTCFG(base, ctx, 0);
> + SET_ACTLR(base, ctx, 0);
> + SET_SCTLR(base, ctx, 0);
> + SET_FSRRESTORE(base, ctx, 0);
> + SET_TTBR0(base, ctx, 0);
> + SET_TTBR1(base, ctx, 0);
> + SET_TTBCR(base, ctx, 0);
> + SET_BFBCR(base, ctx, 0);
> + SET_PAR(base, ctx, 0);
> + SET_FAR(base, ctx, 0);
> + SET_CTX_TLBIALL(base, ctx, 0);
> + SET_TLBFLPTER(base, ctx, 0);
> + SET_TLBSLPTER(base, ctx, 0);
> + SET_TLBLKCR(base, ctx, 0);
> + SET_PRRR(base, ctx, 0);
> + SET_NMRR(base, ctx, 0);
> + SET_CONTEXTIDR(base, ctx, 0);
> + }
> +}
> +
> +static int msm_iommu_probe(struct platform_device *pdev)
> +{
> + struct resource *r;
> + struct clk *iommu_clk;
> + struct msm_iommu_drvdata *drvdata;
> + struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
> + void __iomem *regs_base;
> + resource_size_t len;
> + int ret = 0, ncb, nm2v, irq;
> +
> + if (pdev->id != -1) {
> + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
> +
> + if (!drvdata) {
> + ret = -ENOMEM;
> + goto fail;
> + }
> +
> + if (!iommu_dev) {
> + ret = -ENODEV;
> + goto fail;
> + }
> +
> + if (iommu_dev->clk_rate != 0) {
> + iommu_clk = clk_get(&pdev->dev, "iommu_clk");
> +
> + if (IS_ERR(iommu_clk)) {
> + ret = -ENODEV;
> + goto fail;
> + }
> +
> + if (iommu_dev->clk_rate > 0)
> + clk_set_rate(iommu_clk, iommu_dev->clk_rate);
> +
> + clk_enable(iommu_clk);
Steve,
What happens if clk_enable fails? Doesn't look like your handling that
case here.
Daniel
--
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum.
More information about the linux-arm-kernel
mailing list