Maemo patchset 20101501+0m5
[h-e-n] / drivers / dsp / bridge / wmd / tiomap_io.c
diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
new file mode 100644 (file)
index 0000000..6121e8f
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * 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 <dspbridge/dbdefs.h>
+#include <dspbridge/errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dspbridge/dbc.h>
+#include <dspbridge/dbg.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dspbridge/dev.h>
+#include <dspbridge/drv.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <dspbridge/mem.h>
+#include <dspbridge/util.h>
+#include <dspbridge/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;
+static u32 ulTraceSecBeg;
+static u32 ulTraceSecEnd;
+static 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;
+       u32     ulTLBBaseVirt = 0;
+       u32     ulShmOffsetVirt = 0;
+       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;
+}
+