OMAP5 VirtQueue: Added ti.family.omap54xx VirtQueue/Interrupt* OPBU modules.
authorG Anthony <a0783926@ti.com>
Thu, 28 Feb 2013 02:30:03 +0000 (18:30 -0800)
committerG Anthony <a0783926@ti.com>
Thu, 28 Feb 2013 02:30:03 +0000 (18:30 -0800)
Signed-off-by: G Anthony <a0783926@ti.com>
packages/ti/ipc/family/omap54xx/InterruptDsp.c [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/InterruptDsp.h [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/InterruptIpu.c [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/InterruptIpu.h [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/InterruptProxy.h [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/OffloadM3.c [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/VirtQueue.c [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/VirtQueue.h [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/package.bld [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/package.xdc [new file with mode: 0644]
packages/ti/ipc/family/omap54xx/package.xs [new file with mode: 0644]

diff --git a/packages/ti/ipc/family/omap54xx/InterruptDsp.c b/packages/ti/ipc/family/omap54xx/InterruptDsp.c
new file mode 100644 (file)
index 0000000..459fcb8
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== Interrupt.c ========
+ *  OMAP4430/Ducati Interrupt Manger
+ */
+
+#include <xdc/std.h>
+#include <xdc/runtime/Assert.h>
+
+#include <ti/sysbios/hal/Hwi.h>
+#include <ti/sysbios/family/c64p/tesla/Wugen.h>
+
+#include <ti/ipc/MultiProc.h>
+
+#include "InterruptDsp.h"
+
+/* Register access method. */
+#define REG16(A)   (*(volatile UInt16 *) (A))
+#define REG32(A)   (*(volatile UInt32 *) (A))
+
+#define HOSTINT                 26
+#define DSPINT                  55
+#define M3INT_MBX               50
+#define M3INT                   19
+
+#define DSPEVENTID              5
+
+/* Assigned mailboxes */
+#define HOST_TO_SYSM3_MBX       0 /* Rx on SysM3 from Host */
+#define M3_TO_HOST_MBX          1 /* Tx to Host from M3 */
+#define DSP_TO_HOST_MBX         2 /* Tx to Host from DSP */
+#define HOST_TO_DSP_MBX         3 /* Rx on DSP from Host */
+#define SYSM3_TO_APPM3_MBX      4 /* Rx on AppM3 from Host/SysM3 */
+
+#define MAILBOX_BASEADDR    (0x4A0F4000)
+
+#define MAILBOX_MESSAGE(M)  (MAILBOX_BASEADDR + 0x040 + (0x4 * M))
+#define MAILBOX_STATUS(M)   (MAILBOX_BASEADDR + 0x0C0 + (0x4 * M))
+#define MAILBOX_REG_VAL(M)  (0x1 << (2 * M))
+
+#define MAILBOX_IRQSTATUS_CLR_DSP   (MAILBOX_BASEADDR + 0x114)
+#define MAILBOX_IRQENABLE_SET_DSP   (MAILBOX_BASEADDR + 0x118)
+#define MAILBOX_IRQENABLE_CLR_DSP   (MAILBOX_BASEADDR + 0x11C)
+
+Hwi_FuncPtr userFxn = NULL;
+
+Void InterruptDsp_isr(UArg arg);
+
+/*
+ *************************************************************************
+ *                      Module functions
+ *************************************************************************
+ */
+
+/*!
+ *  ======== InterruptDsp_intEnable ========
+ *  Enable remote processor interrupt
+ */
+Void InterruptDsp_intEnable()
+{
+    REG32(MAILBOX_IRQENABLE_SET_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
+}
+
+/*!
+ *  ======== InterruptDsp_intDisable ========
+ *  Disables remote processor interrupt
+ */
+Void InterruptDsp_intDisable()
+{
+    REG32(MAILBOX_IRQENABLE_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
+}
+
+/*!
+ *  ======== InterruptDsp_intRegister ========
+ */
+Void InterruptDsp_intRegister(Hwi_FuncPtr fxn)
+{
+    Hwi_Params  hwiAttrs;
+    UInt        key;
+
+    userFxn = fxn;
+
+    /* Disable global interrupts */
+    key = Hwi_disable();
+
+    /*
+     * DSP interrupts are edge-triggered, so clear the interrupt status to
+     * regenerate an interrupt if there are some messages sent prior to
+     * booting the DSP.
+     */
+    REG32(MAILBOX_IRQSTATUS_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
+
+    Hwi_Params_init(&hwiAttrs);
+
+    hwiAttrs.eventId = DSPINT;
+    Hwi_create(DSPEVENTID,
+               (Hwi_FuncPtr)InterruptDsp_isr,
+               &hwiAttrs,
+               NULL);
+
+    /* Enable the interrupt */
+    Wugen_enableEvent(DSPINT);
+    Hwi_enableInterrupt(DSPEVENTID);
+
+    /* Enable the mailbox interrupt to the M3 core */
+    InterruptDsp_intEnable();
+
+    /* Restore global interrupts */
+    Hwi_restore(key);
+}
+
+/*!
+ *  ======== InterruptDsp_intSend ========
+ *  Send interrupt to the remote processor
+ */
+Void InterruptDsp_intSend(UInt16 remoteProcId, UArg arg)
+{
+    static Bool configured = FALSE;
+    static UInt16 sysm3ProcId = MultiProc_INVALIDID;
+    static UInt16 appm3ProcId = MultiProc_INVALIDID;
+    static UInt16 hostProcId = MultiProc_INVALIDID;
+    static UInt16 dspProcId = MultiProc_INVALIDID;
+
+    if (!configured) {
+        hostProcId  = MultiProc_getId("HOST");
+        dspProcId   = MultiProc_getId("DSP");
+        sysm3ProcId = MultiProc_getId("CORE0");
+        appm3ProcId = MultiProc_getId("CORE1");
+        configured  = TRUE;
+    }
+
+    if (remoteProcId == sysm3ProcId) {
+        REG32(MAILBOX_MESSAGE(HOST_TO_SYSM3_MBX)) = arg;
+    }
+    else if (remoteProcId == appm3ProcId) {
+        REG32(MAILBOX_MESSAGE(SYSM3_TO_APPM3_MBX)) = arg;
+    }
+    else if (remoteProcId == hostProcId) {
+        REG32(MAILBOX_MESSAGE(DSP_TO_HOST_MBX)) = arg;
+    }
+    else if (remoteProcId == dspProcId) {
+        REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX)) = arg;
+    }
+    else {
+        /* Should never get here */
+        Assert_isTrue(FALSE, NULL);
+    }
+}
+
+/*!
+ *  ======== InterruptDsp_intClear ========
+ *  Clear interrupt and return payload
+ */
+UInt InterruptDsp_intClear()
+{
+    UInt arg = INVALIDPAYLOAD;
+
+    if (REG32(MAILBOX_STATUS(HOST_TO_DSP_MBX)) != 0) {
+        /* If there is a message, return the argument to the caller */
+        arg = REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX));
+        REG32(MAILBOX_IRQSTATUS_CLR_DSP) = MAILBOX_REG_VAL(HOST_TO_DSP_MBX);
+    }
+
+    return (arg);
+}
+
+/*!
+ *  ======== InterruptDsp_isr ========
+ */
+Void InterruptDsp_isr(UArg arg)
+{
+    UArg payload;
+
+    payload = InterruptDsp_intClear();
+    if (payload != (UInt)INVALIDPAYLOAD) {
+        userFxn(payload);
+    }
+}
diff --git a/packages/ti/ipc/family/omap54xx/InterruptDsp.h b/packages/ti/ipc/family/omap54xx/InterruptDsp.h
new file mode 100644 (file)
index 0000000..ba24d93
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== InterruptDsp.h ========
+ *  OMAP4430/DSP Interrupt Manger
+ */
+
+#include <ti/sysbios/hal/Hwi.h>
+
+#define INVALIDPAYLOAD       (0xFFFFFFFF)
+
+
+/*!
+ *  ======== InterruptDsp_intEnable ========
+ *  Enable remote processor interrupt
+ */
+Void InterruptDsp_intEnable();
+
+/*!
+ *  ======== InterruptDsp_intDisable ========
+ */
+Void InterruptDsp_intDisable();
+
+/*!
+ *  ======== InterruptDsp_intRegister ========
+ */
+Void InterruptDsp_intRegister(Hwi_FuncPtr fxn);
+
+
+/*!
+ *  ======== InterruptDsp_intSend ========
+ *  Send interrupt to the remote processor
+ */
+Void InterruptDsp_intSend(UInt16 remoteProcId,  UArg arg);
+
+
+/*!
+ *  ======== InterruptDsp_intClear ========
+ *  Clear interrupt
+ */
+UInt InterruptDsp_intClear();
diff --git a/packages/ti/ipc/family/omap54xx/InterruptIpu.c b/packages/ti/ipc/family/omap54xx/InterruptIpu.c
new file mode 100644 (file)
index 0000000..443651f
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== InterruptIpu.c ========
+ *  IPU Interrupt Manger
+ */
+
+#include <xdc/std.h>
+#include <xdc/runtime/Assert.h>
+#include <xdc/runtime/Log.h>
+#include <xdc/runtime/Diags.h>
+
+#include <ti/sysbios/hal/Hwi.h>
+#ifndef SMP
+#include <ti/sysbios/family/arm/ducati/Core.h>
+#endif
+
+#include <ti/ipc/MultiProc.h>
+
+#include "InterruptIpu.h"
+
+/* Register access method. */
+#define REG16(A)   (*(volatile UInt16 *) (A))
+#define REG32(A)   (*(volatile UInt32 *) (A))
+
+#define HOSTINT                 26
+#define DSPINT                  55
+#define M3INT_MBX               50
+#define M3INT                   19
+
+/* Assigned mailboxes */
+#define HOST_TO_SYSM3_MBX       0 /* Rx on SysM3 from Host */
+#define M3_TO_HOST_MBX          1 /* Tx to Host from M3 */
+#define DSP_TO_HOST_MBX         2 /* Tx to Host from DSP */
+#define HOST_TO_DSP_MBX         3 /* Rx on DSP from Host */
+#define SYSM3_TO_APPM3_MBX      4 /* Rx on AppM3 from Host/SysM3 */
+
+#define MAILBOX_BASEADDR        (0xAA0F4000)
+
+#define MAILBOX_MESSAGE(M)      (MAILBOX_BASEADDR + 0x040 + (0x4 * M))
+#define MAILBOX_FIFOSTATUS(M)   (MAILBOX_BASEADDR + 0x080 + (0x4 * M))
+#define MAILBOX_STATUS(M)       (MAILBOX_BASEADDR + 0x0C0 + (0x4 * M))
+#define MAILBOX_REG_VAL(M)      (0x1 << (2 * M))
+
+#define MAILBOX_IRQSTATUS_CLR_M3    (MAILBOX_BASEADDR + 0x124)
+#define MAILBOX_IRQENABLE_SET_M3    (MAILBOX_BASEADDR + 0x128)
+#define MAILBOX_IRQENABLE_CLR_M3    (MAILBOX_BASEADDR + 0x12C)
+
+/*
+ *  Ducati control register that maintains inter-core interrupt bits.
+ *
+ *  Using separate core0 and core1 values to do 16-bit reads/writes
+ *  because we do not want to overwrite the other cores value.
+ */
+#define INTERRUPT_CORE_0       (0x40001000)
+#define INTERRUPT_CORE_1       (0x40001000 + 2)
+
+Hwi_FuncPtr userFxn = NULL;
+
+Void InterruptIpu_isr(UArg arg);
+
+
+/*
+ *************************************************************************
+ *                      Module functions
+ *************************************************************************
+ */
+
+/*!
+ *  ======== InterruptIpu_intEnable ========
+ *  Enable remote processor interrupt
+ */
+Void InterruptIpu_intEnable()
+{
+    /*
+     *  If the remote processor communicates via mailboxes, we should enable
+     *  the Mailbox IRQ instead of enabling the Hwi because multiple mailboxes
+     *  share the same Hwi
+     */
+#ifndef SMP
+    if (Core_getId() == 0) {
+#endif
+        REG32(MAILBOX_IRQENABLE_SET_M3) = MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
+#ifndef SMP
+    }
+    else {
+        Hwi_enableInterrupt(M3INT);
+    }
+#endif
+}
+
+/*!
+ *  ======== InterruptIpu_intDisable ========
+ *  Disables remote processor interrupt
+ */
+Void InterruptIpu_intDisable()
+{
+    /*
+     *  If the remote processor communicates via mailboxes, we should disable
+     *  the Mailbox IRQ instead of disabling the Hwi because multiple mailboxes
+     *  share the same Hwi
+     */
+#ifndef SMP
+    if (Core_getId() == 0) {
+#endif
+        REG32(MAILBOX_IRQENABLE_CLR_M3) = MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
+#ifndef SMP
+    }
+    else {
+        Hwi_disableInterrupt(M3INT);
+    }
+#endif
+}
+
+/*!
+ *  ======== InterruptIpu_intRegister ========
+ */
+Void InterruptIpu_intRegister(Hwi_FuncPtr fxn)
+{
+    Hwi_Params  hwiAttrs;
+    UInt        key;
+
+    /* Disable global interrupts */
+    key = Hwi_disable();
+
+    userFxn = fxn;
+    Hwi_Params_init(&hwiAttrs);
+    hwiAttrs.maskSetting = Hwi_MaskingOption_LOWER;
+
+#ifndef SMP
+    if (Core_getId() == 0) {
+#endif
+        Hwi_create(M3INT_MBX,
+                   (Hwi_FuncPtr)InterruptIpu_isr,
+                   &hwiAttrs,
+                   NULL);
+        /* InterruptIpu_intEnable won't enable the Hwi */
+        Hwi_enableInterrupt(M3INT_MBX);
+#ifndef SMP
+    }
+    else {
+        Hwi_create(M3INT,
+                   (Hwi_FuncPtr)InterruptIpu_isr,
+                   &hwiAttrs,
+                   NULL);
+    }
+#endif
+
+    /* Enable the mailbox interrupt to the M3 core */
+    InterruptIpu_intEnable();
+
+    /* Restore global interrupts */
+    Hwi_restore(key);
+}
+
+/*!
+ *  ======== InterruptIpu_intSend ========
+ *  Send interrupt to the remote processor
+ */
+Void InterruptIpu_intSend(UInt16 remoteProcId, UArg arg)
+{
+    static Bool configured = FALSE;
+#ifndef SMP
+    static UInt16 sysm3ProcId = MultiProc_INVALIDID;
+    static UInt16 appm3ProcId = MultiProc_INVALIDID;
+#endif
+    static UInt16 hostProcId = MultiProc_INVALIDID;
+    static UInt16 dspProcId = MultiProc_INVALIDID;
+
+    Log_print2(Diags_USER1,
+        "InterruptIpu_intSend: Sending interrupt with payload 0x%x to proc #%d",
+        (IArg)arg, (IArg)remoteProcId);
+
+    if (!configured) {
+        hostProcId  = MultiProc_getId("HOST");
+        dspProcId   = MultiProc_getId("DSP");
+#ifndef SMP
+        sysm3ProcId = MultiProc_getId("CORE0");
+        appm3ProcId = MultiProc_getId("CORE1");
+#endif
+        configured  = TRUE;
+    }
+
+#ifndef SMP
+    if (remoteProcId == sysm3ProcId) {
+        while(REG32(MAILBOX_FIFOSTATUS(HOST_TO_SYSM3_MBX)));
+        REG32(MAILBOX_MESSAGE(HOST_TO_SYSM3_MBX)) = arg;
+    }
+    else if (remoteProcId == appm3ProcId) {
+        while(REG32(MAILBOX_FIFOSTATUS(SYSM3_TO_APPM3_MBX)));
+        /* Write to the mailbox, but this won't trigger an interrupt */
+        REG32(MAILBOX_MESSAGE(SYSM3_TO_APPM3_MBX)) = arg;
+        /* Actually trigger the interrupt */
+        REG16(INTERRUPT_CORE_1) |= 0x1;
+    }
+    else
+#endif
+    if (remoteProcId == dspProcId) {
+        while(REG32(MAILBOX_FIFOSTATUS(HOST_TO_DSP_MBX)));
+        REG32(MAILBOX_MESSAGE(HOST_TO_DSP_MBX)) = arg;
+    }
+    else if (remoteProcId == hostProcId) {
+        while(REG32(MAILBOX_FIFOSTATUS(M3_TO_HOST_MBX)));
+        REG32(MAILBOX_MESSAGE(M3_TO_HOST_MBX)) = arg;
+    }
+    else {
+        /* Should never get here */
+        Assert_isTrue(FALSE, NULL);
+    }
+}
+
+/*!
+ *  ======== InterruptIpu_intClear ========
+ *  Clear interrupt and return payload
+ */
+UInt InterruptIpu_intClear()
+{
+    UInt arg = INVALIDPAYLOAD;
+
+    /* First check whether incoming mailbox has a message */
+#ifndef SMP
+    if (Core_getId() == 0) {
+#endif
+        /* If FIFO is empty, return INVALIDPAYLOAD */
+        if (REG32(MAILBOX_STATUS(HOST_TO_SYSM3_MBX)) == 0) {
+            return (arg);
+        }
+        else {
+            /* If there is a message, return the argument to the caller */
+            arg = REG32(MAILBOX_MESSAGE(HOST_TO_SYSM3_MBX));
+            REG32(MAILBOX_IRQSTATUS_CLR_M3) =
+                                        MAILBOX_REG_VAL(HOST_TO_SYSM3_MBX);
+        }
+#ifndef SMP
+    }
+    else {
+        /* Clear the inter-M3 interrupt if necessary */
+        if ((REG16(INTERRUPT_CORE_1) & 0x1) == 0x1) {
+            REG16(INTERRUPT_CORE_1) &= ~(0x1);
+        }
+
+        /* If FIFO is empty, return INVALIDPAYLOAD */
+        if (REG32(MAILBOX_STATUS(SYSM3_TO_APPM3_MBX)) == 0) {
+            return (arg);
+        }
+        else {
+            /* If there is a message, return the argument to the caller */
+            arg = REG32(MAILBOX_MESSAGE(SYSM3_TO_APPM3_MBX));
+            REG32(MAILBOX_IRQSTATUS_CLR_M3) =
+                                        MAILBOX_REG_VAL(SYSM3_TO_APPM3_MBX);
+
+            if (REG32(MAILBOX_STATUS(SYSM3_TO_APPM3_MBX)) != 0) {
+                /* Trigger our own interrupt since another interrupt pending */
+                REG16(INTERRUPT_CORE_1) |= 0x1;
+            }
+        }
+    }
+#endif
+
+    return (arg);
+}
+
+/*!
+ *  ======== InterruptIpu_isr ========
+ *  Calls the function supplied by the user in intRegister
+ */
+Void InterruptIpu_isr(UArg arg)
+{
+    UArg payload;
+
+    payload = InterruptIpu_intClear();
+    if (payload != INVALIDPAYLOAD) {
+        Log_print1(Diags_USER1,
+            "InterruptIpu_isr: Interrupt received, payload = 0x%x\n",
+            (IArg)payload);
+        userFxn(payload);
+    }
+}
diff --git a/packages/ti/ipc/family/omap54xx/InterruptIpu.h b/packages/ti/ipc/family/omap54xx/InterruptIpu.h
new file mode 100644 (file)
index 0000000..cfd56de
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== InterruptIpu.h ========
+ *  OMAP4430/Ducati Interrupt Manger
+ */
+
+#include <ti/sysbios/hal/Hwi.h>
+
+#define INVALIDPAYLOAD       (0xFFFFFFFF)
+
+
+/*!
+ *  ======== InterruptIpu_intEnable ========
+ *  Enable remote processor interrupt
+ */
+Void InterruptIpu_intEnable();
+
+/*!
+ *  ======== InterruptIpu_intDisable ========
+ */
+Void InterruptIpu_intDisable();
+
+/*!
+ *  ======== InterruptIpu_intRegister ========
+ */
+Void InterruptIpu_intRegister(Hwi_FuncPtr fxn);
+
+/*!
+ *  ======== InterruptIpu_intSend ========
+ *  Send interrupt to the remote processor
+ */
+Void InterruptIpu_intSend(UInt16 remoteProcId,  UArg arg);
+
+/*!
+ *  ======== InterruptIpu_intClear ========
+ *  Clear interrupt
+ */
+UInt InterruptIpu_intClear();
diff --git a/packages/ti/ipc/family/omap54xx/InterruptProxy.h b/packages/ti/ipc/family/omap54xx/InterruptProxy.h
new file mode 100644 (file)
index 0000000..250379f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== InterruptProxy.h ========
+ *  Proxy Interrupt Manager
+ */
+
+#ifndef ti_ipc_rpmsg_InterruptProxy__include
+#define ti_ipc_rpmsg_InterruptProxy__include
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <ti/sysbios/hal/Hwi.h>
+
+#define INVALIDPAYLOAD       (0xFFFFFFFF)
+
+#if defined(M3_ONLY) || defined(SMP)
+#include <ti/ipc/family/omap54xx/InterruptIpu.h>
+
+/*
+ *************************************************************************
+ *                      M3 Interrupt Proxy Macros
+ *************************************************************************
+ */
+
+#define InterruptProxy_intEnable        InterruptIpu_intEnable
+
+#define InterruptProxy_intDisable       InterruptIpu_intDisable
+
+#define InterruptProxy_intRegister      InterruptIpu_intRegister
+
+#define InterruptProxy_intSend          InterruptIpu_intSend
+
+#define InterruptProxy_intClear         InterruptIpu_intClear
+#endif
+
+#if defined(DSP)
+#include <ti/ipc/family/omap54xx/InterruptDsp.h>
+
+/*
+ *************************************************************************
+ *                      DSP Interrupt Proxy Macros
+ *************************************************************************
+ */
+#define InterruptProxy_intEnable        InterruptDsp_intEnable
+
+#define InterruptProxy_intDisable       InterruptDsp_intDisable
+
+#define InterruptProxy_intRegister      InterruptDsp_intRegister
+
+#define InterruptProxy_intSend          InterruptDsp_intSend
+
+#define InterruptProxy_intClear         InterruptDsp_intClear
+#endif
+
+#if defined(__cplusplus)
+}
+#endif /* defined (__cplusplus) */
+
+#endif /* ti_ipc_rpmsg_InterruptProxy__include */
diff --git a/packages/ti/ipc/family/omap54xx/OffloadM3.c b/packages/ti/ipc/family/omap54xx/OffloadM3.c
new file mode 100644 (file)
index 0000000..32ffc35
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== OffloadM3.c ========
+ *  Offload some algorithms from AppM3 to SysM3 due to lack of MIPS on AppM3
+ *
+ */
+
+#include <xdc/std.h>
+#include <xdc/cfg/global.h>
+#include <xdc/runtime/System.h>
+#include <xdc/runtime/Diags.h>
+#include <xdc/runtime/Log.h>
+#include <xdc/runtime/knl/Thread.h>
+
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Task.h>
+#include <ti/sysbios/knl/Semaphore.h>
+
+#include <ti/ipc/MultiProc.h>
+
+#define RP_MSG_OFFLOAD_BASE 0xF0F0F0F0
+
+enum {
+    OFFLOAD_CREATE_IDX  = 0,
+    OFFLOAD_DELETE_IDX  = 1,
+    OFFLOAD_AC_IDX      = 2,
+    OFFLOAD_VS_IDX      = 3,
+    OFFLOAD_MM_IDX      = 4,
+    OFFLOAD_MAX_IDX     = 5
+};
+
+typedef struct {
+    Void    (*fxn)(Void *);
+    Void    *data;
+    Int     status;
+} MSP_PAYLOAD_TYPE;
+
+typedef struct {
+    Bool             created;
+    Semaphore_Handle mutex;
+    Task_Handle      tasks[OFFLOAD_MAX_IDX];
+    Semaphore_Handle semaphores[OFFLOAD_MAX_IDX];
+} OffloadM3_module;
+
+#pragma DATA_SECTION(interm3PayloadAC, ".interm3offload")
+MSP_PAYLOAD_TYPE interm3PayloadAC;
+#pragma DATA_SECTION(interm3PayloadVS, ".interm3offload")
+MSP_PAYLOAD_TYPE interm3PayloadVS;
+#pragma DATA_SECTION(interm3PayloadMM, ".interm3offload")
+MSP_PAYLOAD_TYPE interm3PayloadMM;
+
+static OffloadM3_module module;
+static UInt16 sysm3ProcId;
+
+/*!
+ * ======== OffloadM3_processSysM3Tasks ========
+ *
+ * Process the different Offload request messages on SysM3. Signal the
+ * appropriate tasks for executing the functions to be offloaded.
+ */
+Int OffloadM3_processSysM3Tasks(UArg msg)
+{
+    UInt index = (UInt)msg - RP_MSG_OFFLOAD_BASE;
+    if (index >= OFFLOAD_MAX_IDX)
+        return 0;
+
+    Semaphore_post(module.semaphores[index]);
+    return 1;
+}
+
+static Void inline Mutex_enter()
+{
+    Semaphore_pend(module.mutex, BIOS_WAIT_FOREVER);
+}
+
+static Void inline Mutex_leave()
+{
+    Semaphore_post(module.mutex);
+}
+
+static Void OffloadM3_workerTask(UArg sem, UArg fxn)
+{
+    Semaphore_Handle semHandle = (Semaphore_Handle)sem;
+    MSP_PAYLOAD_TYPE *payload = (MSP_PAYLOAD_TYPE *)fxn;
+
+    while(1) {
+        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
+        payload->fxn(payload->data);
+        payload->status = 0;
+    }
+}
+
+static Void OffloadM3_createTask(UArg sem, UArg arg1)
+{
+    Semaphore_Handle semHandle = (Semaphore_Handle)sem;
+    Task_Params params;
+    Int i;
+
+    while (1) {
+        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
+
+        Mutex_enter();
+        if (!module.created) {
+            for (i = OFFLOAD_AC_IDX; i < OFFLOAD_MAX_IDX; i++) {
+                module.semaphores[i] = Semaphore_create(0, NULL, NULL);
+            }
+
+            Task_Params_init(&params);
+            params.instance->name = "workerTaskAC";
+            params.priority = xdc_runtime_knl_Thread_Priority_NORMAL;
+            params.arg0 = (UArg)module.semaphores[OFFLOAD_AC_IDX];
+            params.arg1 = (UArg)&interm3PayloadAC;
+            module.tasks[OFFLOAD_AC_IDX] = Task_create(OffloadM3_workerTask, &params, NULL);
+
+            Task_Params_init(&params);
+            params.instance->name = "workerTaskVS";
+            params.priority = xdc_runtime_knl_Thread_Priority_NORMAL;
+            params.arg0 = (UArg)module.semaphores[OFFLOAD_VS_IDX];
+            params.arg1 = (UArg)&interm3PayloadVS;
+            module.tasks[OFFLOAD_VS_IDX] = Task_create(OffloadM3_workerTask, &params, NULL);
+
+            Task_Params_init(&params);
+            /* Create a lower priority thread */
+            params.instance->name = "workerTaskMM";
+            params.priority = xdc_runtime_knl_Thread_Priority_BELOW_NORMAL;
+            params.arg0 = (UArg)module.semaphores[OFFLOAD_MM_IDX];
+            params.arg1 = (UArg)&interm3PayloadMM;
+            module.tasks[OFFLOAD_MM_IDX] = Task_create(OffloadM3_workerTask, &params, NULL);
+
+            module.created = TRUE;
+        }
+        Mutex_leave();
+    }
+}
+
+static Void OffloadM3_deleteTask(UArg sem, UArg arg1)
+{
+    Semaphore_Handle semHandle = (Semaphore_Handle)sem;
+    Int i;
+
+    while (1) {
+        Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
+
+        Mutex_enter();
+        if (module.created) {
+            /*
+             * Since this task is higher priority than any of the subtasks,
+             * they won't be in running state, so we can call Task_delete on
+             * them
+             */
+            for (i = OFFLOAD_AC_IDX; i < OFFLOAD_MAX_IDX; i++) {
+                Task_delete(&module.tasks[i]);
+                Semaphore_delete(&module.semaphores[i]);
+                module.tasks[i] = NULL;
+                module.semaphores[i] = NULL;
+            }
+            module.created = FALSE;
+        }
+        Mutex_leave();
+    }
+}
+
+/*!
+ * ======== OffloadM3_init ========
+ *
+ * Initialize the OffloadM3 module, currently supported only on SysM3
+ */
+Void OffloadM3_init()
+{
+    Task_Params taskParams;
+    Semaphore_Params mutexParams;
+
+    sysm3ProcId = MultiProc_getId("CORE0");
+    if (MultiProc_self() != sysm3ProcId)
+        return;
+
+    Semaphore_Params_init(&mutexParams);
+    mutexParams.mode = Semaphore_Mode_BINARY;
+    module.mutex = Semaphore_create(1, NULL, NULL);
+
+    module.created = FALSE;
+    module.semaphores[OFFLOAD_CREATE_IDX] = Semaphore_create(0, NULL, NULL);
+    module.semaphores[OFFLOAD_DELETE_IDX] = Semaphore_create(0, NULL, NULL);
+
+    Task_Params_init(&taskParams);
+    taskParams.instance->name = "OffloadM3_createTask";
+    taskParams.priority = xdc_runtime_knl_Thread_Priority_NORMAL;
+    taskParams.arg0 = (UArg)module.semaphores[OFFLOAD_CREATE_IDX];
+    module.tasks[OFFLOAD_CREATE_IDX] = Task_create(OffloadM3_createTask, &taskParams, NULL);
+
+    Task_Params_init(&taskParams);
+    taskParams.instance->name = "OffloadM3_deleteTask";
+    taskParams.priority = xdc_runtime_knl_Thread_Priority_HIGHEST;
+    taskParams.arg0 = (UArg)module.semaphores[OFFLOAD_DELETE_IDX];
+    module.tasks[OFFLOAD_DELETE_IDX] = Task_create(OffloadM3_deleteTask, &taskParams, NULL);
+}
+
+/*!
+ * ======== OffloadM3_exit ========
+ *
+ * Finalize the OffloadM3 module, currently supported only on SysM3
+ */
+Void OffloadM3_exit()
+{
+    if (MultiProc_self() != sysm3ProcId)
+        return;
+
+    Task_delete(&module.tasks[OFFLOAD_CREATE_IDX]);
+    Task_delete(&module.tasks[OFFLOAD_DELETE_IDX]);
+
+    Semaphore_delete(&module.semaphores[OFFLOAD_CREATE_IDX]);
+    Semaphore_delete(&module.semaphores[OFFLOAD_DELETE_IDX]);
+    Semaphore_delete(&module.mutex);
+}
diff --git a/packages/ti/ipc/family/omap54xx/VirtQueue.c b/packages/ti/ipc/family/omap54xx/VirtQueue.c
new file mode 100644 (file)
index 0000000..ab01173
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** ============================================================================
+ *  @file       VirtQueue.c
+ *
+ *  @brief      Virtio Queue implementation for BIOS
+ *
+ *  Differences between BIOS version and Linux kernel (include/linux/virtio.h):
+ *  - Renamed module from virtio.h to VirtQueue_Object.h to match the API prefixes;
+ *  - BIOS (XDC) types and CamelCasing used;
+ *  - virtio_device concept removed (i.e, assumes no containing device);
+ *  - simplified scatterlist from Linux version;
+ *  - VirtQueue_Objects are created statically here, so just added a VirtQueue_Object_init()
+ *    fxn to take the place of the Virtio vring_new_virtqueue() API;
+ *  - The notify function is implicit in the implementation, and not provided
+ *    by the client, as it is in Linux virtio.
+ *
+ *  All VirtQueue operations can be called in any context.
+ *
+ *  The virtio header should be included in an application as follows:
+ *  @code
+ *  #include <ti/ipc/family/omap54xx/VirtQueue.h>
+ *  @endcode
+ *
+ */
+
+#include <xdc/std.h>
+#include <xdc/runtime/System.h>
+#include <xdc/runtime/Error.h>
+#include <xdc/runtime/Memory.h>
+#include <xdc/runtime/Log.h>
+#include <xdc/runtime/Diags.h>
+
+#include <ti/sysbios/hal/Hwi.h>
+#include <ti/sysbios/knl/Semaphore.h>
+#include <ti/sysbios/knl/Clock.h>
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/hal/Cache.h>
+
+#include <ti/ipc/MultiProc.h>
+
+#include <ti/ipc/rpmsg/virtio_ring.h>
+#include <ti/pm/IpcPower.h>
+#include <string.h>
+
+#include <ti/ipc/rpmsg/_VirtQueue.h>
+
+#include "InterruptProxy.h"
+#include "VirtQueue.h"
+
+
+/* Used for defining the size of the virtqueue registry */
+#define NUM_QUEUES              4
+
+/* Predefined device addresses */
+#ifndef DSPC674
+#define IPC_MEM_VRING0          0xA0000000
+#define IPC_MEM_VRING1          0xA0004000
+#else
+#define IPC_MEM_VRING0          0x9FB00000
+#define IPC_MEM_VRING1          0x9FB04000
+#endif
+#define IPC_MEM_VRING2          0xA0008000
+#define IPC_MEM_VRING3          0xA000c000
+
+/*
+ * Sizes of the virtqueues (expressed in number of buffers supported,
+ * and must be power of two)
+ */
+#define VQ0_SIZE                256
+#define VQ1_SIZE                256
+#define VQ2_SIZE                256
+#define VQ3_SIZE                256
+
+/*
+ * enum - Predefined Mailbox Messages
+ *
+ * @RP_MSG_MBOX_READY: informs the M3's that we're up and running. will be
+ * followed by another mailbox message that carries the A9's virtual address
+ * of the shared buffer. This would allow the A9's drivers to send virtual
+ * addresses of the buffers.
+ *
+ * @RP_MSG_MBOX_STATE_CHANGE: informs the receiver that there is an inbound
+ * message waiting in its own receive-side vring. please note that currently
+ * this message is optional: alternatively, one can explicitly send the index
+ * of the triggered virtqueue itself. the preferred approach will be decided
+ * as we progress and experiment with those design ideas.
+ *
+ * @RP_MSG_MBOX_CRASH: this message indicates that the BIOS side is unhappy
+ *
+ * @RP_MBOX_ECHO_REQUEST: this message requests the remote processor to reply
+ * with RP_MBOX_ECHO_REPLY
+ *
+ * @RP_MBOX_ECHO_REPLY: this is a reply that is sent when RP_MBOX_ECHO_REQUEST
+ * is received.
+ *
+ * @RP_MBOX_ABORT_REQUEST:  tells the M3 to crash on demand
+ *
+ * @RP_MBOX_BOOTINIT_DONE: this message indicates the BIOS side has reached a
+ * certain state during the boot process. This message is used to inform the
+ * host that the basic BIOS initialization is done, and lets the host use this
+ * notification to perform certain actions.
+ */
+enum {
+    RP_MSG_MBOX_READY           = (Int)0xFFFFFF00,
+    RP_MSG_MBOX_STATE_CHANGE    = (Int)0xFFFFFF01,
+    RP_MSG_MBOX_CRASH           = (Int)0xFFFFFF02,
+    RP_MBOX_ECHO_REQUEST        = (Int)0xFFFFFF03,
+    RP_MBOX_ECHO_REPLY          = (Int)0xFFFFFF04,
+    RP_MBOX_ABORT_REQUEST       = (Int)0xFFFFFF05,
+    RP_MSG_FLUSH_CACHE          = (Int)0xFFFFFF06,
+    RP_MSG_BOOTINIT_DONE        = (Int)0xFFFFFF07,
+    RP_MSG_HIBERNATION          = (Int)0xFFFFFF10,
+    RP_MSG_HIBERNATION_FORCE    = (Int)0xFFFFFF11,
+    RP_MSG_HIBERNATION_ACK      = (Int)0xFFFFFF12,
+    RP_MSG_HIBERNATION_CANCEL   = (Int)0xFFFFFF13
+};
+
+#define DIV_ROUND_UP(n,d)   (((n) + (d) - 1) / (d))
+#define RP_MSG_NUM_BUFS     (VQ0_SIZE) /* must be power of two */
+#define RP_MSG_BUF_SIZE     (512)
+#define RP_MSG_BUFS_SPACE   (RP_MSG_NUM_BUFS * RP_MSG_BUF_SIZE * 2)
+
+#define PAGE_SIZE           (4096)
+/*
+ * The alignment to use between consumer and producer parts of vring.
+ * Note: this is part of the "wire" protocol. If you change this, you need
+ * to update your BIOS image as well
+ */
+#define RP_MSG_VRING_ALIGN  (4096)
+
+/* With 256 buffers, our vring will occupy 3 pages */
+#define RP_MSG_RING_SIZE    ((DIV_ROUND_UP(vring_size(RP_MSG_NUM_BUFS, \
+                            RP_MSG_VRING_ALIGN), PAGE_SIZE)) * PAGE_SIZE)
+
+/* The total IPC space needed to communicate with a remote processor */
+#define RPMSG_IPC_MEM   (RP_MSG_BUFS_SPACE + 2 * RP_MSG_RING_SIZE)
+
+#define ID_SYSM3_TO_A9      ID_SELF_TO_A9
+#define ID_A9_TO_SYSM3      ID_A9_TO_SELF
+#define ID_DSP_TO_A9        ID_SELF_TO_A9
+#define ID_A9_TO_DSP        ID_A9_TO_SELF
+#define ID_APPM3_TO_A9      200
+#define ID_A9_TO_APPM3      201
+
+typedef struct VirtQueue_Object {
+    /* Id for this VirtQueue_Object */
+    UInt16                  id;
+
+    /* The function to call when buffers are consumed (can be NULL) */
+    VirtQueue_callback      callback;
+
+    /* Shared state */
+    struct vring            vring;
+
+    /* Number of free buffers */
+    UInt16                  num_free;
+
+    /* Last available index; updated by VirtQueue_getAvailBuf */
+    UInt16                  last_avail_idx;
+
+    /* Last available index; updated by VirtQueue_addUsedBuf */
+    UInt16                  last_used_idx;
+
+    /* Will eventually be used to kick remote processor */
+    UInt16                  procId;
+} VirtQueue_Object;
+
+static struct VirtQueue_Object *queueRegistry[NUM_QUEUES] = {NULL};
+
+static UInt16 hostProcId;
+#ifndef SMP
+static UInt16 dspProcId;
+static UInt16 sysm3ProcId;
+static UInt16 appm3ProcId;
+#endif
+
+#if defined(M3_ONLY) && !defined(SMP)
+extern Void OffloadM3_init();
+extern Int OffloadM3_processSysM3Tasks(UArg msg);
+#endif
+
+static inline Void * mapPAtoVA(UInt pa)
+{
+#ifndef DSPC674
+    return (Void *)((pa & 0x000fffffU) | 0xa0000000U);
+#else
+    return (Void *)((pa & 0x000fffffU) | 0x9fb00000U);
+#endif
+}
+
+static inline UInt mapVAtoPA(Void * va)
+{
+    return ((UInt)va & 0x000fffffU) | 0x9cf00000U;
+}
+
+/*!
+ * ======== VirtQueue_kick ========
+ */
+Void VirtQueue_kick(VirtQueue_Handle vq)
+{
+    /* For now, simply interrupt remote processor */
+    if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
+        Log_print0(Diags_USER1,
+                "VirtQueue_kick: no kick because of VRING_AVAIL_F_NO_INTERRUPT\n");
+        return;
+    }
+
+    Log_print2(Diags_USER1,
+            "VirtQueue_kick: Sending interrupt to proc %d with payload 0x%x\n",
+            (IArg)vq->procId, (IArg)vq->id);
+    InterruptProxy_intSend(vq->procId, vq->id);
+}
+
+/*!
+ * ======== VirtQueue_addUsedBuf ========
+ */
+Int VirtQueue_addUsedBuf(VirtQueue_Handle vq, Int16 head, Int len)
+{
+    struct vring_used_elem *used;
+
+    if ((head > vq->vring.num) || (head < 0)) {
+        Error_raise(NULL, Error_E_generic, 0, 0);
+    }
+
+    /*
+    * The virtqueue contains a ring of used buffers.  Get a pointer to the
+    * next entry in that used ring.
+    */
+    used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
+    used->id = head;
+    used->len = len;
+
+    vq->vring.used->idx++;
+
+    return (0);
+}
+
+/*!
+ * ======== VirtQueue_addAvailBuf ========
+ */
+Int VirtQueue_addAvailBuf(VirtQueue_Object *vq, Void *buf)
+{
+    UInt16 avail;
+
+    if (vq->num_free == 0) {
+        /* There's no more space */
+        Error_raise(NULL, Error_E_generic, 0, 0);
+    }
+
+    vq->num_free--;
+
+    avail =  vq->vring.avail->idx++ % vq->vring.num;
+
+    vq->vring.desc[avail].addr = mapVAtoPA(buf);
+    vq->vring.desc[avail].len = RP_MSG_BUF_SIZE;
+
+    return (vq->num_free);
+}
+
+/*!
+ * ======== VirtQueue_getUsedBuf ========
+ */
+Void *VirtQueue_getUsedBuf(VirtQueue_Object *vq)
+{
+    UInt16 head;
+    Void *buf;
+
+    /* There's nothing available? */
+    if (vq->last_used_idx == vq->vring.used->idx) {
+        return (NULL);
+    }
+
+    head = vq->vring.used->ring[vq->last_used_idx % vq->vring.num].id;
+    vq->last_used_idx++;
+
+    buf = mapPAtoVA(vq->vring.desc[head].addr);
+
+    return (buf);
+}
+
+/*!
+ * ======== VirtQueue_getAvailBuf ========
+ */
+Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf, Int *len)
+{
+    UInt16 head;
+
+    Log_print6(Diags_USER1, "getAvailBuf vq: 0x%x %d %d %d 0x%x 0x%x\n",
+        (IArg)vq, vq->last_avail_idx, vq->vring.avail->idx, vq->vring.num,
+        (IArg)&vq->vring.avail, (IArg)vq->vring.avail);
+
+    /* There's nothing available? */
+    if (vq->last_avail_idx == vq->vring.avail->idx) {
+        /* We need to know about added buffers */
+        vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+
+        return (-1);
+    }
+    /*
+     * Grab the next descriptor number they're advertising, and increment
+     * the index we've seen.
+     */
+    head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
+
+    *buf = mapPAtoVA(vq->vring.desc[head].addr);
+    *len = vq->vring.desc[head].len;
+
+    return (head);
+}
+
+/*!
+ * ======== VirtQueue_disableCallback ========
+ */
+Void VirtQueue_disableCallback(VirtQueue_Object *vq)
+{
+    //TODO
+    Log_print0(Diags_USER1, "VirtQueue_disableCallback called.");
+}
+
+/*!
+ * ======== VirtQueue_enableCallback ========
+ */
+Bool VirtQueue_enableCallback(VirtQueue_Object *vq)
+{
+    Log_print0(Diags_USER1, "VirtQueue_enableCallback called.");
+
+    //TODO
+    return (FALSE);
+}
+
+/*!
+ * ======== VirtQueue_isr ========
+ * Note 'arg' is ignored: it is the Hwi argument, not the mailbox argument.
+ */
+Void VirtQueue_isr(UArg msg)
+{
+    VirtQueue_Object *vq;
+
+    Log_print1(Diags_USER1, "VirtQueue_isr received msg = 0x%x\n", msg);
+
+#ifndef SMP
+    if (MultiProc_self() == sysm3ProcId || MultiProc_self() == dspProcId) {
+#endif
+        switch(msg) {
+            case (UInt)RP_MSG_MBOX_READY:
+                return;
+
+            case (UInt)RP_MBOX_ECHO_REQUEST:
+                InterruptProxy_intSend(hostProcId, (UInt)(RP_MBOX_ECHO_REPLY));
+                return;
+
+            case (UInt)RP_MBOX_ABORT_REQUEST:
+                {
+                    Fxn f = (Fxn)0x0;
+                    Log_print0(Diags_USER1, "Crash on demand ...\n");
+                    f();
+                }
+                return;
+
+            case (UInt)RP_MSG_FLUSH_CACHE:
+                Cache_wbAll();
+                return;
+
+#ifndef DSPC674
+            case (UInt)RP_MSG_HIBERNATION:
+                if (IpcPower_canHibernate() == FALSE) {
+                    InterruptProxy_intSend(hostProcId,
+                                        (UInt)RP_MSG_HIBERNATION_CANCEL);
+                    return;
+                }
+
+            /* Fall through */
+            case (UInt)RP_MSG_HIBERNATION_FORCE:
+#ifndef SMP
+                /* Core0 should notify Core1 */
+                if (MultiProc_self() == sysm3ProcId) {
+                    InterruptProxy_intSend(appm3ProcId,
+                                           (UInt)(RP_MSG_HIBERNATION));
+                }
+#endif
+                /* Ack request */
+                InterruptProxy_intSend(hostProcId,
+                                    (UInt)RP_MSG_HIBERNATION_ACK);
+                IpcPower_suspend();
+                return;
+#endif
+            default:
+#if defined(M3_ONLY) && !defined(SMP)
+                /* Check and process any Inter-M3 Offload messages */
+                if (OffloadM3_processSysM3Tasks(msg))
+                    return;
+#endif
+
+                /*
+                 *  If the message isn't one of the above, it's either part of the
+                 *  2-message synchronization sequence or it a virtqueue message
+                 */
+                break;
+        }
+#ifndef SMP
+    }
+#ifndef DSPC674
+    else if (msg & 0xFFFF0000) {
+        if (msg == (UInt)RP_MSG_HIBERNATION) {
+            IpcPower_suspend();
+        }
+        return;
+    }
+
+    if (MultiProc_self() == sysm3ProcId && (msg == ID_A9_TO_APPM3 || msg == ID_APPM3_TO_A9)) {
+        InterruptProxy_intSend(appm3ProcId, (UInt)msg);
+    }
+    else {
+#endif
+#endif
+        /* Don't let unknown messages to pass as a virtqueue index */
+        if (msg >= NUM_QUEUES) {
+            /* Adding print here deliberately, we should never see this */
+            System_printf("VirtQueue_isr: Invalid mailbox message 0x%x "
+                          "received\n", msg);
+            return;
+        }
+
+        vq = queueRegistry[msg];
+        if (vq) {
+            vq->callback(vq);
+        }
+#ifndef SMP
+#ifndef DSPC674
+    }
+#endif
+#endif
+}
+
+
+/*!
+ * ======== VirtQueue_create ========
+ */
+VirtQueue_Handle VirtQueue_create(UInt16 remoteProcId, VirtQueue_Params *params,
+                                  Error_Block *eb)
+{
+    VirtQueue_Object *vq;
+    Void *vringAddr;
+
+    vq = Memory_alloc(NULL, sizeof(VirtQueue_Object), 0, eb);
+    if (!vq) {
+        return (NULL);
+    }
+
+    vq->callback = params->callback;
+    vq->id = params->vqId;
+    vq->procId = remoteProcId;
+    vq->last_avail_idx = 0;
+
+#ifndef SMP
+    if (MultiProc_self() == appm3ProcId) {
+        /* vqindices that belong to AppM3 should be big so they don't
+         * collide with SysM3's virtqueues */
+        vq->id += 200;
+    }
+#endif
+
+    switch (vq->id) {
+        /* IPC transport vrings */
+        case ID_SELF_TO_A9:
+            /* IPU/DSP -> A9 */
+            vringAddr = (struct vring *) IPC_MEM_VRING0;
+            break;
+        case ID_A9_TO_SELF:
+            /* A9 -> IPU/DSP */
+            vringAddr = (struct vring *) IPC_MEM_VRING1;
+            break;
+#ifndef SMP
+        case ID_APPM3_TO_A9:
+            /* APPM3 -> A9 */
+            vringAddr = (struct vring *) IPC_MEM_VRING2;
+            break;
+        case ID_A9_TO_APPM3:
+            /* A9 -> APPM3 */
+            vringAddr = (struct vring *) IPC_MEM_VRING3;
+            break;
+#endif
+    }
+
+    Log_print3(Diags_USER1,
+            "vring: %d 0x%x (0x%x)\n", vq->id, (IArg)vringAddr,
+            RP_MSG_RING_SIZE);
+
+    vring_init(&(vq->vring), RP_MSG_NUM_BUFS, vringAddr, RP_MSG_VRING_ALIGN);
+
+    /*
+     *  Don't trigger a mailbox message every time MPU makes another buffer
+     *  available
+     */
+    if (vq->procId == hostProcId) {
+        vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+    }
+
+    queueRegistry[vq->id] = vq;
+
+    return (vq);
+}
+
+/*!
+ * ======== VirtQueue_startup ========
+ */
+Void VirtQueue_startup()
+{
+    hostProcId      = MultiProc_getId("HOST");
+#ifndef SMP
+    dspProcId       = MultiProc_getId("DSP");
+    sysm3ProcId     = MultiProc_getId("CORE0");
+    appm3ProcId     = MultiProc_getId("CORE1");
+#endif
+
+#ifndef DSPC674
+    /* Initilize the IpcPower module */
+    IpcPower_init();
+#endif
+
+#if defined(M3_ONLY) && !defined(SMP)
+    if (MultiProc_self() == sysm3ProcId) {
+        OffloadM3_init();
+    }
+#endif
+
+    InterruptProxy_intRegister(VirtQueue_isr);
+}
+
+/*!
+ * ======== VirtQueue_postCrashToMailbox ========
+ */
+Void VirtQueue_postCrashToMailbox(Void)
+{
+    InterruptProxy_intSend(0, (UInt)RP_MSG_MBOX_CRASH);
+}
+
+/*!
+ * ======== VirtQueue_postInitDone ========
+ */
+Void VirtQueue_postInitDone(Void)
+{
+    InterruptProxy_intSend(0, (UInt)RP_MSG_BOOTINIT_DONE);
+}
+
+#define CACHE_WB_TICK_PERIOD    5
+
+/*!
+ * ======== VirtQueue_cacheWb ========
+ *
+ * Used for flushing SysMin trace buffer.
+ */
+Void VirtQueue_cacheWb()
+{
+    static UInt32 oldticks = 0;
+    UInt32 newticks;
+
+    newticks = Clock_getTicks();
+    if (newticks - oldticks < (UInt32)CACHE_WB_TICK_PERIOD) {
+        /* Don't keep flushing cache */
+        return;
+    }
+
+    oldticks = newticks;
+
+    /* Flush the cache */
+    Cache_wbAll();
+}
diff --git a/packages/ti/ipc/family/omap54xx/VirtQueue.h b/packages/ti/ipc/family/omap54xx/VirtQueue.h
new file mode 100644 (file)
index 0000000..c14f0fe
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** ============================================================================
+ *  @file       VirtQueue.h
+ *
+ *  @brief      Virtio Queue interface for BIOS
+ *
+ *  Differences between BIOS version and Linux kernel (include/linux/virtio.h):
+ *  - Renamed module from virtio.h to VirtQueue.h to match the API prefixes;
+ *  - BIOS (XDC) types and CamelCasing used;
+ *  - virtio_device concept removed (i.e, assumes no containing device);
+ *  - removed scatterlist;
+ *  - VirtQueues are created statically here, so just added a VirtQueue_init()
+ *    fxn to take the place of the Virtio vring_new_virtqueue() API;
+ *  - The notify function is implicit in the implementation, and not provided
+ *    by the client, as it is in Linux virtio.
+ *  - Broke into APIs to add/get used and avail buffers, as the API is
+ *    assymmetric.
+ *
+ *  Usage:
+ *     This IPC only works between one processor designated as the Host (Linux)
+ *     and one or more Slave processors (BIOS).
+ *
+ *     For any Host/Slave pair, there are 2 VirtQueues (aka Vrings);
+ *     Only the Host adds new buffers to the avail list of a vring;
+ *     Available buffers can be empty or full, depending on direction;
+ *     Used buffer means "processed" (emptied or filled);
+ *
+ *  Host:
+ *    - To send buffer to the slave processor:
+ *          add_avail_buf(slave_virtqueue);
+ *          kick(slave_virtqueue);
+ *          get_used_buf(slave_virtqueue);
+ *    - To receive buffer from slave processor:
+ *          add_avail_buf(host_virtqueue);
+ *          kick(host_virtqueue);
+ *          get_used_buf(host_virtqueue);
+ *
+ *  Slave:
+ *    - To send buffer to the host:
+ *          get_avail_buf(host_virtqueue);
+ *          add_used_buf(host_virtqueue);
+ *          kick(host_virtqueue);
+ *    - To receive buffer from the host:
+ *          get_avail_buf(slave_virtqueue);
+ *          add_used_buf(slave_virtqueue);
+ *          kick(slave_virtqueue);
+ *
+ *  All VirtQueue operations can be called in any context.
+ *
+ *  The virtio header should be included in an application as follows:
+ *  @code
+ *  #include <ti/ipc/rpmsg/VirtQueue.h>
+ *  @endcode
+ *
+ *  ============================================================================
+ */
+
+#ifndef ti_ipc_family_omap54xx_VirtQueue__include
+#define ti_ipc_family_omap54xx_VirtQueue__include
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ *  @brief  VirtQueue Ids for the basic IPC transport rings.
+ */
+#define ID_SELF_TO_A9      0
+#define ID_A9_TO_SELF      1
+
+/*!
+ *  @brief  a queue to register buffers for sending or receiving.
+ */
+typedef struct VirtQueue_Object *VirtQueue_Handle;
+
+/*!
+ *  @var     VirtQueue_callback
+ *  @brief   Signature of any callback function that can be registered with the
+ *           VirtQueue
+ *
+ *  @param[in]  VirtQueue     Pointer to the VirtQueue which was signalled.
+ */
+typedef Void (*VirtQueue_callback)(VirtQueue_Handle);
+
+/*!
+ *  @brief      VirtQueue_params
+ */
+typedef struct VirtQueue_Params {
+    VirtQueue_callback callback;
+    Int vqId;
+} VirtQueue_Params;
+
+/* Params_init */
+static inline void VirtQueue_Params_init( VirtQueue_Params *prms )
+{
+    /* Do nothing: We are emulating an XDC generated fxn, w/o XDC config! */
+}
+
+/*!
+ *  @brief      Initialize at runtime the VirtQueue
+ *
+ *  @param[in]  procId    Processor ID associated with this VirtQueue.
+ *  @param[in]  params    VirtQueue_Params {callback, vqId}.
+ *  @param[in]  eb        Error_Block (or NULL).
+ *
+ *  @Returns    Returns a handle to a new initialized VirtQueue.
+ */
+VirtQueue_Handle VirtQueue_create(UInt16 procId, VirtQueue_Params *params,
+                                  Error_Block *eb);
+
+/*!
+ *  @brief      Notify other processor of new buffers in the queue.
+ *
+ *  After one or more add_buf calls, invoke this to kick the other side.
+ *
+ *  @param[in]  vq        the VirtQueue.
+ *
+ *  @sa         VirtQueue_addBuf
+ */
+Void VirtQueue_kick(VirtQueue_Handle vq);
+
+/*!
+ *  @brief       Used at startup-time for initialization
+ *
+ *  Should be called before any other VirtQueue APIs
+ */
+Void VirtQueue_startup();
+
+
+/*
+ *  ============================================================================
+ *  Host Only Functions:
+ *  ============================================================================
+ */
+
+/*!
+ *  @brief      Add available buffer to virtqueue's available buffer list.
+ *              Only used by Host.
+ *
+ *  @param[in]  vq        the VirtQueue.
+ *  @param[in]  buf      the buffer to be processed by the slave.
+ *
+ *  @return     Remaining capacity of queue or a negative error.
+ *
+ *  @sa         VirtQueue_getUsedBuf
+ */
+Int VirtQueue_addAvailBuf(VirtQueue_Handle vq, Void *buf);
+
+/*!
+ *  @brief      Get the next used buffer.
+ *              Only used by Host.
+ *
+ *  @param[in]  vq        the VirtQueue.
+ *
+ *  @return     Returns NULL or the processed buffer.
+ *
+ *  @sa         VirtQueue_addAvailBuf
+ */
+Void *VirtQueue_getUsedBuf(VirtQueue_Handle vq);
+
+/*
+ *  ============================================================================
+ *  Slave Only Functions:
+ *  ============================================================================
+ */
+
+/*!
+ *  @brief      Get the next available buffer.
+ *              Only used by Slave.
+ *
+ *  @param[in]  vq        the VirtQueue.
+ *  @param[out] buf       Pointer to location of available buffer;
+ *  @param[out] len       Length of the available buffer message.
+ *
+ *  @return     Returns a token used to identify the available buffer, to be
+ *              passed back into VirtQueue_addUsedBuf();
+ *              token is negative if failure to find an available buffer.
+ *
+ *  @sa         VirtQueue_addUsedBuf
+ */
+Int16 VirtQueue_getAvailBuf(VirtQueue_Handle vq, Void **buf, Int *len);
+
+/*!
+ *  @brief      Add used buffer to virtqueue's used buffer list.
+ *              Only used by Slave.
+ *
+ *  @param[in]  vq        the VirtQueue.
+ *  @param[in]  token     token of the buffer to be added to vring used list.
+ *  @param[in]  len       length of the message being added.
+ *
+ *  @return     Remaining capacity of queue or a negative error.
+ *
+ *  @sa         VirtQueue_getAvailBuf
+ */
+Int VirtQueue_addUsedBuf(VirtQueue_Handle vq, Int16 token, Int len);
+
+/*!
+ *  @brief      Post crash message to host mailbox
+ */
+Void VirtQueue_postCrashToMailbox(Void);
+
+/*!
+ *  @brief      Post a init done message to host
+ */
+Void VirtQueue_postInitDone(Void);
+
+
+#if defined (__cplusplus)
+}
+#endif /* defined (__cplusplus) */
+
+#endif /* ti_ipc_family_omap54xx_VirtQueue__include */
diff --git a/packages/ti/ipc/family/omap54xx/package.bld b/packages/ti/ipc/family/omap54xx/package.bld
new file mode 100644 (file)
index 0000000..10efe6c
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011-2013-2012, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  ======== package.bld ========
+ *
+ */
+
+/* explicit references to global objects */
+var Build = xdc.useModule('xdc.bld.BuildEnvironment');
+var Pkg = xdc.useModule('xdc.bld.PackageContents');
+var smpBuild = java.lang.System.getenv("BUILD_SMP");
+
+/* clean lib folder */
+Pkg.generatedFiles.$add("lib/");
+Pkg.libDir = "package/";
+
+/* add custom files to all releases */
+Pkg.attrs.exportSrc = false;
+Pkg.attrs.exportCfg = true;
+Pkg.otherFiles = [
+    "InterruptProxy.h",
+];
+
+/* list of libraries to build */
+var libArray = new Array();
+if (smpBuild == "1") {
+    /* rpmsg library for IPU SMP target */
+    libArray.push(
+        {
+            name: "ti.ipc.rpmsg_smp",
+            sources: [
+                "VirtQueue",
+                "InterruptIpu",
+            ],
+            libAttrs: {
+                defs: " -DSMP"
+            },
+            isas: [ "v7M" ],
+        }
+    );
+}
+else {
+    /* rpmsg library for IPU non-SMP target */
+    libArray.push(
+        {
+            name: "ti.ipc.rpmsg",
+            sources: [
+                "VirtQueue",
+                "InterruptIpu",
+                "OffloadM3",
+            ],
+            libAttrs: {
+                defs: " -DM3_ONLY"
+            },
+            isas: [ "v7M" ],
+        }
+    );
+
+    /* rpmsg library for DSP target */
+    libArray.push(
+        {
+            name: "ti.ipc.rpmsg",
+            sources: [
+                "VirtQueue",
+                "InterruptDsp",
+            ],
+            libAttrs: {
+                defs: " -DDSP"
+            },
+            isas: [ "64T" ],
+        }
+    );
+}
+
+/* generate the package libraries */
+/* check if profile specified in XDCARGS */
+/* XDCARGS="... profile=debug ..." */
+var cmdlProf = (" " + arguments.join(" ") + " ").match(/ profile=([^ ]+) /);
+cmdlProf = cmdlProf != null ? cmdlProf[1] : null;
+
+/* ==== loop over array of libraries ==== */
+for (var i = 0; i < libArray.length; i++) {
+    var lib = libArray[i];
+
+    /* ==== loop over all targets in build array ==== */
+    for (var j = 0; j < Build.targets.length; j++) {
+        var targ = Build.targets[j];
+
+        /* skip target if not compatible with source code */
+        if ("icw" in lib) {
+            var skipTarget = true;
+            var targIsaChain = "/" + targ.getISAChain().join("/") + "/";
+            for (var k = 0; k < lib.icw.length; k++) {
+                if (targIsaChain.match("/" + lib.icw[k] + "/")) {
+                    skipTarget = false;
+                    break;
+                }
+            }
+            if (skipTarget) continue;
+        }
+
+        /* skip target if it does not generate code for the given isa */
+        if ("isas" in lib) {
+            var skipTarget = true;
+            var list = "/" + lib.isas.join("/") + "/";
+            if (list.match("/" + targ.isa + "/")) {
+                skipTarget = false;
+            }
+            if (skipTarget) continue;
+        }
+
+        /* ==== loop over all profiles ==== */
+        for (var profile in targ.profiles) {
+
+            /* skip profile if different than specified on command line */
+            if ((cmdlProf != null) && (profile != cmdlProf)) {
+                continue;
+            }
+
+            /* name = lib/profile/name.a+suffix */
+            var name = "lib/" + profile + "/" + lib.name;
+
+            /* pass along library attributes specified in library array */
+            var libAttrs = "libAttrs" in lib ? lib.libAttrs : {};
+
+            /* must set profile explicitly */
+            libAttrs.profile = profile;
+
+            /* build the library */
+            var library = Pkg.addLibrary(name, targ, libAttrs);
+
+            /* add the source files */
+            library.addObjects(lib.sources);
+        }
+    }
+}
diff --git a/packages/ti/ipc/family/omap54xx/package.xdc b/packages/ti/ipc/family/omap54xx/package.xdc
new file mode 100644 (file)
index 0000000..6298d15
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ *  ======== package.xdc ========
+ *
+ */
+
+/*!
+ *  ======== ti.ipc.family.omap54xx ========
+ */
+
+package ti.ipc.family.omap54xx[1,0,0] {
+}
diff --git a/packages/ti/ipc/family/omap54xx/package.xs b/packages/ti/ipc/family/omap54xx/package.xs
new file mode 100644 (file)
index 0000000..d549b0a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *  ======== package.xs ========
+ *
+ */
+
+/*
+ *  ======== init ========
+ */
+function init()
+{
+    xdc.loadPackage('ti.pm');
+}
+
+/*
+ *  ======== close ========
+ */
+function close()
+{
+    Program.exportModule('ti.sysbios.hal.Cache');
+    Program.exportModule('ti.sysbios.knl.Idle');
+}
+
+/*
+ *  ======== getLibs ========
+ */
+function getLibs(prog)
+{
+    var suffix;
+    var file;
+    var libAry = [];
+    var profile = this.profile;
+    var smp = "";
+
+    suffix = prog.build.target.findSuffix(this);
+    if (suffix == null) {
+        return "";  /* nothing to contribute */
+    }
+
+    if (prog.platformName.match(/ipu/)) {
+        smp = "_smp";
+    }
+
+    /* make sure the library exists, else fallback to a built library */
+    file = "lib/" + profile + "/ti.ipc.rpmsg" + smp + ".a" + suffix;
+    if (java.io.File(this.packageBase + file).exists()) {
+        libAry.push(file);
+    }
+    else {
+        file = "lib/release/ti.ipc.rpmsg" + smp + ".a" + suffix;
+        if (java.io.File(this.packageBase + file).exists()) {
+            libAry.push(file);
+        }
+        else {
+            /* fallback to a compatible library built by this package */
+            for (var p in this.build.libDesc) {
+                if (suffix == this.build.libDesc[p].suffix) {
+                    libAry.push(p);
+                    break;
+                }
+            }
+        }
+    }
+
+    return libAry.join(";");
+}