1    /*
     2     * Copyright (c) 2014, Texas Instruments Incorporated
     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     *  ======== IntXbar.xdc ========
    34     */
    35    
    36    package ti.sysbios.family.shared.vayu;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.Assert;
    41    import xdc.runtime.Error;
    42    
    43    import ti.sysbios.interfaces.IHwi;
    44    
    45    /*!
    46     *  ======== IntXbar ========
    47     *  IntXbar module
    48     *
    49     *  This module provides APIs to connect an IRQ source to
    50     *  an IRQ line on the target cpu's interrupt controller
    51     *  using the Interrupt Crossbar module in the hardware.
    52     *
    53     *  Below is an example of how to override the default mapping of
    54     *  interrupt 23 on a M4 so that the interrupt source is I2C module 1
    55     *  rather than Display Controller interrupt request(mapped by default):
    56     *
    57     *  @p(code)
    58     *  #include <ti/sysbios/family/arm/m3/Hwi.h>
    59     *  #include <ti/sysbios/family/shared/vayu/IntXbar.h>
    60     *
    61     *  Void myI2CHandler(UArg arg)
    62     *  {
    63     *      // Handler Code
    64     *  }
    65     *
    66     *  Int main(Int argc, Char* argv[])
    67     *  {
    68     *      Hwi_Params params;
    69     *
    70     *      Hwi_Params_init(&params);
    71     *
    72     *      // Connect IRQ 23 to Interrupt source index 51 (I2C1_IRQ)
    73     *      IntXbar_connectIRQ(23, 51);
    74     *
    75     *      // Alternately, IntXbar_connect API can be used. This
    76     *      // API expects XBAR instance number as an argument.
    77     *      //
    78     *      // Connect Xbar Instance 1 (IRQ 23) to Interrupt
    79     *      // source index 51 (I2C1_IRQ)
    80     *      //
    81     *      // IntXbar_connect(1, 51);
    82     *
    83     *      // create a corresponding interrupt handler
    84     *      params.arg = 23; // pass the Interrupt number to the handler
    85     *
    86     *      Hwi_create(23, myI2CHandler, &params, NULL);
    87     *
    88     *      BIOS_start();
    89     *
    90     *      return (0);
    91     *  }
    92     *  @p
    93     *
    94     *  Here is how you would define the same interrupt handler statically
    95     *  in a configuration script:
    96     *
    97     *  @p(code)
    98     *  var Hwi = xdc.useModule('ti.sysbios.family.arm.m3.Hwi');
    99     *  var IntXbar = xdc.useModule('ti.sysbios.family.shared.vayu.IntXbar');
   100     *
   101     *  // Connect IRQ 23 to Interrupt source index 51 (I2C1_IRQ)
   102     *  IntXbar.connectIRQMeta(23, 51);
   103     *
   104     *  // Alternately, the connectIRQMeta API can be used. This
   105     *  // API expects XBAR instance number as an argument.
   106     *  //
   107     *  // Connect Xbar Instance 1 (IRQ 23) to Interrupt
   108     *  // source index 51 (I2C1_IRQ)
   109     *  //
   110     *  // IntXbar.connectMeta(1, 51);
   111     *
   112     *  var hwiParams = new Hwi.Params();
   113     *  hwiParams.arg = 23;
   114     *
   115     *  Program.global.staticHwi = Hwi.create(23, '&myTimerHandler', hwiParams);
   116     *  @p
   117     *
   118     *  @p(html)
   119     *  <h3> Calling Context </h3>
   120     *  <table border="1" cellpadding="3">
   121     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
   122     *
   123     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   124     *    <!--                                                                                                                 -->
   125     *    <tr><td> {@link #connect}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   126     *    <tr><td> {@link #disconnect}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   127     *    <tr><td colspan="6"> Definitions: <br />
   128     *       <ul>
   129     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   130     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   131     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   132     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   133     *           <ul>
   134     *             <li> In your module startup after this module is started (e.g. Mod_Module_startupDone() returns TRUE). </li>
   135     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   136     *             <li> During main().</li>
   137     *             <li> During BIOS.startupFxns.</li>
   138     *           </ul>
   139     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   140     *           <ul>
   141     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   142     *             <li> In your module startup before this module is started (e.g. Mod_Module_startupDone() returns FALSE).</li>
   143     *           </ul>
   144     *       </ul>
   145     *    </td></tr>
   146     *
   147     *  </table>
   148     *  @p
   149     */
   150    
   151    @DirectCall
   152    module IntXbar
   153    {
   154        /*!
   155         *  ======== ModuleDataView ========
   156         *  @_nodoc
   157         */
   158        metaonly struct ModuleDataView {
   159            Int cpuIRQNumber;
   160            Int xbarInstanceNumber;
   161            Int interruptSourceIndex;
   162        }
   163    
   164        /*!
   165         *  ======== rovViewInfo ========
   166         *  @_nodoc
   167         */
   168        @Facet
   169        metaonly config ViewInfo.Instance rovViewInfo = 
   170            ViewInfo.create({
   171                viewMap: [
   172                [
   173                    'XbarList',
   174                    {
   175                        type: ViewInfo.MODULE_DATA,
   176                        viewInitFxn: 'viewInitData',
   177                        structName: 'ModuleDataView'
   178                    }
   179                ],
   180                ]
   181            });
   182    
   183        /*!
   184         *  Assert if EVE XBAR instance number < 1 or > 8
   185         */
   186        config Assert.Id A_badEveXbarInstanceNum = {
   187            msg: "A_badEveXbarInstanceNum: xbarInstance must be >= 1 and <= 8"
   188        };
   189    
   190        /*!
   191         *  Assert if DSP XBAR instance number < 1 or > 64
   192         */
   193        config Assert.Id A_badDspXbarInstanceNum = {
   194            msg: "A_badDspXbarInstanceNum: xbarInstance must be >= 1 and <= 64"
   195        };
   196    
   197        /*!
   198         *  Assert if Benelli XBAR instance number < 1 or > 57
   199         */
   200        config Assert.Id A_badBenelliXbarInstanceNum = {
   201            msg: "A_badBenelliXbarInstanceNum: xbarInstance must be >= 1 and <= 57"
   202        };
   203    
   204        /*!
   205         *  Assert if A15 XBAR instance number < 1 or > 152
   206         */
   207        config Assert.Id A_badA15XbarInstanceNum = {
   208            msg: "A_badA15XbarInstanceNum: xbarInstance must be >= 1 and <= 152"
   209        };
   210    
   211        /*!
   212         *  Assert if EVE IRQ number > 7
   213         */
   214        config Assert.Id A_badEveIRQNum = {
   215            msg: "A_badEveIRQNum: IRQ number must be <= 7"
   216        };
   217    
   218        /*!
   219         *  Assert if DSP IRQ number is < 32 or > 95
   220         */
   221        config Assert.Id A_badDspIRQNum = {
   222            msg: "A_badDspIRQNum: IRQ number must be >= 32 and <= 95"
   223        };
   224    
   225        /*!
   226         *  Assert if Benelli/IPU IRQ number is < 23 or > 79
   227         */
   228        config Assert.Id A_badBenelliIRQNum = {
   229            msg: "A_badBenelliIRQNum: IRQ number must be >= 23 and <= 79"
   230        };
   231    
   232        /*!
   233         *  Assert if A15 IRQ number is < 4 or == 5 or == 6 or == 131 or == 132 or
   234         *  == 139 or == 140 or > 159
   235         */
   236        config Assert.Id A_badA15IRQNum = {
   237            msg: "A_badA15IRQNum: No XBAR instance corresponding to given IRQ num"
   238        };
   239    
   240        /*!
   241         *  Assert if IRQ crossbar input index is out of range.
   242         */
   243        config Assert.Id A_badIntSourceIdx = {
   244            msg: "A_badIntSourceIdx: IRQ crossbar input index (intSource) out of range."
   245        };
   246    
   247        /*!
   248         *  Assert if EVE CPU Id invalid
   249         */
   250        config Assert.Id A_badEveCpuId = {
   251            msg: "A_badEveCpuId: CPU Id must be 0, 1, 2 or 3"
   252        };
   253    
   254        /*!
   255         *  Assert if DSP CPU Id invalid
   256         */
   257        config Assert.Id A_badDspCpuId = {
   258            msg: "A_badDspCpuId: CPU Id must be 0 or 1"
   259        };
   260    
   261        /*!
   262         *  Assert if Benelli IPU Id invalid
   263         */
   264        config Assert.Id A_badBenelliIpuId = {
   265            msg: "A_badBenelliIpuId: Ipu Id must be 1 or 2"
   266        };
   267    
   268        /*!
   269         *  Base address of interrupt crossbar MMR registers
   270         */
   271        config UInt32 mmrBaseAddr = 0x4A002000;
   272    
   273        /*!
   274         *  Number of IRQ XBAR inputs
   275         */
   276        const UInt16 numIrqXbarInputs = 420;
   277    
   278        /*!
   279         *  Number of XBAR instances per EVE core
   280         */
   281        const UInt16 NUM_EVE_XBAR_INST = 8;
   282    
   283        /*!
   284         *  Number of XBAR instances per DSP core
   285         */
   286        const UInt16 NUM_DSP_XBAR_INST = 64;
   287    
   288        /*!
   289         *  Number of XBAR instances per Benelli Core
   290         */
   291        const UInt16 NUM_BENELLI_XBAR_INST = 57;
   292    
   293        /*!
   294         *  Number of XBAR instances per A15 Core
   295         */
   296        const UInt16 NUM_A15_XBAR_INST = 152;
   297    
   298        /*!
   299         *  Offset of "AVATAR_INTR_DMA_OCPINTF__EVE1_IRQ_0_1" register
   300         */
   301        const UInt32 MMR_OFFSET_EVE0 = 0x7A0;
   302    
   303        /*!
   304         *  Offset of "AVATAR_INTR_DMA_OCPINTF__EVE2_IRQ_0_1" register
   305         */
   306        const UInt32 MMR_OFFSET_EVE1 = 0x7B0;
   307    
   308        /*!
   309         *  Offset of "AVATAR_INTR_DMA_OCPINTF__EVE3_IRQ_0_1" register
   310         */
   311        const UInt32 MMR_OFFSET_EVE2 = 0x7C0;
   312    
   313        /*!
   314         *  Offset of "AVATAR_INTR_DMA_OCPINTF__EVE4_IRQ_0_1" register
   315         */
   316        const UInt32 MMR_OFFSET_EVE3 = 0x7D0;
   317    
   318        /*!
   319         *  Offset of "AVATAR_INTR_DMA_OCPINTF__DSP1_IRQ_32_33" register
   320         */
   321        const UInt32 MMR_OFFSET_DSP0 = 0x948;
   322    
   323        /*!
   324         *  Offset of "AVATAR_INTR_DMA_OCPINTF__DSP2_IRQ_32_33" register
   325         */
   326        const UInt32 MMR_OFFSET_DSP1 = 0x9c8;
   327    
   328        /*!
   329         *  Offset of "AVATAR_INTR_DMA_OCPINTF__IPU1_IRQ_23_24" register
   330         */
   331        const UInt32 MMR_OFFSET_BENELLI_IPU1 = 0x7E0;
   332    
   333        /*!
   334         *  Offset of "AVATAR_INTR_DMA_OCPINTF__IPU2_IRQ_23_24" register
   335         */
   336        const UInt32 MMR_OFFSET_BENELLI_IPU2 = 0x854;
   337        
   338        /*!
   339         *  Offset of "AVATAR_INTR_DMA_OCPINTF__MPU_IRQ_4_5" register
   340         */
   341        const UInt32 MMR_OFFSET_A15 = 0xA48;
   342        
   343        /*!
   344         *  Offset of MMR Lock 2 register
   345         *
   346         *  Register to lock memory region starting at address offset 0x000007A0
   347         *  and ending at address offset 0x00000D9F
   348         */
   349        const UInt32 MMR_OFFSET_LOCK2 = 0x544;
   350    
   351        /*!
   352         *  MMR Lock 2 lock value
   353         */
   354        const UInt32 MMR_LOCK2_LOCK = 0xFDF45530;
   355    
   356        /*!
   357         *  MMR Lock 2 unlock value
   358         */
   359        const UInt32 MMR_LOCK2_UNLOCK = 0xF757FDC0;
   360    
   361        /*!
   362         *  ======== connectMeta ========
   363         *  Connect the XBAR instance associated with an interrupt.
   364         *
   365         *  Dynamically connects the XBAR instance associated with 
   366         *  an interrupt on the current core to the selected
   367         *  interrupt source.
   368         *
   369         *  @param(xbarInstance)    XBAR instance number
   370         *  @p(code)
   371         *              (1-8)   For EVE Cores
   372         *              (1-64)  For DSP Cores
   373         *              (1-57)  For M4 Cores
   374         *              (1-152) For A15 Cores
   375         *  @p
   376         *  @param(intSource)   IRQ crossbar input index
   377         *
   378         */
   379        metaonly Void connectMeta(UInt xbarInstance, UInt intSource);
   380    
   381        /*!
   382         *  ======== connect ========
   383         *  Connect the XBAR instance associated with an interrupt.
   384         *
   385         *  Dynamically connects the XBAR instance associated with 
   386         *  an interrupt on the current core to the selected
   387         *  interrupt source.
   388         *
   389         *  @param(xbarInstance)    XBAR instance number
   390         *  @p(code)
   391         *              (1-8)   For EVE Cores
   392         *              (1-64)  For DSP Cores
   393         *              (1-57)  For M4 Cores
   394         *              (1-152) For A15 Cores
   395         *  @p
   396         *  @param(intSource)   IRQ crossbar input index
   397         */
   398        Void connect(UInt xbarInstance, UInt intSource);
   399    
   400        /*!
   401         *  ======== disconnect ========
   402         *  Disconnect the XBAR instance associated with an interrupt.
   403         *
   404         *  Dynamically disconnects the XBAR instance associated with 
   405         *  an interrupt on the current core by clearing the
   406         *  interrupt source index.
   407         *
   408         *  @param(xbarInstance)    XBAR instance number
   409         *  @p(code)
   410         *              (1-8)   For EVE Cores
   411         *              (1-64)  For DSP Cores
   412         *              (1-57)  For M4 Cores
   413         *              (1-152) For A15 Cores
   414         *  @p
   415         */
   416        Void disconnect(UInt xbarInstance);
   417    
   418        /*!
   419         *  ======== connectIRQMeta ========
   420         *  Make a XBAR connection for the given IRQ number.
   421         *
   422         *  Dynamically connects the XBAR instance associated with
   423         *  the given IRQ number on the current core to the selected
   424         *  interrupt source.
   425         *
   426         *  Please note that IRQ number is same as Event Id on C66 DSP.
   427         *
   428         *  @param(cpuIRQNum)   CPU's IRQ number
   429         *  @param(intSource)   IRQ crossbar input index
   430         */
   431        metaonly Void connectIRQMeta(UInt cpuIRQNum, UInt intSource);
   432    
   433        /*!
   434         *  ======== connectIRQ ========
   435         *  Make a XBAR connection for the given IRQ number.
   436         *
   437         *  Dynamically connects the XBAR instance associated with
   438         *  the given IRQ number on the current core to the selected
   439         *  interrupt source.
   440         *
   441         *  Please note that IRQ number is same as Event Id on C66 DSP.
   442         *
   443         *  @param(cpuIRQNum)   CPU's IRQ number
   444         *  @param(intSource)   IRQ crossbar input index
   445         */
   446        Void connectIRQ(UInt cpuIRQNum, UInt intSource);
   447    
   448        /*!
   449         *  ======== disconnectIRQ ========
   450         *  Disconnect the XBAR connection associated with the given IRQ number.
   451         *
   452         *  Dynamically disconnects the XBAR instance associated with
   453         *  the given IRQ number on the current core by clearing the
   454         *  interrupt source index.
   455         *
   456         *  Please note that IRQ number is same as Event Id on C66 DSP.
   457         *
   458         *  @param(cpuIRQNum)   CPU's IRQ number
   459         */
   460        Void disconnectIRQ(UInt cpuIRQNum);
   461    
   462    internal:
   463    
   464        config UInt16 intXbar[];   // table of interrupt Xbar instances
   465    
   466        /*
   467         *  ======== initXbarRegs ========
   468         */
   469        Void initXbarRegs(volatile UInt32 **intXbarReg, UInt16 *intXbarLength);
   470    
   471        /*
   472         *  ======== initIntXbar ========
   473         */
   474        Void initIntXbar();
   475    
   476        struct Module_State {
   477            UInt16 intXbar[];   // table of interrupt Xbar instances
   478        };
   479    }