From f238a85f926c82e09855d32a595a4487bcffc0fb Mon Sep 17 00:00:00 2001
From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Date: Fri, 15 Aug 2008 01:55:54 +0300
Subject: [PATCH 09/15] TI DSP BRIDGE: Mini driver

Initial port from omapzoom
	http://omapzoom.org/gf/project/omapbridge

For details,
http://omapzoom.org/gf/project/omapbridge/docman/?subdir=3

Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
---
 drivers/dsp/bridge/wmd/_cmm.h           |   59 +
 drivers/dsp/bridge/wmd/_deh.h           |   48 +
 drivers/dsp/bridge/wmd/_msg_sm.h        |  158 +++
 drivers/dsp/bridge/wmd/_tiomap.h        |  400 ++++++
 drivers/dsp/bridge/wmd/_tiomap_api.h    |  182 +++
 drivers/dsp/bridge/wmd/_tiomap_clk.h    |  123 ++
 drivers/dsp/bridge/wmd/_tiomap_mmu.h    |   53 +
 drivers/dsp/bridge/wmd/_tiomap_pwr.h    |   82 ++
 drivers/dsp/bridge/wmd/_tiomap_util.h   |   47 +
 drivers/dsp/bridge/wmd/chnl_sm.c        | 1101 ++++++++++++++++
 drivers/dsp/bridge/wmd/io_sm.c          | 1843 ++++++++++++++++++++++++++
 drivers/dsp/bridge/wmd/mmu_fault.c      |  171 +++
 drivers/dsp/bridge/wmd/mmu_fault.h      |   52 +
 drivers/dsp/bridge/wmd/msg_sm.c         |  599 +++++++++
 drivers/dsp/bridge/wmd/tiomap3430.c     | 2171 +++++++++++++++++++++++++++++++
 drivers/dsp/bridge/wmd/tiomap3430_pwr.c |  568 ++++++++
 drivers/dsp/bridge/wmd/tiomap_io.c      |  430 ++++++
 drivers/dsp/bridge/wmd/tiomap_io.h      |  112 ++
 drivers/dsp/bridge/wmd/tiomap_sm.c      |  305 +++++
 drivers/dsp/bridge/wmd/ue_deh.c         |  502 +++++++
 20 files changed, 9006 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dsp/bridge/wmd/_cmm.h
 create mode 100644 drivers/dsp/bridge/wmd/_deh.h
 create mode 100644 drivers/dsp/bridge/wmd/_msg_sm.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap_api.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap_clk.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap_mmu.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap_pwr.h
 create mode 100644 drivers/dsp/bridge/wmd/_tiomap_util.h
 create mode 100644 drivers/dsp/bridge/wmd/chnl_sm.c
 create mode 100644 drivers/dsp/bridge/wmd/io_sm.c
 create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.c
 create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.h
 create mode 100644 drivers/dsp/bridge/wmd/msg_sm.c
 create mode 100644 drivers/dsp/bridge/wmd/tiomap3430.c
 create mode 100644 drivers/dsp/bridge/wmd/tiomap3430_pwr.c
 create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.c
 create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.h
 create mode 100644 drivers/dsp/bridge/wmd/tiomap_sm.c
 create mode 100644 drivers/dsp/bridge/wmd/ue_deh.c

diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
new file mode 100644
index 0000000..6f55851
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_cmm.h
@@ -0,0 +1,59 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/wmdchnl/common/_cmm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _cmm.h ========
+ *  Description:
+ *      Private header file defining CMM manager objects and defines needed
+ *      by IO manager to register shared memory regions when DSP base image
+ *      is loaded(WMD_IO_OnLoaded).
+ *
+ *  Public Functions:
+ *      None.
+ *
+ *  Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 24-Aug-2001 ag     Created.
+ */
+
+#ifndef _CMM_
+#define _CMM_
+
+/*
+ *  These target side symbols define the beginning and ending addresses
+ *  of the section of shared memory used for shared memory manager CMM.
+ *  They are defined in the *cfg.cmd file by cdb code.
+ */
+#define SHM0_SHARED_BASE_SYM             "_SHM0_BEG"
+#define SHM0_SHARED_END_SYM              "_SHM0_END"
+#define SHM0_SHARED_RESERVED_BASE_SYM    "_SHM0_RSVDSTRT"
+
+/*
+ *  Shared Memory Region #0(SHMSEG0) is used in the following way:
+ *
+ *  |(_SHM0_BEG)                  | (_SHM0_RSVDSTRT)           | (_SHM0_END)
+ *  V                             V                            V
+ *  ------------------------------------------------------------
+ *  |     DSP-side allocations    |    GPP-side allocations    |
+ *  ------------------------------------------------------------
+ *
+ *
+ */
+
+#endif				/* _CMM_ */
diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
new file mode 100644
index 0000000..4306501
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_deh.h
@@ -0,0 +1,48 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_deh.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _deh.h ========
+ *  Description:
+ *      Private header for DEH module.
+ *
+ *! Revision History:
+ *! ================
+ *! 21-Sep-2001 kc: created.
+ */
+
+#ifndef _DEH_
+#define _DEH_
+
+#include <dpc.h>
+#include <isr.h>
+#include <ntfy.h>
+#include <wmd.h>
+
+#define SIGNATURE       0x5f484544	/* "DEH_" backwards */
+
+/* DEH Manager: only one created per board: */
+struct DEH_MGR {
+	u32 dwSignature;	/* Used for object validation.  */
+	struct WMD_DEV_CONTEXT *hWmdContext;	/* WMD device context. */
+	struct NTFY_OBJECT *hNtfy;	/* NTFY object                  */
+	struct DPC_OBJECT *hMmuFaultDpc;	/* DPC object handle.  */
+	struct ISR_IRQ *hMmuFaultIsr;	/* DSP MMU ISR handle.          */
+	struct DSP_ERRORINFO errInfo;	/* DSP exception info.          */
+} ;
+
+#endif				/* _DEH_ */
diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
new file mode 100644
index 0000000..fefcdc5
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_msg_sm.h
@@ -0,0 +1,158 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/wmdchnl/common/_msg_sm.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _msg_sm.h ========
+ *  Description:
+ *      Private header file defining MSG manager objects and defines needed
+ *      by IO manager.
+ *
+ *  Public Functions:
+ *      None.
+ *
+ *  Notes:
+ *
+ *! Revision History:
+ *! ================
+ *! 09-May-2001 jeh     Code Review cleanup.
+ *! 08-Nov-2000 jeh     Created.
+ */
+
+#ifndef _MSG_SM_
+#define _MSG_SM_
+
+#include <list.h>
+#include <msgdefs.h>
+
+/*
+ *  These target side symbols define the beginning and ending addresses
+ *  of the section of shared memory used for messages. They are
+ *  defined in the *cfg.cmd file by cdb code.
+ */
+#define MSG_SHARED_BUFFER_BASE_SYM      "_MSG_BEG"
+#define MSG_SHARED_BUFFER_LIMIT_SYM     "_MSG_END"
+
+#ifndef _CHNL_WORDSIZE
+#define _CHNL_WORDSIZE 4	/* default _CHNL_WORDSIZE is 2 bytes/word */
+#endif
+
+/*
+ *  ======== MSG ========
+ *  There is a control structure for messages to the DSP, and a control
+ *  structure for messages from the DSP. The shared memory region for
+ *  transferring messages is partitioned as follows:
+ *
+ *  ----------------------------------------------------------
+ *  |Control | Messages from DSP | Control | Messages to DSP |
+ *  ----------------------------------------------------------
+ *
+ *  MSG control structure for messages to the DSP is used in the following
+ *  way:
+ *
+ *  bufEmpty -      This flag is set to FALSE by the GPP after it has output
+ *                  messages for the DSP. The DSP host driver sets it to
+ *                  TRUE after it has copied the messages.
+ *  postSWI -       Set to 1 by the GPP after it has written the messages,
+ *                  set the size, and set bufEmpty to FALSE.
+ *                  The DSP Host driver uses SWI_andn of the postSWI field
+ *                  when a host interrupt occurs. The host driver clears
+ *                  this after posting the SWI.
+ *  size -          Number of messages to be read by the DSP.
+ *
+ *  For messages from the DSP:
+ *  bufEmpty -      This flag is set to FALSE by the DSP after it has output
+ *                  messages for the GPP. The DPC on the GPP sets it to
+ *                  TRUE after it has copied the messages.
+ *  postSWI -       Set to 1 the DPC on the GPP after copying the messages.
+ *  size -          Number of messages to be read by the GPP.
+ */
+struct MSG {
+	SMWORD bufEmpty;	/* to/from DSP buffer is empty */
+	SMWORD postSWI;	/* Set to "1" to post MSG SWI */
+	SMWORD size;	/* Number of messages to/from the DSP */
+	SMWORD resvd;
+} ;
+
+/*
+ *  ======== MSG_MGR ========
+ *  The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
+ *  have MSG_QUEUE to hold all messages that come up from the corresponding
+ *  node on the DSP. The MSG_MGR also has a shared queue of messages
+ *  ready to go to the DSP.
+ */
+struct MSG_MGR {
+	/* The first two fields must match those in msgobj.h */
+	u32 dwSignature;
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD. */
+
+	struct IO_MGR *hIOMgr;	/* IO manager */
+	struct LST_LIST *queueList;	/* List of MSG_QUEUEs */
+	struct SYNC_CSOBJECT *hSyncCS;	/* For critical sections */
+	/* Signalled when MsgFrame is available */
+	struct SYNC_OBJECT *hSyncEvent;
+	struct LST_LIST *msgFreeList;	/* Free MsgFrames ready to be filled */
+	struct LST_LIST *msgUsedList;	/* MsgFrames ready to go to DSP */
+	u32 uMsgsPending;	/* # of queued messages to go to DSP */
+	u32 uMaxMsgs;	/* Max # of msgs that fit in buffer */
+	MSG_ONEXIT onExit;	/* called when RMS_EXIT is received */
+} ;
+
+/*
+ *  ======== MSG_QUEUE ========
+ *  Each NODE has a MSG_QUEUE for receiving messages from the
+ *  corresponding node on the DSP. The MSG_QUEUE object maintains a list
+ *  of messages that have been sent to the host, but not yet read (MSG_Get),
+ *  and a list of free frames that can be filled when new messages arrive
+ *  from the DSP.
+ *  The MSG_QUEUE's hSynEvent gets posted when a message is ready.
+ */
+struct MSG_QUEUE {
+	struct LST_ELEM listElem;
+	u32 dwSignature;
+	struct MSG_MGR *hMsgMgr;
+	u32 uMaxMsgs;	/* Node message depth */
+	u32 dwId;	/* Node environment pointer */
+	struct LST_LIST *msgFreeList;	/* Free MsgFrames ready to be filled */
+	/* Filled MsgFramess waiting to be read */
+	struct LST_LIST *msgUsedList;
+	HANDLE hArg;	/* Handle passed to mgr onExit callback */
+	struct SYNC_OBJECT *hSyncEvent;	/* Signalled when message is ready */
+	struct SYNC_OBJECT *hSyncDone;	/* For synchronizing cleanup */
+	struct SYNC_OBJECT *hSyncDoneAck;	/* For synchronizing cleanup */
+	struct NTFY_OBJECT *hNtfy;	/* For notification of message ready */
+	bool fDone;	/* TRUE <==> deleting the object */
+	u32 refCount;	/* Number of pending MSG_get/put calls */
+};
+
+/*
+ *  ======== MSG_DSPMSG ========
+ */
+struct MSG_DSPMSG {
+	struct DSP_MSG msg;
+	u32 dwId;	/* Identifies the node the message goes to */
+} ;
+
+/*
+ *  ======== MSG_FRAME ========
+ */
+struct MSG_FRAME {
+	struct LST_ELEM listElem;
+	struct MSG_DSPMSG msgData;
+} ;
+
+#endif				/* _MSG_SM_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
new file mode 100644
index 0000000..4f2b43c
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap.h
@@ -0,0 +1,400 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_tiomap.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== _tiomap.h ========
+ *  Description:
+ *      Definitions and types private to this WMD.
+ *
+ *! Revision History
+ *! ================
+ *! 12-Apr-2004 hp:  Removed the L4 entry of Dsp DMA , not needed
+ *! 08-Mar-2004 sb:  Added the Dynamic Memory Mapping feature - PgTableAttrs
+ *! 21-Mar-2003 sb:  Added numTLBEntries to struct WMD_DEV_CONTEXT
+ *! 20-Feb-2003 vp:  Ported to Linux platform.
+ *! 30-Jul-2002 rr:  Modified TBC_ID_VALUE to 0xb47002f.
+ *! 10-May-2002 sg:  Added ARM_SYSST_OFFSET and IDLE_DSP_MASK.
+ *! 14-Mar-2002 rr:  Added Boot vector field to pDevContext.
+ *!                  Added TBC Register defines and value for OMAP1510.
+ *! 12-Jan-2002 ag:  wIntrVal2Dsp Added.
+ *! 05-Nov-2001 kc:  Added MMU fault related definitions.
+ *! 03-Aug-2001 ag   Added TLB table for OEM cofig of DSP-MMU.
+ *! 23-Aug-2001 rr:  Added API_SIZE define.
+ *! 16-Aug-2001 rr:  Added dwDspExtBaseAddr to access the Ext memory.
+ *! 24-Jul-2001 ag:  Added Internal SRAM MMU table entry.
+ *! 27-Jun-2001 rr:  Name changed to _tihelen.h.
+ *! 27-Jun-2001 ag:  Added dwIntAddr in WMD_DEV_CONTEXT used for MB INTRs msk.
+ *! 07-May-2001 ag:  Added DSP Clock Module CLKM2.
+ *!                  Added TIHEL_SDRAMPHYSBASE used for DSP MMU init.
+ *!                  Added ClearBit() MACRO.
+ *! 18-Jan-2001 rr:  Created
+ */
+
+#ifndef _TIOMAP_
+#define _TIOMAP_
+
+#include <devdefs.h>
+#include <hw_defs.h>
+#include <hw_mbox.h>
+#include <wmdioctl.h>		/* for WMDIOCTL_EXTPROC defn */
+#include "sync.h"
+#include "clk.h"
+
+struct MAP_L4PERIPHERAL {
+	u32 physAddr;
+	u32 dspVirtAddr;
+} ;
+
+#define ARM_MAILBOX_START               0xfffcf000
+#define ARM_MAILBOX_LENGTH              0x800
+
+/* New Registers in OMAP3.1 */
+
+#define TESTBLOCK_ID_START              0xfffed400
+#define TESTBLOCK_ID_LENGTH             0xff
+
+/* ID Returned by OMAP1510 */
+#define TBC_ID_VALUE                    0xB47002F
+
+#define SPACE_LENGTH                    0x2000
+#define API_CLKM_DPLL_DMA               0xfffec000
+#define ARM_INTERRUPT_OFFSET            0xb00
+
+#define BIOS_24XX
+
+#define L4_PERIPHERAL_NULL          0x0
+#define DSPVA_PERIPHERAL_NULL       0x0
+
+#define MAX_LOCK_TLB_ENTRIES 15
+
+#define L4_PERIPHERAL_PRM        0x48306000  /*PRM L4 Peripheral */
+#define DSPVA_PERIPHERAL_PRM     0x1181e000
+#define L4_PERIPHERAL_SCM        0x48002000  /*SCM L4 Peripheral */
+#define DSPVA_PERIPHERAL_SCM     0x1181f000
+#define L4_PERIPHERAL_MMU        0x5D000000  /*MMU L4 Peripheral */
+#define DSPVA_PERIPHERAL_MMU     0x11820000
+#define L4_PERIPHERAL_CM        0x48004000       /* Core L4, Clock Management */
+#define DSPVA_PERIPHERAL_CM     0x1181c000
+#define L4_PERIPHERAL_PER        0x48005000       /*  PER */
+#define DSPVA_PERIPHERAL_PER     0x1181d000
+
+#define L4_PERIPHERAL_GPIO1       0x48310000
+#define DSPVA_PERIPHERAL_GPIO1    0x11809000
+#define L4_PERIPHERAL_GPIO2       0x49050000
+#define DSPVA_PERIPHERAL_GPIO2    0x1180a000
+#define L4_PERIPHERAL_GPIO3       0x49052000
+#define DSPVA_PERIPHERAL_GPIO3    0x1180b000
+#define L4_PERIPHERAL_GPIO4       0x49054000
+#define DSPVA_PERIPHERAL_GPIO4    0x1180c000
+#define L4_PERIPHERAL_GPIO5       0x49056000
+#define DSPVA_PERIPHERAL_GPIO5    0x1180d000
+
+#define L4_PERIPHERAL_IVA2WDT      0x49030000
+#define DSPVA_PERIPHERAL_IVA2WDT   0x1180e000
+
+#define L4_PERIPHERAL_DISPLAY     0x48050000
+#define DSPVA_PERIPHERAL_DISPLAY  0x1180f000
+
+#define L4_PERIPHERAL_SSI         0x48058000
+#define DSPVA_PERIPHERAL_SSI      0x11804000
+#define L4_PERIPHERAL_GDD         0x48059000
+#define DSPVA_PERIPHERAL_GDD      0x11805000
+#define L4_PERIPHERAL_SS1         0x4805a000
+#define DSPVA_PERIPHERAL_SS1      0x11806000
+#define L4_PERIPHERAL_SS2         0x4805b000
+#define DSPVA_PERIPHERAL_SS2      0x11807000
+
+#define L4_PERIPHERAL_CAMERA      0x480BC000
+#define DSPVA_PERIPHERAL_CAMERA   0x11819000
+
+#define L4_PERIPHERAL_SDMA        0x48056000
+#define DSPVA_PERIPHERAL_SDMA     0x11810000 /*0x1181d000 conflicts with PER */
+
+#define L4_PERIPHERAL_UART1             0x4806a000
+#define DSPVA_PERIPHERAL_UART1          0x11811000
+#define L4_PERIPHERAL_UART2             0x4806c000
+#define DSPVA_PERIPHERAL_UART2          0x11812000
+#define L4_PERIPHERAL_UART3             0x49020000
+#define DSPVA_PERIPHERAL_UART3    0x11813000
+
+#define L4_PERIPHERAL_MCBSP1      0x48074000
+#define DSPVA_PERIPHERAL_MCBSP1   0x11814000
+#define L4_PERIPHERAL_MCBSP2      0x49022000
+#define DSPVA_PERIPHERAL_MCBSP2   0x11815000
+#define L4_PERIPHERAL_MCBSP3      0x49024000
+#define DSPVA_PERIPHERAL_MCBSP3   0x11816000
+#define L4_PERIPHERAL_MCBSP4      0x49026000
+#define DSPVA_PERIPHERAL_MCBSP4   0x11817000
+#define L4_PERIPHERAL_MCBSP5      0x48096000
+#define DSPVA_PERIPHERAL_MCBSP5   0x11818000
+
+#define L4_PERIPHERAL_GPTIMER5    0x49038000
+#define DSPVA_PERIPHERAL_GPTIMER5 0x11800000
+#define L4_PERIPHERAL_GPTIMER6    0x4903a000
+#define DSPVA_PERIPHERAL_GPTIMER6 0x11801000
+#define L4_PERIPHERAL_GPTIMER7    0x4903c000
+#define DSPVA_PERIPHERAL_GPTIMER7 0x11802000
+#define L4_PERIPHERAL_GPTIMER8    0x4903e000
+#define DSPVA_PERIPHERAL_GPTIMER8 0x11803000
+
+#define L4_PERIPHERAL_SPI1      0x48098000
+#define DSPVA_PERIPHERAL_SPI1   0x1181a000
+#define L4_PERIPHERAL_SPI2      0x4809a000
+#define DSPVA_PERIPHERAL_SPI2   0x1181b000
+
+#define L4_PERIPHERAL_MBOX        0x48094000
+#define DSPVA_PERIPHERAL_MBOX     0x11808000
+
+#define PM_GRPSEL_BASE 			0x48307000
+#define DSPVA_GRPSEL_BASE 		0x11821000
+
+/* define a static array with L4 mappings */
+static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
+	{L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX},
+	{L4_PERIPHERAL_SCM, DSPVA_PERIPHERAL_SCM},
+	{L4_PERIPHERAL_MMU, DSPVA_PERIPHERAL_MMU},
+	{L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5},
+	{L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6},
+	{L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7},
+	{L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8},
+	{L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1},
+	{L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2},
+	{L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3},
+	{L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4},
+	{L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5},
+	{L4_PERIPHERAL_IVA2WDT, DSPVA_PERIPHERAL_IVA2WDT},
+	{L4_PERIPHERAL_DISPLAY, DSPVA_PERIPHERAL_DISPLAY},
+	{L4_PERIPHERAL_SSI, DSPVA_PERIPHERAL_SSI},
+	{L4_PERIPHERAL_GDD, DSPVA_PERIPHERAL_GDD},
+	{L4_PERIPHERAL_SS1, DSPVA_PERIPHERAL_SS1},
+	{L4_PERIPHERAL_SS2, DSPVA_PERIPHERAL_SS2},
+	{L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1},
+	{L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2},
+	{L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3},
+	{L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1},
+	{L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2},
+	{L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3},
+	{L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4},
+	{L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5},
+	{L4_PERIPHERAL_CAMERA, DSPVA_PERIPHERAL_CAMERA},
+	{L4_PERIPHERAL_SPI1, DSPVA_PERIPHERAL_SPI1},
+	{L4_PERIPHERAL_SPI2, DSPVA_PERIPHERAL_SPI2},
+	{L4_PERIPHERAL_PRM, DSPVA_PERIPHERAL_PRM},
+	{L4_PERIPHERAL_CM, DSPVA_PERIPHERAL_CM},
+	{L4_PERIPHERAL_PER, DSPVA_PERIPHERAL_PER},
+	{PM_GRPSEL_BASE, DSPVA_GRPSEL_BASE},
+	{L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
+};
+
+/*
+ *   15         10                  0
+ *   ---------------------------------
+ *  |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
+ *  ---------------------------------
+ *  |  (class)  | (module specific) |
+ *
+ *  where  c -> Externel Clock Command: Clk & Autoidle Disable/Enable
+ *  i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
+ */
+
+/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
+#define MBX_PM_CLK_IDMASK   0x7F
+
+/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
+#define MBX_PM_CLK_CMDSHIFT 7
+
+/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
+#define MBX_PM_CLK_CMDMASK 7
+
+/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
+#define MBX_CORE1_RESOURCES 7
+
+/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
+#define MBX_CORE2_RESOURCES 1
+
+/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
+#define MBX_PM_MAX_RESOURCES 11
+
+/*  Power Management Commands */
+enum BPWR_ExtClockCmd {
+	BPWR_DisableClock = 0,
+	BPWR_EnableClock,
+	BPWR_DisableAutoIdle,
+	BPWR_EnableAutoIdle
+} ;
+
+/* OMAP242x specific resources */
+enum BPWR_ExtClockId {
+	BPWR_GPTimer5 = 0x10,
+	BPWR_GPTimer6,
+	BPWR_GPTimer7,
+	BPWR_GPTimer8,
+	BPWR_WDTimer3,
+	BPWR_MCBSP1,
+	BPWR_MCBSP2,
+	BPWR_MCBSP3,
+	BPWR_MCBSP4,
+	BPWR_MCBSP5,
+	BPWR_SSI = 0x20
+} ;
+
+static const u32 BPWR_CLKID[] = {
+	(u32) BPWR_GPTimer5,
+	(u32) BPWR_GPTimer6,
+	(u32) BPWR_GPTimer7,
+	(u32) BPWR_GPTimer8,
+	(u32) BPWR_WDTimer3,
+	(u32) BPWR_MCBSP1,
+	(u32) BPWR_MCBSP2,
+	(u32) BPWR_MCBSP3,
+	(u32) BPWR_MCBSP4,
+	(u32) BPWR_MCBSP5,
+	(u32) BPWR_SSI
+};
+
+struct BPWR_Clk_t {
+	u32 clkId;
+	enum SERVICES_ClkId funClk;
+	enum SERVICES_ClkId intClk;
+} ;
+
+static const struct BPWR_Clk_t BPWR_Clks[] = {
+	{(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
+	{(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
+	{(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
+	{(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
+	{(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
+	{(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
+	{(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
+	{(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
+	{(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
+	{(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
+	{(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
+};
+
+/* Interrupt Register Offsets */
+#define INTH_IT_REG_OFFSET              0x00	/* Interrupt register offset  */
+#define INTH_MASK_IT_REG_OFFSET         0x04	/* Mask Interrupt reg offset  */
+
+#define   DSP_MAILBOX1_INT              10
+
+/*
+ *  INTH_InterruptKind_t
+ *  Identify the kind of interrupt: either FIQ/IRQ
+ */
+enum INTH_InterruptKind_t {
+	INTH_IRQ = 0,
+	INTH_FIQ = 1
+} ;
+
+enum INTH_SensitiveEdge_t {
+	FALLING_EDGE_SENSITIVE = 0,
+	LOW_LEVEL_SENSITIVE = 1
+} ;
+
+/*
+ *  Bit definition of  Interrupt  Level  Registers
+ */
+
+/* Mail Box defines */
+#define MB_ARM2DSP1_REG_OFFSET          0x00
+
+#define MB_ARM2DSP1B_REG_OFFSET         0x04
+
+#define MB_DSP2ARM1B_REG_OFFSET         0x0C
+
+#define MB_ARM2DSP1_FLAG_REG_OFFSET     0x18
+
+#define MB_ARM2DSP_FLAG                 0x0001
+
+#define MBOX_ARM2DSP HW_MBOX_ID_0
+#define MBOX_DSP2ARM HW_MBOX_ID_1
+#define MBOX_ARM HW_MBOX_U0_ARM
+#define MBOX_DSP HW_MBOX_U1_DSP1
+
+#define ENABLE                          true
+#define DISABLE                         false
+
+#define HIGH_LEVEL                      true
+#define LOW_LEVEL                       false
+
+/* Macro's */
+#define REG16(A)    (*(REG_UWORD16 *)(A))
+
+#define ClearBit(reg, mask)             (reg &= ~mask)
+#define SetBit(reg, mask)               (reg |= mask)
+
+#define SetGroupBits16(reg, position, width, value) \
+	do {\
+		reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
+		reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
+	} while (0);
+
+#define ClearBitIndex(reg, index)   (reg &= ~(1 << (index)))
+
+/* This mini driver's device context: */
+struct WMD_DEV_CONTEXT {
+	struct DEV_OBJECT *hDevObject;	/* Handle to WCD device object. */
+	u32 dwDspBaseAddr;	/* Arm's API to DSP virtual base addr */
+	/*
+	 * DSP External memory prog address as seen virtually by the OS on
+	 * the host side.
+	 */
+	u32 dwDspExtBaseAddr;	/* See the comment above        */
+	u32 dwAPIRegBase;	/* API memory mapped registers  */
+	u32 dwDSPMmuBase;	/* DSP MMU Mapped registers     */
+	u32 dwMailBoxBase;	/* Mail box mapped registers    */
+	u32 dwAPIClkBase;	/* CLK Registers                */
+	u32 dwDSPClkM2Base;	/* DSP Clock Module m2          */
+	u32 dwPublicRhea;	/* Pub Rhea                     */
+	u32 dwIntAddr;	/* MB INTR reg                  */
+	u32 dwTCEndianism;	/* TC Endianism register        */
+	u32 dwTestBase;	/* DSP MMU Mapped registers     */
+	u32 dwSelfLoop;	/* Pointer to the selfloop      */
+	u32 dwDSPStartAdd;	/* API Boot vector              */
+	u32 dwInternalSize;	/* Internal memory size         */
+
+	/*
+	 * Processor specific info is set when prog loaded and read from DCD.
+	 * [See WMD_BRD_Ctrl()]  PROC info contains DSP-MMU TLB entries.
+	 */
+	/* DMMU TLB entries */
+	struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
+	u32 dwBrdState;	/* Last known board state.      */
+	u32 ulIntMask;	/* int mask                     */
+	u16 ioBase;	/* Board I/O base               */
+	u16 wIntrVal2Dsp;	/* MBX value to DSP. See mbx_sh.h */
+	u32 numTLBEntries;	/* DSP MMU TLB entry counter    */
+	u32 fixedTLBEntries;	/* Fixed DSPMMU TLB entry count */
+
+	/* TC Settings */
+	bool tcWordSwapOn;	/* Traffic Controller Word Swap */
+	struct PgTableAttrs *pPtAttrs;
+	u32 uDspPerClks;
+} ;
+
+	/*
+	 * ======== WMD_TLB_DspVAToMpuPA ========
+	 *     Given a DSP virtual address, traverse the page table and return
+	 *     a corresponding MPU physical address and size.
+	 */
+extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
+				       IN u32 ulVirtAddr,
+				       OUT u32 *ulPhysAddr,
+				       OUT u32 *sizeTlb);
+
+#endif				/* _TIOMAP_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap_api.h b/drivers/dsp/bridge/wmd/_tiomap_api.h
new file mode 100644
index 0000000..52986de
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_api.h
@@ -0,0 +1,182 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_tiomap_api.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_api.h ========
+ *  Description:
+ *      Definitions, types and function prototypes for the API module.
+ *
+ *! Revision History
+ *! ================
+ *! 27-Mar-2003 vp:  Updated for Power Management
+ *!		     - Added setAPI function
+ *!		     - Added API_DSP_BOOT_IDLE enumeration
+ *!		     - Modified setDSPBootMode function to take boot mode option
+ *! 19-Feb-2003 vp:  Ported to Linux platform.
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_API_
+#define _TIOMAP_API_
+
+/* I/O ARM Memory Mapping and ARM Peripheral mapping */
+#define ARM_API_START                   0xfffec900
+#define ARM_API_LENGTH                  0xff
+
+/* API I/F Registers */
+#define API_CTRL_OFFSET                 0x0000	/* 32 bit control register   */
+#define API_STATUS_OFFSET               0x0010	/* 16 bit status register(RO) */
+#define API_DSP_STATUS_OFFSET           0x0014	/* 16 bit DSP status register */
+#define API_DSP_BOOT_OFFSET             0x0018	/* 16 bit Boot configuration
+						 * register
+						 */
+#define API_SIZE                        0x001c
+#define API_DSP_API_OFFSET              0x0020	/* 16 bit API Configuration
+						 * register
+						 */
+
+/* API_DSP_STATUS_REG related */
+#define API_DSP_STATUS_HOM_MODE         0x0c00	/* HOM Mode bits - set if HOM */
+
+/* SAM/HOM bit in API_DSP_STATUS register value */
+#define SAM_BIT                         0x0400
+
+/*  Define position bit fields */
+#define API_HIGH_FREQ_POSBIT            0
+#define API_TIMEOUT_EN_POSBIT           1
+#define API_API_ERR_EN_POSBIT           3
+#define API_ACCESS_FACTOR_POSBIT        4
+#define API_TIMEOUT_POSBIT              8
+#define API_ENDIANISM_POSBIT            16
+#define API_ACCESS_PRIORITY_POSBIT      18
+
+typedef enum {
+	API_HIGH_FREQ_LOW = 0,
+	API_HIGH_FREQ_HIGH = 1
+} API_HighFreq_t;
+
+typedef enum {
+	API_TIMEOUT_DIS = 0,
+	API_TIMEOUT_EN = 1
+} API_TimeoutEn_t;
+
+typedef enum {
+	API_API_ERR_DIS = 0,
+	API_API_ERR_EN = 1
+} API_ApiErrEn_t;
+
+typedef enum {
+	API_ACCESS_FACTOR_0 = 0,
+	API_ACCESS_FACTOR_1,
+	API_ACCESS_FACTOR_2,
+	API_ACCESS_FACTOR_3,
+	API_ACCESS_FACTOR_4,
+	API_ACCESS_FACTOR_5,
+	API_ACCESS_FACTOR_6,
+	API_ACCESS_FACTOR_7,
+	API_ACCESS_FACTOR_8,
+	API_ACCESS_FACTOR_9,
+	API_ACCESS_FACTOR_10,
+	API_ACCESS_FACTOR_11,
+	API_ACCESS_FACTOR_12,
+	API_ACCESS_FACTOR_13,
+	API_ACCESS_FACTOR_14,
+	API_ACCESS_FACTOR_15
+} API_AccessFactor_t;
+
+typedef enum {
+	API_TIMEOUT_MIN = 0,
+	API_TIMEOUT_MAX = 255
+} API_Timeout_t;
+
+typedef enum {
+	API_ENDIANISM_NO_CONVERT = 0,
+	API_ENDIANISM_CONVERT_ALL_ACCESS = 2,
+	API_ENDIANISM_CONVERT_API_MEM_ONLY = 3
+} API_Endianism_t;
+
+typedef enum {
+	API_ACCESS_PRIORITY_ARM_DMA_HSAB = 0,
+	API_ACCESS_PRIORITY_ARM_HSAB_DMA,
+	API_ACCESS_PRIORITY_DMA_ARM_HSAB,
+	API_ACCESS_PRIORITY_HSAB_ARM_DMA,
+	API_ACCESS_PRIORITY_DMA_HSAB_ARM,
+	API_ACCESS_PRIORITY_HSAB_DMA_ARM
+} API_AccessPriority_t;
+
+typedef enum {
+	API_DSP_BOOT_INTERNAL = 5,
+	API_DSP_BOOT_EXTERNAL = 4,
+	API_DSP_BOOT_EMIF16 = 3,
+	API_DSP_BOOT_IDLE = 2,
+	API_DSP_BOOT_PSEUDO_EXT = 1,
+	API_DSP_BOOT_MPNMC = 0
+} API_DSPBootMode_t;
+
+/* Function prototypes */
+
+/*
+ *  ======== setAPIsize ========
+ *  Configures the SARAM blocks which can be accessed in the HOM mode
+ *  Register 0xfffe:c900 offset 0x1c.
+ */
+extern void setAPIsize(struct WMD_DEV_CONTEXT *pDevContext, u16 size);
+
+/*
+ *  ======== setDspBootModeAPI ========
+ *  Sets up the DSP boot mode
+ *  Register 0xfffe:c900 offset 18.
+ *  Boot mode is set API_DSP_BOOT_INTERNAL; DSP will start executing from
+ *  SARAM location 0x10000 byte address.
+ */
+extern void setDspBootModeAPI(struct WMD_DEV_CONTEXT *pDevContext,
+			      API_DSPBootMode_t dsp_boot_mode);
+
+/*
+ *  ======== setAPI ========
+ *  Configures the API interface.
+ *  Register 0xfffe:c900 offset 0x0.
+ *      -   Set the API access priority to ARM-DMA-HSAB
+ *      -   Sets the no byte swap
+ *      -   Time out is set to MAX
+ *      -   Access factor is 4
+ *      -   Enable the time out
+ *      -   Set it to high frequency mode
+ */
+extern void setAPI(struct WMD_DEV_CONTEXT *pDevContext,
+		   API_HighFreq_t high_freq,
+		   API_TimeoutEn_t timeout_en,
+		   API_ApiErrEn_t api_err_en,
+		   API_AccessFactor_t access_factor,
+		   API_Timeout_t timeout,
+		   API_Endianism_t endianism,
+		   API_AccessPriority_t access_priority);
+
+/*
+ *  ======== setupAPI ========
+ *  Configures the API interface.
+ *  Register 0xfffe:c900 offset 0x0.
+ *      -   Set the API access priority to ARM-DMA-HSAB
+ *      -   Sets the no byte swap
+ *      -   Time out is set to MAX
+ *      -   Access factor is 4
+ *      -   Enable the time out
+ *      -   Set it to high frequency mode
+ */
+extern void setupAPI(struct WMD_DEV_CONTEXT *pDevContext);
+
+#endif				/* _TIOMAP_API_ */
diff --git a/drivers/dsp/bridge/wmd/_tiomap_clk.h b/drivers/dsp/bridge/wmd/_tiomap_clk.h
new file mode 100644
index 0000000..cb5c685
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_clk.h
@@ -0,0 +1,123 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_tiomap_clk.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_clk.h ========
+ *  Description:
+ *      Definitions and types for the CLOCK and RESET modules. This
+ *  includes enabling/disabling peripheral clocks,reseting and releasing
+ *  the DSP.
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_CLK_
+#define _TIOMAP_CLK_
+
+#include "_tiomap.h"
+
+/* ARM CLK Module */
+#define ARM_CLKM_START                  0xfffece00
+#define ARM_CLKM_LENGTH                 0xff
+#define ARM_SYSST_OFFSET                0x18
+#define IDLE_DSP_MASK                   0x40
+
+/* DSP CLK Module */
+#define DSP_CLKM2_BASE                  0xe1008000
+#define DSP_CLKM2_LENGTH                0xff
+#define DSP_IDLECT2_OFFSET              0x8	/* Clock domain control */
+
+/* CLK related defines */
+/*  ARM_CKCTL */
+#define ARM_CKCTL_OFFEST                0x0
+
+#define EN_DSPCK_POS                    13
+#define EN_DSPCK_NUMB                   1
+
+/*  ARM_RSTCT1 */
+#define ARM_RSTCT1_OFFSET               0x10
+
+#define DSP_RST_POS                     2
+#define DSP_RST_NUMB                    1
+#define DSP_EN_POS                      1
+#define DSP_EN_NUMB                     1
+
+/*  ARM_IDLECT2 */
+#define ARM_IDLECT2_OFFSET              0x8
+
+#define EN_APICK_POS                    6
+#define EN_APICK_NUMB                   1
+
+/* Function prototypes */
+/*
+ *  ======== dspPeripheralClockDisable ========
+ *  Disables the clock for the DSP external periperal clock (DSPPER_CK)
+ *  Register 0xe100:8000 offset 0x8 bit position 1 is set to zero.
+ */
+extern void dspPeripheralClockDisable(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ *  ======== dspPeripheralClockEnable ========
+ * Enables the clock for DSP external refernce clock, periperal clock, USART clk
+ *  GPIO clk and GPIO peripheral clock.
+ *  Register 0xe100:8000 offset 0x8 bit position 0,1,2,3,4 and 5 are set to 1.
+ */
+extern void dspPeripheralClockEnable(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ *  ======== releaseDSP ========
+ *  Releases the DSP from reset. Th DSP starts running.from whatever
+ *  boot mode is set to. If it is set to internal boot mode, the DSP
+ *  starts executing from location 0x10000 byte address.
+ *  0xfffe:ce00 bit postion 1 is set to one.
+ */
+extern DSP_STATUS releaseDSP(struct WMD_DEV_CONTEXT *pDevContext,
+			     BOOL fCheckForSAM);
+
+/*
+ *  ======== releaseDspInterFace ========
+ *  Enables the pritoiry registers, EMIF configuration registers and
+ *  the API control logic in the DSP subsystem so that they can be programmed.
+ *  0xfffe:ce00 bit postion 2 is set to one.
+ */
+extern void releaseDSPInterface(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ *  ======== resetDSP ========
+ *  Resets the DSP. This stops the DSP from running.
+ *  0xfffe:ce00 bit postion 1 is set to zero
+ */
+extern void resetDSP(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ *  ======== resetDSPInterface ========
+ *  Resets the pritoiry registers, EMIF configuration registers and
+ *  the API control logic in the DSP subsystem. This is required to configure
+ *  the API and MMU.
+ *  0xfffe:ce00 bit postion 2 is set to zero.
+ */
+extern void resetDSPInterface(struct WMD_DEV_CONTEXT *pDevContext);
+
+ /*
+  *  ======== setTCEndianism =========
+  *  Sets the endianism register.
+  */
+extern void setTCEndianism(struct WMD_DEV_CONTEXT *pDevContext, u32 value);
+
+#endif				/* _TIOMAP_CLK_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
new file mode 100644
index 0000000..72e1631
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
@@ -0,0 +1,53 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/2430/_tiomap_mmu.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_mmu.h ========
+ *  Description:
+ *      Definitions and types for the DSP MMU modules
+ *
+ *! Revision History
+ *! ================
+ *! 19-Apr-2004 sb:  Renamed HW types. Removed dspMmuTlbEntry
+ *! 05-Jan-2004 vp:  Moved the file to a platform specific folder from common.
+ *! 21-Mar-2003 sb:  Added macro definition TIHEL_LARGEPAGESIZE
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_MMU_
+#define _TIOMAP_MMU_
+
+#include "_tiomap.h"
+
+/*
+ *  ======== configureDspMmu ========
+ *
+ *  Make DSP MMu page table entries.
+ *  Note: Not utilizing Coarse / Fine page tables.
+ *  SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
+ *  DSP Byte address 0x40_0000 is word addr 0x20_0000.
+ */
+extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
+			    u32 dataBasePhys,
+			    u32 dspBaseVirt,
+			    u32 sizeInBytes,
+			    s32 nEntryStart,
+			    enum HW_Endianism_t endianism,
+			    enum HW_ElementSize_t elemSize,
+			    enum HW_MMUMixedSize_t mixedSize);
+
+#endif				/* _TIOMAP_MMU_ */
diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
new file mode 100644
index 0000000..697097e
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
@@ -0,0 +1,82 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_tiomap_pwr.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_pwr.h ========
+ *  Description:
+ *      Definitions and types for the DSP wake/sleep routines.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_PWR_
+#define _TIOMAP_PWR_
+
+/* Wait time between MBX and IDLE checks for PWR */
+#define PWR_WAIT_USECS          500
+#define PWR_WAIT_MSECS          50
+
+/*
+ * ======== WakeDSP =========
+ * Wakes up the DSP from DeepSleep
+ */
+extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+
+/*
+ * ======== SleepDSP =========
+ * Places the DSP in DeepSleep.
+ */
+extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
+			   IN u32 dwCmd, IN void *pArgs);
+/*
+ *  ========InterruptDSP========
+ *  	  Sends an interrupt to DSP unconditionally.
+ */
+extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
+
+/*
+ * ======== WakeDSP =========
+ * Wakes up the DSP from DeepSleep
+ */
+extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
+				       IN void *pArgs);
+/*
+ *  ======== handle_hibernation_fromDSP ========
+ *  	Handle Hibernation requested from DSP
+ */
+DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
+/*
+ *  ======== PostScale_DSP ========
+ *  	Handle Post Scale notification to DSP
+ */
+DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+/*
+ *  ======== PreScale_DSP ========
+ *  	Handle Pre Scale notification to DSP
+ */
+DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
+/*
+ *  ======== handle_constraints_set ========
+ *  	Handle constraints request from DSP
+ */
+DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
+				 IN void *pArgs);
+
+#endif				/* _TIOMAP_PWR_ */
+
diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
new file mode 100644
index 0000000..52c4b9d
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
@@ -0,0 +1,47 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/_tiomap_util.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_util.h ========
+ *  Description:
+ *      Definitions and types for the utility routines.
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_UTIL_
+#define _TIOMAP_UTIL_
+
+/* Time out Values in uSeconds*/
+#define TIHELEN_ACKTIMEOUT  10000
+#define TIHELEN_WRITE_DELAY 10
+
+/*  Time delay for HOM->SAM transition. */
+#define  WAIT_SAM   1000000	/* in usec (1000 millisec) */
+
+/*
+ *  ======== WaitForStart ========
+ *  Wait for the singal from DSP that it has started, or time out.
+ *  The argument dwSyncAddr is set to 1 before releasing the DSP.
+ *  If the DSP starts running, it will clear this location.
+ */
+extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
+
+#endif				/* _TIOMAP_UTIL_ */
+
diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
new file mode 100644
index 0000000..12193ba
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/chnl_sm.c
@@ -0,0 +1,1101 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/wmdchnl/common/chnl_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== chnl_sm.c ========
+ *  Description:
+ *      Implements upper edge functions for WMD channel module.
+ *
+ *  Public Functions:
+ *      WMD_CHNL_AddIOReq
+ *      WMD_CHNL_CancelIO
+ *      WMD_CHNL_Close
+ *      WMD_CHNL_Create
+ *      WMD_CHNL_Destroy
+ *      WMD_CHNL_FlushIO
+ *      WMD_CHNL_GetInfo
+ *      WMD_CHNL_GetIOC
+ *      WMD_CHNL_GetMgrInfo
+ *      WMD_CHNL_Idle
+ *      WMD_CHNL_Open
+ *
+ *  Notes:
+ *      The lower edge functions must be implemented by the WMD writer, and
+ *      are declared in chnl_sm.h.
+ *
+ *      Care is taken in this code to prevent simulataneous access to channel
+ *      queues from
+ *      1. Threads.
+ *      2. IO_DPC(), scheduled from the IO_ISR() as an event.
+ *
+ *      This is done primarily by:
+ *      - Semaphores.
+ *      - state flags in the channel object; and
+ *      - ensuring the IO_Dispatch() routine, which is called from both
+ *        CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
+ *
+ *  Channel Invariant:
+ *      There is an important invariant condition which must be maintained per
+ *      channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
+ *      which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
+ *      This invariant condition is:
+ *
+ *          LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
+ *      and
+ *          !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
+ *
+ *! Revision History:
+ *! ================
+ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
+ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
+ *! 23-Apr-2003 sb: Fixed mailbox deadlock
+ *! 24-Feb-2003 vp: Code Review Updates.
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 29-Aug-2002 rr  Changed the SYNC error code return to DSP error code return
+ *            in WMD_CHNL_GetIOC.
+ *! 22-Jan-2002 ag  Zero-copy support added.
+ *!                 CMM_CallocBuf() used for SM allocations.
+ *! 04-Feb-2001 ag  DSP-DMA support added.
+ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
+ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
+ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
+ *!                 WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
+ *!                 Remove #ifdef DEBUG from around channel cIOCs field.
+ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
+ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
+ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
+ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
+ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
+ *! 20-Jan-2000 ag: Incorporated code review comments.
+ *! 05-Jan-2000 ag: Text format cleanup.
+ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
+ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
+ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
+ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
+ *!                 SM addrs taken from COFF(IO) or host resource(SM).
+ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
+ *!                 address and length from symbols defined in the currently
+ *!                 loaded COFF file. See _chn_sm.h.
+ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
+ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
+ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
+ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
+ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
+ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
+ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
+ *!                 of the SHM window length reported by Windows CM.
+ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
+ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
+ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
+ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
+ *! 14-Jan-1997 gp: Updated based on code review feedback.
+ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
+ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
+ *! 13-Sep-1996 gp: Added performance statistics for channel.
+ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
+ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
+ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
+ *! 17-Jul-1996 gp: Started pseudo coding.
+ *! 11-Jul-1996 gp: Stubbed out.
+ */
+
+/*  ----------------------------------- OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <mem.h>
+#include <cfg.h>
+#include <csl.h>
+#include <prcs.h>
+#include <sync.h>
+
+/*  ----------------------------------- Mini-Driver */
+#include <wmd.h>
+#include <wmdchnl.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+
+/*  ----------------------------------- Others */
+#include <io_sm.h>
+
+/*  ----------------------------------- Define for This */
+#define USERMODE_ADDR   PAGE_OFFSET
+
+#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
+
+/*  ----------------------------------- Function Prototypes */
+static struct LST_LIST *CreateChirpList(u32 uChirps);
+
+static void FreeChirpList(struct LST_LIST *pList);
+
+static struct CHNL_IRP *MakeNewChirp(void);
+
+static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
+				   OUT u32 *pdwChnl);
+
+/*
+ *  ======== WMD_CHNL_AddIOReq ========
+ *      Enqueue an I/O request for data transfer on a channel to the DSP.
+ *      The direction (mode) is specified in the channel object. Note the DSP
+ *      address is specified for channels opened in direct I/O mode.
+ */
+DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
+			    u32 cBytes, u32 cBufSize,
+			    OPTIONAL u32 dwDspAddr, u32 dwArg)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+	struct CHNL_IRP *pChirp = NULL;
+	u32 dwState;
+	bool fIsEOS;
+	struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
+	u8 *pHostSysBuf = NULL;
+	bool fSchedDPC = false;
+	u16 wMbVal = 0;
+
+	DBG_Trace(DBG_ENTER,
+		  "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
+		  "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
+		  pChnl->uChnlType, pChnl->uId);
+
+	fIsEOS = (cBytes == 0) ? true : false;
+
+	if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
+		if (!(pHostBuf < (void *)USERMODE_ADDR)) {
+			pHostSysBuf = pHostBuf;
+			goto func_cont;
+		}
+		/* if addr in user mode, then copy to kernel space */
+		pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
+		if (pHostSysBuf == NULL) {
+			status = DSP_EMEMORY;
+			DBG_Trace(DBG_LEVEL7,
+				 "No memory to allocate kernel buffer\n");
+			goto func_cont;
+		}
+		if (CHNL_IsOutput(pChnl->uMode)) {
+			status = copy_from_user(pHostSysBuf, pHostBuf,
+						cBufSize);
+			if (status) {
+				DBG_Trace(DBG_LEVEL7,
+					 "Error copying user buffer to "
+					 "kernel, %d bytes remaining.\n",
+					 status);
+				MEM_Free(pHostSysBuf);
+				pHostSysBuf = NULL;
+				status = DSP_EPOINTER;
+			}
+		}
+	}
+func_cont:
+	/* Validate args:  */
+	if (pHostBuf == NULL) {
+		status = DSP_EPOINTER;
+	} else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
+		status = CHNL_E_NOEOS;
+	} else {
+		/* Check the channel state: only queue chirp if channel state
+		 * allows */
+		dwState = pChnl->dwState;
+		if (dwState != CHNL_STATEREADY) {
+			if (dwState & CHNL_STATECANCEL) {
+				status = CHNL_E_CANCELLED;
+			} else if ((dwState & CHNL_STATEEOS)
+				   && CHNL_IsOutput(pChnl->uMode)) {
+				status = CHNL_E_EOS;
+			} else {
+				/* No other possible states left: */
+				DBC_Assert(0);
+			}
+		}
+	}
+	/* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
+	 * channels. DPCCS is held to avoid race conditions with PCPY channels.
+	 * If DPC is scheduled in process context (IO_Schedule) and any
+	 * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
+	 * we disable ALL DPCs. We will try to disable ONLY IO DPC later.  */
+	SYNC_EnterCS(pChnlMgr->hCSObj);
+	disable_irq(MAILBOX_IRQ);
+	if (pChnl->uChnlType == CHNL_PCPY) {
+		/* This is a processor-copy channel. */
+		if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
+			/* Check buffer size on output channels for fit. */
+			if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
+				status = CHNL_E_BUFSIZE;
+
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Get a free chirp: */
+		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
+		if (pChirp == NULL)
+			status = CHNL_E_NOIORPS;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Enqueue the chirp on the chnl's IORequest queue: */
+		pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
+		if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
+			pChirp->pHostSysBuf = pHostSysBuf;
+
+		if (DSP_SUCCEEDED(status)) {
+			/* Note: for dma chans dwDspAddr contains dsp address
+			 * of SM buffer.*/
+			DBC_Assert(pChnlMgr->uWordSize != 0);
+			/* DSP address */
+			pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
+			pChirp->cBytes = cBytes;
+			pChirp->cBufSize = cBufSize;
+			/* Only valid for output channel */
+			pChirp->dwArg = dwArg;
+			pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
+					 CHNL_IOCSTATCOMPLETE);
+			LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
+				   pChirp);
+			pChnl->cIOReqs++;
+			DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
+			/* If end of stream, update the channel state to prevent
+			 * more IOR's: */
+			if (fIsEOS)
+				pChnl->dwState |= CHNL_STATEEOS;
+
+			{
+				/* Legacy DSM Processor-Copy */
+				DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
+				/* Request IO from the DSP */
+				IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
+					(CHNL_IsInput(pChnl->uMode) ?
+					IO_INPUT : IO_OUTPUT), &wMbVal);
+				fSchedDPC = true;
+			}
+		}
+	}
+	enable_irq(MAILBOX_IRQ);
+	SYNC_LeaveCS(pChnlMgr->hCSObj);
+	if (wMbVal != 0)
+		IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
+
+	if (fSchedDPC == true) {
+		/* Schedule a DPC, to do the actual data transfer: */
+		IO_Schedule(pChnlMgr->hIOMgr);
+	}
+	DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_CancelIO ========
+ *      Return all I/O requests to the client which have not yet been
+ *      transferred.  The channel's I/O completion object is
+ *      signalled, and all the I/O requests are queued as IOC's, with the
+ *      status field set to CHNL_IOCSTATCANCEL.
+ *      This call is typically used in abort situations, and is a prelude to
+ *      CHNL_Close();
+ */
+DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+	u32 iChnl = -1;
+	CHNL_MODE uMode;
+	struct CHNL_IRP *pChirp;
+	struct CHNL_MGR *pChnlMgr = NULL;
+
+	/* Check args: */
+	if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+		iChnl = pChnl->uId;
+		uMode = pChnl->uMode;
+		pChnlMgr = pChnl->pChnlMgr;
+	} else {
+		status = DSP_EHANDLE;
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	 /*  Mark this channel as cancelled, to prevent further IORequests or
+	 *  IORequests or dispatching.  */
+	SYNC_EnterCS(pChnlMgr->hCSObj);
+	pChnl->dwState |= CHNL_STATECANCEL;
+	if (LST_IsEmpty(pChnl->pIORequests))
+		goto func_cont;
+
+	if (pChnl->uChnlType == CHNL_PCPY) {
+		/* Indicate we have no more buffers available for transfer: */
+		if (CHNL_IsInput(pChnl->uMode)) {
+			IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
+		} else {
+			/* Record that we no longer have output buffers
+			 * available: */
+			pChnlMgr->dwOutputMask &= ~(1 << iChnl);
+		}
+	}
+	/* Move all IOR's to IOC queue:  */
+	while (!LST_IsEmpty(pChnl->pIORequests)) {
+		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
+		if (pChirp) {
+			pChirp->cBytes = 0;
+			pChirp->status |= CHNL_IOCSTATCANCEL;
+			LST_PutTail(pChnl->pIOCompletions,
+				   (struct LST_ELEM *)pChirp);
+			pChnl->cIOCs++;
+			pChnl->cIOReqs--;
+			DBC_Assert(pChnl->cIOReqs >= 0);
+		}
+	}
+func_cont:
+		SYNC_LeaveCS(pChnlMgr->hCSObj);
+func_end:
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_Close ========
+ *  Purpose:
+ *      Ensures all pending I/O on this channel is cancelled, discards all
+ *      queued I/O completion notifications, then frees the resources allocated
+ *      for this channel, and makes the corresponding logical channel id
+ *      available for subsequent use.
+ */
+DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
+{
+	DSP_STATUS status;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+
+	/* Check args: */
+	if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		goto func_cont;
+	}
+	{
+		/* Cancel IO: this ensures no further IO requests or
+		 * notifications.*/
+		status = WMD_CHNL_CancelIO(hChnl);
+	}
+func_cont:
+	if (DSP_SUCCEEDED(status)) {
+		/* Assert I/O on this channel is now cancelled: Protects
+		 * from IO_DPC. */
+		DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
+		/* Invalidate channel object: Protects from
+		 * CHNL_GetIOCompletion(). */
+		pChnl->dwSignature = 0x0000;
+		/* Free the slot in the channel manager: */
+		pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
+		pChnl->pChnlMgr->cOpenChannels -= 1;
+		if (pChnl->hNtfy) {
+			NTFY_Delete(pChnl->hNtfy);
+			pChnl->hNtfy = NULL;
+		}
+		/* Reset channel event: (NOTE: hUserEvent freed in user
+		 * context.). */
+		if (pChnl->hSyncEvent) {
+			SYNC_ResetEvent(pChnl->hSyncEvent);
+			SYNC_CloseEvent(pChnl->hSyncEvent);
+			pChnl->hSyncEvent = NULL;
+		}
+		/* Free I/O request and I/O completion queues:  */
+		if (pChnl->pIOCompletions) {
+			FreeChirpList(pChnl->pIOCompletions);
+			pChnl->pIOCompletions = NULL;
+			pChnl->cIOCs = 0;
+		}
+		if (pChnl->pIORequests) {
+			FreeChirpList(pChnl->pIORequests);
+			pChnl->pIORequests = NULL;
+			pChnl->cIOReqs = 0;
+		}
+		if (pChnl->pFreeList) {
+			FreeChirpList(pChnl->pFreeList);
+			pChnl->pFreeList = NULL;
+		}
+		/* Release channel object. */
+		MEM_FreeObject(pChnl);
+		pChnl = NULL;
+	}
+	DBC_Ensure(DSP_FAILED(status) ||
+		  !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_Create ========
+ *      Create a channel manager object, responsible for opening new channels
+ *      and closing old ones for a given board.
+ */
+DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
+			  struct DEV_OBJECT *hDevObject,
+			  IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_MGR *pChnlMgr = NULL;
+	s32 cChannels;
+#ifdef DEBUG
+	struct CHNL_MGR *hChnlMgr;
+#endif
+	/* Check DBC requirements:  */
+	DBC_Require(phChnlMgr != NULL);
+	DBC_Require(pMgrAttrs != NULL);
+	DBC_Require(pMgrAttrs->cChannels > 0);
+	DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
+	DBC_Require(pMgrAttrs->uWordSize != 0);
+#ifdef DEBUG
+	/* This for the purposes of DBC_Require: */
+	status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
+	DBC_Require(status != DSP_EHANDLE);
+	DBC_Require(hChnlMgr == NULL);
+#endif
+	if (DSP_SUCCEEDED(status)) {
+		/* Allocate channel manager object: */
+		MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
+		if (pChnlMgr) {
+			/* The cChannels attr must equal the # of supported
+			 * chnls for each transport(# chnls for PCPY = DDMA =
+			 * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
+			 * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS.  */
+			DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
+			cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
+				    CHNL_PCPY));
+			/* Create array of channels: */
+			pChnlMgr->apChannel = MEM_Calloc(
+						sizeof(struct CHNL_OBJECT *) *
+						cChannels, MEM_NONPAGED);
+			if (pChnlMgr->apChannel) {
+				/* Initialize CHNL_MGR object: */
+				/* Shared memory driver. */
+				pChnlMgr->dwType = CHNL_TYPESM;
+				pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
+				/* total # chnls supported */
+				pChnlMgr->cChannels = cChannels;
+				pChnlMgr->cOpenChannels = 0;
+				pChnlMgr->dwOutputMask = 0;
+				pChnlMgr->dwLastOutput = 0;
+				pChnlMgr->hDevObject = hDevObject;
+				if (DSP_SUCCEEDED(status)) {
+					status = SYNC_InitializeDPCCS
+						(&pChnlMgr->hCSObj);
+				}
+			} else {
+				status = DSP_EMEMORY;
+			}
+		} else {
+			status = DSP_EMEMORY;
+		}
+	}
+	if (DSP_FAILED(status)) {
+		WMD_CHNL_Destroy(pChnlMgr);
+		*phChnlMgr = NULL;
+	} else {
+		/* Return channel manager object to caller... */
+		*phChnlMgr = pChnlMgr;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_Destroy ========
+ *  Purpose:
+ *      Close all open channels, and destroy the channel manager.
+ */
+DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_MGR *pChnlMgr = hChnlMgr;
+	u32 iChnl;
+
+	if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+		/* Close all open channels: */
+		for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
+			if (DSP_SUCCEEDED
+			    (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
+				DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
+			}
+		}
+		/* release critical section */
+		if (pChnlMgr->hCSObj)
+			SYNC_DeleteCS(pChnlMgr->hCSObj);
+
+		/* Free channel manager object: */
+		if (pChnlMgr->apChannel)
+			MEM_Free(pChnlMgr->apChannel);
+
+		/* Set hChnlMgr to NULL in device object. */
+		DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
+		/* Free this Chnl Mgr object: */
+		MEM_FreeObject(hChnlMgr);
+	} else {
+		status = DSP_EHANDLE;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_FlushIO ========
+ *  purpose:
+ *      Flushes all the outstanding data requests on a channel.
+ */
+DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+	CHNL_MODE uMode = -1;
+	struct CHNL_MGR *pChnlMgr;
+	struct CHNL_IOC chnlIOC;
+	/* Check args:  */
+	if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+		if ((dwTimeOut == CHNL_IOCNOWAIT)
+		    && CHNL_IsOutput(pChnl->uMode)) {
+			status = DSP_EINVALIDARG;
+		} else {
+			uMode = pChnl->uMode;
+			pChnlMgr = pChnl->pChnlMgr;
+		}
+	} else {
+		status = DSP_EHANDLE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Note: Currently, if another thread continues to add IO
+		 * requests to this channel, this function will continue to
+		 * flush all such queued IO requests.  */
+		if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
+			/* Wait for IO completions, up to the specified
+			 * timeout: */
+			while (!LST_IsEmpty(pChnl->pIORequests) &&
+			      DSP_SUCCEEDED(status)) {
+				status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
+							 &chnlIOC);
+				if (DSP_FAILED(status))
+					continue;
+
+				if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
+					status = CHNL_E_WAITTIMEOUT;
+
+			}
+		} else {
+			status = WMD_CHNL_CancelIO(hChnl);
+			/* Now, leave the channel in the ready state: */
+			pChnl->dwState &= ~CHNL_STATECANCEL;
+		}
+	}
+	DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_GetInfo ========
+ *  Purpose:
+ *      Retrieve information related to a channel.
+ */
+DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
+			   OUT struct CHNL_INFO *pInfo)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+	if (pInfo != NULL) {
+		if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+			/* Return the requested information:  */
+			pInfo->hChnlMgr = pChnl->pChnlMgr;
+			pInfo->hEvent = pChnl->hUserEvent;
+			pInfo->dwID = pChnl->uId;
+			pInfo->dwMode = pChnl->uMode;
+			pInfo->cPosition = pChnl->cBytesMoved;
+			pInfo->hProcess = pChnl->hProcess;
+			pInfo->hSyncEvent = pChnl->hSyncEvent;
+			pInfo->cIOCs = pChnl->cIOCs;
+			pInfo->cIOReqs = pChnl->cIOReqs;
+			pInfo->dwState = pChnl->dwState;
+		} else {
+			status = DSP_EHANDLE;
+		}
+	} else {
+		status = DSP_EPOINTER;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_GetIOC ========
+ *      Optionally wait for I/O completion on a channel.  Dequeue an I/O
+ *      completion record, which contains information about the completed
+ *      I/O request.
+ *      Note: Ensures Channel Invariant (see notes above).
+ */
+DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
+			  OUT struct CHNL_IOC *pIOC)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
+	struct CHNL_IRP *pChirp;
+	DSP_STATUS statSync;
+	bool fDequeueIOC = true;
+	struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
+	u8 *pHostSysBuf = NULL;
+
+	DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
+		 "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
+		 pChnl->uChnlType);
+	/* Check args: */
+	if (pIOC == NULL) {
+		status = DSP_EPOINTER;
+	} else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else if (dwTimeOut == CHNL_IOCNOWAIT) {
+		if (LST_IsEmpty(pChnl->pIOCompletions))
+			status = CHNL_E_NOIOC;
+
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	ioc.status = CHNL_IOCSTATCOMPLETE;
+	if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
+		if (dwTimeOut == CHNL_IOCINFINITE)
+			dwTimeOut = SYNC_INFINITE;
+
+		statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
+		if (statSync == DSP_ETIMEOUT) {
+			/* No response from DSP */
+			ioc.status |= CHNL_IOCSTATTIMEOUT;
+			fDequeueIOC = false;
+		} else if (statSync == DSP_EFAIL) {
+			/* This can occur when the user mode thread is
+			 * aborted (^C), or when _VWIN32_WaitSingleObject()
+			 * fails due to unkown causes.  */
+			/* Even though Wait failed, there may be something in
+			 * the Q: */
+			if (LST_IsEmpty(pChnl->pIOCompletions)) {
+				ioc.status |= CHNL_IOCSTATCANCEL;
+				fDequeueIOC = false;
+			}
+		}
+	}
+	/* See comment in AddIOReq */
+	SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
+	disable_irq(MAILBOX_IRQ);
+	if (fDequeueIOC) {
+		/* Dequeue IOC and set pIOC; */
+		DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
+		pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
+		/* Update pIOC from channel state and chirp: */
+		if (pChirp) {
+			pChnl->cIOCs--;
+			/*  If this is a zero-copy channel, then set IOC's pBuf
+			 *  to the DSP's address. This DSP address will get
+			 *  translated to user's virtual addr later.  */
+			{
+				pHostSysBuf = pChirp->pHostSysBuf;
+				ioc.pBuf = pChirp->pHostUserBuf;
+			}
+			ioc.cBytes = pChirp->cBytes;
+			ioc.cBufSize = pChirp->cBufSize;
+			ioc.dwArg = pChirp->dwArg;
+			ioc.status |= pChirp->status;
+			/* Place the used chirp on the free list: */
+			LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
+				   pChirp);
+		} else {
+			ioc.pBuf = NULL;
+			ioc.cBytes = 0;
+		}
+	} else {
+		ioc.pBuf = NULL;
+		ioc.cBytes = 0;
+		ioc.dwArg = 0;
+		ioc.cBufSize = 0;
+	}
+	/* Ensure invariant: If any IOC's are queued for this channel... */
+	if (!LST_IsEmpty(pChnl->pIOCompletions)) {
+		/*  Since DSPStream_Reclaim() does not take a timeout
+		 *  parameter, we pass the stream's timeout value to
+		 *  WMD_CHNL_GetIOC. We cannot determine whether or not
+		 *  we have waited in User mode. Since the stream's timeout
+		 *  value may be non-zero, we still have to set the event.
+		 *  Therefore, this optimization is taken out.
+		 *
+		 *  if (dwTimeOut == CHNL_IOCNOWAIT) {
+		 *    ... ensure event is set..
+		 *      SYNC_SetEvent(pChnl->hSyncEvent);
+		 *  } */
+		SYNC_SetEvent(pChnl->hSyncEvent);
+	} else {
+		/* else, if list is empty, ensure event is reset. */
+		SYNC_ResetEvent(pChnl->hSyncEvent);
+	}
+	enable_irq(MAILBOX_IRQ);
+	SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
+	if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
+		if (!(ioc.pBuf < (void *) USERMODE_ADDR))
+			goto func_cont;
+
+		/* If the addr is in user mode, then copy it */
+		if (!pHostSysBuf || !ioc.pBuf) {
+			status = DSP_EPOINTER;
+			DBG_Trace(DBG_LEVEL7,
+				 "System buffer NULL in IO completion.\n");
+			goto func_cont;
+		}
+		if (!CHNL_IsInput(pChnl->uMode))
+			goto func_cont1;
+
+		/*pHostUserBuf */
+		status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
+#ifndef RES_CLEANUP_DISABLE
+		if (status) {
+			if (current->flags & PF_EXITING) {
+				DBG_Trace(DBG_LEVEL7,
+					 "\n2current->flags ==  PF_EXITING, "
+					 " current->flags;0x%x\n",
+					 current->flags);
+				status = 0;
+			} else {
+				DBG_Trace(DBG_LEVEL7,
+					 "\n2current->flags != PF_EXITING, "
+					 " current->flags;0x%x\n",
+					 current->flags);
+			}
+		}
+#endif
+		if (status) {
+			DBG_Trace(DBG_LEVEL7,
+				 "Error copying kernel buffer to user, %d"
+				 " bytes remaining.  in_interupt %d\n",
+				 status, in_interrupt());
+			status = DSP_EPOINTER;
+		}
+func_cont1:
+		MEM_Free(pHostSysBuf);
+	}
+func_cont:
+	/* Update User's IOC block: */
+	*pIOC = ioc;
+func_end:
+	DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_GetMgrInfo ========
+ *      Retrieve information related to the channel manager.
+ */
+DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
+			      OUT struct CHNL_MGRINFO *pMgrInfo)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
+
+	if (pMgrInfo != NULL) {
+		if (uChnlID <= CHNL_MAXCHANNELS) {
+			if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+				/* Return the requested information:  */
+				pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
+				pMgrInfo->cOpenChannels = pChnlMgr->
+							  cOpenChannels;
+				pMgrInfo->dwType = pChnlMgr->dwType;
+				/* total # of chnls */
+				pMgrInfo->cChannels = pChnlMgr->cChannels;
+			} else {
+				status = DSP_EHANDLE;
+			}
+		} else {
+			status = CHNL_E_BADCHANID;
+		}
+	} else {
+		status = DSP_EPOINTER;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_Idle ========
+ *      Idles a particular channel.
+ */
+DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
+			 bool fFlush)
+{
+	CHNL_MODE uMode;
+	struct CHNL_MGR *pChnlMgr;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
+
+	uMode = hChnl->uMode;
+	pChnlMgr = hChnl->pChnlMgr;
+
+	if (CHNL_IsOutput(uMode) && !fFlush) {
+		/* Wait for IO completions, up to the specified timeout: */
+		status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
+	} else {
+		status = WMD_CHNL_CancelIO(hChnl);
+
+		/* Reset the byte count and put channel back in ready state. */
+		hChnl->cBytesMoved = 0;
+		hChnl->dwState &= ~CHNL_STATECANCEL;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_Open ========
+ *      Open a new half-duplex channel to the DSP board.
+ */
+DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
+			 struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
+			 u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CHNL_MGR *pChnlMgr = hChnlMgr;
+	struct CHNL_OBJECT *pChnl = NULL;
+	struct SYNC_ATTRS *pSyncAttrs = NULL;
+	struct SYNC_OBJECT *hSyncEvent = NULL;
+	/* Ensure DBC requirements:  */
+	DBC_Require(phChnl != NULL);
+	DBC_Require(pAttrs != NULL);
+	*phChnl = NULL;
+	/* Validate Args:  */
+	if (pAttrs->uIOReqs == 0) {
+		status = DSP_EINVALIDARG;
+	} else {
+		if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
+			status = DSP_EHANDLE;
+		} else {
+			if (uChnlId != CHNL_PICKFREE) {
+				if (uChnlId >= pChnlMgr->cChannels) {
+					status = CHNL_E_BADCHANID;
+				} else if (pChnlMgr->apChannel[uChnlId] !=
+					  NULL) {
+					status = CHNL_E_CHANBUSY;
+				}
+			} else {
+				/* Check for free channel */
+				status = SearchFreeChannel(pChnlMgr, &uChnlId);
+			}
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	DBC_Assert(uChnlId < pChnlMgr->cChannels);
+	/* Create channel object:  */
+	MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
+	if (!pChnl) {
+		status = DSP_EMEMORY;
+		goto func_cont;
+	}
+	/* Protect queues from IO_DPC: */
+	pChnl->dwState = CHNL_STATECANCEL;
+	/* Allocate initial IOR and IOC queues: */
+	pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
+	pChnl->pIORequests = CreateChirpList(0);
+	pChnl->pIOCompletions = CreateChirpList(0);
+	pChnl->cChirps = pAttrs->uIOReqs;
+	pChnl->cIOCs = 0;
+	pChnl->cIOReqs = 0;
+	/* #WinCE# Let SYNC_ create our event  */
+	status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
+	if (DSP_SUCCEEDED(status)) {
+		status = NTFY_Create(&pChnl->hNtfy);
+		if (DSP_FAILED(status)) {
+			/* The only failure that could have occurred */
+			status = DSP_EMEMORY;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		if (pChnl->pIOCompletions && pChnl->pIORequests &&
+		   pChnl->pFreeList) {
+			/* Initialize CHNL object fields:    */
+			pChnl->pChnlMgr = pChnlMgr;
+			pChnl->uId = uChnlId;
+			pChnl->uMode = uMode;
+			pChnl->hUserEvent = hSyncEvent;	/* for Linux */
+			pChnl->hSyncEvent = hSyncEvent;
+			PRCS_GetCurrentHandle(&pChnl->hProcess);
+			pChnl->pCBArg = 0;
+			pChnl->cBytesMoved = 0;
+			/* Default to proc-copy */
+			pChnl->uChnlType = CHNL_PCPY;
+		} else {
+			status = DSP_EMEMORY;
+		}
+	} else {
+		status = DSP_EINVALIDARG;
+	}
+	if (DSP_FAILED(status)) {
+		/* Free memory */
+		if (pChnl->pIOCompletions) {
+			FreeChirpList(pChnl->pIOCompletions);
+			pChnl->pIOCompletions = NULL;
+			pChnl->cIOCs = 0;
+		}
+		if (pChnl->pIORequests) {
+			FreeChirpList(pChnl->pIORequests);
+			pChnl->pIORequests = NULL;
+		}
+		if (pChnl->pFreeList) {
+			FreeChirpList(pChnl->pFreeList);
+			pChnl->pFreeList = NULL;
+		}
+		if (hSyncEvent) {
+			SYNC_CloseEvent(hSyncEvent);
+			hSyncEvent = NULL;
+		}
+		if (pChnl->hNtfy) {
+			NTFY_Delete(pChnl->hNtfy);
+			pChnl->hNtfy = NULL;
+		}
+		MEM_FreeObject(pChnl);
+	}
+func_cont:
+	if (DSP_SUCCEEDED(status)) {
+		/* Insert channel object in channel manager: */
+		pChnlMgr->apChannel[pChnl->uId] = pChnl;
+		SYNC_EnterCS(pChnlMgr->hCSObj);
+		pChnlMgr->cOpenChannels++;
+		SYNC_LeaveCS(pChnlMgr->hCSObj);
+		/* Return result... */
+		pChnl->dwSignature = CHNL_SIGNATURE;
+		pChnl->dwState = CHNL_STATEREADY;
+		*phChnl = pChnl;
+	}
+func_end:
+	DBC_Ensure((DSP_SUCCEEDED(status) &&
+		  MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
+		  (*phChnl == NULL));
+	return status;
+}
+
+/*
+ *  ======== WMD_CHNL_RegisterNotify ========
+ *      Registers for events on a particular channel.
+ */
+DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
+				  u32 uNotifyType,
+				  struct DSP_NOTIFICATION *hNotification)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
+
+	status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
+			      uNotifyType);
+
+	return status;
+}
+
+/*
+ *  ======== CreateChirpList ========
+ *  Purpose:
+ *      Initialize a queue of channel I/O Request/Completion packets.
+ *  Parameters:
+ *      uChirps:    Number of Chirps to allocate.
+ *  Returns:
+ *      Pointer to queue of IRPs, or NULL.
+ *  Requires:
+ *  Ensures:
+ */
+static struct LST_LIST *CreateChirpList(u32 uChirps)
+{
+	struct LST_LIST *pChirpList;
+	struct CHNL_IRP *pChirp;
+	u32 i;
+
+	pChirpList = LST_Create();
+
+	if (pChirpList) {
+		/* Make N chirps and place on queue. */
+		for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
+		    NULL); i++) {
+			LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
+		}
+
+		/* If we couldn't allocate all chirps, free those allocated: */
+		if (i != uChirps) {
+			FreeChirpList(pChirpList);
+			pChirpList = NULL;
+		}
+	}
+
+	return pChirpList;
+}
+
+/*
+ *  ======== FreeChirpList ========
+ *  Purpose:
+ *      Free the queue of Chirps.
+ */
+static void FreeChirpList(struct LST_LIST *pChirpList)
+{
+	DBC_Require(pChirpList != NULL);
+
+	while (!LST_IsEmpty(pChirpList))
+		MEM_Free(LST_GetHead(pChirpList));
+
+	LST_Delete(pChirpList);
+}
+
+/*
+ *  ======== MakeNewChirp ========
+ *      Allocate the memory for a new channel IRP.
+ */
+static struct CHNL_IRP *MakeNewChirp(void)
+{
+	struct CHNL_IRP *pChirp;
+
+	pChirp = (struct CHNL_IRP *)MEM_Calloc(
+		 sizeof(struct CHNL_IRP), MEM_NONPAGED);
+	if (pChirp != NULL) {
+		/* LST_InitElem only resets the list's member values. */
+		LST_InitElem(&pChirp->link);
+	}
+
+	return pChirp;
+}
+
+/*
+ *  ======== SearchFreeChannel ========
+ *      Search for a free channel slot in the array of channel pointers.
+ */
+static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
+				   OUT u32 *pdwChnl)
+{
+	DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
+	u32 i;
+
+	DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
+
+	for (i = 0; i < pChnlMgr->cChannels; i++) {
+		if (pChnlMgr->apChannel[i] == NULL) {
+			status = DSP_SOK;
+			*pdwChnl = i;
+			break;
+		}
+	}
+
+	return status;
+}
diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
new file mode 100644
index 0000000..afb96bb
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/io_sm.c
@@ -0,0 +1,1843 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/wmdchnl/common/io_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== io_sm.c ========
+ *  Description:
+ *      IO dispatcher for a shared memory channel driver.
+ *
+ *  Public Functions:
+ *      WMD_IO_Create
+ *      WMD_IO_Destroy
+ *      WMD_IO_OnLoaded
+ *      IO_AndSetValue
+ *      IO_BufSize
+ *      IO_CancelChnl
+ *      IO_DPC
+ *      IO_ISR
+ *      IO_IVAISR
+ *      IO_OrSetValue
+ *      IO_ReadValue
+ *      IO_ReadValueLong
+ *      IO_RequestChnl
+ *      IO_Schedule
+ *      IO_WriteValue
+ *      IO_WriteValueLong
+ *
+ *  Channel Invariant:
+ *      There is an important invariant condition which must be maintained per
+ *      channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
+ *      which may cause timeouts and/or failure of the WIN32_WaitSingleObject
+ *      function (SYNC_WaitOnEvent).
+ *
+ *! Revision History:
+ *! ================
+ *! 28-Apr-2004 vp: Updated IVA MMU entries based on Aptix validation.
+ *! 19-Apr-2004 sb: Clear MBX_DEH_RESET from hIOMgr->wIntrVal to prevent
+		    DEH when MPU invokes DPC before next DSP interrupt.
+		    Revert back GP timer mapping endianness to LE
+ *! 22-Apr-2004 sb: Fixed SHM & peripherals endianness settings for 2420
+		    Optimized num. of SHM entries for any SHM size.
+ *! 08-Mar-2004 sb: Updated HW_MMU page size macros
+ *! 09-Feb-2004 vp: Updated for IVA link driver.
+ *! 05-Jan-2004 vp: Updated for the 24xx platform.
+ *! 23-Apr-2003 sb: Fixed mailbox deadlock
+ *! 13-Apr-2003 vp: Updated to support TC Word Swap option.
+ *! 21-Mar-2003 sb: OEM configuration updates
+ *! 24-Feb-2003 vp: Code Review Updates.
+ *! 18-Oct-2002 sb: Ported to Linux platform
+ *! 28-Mar-2002 jeh Assume word addresses for SHM, MSG, ... symbol values.
+ *! 25-Jan-2002 ag  bDspAck incorrectly set in IO_DDZCDispatchChnl()
+ *! 05-Jan-2002 ag  Set MBX value to DSP using IO_InterruptDSP2().
+ *!		 Check for CHNL_STATECANCEL in ACK processing.
+ *! 20-Dec-2001 ag  Removed #ifdef CHNL_NOIPCINTR & CHNL_PREOMAP for DSP-DMA.
+ *!		 Removed unused fxn GetDDMAChnl().
+ *! 11-Dec-2001 ag  Fix in DDMA_Dispatch for multi-bufs.
+ *! 06-Nov-2001 ag  DSP-DMA I/O processing support added.
+ *! 05-Nov-2001 kc  Updated to support DEH module.
+ *! 18-Sep-2001 ag  Using virtual cached addressing for SM.
+ *! 29-Aug-2001 ag  User SM regions registered during prog load.
+ *! 10-Aug-2001 ag  Removed dependency on platform\inc\Config.h.
+ *!		 MMU setup OnLoaded & per DEV context.
+ *! 08-May-2001 ag  Don't SwapWord if TIHELEN.
+ *! 31-May-2001 ag  Fixed bug in pInput calc.
+ *! 21-May-2001 ag  Helen SM uses TICFG_BRIDGE_DATA_BASE[SIZE] in Config.h.
+ *! 04-May-2001 jeh Replaced CHNL_PREOMAP with CHNL_OMAP, added CHNL_HELEN.
+ *!		 Cleaned up WMD_IO_OnLoaded a bit.
+ *! 10-Apr-2001 rr: Replaced DBG_ENTER with DBG_LEVEL3.
+ *! 28-Mar-2001 ag  Added CHNL_NOIPCINTR. Disables IPC INTR handling.
+ *! 16-Feb-2001 jeh Messaging disabled for PREOMAP.
+ *! 16-Dec-2000 ag  IO_DispatchMsg() enabled for PreOMAP.
+ *!		 SM must be in last 4 Meg region SDRAM for PreOMAP.
+ *! 14-Dec-2000 jeh Now reads SM addresses from COFF for PreOMAP.
+ *! 04-Dec-2000 jeh Bug fixes for messaging.
+ *! 20-Nov-2000 jeh Updated to handle messaging.
+ *! 23-Oct-2000 jeh Added notifications of IO complete and end of stream for
+ *!		 DSPStream support. Pass arg in SHM structure.
+ *! 07-Jul-2000 rr: Changed Prefix proc to prcs for Process module.
+ *! 03-Feb-2000 rr: DBG statements during fxn entry added.
+ *! 21-Jan-2000 ag: Clean-up per code review.
+ *! 10-Dev-1999 ag: Added critical section in IO_Dispatch() to protect IOCL/IOR.
+ *!		 Removed DBC_Asserts after cancelled/closed channels.
+ *!		 Replaced x86 specific __asm int 3 with DBC_Assert(false);
+ *! 12-Nov-1999 ag: Removed some warnings when compiling for 16 bit targets.
+ *!		 (See #if _CHNL_WORDSIZE).
+ *! 04-Nov-1999 ag: WinCE port.
+ *! 25-May-1999 jg: Test that CHNL_IOCLASS boards have a loaded program with
+ *!		 a defined shared memory buffer.
+ *! 09-Jul-1997 gp: Added some checks for validity of SHM control block values.
+ *! 17-Jan-1997 db: Added capability to log shared memory header.
+ *! 15-Jan-1997 gp: Code Review mods: moved static dwLastId to CHNL_MGR object.
+ *! 03-Jan-1997 gp: Added call to CHNLSM_DPC from IO_DPC. Check for ISR failing
+ *!		 to process interrupt on a non-shared IRQ line.
+ *! 10-Dec-1996 gp: Added EOS notification on input channel (CHNL_MODEFROMDSP).
+ *! 27-Nov-1996 gp: Fixed bug in IO_Dispatch(), which fixed flushing.
+ *! 23-Oct-1996 gp: Ensure client buffer bounds are not overrun on input.
+ *! 12-Aug-1996 gp: Created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+#endif
+#endif
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <dpc.h>
+#include <mem.h>
+#include <ntfy.h>
+#include <sync.h>
+#include <reg.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/*  ----------------------------------- Mini Driver */
+#include <wmddeh.h>
+#include <wmdio.h>
+#include <wmdioctl.h>
+#include <_tiomap.h>
+#include <tiomap_io.h>
+#include <_tiomap_pwr.h>
+#include <tiomap_io.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <cod.h>
+#include <dev.h>
+#include <chnl_sm.h>
+#include <dbreg.h>
+
+/*  ----------------------------------- Others */
+#include <rms_sh.h>
+#include <mgr.h>
+#include "_cmm.h"
+
+/*  ----------------------------------- This */
+#include <io_sm.h>
+#include "_msg_sm.h"
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define OUTPUTNOTREADY  0xffff
+#define NOTENABLED      0xffff	/* channel(s) not enabled */
+
+#define EXTEND      "_EXT_END"
+
+#define SwapWord(x)     (x)
+#define ulPageAlignSize 0x10000   /* Page Align Size */
+
+#define MAX_PM_REQS 32
+
+/* IO Manager: only one created per board: */
+struct IO_MGR {
+	/* These four fields must be the first fields in a IO_MGR_ struct: */
+	u32 dwSignature; 	/* Used for object validation   */
+	struct WMD_DEV_CONTEXT *hWmdContext; 	/* WMD device context  */
+	struct WMD_DRV_INTERFACE *pIntfFxns; 	/* Function interface to WMD */
+	struct DEV_OBJECT *hDevObject; 	/* Device this board represents */
+
+	/* These fields initialized in WMD_IO_Create():    */
+	struct CHNL_MGR *hChnlMgr;
+	struct SHM *pSharedMem; 	/* Shared Memory control	*/
+	u8 *pInput; 		/* Address of input channel     */
+	u8 *pOutput; 		/* Address of output channel    */
+	struct MSG_MGR *hMsgMgr; 	/* Message manager */
+	struct MSG *pMsgInputCtrl; 	/* Msg control for from DSP messages */
+	struct MSG *pMsgOutputCtrl; 	/* Msg control for to DSP messages */
+	u8 *pMsgInput; 	/* Address of input messages    */
+	u8 *pMsgOutput; 	/* Address of output messages   */
+	u32 uSMBufSize; 	/* Size of a shared memory I/O channel */
+	struct ISR_IRQ *hIRQ; 		/* Virutalized IRQ handle       */
+	bool fSharedIRQ; 	/* Is this IRQ shared?	  */
+	struct DPC_OBJECT *hDPC; 	/* DPC object handle	    */
+	struct SYNC_CSOBJECT *hCSObj; 	/* Critical section object handle */
+	u32 uWordSize; 	/* Size in bytes of DSP word    */
+	u16 wIntrVal; 		/* interrupt value	      */
+	/* private extnd proc info; mmu setup */
+	struct MGR_PROCESSOREXTINFO extProcInfo;
+	struct CMM_OBJECT *hCmmMgr; 	/* Shared Mem Mngr	      */
+	u32 dQuePowerMbxVal[MAX_PM_REQS];
+	u32 iQuePowerHead;
+	u32 iQuePowerTail;
+#ifndef DSP_TRACEBUF_DISABLED
+	u32 ulTraceBufferBegin; 	/* Trace message start address */
+	u32 ulTraceBufferEnd; 	/* Trace message end address */
+	u32 ulTraceBufferCurrent; 	/* Trace message current address */
+	u32 ulGPPReadPointer; 	/* GPP Read pointer to Trace buffer */
+	u8 *pMsg;
+	u32 ulGppVa;
+	u32 ulDspVa;
+#endif
+} ;
+
+/*  ----------------------------------- Function Prototypes */
+static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
+			   IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
+static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static void IO_DispatchPM(IN struct IO_MGR *pIOMgr);
+static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
+				struct CHNL_IRP *pChirp);
+static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+			u32 iMode);
+static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+			u32 iMode);
+static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
+static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
+			     struct CHNL_OBJECT *pChnl, u32 dwMask);
+static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+			void *pSrc, u32 uSize);
+static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+			void *pSrc, u32 uSize);
+#ifndef DSP_TRACEBUF_DISABLED
+void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
+#endif
+
+/* Bus Addr (cached kernel)*/
+static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
+				  struct COD_MANAGER *hCodMan,
+				  u32 dwGPPBasePA);
+
+extern u32 DRV_GetFirstDevExtension();
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+/* The maximum number of OPPs that are supported by Baseport */
+extern s32 dsp_max_opps;
+/* The Vdd1 opp table information */
+extern u32 vdd1_dsp_freq[6][4] ;
+/* The contraint handle for OPP information */
+extern struct constraint_handle *dsp_constraint_handle;
+#endif
+#endif
+/*
+ *  ======== WMD_IO_Create ========
+ *      Create an IO manager object.
+ */
+DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
+			 struct DEV_OBJECT *hDevObject,
+			 IN CONST struct IO_ATTRS *pMgrAttrs)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct IO_MGR *pIOMgr = NULL;
+	struct SHM *pSharedMem = NULL;
+	struct WMD_DEV_CONTEXT *hWmdContext = NULL;
+	struct CFG_HOSTRES hostRes;
+	struct CFG_DEVNODE *hDevNode;
+	struct CHNL_MGR *hChnlMgr;
+	u32 devType;
+	/* Check DBC requirements:  */
+	DBC_Require(phIOMgr != NULL);
+	DBC_Require(pMgrAttrs != NULL);
+	DBC_Require(pMgrAttrs->uWordSize != 0);
+	/* This for the purposes of DBC_Require: */
+	status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
+	DBC_Require(status != DSP_EHANDLE);
+	DBC_Require(hChnlMgr != NULL);
+	DBC_Require(hChnlMgr->hIOMgr == NULL);
+	 /*  Message manager will be created when a file is loaded, since
+	 *  size of message buffer in shared memory is configurable in
+	 *  the base image.  */
+	DEV_GetWMDContext(hDevObject, &hWmdContext);
+	DBC_Assert(hWmdContext);
+	DEV_GetDevType(hDevObject, &devType);
+	/*  DSP shared memory area will get set properly when
+	 *  a program is loaded. They are unknown until a COFF file is
+	 *  loaded. I chose the value -1 because it was less likely to be
+	 *  a valid address than 0.  */
+	pSharedMem = (struct SHM *) -1;
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Allocate IO manager object: */
+	MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
+	if (pIOMgr == NULL) {
+		status = DSP_EMEMORY;
+		goto func_cont;
+	}
+	/* Initialize CHNL_MGR object:    */
+#ifndef DSP_TRACEBUF_DISABLED
+	pIOMgr->pMsg = NULL;
+#endif
+	pIOMgr->hChnlMgr = hChnlMgr;
+	pIOMgr->uWordSize = pMgrAttrs->uWordSize;
+	pIOMgr->pSharedMem = pSharedMem;
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_InitializeCS(&pIOMgr->hCSObj);
+
+	if (devType == DSP_UNIT) {
+		/* Create a DPC object: */
+		status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
+		if (DSP_SUCCEEDED(status))
+			status = DEV_GetDevNode(hDevObject, &hDevNode);
+
+		pIOMgr->iQuePowerHead = 0;
+		pIOMgr->iQuePowerTail = 0;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = CFG_GetHostResources((struct CFG_DEVNODE *)
+				DRV_GetFirstDevExtension() , &hostRes);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pIOMgr->hWmdContext = hWmdContext;
+		pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
+		IO_DisableInterrupt(hWmdContext);
+		if (devType == DSP_UNIT) {
+			/* Plug the channel ISR:. */
+			status = ISR_Install(&pIOMgr->hIRQ, &hostRes, IO_ISR,
+				 ISR_MAILBOX1, (void *)pIOMgr);
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* Enable interrupt used for dsp i/o link */
+			/* moved  IO_EnableInterrupt(hWmdContext); */
+		} else {
+			status = CHNL_E_ISR;
+		}
+	} else {
+		status = CHNL_E_ISR;
+	}
+func_cont:
+	if (DSP_FAILED(status)) {
+		/* Cleanup: */
+		WMD_IO_Destroy(pIOMgr);
+		*phIOMgr = NULL;
+	} else {
+		/* Return IO manager object to caller... */
+		hChnlMgr->hIOMgr = pIOMgr;
+		*phIOMgr = pIOMgr;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_IO_Destroy ========
+ *  Purpose:
+ *      Disable interrupts, destroy the IO manager.
+ */
+DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *hWmdContext;
+	if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
+		/* Unplug IRQ:    */
+		if (hIOMgr->hIRQ) {
+			/* Disable interrupts from the board:  */
+			if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject,
+			   &hWmdContext))) {
+				DBC_Assert(hWmdContext);
+			}
+			(void)CHNLSM_DisableInterrupt(hWmdContext);
+			(void)ISR_Uninstall(hIOMgr->hIRQ);
+			(void)DPC_Destroy(hIOMgr->hDPC);
+		}
+#ifndef DSP_TRACEBUF_DISABLED
+		if (hIOMgr->pMsg)
+			MEM_Free(hIOMgr->pMsg);
+#endif
+		SYNC_DeleteCS(hIOMgr->hCSObj); 	/* Leak Fix. */
+		/* Free this IO manager object: */
+		MEM_FreeObject(hIOMgr);
+	} else {
+		status = DSP_EHANDLE;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_IO_OnLoaded ========
+ *  Purpose:
+ *      Called when a new program is loaded to get shared memory buffer
+ *      parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
+ *      are in DSP address units.
+ */
+DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
+{
+	struct COD_MANAGER *hCodMan;
+	struct CHNL_MGR *hChnlMgr;
+	struct MSG_MGR *hMsgMgr;
+	u32 ulShmBase;
+	u32 ulShmBaseOffset;
+	u32 ulShmLimit;
+	u32 ulShmLength = -1;
+	u32 ulMemLength = -1;
+	u32 ulMsgBase;
+	u32 ulMsgLimit;
+	u32 ulMsgLength = -1;
+	u32 ulExtEnd;
+	u32 ulGppPa = 0;
+	u32 ulGppVa = 0;
+	u32 ulDspVa = 0;
+	u32 ulSegSize = 0;
+	u32 ulPadSize = 0;
+	u32 i;
+	DSP_STATUS status = DSP_SOK;
+	u32 uNumProcs = 0;
+	s32 ndx = 0;
+	/* DSP MMU setup table */
+	struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
+	struct CFG_HOSTRES hostRes;
+	u32 mapAttrs;
+	u32 ulShm0End;
+	u32 ulDynExtBase;
+	u32 ulSeg1Size = 0;
+	u32 paCurr = 0;
+	u32 vaCurr = 0;
+	u32 gppVaCurr = 0;
+	u32 numBytes = 0;
+	u32 allBits = 0;
+	u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
+			   HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
+
+	status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
+	DBC_Assert(DSP_SUCCEEDED(status));
+	hChnlMgr = hIOMgr->hChnlMgr;
+	 /*  The message manager is destroyed when the board is stopped.  */
+	DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
+	hMsgMgr = hIOMgr->hMsgMgr;
+	DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
+	DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+	if (hIOMgr->pSharedMem)
+		hIOMgr->pSharedMem = NULL;
+
+	/* Get start and length of channel part of shared memory */
+	status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
+				 &ulShmBase);
+	if (DSP_FAILED(status)) {
+		status = CHNL_E_NOMEMMAP;
+		goto func_cont1;
+	}
+	status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
+				&ulShmLimit);
+	if (DSP_FAILED(status)) {
+		status = CHNL_E_NOMEMMAP;
+		goto func_cont1;
+	}
+	if (ulShmLimit <= ulShmBase) {
+		status = CHNL_E_INVALIDMEMBASE;
+	} else {
+		/* get total length in bytes */
+		ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
+		/* Calculate size of a PROCCOPY shared memory region */
+		DBG_Trace(DBG_LEVEL7,
+			 "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
+			  (ulShmLength - sizeof(struct SHM)));
+	}
+func_cont1:
+	if (DSP_SUCCEEDED(status)) {
+		/* Get start and length of message part of shared memory */
+		status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
+					&ulMsgBase);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
+					&ulMsgLimit);
+		if (DSP_SUCCEEDED(status)) {
+			if (ulMsgLimit <= ulMsgBase) {
+				status = CHNL_E_INVALIDMEMBASE;
+			} else {
+				/* Length (bytes) of messaging part of shared
+				 * memory */
+				ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
+					      hIOMgr->uWordSize;
+				/* Total length (bytes) of shared memory:
+				 * chnl + msg */
+				ulMemLength = ulShmLength + ulMsgLength;
+			}
+		} else {
+			status = CHNL_E_NOMEMMAP;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+#ifndef DSP_TRACEBUF_DISABLED
+		status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
+		DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
+			 ulShm0End);
+#else
+		status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
+					 &ulShm0End);
+		DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
+#endif
+		if (DSP_FAILED(status))
+			status = CHNL_E_NOMEMMAP;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
+		if (DSP_FAILED(status))
+			status = CHNL_E_NOMEMMAP;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
+		if (DSP_FAILED(status))
+			status = CHNL_E_NOMEMMAP;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Get memory reserved in host resources */
+		(void)MGR_EnumProcessorInfo(0,
+			(struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
+			sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
+		CFG_GetHostResources((
+			struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&hostRes);
+		/* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
+		ndx = 0;
+		ulGppPa = hostRes.dwMemPhys[1];
+		ulGppVa = hostRes.dwMemBase[1];
+		/* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
+		/* Why can't we directly take the DSPVA from the symbols? */
+		ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
+		ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
+		ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
+		ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
+		ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
+		ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
+			     ulPageAlignSize);
+			if (ulPadSize == ulPageAlignSize)
+				ulPadSize = 0x0;
+
+		 DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
+			  "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
+			  "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
+			  ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
+			  ulSeg1Size);
+
+		if ((ulSegSize + ulSeg1Size + ulPadSize) >
+		   hostRes.dwMemLength[1]) {
+			DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
+				 "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
+				 "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
+				 ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
+				 ulExtEnd, ulSegSize, ulSeg1Size);
+			DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
+				 "Required 0x%x\n", hostRes.dwMemLength[1],
+				 ulSegSize + ulSeg1Size + ulPadSize);
+			status = DSP_EMEMORY;
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	paCurr = ulGppPa;
+	vaCurr = ulDynExtBase * hIOMgr->uWordSize;
+	gppVaCurr = ulGppVa;
+	numBytes = ulSeg1Size;
+
+	/*
+	 * Try to fit into TLB entries. If not possible, push them to page
+	 * tables. It is quite possible that if sections are not on
+	 * bigger page boundary, we may end up making several small pages.
+	 * So, push them onto page tables, if that is the case.
+	 */
+	mapAttrs = 0x00000000;
+	mapAttrs = DSP_MAPLITTLEENDIAN;
+	mapAttrs |= DSP_MAPPHYSICALADDR;
+	mapAttrs |= DSP_MAPELEMSIZE32;
+	while (numBytes && DSP_SUCCEEDED(status)) {
+		/* To find the max. page size with which both PA & VA are
+		 * aligned */
+		allBits = paCurr | vaCurr;
+		DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
+			 "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
+		for (i = 0; i < 4; i++) {
+			if ((numBytes >= pgSize[i]) && ((allBits &
+			   (pgSize[i] - 1)) == 0)) {
+				status = hIOMgr->pIntfFxns->pfnBrdMemMap
+					(hIOMgr->hWmdContext, paCurr, vaCurr,
+					pgSize[i], mapAttrs);
+				DBC_Assert(DSP_SUCCEEDED(status));
+				paCurr += pgSize[i];
+				vaCurr += pgSize[i];
+				gppVaCurr += pgSize[i];
+				numBytes -= pgSize[i];
+				/* Don't try smaller sizes. Hopefully we have
+				 * reached an address aligned to a bigger page
+				 * size*/
+				break;
+			}
+		}
+	}
+	paCurr += ulPadSize;
+	vaCurr += ulPadSize;
+	gppVaCurr += ulPadSize;
+
+	/* configure the TLB entries for the next cacheable segment */
+	numBytes = ulSegSize;
+	vaCurr = ulDspVa * hIOMgr->uWordSize;
+	allBits = 0x0;
+	while (numBytes && DSP_SUCCEEDED(status)) {
+		/* To find the max. page size with which both PA & VA are
+		 * aligned*/
+		allBits = paCurr | vaCurr;
+		DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
+			 "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
+			 numBytes);
+		for (i = 0; i < 4; i++) {
+			if (!(numBytes >= pgSize[i]) ||
+			   !((allBits & (pgSize[i]-1)) == 0)) {
+				continue;
+			}
+			if (ndx < MAX_LOCK_TLB_ENTRIES) {
+				/* This is the physical address written to
+				 * DSP MMU */
+				aEProc[ndx].ulGppPa = paCurr;
+				/* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
+				 * ADDRESS!!! */
+				aEProc[ndx].ulGppVa = gppVaCurr;
+				aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
+						      uWordSize;
+				aEProc[ndx].ulSize = pgSize[i];
+				aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
+				aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
+				aEProc[ndx].mixedMode = HW_MMU_CPUES;
+				DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
+					 " VA %lx DSP_VA %lx Size %lx\n",
+					 aEProc[ndx].ulGppPa,
+					 aEProc[ndx].ulGppVa,
+					 aEProc[ndx].ulDspVa *
+					 hIOMgr->uWordSize, pgSize[i]);
+				ndx++;
+			} else {
+				status = hIOMgr->pIntfFxns->pfnBrdMemMap(
+				hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
+					mapAttrs);
+				DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
+					 " VA %lx DSP_VA %lx Size %lx\n",
+					 aEProc[ndx].ulGppPa,
+					 aEProc[ndx].ulGppVa,
+					 aEProc[ndx].ulDspVa *
+					 hIOMgr->uWordSize, pgSize[i]);
+				DBC_Assert(DSP_SUCCEEDED(status));
+			}
+			paCurr += pgSize[i];
+			vaCurr += pgSize[i];
+			gppVaCurr += pgSize[i];
+			numBytes -= pgSize[i];
+			/* Don't try smaller sizes. Hopefully we have reached
+			 an address aligned to a bigger page size*/
+			break;
+		}
+	}
+
+	 /* Copy remaining entries from CDB. All entries are 1 MB and should not
+	 * conflict with SHM entries on MPU or DSP side */
+	for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
+	    DSP_SUCCEEDED(status); i++) {
+		if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
+			continue;
+
+		if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
+			&& hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
+				ulGppPa + ulSegSize)
+			|| (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
+				0x100000 / hIOMgr->uWordSize && hIOMgr->
+				extProcInfo.tyTlb[i].ulDspVirt
+				<= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
+			DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
+				 "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
+				 "GppPa %x, DspVa %x, Bytes %x.\n", i,
+				 hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
+				 hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
+				 ulGppPa, ulDspVa, ulSegSize);
+			status = DSP_EFAIL;
+		} else {
+			if (ndx < MAX_LOCK_TLB_ENTRIES) {
+				aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
+					tyTlb[i].ulDspVirt;
+				aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
+					tyTlb[i].ulGppPhys;
+				aEProc[ndx].ulGppVa = 0;
+				/* Can't convert, so set to zero*/
+				aEProc[ndx].ulSize = 0x100000; 	/* 1 MB*/
+				DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
+					 "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
+					aEProc[ndx].ulDspVa);
+				ndx++;
+			} else {
+				status = hIOMgr->pIntfFxns->pfnBrdMemMap
+					(hIOMgr->hWmdContext,
+					hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
+					hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
+					0x100000, mapAttrs);
+			}
+		}
+	}
+	if (i < 7 && DSP_SUCCEEDED(status)) {
+		/* All CDB entries could not be made*/
+		status = DSP_EFAIL;
+	}
+func_cont:
+	mapAttrs = 0x00000000;
+	mapAttrs = DSP_MAPLITTLEENDIAN;
+	mapAttrs |= DSP_MAPPHYSICALADDR;
+	mapAttrs |= DSP_MAPELEMSIZE32;
+	/* Map the L4 peripherals */
+	{
+		int i = 0;
+		while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
+				status = hIOMgr->pIntfFxns->pfnBrdMemMap
+					(hIOMgr->hWmdContext,
+					L4PeripheralTable[i].physAddr,
+					L4PeripheralTable[i].dspVirtAddr,
+					HW_PAGE_SIZE_4KB, mapAttrs);
+				DBC_Assert(DSP_SUCCEEDED(status));
+				i++;
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
+			aEProc[i].ulDspVa = 0;
+			aEProc[i].ulGppPa = 0;
+			aEProc[i].ulGppVa = 0;
+			aEProc[i].ulSize = 0;
+		}
+		/* Set the SHM physical address entry (grayed out in CDB file)
+		 * to the virtual uncached ioremapped address of SHM reserved
+		 * on MPU */
+		hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
+							 ulPadSize);
+		DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
+			  hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
+		/* Need SHM Phys addr. IO supports only one DSP for now:
+		 * uNumProcs=1 */
+		if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
+		   (uNumProcs != 1)) {
+			status = CHNL_E_NOMEMMAP;
+			DBC_Assert(false);
+		} else {
+			DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
+			/* ulShmBase may not be at ulDspVa address */
+			ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
+			    hIOMgr->uWordSize;
+			 /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
+			 *   _BRD_Start() the MMU will be re-programed with MMU
+			 *   DSPVa-GPPPa pair info while DSP is in a known
+			 *   (reset) state.  */
+			DBC_Assert(hIOMgr->pIntfFxns != NULL);
+			DBC_Assert(hIOMgr->hWmdContext != NULL);
+			status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
+				 hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
+			ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
+			DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
+				 "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
+				 ulGppPhys);
+			ulShmBase += ulShmBaseOffset;
+			ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
+				    ulMemLength);
+			DBC_Assert(ulShmBase != 0);
+			if (DSP_SUCCEEDED(status)) {
+				status = registerSHMSegs(hIOMgr, hCodMan,
+					 aEProc[0].ulGppPa);
+				/* Register SM */
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
+		hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
+				 sizeof(struct SHM);
+		hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
+				  sizeof(struct SHM))/2;
+		hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
+		DBG_Trace(DBG_LEVEL3,
+			 "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
+			 hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
+		DBG_Trace(DBG_LEVEL3,
+			 "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
+			 hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
+			 sizeof(struct SHM));
+		 /*  Set up Shared memory addresses for messaging. */
+		hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
+					hIOMgr->pSharedMem +
+					ulShmLength);
+		hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
+				    sizeof(struct MSG);
+		hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
+					 pMsgInputCtrl + ulMsgLength / 2);
+		hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
+				     sizeof(struct MSG);
+		hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
+				    hIOMgr->pMsgInput) /
+				    sizeof(struct MSG_DSPMSG);
+		DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
+			 "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
+			 "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
+			 "0x%x \n", (u8 *)hIOMgr->pSharedMem,
+			 (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
+			 (u8 *)hIOMgr->pMsgInputCtrl,
+			 (u8 *)hIOMgr->pMsgInput,
+			 (u8 *)hIOMgr->pMsgOutputCtrl,
+			 (u8 *)hIOMgr->pMsgOutput);
+		DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
+			 "0x%x\n", hMsgMgr->uMaxMsgs);
+		memzero((void *) hIOMgr->pSharedMem, sizeof(struct SHM));
+	}
+#ifndef DSP_TRACEBUF_DISABLED
+	if (DSP_SUCCEEDED(status)) {
+		/* Get the start address of trace buffer */
+		if (DSP_SUCCEEDED(status)) {
+			status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
+				 &hIOMgr->ulTraceBufferBegin);
+			if (DSP_FAILED(status))
+				status = CHNL_E_NOMEMMAP;
+
+		}
+		hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
+			(ulGppVa + ulSeg1Size + ulPadSize) +
+			(hIOMgr->ulTraceBufferBegin - ulDspVa);
+		/* Get the end address of trace buffer */
+		if (DSP_SUCCEEDED(status)) {
+			status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
+				 &hIOMgr->ulTraceBufferEnd);
+			if (DSP_FAILED(status))
+				status = CHNL_E_NOMEMMAP;
+
+		}
+		hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
+					   (hIOMgr->ulTraceBufferEnd - ulDspVa);
+		/* Get the current address of DSP write pointer */
+		if (DSP_SUCCEEDED(status)) {
+			status = COD_GetSymValue(hCodMan,
+				 BRIDGE_SYS_PUTC_current,
+				 &hIOMgr->ulTraceBufferCurrent);
+			if (DSP_FAILED(status))
+				status = CHNL_E_NOMEMMAP;
+
+		}
+		hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
+						ulPadSize) + (hIOMgr->
+						ulTraceBufferCurrent - ulDspVa);
+		/* Calculate the size of trace buffer */
+		if (hIOMgr->pMsg)
+			MEM_Free(hIOMgr->pMsg);
+		hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
+					hIOMgr->ulTraceBufferBegin) *
+					hIOMgr->uWordSize) + 2, MEM_NONPAGED);
+		if (!hIOMgr->pMsg)
+			status = DSP_EMEMORY;
+
+		DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
+		hIOMgr->ulDspVa = ulDspVa;
+		hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
+    }
+#endif
+	IO_EnableInterrupt(hIOMgr->hWmdContext);
+	return status;
+}
+
+/*
+ *  ======== IO_BufSize ========
+ *      Size of shared memory I/O channel.
+ */
+u32 IO_BufSize(struct IO_MGR *hIOMgr)
+{
+	DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+
+	return hIOMgr->uSMBufSize;
+}
+
+/*
+ *  ======== IO_CancelChnl ========
+ *      Cancel IO on a given PCPY channel.
+ */
+void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
+{
+	struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
+	struct SHM *sm;
+
+	DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+	sm = hIOMgr->pSharedMem;
+
+	/* Inform DSP that we have no more buffers on this channel:  */
+	IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
+		   (~(1 << ulChnl)));
+
+	IO_InterruptDSP(pIOMgr->hWmdContext);
+}
+
+/*
+ *  ======== IO_DispatchChnl ========
+ *      Proc-copy chanl dispatch.
+ */
+static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
+			   IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
+{
+	DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+	DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
+
+	/* See if there is any data available for transfer: */
+	DBC_Assert(iMode == IO_SERVICE);
+
+	/* Any channel will do for this mode: */
+	InputChnl(pIOMgr, pChnl, iMode);
+	OutputChnl(pIOMgr, pChnl, iMode);
+}
+
+/*
+ *  ======== IO_DispatchMsg ========
+ *      Performs I/O dispatch on message queues.
+ */
+static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+	DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+	DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
+
+	/*  We are performing both input and output processing. */
+	InputMsg(pIOMgr, hMsgMgr);
+	OutputMsg(pIOMgr, hMsgMgr);
+}
+
+/*
+ *  ======== IO_DispatchPM ========
+ *      Performs I/O dispatch on PM related messages from DSP
+ */
+static void IO_DispatchPM(IN struct IO_MGR *pIOMgr)
+{
+	DSP_STATUS status;
+	u32 pArg[2];
+
+	DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+	DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
+
+	/*  Perform Power message processing here  */
+	while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
+		pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
+			  iQuePowerTail]);
+		DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
+			 pArg[0]);
+		/* Send the command to the WMD clk/pwr manager to handle */
+		if (pArg[0] ==  MBX_PM_HIBERNATE_EN) {
+			DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
+				 "command\n");
+			status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+				 hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
+					 "Hibernation command failed\n");
+			}
+		} else if (pArg[0] == MBX_PM_OPP_REQ) {
+			pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
+			DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
+				 "value =0x%x \n", pArg[1]);
+			status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+				 hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
+				 pArg);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
+					 "to set constraint = 0x%x \n",
+					 pArg[1]);
+			}
+
+		} else {
+			DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
+				 "value of msg = 0x%x: \n", pArg[0]);
+			status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
+				 hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
+					 "to control the DSP clk = 0x%x \n",
+					 *pArg);
+			}
+		}
+		/* increment the tail count here */
+		pIOMgr->iQuePowerTail++;
+		if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
+			pIOMgr->iQuePowerTail = 0;
+
+	}
+}
+
+/*
+ *  ======== IO_DPC ========
+ *      Deferred procedure call for shared memory channel driver ISR.  Carries
+ *      out the dispatch of I/O as a non-preemptible event.It can only be
+ *      pre-empted      by an ISR.
+ */
+void IO_DPC(IN OUT void *pRefData)
+{
+	struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
+	struct CHNL_MGR *pChnlMgr;
+	struct MSG_MGR *pMsgMgr;
+	struct DEH_MGR *hDehMgr;
+
+	DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+	pChnlMgr = pIOMgr->hChnlMgr;
+	DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
+	DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
+	DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
+	DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
+	/* Check value of interrupt register to ensure it is a valid error */
+	if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
+		/* notify DSP/BIOS exception */
+		if (hDehMgr)
+			WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
+
+	}
+	/* Call WMD's DPC: */
+	IO_CALLDPC(pIOMgr->hWmdContext);
+	IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
+#ifdef CHNL_MESSAGES
+	if (pMsgMgr) {
+		DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
+		IO_DispatchMsg(pIOMgr, pMsgMgr);
+	}
+#endif
+#ifndef DSP_TRACEBUF_DISABLED
+	if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
+		/* notify DSP Trace message */
+		if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
+			PrintDSPDebugTrace(pIOMgr);
+	}
+#endif
+	IO_DispatchPM(pIOMgr);
+#ifndef DSP_TRACEBUF_DISABLED
+	PrintDSPDebugTrace(pIOMgr);
+#endif
+}
+
+
+/*
+ *  ======== IO_ISR ========
+ *      Main interrupt handler for the shared memory IO manager.
+ *      Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
+ *      schedules a DPC to dispatch I/O.
+ */
+bool IO_ISR(IN void *pRefData)
+{
+	struct IO_MGR *hIOMgr = (struct IO_MGR *)pRefData;
+	bool fSchedDPC;
+	DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
+	DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
+	/* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
+	if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
+		{
+			DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
+			if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
+				hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
+					hIOMgr->wIntrVal;
+				hIOMgr->iQuePowerHead++;
+				if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
+					hIOMgr->iQuePowerHead = 0;
+
+			}
+			if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
+				DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
+				hIOMgr->wIntrVal = 0;
+			} else if (fSchedDPC) {
+				/* PROC-COPY defer i/o  */
+				DPC_Schedule(hIOMgr->hDPC);
+			}
+		}
+		return true;
+	} else {
+		/* Ensure that, if WMD didn't claim it, the IRQ is shared. */
+		DBC_Ensure(hIOMgr->fSharedIRQ);
+		/* If not ours, return false. */
+		return false;
+	}
+}
+
+/*
+ *  ======== IO_RequestChnl ========
+ *  Purpose:
+ *      Request chanenel I/O from the DSP. Sets flags in shared memory, then
+ *      interrupts the DSP.
+ */
+void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+		   u32 iMode, OUT u16 *pwMbVal)
+{
+	struct CHNL_MGR *pChnlMgr;
+	struct SHM *sm;
+	DBC_Require(pChnl != NULL);
+	DBC_Require(pwMbVal != NULL);
+	pChnlMgr = pIOMgr->hChnlMgr;
+	sm = pIOMgr->pSharedMem;
+	if (iMode == IO_INPUT) {
+		/*  Assertion fires if CHNL_AddIOReq() called on a stream
+		 * which was cancelled, or attached to a dead board: */
+		DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
+			  (pChnl->dwState == CHNL_STATEEOS));
+		/* Indicate to the DSP we have a buffer available for input: */
+		IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
+			  (1 << pChnl->uId));
+		*pwMbVal = MBX_PCPY_CLASS;
+	} else if (iMode == IO_OUTPUT) {
+		/*  This assertion fails if CHNL_AddIOReq() was called on a
+		 * stream which was cancelled, or attached to a dead board: */
+		DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
+			  CHNL_STATEREADY);
+		/* Record the fact that we have a buffer available for
+		 * output: */
+		pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
+	} else {
+		DBC_Assert(iMode); 	/* Shouldn't get here. */
+	}
+}
+
+/*
+ *  ======== IO_Schedule ========
+ *      Schedule DPC for IO.
+ */
+void IO_Schedule(struct IO_MGR *pIOMgr)
+{
+	DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
+
+	DPC_Schedule(pIOMgr->hDPC);
+}
+
+/*
+ *  ======== FindReadyOutput ========
+ *      Search for a host output channel which is ready to send.  If this is
+ *      called as a result of servicing the DPC, then implement a round
+ *      robin search; otherwise, this was called by a client thread (via
+ *      IO_Dispatch()), so just start searching from the current channel id.
+ */
+static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
+			     struct CHNL_OBJECT *pChnl, u32 dwMask)
+{
+	u32 uRetval = OUTPUTNOTREADY;
+	u32 id, startId;
+	u32 shift;
+
+	id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
+	id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
+	DBC_Assert(id < CHNL_MAXCHANNELS);
+	if (dwMask) {
+		shift = (1 << id);
+		startId = id;
+		do {
+			if (dwMask & shift) {
+				uRetval = id;
+				if (pChnl == NULL)
+					pChnlMgr->dwLastOutput = id;
+
+				break;
+			}
+			id = id + 1;
+			id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
+			shift = (1 << id);
+		} while (id != startId);
+	}
+	DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
+	return uRetval;
+}
+
+/*
+ *  ======== InputChnl ========
+ *      Dispatch a buffer on an input channel.
+ */
+static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+		      u32 iMode)
+{
+	struct CHNL_MGR *pChnlMgr;
+	struct SHM *sm;
+	u32 chnlId;
+	u32 uBytes;
+	struct CHNL_IRP *pChirp = NULL;
+	u32 dwArg;
+	bool fClearChnl = false;
+	bool fNotifyClient = false;
+
+	sm = pIOMgr->pSharedMem;
+	pChnlMgr = pIOMgr->hChnlMgr;
+
+	DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
+
+	/* Attempt to perform input.... */
+	if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
+		goto func_end;
+
+	uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
+			    pChnlMgr->uWordSize;
+	chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
+	dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
+	if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
+		/* Shouldn't be here: would indicate corrupted SHM. */
+		DBC_Assert(chnlId);
+		goto func_end;
+	}
+	pChnl = pChnlMgr->apChannel[chnlId];
+	if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
+		if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
+			/* Get the I/O request, and attempt a transfer:  */
+			pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
+				 pIORequests);
+			if (pChirp) {
+				pChnl->cIOReqs--;
+				DBC_Assert(pChnl->cIOReqs >= 0);
+				/* Ensure we don't overflow the client's
+				 * buffer: */
+				uBytes = min(uBytes, pChirp->cBytes);
+				/* Transfer buffer from DSP side: */
+				uBytes = ReadData(pIOMgr->hWmdContext,
+						pChirp->pHostSysBuf,
+						pIOMgr->pInput, uBytes);
+				pChnl->cBytesMoved += uBytes;
+				pChirp->cBytes = uBytes;
+				pChirp->dwArg = dwArg;
+				pChirp->status = CHNL_IOCSTATCOMPLETE;
+				DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
+					 "\n", *((RMS_WORD *)(pChirp->
+					 pHostSysBuf)));
+				if (uBytes == 0) {
+					/* This assertion fails if the DSP
+					 * sends EOS more than once on this
+					 * channel: */
+					DBC_Assert(!(pChnl->dwState &
+						  CHNL_STATEEOS));
+					 /* Zero bytes indicates EOS. Update
+					  * IOC status for this chirp, and also
+					  * the channel state: */
+					pChirp->status |= CHNL_IOCSTATEOS;
+					pChnl->dwState |= CHNL_STATEEOS;
+					/* Notify that end of stream has
+					 * occurred */
+					NTFY_Notify(pChnl->hNtfy,
+						   DSP_STREAMDONE);
+					DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
+						 "chnl = 0x%x\n", pChnl);
+				}
+				/* Tell DSP if no more I/O buffers available: */
+				if (LST_IsEmpty(pChnl->pIORequests)) {
+					IO_AndValue(pIOMgr->hWmdContext,
+						   struct SHM, sm, hostFreeMask,
+						   ~(1 << pChnl->uId));
+				}
+				fClearChnl = true;
+				fNotifyClient = true;
+			} else {
+				/* Input full for this channel, but we have no
+				 * buffers available.  The channel must be
+				 * "idling". Clear out the physical input
+				 * channel.  */
+				fClearChnl = true;
+			}
+		} else {
+			/* Input channel cancelled:  clear input channel.  */
+			fClearChnl = true;
+		}
+	} else {
+		/* DPC fired after host closed channel: clear input channel. */
+		fClearChnl = true;
+	}
+	if (fClearChnl) {
+		/* Indicate to the DSP we have read the input: */
+		IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
+		IO_InterruptDSP(pIOMgr->hWmdContext);
+	}
+	if (fNotifyClient) {
+		/* Notify client with IO completion record:  */
+		NotifyChnlComplete(pChnl, pChirp);
+	}
+func_end:
+	DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
+}
+
+/*
+ *  ======== InputMsg ========
+ *      Copies messages from shared memory to the message queues.
+ */
+static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+	u32 uMsgs;
+	u32 i;
+	u8 *pMsgInput;
+	struct MSG_QUEUE *hMsgQueue;
+	struct MSG_FRAME *pMsg;
+	struct MSG_DSPMSG msg;
+	struct MSG *pCtrl;
+	u32 fInputEmpty;
+	u32 addr;
+
+	pCtrl = pIOMgr->pMsgInputCtrl;
+	/* Get the number of input messages to be read. */
+	fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				 bufEmpty);
+	uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
+	if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
+		return;
+
+	pMsgInput = pIOMgr->pMsgInput;
+	for (i = 0; i < uMsgs; i++) {
+		/* Read the next message */
+		addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
+		msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+		addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
+		msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+		addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
+		msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+		addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
+		msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
+		pMsgInput += sizeof(struct MSG_DSPMSG);
+		/* Determine which queue to put the message in */
+		hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
+		DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
+			 "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
+			 msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
+		 /*  Interrupt may occur before shared memory and message
+		 *  input locations have been set up. If all nodes were
+		 *  cleaned up, hMsgMgr->uMaxMsgs should be 0.  */
+		if (hMsgQueue)
+			DBC_Assert(uMsgs <= hMsgMgr->uMaxMsgs);
+
+		while (hMsgQueue != NULL) {
+			if (msg.dwId == hMsgQueue->dwId) {
+				/* Found it */
+				if (msg.msg.dwCmd == RMS_EXITACK) {
+					/* The exit message does not get
+					 * queued */
+					/* Call the node exit notification */
+					/* Node handle */ /* status */
+					(*hMsgMgr->onExit)((HANDLE)hMsgQueue->
+						hArg, msg.msg.dwArg1);
+				} else {
+					/* Not an exit acknowledgement, queue
+					 * the message */
+					pMsg = (struct MSG_FRAME *)LST_GetHead
+						(hMsgQueue->msgFreeList);
+					if (pMsg) {
+						pMsg->msgData = msg;
+						LST_PutTail(hMsgQueue->
+						      msgUsedList,
+						      (struct LST_ELEM *)pMsg);
+						NTFY_Notify(hMsgQueue->hNtfy,
+							DSP_NODEMESSAGEREADY);
+						SYNC_SetEvent(hMsgQueue->
+							hSyncEvent);
+					} else {
+						/* No free frame to copy the
+						 * message into */
+						DBG_Trace(DBG_LEVEL7, "NO FREE "
+							"MSG FRAMES, DISCARDING"
+							" MESSAGE\n");
+					}
+				}
+				break;
+			}
+			hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
+				    queueList, (struct LST_ELEM *)hMsgQueue);
+		}
+	}
+	/* Set the post SWI flag */
+	if (uMsgs > 0) {
+		/* Tell the DSP we've read the messages */
+		IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
+			   true);
+		IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
+			   true);
+		IO_InterruptDSP(pIOMgr->hWmdContext);
+	}
+}
+
+/*
+ *  ======== NotifyChnlComplete ========
+ *  Purpose:
+ *      Signal the channel event, notifying the client that I/O has completed.
+ */
+static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
+			      struct CHNL_IRP *pChirp)
+{
+	bool fSignalEvent;
+
+	DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
+	DBC_Require(pChnl->hSyncEvent != NULL);
+	 /*  Note: we signal the channel event only if the queue of IO
+	  *  completions is empty.  If it is not empty, the event is sure to be
+	  *  signalled by the only IO completion list consumer:
+	  *  WMD_CHNL_GetIOC().  */
+	fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
+	/* Enqueue the IO completion info for the client: */
+	LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
+	pChnl->cIOCs++;
+	DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
+	/* Signal the channel event (if not already set) that IO is complete: */
+	if (fSignalEvent)
+		SYNC_SetEvent(pChnl->hSyncEvent);
+
+	/* Notify that IO is complete */
+	NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
+}
+
+/*
+ *  ======== OutputChnl ========
+ *  Purpose:
+ *      Dispatch a buffer on an output channel.
+ */
+static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
+			u32 iMode)
+{
+	struct CHNL_MGR *pChnlMgr;
+	struct SHM *sm;
+	u32 chnlId;
+	struct CHNL_IRP *pChirp;
+	u32 dwDspFMask;
+
+	pChnlMgr = pIOMgr->hChnlMgr;
+	sm = pIOMgr->pSharedMem;
+	DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
+	/* Attempt to perform output: */
+	if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
+		goto func_end;
+
+	if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
+		goto func_end;
+
+	/* Look to see if both a PC and DSP output channel are ready: */
+	dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
+				 dspFreeMask);
+	chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
+				 dwDspFMask));
+	if (chnlId == OUTPUTNOTREADY)
+		goto func_end;
+
+	pChnl = pChnlMgr->apChannel[chnlId];
+	if (!pChnl) {
+		/* Shouldn't get here: */
+		DBC_Assert(pChnl == NULL);
+		goto func_end;
+	}
+	/* Get the I/O request, and attempt a transfer:  */
+	pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
+	if (!pChirp)
+		goto func_end;
+
+	pChnl->cIOReqs--;
+	DBC_Assert(pChnl->cIOReqs >= 0);
+	/* Record fact that no more I/O buffers available:  */
+	if (LST_IsEmpty(pChnl->pIORequests))
+		pChnlMgr->dwOutputMask &= ~(1 << chnlId);
+
+	/* Transfer buffer to DSP side: */
+	pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
+			pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
+			cBytes));
+	pChnl->cBytesMoved += pChirp->cBytes;
+	/* Write all 32 bits of arg */
+	IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
+#if _CHNL_WORDSIZE == 2
+	IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
+		   (u16)chnlId);
+	IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
+		   (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
+		   (u16)pChnlMgr->uWordSize);
+#else
+	IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
+	IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
+		   (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
+		   uWordSize);
+#endif
+	IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
+	/* Indicate to the DSP we have written the output: */
+	IO_InterruptDSP(pIOMgr->hWmdContext);
+	/* Notify client with IO completion record (keep EOS) */
+	pChirp->status &= CHNL_IOCSTATEOS;
+	NotifyChnlComplete(pChnl, pChirp);
+	/* Notify if stream is done. */
+	if (pChirp->status & CHNL_IOCSTATEOS)
+		NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
+
+func_end:
+	DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
+}
+/*
+ *  ======== OutputMsg ========
+ *      Copies messages from the message queues to the shared memory.
+ */
+static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
+{
+	u32 uMsgs = 0;
+	u32 i;
+	u8 *pMsgOutput;
+	struct MSG_FRAME *pMsg;
+	struct MSG *pCtrl;
+	u32 fOutputEmpty;
+	u32 val;
+	u32 addr;
+
+	pCtrl = pIOMgr->pMsgOutputCtrl;
+
+	/* Check if output has been cleared */
+	fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				  bufEmpty);
+	if (fOutputEmpty) {
+		uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
+			 hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
+		pMsgOutput = pIOMgr->pMsgOutput;
+		/* Copy uMsgs messages into shared memory */
+		for (i = 0; i < uMsgs; i++) {
+			pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
+				msgUsedList);
+			DBC_Assert(pMsg != NULL);
+			if (pMsg != NULL) {
+				val = (pMsg->msgData).dwId;
+				addr = (u32)&(((struct MSG_DSPMSG *)
+					pMsgOutput)->dwId);
+				WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+						     val);
+				val = (pMsg->msgData).msg.dwCmd;
+				addr = (u32)&((((struct MSG_DSPMSG *)
+					pMsgOutput)->msg).dwCmd);
+				WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+						     val);
+				val = (pMsg->msgData).msg.dwArg1;
+				addr =
+					(u32)&((((struct MSG_DSPMSG *)
+					pMsgOutput)->msg).dwArg1);
+				WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+						    val);
+				val = (pMsg->msgData).msg.dwArg2;
+				addr =
+					(u32)&((((struct MSG_DSPMSG *)
+					pMsgOutput)->msg).dwArg2);
+				WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
+						    val);
+				pMsgOutput += sizeof(struct MSG_DSPMSG);
+				LST_PutTail(hMsgMgr->msgFreeList,
+					   (struct LST_ELEM *) pMsg);
+				SYNC_SetEvent(hMsgMgr->hSyncEvent);
+			} else {
+				DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
+			}
+		}
+
+		if (uMsgs > 0) {
+			hMsgMgr->uMsgsPending -= uMsgs;
+#if _CHNL_WORDSIZE == 2
+			IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				   size, (u16)uMsgs);
+#else
+			IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				   size, uMsgs);
+#endif
+			IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				   bufEmpty, false);
+			/* Set the post SWI flag */
+			IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
+				   postSWI, true);
+			/* Tell the DSP we have written the output. */
+			IO_InterruptDSP(pIOMgr->hWmdContext);
+		}
+	}
+}
+
+/*
+ *  ======== registerSHMSegs ========
+ *  purpose:
+ *      Registers GPP SM segment with CMM.
+ */
+static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
+				 struct COD_MANAGER *hCodMan,
+				 u32 dwGPPBasePA)
+{
+	DSP_STATUS status = DSP_SOK;
+	u32 ulShm0_Base = 0;
+	u32 ulShm0_End = 0;
+	u32 ulShm0_RsrvdStart = 0;
+	u32 ulRsrvdSize = 0;
+	u32 ulGppPhys;
+	u32 ulDspVirt;
+	u32 ulShmSegId0 = 0;
+	u32 dwOffset, dwGPPBaseVA, ulDSPSize;
+
+	/* Read address and size info for first SM region.*/
+	/* Get start of 1st SM Heap region */
+	status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
+	DBC_Assert(ulShm0_Base != 0);
+	/* Get end of 1st SM Heap region */
+	if (DSP_SUCCEEDED(status)) {
+		/* Get start and length of message part of shared memory */
+		status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
+					 &ulShm0_End);
+		DBC_Assert(ulShm0_End != 0);
+	}
+	/* start of Gpp reserved region */
+	if (DSP_SUCCEEDED(status)) {
+		/* Get start and length of message part of shared memory */
+		status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
+					&ulShm0_RsrvdStart);
+		DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart  0x%x \n",
+			 ulShm0_RsrvdStart);
+		DBC_Assert(ulShm0_RsrvdStart != 0);
+	}
+	/* Register with CMM */
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
+		if (DSP_SUCCEEDED(status)) {
+			status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
+				 CMM_ALLSEGMENTS);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
+					 "Un-Register SM segments \n");
+			}
+		} else {
+			DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
+				 "Handle \n");
+		}
+	}
+	/* Register new SM region(s) */
+	if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
+		/* calc size (bytes) of SM the GPP can alloc from */
+		ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
+			      uWordSize;
+		DBC_Assert(ulRsrvdSize > 0);
+		/* calc size of SM DSP can alloc from */
+		ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
+			uWordSize;
+		DBC_Assert(ulDSPSize > 0);
+		/*  First TLB entry reserved for Bridge SM use.*/
+		ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
+		/* get size in bytes */
+		ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
+			uWordSize;
+		 /* Calc byte offset used to convert GPP phys <-> DSP byte
+		  * address.*/
+		if (dwGPPBasePA > ulDspVirt)
+			dwOffset = dwGPPBasePA - ulDspVirt;
+		else
+			dwOffset = ulDspVirt - dwGPPBasePA;
+
+		DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
+		/* calc Gpp phys base of SM region */
+		/* Linux - this is actually uncached kernel virtual address*/
+		dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
+				- ulDspVirt;
+		/* calc Gpp phys base of SM region */
+		/* Linux - this is the physical address*/
+		dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
+			      uWordSize - ulDspVirt;
+		 /* Register SM Segment 0.*/
+		status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
+			 ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
+			 CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
+			 (u32)(ulShm0_Base * hIOMgr->uWordSize),
+			 ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
+		if (DSP_FAILED(status)) {
+			DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
+				 "Seg 0 \n");
+		}
+		/* first SM region is segId = 1 */
+		DBC_Assert(ulShmSegId0 == 1);
+	}
+	return status;
+}
+
+/*
+ *  ======== ReadData ========
+ *      Copies buffers from the shared memory to the host buffer.
+ */
+static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+		     void *pSrc, u32 uSize)
+{
+	memcpy(pDest, pSrc, uSize);
+	return uSize;
+}
+
+/*
+ *  ======== WriteData ========
+ *      Copies buffers from the host side buffer to the shared memory.
+ */
+static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
+		       void *pSrc, u32 uSize)
+{
+	memcpy(pDest, pSrc, uSize);
+	return uSize;
+}
+
+/* ZCPY IO routines. */
+void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
+{
+	IO_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
+}
+
+/*
+ *  ======== IO_SHMcontrol ========
+ *      Sets the requested SHM setting.
+ */
+DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
+			 IN void *pArgs)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	u32 i;
+
+	switch (desc) {
+	case SHM_CURROPP:
+		/* Update the shared memory with requested OPP information */
+		if (pArgs != NULL)
+			hIOMgr->pSharedMem->oppTableStruct.currOppPt =
+				*(u32 *)pArgs;
+		else
+			return DSP_EFAIL;
+		break;
+	case SHM_OPPINFO:
+		/* Update the shared memory with the voltage, frequency,
+				   min and max frequency values for an OPP */
+		for (i = 0; i <= dsp_max_opps; i++) {
+			hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
+				vdd1_dsp_freq[i][0];
+			DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
+				 "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+				 oppPoint[i].voltage);
+			hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
+				frequency = vdd1_dsp_freq[i][1];
+			DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
+				 "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+				 oppPoint[i].frequency);
+			hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
+				vdd1_dsp_freq[i][2];
+			DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
+				 "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+				  oppPoint[i].minFreq);
+			hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
+				vdd1_dsp_freq[i][3];
+			DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
+				 "%d\n", hIOMgr->pSharedMem->oppTableStruct.
+				 oppPoint[i].maxFreq);
+		}
+		hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
+		DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
+			 "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
+		/* Update the current OPP number */
+		i = constraint_get_level(dsp_constraint_handle);
+		hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
+		DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
+			 "%d\n", i);
+		break;
+	case SHM_GETOPP:
+		/* Get the OPP that DSP has requested */
+		*(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
+		break;
+	default:
+		break;
+
+	}
+#endif
+#endif
+	return DSP_SOK;
+}
+
+/*
+ *  ======== WMD_IO_GetProcLoad ========
+ *      Gets the Processor's Load information
+ */
+DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
+			     OUT struct DSP_PROCLOADSTAT *pProcStat)
+{
+	pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
+	pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
+	pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
+	pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
+
+	DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
+			     "Pred Freq = %d\n", pProcStat->uCurrLoad,
+			     pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
+			     pProcStat->uPredictedFreq);
+	return DSP_SOK;
+}
+
+#ifndef DSP_TRACEBUF_DISABLED
+void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
+{
+	u32 ulNewMessageLength = 0, ulGPPCurPointer;
+
+	while (true) {
+		/* Get the DSP current pointer */
+		ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
+		ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
+				  hIOMgr->ulDspVa);
+
+		/* No new debug messages available yet */
+		if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
+			break;
+
+		/* Continuous data */
+		else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
+			ulNewMessageLength = ulGPPCurPointer - hIOMgr->
+					     ulGPPReadPointer;
+
+			memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
+			       ulNewMessageLength);
+			hIOMgr->pMsg[ulNewMessageLength] = '\0';
+			/* Advance the GPP trace pointer to DSP current
+			 * pointer */
+			hIOMgr->ulGPPReadPointer += ulNewMessageLength;
+			/* Print the trace messages */
+			DBG_Trace(DBG_LEVEL3, "hIOMgr->pMsg=0x%x",
+				 hIOMgr->pMsg);
+		}
+		/* Handle trace buffer wraparound */
+		else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
+			memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
+				hIOMgr->ulTraceBufferEnd -
+				hIOMgr->ulGPPReadPointer);
+			ulNewMessageLength = ulGPPCurPointer -
+				hIOMgr->ulTraceBufferBegin;
+			memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
+				hIOMgr->ulGPPReadPointer],
+				(char *)hIOMgr->ulTraceBufferBegin,
+				ulNewMessageLength);
+			hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
+				hIOMgr->ulGPPReadPointer +
+				ulNewMessageLength] = '\0';
+			/* Advance the GPP trace pointer to DSP current
+			 * pointer */
+			hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
+						   ulNewMessageLength;
+			/* Print the trace messages */
+			DBG_Trace(DBG_LEVEL3, "hIOMgr->pMsg=0x%x",
+				 hIOMgr->pMsg);
+		}
+	}
+}
+#endif
+
diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
new file mode 100644
index 0000000..346756a
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/mmu_fault.c
@@ -0,0 +1,171 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/mmu_fault.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== mmu_fault.c ========
+ *  Description:
+ *      Implements DSP MMU fault handling functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Dec-2004 hn: Support for IVA MMU exception.
+ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
+ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
+ *! 05-Jan-2004 vp: Updated support for 24xx silicon
+ *! 19-Feb-2003 vp: Code review updates.
+ *!                 - Cosmetic changes.
+ *! 18-Oct-2002 sb: Ported to Linux platform.
+ *! 10-Sep-2001 kc: created.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <host_os.h>
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <dpc.h>
+#include <mem.h>
+#include <drv.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmddeh.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/*  ----------------------------------- This */
+#include "_deh.h"
+#include "_tiomap_mmu.h"
+#include "_tiomap.h"
+#include "mmu_fault.h"
+
+u32 dmmuEventMask;
+u32 faultAddr;
+
+static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
+
+/*
+ *  ======== MMU_FaultDpc ========
+ *      Deferred procedure call to handle DSP MMU fault.
+ */
+void MMU_FaultDpc(IN void *pRefData)
+{
+	struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+	DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
+
+	if (pDehMgr)
+		WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
+
+	DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
+}
+
+/*
+ *  ======== MMU_FaultIsr ========
+ *      ISR to be triggered by a DSP MMU fault interrupt.
+ */
+void MMU_FaultIsr(IN void *pRefData)
+{
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
+	struct WMD_DEV_CONTEXT *pDevContext;
+	struct CFG_HOSTRES resources;
+	DSP_STATUS status = DSP_SOK;
+
+
+	DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
+
+	DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
+
+	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+
+		pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
+		status = CFG_GetHostResources(
+			 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			 &resources);
+		if (DSP_FAILED(status))
+			DBG_Trace(DBG_LEVEL7,
+				 "**Failed to get Host Resources "
+				 "in MMU ISR **\n");
+		if (MMU_CheckIfFault(pDevContext)) {
+			printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
+				"0x%x\n", dmmuEventMask);
+			printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
+				"0x%x\n", faultAddr);
+			/* Disable the MMU events, else once we clear it will
+			 * start to raise INTs again */
+			/*
+			 * Schedule a DPC directly. In the future, it may be
+			 * necessary to check if DSP MMU fault is intended for
+			 * Bridge.
+			 */
+			DPC_Schedule(pDehMgr->hMmuFaultDpc);
+			/* Reset errInfo structure before use. */
+			pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
+			pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
+			pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
+			pDehMgr->errInfo.dwVal3 = 0L;
+			/* Disable the MMU events, else once we clear it will
+			 * start to raise INTs again */
+			HW_MMU_EventDisable(resources.dwDmmuBase,
+					    HW_MMU_TRANSLATION_FAULT);
+		} else {
+			DBG_Trace(DBG_LEVEL7,
+				 "***** MMU FAULT ***** faultcode 0x%x\n",
+				 dmmuEventMask);
+			HW_MMU_EventDisable(resources.dwDmmuBase,
+					    HW_MMU_ALL_INTERRUPTS);
+		}
+		PrintDspTraceBuffer(pDehMgr);
+	}
+}
+
+
+/*
+ *  ======== MMU_CheckIfFault ========
+ *      Check to see if MMU Fault is valid TLB miss from DSP
+ *  Note: This function is called from an ISR
+ */
+static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
+{
+
+
+	bool retVal = false;
+	DSP_STATUS status = DSP_SOK;
+	HW_STATUS hwStatus;
+	struct CFG_HOSTRES resources;
+	status = CFG_GetHostResources(
+		(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status))
+		DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
+			 "MMU_CheckIfFault **\n");
+
+	hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
+	if (dmmuEventMask  ==  HW_MMU_TRANSLATION_FAULT) {
+		HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
+		DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
+			 "address = 0x%x\n", faultAddr);
+		retVal = true;
+	}
+	return retVal;
+}
diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
new file mode 100644
index 0000000..47602a9
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/mmu_fault.h
@@ -0,0 +1,52 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/mmu_fault.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== mmu_fault.h ========
+ *  Description:
+ *      Defines DSP MMU fault handling functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 26-Dec-2004 hn: IVA MMU handlers.
+ *! 10-Sep-2001 kc: created.
+ */
+
+#ifndef MMU_FAULT_
+#define MMU_FAULT_
+
+/*
+ *  ======== MMU_FaultDpc ========
+ *      Deferred procedure call to handle DSP MMU fault.
+ */
+	void MMU_FaultDpc(IN void *pRefData);
+
+/*
+ *  ======== MMU_FaultIsr ========
+ *      ISR to be triggered by a DSP MMU fault interrupt.
+ */
+	void MMU_FaultIsr(IN void *pRefData);
+
+/*
+ *  ========PrintDspTraceBuffer ========
+ *      Print DSP tracebuffer.
+ */
+
+extern DSP_STATUS  PrintDspTraceBuffer(struct DEH_MGR *hDehMgr);
+
+#endif				/* MMU_FAULT_ */
+
diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
new file mode 100644
index 0000000..25e3fe1
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/msg_sm.c
@@ -0,0 +1,599 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/wmdchnl/common/msg_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== msg_sm.c ========
+ *  Description:
+ *      Implements upper edge functions for WMD message module.
+ *
+ *  Public Functions:
+ *      WMD_MSG_Create
+ *      WMD_MSG_CreateQueue
+ *      WMD_MSG_Delete
+ *      WMD_MSG_DeleteQueue
+ *      WMD_MSG_Get
+ *      WMD_MSG_Put
+ *      WMD_MSG_RegisterNotify
+ *      WMD_MSG_SetQueueId
+ *
+ *! Revision History:
+ *! =================
+ *! 24-Jul-2002 jeh     Release critical section in WMD_MSG_Put() before
+ *!                     scheduling DPC.
+ *! 09-May-2001 jeh     Free MSG queue NTFY object, remove unnecessary set/
+ *!                     reset of events.
+ *! 10-Jan-2001 jeh     Set/Reset message manager and message queue events
+ *!                     correctly.
+ *! 04-Dec-2000 jeh     Bug fixes.
+ *! 12-Sep-2000 jeh     Created.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <list.h>
+#include <mem.h>
+#include <sync.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+
+/*  ----------------------------------- Others */
+#include <io_sm.h>
+
+/*  ----------------------------------- This */
+#include <_msg_sm.h>
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define MSGQ_SIGNATURE      0x5147534d	/* "QGSM" */
+
+/*  ----------------------------------- Function Prototypes */
+static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
+static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
+static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
+static void FreeMsgList(struct LST_LIST *msgList);
+
+/*
+ *  ======== WMD_MSG_Create ========
+ *      Create an object to manage message queues. Only one of these objects
+ *      can exist per device object.
+ */
+DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
+			 struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
+{
+	struct MSG_MGR *pMsgMgr;
+	struct IO_MGR *hIOMgr;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(phMsgMgr != NULL);
+	DBC_Require(msgCallback != NULL);
+	DBC_Require(hDevObject != NULL);
+	DEV_GetIOMgr(hDevObject, &hIOMgr);
+	DBC_Assert(hIOMgr != NULL);
+	*phMsgMgr = NULL;
+	/* Allocate MSG manager object */
+	MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
+
+	if (pMsgMgr) {
+		pMsgMgr->onExit = msgCallback;
+		pMsgMgr->hIOMgr = hIOMgr;
+		/* List of MSG_QUEUEs */
+		pMsgMgr->queueList = LST_Create();
+		 /*  Queues of message frames for messages to the DSP. Message
+		  * frames will only be added to the free queue when a
+		  * MSG_QUEUE object is created.  */
+		pMsgMgr->msgFreeList = LST_Create();
+		pMsgMgr->msgUsedList = LST_Create();
+		if (pMsgMgr->queueList == NULL ||
+		    pMsgMgr->msgFreeList == NULL ||
+		    pMsgMgr->msgUsedList == NULL)
+			status = DSP_EMEMORY;
+		if (DSP_SUCCEEDED(status))
+			status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
+
+		 /*  Create an event to be used by WMD_MSG_Put() in waiting
+		 *  for an available free frame from the message manager.  */
+		if (DSP_SUCCEEDED(status))
+			status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
+
+		if (DSP_SUCCEEDED(status))
+			*phMsgMgr = pMsgMgr;
+		else
+			DeleteMsgMgr(pMsgMgr);
+
+	} else {
+		status = DSP_EMEMORY;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_MSG_CreateQueue ========
+ *      Create a MSG_QUEUE for sending/receiving messages to/from a node
+ *      on the DSP.
+ */
+DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
+			      OUT struct MSG_QUEUE **phMsgQueue,
+			      u32 dwId, u32 uMaxMsgs, HANDLE hArg)
+{
+	u32 i;
+	u32 uNumAllocated = 0;
+	struct MSG_QUEUE *pMsgQ;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+	DBC_Require(phMsgQueue != NULL);
+
+	*phMsgQueue = NULL;
+	/* Allocate MSG_QUEUE object */
+	MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
+	if (!pMsgQ) {
+		status = DSP_EMEMORY;
+		goto func_end;
+	}
+	LST_InitElem((struct LST_ELEM *) pMsgQ);
+	pMsgQ->uMaxMsgs = uMaxMsgs;
+	pMsgQ->hMsgMgr = hMsgMgr;
+	pMsgQ->hArg = hArg;	/* Node handle */
+	pMsgQ->dwId = dwId;	/* Node env (not valid yet) */
+	/* Queues of Message frames for messages from the DSP */
+	pMsgQ->msgFreeList = LST_Create();
+	pMsgQ->msgUsedList = LST_Create();
+	if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
+		status = DSP_EMEMORY;
+
+	 /*  Create event that will be signalled when a message from
+	 *  the DSP is available.  */
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
+
+	/* Create a notification list for message ready notification. */
+	if (DSP_SUCCEEDED(status))
+		status = NTFY_Create(&pMsgQ->hNtfy);
+
+	 /*  Create events that will be used to synchronize cleanup
+	 *  when the object is deleted. hSyncDone will be set to
+	 *  unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
+	 *  will be set by the unblocked thread to signal that it
+	 *  is unblocked and will no longer reference the object.  */
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
+
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Enter critical section */
+		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+		/* Initialize message frames and put in appropriate queues */
+		for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
+			status = AddNewMsg(hMsgMgr->msgFreeList);
+			if (DSP_SUCCEEDED(status)) {
+				uNumAllocated++;
+				status = AddNewMsg(pMsgQ->msgFreeList);
+			}
+		}
+		if (DSP_FAILED(status)) {
+			/*  Stay inside CS to prevent others from taking any
+			 *  of the newly allocated message frames.  */
+			DeleteMsgQueue(pMsgQ, uNumAllocated);
+		} else {
+			LST_PutTail(hMsgMgr->queueList,
+				   (struct LST_ELEM *)pMsgQ);
+			*phMsgQueue = pMsgQ;
+			/* Signal that free frames are now available */
+			if (!LST_IsEmpty(hMsgMgr->msgFreeList))
+				SYNC_SetEvent(hMsgMgr->hSyncEvent);
+
+		}
+		/* Exit critical section */
+		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+	} else {
+		DeleteMsgQueue(pMsgQ, 0);
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== WMD_MSG_Delete ========
+ *      Delete a MSG manager allocated in WMD_MSG_Create().
+ */
+void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
+{
+	DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+
+	DeleteMsgMgr(hMsgMgr);
+}
+
+/*
+ *  ======== WMD_MSG_DeleteQueue ========
+ *      Delete a MSG queue allocated in WMD_MSG_CreateQueue.
+ */
+void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
+{
+	struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
+	u32 refCount;
+
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+	hMsgQueue->fDone = true;
+	 /*  Unblock all threads blocked in MSG_Get() or MSG_Put().  */
+	refCount = hMsgQueue->refCount;
+	while (refCount) {
+		/* Unblock thread */
+		SYNC_SetEvent(hMsgQueue->hSyncDone);
+		/* Wait for acknowledgement */
+		SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
+		refCount = hMsgQueue->refCount;
+	}
+	/* Remove message queue from hMsgMgr->queueList */
+	(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+	LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
+	/* Free the message queue object */
+	DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
+	if (LST_IsEmpty(hMsgMgr->msgFreeList))
+		SYNC_ResetEvent(hMsgMgr->hSyncEvent);
+
+	(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+}
+
+/*
+ *  ======== WMD_MSG_Get ========
+ *      Get a message from a MSG queue.
+ */
+DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
+		      struct DSP_MSG *pMsg, u32 uTimeout)
+{
+	struct MSG_FRAME *pMsgFrame;
+	struct MSG_MGR *hMsgMgr;
+	bool fGotMsg = false;
+	struct SYNC_OBJECT *hSyncs[2];
+	u32 uIndex;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+	DBC_Require(pMsg != NULL);
+
+	hMsgMgr = hMsgQueue->hMsgMgr;
+	/* Enter critical section */
+	(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+	/* If a message is already there, get it */
+	if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
+		pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
+			    msgUsedList);
+		if (pMsgFrame != NULL) {
+			*pMsg = pMsgFrame->msgData.msg;
+			LST_PutTail(hMsgQueue->msgFreeList,
+				   (struct LST_ELEM *)pMsgFrame);
+			if (LST_IsEmpty(hMsgQueue->msgUsedList))
+				SYNC_ResetEvent(hMsgQueue->hSyncEvent);
+
+			fGotMsg = true;
+		}
+	} else {
+		if (hMsgQueue->fDone)
+			status = DSP_EFAIL;
+		else
+			hMsgQueue->refCount++;
+
+	}
+	/* Exit critical section */
+	(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+	if (DSP_SUCCEEDED(status) && !fGotMsg) {
+		/*  Wait til message is available, timeout, or done. We don't
+		 *  have to schedule the DPC, since the DSP will send messages
+		 *  when they are available.  */
+		hSyncs[0] = hMsgQueue->hSyncEvent;
+		hSyncs[1] = hMsgQueue->hSyncDone;
+		status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
+			 &uIndex);
+		/* Enter critical section */
+		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+		if (hMsgQueue->fDone) {
+			hMsgQueue->refCount--;
+			/* Exit critical section */
+			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+			 /*  Signal that we're not going to access hMsgQueue
+			  *  anymore, so it can be deleted.  */
+			(void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
+			status = DSP_EFAIL;
+		} else {
+			if (DSP_SUCCEEDED(status)) {
+				DBC_Assert(!LST_IsEmpty(hMsgQueue->
+					  msgUsedList));
+				/* Get msg from used list */
+				pMsgFrame = (struct MSG_FRAME *)
+					   LST_GetHead(hMsgQueue->msgUsedList);
+				/* Copy message into pMsg and put frame on the
+				 * free list */
+				if (pMsgFrame != NULL) {
+					*pMsg = pMsgFrame->msgData.msg;
+					LST_PutTail(hMsgQueue->msgFreeList,
+					(struct LST_ELEM *)pMsgFrame);
+				}
+			}
+			hMsgQueue->refCount--;
+			/* Reset the event if there are still queued messages */
+			if (!LST_IsEmpty(hMsgQueue->msgUsedList))
+				SYNC_SetEvent(hMsgQueue->hSyncEvent);
+
+			/* Exit critical section */
+			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_MSG_Put ========
+ *      Put a message onto a MSG queue.
+ */
+DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
+		      IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
+{
+	struct MSG_FRAME *pMsgFrame;
+	struct MSG_MGR *hMsgMgr;
+	bool fPutMsg = false;
+	struct SYNC_OBJECT *hSyncs[2];
+	u32 uIndex;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+	DBC_Require(pMsg != NULL);
+
+	hMsgMgr = hMsgQueue->hMsgMgr;
+
+	(void) SYNC_EnterCS(hMsgMgr->hSyncCS);
+
+	/* If a message frame is available, use it */
+	if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
+		pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
+			    msgFreeList);
+		if (pMsgFrame != NULL) {
+			pMsgFrame->msgData.msg = *pMsg;
+			pMsgFrame->msgData.dwId = hMsgQueue->dwId;
+			LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
+				   pMsgFrame);
+			hMsgMgr->uMsgsPending++;
+			fPutMsg = true;
+		}
+		if (LST_IsEmpty(hMsgMgr->msgFreeList))
+			SYNC_ResetEvent(hMsgMgr->hSyncEvent);
+
+		/* Release critical section before scheduling DPC */
+		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+		/* Schedule a DPC, to do the actual data transfer: */
+		IO_Schedule(hMsgMgr->hIOMgr);
+	} else {
+		if (hMsgQueue->fDone)
+			status = DSP_EFAIL;
+		else
+			hMsgQueue->refCount++;
+
+		(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+	}
+	if (DSP_SUCCEEDED(status) && !fPutMsg) {
+		/* Wait til a free message frame is available, timeout,
+		 * or done */
+		hSyncs[0] = hMsgMgr->hSyncEvent;
+		hSyncs[1] = hMsgQueue->hSyncDone;
+		status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
+			 &uIndex);
+		/* Enter critical section */
+		(void)SYNC_EnterCS(hMsgMgr->hSyncCS);
+		if (hMsgQueue->fDone) {
+			hMsgQueue->refCount--;
+			/* Exit critical section */
+			(void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
+			 /*  Signal that we're not going to access hMsgQueue
+			  *  anymore, so it can be deleted.  */
+			(void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
+			status = DSP_EFAIL;
+		} else {
+			if (DSP_SUCCEEDED(status)) {
+				DBC_Assert(!LST_IsEmpty(hMsgMgr->msgFreeList));
+				/* Get msg from free list */
+				pMsgFrame = (struct MSG_FRAME *)
+					    LST_GetHead(hMsgMgr->msgFreeList);
+				/* Copy message into pMsg and put frame on the
+				 * used list */
+				if (pMsgFrame != NULL) {
+					pMsgFrame->msgData.msg = *pMsg;
+					pMsgFrame->msgData.dwId =
+						hMsgQueue->dwId;
+					LST_PutTail(hMsgMgr->msgUsedList,
+						   (struct LST_ELEM *)
+						   pMsgFrame);
+					hMsgMgr->uMsgsPending++;
+					/* Schedule a DPC, to do the actual
+					 * data transfer: */
+					IO_Schedule(hMsgMgr->hIOMgr);
+				}
+			}
+			hMsgQueue->refCount--;
+			/* Reset event if there are still frames available */
+			if (!LST_IsEmpty(hMsgMgr->msgFreeList))
+				SYNC_SetEvent(hMsgMgr->hSyncEvent);
+
+			/* Exit critical section */
+			(void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_MSG_RegisterNotify ========
+ */
+DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
+				  u32 uNotifyType,
+				  struct DSP_NOTIFICATION *hNotification)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+	DBC_Require(hNotification != NULL);
+	DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
+	DBC_Require(uNotifyType == DSP_SIGNALEVENT);
+
+	status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
+			      uNotifyType);
+
+	if (status == DSP_EVALUE) {
+		/*  Not registered. Ok, since we couldn't have known. Node
+		 *  notifications are split between node state change handled
+		 *  by NODE, and message ready handled by MSG.  */
+		status = DSP_SOK;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== WMD_MSG_SetQueueId ========
+ */
+void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
+{
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+	/* DBC_Require(dwId != 0); */
+
+	/*
+	 *  A message queue must be created when a node is allocated,
+	 *  so that NODE_RegisterNotify() can be called before the node
+	 *  is created. Since we don't know the node environment until the
+	 *  node is created, we need this function to set hMsgQueue->dwId
+	 *  to the node environment, after the node is created.
+	 */
+	hMsgQueue->dwId = dwId;
+}
+
+/*
+ *  ======== AddNewMsg ========
+ *      Must be called in message manager critical section.
+ */
+static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
+{
+	struct MSG_FRAME *pMsg;
+	DSP_STATUS status = DSP_SOK;
+
+	pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
+		MEM_PAGED);
+	if (pMsg != NULL) {
+		LST_InitElem((struct LST_ELEM *) pMsg);
+		LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
+	} else {
+		status = DSP_EMEMORY;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DeleteMsgMgr ========
+ */
+static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
+{
+	DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
+
+	if (hMsgMgr->queueList) {
+		DBC_Assert(LST_IsEmpty(hMsgMgr->queueList));
+		LST_Delete(hMsgMgr->queueList);
+	}
+
+	if (hMsgMgr->msgFreeList)
+		FreeMsgList(hMsgMgr->msgFreeList);
+
+	if (hMsgMgr->msgUsedList)
+		FreeMsgList(hMsgMgr->msgUsedList);
+
+	if (hMsgMgr->hSyncEvent)
+		SYNC_CloseEvent(hMsgMgr->hSyncEvent);
+
+	if (hMsgMgr->hSyncCS)
+		SYNC_DeleteCS(hMsgMgr->hSyncCS);
+
+	MEM_FreeObject(hMsgMgr);
+}
+
+/*
+ *  ======== DeleteMsgQueue ========
+ */
+static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
+{
+	struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
+	struct MSG_FRAME *pMsg;
+	u32 i;
+
+	DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
+
+	/* Pull off uNumToDSP message frames from Msg manager and free */
+	for (i = 0; i < uNumToDSP; i++) {
+
+		if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
+			pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
+				msgFreeList);
+			MEM_Free(pMsg);
+		} else {
+			/* Cannot free all of the message frames */
+			break;
+		}
+	}
+
+	if (hMsgQueue->msgFreeList)
+		FreeMsgList(hMsgQueue->msgFreeList);
+
+	if (hMsgQueue->msgUsedList)
+		FreeMsgList(hMsgQueue->msgUsedList);
+
+	if (hMsgQueue->hNtfy)
+		NTFY_Delete(hMsgQueue->hNtfy);
+
+	if (hMsgQueue->hSyncEvent)
+		SYNC_CloseEvent(hMsgQueue->hSyncEvent);
+
+	if (hMsgQueue->hSyncDone)
+		SYNC_CloseEvent(hMsgQueue->hSyncDone);
+
+	if (hMsgQueue->hSyncDoneAck)
+		SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
+
+	MEM_FreeObject(hMsgQueue);
+}
+
+/*
+ *  ======== FreeMsgList ========
+ */
+static void FreeMsgList(struct LST_LIST *msgList)
+{
+	struct MSG_FRAME *pMsg;
+
+	DBC_Require(msgList != NULL);
+
+	while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
+		MEM_Free(pMsg);
+
+	DBC_Assert(LST_IsEmpty(msgList));
+
+	LST_Delete(msgList);
+}
+
diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
new file mode 100644
index 0000000..e8c6b33
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap3430.c
@@ -0,0 +1,2171 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/3430/tiomap.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== tiomap.c ========
+ *  Processor Manager Driver for TI OMAP3430 EVM.
+ *
+ *  Public Function:
+ *      WMD_DRV_Entry
+ *
+ *! Revision History:
+ *! ================
+ *   26-March-2008 HK and AL:  Added WMD_DEV_WalkTbl funciton.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <mem.h>
+#include <util.h>
+#include <reg.h>
+#include <dbreg.h>
+#include <cfg.h>
+#include <drv.h>
+#include <csl.h>
+#include <sync.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_dspssC64P.h>
+#include <hw_prcm.h>
+#include <hw_mmu.h>
+#include <hw_mbox.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmd.h>
+#include <wmdchnl.h>
+#include <wmddeh.h>
+#include <wmdio.h>
+#include <wmdmsg.h>
+#include <pwr.h>
+#include <chnl_sm.h>
+#include <io_sm.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+#include <wcd.h>
+#include <dmm.h>
+
+/*  ----------------------------------- Local */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "_tiomap_mmu.h"
+#include "_tiomap_util.h"
+#include "tiomap_io.h"
+
+/* Offset in shared mem to write to in order to synchronize start with DSP */
+#define SHMSYNCOFFSET 4		/* GPP byte offset */
+
+#define BUFFERSIZE 1024
+
+#define MMU_SECTION_ADDR_MASK    0xFFF00000
+#define MMU_SSECTION_ADDR_MASK   0xFF000000
+#define MMU_LARGE_PAGE_MASK      0xFFFF0000
+#define MMU_SMALL_PAGE_MASK      0xFFFFF000
+#define PAGES_II_LVL_TABLE   512
+/* Forward Declarations: */
+static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
+static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
+			OUT u8 *pbHostBuf,
+			u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
+			u32 dwDSPAddr);
+static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
+			OUT BRD_STATUS *pdwState);
+static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
+static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
+			IN u8 *pbHostBuf,
+			u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
+			u32 ulBrdState);
+static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
+			u32 ulDspDestAddr, u32 ulDspSrcAddr,
+			u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
+			IN u8 *pbHostBuf, u32 dwDSPAddr,
+			u32 ulNumBytes, u32 ulMemType);
+static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
+			u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
+			u32 ulMapAttr);
+static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
+			u32 ulVirtAddr, u32 ulNumBytes);
+static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
+			struct DEV_OBJECT *hDevObject,
+			IN CONST struct CFG_HOSTRES *pConfig,
+			IN CONST struct CFG_DSPRES *pDspConfig);
+static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
+			IN OUT void *pArgs);
+static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
+static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr,
+			u32 ulNumBytes, u32 *numOfTableEntries,
+			u32 *physicalAddrTable);
+static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
+			u32 va, u32 size,
+			struct HW_MMUMapAttrs_t *mapAttrs);
+static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
+			u32 size, struct HW_MMUMapAttrs_t *attrs);
+static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
+			u32 ulMpuAddr, u32 ulVirtAddr,
+			u32 ulNumBytes, u32 ulMapAttr);
+static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,
+			u32 sysctrl_base);
+void GetHWRegs(u32 prcm_base, u32 cm_base);
+
+/*  ----------------------------------- Globals */
+#ifndef DEBUG
+u64 tiomap1510_liTicksPerSecond;	/* Timer frequency */
+#endif
+
+/* Attributes of L2 page tables for DSP MMU */
+struct PageInfo {
+	u32 numEntries;	/* Number of valid PTEs in the L2 PT */
+} ;
+
+/* Attributes used to manage the DSP MMU page tables */
+struct PgTableAttrs {
+	struct SYNC_CSOBJECT *hCSObj;	/* Critical section object handle */
+
+	u32 L1BasePa;		/* Physical address of the L1 PT */
+	u32 L1BaseVa;		/* Virtual  address of the L1 PT */
+	u32 L1size;		/* Size of the L1 PT */
+	u32 L1TblAllocPa;
+	/* Physical address of Allocated mem for L1 table. May not be aligned */
+	u32 L1TblAllocVa;
+	/* Virtual address of Allocated mem for L1 table. May not be aligned */
+	u32 L1TblAllocSz;
+	/* Size of consistent memory allocated for L1 table.
+	 * May not be aligned */
+
+	u32 L2BasePa;		/* Physical address of the L2 PT */
+	u32 L2BaseVa;		/* Virtual  address of the L2 PT */
+	u32 L2size;		/* Size of the L2 PT */
+	u32 L2TblAllocPa;
+	/* Physical address of Allocated mem for L2 table. May not be aligned */
+	u32 L2TblAllocVa;
+	/* Virtual address of Allocated mem for L2 table. May not be aligned */
+	u32 L2TblAllocSz;
+	/* Size of consistent memory allocated for L2 table.
+	 * May not be aligned */
+
+	u32 L2NumPages;	/* Number of allocated L2 PT */
+	struct PageInfo *pgInfo;  /* Array [L2NumPages] of L2 PT info structs */
+} ;
+
+/*
+ *  If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
+ *  to boot
+ */
+extern s32 dsp_debug;
+
+
+/*
+ *  This mini driver's function interface table.
+ */
+static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
+	WCD_MAJOR_VERSION,  /* WCD ver. for which this mini driver is built. */
+	WCD_MINOR_VERSION,
+	WMD_DEV_Create,
+	WMD_DEV_Destroy,
+	WMD_DEV_Ctrl,
+	WMD_BRD_Monitor,
+	WMD_BRD_Start,
+	WMD_BRD_Stop,
+	WMD_BRD_Status,
+	WMD_BRD_Read,
+	WMD_BRD_Write,
+	WMD_BRD_SetState,
+	WMD_BRD_MemCopy,
+	WMD_BRD_MemWrite,
+	WMD_BRD_MemMap,
+	WMD_BRD_MemUnMap,
+	/* The following CHNL functions are provided by chnl_io.lib: */
+	WMD_CHNL_Create,
+	WMD_CHNL_Destroy,
+	WMD_CHNL_Open,
+	WMD_CHNL_Close,
+	WMD_CHNL_AddIOReq,
+	WMD_CHNL_GetIOC,
+	WMD_CHNL_CancelIO,
+	WMD_CHNL_FlushIO,
+	WMD_CHNL_GetInfo,
+	WMD_CHNL_GetMgrInfo,
+	WMD_CHNL_Idle,
+	WMD_CHNL_RegisterNotify,
+	/* The following DEH functions are provided by tihelen_ue_deh.c */
+	WMD_DEH_Create,
+	WMD_DEH_Destroy,
+	WMD_DEH_Notify,
+	WMD_DEH_RegisterNotify,
+	WMD_DEH_GetInfo,
+	/* The following IO functions are provided by chnl_io.lib: */
+	WMD_IO_Create,
+	WMD_IO_Destroy,
+	WMD_IO_OnLoaded,
+	WMD_IO_GetProcLoad,
+	/* The following MSG functions are provided by chnl_io.lib: */
+	WMD_MSG_Create,
+	WMD_MSG_CreateQueue,
+	WMD_MSG_Delete,
+	WMD_MSG_DeleteQueue,
+	WMD_MSG_Get,
+	WMD_MSG_Put,
+	WMD_MSG_RegisterNotify,
+	WMD_MSG_SetQueueId,
+};
+
+/*
+ *  ======== WMD_DRV_Entry ========
+ *  purpose:
+ *      Mini Driver entry point.
+ */
+void CDECL WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
+	      IN CONST char *pstrWMDFileName)
+{
+
+	DBC_Require(pstrWMDFileName != NULL);
+	DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
+
+#ifndef DEBUG
+	tiomap1510_liTicksPerSecond = HZ;
+#endif
+
+	if (CSL_Strcmp(pstrWMDFileName, "UMA") == 0)
+		*ppDrvInterface = &drvInterfaceFxns;
+	else
+		DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
+
+}
+
+/*
+ *  ======== WMD_BRD_Monitor ========
+ *  purpose:
+ *      This WMD_BRD_Monitor puts DSP into a Loadable state.
+ *      i.e Application can load and start the device.
+ *
+ *  Preconditions:
+ *      Device in 'OFF' state.
+ */
+static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct CFG_HOSTRES resources;
+	u32 temp;
+	enum HW_PwrState_t    pwrState;
+
+	DBG_Trace(DBG_ENTER, "Board in the monitor state  \n");
+	status = CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status))
+		goto error_return;
+
+	GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+	HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
+    if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
+		/* IVA2 is not in ON state */
+		/* Read and set PM_PWSTCTRL_IVA2  to ON */
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				     &pwrState);
+		HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
+					  HW_PWR_DOMAIN_DSP,
+					  HW_PWR_STATE_ON);
+		/* Set the SW supervised state transition */
+		HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
+					   HW_SW_SUP_WAKEUP);
+		/* Wait until the state has moved to ON */
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				     &pwrState);
+		/* Disable Automatic transition */
+	HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
+	}
+	DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
+	GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+	status = run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
+			      resources.dwSysCtrlBase);
+	if (DSP_SUCCEEDED(status)) {
+		/* set the device state to IDLE */
+		pDevContext->dwBrdState = BRD_IDLE;
+
+	}
+error_return:
+	DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
+	GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_Read ========
+ *  purpose:
+ *      Reads buffers for DSP memory.
+ */
+static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
+			       OUT u8 *pbHostBuf, u32 dwDSPAddr,
+			       u32 ulNumBytes, u32 ulMemType)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	u32 offset;
+	u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
+
+	DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
+		  " 0x%x\n\t\tdwDSPAddr:  0x%x\n\t\tulNumBytes:  0x%x\n\t\t"
+		  "ulMemType:  0x%x\n", pDevContext, pbHostBuf,
+		  dwDSPAddr, ulNumBytes, ulMemType);
+	if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
+		DBG_Trace(DBG_LEVEL7,
+			  "WMD_BRD_Read: DSP address < start address \n ");
+		status = DSP_EFAIL;
+		return status;
+	}
+	/* change here to account for the 3 bands of the DSP internal memory */
+	if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
+	    pDevContext->dwInternalSize) {
+		offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
+	} else {
+		DBG_Trace(DBG_LEVEL1,
+			  "**** Reading From external memory ****  \n ");
+		status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
+					ulNumBytes, ulMemType);
+		return status;
+	}
+	/* copy the data from  DSP memory, */
+	memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_SetState ========
+ *  purpose:
+ *      This routine updates the Board status.
+ */
+static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
+				   u32 ulBrdState)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+	DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
+		  ulBrdState);
+	pDevContext->dwBrdState = ulBrdState;
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_Start ========
+ *  purpose:
+ *      Initializes DSP MMU and Starts DSP.
+ *
+ *  Preconditions:
+ *  a) DSP domain is 'ACTIVE'.
+ *  b) DSP_RST1 is asserted.
+ *  b) DSP_RST2 is released.
+ */
+static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
+				u32 dwDSPAddr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	u32 dwSyncAddr = 0;
+	u32 ulShmBase;	/* Gpp Phys SM base addr(byte) */
+	u32 ulShmBaseVirt;	/* Dsp Virt SM base addr */
+	u32 ulTLBBaseVirt;	/* Base of MMU TLB entry */
+	u32 ulShmOffsetVirt;	/* offset of ulShmBaseVirt from ulTLBBaseVirt */
+	s32 iEntryNdx;
+	s32 itmpEntryNdx = 0;	/* DSP-MMU TLB entry base address */
+	struct CFG_HOSTRES resources;
+	u32 temp;
+	u32 ulDspClkRate;
+	u32 ulDspClkAddr;
+	u32 ulBiosGpTimer;
+	u32 uClkCmd;
+	struct IO_MGR *hIOMgr;
+	u32 ulLoadMonitorTimer;
+	u32 extClkId = 0;
+	u32 tmpIndex;
+	u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
+
+	DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
+			     "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
+
+	 /* The device context contains all the mmu setup info from when the
+	 * last dsp base image was loaded. The first entry is always
+	 * SHMMEM base. */
+	/* Get SHM_BEG - convert to byte address */
+	(void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
+			     &ulShmBaseVirt);
+	ulShmBaseVirt *= DSPWORDSIZE;
+	DBC_Assert(ulShmBaseVirt != 0);
+	/* DSP Virtual address */
+	ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
+	DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+	ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
+	/* Kernel logical address */
+	ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
+
+	DBC_Assert(ulShmBase != 0);
+	/* 2nd wd is used as sync field */
+	dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
+	 /* Write a signature into the SHM base + offset; this will
+	 * get cleared when the DSP program starts.  */
+	if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
+		DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
+		status = DSP_EFAIL;
+	} else
+		*((volatile u32 *)dwSyncAddr) = 0xffffffff;
+
+	if (DSP_SUCCEEDED(status)) {
+		status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+		/* Assert RST1 i.e only the RST only for DSP megacell  */
+		/* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
+		if (DSP_SUCCEEDED(status)) {
+			HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
+			if (dsp_debug) {
+				/* Set the bootmode to self loop  */
+				DBG_Trace(DBG_LEVEL7,
+						"Set boot mode to self loop"
+						" for IVA2 Device\n");
+				HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
+					HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
+			} else {
+				/* Set the bootmode to '0' - direct boot */
+				DBG_Trace(DBG_LEVEL7,
+						"Set boot mode to direct"
+						" boot for IVA2 Device \n");
+				HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
+					HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Reset and Unreset the RST2, so that BOOTADDR is copied to
+		 * IVA2 SYSC register */
+		HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
+		UTIL_Wait(100);
+		HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
+		UTIL_Wait(100);
+		DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
+		GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+		/* Disbale the DSP MMU */
+		HW_MMU_Disable(resources.dwDmmuBase);
+		/* Disable TWL */
+		HW_MMU_TWLDisable(resources.dwDmmuBase);
+
+		/* Only make TLB entry if both addresses are non-zero */
+		for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
+			iEntryNdx++) {
+			if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
+			   (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
+				DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
+				    " 0x%x DspVa 0x%x Size 0x%x\n",
+				    itmpEntryNdx,
+				    pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
+				    pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
+				    pDevContext->aTLBEntry[iEntryNdx].ulSize);
+				configureDspMmu(pDevContext,
+				    pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
+				    pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
+						DSPWORDSIZE,
+				    pDevContext->aTLBEntry[iEntryNdx].ulSize,
+				    itmpEntryNdx,
+				    pDevContext->aTLBEntry[iEntryNdx].endianism,
+				    pDevContext->aTLBEntry[iEntryNdx].elemSize,
+				    pDevContext->aTLBEntry[iEntryNdx].
+						mixedMode);
+				itmpEntryNdx++;
+			}
+		}		/* end for */
+	}
+
+	/* Lock the above TLB entries and get the BIOS and load monitor timer
+	 * information*/
+	if (DSP_SUCCEEDED(status)) {
+		HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
+		HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
+		HW_MMU_TTBSet(resources.dwDmmuBase,
+				pDevContext->pPtAttrs->L1BasePa);
+		HW_MMU_TWLEnable(resources.dwDmmuBase);
+		/* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
+
+		temp = (u32) *((REG_UWORD32 *)
+				((u32) (resources.dwDmmuBase) + 0x10));
+		temp = (temp & 0xFFFFFFEF) | 0x11;
+		*((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)) =
+			(u32) temp;
+
+		/* Let the DSP MMU run */
+		HW_MMU_Enable(resources.dwDmmuBase);
+
+		/* Enable the BIOS clock  */
+		(void)DEV_GetSymbol(pDevContext->hDevObject,
+					BRIDGEINIT_BIOSGPTIMER,
+				     &ulBiosGpTimer);
+		DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
+		(void)DEV_GetSymbol(pDevContext->hDevObject,
+				BRIDGEINIT_LOADMON_GPTIMER,
+				     &ulLoadMonitorTimer);
+		DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
+			  ulLoadMonitorTimer);
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		if (ulLoadMonitorTimer != 0xFFFF) {
+			uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
+						ulLoadMonitorTimer;
+			DBG_Trace(DBG_LEVEL7,
+				  "encoded LoadMonitor cmd for Disable: 0x%x\n",
+				  uClkCmd);
+			DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+			extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
+			for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
+			     tmpIndex++) {
+				if (extClkId == BPWR_CLKID[tmpIndex]) {
+					clkIdIndex = tmpIndex;
+					break;
+				}
+			}
+
+			if (clkIdIndex < MBX_PM_MAX_RESOURCES)
+				status = CLK_Set_32KHz(
+						BPWR_Clks[clkIdIndex].funClk);
+			else
+				status = DSP_EFAIL;
+
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, " Error while setting"
+							"LM Timer  to 32KHz\n");
+			}
+			uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
+				  ulLoadMonitorTimer;
+			DBG_Trace(DBG_LEVEL7,
+				 "encoded LoadMonitor cmd for Enable : 0x%x\n",
+				 uClkCmd);
+			DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+		} else {
+			DBG_Trace(DBG_LEVEL7,
+				  "Not able to get the symbol for Load "
+				  "Monitor Timer\n");
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		if (ulBiosGpTimer != 0xFFFF) {
+			uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
+								ulBiosGpTimer;
+			DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
+					"Disable: 0x%x\n", uClkCmd);
+			DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+			extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
+
+			for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
+			     tmpIndex++) {
+				if (extClkId == BPWR_CLKID[tmpIndex]) {
+					clkIdIndex = tmpIndex;
+					break;
+				}
+			}
+
+			if (clkIdIndex < MBX_PM_MAX_RESOURCES)
+				status = CLK_Set_32KHz(
+						BPWR_Clks[clkIdIndex].funClk);
+			else
+				status = DSP_EFAIL;
+
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7,
+				" Error while setting BIOS Timer  to 32KHz\n");
+			}
+
+			uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
+				   ulBiosGpTimer;
+			DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
+						"0x%x\n", uClkCmd);
+			DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
+
+		} else {
+		DBG_Trace(DBG_LEVEL7,
+			  "Not able to get the symbol for BIOS Timer\n");
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Set the DSP clock rate */
+		(void)DEV_GetSymbol(pDevContext->hDevObject,
+					"_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
+		DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
+				"0x%x \n", ulDspClkAddr);
+		if ((unsigned int *)ulDspClkAddr != NULL) {
+			/* Get the clock rate */
+			status = CLK_GetRate(SERVICESCLK_iva2_ck,
+				 &ulDspClkRate);
+			DBG_Trace(DBG_LEVEL5,
+				 "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
+				 ulDspClkRate);
+			(void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
+				 ulDspClkAddr, sizeof(u32), 0);
+		}
+		/* Enable Mailbox events and also drain any pending
+		 * stale messages */
+		(void)CHNLSM_EnableInterrupt(pDevContext);
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+		DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
+				temp);
+		HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+		DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
+				temp);
+
+		/* Let DSP go */
+		DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
+		/* Enable DSP MMU Interrupts */
+		HW_MMU_EventEnable(resources.dwDmmuBase,
+				HW_MMU_ALL_INTERRUPTS);
+		/* release the RST1, DSP starts executing now .. */
+		HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
+
+		HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+		DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
+				temp);
+		HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
+		DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
+				temp);
+		DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
+				dwSyncAddr);
+		DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address =  0x%x \n",
+				dwDSPAddr);
+		if (dsp_debug)
+			while (*((volatile u16 *)dwSyncAddr))
+				;;
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Wait for DSP to clear word in shared memory */
+		/* Read the Location */
+		if (!WaitForStart(pDevContext, dwSyncAddr)) {
+			status = WMD_E_TIMEOUT;
+			DBG_Trace(DBG_LEVEL7,
+				 "WMD_BRD_Start Failed to Synchronize\n");
+		}
+		status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+		if (DSP_SUCCEEDED(status)) {
+			IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
+			DBG_Trace(DBG_LEVEL7,
+			"WMD_BRD_Start: OPP information initialzed\n");
+			/* Write the synchronization bit to indicate the
+			 * completion of OPP table update to DSP
+			 */
+			*((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* update board state */
+			pDevContext->dwBrdState = BRD_RUNNING;
+			/* (void)CHNLSM_EnableInterrupt(pDevContext);*/
+			DBG_Trace(DBG_LEVEL7, "Device Started \n ");
+		} else {
+			pDevContext->dwBrdState = BRD_UNKNOWN;
+			DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_Stop ========
+ *  purpose:
+ *      Puts DSP in self loop.
+ *
+ *  Preconditions :
+ *  a) None
+ */
+static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct CFG_HOSTRES resources;
+	struct PgTableAttrs *pPtAttrs;
+	u32 dspPwrState;
+	enum HW_PwrState_t pwrState;
+	DSP_STATUS clk_status;
+
+	DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
+		  hDevContext);
+
+	/* Disable the mail box interrupts */
+	(void)CHNLSM_DisableInterrupt(pDevContext);
+
+	if (pDevContext->dwBrdState == BRD_STOPPED)
+		return status;
+
+	/* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
+	 * before turning off the clocks.. This is to ensure that there are no
+	 * pending L3 or other transactons from IVA2 */
+	status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+	if (DSP_FAILED(status)) {
+		DBG_Trace(DBG_LEVEL7,
+			  "WMD_BRD_Stop: Get Host resources failed \n");
+		DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
+		return DSP_EFAIL;
+	}
+
+	HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
+	if (dspPwrState != HW_PWR_STATE_OFF) {
+
+			IO_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
+
+			UTIL_Wait(10000);	/* 10 msec */
+
+			GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
+
+		run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
+			     resources.dwSysCtrlBase);
+
+		udelay(50);
+
+		clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+		if (DSP_FAILED(clk_status)) {
+			DBG_Trace(DBG_LEVEL6,
+				 "\n WMD_BRD_Stop: CLK_Disable failed "
+				 "for iva2_fck\n");
+			}
+		/* IVA2 is not in OFF state */
+		/* Read and set PM_PWSTCTRL_IVA2  to OFF */
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				     &pwrState);
+		HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
+					  HW_PWR_DOMAIN_DSP,
+					  HW_PWR_STATE_OFF);
+		/* Set the SW supervised state transition for Sleep */
+		HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
+					   HW_SW_SUP_SLEEP);
+	} else {
+		clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+		if (DSP_FAILED(clk_status)) {
+			DBG_Trace(DBG_LEVEL6,
+				 "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
+				 " for iva2_fck\n");
+		}
+	}
+	udelay(10);
+	/* Release the Ext Base virtual Address as the next DSP Program
+	 * may have a different load address */
+	if (pDevContext->dwDspExtBaseAddr)
+		pDevContext->dwDspExtBaseAddr = 0;
+
+	pDevContext->dwBrdState = BRD_STOPPED;	/* update board state */
+	DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
+	/* This is a good place to clear the MMU page tables as well */
+	if (pDevContext->pPtAttrs) {
+		pPtAttrs = pDevContext->pPtAttrs;
+		memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
+		memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
+		memset((u8 *) pPtAttrs->pgInfo, 0x00,
+		       (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
+	}
+
+		DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
+
+	return status;
+}
+
+
+/*
+ *  ======== WMD_BRD_Delete ========
+ *  purpose:
+ *      Puts DSP in Low power mode
+ *
+ *  Preconditions :
+ *  a) None
+ */
+static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct CFG_HOSTRES resources;
+	struct PgTableAttrs *pPtAttrs;
+	DSP_STATUS clk_status;
+
+	DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
+		  hDevContext);
+
+	/* Disable the mail box interrupts */
+	(void) CHNLSM_DisableInterrupt(pDevContext);
+
+	if (pDevContext->dwBrdState == BRD_STOPPED)
+		return status;
+
+	/* as per TRM, it is advised to first drive
+	 * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
+	 * to ensure that there are no pending L3 or other transactons from
+	 * IVA2 */
+	status = CFG_GetHostResources(
+		(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status)) {
+		DBG_Trace(DBG_LEVEL7,
+			 "WMD_BRD_Stop: Get Host resources failed \n");
+		DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
+		return DSP_EFAIL;
+	}
+	status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
+	clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+	if (DSP_FAILED(clk_status)) {
+		DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
+			  " iva2_fck\n");
+	}
+	/* Release the Ext Base virtual Address as the next DSP Program
+	 * may have a different load address */
+	if (pDevContext->dwDspExtBaseAddr)
+		pDevContext->dwDspExtBaseAddr = 0;
+
+	pDevContext->dwBrdState = BRD_STOPPED;	/* update board state */
+	DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
+	/* This is a good place to clear the MMU page tables as well */
+	if (pDevContext->pPtAttrs) {
+		pPtAttrs = pDevContext->pPtAttrs;
+		memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
+		memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
+		memset((u8 *)pPtAttrs->pgInfo, 0x00,
+			(pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
+	}
+	DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
+	return status;
+}
+
+
+/*
+ *  ======== WMD_BRD_Status ========
+ *      Returns the board status.
+ */
+static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
+				 OUT BRD_STATUS *pdwState)
+{
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	*pdwState = pDevContext->dwBrdState;
+	return DSP_SOK;
+}
+
+/*
+ *  ======== WMD_BRD_Write ========
+ *      Copies the buffers to DSP internal or external memory.
+ */
+static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
+				IN u8 *pbHostBuf, u32 dwDSPAddr,
+				u32 ulNumBytes, u32 ulMemType)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+	DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
+		 "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
+		 "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
+		 dwDSPAddr, ulNumBytes, ulMemType);
+	if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
+		DBG_Trace(DBG_LEVEL7,
+			 "WMD_BRD_Write: DSP address < start address \n ");
+		status = DSP_EFAIL;
+		return status;
+	}
+	if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
+	   pDevContext->dwInternalSize) {
+		status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
+			 ulNumBytes, ulMemType);
+	} else {
+		status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
+					 ulNumBytes, ulMemType, false);
+	}
+
+	DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy :  DspLogicAddr=0x%x \n",
+			pDevContext->dwDspBaseAddr);
+	return status;
+}
+
+/*
+ *  ======== WMD_DEV_Create ========
+ *      Creates a driver object. Puts DSP in self loop.
+ */
+static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
+				 struct DEV_OBJECT *hDevObject,
+				 IN CONST struct CFG_HOSTRES *pConfig,
+				 IN CONST struct CFG_DSPRES *pDspConfig)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = NULL;
+	s32 iEntryNdx;
+	s32 tcWordSwap;
+	u32 tcWordSwapSize = sizeof(tcWordSwap);
+	struct CFG_HOSTRES resources;
+	struct PgTableAttrs *pPtAttrs;
+	u32   pg_tbl_pa;
+	u32   pg_tbl_va;
+	u32   align_size;
+
+	DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
+		  "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
+		  ppDevContext, hDevObject, pConfig, pDspConfig);
+	 /* Allocate and initialize a data structure to contain the mini driver
+	 *  state, which becomes the context for later calls into this WMD.  */
+	pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
+	if (!pDevContext) {
+		DBG_Trace(DBG_ENTER, "Failed to allocate mem  \n");
+		status = DSP_EMEMORY;
+		goto func_end;
+	}
+	status = CFG_GetHostResources(
+		(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status)) {
+		DBG_Trace(DBG_ENTER, "Failed to get host resources   \n");
+		status = DSP_EMEMORY;
+		goto func_end;
+	}
+
+	pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
+	pDevContext->dwSelfLoop = (u32)NULL;
+	pDevContext->uDspPerClks = 0;
+	pDevContext->dwInternalSize = OMAP_DSP_SIZE;
+	/*  Clear dev context MMU table entries.
+	 *  These get set on WMD_BRD_IOCTL() call after program loaded. */
+	for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
+		pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
+			pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
+	}
+	pDevContext->numTLBEntries = 0;
+	pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
+			(pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
+	if (!pDevContext->dwDspBaseAddr) {
+		status = DSP_EFAIL;
+		DBG_Trace(DBG_LEVEL7,
+			 "WMD_DEV_Create: failed to Map the API memory\n");
+	}
+	pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
+	if (pPtAttrs != NULL) {
+		/* Assuming that we use only DSP's memory map
+		 * until 0x4000:0000 , we would need only 1024
+		 * L1 enties i.e L1 size = 4K */
+		pPtAttrs->L1size = 0x1000;
+		align_size = pPtAttrs->L1size;
+		/* Align sizes are expected to be power of 2 */
+		/* we like to get aligned on L1 table size */
+		pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
+		    align_size, &pg_tbl_pa);
+	/* Check if the PA is aligned for us */
+	if ((pg_tbl_pa) & (align_size-1)) {
+	    /* PA not aligned to page table size ,
+	     * try with more allocation and align */
+	    MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa, pPtAttrs->L1size);
+	    /* we like to get aligned on L1 table size */
+	    pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
+			 align_size, &pg_tbl_pa);
+	    /* We should be able to get aligned table now */
+	    pPtAttrs->L1TblAllocPa = pg_tbl_pa;
+	    pPtAttrs->L1TblAllocVa = pg_tbl_va;
+	    pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
+	    /* Align the PA to the next 'align'  boundary */
+	    pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
+				 (~(align_size-1));
+	    pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
+				 pg_tbl_pa);
+	} else {
+	    /* We got aligned PA, cool */
+	    pPtAttrs->L1TblAllocPa = pg_tbl_pa;
+	    pPtAttrs->L1TblAllocVa = pg_tbl_va;
+	    pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
+	    pPtAttrs->L1BasePa = pg_tbl_pa;
+	    pPtAttrs->L1BaseVa = pg_tbl_va;
+	}
+	if (pPtAttrs->L1BaseVa) {
+			memset((u8 *)pPtAttrs->L1BaseVa, 0x00,
+			pPtAttrs->L1size);
+	}
+		/* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
+		 * L4 pages */
+		pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
+		pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
+				   pPtAttrs->L2NumPages;
+		align_size = 4; /* Make it u32 aligned  */
+		/* we like to get aligned on L1 table size */
+		pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
+			    align_size, &pg_tbl_pa);
+	pPtAttrs->L2TblAllocPa = pg_tbl_pa;
+	pPtAttrs->L2TblAllocVa = pg_tbl_va;
+	pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
+	pPtAttrs->L2BasePa = pg_tbl_pa;
+	pPtAttrs->L2BaseVa = pg_tbl_va;
+	if (pPtAttrs->L2BaseVa) {
+			memset((u8 *)pPtAttrs->L2BaseVa, 0x00,
+			pPtAttrs->L2size);
+	}
+	pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
+				sizeof(struct PageInfo), MEM_NONPAGED);
+		DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
+			 "%x, size %x\n", pPtAttrs->L1BasePa,
+			 pPtAttrs->L1BaseVa, pPtAttrs->L1size,
+			 pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
+			 pPtAttrs->L2size);
+		DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
+			 pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
+	}
+	if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
+	   (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
+		pDevContext->pPtAttrs = pPtAttrs;
+	else
+		status = DSP_EMEMORY;
+
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Set the Endianism Register */ /* Need to set this */
+		/* default to Proc-copy */
+		pDevContext->wIntrVal2Dsp = MBX_PCPY_CLASS;
+		/* Retrieve the TC u16 SWAP Option */
+		status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
+				     (u8 *)&tcWordSwap, &tcWordSwapSize);
+		/* Save the value */
+		pDevContext->tcWordSwapOn = tcWordSwap;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Set the Clock Divisor for the DSP module */
+		DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
+			  "enable the clock \n");
+		status = CLK_Enable(SERVICESCLK_mailbox_ick);
+		if (DSP_FAILED(status)) {
+			DBG_Trace(DBG_LEVEL7,
+				 "WMD_DEV_create:Reset mail box and "
+				 "enable the clock Fail\n");
+		}
+		UTIL_Wait(5);
+		/* 24xx-Linux MMU address is obtained from the host
+		 * resources struct */
+		pDevContext->dwDSPMmuBase = resources.dwDmmuBase;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pDevContext->hDevObject = hDevObject;
+		pDevContext->ulIntMask = 0;
+		/* Store current board state. */
+		pDevContext->dwBrdState = BRD_STOPPED;
+		/* Return this ptr to our device state to the WCD for storage:*/
+		*ppDevContext = pDevContext;
+		DBG_Trace(DBG_ENTER, "Device Created \n");
+	} else {
+		if (pPtAttrs != NULL) {
+			if (pPtAttrs->hCSObj)
+				SYNC_DeleteCS(pPtAttrs->hCSObj);
+
+			if (pPtAttrs->pgInfo)
+				MEM_Free(pPtAttrs->pgInfo);
+
+			if (pPtAttrs->L2TblAllocVa) {
+				MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
+						pPtAttrs->L2TblAllocPa,
+						pPtAttrs->L2TblAllocSz);
+			}
+			if (pPtAttrs->L1TblAllocVa) {
+				MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
+						pPtAttrs->L1TblAllocPa,
+						pPtAttrs->L1TblAllocSz);
+			}
+		}
+		if (pPtAttrs)
+			MEM_Free(pPtAttrs);
+
+		if (pDevContext)
+			MEM_Free(pDevContext);
+
+		DBG_Trace(DBG_LEVEL7,
+			 "WMD_DEV_Create Error Device  not created\n");
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== WMD_DEV_Ctrl ========
+ *      Receives device specific commands.
+ */
+static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
+				IN OUT void *pArgs)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
+	s32 ndx;
+
+	DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext:  0x%x\n\t\t dwCmd:  "
+		  "0x%x\n\t\tpArgs:  0x%x\n", pDevContext, dwCmd, pArgs);
+	switch (dwCmd) {
+	case WMDIOCTL_CHNLREAD:
+		break;
+	case WMDIOCTL_CHNLWRITE:
+		break;
+	case WMDIOCTL_SETMMUCONFIG:
+		/* store away dsp-mmu setup values for later use */
+		for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
+			pDevContext->aTLBEntry[ndx] = *paExtProc;
+
+		break;
+	case WMDIOCTL_DEEPSLEEP:
+	case WMDIOCTL_EMERGENCYSLEEP:
+		/* Currently only DSP Idle is supported Need to update for
+		 * later releases */
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
+		status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
+		break;
+	case WMDIOCTL_WAKEUP:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
+		status = WakeDSP(pDevContext, pArgs);
+		break;
+	case WMDIOCTL_CLK_CTRL:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
+		status = DSP_SOK;
+		/* Looking For Baseport Fix for Clocks */
+		status = DSPPeripheralClkCtrl(pDevContext, pArgs);
+		break;
+	case WMDIOCTL_PWR_HIBERNATE:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
+		status = handle_hibernation_fromDSP(pDevContext);
+		break;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	case WMDIOCTL_PRESCALE_NOTIFY:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
+		status = PreScale_DSP(pDevContext, pArgs);
+		break;
+	case WMDIOCTL_POSTSCALE_NOTIFY:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
+		status = PostScale_DSP(pDevContext, pArgs);
+		break;
+	case WMDIOCTL_CONSTRAINT_REQUEST:
+		DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
+		status = handle_constraints_set(pDevContext, pArgs);
+		break;
+#endif
+#endif
+	default:
+		status = DSP_EFAIL;
+		DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
+		break;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_DEV_Destroy ========
+ *      Destroys the driver object.
+ */
+static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	struct PgTableAttrs *pPtAttrs;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
+						hDevContext;
+	DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
+		  hDevContext);
+	/* first put the device to stop state */
+	WMD_BRD_Delete(pDevContext);
+	if (pDevContext && pDevContext->pPtAttrs) {
+		pPtAttrs = pDevContext->pPtAttrs;
+		if (pPtAttrs->hCSObj)
+			SYNC_DeleteCS(pPtAttrs->hCSObj);
+
+		if (pPtAttrs->pgInfo)
+			MEM_Free(pPtAttrs->pgInfo);
+
+		if (pPtAttrs->L2TblAllocVa) {
+			MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
+					pPtAttrs->L2TblAllocPa, pPtAttrs->
+					L2TblAllocSz);
+		}
+		if (pPtAttrs->L1TblAllocVa) {
+			MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
+					pPtAttrs->L1TblAllocPa, pPtAttrs->
+					L1TblAllocSz);
+		}
+		if (pPtAttrs)
+			MEM_Free(pPtAttrs);
+
+	}
+	/* Free the driver's device context: */
+	MEM_Free((void *) hDevContext);
+	return status;
+}
+
+static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
+				  u32 ulDspDestAddr, u32 ulDspSrcAddr,
+				  u32 ulNumBytes, u32 ulMemType)
+{
+	DSP_STATUS status = DSP_SOK;
+	u32 srcAddr = ulDspSrcAddr;
+	u32 destAddr = ulDspDestAddr;
+	u32 copyBytes = 0;
+	u32 totalBytes = ulNumBytes;
+	u8 hostBuf[BUFFERSIZE];
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
+		copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
+		/* Read from External memory */
+		status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
+					copyBytes, ulMemType);
+		if (DSP_SUCCEEDED(status)) {
+			if (destAddr < (pDevContext->dwDSPStartAdd +
+			    pDevContext->dwInternalSize)) {
+				/* Write to Internal memory */
+				status = WriteDspData(hDevContext, hostBuf,
+					 destAddr, copyBytes, ulMemType);
+			} else {
+				/* Write to External memory */
+				status = WriteExtDspData(hDevContext, hostBuf,
+					 destAddr, copyBytes, ulMemType, false);
+			}
+		}
+		totalBytes -= copyBytes;
+		srcAddr += copyBytes;
+		destAddr += copyBytes;
+	}
+	return status;
+}
+
+/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
+static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
+				   IN u8 *pbHostBuf, u32 dwDSPAddr,
+				   u32 ulNumBytes, u32 ulMemType)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	u32 ulRemainBytes = 0;
+	u32 ulBytes = 0;
+	ulRemainBytes = ulNumBytes;
+	while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
+		ulBytes =
+			ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
+		if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
+		    pDevContext->dwInternalSize)) {
+			status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
+					      ulBytes, ulMemType);
+		} else {
+			status = WriteExtDspData(hDevContext, pbHostBuf,
+				 dwDSPAddr, ulBytes, ulMemType, true);
+		}
+		ulRemainBytes -= ulBytes;
+		dwDSPAddr += ulBytes;
+		pbHostBuf = pbHostBuf + ulBytes;
+	}
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_MemMap ========
+ *      This function maps MPU buffer to the DSP address space. It performs
+ *  linear to physical address translation if required. It translates each
+ *  page since linear addresses can be physically non-contiguous
+ *  All address & size arguments are assumed to be page aligned (in proc.c)
+ *
+ *  TODO: Disable MMU while updating the page tables (but that'll stall DSP)
+ */
+static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
+				 u32 ulMpuAddr, u32 ulVirtAddr,
+				 u32 ulNumBytes, u32 ulMapAttr)
+{
+	u32 attrs;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct HW_MMUMapAttrs_t hwAttrs;
+	u32 numOfActualTabEntries = 0;
+	u32 temp = 0;
+	u32 *pPhysAddrPageTbl = NULL;
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+
+	DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
+		 "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
+		 ulNumBytes, ulMapAttr);
+	if (ulNumBytes == 0)
+		return DSP_EINVALIDARG;
+
+	if (ulMapAttr != 0) {
+		attrs = ulMapAttr;
+	} else {
+		/* Assign default attributes */
+		attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
+	}
+	/* Take mapping properties */
+	if (attrs & DSP_MAPBIGENDIAN)
+		hwAttrs.endianism = HW_BIG_ENDIAN;
+	else
+		hwAttrs.endianism = HW_LITTLE_ENDIAN;
+
+	hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
+			     ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
+	/* Ignore elementSize if mixedSize is enabled */
+	if (hwAttrs.mixedSize == 0) {
+		if (attrs & DSP_MAPELEMSIZE8) {
+			/* Size is 8 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
+		} else if (attrs & DSP_MAPELEMSIZE16) {
+			/* Size is 16 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
+		} else if (attrs & DSP_MAPELEMSIZE32) {
+			/* Size is 32 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
+		} else if (attrs & DSP_MAPELEMSIZE64) {
+			/* Size is 64 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
+		} else {
+			/* Mixedsize isn't enabled, so size can't be
+			 * zero here */
+			DBG_Trace(DBG_LEVEL7,
+				 "WMD_BRD_MemMap: MMU element size is zero\n");
+			return DSP_EINVALIDARG;
+		}
+	}
+	if (attrs & DSP_MAPVMALLOCADDR) {
+		status = MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
+				       ulNumBytes, ulMapAttr);
+		return status;
+	}
+	 /* Do OS-specific user-va to pa translation.
+	 * Combine physically contiguous regions to reduce TLBs.
+	 * Pass the translated pa to PteUpdate.  */
+	if ((attrs & DSP_MAPPHYSICALADDR)) {
+		status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
+			 ulNumBytes, &hwAttrs);
+		goto func_cont;
+	}
+
+	/* Important Note: ulMpuAddr is mapped from user application process
+	 * to current process - it must lie completely within the current
+	 * virtual memory address space in order to be of use to us here!  */
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, ulMpuAddr);
+	up_read(&mm->mmap_sem);
+	if (vma)
+		DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
+			"ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
+			ulMpuAddr, ulNumBytes, vma->vm_start,
+			vma->vm_end, vma->vm_flags);
+
+	/* It is observed that under some circumstances, the user buffer is
+	 * spread across several VMAs. So loop through and check if the entire
+	 * user buffer is covered */
+	while ((vma != NULL) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
+		/* jump to the next VMA region */
+		down_read(&mm->mmap_sem);
+		vma = find_vma(mm, vma->vm_end + 1);
+		up_read(&mm->mmap_sem);
+		DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
+			  "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
+			  ulMpuAddr, ulNumBytes, vma->vm_start,
+			  vma->vm_end, vma->vm_flags);
+	}
+	if (vma == NULL) {
+		DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
+			  "MPU Buffer !!! \n");
+		status = DSP_EINVALIDARG;
+	}
+	if (DSP_FAILED(status))
+		goto func_cont;
+	pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
+	/* Build the array with virtual to physical translations */
+	status = TIOMAP_VirtToPhysical(mm, ulMpuAddr, ulNumBytes,
+				&numOfActualTabEntries, pPhysAddrPageTbl);
+	if (DSP_FAILED(status)) {
+		DBG_Trace(DBG_LEVEL7,
+			 "WMD_BRD_MemMap: TIOMAP_VirtToPhysical",
+			 " failed\n");
+		return DSP_EFAIL;
+	}
+	temp = 0;
+	DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap: numOfActualTabEntries=%d, "
+		  "ulNumBytes= %d\n",  numOfActualTabEntries, ulNumBytes);
+	/* Update the DSP MMU table with the physical addresses received from
+	    from translation function */
+	while (temp < numOfActualTabEntries) {
+		status = PteSet(pDevContext->pPtAttrs, pPhysAddrPageTbl[temp++],
+				ulVirtAddr, HW_PAGE_SIZE_4KB, &hwAttrs);
+		if (DSP_FAILED(status)) {
+			DBG_Trace(DBG_LEVEL7,
+				 "WMD_BRD_MemMap: FAILED IN PTESET \n");
+			return DSP_EFAIL;
+		}
+		ulVirtAddr += HW_PAGE_SIZE_4KB;
+	}
+	if (DSP_FAILED(status))
+		DBG_Trace(DBG_LEVEL5, "WMD_BRD_MemMap: PteSet failed \n");
+	else
+		DBG_Trace(DBG_LEVEL5, "WMD_BRD_MemMap: PteSet passed \n");
+
+func_cont:
+	/* Don't propogate Linux or HW status to upper layers */
+	if (DSP_SUCCEEDED(status)) {
+		status = DSP_SOK;
+	} else {
+		DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
+		status = DSP_EFAIL;
+	}
+	 /* In any case, flush the TLB
+	 * This is called from here instead from PteUpdate to avoid unnecessary
+	 * repetition while mapping non-contiguous physical regions of a virtual
+	 * region */
+	HW_MMU_TLBFlushAll(pDevContext->dwDSPMmuBase);
+	DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
+	return status;
+}
+
+/*
+ *  ======== WMD_BRD_MemUnMap ========
+ *      Invalidate the PTEs for the DSP VA block to be unmapped.
+ *
+ *      PTEs of a mapped memory block are contiguous in any page table
+ *      So, instead of looking up the PTE address for every 4K block,
+ *      we clear consecutive PTEs until we unmap all the bytes
+ */
+static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
+				   u32 ulVirtAddr, u32 ulNumBytes)
+{
+	u32 L1BaseVa;
+	u32 L2BaseVa;
+	u32 L2BasePa;
+	u32 L2PageNum;
+	u32 pteVal;
+	u32 pteSize;
+	u32 pteCount;
+	u32 pteAddrL1;
+	u32 pteAddrL2 = 0;
+	u32 remBytes;
+	u32 remBytesL2;
+	u32 vaCurr;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct PgTableAttrs *pt = pDevContext->pPtAttrs;
+
+	DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
+		  "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
+	vaCurr = ulVirtAddr;
+	remBytes = ulNumBytes;
+	remBytesL2 = 0;
+	L1BaseVa = pt->L1BaseVa;
+	pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
+	DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
+		  "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
+		  vaCurr, remBytes);
+	while (remBytes && (DSP_SUCCEEDED(status))) {
+		u32 vaCurrOrig = vaCurr;
+		/* Find whether the L1 PTE points to a valid L2 PT */
+		pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
+		pteVal = *(u32 *)pteAddrL1;
+		pteSize = HW_MMU_PteSizeL1(pteVal);
+		if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
+			/* Get the L2 PA from the L1 PTE, and find
+			 * corresponding L2 VA */
+			L2BasePa = HW_MMU_PteCoarseL1(pteVal);
+			L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
+			L2PageNum = (L2BasePa - pt->L2BasePa) /
+				    HW_MMU_COARSE_PAGE_SIZE;
+			 /* Find the L2 PTE address from which we will start
+			 * clearing, the number of PTEs to be cleared on this
+			 * page, and the size of VA space that needs to be
+			 * cleared on this L2 page */
+			pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
+			pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
+			pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
+				    sizeof(u32);
+			if (remBytes < (pteCount * PG_SIZE_4K))
+				pteCount = remBytes / PG_SIZE_4K;
+
+			remBytesL2 = pteCount * PG_SIZE_4K;
+			DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
+				  "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
+				  L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
+			 /* Unmap the VA space on this L2 PT. A quicker way
+			 * would be to clear pteCount entries starting from
+			 * pteAddrL2. However, below code checks that we don't
+			 * clear invalid entries or less than 64KB for a 64KB
+			 * entry. Similar checking is done for L1 PTEs too
+			 * below */
+			while (remBytesL2 && (DSP_SUCCEEDED(status))) {
+				pteVal = *(u32 *)pteAddrL2;
+				pteSize = HW_MMU_PteSizeL2(pteVal);
+				/* vaCurr aligned to pteSize? */
+				if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
+				   !(vaCurr & (pteSize - 1))) {
+					HW_MMU_PteClear(pteAddrL2, vaCurr,
+							 pteSize);
+					remBytesL2 -= pteSize;
+					vaCurr += pteSize;
+					pteAddrL2 += (pteSize >> 12) *
+						      sizeof(u32);
+				} else {
+					status = DSP_EFAIL;
+				}
+			}
+			SYNC_EnterCS(pt->hCSObj);
+			if (remBytesL2 == 0) {
+				pt->pgInfo[L2PageNum].numEntries -= pteCount;
+				if (pt->pgInfo[L2PageNum].numEntries == 0) {
+					/* Clear the L1 PTE pointing to the
+					 * L2 PT */
+					status = HW_MMU_PteClear(L1BaseVa,
+						 vaCurrOrig,
+						 HW_MMU_COARSE_PAGE_SIZE);
+				}
+				remBytes -= pteCount * PG_SIZE_4K;
+			} else {
+				status = DSP_EFAIL;
+			}
+			DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
+				  "numEntries %x, pteCount %x, status: 0x%x\n",
+				  L2PageNum, pt->pgInfo[L2PageNum].numEntries,
+				  pteCount, status);
+			SYNC_LeaveCS(pt->hCSObj);
+		} else
+			/* vaCurr aligned to pteSize? */
+			/* pteSize = 1 MB or 16 MB */
+			if ((pteSize != 0) && (remBytes >= pteSize) &&
+			   !(vaCurr & (pteSize - 1))) {
+				HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize);
+				remBytes -= pteSize;
+				vaCurr += pteSize;
+		} else {
+			status = DSP_EFAIL;
+		}
+	}
+	 /* It is better to flush the TLB here, so that any stale old entries
+	 * get flushed */
+	HW_MMU_TLBFlushAll(pDevContext->dwDSPMmuBase);
+	DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
+		  "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
+	DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
+		  "remBytesL2 %x\n", status, remBytes, remBytesL2);
+	return status;
+}
+/*
+ * ========= TIOMAP_VirtToPhysical ==========
+ * Purpose:
+ * 		This function builds the array with virtual to physical
+ *	    address translation
+ */
+static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr,
+					u32 ulNumBytes,
+					u32 *numOfTableEntries,
+					u32 *physicalAddrTable)
+{
+	u32 pAddr;
+	u32 chunkSz;
+	DSP_STATUS status = DSP_SOK;
+	volatile u32 pteVal;
+	u32 pteSize;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	volatile pte_t *ptep;
+	u32 numEntries = 0;
+	u32 numof4KPages = 0;
+	u32 phyEntryCounter = 0;
+	u32 temp = 0;
+	u32 numUsrPgs;
+	struct task_struct *curr_task = current;
+
+	DBG_Trace(DBG_ENTER, "TIOMAP_VirtToPhysical: START:ulMpuAddr=%x, "
+		  "ulNumBytes=%x\n", ulMpuAddr, ulNumBytes);
+	if (physicalAddrTable == NULL)
+		return DSP_EMEMORY;
+	while (ulNumBytes) {
+		DBG_Trace(DBG_LEVEL4, "TIOMAP_VirtToPhysical:Read the next PGD "
+			  "and PMD entry\n");
+		numEntries = 0;
+		/* Get the first level page table entry information */
+		/* Read the pointer to first level page table entry */
+		pgd = pgd_offset(mm, ulMpuAddr);
+		/* Read the value in the first level page table entry */
+		pteVal = *(u32 *)pgd;
+		/* Find the page size that is pointed by the first level page
+		 * table entry */
+		pteSize = HW_MMU_PteSizeL1(pteVal); /* update 16 or 1 */
+		/* If pteSize is zero, then call the get_user_pages to create
+		 * the page table entries for this buffer
+		 */
+		if (!pteSize) {
+			down_read(&mm->mmap_sem);
+			/* This call invokes handle_mmu _fault call, which
+			 *causes all pages to be created before we scan the
+			 * page tables
+			 */
+			numUsrPgs = get_user_pages(curr_task, mm, ulMpuAddr, 1,
+							true, 0, NULL, NULL);
+			up_read(&mm->mmap_sem);
+			/* Get the first level page table entry information */
+			/* Read the pointer to first level page table entry */
+			pgd = pgd_offset(mm, ulMpuAddr);
+			/* Read the value in the first level page table entry*/
+			pteVal = *(u32 *)pgd;
+			/* Find the page size that is pointed by the first level
+			 * page table entry
+			 */
+			pteSize = HW_MMU_PteSizeL1(pteVal);
+			DBG_Trace(DBG_LEVEL4, "First level  get_user_pages "
+							"called\n");
+		}
+		/* If the page size is 4K or 64K, then we have to traverse to
+		 * second level page table */
+		if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
+			DBG_Trace(DBG_LEVEL5, "Read the next PMD entry\n");
+			/* Get the second level page table information */
+			pmd = pmd_offset(pgd, ulMpuAddr);
+			ptep = pte_offset_map(pmd, ulMpuAddr);
+			do {
+				ptep = ptep+numEntries;
+				/* Read the value of second level page table
+				 * entry */
+				pteVal = *(u32 *)ptep;
+				/* Find the size of page the second level
+				 * table entry is pointing */
+				/* update 64 or 4 */
+				pteSize = HW_MMU_PteSizeL2(pteVal);
+				/* If pteSize is invalid, then call
+				 * get_user_pages to create the
+				 * page table entries
+				 */
+				if (!pteSize) {
+					numUsrPgs =
+						(ulNumBytes/HW_PAGE_SIZE_4KB);
+					down_read(&mm->mmap_sem);
+					/* This call invokes
+					 *handle_mmu _fault call, which causes
+					 *all pages to be created before we scan
+					 * the page tables */
+					if (numUsrPgs <= PAGES_II_LVL_TABLE) {
+						get_user_pages(curr_task, mm,
+						ulMpuAddr, numUsrPgs, true,  0,
+						NULL, NULL);
+						DBG_Trace(DBG_LEVEL4,
+						"get_user_pages, numUsrPgs"
+						"= %d\n", numUsrPgs);
+					} else {
+						get_user_pages(curr_task, mm,
+						ulMpuAddr, PAGES_II_LVL_TABLE,
+						true, 0, NULL, NULL);
+						DBG_Trace(DBG_LEVEL4,
+						"get_user_pages, numUsrPgs"
+						"= %d\n", PAGES_II_LVL_TABLE);
+					}
+					up_read(&mm->mmap_sem);
+					/* Read the value of second level page
+					 * table  entry */
+					pteVal = *(u32 *)ptep;
+					/* Find the size of page the second
+					 * level table entry is pointing */
+					pteSize = HW_MMU_PteSizeL2(pteVal);
+				}
+				DBG_Trace(DBG_LEVEL4, "TIOMAP_VirtToPhysical:"
+					"*pmd=%x, *pgd=%x, ptep = %x, pteVal="
+					" %x, pteSize=%x\n", *pmd,
+					*(u32 *)pgd, (u32)ptep, pteVal,
+					pteSize);
+
+				/* Extract the physical Addresses */
+				switch (pteSize) {
+				case HW_PAGE_SIZE_64KB:
+					pAddr = pteVal & MMU_LARGE_PAGE_MASK;
+					chunkSz = HW_PAGE_SIZE_64KB;
+					numEntries = 16;
+					numof4KPages = 16;
+					break;
+				case HW_PAGE_SIZE_4KB:
+					pAddr = pteVal & MMU_SMALL_PAGE_MASK;
+					chunkSz = HW_PAGE_SIZE_4KB;
+					numEntries = 1;
+					numof4KPages = 1;
+					break;
+				default:
+					DBG_Trace(DBG_LEVEL7,
+						"TIOMAP_VirtToPhysical:"
+						"Descriptor"
+						"Format Fault-II level,"
+						" PTE size = %x\n",
+						pteSize);
+					return DSP_EFAIL;
+				}
+				temp = 0;
+				while (temp++ < numof4KPages) {
+					physicalAddrTable[phyEntryCounter++] =
+									pAddr;
+					DBG_Trace(DBG_LEVEL4,
+						 "TIOMAP_VirtToPhysical:"
+						 "physicalAddrTable[%d]= %x\n",
+						 (phyEntryCounter-1), pAddr);
+					pAddr += HW_PAGE_SIZE_4KB;
+				}
+				if (DSP_SUCCEEDED(status)) {
+					/* Go to the next page */
+					ulMpuAddr += chunkSz;
+					/* Update the number of bytes that
+					 * are copied */
+					ulNumBytes -= chunkSz;
+					DBG_Trace(DBG_LEVEL4,
+						"TIOMAP_VirtToPhysical: mpuCurr"
+						" = %x, pagesize = %x, "
+						"numBytesRem=%x\n",
+						ulMpuAddr, chunkSz, ulNumBytes);
+				} else {
+					DBG_Trace(DBG_LEVEL7,
+					     " TIOMAP_VirtToPhysical:PTEupdate"
+					     "failed\n");
+				}
+			/* It is observed that the pgd value (first level page
+			 * table entry) is changed after reading the 512
+			 * entries in second level table. So, call the pgd
+			 * functions after reaching 512 entries in second
+			 * level table */
+			} while ((ulMpuAddr & 0x001ff000) && (ulNumBytes));
+		} else {
+			/* Extract the Address to update the IVA MMU table
+			 * with */
+			switch (pteSize) {
+			case HW_PAGE_SIZE_16MB:
+				pAddr = pteVal & MMU_SSECTION_ADDR_MASK;
+					chunkSz = HW_PAGE_SIZE_16MB;
+					numEntries = 16;
+					numof4KPages = 4096;
+					break;
+			case HW_PAGE_SIZE_1MB:
+				pAddr = pteVal & MMU_SECTION_ADDR_MASK;
+					chunkSz = HW_PAGE_SIZE_1MB;
+					numEntries = 1;
+					numof4KPages = 256;
+					break;
+			default:
+				DBG_Trace(DBG_LEVEL7,
+				     "TIOMAP_VirtToPhysical:Descriptor"
+				     "Format Faul-I level, PTE size = "
+				     "%x\n", pteSize);
+				return DSP_EFAIL;
+			}
+			temp = 0;
+			while (temp++ < numof4KPages) {
+					physicalAddrTable[phyEntryCounter++] =
+									 pAddr;
+					DBG_Trace(DBG_LEVEL4,
+						 "TIOMAP_VirtToPhysical:"
+						 "physicalAddrTable[%d]= %x\n",
+						 (phyEntryCounter-1), pAddr);
+					pAddr += HW_PAGE_SIZE_4KB;
+			}
+			if (DSP_SUCCEEDED(status)) {
+				/* Go to the next page */
+				ulMpuAddr += chunkSz;
+				/* Update the number of bytes that are copied */
+				ulNumBytes -= chunkSz;
+				DBG_Trace(DBG_LEVEL4,
+					 "TIOMAP_VirtToPhysical: mpuCurr = %x, "
+					 "pagesize = %x, numBytesRem=%x\n",
+					 ulMpuAddr, chunkSz, ulNumBytes);
+			} else {
+				DBG_Trace(DBG_LEVEL7,
+					 " TIOMAP_VirtToPhysical:PTEupdate"
+					 "failed\n");
+			}
+
+		}
+	}
+	*numOfTableEntries = phyEntryCounter;
+	DBG_Trace(DBG_LEVEL4, " TIOMAP_VirtToPhysical:numofTableEntries=%d\n",
+		  phyEntryCounter);
+	return status;
+}
+
+/*
+ *  ======== PteUpdate ========
+ *      This function calculates the optimum page-aligned addresses and sizes
+ *      Caller must pass page-aligned values
+ */
+static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
+			    u32 va, u32 size,
+			    struct HW_MMUMapAttrs_t *mapAttrs)
+{
+	u32 i;
+	u32 allBits;
+	u32 paCurr = pa;
+	u32 vaCurr = va;
+	u32 numBytes = size;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	DSP_STATUS status = DSP_SOK;
+	u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
+			   HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
+	DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
+		 "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
+	while (numBytes && DSP_SUCCEEDED(status)) {
+		/* To find the max. page size with which both PA & VA are
+		 * aligned */
+		allBits = paCurr | vaCurr;
+		DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
+			 "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
+		for (i = 0; i < 4; i++) {
+			if ((numBytes >= pgSize[i]) && ((allBits &
+			   (pgSize[i] - 1)) == 0)) {
+				DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
+				status = PteSet(pDevContext->pPtAttrs, paCurr,
+						vaCurr, pgSize[i], mapAttrs);
+				paCurr += pgSize[i];
+				vaCurr += pgSize[i];
+				numBytes -= pgSize[i];
+				 /* Don't try smaller sizes. Hopefully we have
+				 * reached an address aligned to a bigger page
+				 * size */
+				break;
+			}
+		}
+	}
+	DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
+		  numBytes);
+	return status;
+}
+
+/*
+ *  ======== PteSet ========
+ *      This function calculates PTE address (MPU virtual) to be updated
+ *      It also manages the L2 page tables
+ */
+static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
+			 u32 size, struct HW_MMUMapAttrs_t *attrs)
+{
+	u32 i;
+	u32 pteVal;
+	u32 pteAddrL1;
+	u32 pteSize;
+	u32 pgTblVa;      /* Base address of the PT that will be updated */
+	u32 L1BaseVa;
+	 /* Compiler warns that the next three variables might be used
+	 * uninitialized in this function. Doesn't seem so. Working around,
+	 * anyways.  */
+	u32 L2BaseVa = 0;
+	u32 L2BasePa = 0;
+	u32 L2PageNum = 0;
+	DSP_STATUS status = DSP_SOK;
+	DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
+		 "size %x, attrs %x\n", pt, pa, va, size, attrs);
+	L1BaseVa = pt->L1BaseVa;
+	pgTblVa = L1BaseVa;
+	if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
+		/* Find whether the L1 PTE points to a valid L2 PT */
+		pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
+		if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
+			pteVal = *(u32 *)pteAddrL1;
+			pteSize = HW_MMU_PteSizeL1(pteVal);
+		} else {
+			return DSP_EFAIL;
+		}
+		SYNC_EnterCS(pt->hCSObj);
+		if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
+			/* Get the L2 PA from the L1 PTE, and find
+			 * corresponding L2 VA */
+			L2BasePa = HW_MMU_PteCoarseL1(pteVal);
+			L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
+			L2PageNum = (L2BasePa - pt->L2BasePa) /
+				    HW_MMU_COARSE_PAGE_SIZE;
+		} else if (pteSize == 0) {
+			/* L1 PTE is invalid. Allocate a L2 PT and
+			 * point the L1 PTE to it */
+			/* Find a free L2 PT. */
+			for (i = 0; (i < pt->L2NumPages) &&
+			    (pt->pgInfo[i].numEntries != 0); i++)
+				;;
+			if (i < pt->L2NumPages) {
+				L2PageNum = i;
+				L2BasePa = pt->L2BasePa + (L2PageNum *
+					   HW_MMU_COARSE_PAGE_SIZE);
+				L2BaseVa = pt->L2BaseVa + (L2PageNum *
+					   HW_MMU_COARSE_PAGE_SIZE);
+				/* Endianness attributes are ignored for
+				 * HW_MMU_COARSE_PAGE_SIZE */
+				status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
+					 HW_MMU_COARSE_PAGE_SIZE, attrs);
+			} else {
+				status = DSP_EMEMORY;
+			}
+		} else {
+			/* Found valid L1 PTE of another size.
+			 * Should not overwrite it. */
+			status = DSP_EFAIL;
+		}
+		if (DSP_SUCCEEDED(status)) {
+			pgTblVa = L2BaseVa;
+			if (size == HW_PAGE_SIZE_64KB)
+				pt->pgInfo[L2PageNum].numEntries += 16;
+			else
+				pt->pgInfo[L2PageNum].numEntries++;
+
+			DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
+				 "PageNum %x numEntries %x\n", L2BaseVa,
+				 L2BasePa, L2PageNum,
+				 pt->pgInfo[L2PageNum].numEntries);
+		}
+		SYNC_LeaveCS(pt->hCSObj);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
+			 pgTblVa, pa, va, size);
+		DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
+			  "mixedSize %x\n", attrs->endianism,
+			  attrs->elementSize, attrs->mixedSize);
+		status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
+	}
+	DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
+	return status;
+}
+
+/* Memory map kernel VA -- memory allocated with vmalloc */
+static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
+				u32 ulMpuAddr, u32 ulVirtAddr,
+				u32 ulNumBytes, u32 ulMapAttr)
+{
+	u32 attrs = ulMapAttr;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	struct HW_MMUMapAttrs_t hwAttrs;
+	struct page *pPage[1];
+	u32 i;
+	u32 paCurr;
+	u32 paNext;
+	u32 vaCurr;
+	u32 sizeCurr;
+	u32 numPages;
+
+	DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
+		  "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr,
+		  ulVirtAddr, ulNumBytes, ulMapAttr);
+	/* Take mapping properties */
+	if (attrs & DSP_MAPBIGENDIAN)
+		hwAttrs.endianism = HW_BIG_ENDIAN;
+	else
+		hwAttrs.endianism = HW_LITTLE_ENDIAN;
+
+	hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
+			     ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
+	/* Ignore elementSize if mixedSize is enabled */
+	if (hwAttrs.mixedSize == 0) {
+		if (attrs & DSP_MAPELEMSIZE8) {
+			/* Size is 8 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
+		} else if (attrs & DSP_MAPELEMSIZE16) {
+			/* Size is 16 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
+		} else if (attrs & DSP_MAPELEMSIZE32) {
+			/* Size is 32 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
+		} else if (attrs & DSP_MAPELEMSIZE64) {
+			/* Size is 64 bit */
+			hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
+		} else {
+			/* Mixedsize isn't enabled, so size can't be zero
+			 * here */
+			DBG_Trace(DBG_LEVEL7, "WMD_BRD_MemMap: MMU element "
+				 "size is zero\n");
+			return DSP_EINVALIDARG;
+		}
+	}
+	 /* Do Kernel va to pa translation.
+	 * Combine physically contiguous regions to reduce TLBs.
+	 * Pass the translated pa to PteUpdate.  */
+	numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	i = 0;
+	vaCurr = ulMpuAddr;
+	pPage[0] = vmalloc_to_page((void *)vaCurr);
+	paNext = page_to_phys(pPage[0]);
+	while (DSP_SUCCEEDED(status) && (i < numPages)) {
+		/* Reuse paNext from the previous iteraion to avoid
+		 * an extra va2pa call */
+		paCurr = paNext;
+		sizeCurr = PAGE_SIZE;
+		/* If the next page is physically contiguous,
+		 * map it with the current one by increasing
+		 * the size of the region to be mapped */
+		while (++i < numPages) {
+			pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
+			paNext = page_to_phys(pPage[0]);
+			DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
+				 "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
+			if (paNext == (paCurr + sizeCurr))
+				sizeCurr += PAGE_SIZE;
+			else
+				break;
+
+		}
+		if (paNext == 0) {
+			status = DSP_EMEMORY;
+			break;
+		}
+		status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
+				  (vaCurr - ulMpuAddr), sizeCurr, &hwAttrs);
+		vaCurr += sizeCurr;
+	}
+func_cont:
+	/* Don't propogate Linux or HW status to upper layers */
+	if (DSP_SUCCEEDED(status)) {
+		status = DSP_SOK;
+		DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
+			 status);
+	} else {
+		DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
+		status = DSP_EFAIL;
+	}
+	 /* In any case, flush the TLB
+	 * This is called from here instead from PteUpdate to avoid unnecessary
+	 * repetition while mapping non-contiguous physical regions of a virtual
+	 * region */
+	/* Waking up DSP before calling TLB Flush */
+	HW_MMU_TLBFlushAll(pDevContext->dwDSPMmuBase);
+	DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap  at end status %x\n", status);
+	return status;
+}
+
+static DSP_STATUS run_IdleBoot(u32 prm_base, u32 cm_base,
+			       u32 sysctrl_base)
+{
+	u32 temp;
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS clk_status = DSP_SOK;
+	enum HW_PwrState_t    pwrState;
+
+	/* Read PM_PWSTST_IVA2 */
+	HW_PWRST_IVA2RegGet(prm_base, &temp);
+	 if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
+		/* IVA2 is not in ON state */
+		/* Read and set PM_PWSTCTRL_IVA2  to ON */
+		HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
+		HW_PWR_IVA2PowerStateSet(prm_base, HW_PWR_DOMAIN_DSP,
+					  HW_PWR_STATE_ON);
+		/* Set the SW supervised state transition */
+		HW_PWR_CLKCTRL_IVA2RegSet(cm_base, HW_SW_SUP_WAKEUP);
+		/* Wait until the state has moved to ON */
+		HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
+	}
+	clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
+	if (DSP_FAILED(clk_status)) {
+		DBG_Trace(DBG_LEVEL6, "CLK_Disbale failed for clk = 0x%x \n",
+			  SERVICESCLK_iva2_ck);
+	}
+	udelay(10);
+	/* Assert IVA2-RST1 and IVA2-RST2  */
+	*((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x07;
+	udelay(30);
+	/* set the SYSC for Idle Boot */
+	*((REG_UWORD32 *)((u32)(sysctrl_base) + 0x404)) = (u32)0x01;
+	clk_status = CLK_Enable(SERVICESCLK_iva2_ck);
+	if (DSP_FAILED(clk_status)) {
+		DBG_Trace(DBG_LEVEL6, "CLK_Enable failed for clk = 0x%x \n",
+			  SERVICESCLK_iva2_ck);
+	}
+	udelay(20);
+	GetHWRegs(prm_base, cm_base);
+	/* Release Reset1 and Reset2 */
+	*((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x05;
+	udelay(20);
+	*((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x04;
+	udelay(30);
+	return status;
+}
+
+
+void GetHWRegs(u32 prm_base, u32 cm_base)
+{
+	u32 temp;
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x00));
+	   DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x10));
+	   DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x20));
+	   DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x48));
+	   DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x4c));
+	   DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x50));
+	   DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x58));
+	   DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE0));
+	   DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE4));
+	   DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
+       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0xA10));
+	   DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
+}
+
+/*
+ *  ======== configureDspMmu ========
+ *      Make DSP MMU page table entries.
+ */
+void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
+		    u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
+		    enum HW_Endianism_t endianism,
+		    enum HW_ElementSize_t elemSize,
+		    enum HW_MMUMixedSize_t mixedSize)
+{
+	struct CFG_HOSTRES resources;
+	struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(sizeInBytes > 0);
+	DBG_Trace(DBG_LEVEL1,
+		 "configureDspMmu entry %x pa %x, va %x, bytes %x ",
+		 nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
+
+	DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
+		 endianism, elemSize, mixedSize);
+	status = CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	status = HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, dataBasePhys,
+				dspBaseVirt, sizeInBytes, nEntryStart,
+				&mapAttrs, HW_SET, HW_SET);
+}
+
+/*
+ *  ======== WaitForStart ========
+ *      Wait for the singal from DSP that it has started, or time out.
+ */
+bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
+{
+	u16 usCount = TIHELEN_ACKTIMEOUT;
+
+	/*  Wait for response from board */
+	while (*((volatile u16 *)dwSyncAddr) && --usCount)
+		UTIL_Wait(TIHELEN_WRITE_DELAY);
+
+	/*  If timed out: return FALSE */
+	if (!usCount) {
+		DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
+		return FALSE;
+	}
+	return TRUE;
+}
diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
new file mode 100644
index 0000000..e3233b2
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
@@ -0,0 +1,568 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/3430/tiomap_pwr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== _tiomap_pwr.c ========
+ *  Description:
+ *      Implementation of DSP wake/sleep routines.
+ *
+ *! Revision History
+ *! ================
+ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
+ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
+ *!		    code.
+ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
+ *! 06-Dec-2002 cring:  Added Palm support.
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <dbdefs.h>
+#include <errbase.h>
+#include <cfg.h>
+#include <drv.h>
+#include <io_sm.h>
+#include <chnl_sm.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <mem.h>
+#include <util.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <brddefs.h>
+#include <dev.h>
+#include <iodefs.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_dspssC64P.h>
+#include <hw_prcm.h>
+#include <hw_mmu.h>
+
+#include <pwr_sh.h>
+
+/*  ----------------------------------- specific to this file */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "_tiomap_util.h"
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+#endif
+#endif
+extern s32 dsp_test_sleepstate;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+extern struct constraint_handle *dsp_constraint_handle;
+#endif
+extern struct MAILBOX_CONTEXT mboxsetting;
+
+extern void GetHWRegs(u32 prm_base, u32 cm_base);
+DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
+					IN void *pArgs);
+DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
+				       IN void *pArgs);
+
+/*
+ *  ======== handle_constraints_set ========
+ *  	Sets new DSP constraint
+ */
+DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
+				  IN void *pArgs)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	u32 *pConstraintVal;
+
+	pConstraintVal = (u32 *)(pArgs);
+	/* Read the target value requested by DSP  */
+	DBG_Trace(DBG_LEVEL7, "handle_constraints_set: opp requested = 0x%x\n",
+						  (u32)*(pConstraintVal+1));
+
+	/* Set the new constraint in resource framework */
+	if (constraint_set(dsp_constraint_handle,
+			   (u32)*(pConstraintVal+1)) == 0)
+		return DSP_SOK;
+	else {
+		DBG_Trace(DBG_LEVEL7,
+			 "handle_constraints_set: Constraint set failed\n");
+		return DSP_EFAIL;
+	}
+#endif /*#ifndef CONFIG_DISABLE_BRIDGE_DVFS */
+#endif /*#ifndef CONFIG_DISABLE_BRIDGE_PM */
+	return DSP_SOK;
+}
+
+/*
+ *  ======== handle_hibernation_fromDSP ========
+ *  	Handle Hibernation requested from DSP
+ */
+DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+	u16 usCount = TIHELEN_ACKTIMEOUT;
+	struct CFG_HOSTRES resources;
+	DSP_STATUS status = DSP_SOK;
+	enum HW_PwrState_t pwrState;
+	u32 opplevel;
+	struct IO_MGR *hIOMgr;
+
+	status = CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status))
+		return status;
+
+	HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+			    &pwrState);
+	/* Wait for DSP to move into Off state,  how much time should
+	 * we wait? */
+	while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
+		UTIL_Wait(PWR_WAIT_USECS);
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				    &pwrState);
+	}
+	if (usCount == 0) {
+		DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
+		status = WMD_E_TIMEOUT;
+		return status;
+	} else {
+
+		/* Save mailbox settings */
+		status = HW_MBOX_saveSettings(resources.dwMboxBase);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
+			 mboxsetting.sysconfig);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
+			 mboxsetting.irqEnable0);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
+			 mboxsetting.irqEnable1);
+		/* Turn off DSP Peripheral clocks and DSP Load monitor timer */
+		status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
+
+		if (DSP_SUCCEEDED(status)) {
+			/* Update the Bridger Driver state */
+			pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+			status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+			if (DSP_FAILED(status))
+				return status;
+			IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
+			/* Set the OPP to low level before moving to OFF mode */
+			if (opplevel != CO_VDD1_OPP1) {
+					DBG_Trace(DBG_LEVEL5,
+						"Tiomap_pwr.c - DSP requested"
+						" OPP = %d, MPU requesting low"
+						" OPP %d instead\n", opplevel,
+						CO_VDD1_OPP1);
+				if (constraint_set(dsp_constraint_handle,
+						  CO_VDD1_OPP1) != 0) {
+					DBG_Trace(DBG_LEVEL7,
+						"handle_hibernation_fromDSP:"
+						"Constraint set failed\n");
+					status = DSP_EFAIL;
+				}
+			}
+#endif
+		} else {
+			DBG_Trace(DBG_LEVEL7,
+				 "handle_hibernation_fromDSP- FAILED\n");
+		}
+	}
+	return status;
+
+#endif
+	return DSP_SOK;
+
+}
+/*
+ *  ======== SleepDSP ========
+ *  	Put DSP in low power consuming state.
+ */
+DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
+		   IN void *pArgs)
+{
+	DSP_STATUS status = DSP_SOK;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+	struct CFG_HOSTRES resources;
+	u16 usCount = TIHELEN_ACKTIMEOUT;
+	enum HW_PwrState_t pwrState;
+	enum HW_PwrState_t targetPwrState;
+
+	status = CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status))
+		return status;
+	DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
+
+		/* next, check if sleep code is valid... */
+	if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
+		DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
+		return DSP_EINVALIDARG;
+	}
+	switch (pDevContext->dwBrdState) {
+	case BRD_RUNNING:
+		if (dsp_test_sleepstate == HW_PWR_STATE_OFF) {
+			IO_InterruptDSP2(pDevContext,
+					 MBX_PM_DSPHIBERNATE);
+			DBG_Trace(DBG_LEVEL7,
+				 "SleepDSP - Sent hibernate "
+				 "command to DSP\n");
+			targetPwrState = HW_PWR_STATE_OFF;
+		} else {
+			IO_InterruptDSP2(pDevContext,
+					 MBX_PM_DSPRETENTION);
+			targetPwrState = HW_PWR_STATE_RET;
+		}
+		break;
+	case BRD_RETENTION:
+		if (dsp_test_sleepstate == HW_PWR_STATE_OFF) {
+			IO_InterruptDSP2(pDevContext,
+					 MBX_PM_DSPHIBERNATE);
+			targetPwrState = HW_PWR_STATE_OFF;
+		} else
+			return DSP_SOK;
+		break;
+	case BRD_HIBERNATION:
+	case BRD_DSP_HIBERNATION:
+		/* Already in Hibernation, so just return */
+		DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
+			 "hibernation\n");
+		return DSP_SOK;
+	case BRD_STOPPED:
+		DBG_Trace(DBG_LEVEL7,
+			 "SleepDSP- Board in STOP state \n");
+		return DSP_SALREADYASLEEP;
+	default:
+		DBG_Trace(DBG_LEVEL7,
+			 "SleepDSP- Bridge in Illegal state\n");
+			return DSP_EFAIL;
+	}
+	/* Get the PRCM DSP power domain status */
+	HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+			    &pwrState);
+	/* Wait for DSP to move into Standby state,  how much time
+	 * should we wait?*/
+	while ((pwrState != targetPwrState) && --usCount) {
+		UTIL_Wait(PWR_WAIT_USECS);
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				    &pwrState);
+	}
+	if (usCount == 0) {
+		DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
+			 " STANDBY %x \n", pwrState);
+		return WMD_E_TIMEOUT;
+	} else {
+		DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
+			 pwrState);
+		/* Update the Bridger Driver state */
+		if (dsp_test_sleepstate == HW_PWR_STATE_OFF)
+			pDevContext->dwBrdState = BRD_HIBERNATION;
+		else
+			pDevContext->dwBrdState = BRD_RETENTION;
+		/* Turn off DSP Peripheral clocks  */
+		status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
+		if (DSP_FAILED(status))
+			DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
+	}
+#endif
+	return status;
+}
+
+
+/*
+ *  ======== WakeDSP ========
+ *  	Wake up DSP from sleep.
+ */
+DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+	DSP_STATUS status = DSP_SOK;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+	struct CFG_HOSTRES resources;
+	enum HW_PwrState_t pwrState;
+
+	status = CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+	if (DSP_FAILED(status))
+		return status;
+	/* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
+	if (pDevContext->dwBrdState == BRD_RUNNING ||
+		pDevContext->dwBrdState == BRD_STOPPED ||
+		pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
+		/* The Device is in 'RET' or 'OFF' state and WMD state is not
+		 * 'SLEEP', this means state inconsistency, so return  */
+		status = DSP_SOK;
+		return status;
+	}
+	/* Enable the DSP peripheral clocks and load monitor timer
+	 * before waking the DSP */
+	DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
+		 pDevContext->uDspPerClks);
+	status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
+	udelay(10);
+	if (DSP_SUCCEEDED(status)) {
+		/* Send a message to DSP to wake up */
+		IO_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
+		HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
+				    &pwrState);
+		DBG_Trace(DBG_LEVEL7,
+			 "\nWakeDSP: Power State After sending Interrupt "
+			 "to DSP %x\n", pwrState);
+		/* set the device state to RUNNIG */
+		pDevContext->dwBrdState = BRD_RUNNING;
+	} else {
+		DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
+	}
+#endif
+	return status;
+}
+
+/*
+ *  ======== DSPPeripheralClkCtrl ========
+ *  	Enable/Disable the DSP peripheral clocks as needed..
+ */
+DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
+				IN void *pArgs)
+{
+	u32 extClk = 0;
+	u32 extClkId = 0;
+	u32 extClkCmd = 0;
+	u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
+	u32 tmpIndex;
+	u32 dspPerClksBefore;
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+
+	DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
+	dspPerClksBefore = pDevContext->uDspPerClks;
+	DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
+		  dspPerClksBefore);
+
+	extClk = (u32)*((u32 *)pArgs);
+
+	DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
+		 extClk);
+
+	extClkId = extClk & MBX_PM_CLK_IDMASK;
+
+	/* process the power message -- TODO, keep it in a separate function */
+	for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
+		if (extClkId == BPWR_CLKID[tmpIndex]) {
+			clkIdIndex = tmpIndex;
+			break;
+		}
+	}
+	/* TODO -- Assert may be a too hard restriction here.. May be we should
+	 * just return with failure when the CLK ID does not match */
+	/* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
+	if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
+		DBG_Trace(DBG_LEVEL7,
+			 "DSPPeripheralClkCtrl : Could n't get clock Id for"
+			 "clkid 0x%x \n", clkIdIndex);
+		/* return with a more meaningfull error code */
+		return DSP_EFAIL;
+	}
+	extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
+	switch (extClkCmd) {
+	case BPWR_DisableClock:
+		/* Call BP to disable the needed clock */
+		DBG_Trace(DBG_LEVEL3,
+			 "DSPPeripheralClkCtrl : Disable CLK for \n");
+		status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
+		status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
+		if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
+			(pDevContext->uDspPerClks) &=
+				(~((u32) (1 << clkIdIndex)));
+		} else {
+			DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
+				 "to disable clk\n");
+		}
+		break;
+	case BPWR_EnableClock:
+		DBG_Trace(DBG_LEVEL3,
+			 "DSPPeripheralClkCtrl : Enable CLK for \n");
+		status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
+		status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
+		if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
+			(pDevContext->uDspPerClks) |= (1 << clkIdIndex);
+		} else {
+			DBG_Trace(DBG_LEVEL7,
+				 "DSPPeripheralClkCtrl:Failed to Enable clk\n");
+		}
+		break;
+	default:
+		DBG_Trace(DBG_LEVEL3,
+			 "DSPPeripheralClkCtrl : Unsupported CMD \n");
+		/* unsupported cmd */
+		/* TODO -- provide support for AUTOIDLE Enable/Disable
+		 * commands */
+	}
+	return status;
+}
+
+/*
+ *  ========PreScale_DSP========
+ *  Sends prescale notification to DSP
+ *
+ */
+DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	u32 level;
+	u32 voltage_domain;
+
+	voltage_domain = *((u32 *)pArgs);
+	level = *((u32 *)pArgs + 1);
+
+	DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
+		 "0x%x\n", voltage_domain, level);
+	if  ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
+	    (pDevContext->dwBrdState == BRD_RETENTION) ||
+	    (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
+		DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
+			 "No notification to DSP\n");
+		return DSP_SOK;
+	} else  if ((pDevContext->dwBrdState == BRD_RUNNING)) {
+		/* Send a prenotificatio to DSP */
+		DBG_Trace(DBG_LEVEL7,
+			 "PreScale_DSP: Sent notification to DSP\n");
+		IO_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
+		return DSP_SOK;
+	} else {
+		DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
+			  " state in wrong state");
+		return DSP_EFAIL;
+	}
+#endif /*#ifndef CONFIG_DISABLE_BRIDGE_DVFS */
+#endif  /*#ifndef CONFIG_DISABLE_BRIDGE_PM */
+	return DSP_SOK;
+}
+
+/*
+ *  ========PostScale_DSP========
+ *  Sends postscale notification to DSP
+ *
+ */
+DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	u32 level;
+	u32 voltage_domain;
+	struct IO_MGR *hIOMgr;
+	DSP_STATUS status = DSP_SOK;
+
+	status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+
+	voltage_domain = *((u32 *)pArgs);
+	level = *((u32 *)pArgs + 1);
+	DBG_Trace(DBG_LEVEL7,
+		 "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
+		 voltage_domain, level);
+	if  ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
+		    (pDevContext->dwBrdState == BRD_RETENTION) ||
+		    (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
+		/* Update the OPP value in shared memory */
+		IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
+		DBG_Trace(DBG_LEVEL7,
+			 "PostScale_DSP: IVA in sleep. Wrote to shared "
+			 "memory \n");
+		return DSP_SOK;
+	} else  if ((pDevContext->dwBrdState == BRD_RUNNING)) {
+		/* Update the OPP value in shared memory */
+		IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
+		/* Send a post notification to DSP */
+		IO_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
+		DBG_Trace(DBG_LEVEL7,
+			 "PostScale_DSP: Wrote to shared memory Sent post"
+			 " notification to DSP\n");
+		return DSP_SOK;
+	} else {
+		DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
+			  "in wrong state");
+		return DSP_EFAIL;
+	}
+#endif /* CONFIG_DISABLE_BRIDGE_DVFS */
+#endif /* CONFIG_DISABLE_BRIDGE_PM */
+	return DSP_SOK;
+}
+
+/*
+ *  ========DSP_PeripheralClocks_Disable========
+ *  Disables all the peripheral clocks that were requested by DSP
+ */
+DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
+					IN void *pArgs)
+{
+
+	u32 clkIdx;
+	DSP_STATUS status = DSP_SOK;
+
+	for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
+		if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
+			/* Disables the interface clock of the peripheral */
+			status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7,
+					 "Failed to Enable the DSP Peripheral"
+					 "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+			}
+			/* Disables the functional clock of the periphearl */
+			status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7,
+					 "Failed to Enable the DSP Peripheral"
+					 "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+			}
+		}
+	}
+	return status;
+}
+
+/*
+ *  ========DSP_PeripheralClocks_Enable========
+ *  Enables all the peripheral clocks that were requested by DSP
+ */
+DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
+				      IN void *pArgs)
+{
+	u32 clkIdx;
+	DSP_STATUS status = DSP_SOK;
+
+	for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
+		if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
+			/* Enable the interface clock of the peripheral */
+			status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7,
+					 "Failed to Enable the DSP Peripheral"
+					 "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+			}
+			/* Enable the functional clock of the periphearl */
+			status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7,
+					 "Failed to Enable the DSP Peripheral"
+					 "Clk 0x%x \n", BPWR_Clks[clkIdx]);
+			}
+		}
+	}
+	return status;
+}
+
+
+
diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
new file mode 100644
index 0000000..bce33a4
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_io.c
@@ -0,0 +1,430 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/tiomap_io.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_io.c ========
+ *  Description:
+ *      Implementation for the io read/write routines.
+ *
+ *! Revision History
+ *! ================
+ *! 16-Feb-2004 vp:  Fixed warning in WriteDspData function.
+ *! 16-Apr-2003 vp:  Added support for TC word swap
+ *! 26-Feb-2003 vp:  Fixed issue with EXT_BEG and EXT_END address.
+ *! 24-Feb-2003 vp:  Ported to Linux platform
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+#include <drv.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <mem.h>
+#include <util.h>
+#include <cfg.h>
+
+/*  ----------------------------------- specific to this file */
+#include "_tiomap.h"
+#include "_tiomap_pwr.h"
+#include "tiomap_io.h"
+
+static u32 ulExtBase;
+static u32 ulExtEnd;
+
+static u32 ulShm0End;
+static u32 ulDynExtBase;
+u32 ulTraceSecBeg;
+u32 ulTraceSecEnd;
+u32 ulShmBaseVirt;
+
+bool bSymbolsReloaded = true;
+
+/*
+ *  ======== ReadExtDspData ========
+ *      Copies DSP external memory buffers to the host side buffers.
+ */
+DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
+			 OUT u8 *pbHostBuf, u32 dwDSPAddr,
+			 u32 ulNumBytes, u32 ulMemType)
+{
+	DSP_STATUS	status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	u32	offset;
+	static u32	ulShmBaseVirt;
+	u32	ulTLBBaseVirt = 0;
+	u32	ulShmOffsetVirt = 0;
+	static u32	ulTraceSecBeg;
+	static u32	ulTraceSecEnd;
+	u32	dwExtProgVirtMem;
+	u32	dwBaseAddr = pDevContext->dwDspExtBaseAddr;
+	bool	bTraceRead = false;
+
+	DBG_Trace(DBG_ENTER, "ReadExtDspData,"
+	"hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
+	"\n\t\tdwDSPAddr:  0x%x\n\t\tulNumBytes:  0x%x\n\t\t"
+	"ulMemType:  0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
+	ulNumBytes, ulMemType);
+
+	if (!ulShmBaseVirt) {
+		status = DEV_GetSymbol(pDevContext->hDevObject,
+		SHMBASENAME, &ulShmBaseVirt);
+	}
+	DBC_Assert(ulShmBaseVirt != 0);
+
+	/* Check if it is a read of Trace section */
+	if (!ulTraceSecBeg) {
+		status = DEV_GetSymbol(pDevContext->hDevObject,
+		DSP_TRACESEC_BEG, &ulTraceSecBeg);
+	}
+	DBC_Assert(ulTraceSecBeg != 0);
+
+	if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
+		status = DEV_GetSymbol(pDevContext->hDevObject,
+		DSP_TRACESEC_END, &ulTraceSecEnd);
+	}
+	DBC_Assert(ulTraceSecEnd != 0);
+
+	if (DSP_SUCCEEDED(status)) {
+		if ((dwDSPAddr <= ulTraceSecEnd) &&
+			(dwDSPAddr >= ulTraceSecBeg)) {
+			DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
+				 "section 0x%x \n", dwDSPAddr);
+			bTraceRead = true;
+		}
+	}
+
+	/* If reading from TRACE, force remap/unmap */
+	if ((bTraceRead) && dwBaseAddr) {
+		dwBaseAddr = 0;
+		pDevContext->dwDspExtBaseAddr = 0;
+	}
+
+	if (!dwBaseAddr) {
+		/* Initialize ulExtBase and ulExtEnd */
+		ulExtBase = 0;
+		ulExtEnd = 0;
+
+		/* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
+		if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
+			status = DEV_GetSymbol(pDevContext->hDevObject,
+					DYNEXTBASE, &ulDynExtBase);
+		}
+		DBC_Assert(ulDynExtBase != 0);
+
+		if (DSP_SUCCEEDED(status)) {
+			status = DEV_GetSymbol(pDevContext->hDevObject,
+				 EXTBASE, &ulExtBase);
+		}
+		DBC_Assert(ulExtBase != 0);
+
+		if (DSP_SUCCEEDED(status)) {
+			status = DEV_GetSymbol(pDevContext->hDevObject,
+					EXTEND,	&ulExtEnd);
+		}
+		DBC_Assert(ulExtEnd != 0);
+
+	/* Trace buffer is right after the SHM SEG0,
+	*  so set the base address to SHMBASE */
+		if (bTraceRead) {
+			ulExtBase = ulShmBaseVirt;
+			ulExtEnd = ulTraceSecEnd;
+		}
+
+		DBC_Assert(ulExtEnd != 0);
+		DBC_Assert(ulExtEnd > ulExtBase);
+
+		if (ulExtEnd < ulExtBase)
+			status = DSP_EFAIL;
+
+		if (DSP_SUCCEEDED(status)) {
+			ulTLBBaseVirt =
+			pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
+			DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+			dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
+
+			if (bTraceRead) {
+				DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+				"GPP VA pointing to SHMMEMBASE 0x%x \n",
+				 dwExtProgVirtMem);
+			} else {
+				ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
+				ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
+						ulDynExtBase + 1,
+						HW_PAGE_SIZE_64KB);
+				dwExtProgVirtMem -= ulShmOffsetVirt;
+				dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
+				DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+				"GPP VA pointing to EXTMEMBASE 0x%x \n",
+				dwExtProgVirtMem);
+				pDevContext->dwDspExtBaseAddr =
+						dwExtProgVirtMem;
+
+	/* This dwDspExtBaseAddr will get cleared only when the board is
+	* stopped. */
+				if (!pDevContext->dwDspExtBaseAddr) {
+					status = DSP_EFAIL;
+					DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
+					"failed to Map the program memory\n");
+				}
+			}
+
+			dwBaseAddr = dwExtProgVirtMem;
+		}
+	}
+
+	if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
+		DBG_Trace(DBG_LEVEL7,
+		"Symbols missing for Ext Prog reading \n");
+		status = DSP_EFAIL;
+	}
+
+	offset = dwDSPAddr - ulExtBase;
+
+	if (DSP_SUCCEEDED(status))
+		memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
+
+	return status;
+}
+/*
+ *  ======== WriteDspData ========
+ *  purpose:
+ *      Copies buffers to the DSP internal/external memory.
+ */
+DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
+			u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
+{
+	u32 offset;
+	u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
+	struct CFG_HOSTRES resources;
+	DSP_STATUS status;
+	u32 base1, base2, base3;
+	base1 = OMAP_DSP_MEM1_SIZE;
+	base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
+	base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
+	DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
+
+	status =  CFG_GetHostResources(
+		 (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+
+	offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
+	if (offset < base1) {
+		dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
+						resources.dwMemLength[2]);
+	} else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
+		dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
+						resources.dwMemLength[3]);
+		offset = offset - base2;
+	} else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
+		offset < base3 + OMAP_DSP_MEM3_SIZE) {
+		dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
+						resources.dwMemLength[4]);
+		offset = offset - base3;
+	} else{
+		status = DSP_EFAIL;
+		return status;
+	}
+	if (ulNumBytes)
+		memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
+	else
+		*((u32 *) pbHostBuf) = dwBaseAddr+offset;
+
+	return status;
+}
+
+/*
+ *  ======== WriteExtDspData ========
+ *  purpose:
+ *      Copies buffers to the external memory.
+ *
+ */
+DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+			  IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
+			  u32 ulMemType, bool bDynamicLoad)
+{
+	u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
+	u32 dwOffset = 0;
+	u8 bTempByte1, bTempByte2;
+	u8 remainByte[4];
+	s32 i;
+	DSP_STATUS retVal = DSP_SOK;
+	u32 dwExtProgVirtMem;
+	u32 ulTLBBaseVirt = 0;
+	u32 ulShmOffsetVirt = 0;
+	struct CFG_HOSTRES hostRes;
+	bool bTraceLoad = false;
+	bTempByte1 = 0x0;
+	bTempByte2 = 0x0;
+
+	DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
+		 "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
+	  if (bSymbolsReloaded) {
+		/* Check if it is a load to Trace section */
+		retVal = DEV_GetSymbol(pDevContext->hDevObject,
+					DSP_TRACESEC_BEG, &ulTraceSecBeg);
+		if (DSP_SUCCEEDED(retVal))
+			retVal = DEV_GetSymbol(pDevContext->hDevObject,
+				 DSP_TRACESEC_END, &ulTraceSecEnd);
+	}
+	if (DSP_SUCCEEDED(retVal)) {
+		if ((dwDSPAddr <= ulTraceSecEnd) &&
+		   (dwDSPAddr >= ulTraceSecBeg)) {
+			DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
+				 "section 0x%x \n", dwDSPAddr);
+			bTraceLoad = true;
+		}
+	}
+
+	/* If dynamic, force remap/unmap */
+	if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
+		dwBaseAddr = 0;
+		MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
+		pDevContext->dwDspExtBaseAddr = 0x0;
+	}
+	if (!dwBaseAddr) {
+		if (bSymbolsReloaded)
+			/* Get SHM_BEG  EXT_BEG and EXT_END. */
+			retVal = DEV_GetSymbol(pDevContext->hDevObject,
+						SHMBASENAME, &ulShmBaseVirt);
+		DBC_Assert(ulShmBaseVirt != 0);
+		if (bDynamicLoad) {
+			if (DSP_SUCCEEDED(retVal)) {
+				if (bSymbolsReloaded)
+					retVal = DEV_GetSymbol(pDevContext->
+						hDevObject, DYNEXTBASE,
+						&ulExtBase);
+			}
+			DBC_Assert(ulExtBase != 0);
+			if (DSP_SUCCEEDED(retVal)) {
+				/* DR  OMAPS00013235 : DLModules array may be
+				 * in EXTMEM. It is expected that DYNEXTMEM and
+				 * EXTMEM are contiguous, so checking for the
+				 * upper bound at EXTEND should be Ok. */
+				if (bSymbolsReloaded)
+					retVal = DEV_GetSymbol(pDevContext->
+						hDevObject, EXTEND, &ulExtEnd);
+			}
+		} else {
+			if (bSymbolsReloaded) {
+				if (DSP_SUCCEEDED(retVal))
+					retVal = DEV_GetSymbol(pDevContext->
+						hDevObject, EXTBASE,
+						&ulExtBase);
+				DBC_Assert(ulExtBase != 0);
+				if (DSP_SUCCEEDED(retVal))
+					retVal = DEV_GetSymbol(pDevContext->
+						hDevObject, EXTEND, &ulExtEnd);
+			}
+		}
+		/* Trace buffer it right after the SHM SEG0, so set the
+		 * 	base address to SHMBASE */
+		if (bTraceLoad)
+			ulExtBase = ulShmBaseVirt;
+
+		DBC_Assert(ulExtEnd != 0);
+		DBC_Assert(ulExtEnd > ulExtBase);
+		if (ulExtEnd < ulExtBase)
+			retVal = DSP_EFAIL;
+
+		if (DSP_SUCCEEDED(retVal)) {
+			ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
+					DSPWORDSIZE;
+			DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
+
+			if (bSymbolsReloaded) {
+				if (DSP_SUCCEEDED(retVal)) {
+					retVal = DEV_GetSymbol(pDevContext->
+						 hDevObject, DSP_TRACESEC_END,
+						 &ulShm0End);
+				}
+				if (DSP_SUCCEEDED(retVal)) {
+					retVal = DEV_GetSymbol(pDevContext->
+						 hDevObject, DYNEXTBASE,
+						 &ulDynExtBase);
+				}
+			}
+			ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
+			if (bTraceLoad) {
+				dwExtProgVirtMem = pDevContext->aTLBEntry[0].
+						   ulGppVa;
+			} else {
+				CFG_GetHostResources(
+					(struct CFG_DEVNODE *)
+					DRV_GetFirstDevExtension(), &hostRes);
+				dwExtProgVirtMem = hostRes.dwMemBase[1];
+				dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
+			}
+			DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
+				 "pointing to EXTMEMBASE 0x%x \n",
+				 dwExtProgVirtMem);
+
+			pDevContext->dwDspExtBaseAddr =
+				(u32)MEM_LinearAddress((void *)
+				TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
+				- ulExtBase);
+			dwBaseAddr += pDevContext->dwDspExtBaseAddr;
+			/* This dwDspExtBaseAddr will get cleared only when
+			 * the board is stopped.  */
+			if (!pDevContext->dwDspExtBaseAddr) {
+				retVal = DSP_EFAIL;
+				DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
+					 "to Map the program memory\n");
+			}
+		}
+	}
+	if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
+		DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
+		retVal = DSP_EFAIL;
+	}
+	if (DSP_SUCCEEDED(retVal)) {
+		for (i = 0; i < 4; i++)
+			remainByte[i] = 0x0;
+
+		dwOffset = dwDSPAddr - ulExtBase;
+		/* Also make sure the dwDSPAddr is < ulExtEnd */
+		if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
+			DBG_Trace(DBG_LEVEL7, "We can not load at this address "
+				 "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
+				 "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
+				 ulExtEnd);
+			retVal = DSP_EFAIL;
+		}
+	}
+	if (DSP_SUCCEEDED(retVal)) {
+		if (ulNumBytes)
+			memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
+				ulNumBytes);
+		else
+			*((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
+	}
+	/* Unmap here to force remap for other Ext loads */
+	if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
+		MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
+		pDevContext->dwDspExtBaseAddr = 0x0;
+	}
+	bSymbolsReloaded = false;
+	return retVal;
+}
+
diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
new file mode 100644
index 0000000..af6c83f
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_io.h
@@ -0,0 +1,112 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/tiomap_io.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== _tiomap_io.h ========
+ *  Description:
+ *      Definitions, types and function prototypes for the io
+ *      (r/w external mem).
+ *
+ *! Revision History
+ *! ================
+ *! 08-Oct-2002 rr:  Created.
+ */
+
+#ifndef _TIOMAP_IO_
+#define _TIOMAP_IO_
+
+/*
+ * Symbol that defines beginning of shared memory.
+ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
+ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
+ * (see dspMmuTlbEntry()).
+ */
+#define SHMBASENAME "SHM_BEG"
+#define EXTBASE     "EXT_BEG"
+#define EXTEND      "_EXT_END"
+#define DYNEXTBASE  "_DYNEXT_BEG"
+#define DYNEXTEND   "_DYNEXT_END"
+#define IVAEXTMEMBASE   "_IVAEXTMEM_BEG"
+#define IVAEXTMEMEND   "_IVAEXTMEM_END"
+
+
+#define DSP_TRACESEC_BEG  "_BRIDGE_TRACE_BEG"
+#define DSP_TRACESEC_END  "_BRIDGE_TRACE_END"
+
+#define SYS_PUTCBEG               "_SYS_PUTCBEG"
+#define SYS_PUTCEND               "_SYS_PUTCEND"
+#define BRIDGE_SYS_PUTC_current   "_BRIDGE_SYS_PUTC_current"
+
+
+#define WORDSWAP_ENABLE 0x3	/* Enable word swap */
+
+/*
+ *  ======== ReadExtDspData ========
+ *  Reads it from DSP External memory. The external memory for the DSP
+ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
+ */
+extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+				OUT u8 *pbHostBuf, u32 dwDSPAddr,
+				u32 ulNumBytes, u32 ulMemType);
+
+/*
+ *  ======== WriteDspData ========
+ */
+extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
+			       OUT u8 *pbHostBuf, u32 dwDSPAddr,
+			       u32 ulNumBytes, u32 ulMemType);
+
+/*
+ *  ======== WriteExtDspData ========
+ *  Writes to the DSP External memory for external program.
+ *  The ext mem for progra is configured by the combination of DSP MMU and
+ *  SHM Memory manager in the CDB
+ */
+extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
+				 IN u8 *pbHostBuf, u32 dwDSPAddr,
+				 u32 ulNumBytes, u32 ulMemType,
+				 bool bDynamicLoad);
+
+/*
+ * ======== WriteExt32BitDspData ========
+ * Writes 32 bit data to the external memory
+ */
+extern inline void WriteExt32BitDspData(IN const
+		struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
+		IN u32 val)
+{
+	*(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
+			      0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
+}
+
+/*
+ * ======== ReadExt32BitDspData ========
+ * Reads 32 bit data from the external memory
+ */
+extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
+				       *pDevContext, IN u32 dwDSPAddr)
+{
+	u32 retVal;
+	retVal = *(u32 *)dwDSPAddr;
+
+	retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
+		 & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
+	return retVal;
+}
+
+#endif				/* _TIOMAP_IO_ */
+
diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
new file mode 100644
index 0000000..d554e36
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
@@ -0,0 +1,305 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/2430/tiomap_sm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== tiomap_sm.c ========
+ *  Description:
+ *      Implements lower edge channel class library functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 05-Jan-2004 vp    Updated for the new HW library for 24xx platform.
+ *! 12-Feb-2004 hp    use 'CFG_GetHostResources' to fetch virtual addresses of
+ *!           PRCM, dMMU components.
+ *! 08-Oct-2002 rr    Renamed to tiomap1510_sm.c
+ *! 15-Feb-2002 ag    Remove #include <pkfuncs.h> & util.h.
+ *! 07-Jan-2001 ag    Set DSP MBX val (to DSP) contained in DEV context.
+ *! 05-Nov-2001 kc:   Modified CHNLSM_ISR to read mailbox1 interrupt values
+ *! 26-Sep-2001 rr:   InterruptDSP does not spin forever for retail build.
+ *! 29-Aug-2001 rr:   Cleaned up the non referenced variables.
+ *! 26-Jul-2001 jeh   Enable interrupt to DSP.
+ *! 28-Jun-2001 ag    Disable INTR gen to DSP in CHNLSM_InterruptDSP().
+ *! 26-Jun-2001 ag    Added INTR support.
+ *! 17-May-2000 ag    Initial. No INTR support.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <drv.h>
+#include <isr.h>
+#include <util.h>
+
+/*  ----------------------------------- Mini Driver */
+#include <wmd.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <wcd.h>
+#include <dev.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mbox.h>
+
+/*  ----------------------------------- This */
+#include "_tiomap.h"
+#include <chnl_sm.h>
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+extern struct constraint_handle *dsp_constraint_handle;
+#endif
+#endif
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#ifndef DEBUG
+#define TIHELEN_INT_TIMEOUT     1
+#define LOOP_COUNT              1000000
+extern u64 tiomap1510_liTicksPerSecond;	/* Timer frequency */
+#endif
+
+extern struct MAILBOX_CONTEXT mboxsetting;
+extern DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT
+					     *pDevContext, IN void *pArgs);
+/*
+ *  ======== CHNLSM_EnableInterrupt ========
+ *      Enables interrupts from DSP.
+ */
+DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	HW_STATUS hwStatus;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+	u32 numMbxMsg;
+	u32 mbxValue;
+	struct CFG_HOSTRES resources;
+	u32 devType;
+	struct IO_MGR *hIOMgr;
+
+	DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
+
+	/* Read the messages in the mailbox until the message queue is empty */
+
+	status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+	status = DEV_GetDevType(pDevContext->hDevObject, &devType);
+	status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
+	if (devType == DSP_UNIT) {
+		hwStatus = HW_MBOX_NumMsgGet(resources.dwMboxBase,
+					       MBOX_DSP2ARM, &numMbxMsg);
+		while (numMbxMsg != 0) {
+			hwStatus = HW_MBOX_MsgRead(resources.dwMboxBase,
+						     MBOX_DSP2ARM,
+						     &mbxValue);
+			numMbxMsg--;
+		}
+		/* clear the DSP mailbox as well...*/
+		hwStatus = HW_MBOX_NumMsgGet(resources.dwMboxBase,
+					       MBOX_ARM2DSP, &numMbxMsg);
+		while (numMbxMsg != 0) {
+			hwStatus = HW_MBOX_MsgRead(resources.dwMboxBase,
+						    MBOX_ARM2DSP, &mbxValue);
+			numMbxMsg--;
+			UTIL_Wait(10);
+
+			HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP,
+					  HW_MBOX_U1_DSP1,
+					  HW_MBOX_INT_NEW_MSG);
+		}
+		/* Enable the new message events on this IRQ line */
+		hwStatus = HW_MBOX_EventEnable(resources.dwMboxBase,
+						 MBOX_DSP2ARM,
+						 MBOX_ARM,
+						 HW_MBOX_INT_NEW_MSG);
+	}
+
+	return status;
+}
+
+/*
+ *  ======== CHNLSM_DisableInterrupt ========
+ *      Disables interrupts from DSP.
+ */
+DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	HW_STATUS hwStatus;
+	struct CFG_HOSTRES resources;
+
+	DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", hDevContext);
+
+	status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+	hwStatus = HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
+					  MBOX_ARM, HW_MBOX_INT_NEW_MSG);
+	return status;
+}
+
+/*
+ *  ======== CHNLSM_InterruptDSP ========
+ *      Send an interrupt to the DSP processor(s).
+ */
+DSP_STATUS CHNLSM_InterruptDSP(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	u32 opplevel;
+#endif
+#endif
+	HW_STATUS hwStatus;
+	u32 mbxFull;
+	struct CFG_HOSTRES resources;
+	u16 cnt = 10;
+	u32 temp;
+	/* We are waiting indefinitely here. This needs to be fixed in the
+	 * second phase */
+	status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+
+	if  (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
+	    pDevContext->dwBrdState == BRD_HIBERNATION) {
+		pDevContext->dwBrdState = BRD_RUNNING;
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+		opplevel = constraint_get_level(dsp_constraint_handle);
+		/* If OPP is at minimum level, increase it before waking up
+		 * the DSP */
+		if (opplevel == 1) {
+			if (constraint_set(dsp_constraint_handle,
+			   (opplevel+1)) != 0) {
+				DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP: "
+					 "Constraint set failed\n");
+				return DSP_EFAIL;
+			}
+			DBG_Trace(DBG_LEVEL7, "CHNLSM_InterruptDSP:Setting "
+				 "the vdd1 constraint level to %d before "
+				 "waking DSP \n", (opplevel + 1));
+		}
+
+#endif
+#endif
+		/* Read MMU register to invoke short wakeup of DSP */
+		temp = (u32) *((REG_UWORD32 *) ((u32)
+		       (resources.dwDmmuBase) + 0x10));
+
+		/* Restore mailbox settings */
+		status = HW_MBOX_restoreSettings(resources.dwMboxBase);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
+			  mboxsetting.sysconfig);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
+			  mboxsetting.irqEnable0);
+		DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
+			 mboxsetting.irqEnable1);
+		/* Restart the peripheral clocks that were disabled */
+		DSP_PeripheralClocks_Enable(hDevContext, NULL);
+
+	}
+	while (--cnt) {
+		hwStatus = HW_MBOX_IsFull(resources.dwMboxBase,
+					   MBOX_ARM2DSP, &mbxFull);
+		if (mbxFull)
+			UTIL_Wait(1000);	/* wait for 1 ms)      */
+		else
+			break;
+	}
+	if (!cnt) {
+		DBG_Trace(DBG_LEVEL7, "Timed out waiting for DSP mailbox \n");
+		status = WMD_E_TIMEOUT;
+		return status;
+	}
+	DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
+		 pDevContext->wIntrVal2Dsp);
+
+	hwStatus = HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
+				     pDevContext->wIntrVal2Dsp);
+	/* set the Mailbox interrupt to default value */
+	pDevContext->wIntrVal2Dsp = MBX_PCPY_CLASS;
+	return status;
+}
+
+/*
+ *  ======== CHNLSM_InterruptDSP2 ========
+ *      Set MBX value & send an interrupt to the DSP processor(s).
+ */
+DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *hDevContext,
+				u16 wMbVal)
+{
+	struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
+
+	pDevContext->wIntrVal2Dsp = wMbVal;
+
+	return CHNLSM_InterruptDSP(hDevContext);
+}
+
+/*
+ *  ======== CHNLSM_DPC ========
+ */
+void CHNLSM_DPC(struct WMD_DEV_CONTEXT *hDevContext)
+{
+	DBG_Trace(DBG_ENTER, "CHNLSM_DPC(0x%x)\n", hDevContext);
+}
+
+/*
+ *  ======== CHNLSM_ISR ========
+ */
+bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext, OUT bool *pfSchedDPC,
+		OUT u16 *pwIntrVal)
+{
+	bool fMyInterrupt = true;	/*
+					 * We own the mbx and
+					 * we're not sharing it
+					 */
+	struct CFG_HOSTRES resources;
+	u32 numMbxMsg;
+	u32 mbxValue;
+
+	DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", hDevContext);
+
+	CFG_GetHostResources(
+		(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
+
+	HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
+
+	if (numMbxMsg > 0) {
+		HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
+
+		HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
+				 HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
+
+		DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
+		*pwIntrVal = (u16) mbxValue;
+	}
+	/* Set *pfSchedDPC to true; */
+	*pfSchedDPC = true;
+	return fMyInterrupt;
+}
+
diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
new file mode 100644
index 0000000..3529230
--- /dev/null
+++ b/drivers/dsp/bridge/wmd/ue_deh.c
@@ -0,0 +1,502 @@
+/*
+ * linux/drivers/dsp/bridge/wmd/linux/omap/common/ue_deh.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== ue_deh.c ========
+ *  Description:
+ *      Implements upper edge DSP exception handling (DEH) functions.
+ *
+ *! Revision History:
+ *! ================
+ *! 03-Jan-2005 hn: Support for IVA DEH.
+ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
+ *! 19-Feb-2003 vp: Code review updates.
+ *!                 - Cosmetic changes.
+ *! 18-Oct-2002 sb: Ported to Linux platform.
+ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
+ *! 10-Sep-2001 kc: created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <dbg.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <csl.h>
+#include <cfg.h>
+#include <dpc.h>
+#include <isr.h>
+#include <mem.h>
+#include <ntfy.h>
+#include <drv.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmddeh.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+#include <wcd.h>
+
+/* ------------------------------------ Hardware Abstraction Layer */
+#include <hw_defs.h>
+#include <hw_mmu.h>
+
+/*  ----------------------------------- This */
+#include "mmu_fault.h"
+#include "_tiomap.h"
+#include "_deh.h"
+#include <_tiomap_mmu.h>
+
+struct HW_MMUMapAttrs_t  mapAttrs = { HW_LITTLE_ENDIAN, HW_ELEM_SIZE_16BIT,
+					HW_MMU_CPUES} ;
+#define VirtToPhys(x)       ((x) - PAGE_OFFSET + PHYS_OFFSET)
+/*
+ *  ======== WMD_DEH_Create ========
+ *      Creates DEH manager object.
+ */
+DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
+			 struct DEV_OBJECT *hDevObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DEH_MGR *pDehMgr = NULL;
+	struct CFG_HOSTRES cfgHostRes;
+	struct CFG_DEVNODE *hDevNode;
+	struct WMD_DEV_CONTEXT *hWmdContext = NULL;
+
+	DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
+	 /*  Message manager will be created when a file is loaded, since
+	 *  size of message buffer in shared memory is configurable in
+	 *  the base image.  */
+	/* Get WMD context info. */
+	DEV_GetWMDContext(hDevObject, &hWmdContext);
+	DBC_Assert(hWmdContext);
+	/* Allocate IO manager object: */
+	MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
+	if (pDehMgr == NULL) {
+		status = DSP_EMEMORY;
+	} else {
+		/* Create an NTFY object to manage notifications */
+		if (DSP_SUCCEEDED(status))
+			status = NTFY_Create(&pDehMgr->hNtfy);
+
+		/* Create a DPC object. */
+		status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
+				   (void *)pDehMgr);
+		if (DSP_SUCCEEDED(status))
+			status = DEV_GetDevNode(hDevObject, &hDevNode);
+
+		if (DSP_SUCCEEDED(status))
+			status = CFG_GetHostResources(hDevNode, &cfgHostRes);
+
+		if (DSP_SUCCEEDED(status)) {
+			/* Fill in context structure */
+			pDehMgr->hWmdContext = hWmdContext;
+			pDehMgr->errInfo.dwErrMask = 0L;
+			pDehMgr->errInfo.dwVal1 = 0L;
+			pDehMgr->errInfo.dwVal2 = 0L;
+			pDehMgr->errInfo.dwVal3 = 0L;
+			/* Install ISR function for DSP MMU fault */
+			status = ISR_Install(&pDehMgr->hMmuFaultIsr,
+				 &cfgHostRes, (ISR_PROC)MMU_FaultIsr,
+				 DSP_MMUFAULT, (void *)pDehMgr);
+		}
+	}
+	if (DSP_FAILED(status)) {
+		/* If create failed, cleanup */
+		WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
+		*phDehMgr = NULL;
+	} else {
+		*phDehMgr = (struct DEH_MGR *)pDehMgr;
+	}
+	DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
+	return status;
+}
+
+/*
+ *  ======== WMD_DEH_Destroy ========
+ *      Destroys DEH manager object.
+ */
+DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+	DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
+	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+		/* If notification object exists, delete it */
+		if (pDehMgr->hNtfy)
+			(void)NTFY_Delete(pDehMgr->hNtfy);
+
+		/* Disable DSP MMU fault */
+		(void)ISR_Uninstall(pDehMgr->hMmuFaultIsr);
+		(void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
+		/* Deallocate the DEH manager object */
+		MEM_FreeObject(pDehMgr);
+	}
+	DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
+	return status;
+}
+
+/*
+ *  ======== WMD_DEH_RegisterNotify ========
+ *      Registers for DEH notifications.
+ */
+DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
+				 u32 uNotifyType,
+				 struct DSP_NOTIFICATION *hNotification)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+	DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
+		 pDehMgr);
+
+	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+		status = NTFY_Register(pDehMgr->hNtfy, hNotification,
+			 uEventMask, uNotifyType);
+	}
+	DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
+	return status;
+}
+
+
+/*
+ *  ======== PackTraceBuffer ========
+ *      Removes extra nulls from the trace buffer returned from the DSP.
+ *      Works even on buffers that already are packed (null removed); but has
+ *      one bug in that case -- loses the last character (replaces with '\0').
+ *      Continues through conversion for full set of nBytes input characters.
+ *  Parameters:
+ *    lpBuf:            Pointer to input/output buffer
+ *    nBytes:           Number of characters in the buffer
+ *    ulNumWords:       Number of DSP words in the buffer.  Indicates potential
+ *                      number of extra carriage returns to generate.
+ *  Returns:
+ *      DSP_SOK:        Success.
+ *      DSP_EMEMORY:    Unable to allocate memory.
+ *  Requires:
+ *      lpBuf must be a fully allocated writable block of at least nBytes.
+ *      There are no more than ulNumWords extra characters needed (the number of
+ *      linefeeds minus the number of NULLS in the input buffer).
+ */
+#if ((defined DEBUG) || (defined DDSP_DEBUG_PRODUCT))\
+	&& GT_TRACE
+static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	char *lpTmpBuf;
+	char *lpBufStart;
+	char *lpTmpStart;
+	u32 nCnt;
+	char thisChar;
+
+	/* tmp workspace, 1 KB longer than input buf */
+	lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
+	if (lpTmpBuf == NULL) {
+		DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
+		status = DSP_EMEMORY;
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		lpBufStart = lpBuf;
+		lpTmpStart = lpTmpBuf;
+		for (nCnt = nBytes; nCnt > 0; nCnt--) {
+			thisChar = *lpBuf++;
+			switch (thisChar) {
+			case '\0':	/* Skip null bytes */
+				break;
+			case '\n':	/* Convert \n to \r\n */
+				/* NOTE: do not reverse order; Some OS */
+				/* editors control doesn't understand "\n\r" */
+				*lpTmpBuf++ = '\r';
+				*lpTmpBuf++ = '\n';
+				break;
+			default:	/* Copy in the actual ascii byte */
+				*lpTmpBuf++ = thisChar;
+				break;
+			}
+		}
+		*lpTmpBuf = '\0';    /* Make sure tmp buf is null terminated */
+		/* Cut output down to input buf size */
+		CSL_Strcpyn(lpBufStart, lpTmpStart, nBytes);
+		/*Make sure output is null terminated */
+		lpBufStart[nBytes - 1] = '\0';
+		MEM_Free(lpTmpStart);
+	}
+
+	return status;
+}
+#endif	   /* ((defined DEBUG) || (defined DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+
+/*
+ *  ======== PrintDspTraceBuffer ========
+ *      Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
+ *  Parameters:
+ *    hDehMgr:          Handle to DEH manager object
+ *                      number of extra carriage returns to generate.
+ *  Returns:
+ *      DSP_SOK:        Success.
+ *      DSP_EMEMORY:    Unable to allocate memory.
+ *  Requires:
+ *      hDehMgr muse be valid. Checked in WMD_DEH_Notify.
+ */
+DSP_STATUS PrintDspTraceBuffer(struct DEH_MGR *hDehMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+
+#if ((defined DEBUG) || (defined DDSP_DEBUG_PRODUCT))\
+	&& GT_TRACE
+
+	struct COD_MANAGER *hCodMgr;
+	u32 ulTraceEnd;
+	u32 ulTraceBegin;
+	u32 ulNumBytes = 0;
+	u32 ulNumWords = 0;
+	u32 ulWordSize = 2;
+	CONST u32 uMaxSize = 512;
+	char *pszBuf;
+	u16 *lpszBuf;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+	struct DEV_OBJECT *hDevObject = ((struct WMD_DEV_CONTEXT *)
+					pDehMgr->hWmdContext)->hDevObject;
+
+	status = DEV_GetCodMgr(hDevObject, &hCodMgr);
+	if (DSP_FAILED(status)) {
+		DBG_Trace(DBG_LEVEL7,
+			 "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Look for SYS_PUTCBEG/SYS_PUTCEND: */
+		status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
+		DBG_Trace(DBG_LEVEL1,
+			 "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
+			 ulTraceBegin);
+		if (DSP_FAILED(status)) {
+			DBG_Trace(DBG_LEVEL7, "PrintDspTraceBuffer: Failed on "
+				 "COD_GetSymValue.\n");
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
+		DBG_Trace(DBG_LEVEL1,
+			 "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
+			 ulTraceEnd);
+		if (DSP_FAILED(status)) {
+			DBG_Trace(DBG_LEVEL7, "PrintDspTraceBuffer: Failed on "
+				 "COD_GetSymValue.\n");
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
+		 /*  If the chip type is 55 then the addresses will be
+		 *  byte addresses; convert them to word addresses.  */
+		if (ulNumBytes > uMaxSize)
+			ulNumBytes = uMaxSize;
+
+		/* make sure the data we request fits evenly */
+		ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
+		DBG_Trace(DBG_LEVEL1, "PrintDspTraceBuffer: ulNumBytes 0x%x\n",
+			 ulNumBytes);
+		ulNumWords = ulNumBytes * ulWordSize;
+		DBG_Trace(DBG_LEVEL1, "PrintDspTraceBuffer: ulNumWords 0x%x\n",
+			 ulNumWords);
+		status = DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+	}
+
+
+	if (DSP_SUCCEEDED(status)) {
+		pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
+		lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
+		if (pszBuf != NULL) {
+			/* Read bytes from the DSP trace buffer... */
+			status = (*pIntfFxns->pfnBrdRead)(pDehMgr->hWmdContext,
+				 (u8 *)pszBuf, (u32)ulTraceBegin,
+				 ulNumBytes, 0);
+			if (DSP_FAILED(status)) {
+				DBG_Trace(DBG_LEVEL7, "PrintDspTraceBuffer: "
+					 "Failed to Read Trace Buffer.\n");
+			}
+			if (DSP_SUCCEEDED(status)) {
+				/* Pack and do newline conversion */
+				DBG_Trace(DBG_LEVEL1, "PrintDspTraceBuffer: "
+					 "before pack and unpack.\n");
+				PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
+				DBG_Trace(DBG_LEVEL7, "DSP Trace Buffer:\n%s\n",
+					 pszBuf);
+			}
+			MEM_Free(pszBuf);
+			MEM_Free(lpszBuf);
+		} else {
+			DBG_Trace(DBG_LEVEL7, "PrintDspTraceBuffer: Failed to "
+				 "allocate trace buffer.\n");
+			status = DSP_EMEMORY;
+		}
+	}
+#endif
+	return status;
+}
+
+
+/*
+ *  ======== WMD_DEH_Notify ========
+ *      DEH error notification function. Informs user about the error.
+ */
+void CDECL WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
+			 u32 dwErrInfo)
+{
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+	struct WMD_DEV_CONTEXT *pDevContext;
+	DSP_STATUS status = DSP_SOK;
+	u32 memPhysical = 0;
+	u32 HW_MMU_MAX_TLB_COUNT = 31;
+	u32 extern faultAddr;
+	struct CFG_HOSTRES resources;
+	u32 dummyVaAddr;
+	HW_STATUS hwStatus;
+
+	status = CFG_GetHostResources(
+			(struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
+			&resources);
+	if (DSP_FAILED(status))
+		DBG_Trace(DBG_LEVEL7,
+			 "**Failed to get Host Resources in MMU ISR **\n");
+
+	DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
+		 ulEventMask);
+	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+		printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
+			"**********\n");
+		switch (ulEventMask) {
+		case DSP_SYSERROR:
+			/* reset errInfo structure before use */
+			pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
+			pDehMgr->errInfo.dwVal1 = 0L;
+			pDehMgr->errInfo.dwVal2 = 0L;
+			pDehMgr->errInfo.dwVal3 = 0L;
+			pDehMgr->errInfo.dwVal1 = dwErrInfo;
+			printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
+				"= 0x%x\n", dwErrInfo);
+			break;
+		case DSP_MMUFAULT:
+			/* MMU fault routine should have set err info
+			 * structure */
+			pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
+			pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
+			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
+				"errInfo = 0x%x\n", dwErrInfo);
+			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
+				"Address = 0x%x\n",
+				(unsigned int)pDehMgr->errInfo.dwVal1);
+			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
+				"Address = 0x%x\n",
+				(unsigned int)pDehMgr->errInfo.dwVal2);
+			printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
+				"address = 0x%x\n", (unsigned int)faultAddr);
+			dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
+					MEM_PAGED);
+			memPhysical = (u32)MEM_Calloc(sizeof(char) * 0x1000,
+					MEM_PAGED);
+			dummyVaAddr = PG_ALIGN_LOW((u32)dummyVaAddr,
+					PG_SIZE_4K);
+			memPhysical  = VirtToPhys(dummyVaAddr);
+			DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
+				 "mem Physical= 0x%x\n", memPhysical);
+			pDevContext = (struct WMD_DEV_CONTEXT *)
+						pDehMgr->hWmdContext;
+			/* Reset the dynamic mmu index to fixed count if it
+			 * exceeds 31. So that the dynmmuindex is always
+			 * between the range of standard/fixed entries
+			 * and 31.  */
+			if (pDevContext->numTLBEntries >
+			   HW_MMU_MAX_TLB_COUNT) {
+				pDevContext->numTLBEntries = pDevContext->
+					fixedTLBEntries;
+			}
+			DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
+				 "PA: 0x%x\n", pDevContext->
+				numTLBEntries, faultAddr, memPhysical);
+			if (DSP_SUCCEEDED(status)) {
+				hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
+					memPhysical, faultAddr,
+					HW_PAGE_SIZE_4KB, 1, &mapAttrs,
+					HW_SET, HW_SET);
+			}
+			/* send an interrupt to DSP */
+			HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
+					 MBX_DEH_CLASS | MBX_DEH_EMMU);
+			/* Clear MMU interrupt */
+			HW_MMU_EventAck(resources.dwDmmuBase,
+					 HW_MMU_TRANSLATION_FAULT);
+			DBG_Trace(DBG_LEVEL6,
+				 "***** PrintDspTraceBuffer: before\n");
+			PrintDspTraceBuffer(hDehMgr);
+			DBG_Trace(DBG_LEVEL6,
+				 "***** PrintDspTraceBuffer: after \n");
+			break;
+		default:
+			DBG_Trace(DBG_LEVEL6,
+				 "WMD_DEH_Notify: Unknown Error, errInfo = "
+				 "0x%x\n", dwErrInfo);
+			break;
+		}
+		/* Signal DSP error/exception event. */
+		NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
+	}
+	DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
+
+}
+
+/*
+ *  ======== WMD_DEH_GetInfo ========
+ *      Retrieves error information.
+ */
+DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
+			  struct DSP_ERRORINFO *pErrInfo)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
+
+	DBC_Require(pDehMgr);
+	DBC_Require(pErrInfo);
+
+	DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
+
+	if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
+		/* Copy DEH error info structure to PROC error info
+		 * structure. */
+		pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
+		pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
+		pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
+		pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
+	}
+
+	DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
+
+	return status;
+}
+
-- 
1.5.5.1.357.g1af8b

