From: johlstei@codeaurora.org (Jeff Ohlstein)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 23/24] msm: Platform initialization for the IOMMU driver
Date: Tue, 24 Aug 2010 21:57:52 -0700 [thread overview]
Message-ID: <1282712273-344-24-git-send-email-johlstei@codeaurora.org> (raw)
In-Reply-To: <1282712273-344-1-git-send-email-johlstei@codeaurora.org>
From: Stepan Moskovchenko <stepanm@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@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 c984f4d..0d16232 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.o
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);
+ clk_put(iommu_clk);
+ }
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "physbase");
+ if (!r) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ len = r->end - r->start + 1;
+
+ r = request_mem_region(r->start, len, r->name);
+ if (!r) {
+ pr_err("Could not request memory region: "
+ "start=%p, len=%d\n", (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ regs_base = ioremap(r->start, len);
+
+ if (!regs_base) {
+ pr_err("Could not ioremap: start=%p, len=%d\n",
+ (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail;
+ }
+
+ irq = platform_get_irq_byname(pdev, "secure_irq");
+ if (irq < 0) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ mb();
+
+ if (GET_IDR(regs_base) == 0) {
+ pr_err("Invalid IDR value detected\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ret = request_irq(irq, msm_iommu_fault_handler, 0,
+ "msm_iommu_secure_irpt_handler", drvdata);
+ if (ret) {
+ pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+ goto fail;
+ }
+
+ msm_iommu_reset(regs_base);
+ drvdata->base = regs_base;
+ drvdata->irq = irq;
+
+ nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+ ncb = GET_NCB((unsigned long) regs_base);
+
+ pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+ iommu_dev->name, regs_base, irq, ncb+1);
+
+ platform_set_drvdata(pdev, drvdata);
+ } else
+ msm_iommu_root_dev = pdev;
+
+ return 0;
+
+fail:
+ kfree(drvdata);
+ return ret;
+}
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+ struct msm_iommu_drvdata *drv = NULL;
+
+ drv = platform_get_drvdata(pdev);
+ if (drv) {
+ memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+ kfree(drv);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return 0;
+}
+
+static int msm_iommu_ctx_probe(struct platform_device *pdev)
+{
+ struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
+ struct msm_iommu_drvdata *drvdata;
+ struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
+ int i, ret = 0;
+ if (!c || !pdev->dev.parent) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ drvdata = dev_get_drvdata(pdev->dev.parent);
+
+ if (!drvdata) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
+ if (!ctx_drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ ctx_drvdata->num = c->num;
+ ctx_drvdata->pdev = pdev;
+
+ INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
+ platform_set_drvdata(pdev, ctx_drvdata);
+
+ /* Program the M2V tables for this context */
+ for (i = 0; i < MAX_NUM_MIDS; i++) {
+ int mid = c->mids[i];
+ if (mid == -1)
+ break;
+
+ SET_M2VCBR_N(drvdata->base, mid, 0);
+ SET_CBACR_N(drvdata->base, c->num, 0);
+
+ /* Set VMID = MID */
+ SET_VMID(drvdata->base, mid, mid);
+
+ /* Set the context number for that MID to this context */
+ SET_CBNDX(drvdata->base, mid, c->num);
+
+ /* Set MID associated with this context bank */
+ SET_CBVMID(drvdata->base, c->num, mid);
+
+ /* Set security bit override to be Non-secure */
+ SET_NSCFG(drvdata->base, mid, 3);
+ }
+
+ pr_info("context device %s with bank index %d\n", c->name, c->num);
+
+ return 0;
+fail:
+ kfree(ctx_drvdata);
+ return ret;
+}
+
+static int msm_iommu_ctx_remove(struct platform_device *pdev)
+{
+ struct msm_iommu_ctx_drvdata *drv = NULL;
+ drv = platform_get_drvdata(pdev);
+ if (drv) {
+ memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
+ kfree(drv);
+ platform_set_drvdata(pdev, NULL);
+ }
+ return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+ .driver = {
+ .name = "msm_iommu",
+ },
+ .probe = msm_iommu_probe,
+ .remove = msm_iommu_remove,
+};
+
+static struct platform_driver msm_iommu_ctx_driver = {
+ .driver = {
+ .name = "msm_iommu_ctx",
+ },
+ .probe = msm_iommu_ctx_probe,
+ .remove = msm_iommu_ctx_remove,
+};
+
+static int msm_iommu_driver_init(void)
+{
+ int ret;
+ ret = platform_driver_register(&msm_iommu_driver);
+ if (ret != 0) {
+ pr_err("Failed to register IOMMU driver\n");
+ goto error;
+ }
+
+ ret = platform_driver_register(&msm_iommu_ctx_driver);
+ if (ret != 0) {
+ pr_err("Failed to register IOMMU context driver\n");
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+static void msm_iommu_driver_exit(void)
+{
+ platform_driver_unregister(&msm_iommu_ctx_driver);
+ platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
--
1.7.2.1
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
next prev parent reply other threads:[~2010-08-25 4:57 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-25 4:57 [PATCH 00/24] Support for Qualcomm msm8660 target Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 01/24] msm: create config option for proc-comm Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 02/24] arm: Kconfig option for ARCH_MSM_SCORPIONMP Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 03/24] arm: mm: add proc info for ScorpionMP Jeff Ohlstein
2010-08-27 13:54 ` Catalin Marinas
2010-08-27 15:29 ` Daniel Walker
2010-08-27 16:04 ` Catalin Marinas
2010-08-27 16:33 ` Daniel Walker
2010-08-27 16:49 ` Catalin Marinas
2010-08-27 19:53 ` Daniel Walker
2010-08-31 12:18 ` Catalin Marinas
2010-08-31 16:44 ` Daniel Walker
2010-09-01 5:56 ` Shilimkar, Santosh
2010-09-04 14:32 ` Russell King - ARM Linux
2010-09-06 22:22 ` Daniel Walker
2010-09-04 14:31 ` Russell King - ARM Linux
2010-08-25 4:57 ` [PATCH 04/24] GIC: Dont disable INT in ack callback Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 05/24] msm: io: MSM8X60 io support Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 06/24] msm: initial irq definitions for MSM8X60 Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 07/24] msm: irqs-8x60: interrupt map Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 08/24] msm: timer: support 8x60 timers Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 09/24] msm: MSM8X60 RUMI3 board support Jeff Ohlstein
2010-09-02 11:08 ` Russell King - ARM Linux
2010-09-09 3:15 ` Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 10/24] msm: irq: rename existing entry-macro to entry-macro-vic Jeff Ohlstein
2010-09-02 11:10 ` Russell King - ARM Linux
2010-08-25 4:57 ` [PATCH 11/24] msm: 8x60: gic initialization fixup for RUMI Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 12/24] msm: clock: add dummy clock driver Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 13/24] dma: add stub functions for dma features not yet present on 8x60 Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 14/24] msm: add hotplug stub functions Jeff Ohlstein
2010-09-02 11:11 ` Russell King - ARM Linux
2010-09-02 16:49 ` Daniel Walker
2010-09-02 17:12 ` Russell King - ARM Linux
2010-09-02 22:25 ` Daniel Walker
2010-09-02 22:36 ` Daniel Walker
2010-09-03 7:31 ` Russell King - ARM Linux
2010-09-03 16:23 ` Daniel Walker
2010-08-25 4:57 ` [PATCH 15/24] msm: allow uart to be conditionally disabled Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 16/24] msm: add build support for msm8x60 target Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 17/24] msm: 8x60: setup correct handlers for private interrupts Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 18/24] msm: physical offset for MSM8X60 Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 19/24] msm: add msm8x60_surf machine Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 20/24] msm: MSM8X60 simulator board support Jeff Ohlstein
2010-09-02 11:13 ` Russell King - ARM Linux
2010-09-02 18:19 ` David Brown
2010-09-02 18:52 ` Russell King - ARM Linux
2010-08-25 4:57 ` [PATCH 21/24] msm: add MSM8x60 FFA support Jeff Ohlstein
2010-08-25 4:57 ` [PATCH 22/24] msm: Add MSM IOMMU support Jeff Ohlstein
2010-08-25 4:57 ` Jeff Ohlstein [this message]
2010-08-25 4:57 ` [PATCH 24/24] msm: Platform data for msm8x60 IOMMUs Jeff Ohlstein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1282712273-344-24-git-send-email-johlstei@codeaurora.org \
--to=johlstei@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).