summaryrefslogtreecommitdiff
path: root/drivers/dsp/syslink/devh
diff options
context:
space:
mode:
authorAngela Stegmaier <angelabaker@ti.com>2010-09-09 10:10:25 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-09-14 19:28:55 -0500
commit5ce43feeb813cb212f233a361ae96f4412fc23a4 (patch)
treee04b0e0b750f51f1c8f0321c36628a81b6d1ff08 /drivers/dsp/syslink/devh
parent21c0be13701968b9e995c79fd3f2dfc53f5596be (diff)
SYSLINK:devh: adding devh to syslink tree
This patch adds devh to syslink tree Signed-off-by: Angela Stegmaier <angelabaker@ti.com> Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com>
Diffstat (limited to 'drivers/dsp/syslink/devh')
-rw-r--r--drivers/dsp/syslink/devh/44xx/Kbuild7
-rw-r--r--drivers/dsp/syslink/devh/44xx/devh44xx.c720
-rw-r--r--drivers/dsp/syslink/devh/Kbuild7
-rw-r--r--drivers/dsp/syslink/devh/devh.c261
-rw-r--r--drivers/dsp/syslink/devh/devh.h64
5 files changed, 1059 insertions, 0 deletions
diff --git a/drivers/dsp/syslink/devh/44xx/Kbuild b/drivers/dsp/syslink/devh/44xx/Kbuild
new file mode 100644
index 000000000000..1cc02051301f
--- /dev/null
+++ b/drivers/dsp/syslink/devh/44xx/Kbuild
@@ -0,0 +1,7 @@
+
+obj-$(CONFIG_OMAP_DEVICE_HANDLER) += devh44xx.o
+
+ccflags-y += -Wno-strict-prototypes
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include/syslink
diff --git a/drivers/dsp/syslink/devh/44xx/devh44xx.c b/drivers/dsp/syslink/devh/44xx/devh44xx.c
new file mode 100644
index 000000000000..0e1d09b09d0c
--- /dev/null
+++ b/drivers/dsp/syslink/devh/44xx/devh44xx.c
@@ -0,0 +1,720 @@
+/*
+ * Device Handler machine-specific module for OMAP4
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched.h>
+#include <mach/irqs.h>
+#include <plat/omap_device.h>
+#include <plat/iommu.h>
+#include <plat/remoteproc.h>
+#if defined(CONFIG_TILER_OMAP)
+#include <mach/tiler.h>
+#endif
+
+#include <syslink/ipc.h>
+
+#include "../devh.h"
+#include "../../ipu_pm/ipu_pm.h"
+
+static struct mutex local_gate;
+
+struct omap_devh_runtime_info {
+ int brd_state;
+ struct iommu *iommu;
+ struct omap_rproc *rproc;
+};
+
+enum {
+ DEVH_BRDST_RUNNING,
+ DEVH_BRDST_STOPPED,
+ DEVH_BRDST_ERROR,
+};
+
+static struct omap_devh_platform_data *devh_get_plat_data_by_name(char *name)
+{
+ int i, j = devh_get_plat_data_size();
+ struct omap_devh_platform_data *pdata = devh_get_plat_data();
+
+ if (name) {
+ for (i = 0; i < j; i++) {
+ if (!(strcmp(name, pdata[i].name)))
+ return &pdata[i];
+ }
+ }
+ return NULL;
+}
+
+static int devh44xx_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v,
+ struct omap_devh_platform_data *pdata)
+{
+ int err = 0;
+ pid_t my_pid = current->tgid;
+ struct omap_devh_runtime_info *pinfo = NULL;
+ struct omap_devh_platform_data *pdata2 = NULL;
+
+ if (pdata)
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+ else
+ return -EINVAL;
+
+ if (pinfo->brd_state == DEVH_BRDST_RUNNING) {
+ err = mutex_lock_interruptible(&local_gate);
+ if (err)
+ goto exit;
+ err = ipu_pm_notifications(PM_PID_DEATH, (void *)my_pid);
+ if (err) {
+ pinfo->brd_state = DEVH_BRDST_ERROR;
+ if (!strcmp(pdata->name, "SysM3")) {
+ pdata2 = devh_get_plat_data_by_name("AppM3");
+ if (pdata2) {
+ pinfo =
+ (struct omap_devh_runtime_info *)
+ pdata2->private_data;
+ pinfo->brd_state = DEVH_BRDST_ERROR;
+ }
+ }
+ }
+ mutex_unlock(&local_gate);
+ }
+
+exit:
+ return err;
+}
+
+static int devh44xx_sysm3_iommu_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("SysM3");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!pdata)
+ return 0;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ switch ((int)val) {
+ case IOMMU_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ case IOMMU_FAULT:
+ pinfo->brd_state = DEVH_BRDST_ERROR;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_appm3_iommu_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("AppM3");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!pdata)
+ return 0;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ switch ((int)val) {
+ case IOMMU_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ case IOMMU_FAULT:
+ pinfo->brd_state = DEVH_BRDST_ERROR;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_tesla_iommu_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("Tesla");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!pdata)
+ return 0;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ switch ((int)val) {
+ case IOMMU_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ case IOMMU_FAULT:
+ pinfo->brd_state = DEVH_BRDST_ERROR;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static struct notifier_block devh_notify_nb_iommu_tesla = {
+ .notifier_call = devh44xx_tesla_iommu_notifier_call,
+};
+static struct notifier_block devh_notify_nb_iommu_ducati0 = {
+ .notifier_call = devh44xx_sysm3_iommu_notifier_call,
+};
+static struct notifier_block devh_notify_nb_iommu_ducati1 = {
+ .notifier_call = devh44xx_appm3_iommu_notifier_call,
+};
+
+static int devh44xx_sysm3_ipc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("SysM3");
+
+ switch ((int)val) {
+ case IPC_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_appm3_ipc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("AppM3");
+
+ switch ((int)val) {
+ case IPC_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_tesla_ipc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("Tesla");
+
+ switch ((int)val) {
+ case IPC_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static struct notifier_block devh_notify_nb_ipc_tesla = {
+ .notifier_call = devh44xx_tesla_ipc_notifier_call,
+};
+static struct notifier_block devh_notify_nb_ipc_ducati1 = {
+ .notifier_call = devh44xx_appm3_ipc_notifier_call,
+};
+static struct notifier_block devh_notify_nb_ipc_ducati0 = {
+ .notifier_call = devh44xx_sysm3_ipc_notifier_call,
+};
+
+static int devh44xx_sysm3_rproc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("SysM3");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (pdata)
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+ else
+ return -EINVAL;
+
+ switch ((int)val) {
+ case OMAP_RPROC_START:
+ pinfo->brd_state = DEVH_BRDST_RUNNING;
+ pinfo->iommu = iommu_get("ducati");
+ if (pinfo->iommu != ERR_PTR(-ENODEV) &&
+ pinfo->iommu != ERR_PTR(-EINVAL))
+ iommu_register_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati0);
+ else
+ pinfo->iommu = NULL;
+ return 0;
+ case OMAP_RPROC_STOP:
+ pinfo->brd_state = DEVH_BRDST_STOPPED;
+ if (pinfo->iommu != NULL) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati0);
+ iommu_put(pinfo->iommu);
+ pinfo->iommu = NULL;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_appm3_rproc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("AppM3");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (pdata)
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+ else
+ return -EINVAL;
+
+ switch ((int)val) {
+ case OMAP_RPROC_START:
+ pinfo->brd_state = DEVH_BRDST_RUNNING;
+ pinfo->iommu = iommu_get("ducati");
+ if (pinfo->iommu != ERR_PTR(-ENODEV) &&
+ pinfo->iommu != ERR_PTR(-EINVAL))
+ iommu_register_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati1);
+ else
+ pinfo->iommu = NULL;
+ return 0;
+ case OMAP_RPROC_STOP:
+ pinfo->brd_state = DEVH_BRDST_STOPPED;
+ if (pinfo->iommu != NULL) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati1);
+ iommu_put(pinfo->iommu);
+ pinfo->iommu = NULL;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_tesla_rproc_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("Tesla");
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (pdata)
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+ else
+ return -EINVAL;
+
+ switch ((int)val) {
+ case OMAP_RPROC_START:
+ pinfo->brd_state = DEVH_BRDST_RUNNING;
+ pinfo->iommu = iommu_get("tesla");
+ if (pinfo->iommu != ERR_PTR(-ENODEV) &&
+ pinfo->iommu != ERR_PTR(-EINVAL))
+ iommu_register_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_tesla);
+ else
+ pinfo->iommu = NULL;
+ return 0;
+ case OMAP_RPROC_STOP:
+ pinfo->brd_state = DEVH_BRDST_STOPPED;
+ if (pinfo->iommu != NULL) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_tesla);
+ iommu_put(pinfo->iommu);
+ pinfo->iommu = NULL;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static struct notifier_block devh_notify_nb_rproc_tesla = {
+ .notifier_call = devh44xx_tesla_rproc_notifier_call,
+};
+static struct notifier_block devh_notify_nb_rproc_ducati0 = {
+ .notifier_call = devh44xx_sysm3_rproc_notifier_call,
+};
+static struct notifier_block devh_notify_nb_rproc_ducati1 = {
+ .notifier_call = devh44xx_appm3_rproc_notifier_call,
+};
+
+#if defined(CONFIG_TILER_OMAP)
+static int devh44xx_sysm3_tiler_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("SysM3");
+
+ switch ((int)val) {
+ case TILER_DEVICE_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_appm3_tiler_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("AppM3");
+
+ switch ((int)val) {
+ case TILER_DEVICE_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static int devh44xx_tesla_tiler_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct omap_devh_platform_data *pdata =
+ devh_get_plat_data_by_name("Tesla");
+
+ switch ((int)val) {
+ case TILER_DEVICE_CLOSE:
+ return devh44xx_notifier_call(nb, val, v, pdata);
+ default:
+ return 0;
+ }
+}
+
+static struct notifier_block devh_notify_nb_tiler_tesla = {
+ .notifier_call = devh44xx_tesla_tiler_notifier_call,
+};
+static struct notifier_block devh_notify_nb_tiler_ducati0 = {
+ .notifier_call = devh44xx_sysm3_tiler_notifier_call,
+};
+static struct notifier_block devh_notify_nb_tiler_ducati1 = {
+ .notifier_call = devh44xx_appm3_tiler_notifier_call,
+};
+#endif
+
+static inline int devh44xx_sysm3_register(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* register will kernel modules for event notifications. */
+ ipc_register_notifier(&devh_notify_nb_ipc_ducati0);
+ pinfo->rproc = omap_rproc_get("ducati-proc0");
+ if (pinfo->rproc != ERR_PTR(-ENODEV))
+ omap_rproc_register_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_ducati0);
+ else
+ pinfo->rproc = NULL;
+#if defined(CONFIG_TILER_OMAP)
+ tiler_reg_notifier(&devh_notify_nb_tiler_ducati0);
+#endif
+
+ return retval;
+}
+
+static inline int devh44xx_appm3_register(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* register will kernel modules for event notifications. */
+ ipc_register_notifier(&devh_notify_nb_ipc_ducati1);
+ pinfo->rproc = omap_rproc_get("ducati-proc1");
+ if (pinfo->rproc != ERR_PTR(-ENODEV))
+ omap_rproc_register_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_ducati1);
+ else
+ pinfo->rproc = NULL;
+#if defined(CONFIG_TILER_OMAP)
+ tiler_reg_notifier(&devh_notify_nb_tiler_ducati1);
+#endif
+
+ return retval;
+}
+
+static inline int devh44xx_tesla_register(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* register will kernel modules for event notifications. */
+ ipc_register_notifier(&devh_notify_nb_ipc_tesla);
+ pinfo->rproc = omap_rproc_get("tesla");
+ if (pinfo->rproc != ERR_PTR(-ENODEV))
+ omap_rproc_register_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_tesla);
+ else
+ pinfo->rproc = NULL;
+#if defined(CONFIG_TILER_OMAP)
+ tiler_reg_notifier(&devh_notify_nb_tiler_tesla);
+#endif
+
+ return retval;
+}
+
+static inline int devh44xx_sysm3_unregister(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* un-register will kernel modules for event notifications. */
+ ipc_unregister_notifier(&devh_notify_nb_ipc_ducati0);
+ if (pinfo->rproc) {
+ omap_rproc_unregister_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_ducati0);
+ omap_rproc_put(pinfo->rproc);
+ }
+ if (pinfo->iommu) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati0);
+ iommu_put(pinfo->iommu);
+ }
+#if defined(CONFIG_TILER_OMAP)
+ tiler_unreg_notifier(&devh_notify_nb_tiler_ducati0);
+#endif
+
+ return retval;
+}
+
+static inline int devh44xx_appm3_unregister(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* un-register will kernel modules for event notifications. */
+ ipc_unregister_notifier(&devh_notify_nb_ipc_ducati1);
+ if (pinfo->rproc) {
+ omap_rproc_unregister_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_ducati1);
+ omap_rproc_put(pinfo->rproc);
+ }
+ if (pinfo->iommu) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_ducati1);
+ iommu_put(pinfo->iommu);
+ }
+#if defined(CONFIG_TILER_OMAP)
+ tiler_unreg_notifier(&devh_notify_nb_tiler_ducati1);
+#endif
+
+ return retval;
+}
+
+static inline int devh44xx_tesla_unregister(struct omap_devh *devh)
+{
+ int retval = 0;
+ struct omap_devh_platform_data *pdata = NULL;
+ struct omap_devh_runtime_info *pinfo = NULL;
+
+ if (!devh->dev)
+ return -EINVAL;
+
+ pdata = (struct omap_devh_platform_data *)devh->dev->platform_data;
+
+ if (!pdata)
+ return -EINVAL;
+
+ pinfo = (struct omap_devh_runtime_info *)pdata->private_data;
+
+ /* un-register will kernel modules for event notifications. */
+ ipc_unregister_notifier(&devh_notify_nb_ipc_tesla);
+ if (pinfo->rproc) {
+ omap_rproc_unregister_notifier(pinfo->rproc,
+ &devh_notify_nb_rproc_tesla);
+ omap_rproc_put(pinfo->rproc);
+ }
+ if (pinfo->iommu) {
+ iommu_unregister_notifier(pinfo->iommu,
+ &devh_notify_nb_iommu_tesla);
+ iommu_put(pinfo->iommu);
+ }
+#if defined(CONFIG_TILER_OMAP)
+ tiler_unreg_notifier(&devh_notify_nb_tiler_tesla);
+#endif
+ return retval;
+}
+
+static struct omap_devh_runtime_info omap4_sysm3_runtime_info = {
+ .brd_state = DEVH_BRDST_STOPPED,
+ .iommu = NULL,
+ .rproc = NULL,
+};
+
+static struct omap_devh_runtime_info omap4_appm3_runtime_info = {
+ .brd_state = DEVH_BRDST_STOPPED,
+ .iommu = NULL,
+ .rproc = NULL,
+};
+
+static struct omap_devh_runtime_info omap4_tesla_runtime_info = {
+ .brd_state = DEVH_BRDST_STOPPED,
+ .iommu = NULL,
+ .rproc = NULL,
+};
+
+static struct omap_devh_ops omap4_sysm3_ops = {
+ .register_notifiers = devh44xx_sysm3_register,
+ .unregister_notifiers = devh44xx_sysm3_unregister,
+};
+
+static struct omap_devh_ops omap4_appm3_ops = {
+ .register_notifiers = devh44xx_appm3_register,
+ .unregister_notifiers = devh44xx_appm3_unregister,
+};
+
+static struct omap_devh_ops omap4_tesla_ops = {
+ .register_notifiers = devh44xx_tesla_register,
+ .unregister_notifiers = devh44xx_tesla_unregister,
+};
+
+static struct omap_devh_platform_data omap4_devh_data[] = {
+ {
+ .name = "Tesla",
+ .ops = &omap4_tesla_ops,
+ .proc_id = 0,
+ .private_data = &omap4_tesla_runtime_info,
+ },
+ {
+ .name = "SysM3",
+ .ops = &omap4_sysm3_ops,
+ .proc_id = 2,
+ .private_data = &omap4_sysm3_runtime_info,
+ },
+ {
+ .name = "AppM3",
+ .ops = &omap4_appm3_ops,
+ .proc_id = 1,
+ .private_data = &omap4_appm3_runtime_info,
+ },
+};
+
+int devh_get_plat_data_size(void)
+{
+ return ARRAY_SIZE(omap4_devh_data);
+}
+EXPORT_SYMBOL(devh_get_plat_data_size);
+
+
+#define NR_DEVH_DEVICES ARRAY_SIZE(omap4_devh_data)
+
+static struct platform_device *omap4_devh_pdev[NR_DEVH_DEVICES];
+
+struct omap_devh_platform_data *devh_get_plat_data(void)
+{
+ return omap4_devh_data;
+}
+
+static int __init omap4_devh_init(void)
+{
+ int i, err;
+
+ mutex_init(&local_gate);
+ for (i = 0; i < NR_DEVH_DEVICES; i++) {
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("omap-devicehandler", i);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ err = platform_device_add_data(pdev, &omap4_devh_data[i],
+ sizeof(omap4_devh_data[0]));
+ sema_init(&(omap4_devh_data[i].sem_handle), 0);
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_out;
+ omap4_devh_pdev[i] = pdev;
+ }
+ return 0;
+
+err_out:
+ while (i--)
+ platform_device_put(omap4_devh_pdev[i]);
+ return err;
+}
+module_init(omap4_devh_init);
+
+static void __exit omap4_devh_exit(void)
+{
+ int i;
+
+ for (i = 0; i < NR_DEVH_DEVICES; i++)
+ platform_device_unregister(omap4_devh_pdev[i]);
+}
+module_exit(omap4_devh_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("OMAP4 Device Handler module");
+MODULE_AUTHOR("Angela Stegmaier <angelabaker@ti.com>");
diff --git a/drivers/dsp/syslink/devh/Kbuild b/drivers/dsp/syslink/devh/Kbuild
new file mode 100644
index 000000000000..65184bd3b59e
--- /dev/null
+++ b/drivers/dsp/syslink/devh/Kbuild
@@ -0,0 +1,7 @@
+
+obj-$(CONFIG_OMAP_DEVICE_HANDLER) += devh.o
+
+ccflags-y += -Wno-strict-prototypes
+
+#Header files
+ccflags-y += -Iarch/arm/plat-omap/include/syslink
diff --git a/drivers/dsp/syslink/devh/devh.c b/drivers/dsp/syslink/devh/devh.c
new file mode 100644
index 000000000000..a9bed7c49938
--- /dev/null
+++ b/drivers/dsp/syslink/devh/devh.c
@@ -0,0 +1,261 @@
+/*
+ * OMAP Device Handler driver
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Written by Angela Stegmaier <angelabaker@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "devh.h"
+
+#define OMAP_DEVH_NAME "omap-devh"
+#define DRV_NAME "omap-devicehandler"
+
+static struct class *omap_devh_class;
+static dev_t omap_devh_dev;
+static atomic_t num_of_devhs;
+static struct platform_driver omap_devh_driver;
+
+static int omap_devh_open(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+ struct omap_devh *devh;
+
+ devh = container_of(inode->i_cdev, struct omap_devh, cdev);
+ if (!devh->dev)
+ return -EINVAL;
+
+ filp->private_data = devh;
+
+ return ret;
+}
+
+static int omap_devh_release(struct inode *inode, struct file *filp)
+{
+ struct omap_devh *devh = filp->private_data;
+ if (!devh || !devh->dev)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int omap_devh_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int rc = 0;
+ struct omap_devh *devh = filp->private_data;
+
+ if (!devh)
+ return -EINVAL;
+
+ if (_IOC_TYPE(cmd) != DEVH_IOC_MAGIC)
+ return -ENOTTY;
+ if (_IOC_NR(cmd) > DEVH_IOC_MAXNR)
+ return -ENOTTY;
+ if (_IOC_DIR(cmd) & _IOC_READ) {
+ if (!access_ok(VERIFY_WRITE, (void __user *)arg,
+ _IOC_SIZE(cmd)))
+ return -EFAULT;
+ } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ if (!access_ok(VERIFY_READ, (void __user *)arg,
+ _IOC_SIZE(cmd)))
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+
+ /*
+ * this will be updated to support user registering for event
+ * notifications.
+ */
+ case DEVH_IOCWAITONEVENTS:
+ /*rc = omap_devh_wait_on_events(devh);*/
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ return rc;
+}
+
+static const struct file_operations omap_devh_fops = {
+ .open = omap_devh_open,
+ .release = omap_devh_release,
+ .ioctl = omap_devh_ioctl,
+ .owner = THIS_MODULE,
+};
+
+static int omap_devh_probe(struct platform_device *pdev)
+{
+ int ret = 0, major, minor;
+ struct device *tmpdev;
+ struct device *dev = &pdev->dev;
+ struct omap_devh_platform_data *pdata = dev->platform_data;
+ struct omap_devh *devh;
+
+ if (!pdata || !pdata->name || !pdata->ops)
+ return -EINVAL;
+
+ dev_info(dev, "%s: adding devh %s\n", __func__, pdata->name);
+
+ devh = kzalloc(sizeof(struct omap_devh), GFP_KERNEL);
+ if (!devh) {
+ dev_err(dev, "%s: kzalloc failed\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ platform_set_drvdata(pdev, devh);
+ major = MAJOR(omap_devh_dev);
+ minor = atomic_read(&num_of_devhs);
+ atomic_inc(&num_of_devhs);
+
+ devh->dev = dev;
+ devh->minor = minor;
+ devh->name = pdata->name;
+
+ cdev_init(&devh->cdev, &omap_devh_fops);
+ devh->cdev.owner = THIS_MODULE;
+ ret = cdev_add(&devh->cdev, MKDEV(major, minor), 1);
+ if (ret) {
+ dev_err(dev, "%s: cdev_add failed: %d\n", __func__, ret);
+ goto free_devh;
+ }
+
+ tmpdev = device_create(omap_devh_class, NULL,
+ MKDEV(major, minor),
+ NULL,
+ OMAP_DEVH_NAME "%d", minor);
+ if (IS_ERR(tmpdev)) {
+ ret = PTR_ERR(tmpdev);
+ pr_err("%s: device_create failed: %d\n", __func__, ret);
+ goto clean_cdev;
+ }
+
+ pr_info("%s initialized %s, major: %d, base-minor: %d\n",
+ OMAP_DEVH_NAME,
+ pdata->name,
+ MAJOR(omap_devh_dev),
+ minor);
+
+ if (pdata->ops->register_notifiers)
+ pdata->ops->register_notifiers(devh);
+
+ return 0;
+
+clean_cdev:
+ cdev_del(&devh->cdev);
+free_devh:
+ kfree(devh);
+out:
+ return ret;
+}
+
+static int omap_devh_remove(struct platform_device *pdev)
+{
+ int major = MAJOR(omap_devh_dev);
+ struct device *dev = &pdev->dev;
+ struct omap_devh_platform_data *pdata = dev->platform_data;
+ struct omap_devh *devh = platform_get_drvdata(pdev);
+
+ if (!pdata || !devh)
+ return -EINVAL;
+
+ if (pdata->ops->unregister_notifiers)
+ pdata->ops->unregister_notifiers(devh);
+
+ dev_info(dev, "%s removing %s, major: %d, base-minor: %d\n",
+ OMAP_DEVH_NAME,
+ pdata->name,
+ major,
+ devh->minor);
+
+ device_destroy(omap_devh_class, MKDEV(major, devh->minor));
+ cdev_del(&devh->cdev);
+ kfree(devh);
+
+ return 0;
+}
+
+static struct platform_driver omap_devh_driver = {
+ .probe = omap_devh_probe,
+ .remove = omap_devh_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init omap_devh_init(void)
+{
+ int num = devh_get_plat_data_size();
+ int ret;
+
+ ret = alloc_chrdev_region(&omap_devh_dev, 0, num, OMAP_DEVH_NAME);
+ if (ret) {
+ pr_err("%s: alloc_chrdev_region failed: %d\n", __func__, ret);
+ goto out;
+ }
+
+ omap_devh_class = class_create(THIS_MODULE, OMAP_DEVH_NAME);
+ if (IS_ERR(omap_devh_class)) {
+ ret = PTR_ERR(omap_devh_class);
+ pr_err("%s: class_create failed: %d\n", __func__, ret);
+ goto unreg_region;
+ }
+
+ atomic_set(&num_of_devhs, 0);
+
+ ret = platform_driver_register(&omap_devh_driver);
+ if (ret) {
+ pr_err("%s: platform_driver_register failed: %d\n",
+ __func__, ret);
+ goto out;
+ }
+ return 0;
+unreg_region:
+ unregister_chrdev_region(omap_devh_dev, num);
+out:
+ return ret;
+}
+module_init(omap_devh_init);
+
+static void __exit omap_devh_exit(void)
+{
+ int num = devh_get_plat_data_size();
+ pr_info("%s\n", __func__);
+ platform_driver_unregister(&omap_devh_driver);
+ class_destroy(omap_devh_class);
+ unregister_chrdev_region(omap_devh_dev, num);
+}
+module_exit(omap_devh_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("OMAP Device Handler driver");
+MODULE_AUTHOR("Angela Stegmaier <angelabaker@ti.com>");
diff --git a/drivers/dsp/syslink/devh/devh.h b/drivers/dsp/syslink/devh/devh.h
new file mode 100644
index 000000000000..81dbb1b67df4
--- /dev/null
+++ b/drivers/dsp/syslink/devh/devh.h
@@ -0,0 +1,64 @@
+/*
+ * OMAP Device Handler driver
+ *
+ * Copyright (C) 2010 Texas Instruments Inc.
+ *
+ * Written by Angela Stegmaier <angelabaker@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef DEVH_H
+#define DEVH_H
+
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/semaphore.h>
+
+#define DEVH_IOC_MAGIC 'P'
+
+#define DEVH_IOCWAITONEVENTS _IOR(DEVH_IOC_MAGIC, 0, int)
+
+#define DEVH_IOC_MAXNR (1)
+
+struct omap_devh;
+
+struct omap_devh_ops {
+ int (*register_notifiers)(struct omap_devh *devh);
+ int (*unregister_notifiers)(struct omap_devh *devh);
+};
+
+struct omap_devh_platform_data {
+ struct omap_devh_ops *ops;
+ char *name;
+ int proc_id;
+ struct semaphore sem_handle;
+ void *private_data;
+};
+
+struct omap_devh {
+ struct device *dev;
+ struct cdev cdev;
+ atomic_t count;
+ int state;
+ int minor;
+ char *name;
+};
+
+extern struct omap_devh_platform_data *devh_get_plat_data(void);
+extern int devh_get_plat_data_size(void);
+
+#endif /* DEVH_H */