1    /*
     2     * Copyright (c) 2012-2014 Texas Instruments Incorporated - https://www.ti.com
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    
    33    /*
    34     *  ======== NotifySetup.xdc ========
    35     */
    36    
    37    package ti.sdo.ipc.family.vayu;
    38    
    39    import xdc.runtime.Assert;
    40    import ti.sdo.utils.MultiProc;
    41    
    42    /*!
    43     *  ======== NotifySetup ========
    44     *  Notify driver setup proxy for Vayu
    45     *
    46     *  This module creates and registers the IPC Notify drivers for the Vayu
    47     *  device family. There are two types of notify drivers available: 1) shared
    48     *  memory driver, and 2) mailbox driver. Use the {@link #connections}
    49     *  configuration parameter to select which driver to use for communicating
    50     *  with each remote processor.
    51     *
    52     *  The shared memory notify driver is the default driver. It implements the
    53     *  full Notify API set. This driver uses memory for passing the notify
    54     *  payload between processors. The memory is allocated from SharedRegion #0.
    55     *
    56     *  The mailbox notify driver uses hardware FIFOs for passing the notify
    57     *  payload between processors. No shared memory is required. However, this
    58     *  driver does not implement the full Notify API set. For example, the
    59     *  `Notify_sendEvent()` API will never return `Notify_E_EVTNOTREGISTERED`
    60     *  because it does not track this information.
    61     *
    62     *  When configuring the notify driver, you specify which driver to use
    63     *  for communicating to each remote processor. If not configured, the
    64     *  shared memory driver will be used by default. Both sides of each connection
    65     *  must use the same driver. This is an easy mistake to make and there is
    66     *  no way to check this.
    67     *
    68     *  This module is primarily used by notify driver authors. It is not expected
    69     *  that any application would ever use this module in its runtime code.
    70     *  The typical use of this module is simply to configure which notify driver
    71     *  to use. See the following example for details.
    72     *
    73     *  @a(Configuration Example)
    74     *
    75     *  The following is a three processor example: HOST DSP1 EVE1. In this
    76     *  example, HOST and DSP1 will communicate using the shared memory driver
    77     *  and DSP1 and EVE1 will communicate using the mailbox driver. This example
    78     *  explicitly configures the shared memory driver for HOST and DSP1, but
    79     *  this is strictly not necessary. If left unconfigured, the shared memory
    80     *  driver would be used as the default. Also, the connection between HOST
    81     *  and EVE1 is left undefined as we don't expect to use this connection.
    82     *
    83     *  Notice that each connection configuration specifies the remote processor
    84     *  name and the driver type. This is how the local processor declares which
    85     *  driver it will use when communicating to that remote processor. The
    86     *  corresponding configuration on the remote processor must be complimentary.
    87     *
    88     *  Add the following to your HOST configuration script.
    89     *
    90     *  @p(code)
    91     *  // configure the notify driver
    92     *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
    93     *
    94     *  NotifySetup.connections.$add(
    95     *      new NotifySetup.Connection({
    96     *          driver: NotifySetup.Driver_SHAREDMEMORY,
    97     *          procName: "DSP1"
    98     *      })
    99     *  );
   100     *  @p
   101     *  Add the following to your DSP1 configuration script.
   102     *
   103     *  @p(code)
   104     *  // configure the notify driver
   105     *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
   106     *
   107     *  NotifySetup.connections.$add(
   108     *      new NotifySetup.Connection({
   109     *          driver: NotifySetup.Driver_SHAREDMEMORY,
   110     *          procName: "HOST"
   111     *      })
   112     *  );
   113     *
   114     *  NotifySetup.connections.$add(
   115     *      new NotifySetup.Connection({
   116     *          driver: NotifySetup.Driver_MAILBOX,
   117     *          procName: "EVE1"
   118     *      })
   119     *  );
   120     *  @p
   121     *  Add the following to your EVE1 configuration script.
   122     *
   123     *  @p(code)
   124     *  // configure the notify driver
   125     *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
   126     *
   127     *  NotifySetup.connections.$add(
   128     *      new NotifySetup.Connection({
   129     *          driver: NotifySetup.Driver_MAILBOX,
   130     *          procName: "DSP1"
   131     *      })
   132     *  );
   133     *  @p
   134     */
   135    
   136    @ModuleStartup
   137    @Template("./NotifySetup.xdt")
   138    
   139    module NotifySetup inherits ti.sdo.ipc.interfaces.INotifySetup
   140    {
   141        /*! @_nodoc
   142         *  ======== DriverIsr ========
   143         *  Notify driver isr function type definition
   144         *  param1 = mailbox table index
   145         */
   146        typedef Void (*DriverIsr)(UInt16);
   147    
   148        /*!
   149         *  ======== Driver ========
   150         *  Define the available notify drivers
   151         *
   152         *  For any given connection to a remote processor, one of the
   153         *  following notify driver types may be used. Each driver has
   154         *  different characteristics and system requirements.
   155         *
   156         *  @p(html)
   157         *  <div class="xdocText"><dl>
   158         *  <dt>Driver_SHAREDMEMORY</dt>
   159         *      <dd>
   160         *      This driver uses shared memory for passing the notify payload
   161         *      between processors. Additional state is also stored in the
   162         *      shared memory.<br><br>
   163         *
   164         *      There is a separate, cache-aligned block of memory for each
   165         *      event number. This is necessary to maintain cache coherency.
   166         *      However, this requires a non-trivial amount of memory.<br><br>
   167         *      </dd>
   168         *
   169         *  <dt>Driver_MAILBOX</dt>
   170         *      <dd>
   171         *      This driver uses a hardware FIFO (provided by the hardware
   172         *      mailbox) to pass the notify payload between processors. No
   173         *      shared memory is required by this driver.<br><br>
   174         *
   175         *      This driver does not support the full Notify API set. This
   176         *      driver has lower delivery latency when compard to the shared
   177         *      memory driver.<br><br>
   178         *      </dd>
   179         *  </dl>
   180         *  @p
   181         */
   182        enum Driver {
   183            Driver_SHAREDMEMORY = 0x01,     /*! shared memory driver */
   184            Driver_MAILBOX = 0x02           /*! hardware mailbox driver */
   185        };
   186    
   187        /*!
   188         *  ======== Connection ========
   189         *  Define a notify driver connection
   190         *
   191         *  Each IPC connection is defined by two end-points: the local
   192         *  processor and the remote processor. Each connection supports
   193         *  only one type of notify driver. In other words, both ends of
   194         *  the connection must configure the same notify driver type.
   195         *
   196         *  However, when a processor has multiple connections (when
   197         *  communicating with multiple remote processors), each connection
   198         *  is configured independently. Therefore, different notify drivers
   199         *  may be used for different connections. Currently, IPC supports
   200         *  only one connection for each remote processor.
   201         *
   202         *  The configuration for a given connection must be coordinated with
   203         *  the remote processor. Each processor is only able to configure its
   204         *  local end-point for the connection. It is important that the remote
   205         *  processor use the same notify driver for the connection.
   206         *
   207         *  @field(driver)
   208         *  The driver to be used for this connection. See the {@link #Driver}
   209         *  enumeration for details.
   210         *
   211         *  @field(procName)
   212         *  The name of the remote processor for the given connection.
   213         *  @p
   214         */
   215        struct Connection {
   216            Driver driver;                  /*! notify driver */
   217            String procName;                /*! remote processor name */
   218        };
   219    
   220        /*!
   221         *  ======== connections ========
   222         *  Configure the notify driver for each given connection
   223         *
   224         *  Use this configuration parameter to define which notify driver
   225         *  is to be used when communicating with remote processors. Create
   226         *  one entry in this array for each connection. Each entry you create,
   227         *  defines the local end-point of the connection. The remote processor
   228         *  must have a complimentary entry in its `connections` array.
   229         *
   230         *  Any connection which is undefined, will use the shared memory
   231         *  notify driver. It is not necessary to define all connections, just
   232         *  the ones which will not use the default.
   233         *
   234         *  To define a local end-point connection, establish a reference to
   235         *  this module and add a new entry to this array.
   236         *
   237         *  The following example show how to setup the mailbox driver for
   238         *  communicating from DSP1 to EVE1 and EVE2.
   239         *
   240         *  Add the following to your DSP1 configuration script.
   241         *
   242         *  @p(code)
   243         *  // configure the notify driver
   244         *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
   245         *
   246         *  NotifySetup.connections.$add(
   247         *      new NotifySetup.Connection({
   248         *          driver: NotifySetup.Driver_MAILBOX,
   249         *          procName: "EVE1"
   250         *      })
   251         *  );
   252         *
   253         *  NotifySetup.connections.$add(
   254         *      new NotifySetup.Connection({
   255         *          driver: NotifySetup.Driver_MAILBOX,
   256         *          procName: "EVE2"
   257         *      })
   258         *  );
   259         *  @p
   260         *
   261         *  Add the following to your EVE1 configuration script.
   262         *
   263         *  @p(code)
   264         *  // configure the notify driver
   265         *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
   266         *
   267         *  NotifySetup.connections.$add(
   268         *      new NotifySetup.Connection({
   269         *          driver: NotifySetup.Driver_MAILBOX,
   270         *          procName: "DSP1"
   271         *      })
   272         *  );
   273         *  @p
   274         *
   275         *  Add the following to your EVE2 configuration script.
   276         *
   277         *  @p(code)
   278         *  // configure the notify driver
   279         *  var NotifySetup = xdc.useModule('ti.sdo.ipc.family.vayu.NotifySetup');
   280         *
   281         *  NotifySetup.connections.$add(
   282         *      new NotifySetup.Connection({
   283         *          driver: NotifySetup.Driver_MAILBOX,
   284         *          procName: "DSP1"
   285         *      })
   286         *  );
   287         *  @p
   288         */
   289        metaonly config Connection connections[length];
   290    
   291        /*! @_nodoc
   292         *  ======== plugHwi ========
   293         *  Register an isr for the given interrupt and event.
   294         *
   295         *  @param(remoteProcId) The MutiProc Id of the remote processor
   296         *  which will raise the given interrupt.
   297         *
   298         *  @param(cpuIntrNum) The interrupt number which will be raised
   299         *  by the remote processor.
   300         *
   301         *  @param(isr) The ISR which should be invoked to service the
   302         *  given interrupt.
   303         */
   304        Void plugHwi(UInt16 remoteProcId, Int cpuIntrNum, DriverIsr isr);
   305    
   306        /*! @_nodoc
   307         *  ======== unplugHwi ========
   308         *  Unregister the isr for the given interrupt.
   309         */
   310        Void unplugHwi(UInt16 remoteProcId, Int cpuIntrNum);
   311    
   312        /*! @_nodoc
   313         *  ======== interruptTable ========
   314         *  Accessor method to return interrupt id for given virtual proc id
   315         */
   316        UInt16 interruptTable(Int srcVirtId);
   317    
   318    internal:
   319        /* interrupt vector id for dsp */
   320        config UInt dspIntVectId = 4;
   321    
   322        /* interrupt vector id for eve */
   323        config UInt eveIntVectId_INTC0 = 4;
   324        config UInt eveIntVectId_INTC1 = 8;
   325    
   326        /* total number of cores on Vayu SoC */
   327        const UInt8 NUM_CORES = 11;
   328    
   329        /* number of cores in eve subsystem */
   330        const UInt8 NUM_EVES = 4;
   331    
   332        /* number of internal eve mailboxes */
   333        const UInt8 NUM_EVE_MBX = 12;
   334    
   335        /* number of system mailboxes (used by IPC) */
   336        const UInt8 NUM_SYS_MBX = 4;
   337    
   338        /*  Mailbox table for storing encoded base address, mailbox user ID,
   339         *  and sub-mailbox index.
   340         */
   341        config UInt32 mailboxTable[NUM_CORES * NUM_CORES];
   342    
   343        /* base address table for the mailbox subsystem */
   344        config UInt32 mailboxBaseAddr[NUM_EVE_MBX + NUM_SYS_MBX];
   345    
   346        /* map procId to discrete processor/core */
   347        config UInt eve1ProcId = MultiProc.INVALIDID;
   348        config UInt eve2ProcId = MultiProc.INVALIDID;
   349        config UInt eve3ProcId = MultiProc.INVALIDID;
   350        config UInt eve4ProcId = MultiProc.INVALIDID;
   351        config UInt dsp1ProcId = MultiProc.INVALIDID;
   352        config UInt dsp2ProcId = MultiProc.INVALIDID;
   353        config UInt ipu1_0ProcId = MultiProc.INVALIDID;  /* also used for ipu1 */
   354        config UInt ipu1_1ProcId = MultiProc.INVALIDID;
   355        config UInt ipu2_0ProcId = MultiProc.INVALIDID;  /* also used for ipu2 */
   356        config UInt ipu2_1ProcId = MultiProc.INVALIDID;
   357        config UInt hostProcId = MultiProc.INVALIDID;
   358    
   359        /* map MultiProc ID to virtual ID, virtId = procIdTable[procId] */
   360        config UInt32 procIdTable[NUM_CORES];
   361    
   362        /* runtime driver binding structure */
   363        struct DrvBind {
   364            Driver driver;                  /* notify driver */
   365            UInt16 procId;                  /* remote processor ID */
   366        };
   367    
   368        /*
   369         *  ======== A_internal ========
   370         *  Internal implementation error.
   371         */
   372        config Assert.Id A_internal = {
   373            msg: "A_internal: internal implementation error"
   374        };
   375    
   376        /*
   377         *  ======== driverType ========
   378         */
   379        Driver driverType(UInt16 remoteProcId);
   380    
   381        /*
   382         *  ======== Shm_attach ========
   383         */
   384        Int Shm_attach(UInt16 remoteProcId, Ptr sharedAddr);
   385    
   386        /*
   387         *  ======== Shm_sharedMemReq ========
   388         */
   389        SizeT Shm_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr);
   390    
   391        /*
   392         *  ======== Mbx_attach ========
   393         */
   394        Int Mbx_attach(UInt16 remoteProcId, Ptr sharedAddr);
   395    
   396        /*
   397         *  ======== Mbx_sharedMemReq ========
   398         */
   399        SizeT Mbx_sharedMemReq(UInt16 remoteProcId, Ptr sharedAddr);
   400    
   401        /*
   402         *  ======== dispatchIsr ========
   403         *  Dispatch interrupt to notify driver instance.
   404         */
   405        Void dispatchIsr(UArg arg);
   406    
   407        /*
   408         *  ======== Module_State ========
   409         */
   410        struct Module_State {
   411            /* interrupt plug counter */
   412            UInt16 numPlugged[];
   413    
   414            /* connection array */
   415            DrvBind connAry[length];
   416    
   417            /*  Interrupt event IDs used to communicate with this processor.
   418             *  This table is indexed by virtual processor ID.
   419             */
   420            UInt16 interruptTable[NUM_CORES];
   421    
   422            /*  Notify driver isr dispatch table. This table is indexed
   423             *  by virtual processor ID.
   424             */
   425            DriverIsr isrDispatchTable[NUM_CORES];
   426        };
   427    }