1    /*
     2     * Copyright (c) 2015, 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     *  ======== MPU.xdc ========
    34     */
    35    
    36    package ti.sysbios.family.arm;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    /*!
    41     *  ======== MPU ========
    42     *  Memory Protection Unit (MPU) Manager.
    43     *
    44     *  This module manages the Memory Protect Unit (MPU) present in many ARM
    45     *  Cortex-R and Cortex-M devices. It enables the application to partition
    46     *  the memory into different regions and set protection attributes for
    47     *  each region.
    48     *
    49     *  The number of memory regions supported is device specific and may vary
    50     *  on different devices. The Cortex-R5F based TMS570DCxx/RM57D8xx devices
    51     *  for instance support 16 memory regions.
    52     *
    53     *  Programming a memory region requires specifying the base address and
    54     *  size of the region, and the region's protection attributes. It is also
    55     *  possible to overlap different memory regions with higher region numbers
    56     *  enjoying higher priority than lower region numbers i.e. region 15 has
    57     *  a higher priority than region 14, and if both were overlapping, the
    58     *  overlapped memory region's attributes would be defined by region 15's
    59     *  entry.
    60     *
    61     *  The protection attributes for each region include attributes such as
    62     *  memory type (strongly-ordered, device or normal), shareability,
    63     *  cacheability and read-write access permission.
    64     *
    65     *  By default, this module programs the MPU regions with some default
    66     *  settings/attributes. Please see this
    67     *  {@link ./doc-files/MpuRegions.html MPU Region Settings} table for
    68     *  a list of default settings used for various supported devices.
    69     *
    70     *  @a(Memory region attributes)
    71     *  Memory regions can be configured as different memory types by setting
    72     *  the {@link #RegionAttrs bufferable}, {@link #RegionAttrs cacheable} and
    73     *  {@link #RegionAttrs tex} (type extension) fields of the {@link #RegionAttrs}
    74     *  structure which is passed as an argument to
    75     *  {@link #setRegion MPU_setRegion()} function. The three memory types
    76     *  supported by the hardware are "Normal" (cacheable), "Device" and
    77     *  "Strongly-ordered" memory. "Device" and "Strongly-ordered" memory types
    78     *  are recommended for mapping peripheral address space like memory-mapped
    79     *  registers. These two types ensure that the memory accesses to the
    80     *  peripheral memory are not performed speculatively, are not repeated and
    81     *  are performed in order. The "Normal" memory type is recommended for mapping
    82     *  memory regions storing application code and data.
    83     *
    84     *  Here are some common settings for the {@link #RegionAttrs bufferable},
    85     *  {@link #RegionAttrs cacheable} and {@link #RegionAttrs tex} fields to
    86     *  define different memory region types:
    87     *
    88     *  @p(code)
    89     *  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    90     *  + Memory Type                             | bufferable | cacheable | tex +
    91     *  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    92     *  + Shareable Strongly-ordered memory       |    false   |   false   |  0  +
    93     *  +-----------------------------------------+------------+-----------+-----+
    94     *  + Shareable Device memory                 |    true    |   false   |  0  +
    95     *  +-----------------------------------------+------------+-----------+-----+
    96     *  + Outer & Inner Non-cacheable             |    false   |   false   |  1  +
    97     *  +-----------------------------------------+------------+-----------+-----+
    98     *  + Outer & Inner Write-back Write-allocate |    true    |   true    |  1  +
    99     *  + cacheable                               |            |           |     +
   100     *  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   101     *  @p
   102     *
   103     *  For an exhaustive list of all different memory type settings and a
   104     *  detailed explanation of the memory region attributes, please read the
   105     *  'Protected Memory System Architecture (PMSA)' chapter of the
   106     *  {@link http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/index.html ARM v7AR Architecture Reference Manual}.
   107     *
   108     *  @a(Changing shareability attributes of a cacheable memory region)
   109     *  If changing the shareability attribute of a cacheable memory region,
   110     *  it is possible for coherency problems to arise. In order to avoid possible
   111     *  coherency errors, the below sequence should be followed to change the
   112     *  shareability attributes of the memory region:
   113     *  - Make the memory region Non-cacheable and outer-shareable
   114     *  - Clean and invalidate the memory region from the cache
   115     *  - Change the shareability attribute to the desired value
   116     *
   117     *  @a(Examples)
   118     *  Example showing how to set attributes for a given memory region using
   119     *  *.cfg script:
   120     *
   121     *  @p(code)
   122     *  var MPU = xdc.useModule('ti.sysbios.family.arm.MPU');
   123     *
   124     *  // Mark memory region as normal outer and inner write-back
   125     *  // and write-through cacheable
   126     *  var attrs = new MPU.RegionAttrs();
   127     *  MPU.initRegionAttrsMeta(attrs);
   128     *  attrs.enable = true;
   129     *  attrs.bufferable = true;
   130     *  attrs.cacheable = true;
   131     *  attrs.shareable = false;
   132     *  attrs.noExecute = false;
   133     *  attrs.accPerm = 6;  // Read-only at PL1 and PL0
   134     *  attrs.tex = 1;
   135     *
   136     *  // Set attributes for memory region of size 4MB starting at address 0x0
   137     *  // using MPU region Id 0 to store the attributes.
   138     *  MPU.setRegionMeta(0, 0x00000000, MPU.RegionSize_4M, attrs);
   139     *  @p
   140     *
   141     *  @p(html)
   142     *  <h3> Calling Context </h3>
   143     *  <table border="1" cellpadding="3">
   144     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   145     *    </colgroup>
   146     *
   147     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   148     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   149     *    <!--                               -->
   150     *    <tr><td> {@link #disable}     </td><td>   Y    </td><td>   Y    </td>
   151     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   152     *    <tr><td> {@link #enable}      </td><td>   Y    </td><td>   Y    </td>
   153     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   154     *    <tr><td> {@link #initRegionAttrs}  </td><td>   Y    </td><td>   Y    </td>
   155     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   156     *    <tr><td> {@link #isEnabled}  </td><td>   Y    </td><td>   Y    </td>
   157     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   158     *    <tr><td> {@link #setRegion}  </td><td>   Y    </td><td>   Y    </td>
   159     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   160     *    <tr><td colspan="6"> Definitions: <br />
   161     *       <ul>
   162     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   163     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   164     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   165     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   166     *           <ul>
   167     *             <li> In your module startup. </li>
   168     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   169     *             <li> During main().</li>
   170     *             <li> During BIOS.startupFxns.</li>
   171     *           </ul>
   172     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   173     *           <ul>
   174     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   175     *             <li> In your module startup.</li>
   176     *           </ul>
   177     *       </ul>
   178     *    </td></tr>
   179     *
   180     *  </table>
   181     *  @p
   182     */
   183    
   184    @DirectCall
   185    module MPU
   186    {
   187        // -------- ROV views --------
   188    
   189        /*! @_nodoc */
   190        metaonly struct RegionAttrsView {
   191            UInt8       RegionIdx;
   192            Bool        Enabled;
   193            String      BaseAddress;
   194            String      Size;
   195            Bool        Bufferable;
   196            Bool        Cacheable;
   197            Bool        Shareable;
   198            Bool        Noexecute;
   199            String      AccessPerm;
   200            String      Tex;
   201            String      SubregionDisableMask;
   202        };
   203    
   204        @Facet
   205        metaonly config ViewInfo.Instance rovViewInfo =
   206            ViewInfo.create({
   207                viewMap: [
   208                    ['MpuRegionAttrsView', {
   209                        type: ViewInfo.MODULE_DATA,
   210                        viewInitFxn: 'viewMpuRegionAttrs',
   211                        structName: 'RegionAttrsView'
   212                    }],
   213               ]
   214           });
   215    
   216        /*!
   217         *  Memory Protection Unit (MPU) registers. Symbol "MPU_deviceRegs" is
   218         *  a physical device
   219         */
   220        struct DeviceRegs {
   221            UInt32 TYPE;            /*! 0xD90 Type Register                      */
   222            UInt32 CTRL;            /*! 0xD94 Control Register                   */
   223            UInt32 RNR;             /*! 0xD98 Region Register                    */
   224            UInt32 RBAR;            /*! 0xD9C Region Base Address Register       */
   225            UInt32 RASR;            /*! 0xDA0 Region Attribute and Size Register */
   226            UInt32 RBAR_A1;         /*! 0xDA4 MPU Alias 1                        */
   227            UInt32 RASR_A1;         /*! 0xDA8 MPU Alias 1                        */
   228            UInt32 RBAR_A2;         /*! 0xDAC MPU Alias 2                        */
   229            UInt32 RASR_A2;         /*! 0xDB0 MPU Alias 2                        */
   230            UInt32 RBAR_A3;         /*! 0xDB4 MPU Alias 3                        */
   231            UInt32 RASR_A3;         /*! 0xDB8 MPU Alias 3                        */
   232        };
   233    
   234        extern volatile DeviceRegs deviceRegs;
   235    
   236        /*!
   237         *  ======== RegionSize ========
   238         */
   239        enum RegionSize {
   240            RegionSize_32   = 0x8,
   241            RegionSize_64   = 0xA,
   242            RegionSize_128  = 0xC,
   243            RegionSize_256  = 0xE,
   244            RegionSize_512  = 0x10,
   245            RegionSize_1K   = 0x12,
   246            RegionSize_2K   = 0x14,
   247            RegionSize_4K   = 0x16,
   248            RegionSize_8K   = 0x18,
   249            RegionSize_16K  = 0x1A,
   250            RegionSize_32K  = 0x1C,
   251            RegionSize_64K  = 0x1E,
   252            RegionSize_128K = 0x20,
   253            RegionSize_256K = 0x22,
   254            RegionSize_512K = 0x24,
   255            RegionSize_1M   = 0x26,
   256            RegionSize_2M   = 0x28,
   257            RegionSize_4M   = 0x2A,
   258            RegionSize_8M   = 0x2C,
   259            RegionSize_16M  = 0x2E,
   260            RegionSize_32M  = 0x30,
   261            RegionSize_64M  = 0x32,
   262            RegionSize_128M = 0x34,
   263            RegionSize_256M = 0x36,
   264            RegionSize_512M = 0x38,
   265            RegionSize_1G   = 0x3A,
   266            RegionSize_2G   = 0x3C,
   267            RegionSize_4G   = 0x3E
   268        };
   269    
   270    
   271        /*!
   272         *  ======== RegionAttrs ========
   273         *  Structure for setting the region attributes
   274         *
   275         *  The B (Bufferable), C (Cacheable), TEX (Type extension), S (Shareable),
   276         *  XN (No execute or Execute never) and AP (Access permission) bits in the
   277         *  memory region entry define the memory region attributes.
   278         *
   279         *  See the 'Memory region attributes' section in the 'Protected Memory
   280         *  System Architecture (PMSA)' of the ARM v7-AR Architecture Reference
   281         *  Manual for more details.
   282         */
   283        struct RegionAttrs {
   284            Bool  enable;               /*! is MPU region enabled                */
   285            Bool  bufferable;           /*! is memory region bufferable (B)      */
   286            Bool  cacheable;            /*! is memory region cacheable (C)       */
   287            Bool  shareable;            /*! is memory region shareable (S)       */
   288            Bool  noExecute;            /*! is memory region not executable (XN) */
   289            UInt8 accPerm;              /*! access permission bits value 0-7
   290                                            (AP[2:0])                            */
   291            UInt8 tex;                  /*! memory region attr type extension
   292                                            field (TEX[2:0])                     */
   293            UInt8 subregionDisableMask; /*! disable mask for all 8 subregions    */
   294        };
   295    
   296        /*!
   297         *  ======== defaultAttrs ========
   298         *  Default region attributes structure
   299         *
   300         *  The default attributes structure marks the memory region as outer and
   301         *  inner non-cacheable and non-shareable, with read-write access in
   302         *  privileged mode (PL1) only.
   303         */
   304        config RegionAttrs defaultAttrs = {
   305            enable: true,                   /* true by default                   */
   306            bufferable: false,              /* false by default                  */
   307            cacheable: false,               /* false by default                  */
   308            shareable: false,               /* false by default                  */
   309            noExecute: false,               /* false by default                  */
   310            accPerm: 1,                     /* allow read/write access at PL1    */
   311            tex: 1,                         /* 1 by default                      */
   312            subregionDisableMask: 0         /* no subregions disabled by default */
   313        };
   314    
   315        /*!
   316         *  ======== A_nullPointer ========
   317         *  Assert raised when a pointer is null
   318         */
   319        config xdc.runtime.Assert.Id A_nullPointer  = {
   320            msg: "A_nullPointer: Pointer is null"
   321        };
   322    
   323        /*!
   324         *  ======== A_invalidRegionId ========
   325         *  Assert raised when an invalid region number is passed to MPU_setRegion()
   326         */
   327        config xdc.runtime.Assert.Id A_invalidRegionId  = {
   328            msg: "A_invalidRegionId: MPU Region number passed is invalid."
   329        };
   330    
   331        /*!
   332         *  ======== A_unalignedBaseAddr ========
   333         *  Assert raised when region's base address is not aligned to the region's
   334         *  size
   335         */
   336        config xdc.runtime.Assert.Id A_unalignedBaseAddr  = {
   337            msg: "A_unalignedBaseAddr: MPU region base address not aligned to size."
   338        };
   339    
   340        /*!
   341         *  ======== enableMPU ========
   342         *  Configuration parameter to enable MPU.
   343         */
   344        config Bool enableMPU = true;
   345    
   346        /*!
   347         *  ======== enableBackgroundRegion ========
   348         *  Configuration parameter to enable background region.
   349         *
   350         *  If the MPU is enabled and background region is also enabled, any
   351         *  privileged access that does not map to any MPU memory region is
   352         *  handled using the default memory map.
   353         *
   354         *  @p(blist)
   355         *      -See the "Protected Memory System Architecture (PMSA)" chapter
   356         *       in the {@link http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/index.html ARM v7AR Architecture Reference Manual}
   357         *       for more info on the default memory map.
   358         *  @p
   359         */
   360        config Bool enableBackgroundRegion = true;
   361    
   362        /*!
   363         *  @_nodoc
   364         *  ======== numRegions ========
   365         *  Number of MPU regions. Default is determined based on device type.
   366         */
   367        config UInt8 numRegions;
   368    
   369        /*!
   370         *  ======== initRegionAttrsMeta ========
   371         *  Initializes the region attribute structure
   372         *
   373         *   @param(attrs)        Pointer to region attribute struct
   374         */
   375        metaonly Void initRegionAttrsMeta(RegionAttrs *regionAttrs);
   376    
   377        /*!
   378         *  ======== setRegionMeta ========
   379         *  Statically sets the MPU region attributes
   380         *
   381         *  @see ti.sysbios.family.arm.r5.MPU
   382         *
   383         *  @param(regionId)        MPU region number
   384         *  @param(regionBaseAddr)  MPU region base address
   385         *  @param(regionSize)      MPU region size
   386         *  @param(attrs)           Protection attributes
   387         */
   388        metaonly Void setRegionMeta(UInt8 regionId, Ptr regionBaseAddr,
   389            RegionSize regionSize, RegionAttrs attrs);
   390    
   391        /*!
   392         *  ======== disable ========
   393         *  Disables the MPU.
   394         *
   395         *  If the MPU is already disabled, then simply return.
   396         *  Otherwise this function does the following:
   397         *  @p(blist)
   398         *  - If the L1 data cache is enabled, write back invalidate all
   399         *  of L1 data cache.
   400         *  - If the L1 program cache is enabled, invalidate all of L1
   401         *  program cache.
   402         *  @p
   403         *
   404         *  @a(Note)
   405         *  This function does not change the cache L1 data/program settings.
   406         */
   407        Void disable();
   408    
   409        /*!
   410         *  ======== enable ========
   411         *  Enables the MPU.
   412         *
   413         *  If the MPU is already enabled, then simply return.
   414         *  Otherwise this function does the following:
   415         *  @p(blist)
   416         *  If the L1 program cache is enabled, invalidate all of L1
   417         *  program cache.
   418         *  @p
   419         *
   420         *  This function enables the MPU on the core it is called from.
   421         *
   422         *  @a(Note)
   423         *  This function does not change the L1 data/program cache settings.
   424         */
   425        Void enable();
   426    
   427        /*!
   428         *  @_nodoc
   429         *  ======== disableBR ========
   430         *  Disable background region
   431         */
   432        Void disableBR();
   433    
   434        /*!
   435         *  @_nodoc
   436         *  ======== enableBR ========
   437         *  Enable background region
   438         */
   439        Void enableBR();
   440    
   441        /*!
   442         *  ======== initRegionAttrs() ========
   443         *  Initializes the region attribute structure
   444         *
   445         *  @param(attrs)      Pointer to region attribute struct
   446         */
   447        Void initRegionAttrs(RegionAttrs *regionAttrs);
   448    
   449        /*!
   450         *  ======== isEnabled ========
   451         *  Determines if the MPU is enabled
   452         */
   453        Bool isEnabled();
   454    
   455        /*!
   456         *  ======== setRegion ========
   457         *  Sets the MPU region attributes
   458         *
   459         *  @see ti.sysbios.family.arm.r5.MPU
   460         *
   461         *  @param(regionId)        MPU region number
   462         *  @param(regionBaseAddr)  MPU region base address
   463         *  @param(regionSize)      MPU region size
   464         *  @param(attrs)           Protection attributes
   465         */
   466        Void setRegion(UInt8 regionId, Ptr regionBaseAddr,
   467            RegionSize regionSize, RegionAttrs *attrs);
   468    
   469        /*!
   470         *  @_nodoc
   471         *  ======== startup ========
   472         *  startup function to initialize MPU module
   473         */
   474        Void startup();
   475    
   476    internal:
   477    
   478        /*
   479         *  ======== RegionEntry ========
   480         */
   481        struct RegionEntry {
   482            UInt32      baseAddress;
   483            UInt32      sizeAndEnable;
   484            UInt32      regionAttrs;
   485        };
   486    
   487        /*
   488         *  ======== regionEntry ========
   489         *  Array to hold statically configured MPU region entries
   490         */
   491        config RegionEntry regionEntry[];
   492    
   493        /*
   494         *  ======== isMemoryMapped ========
   495         *  Are the MPU registers memory mapped ?
   496         *
   497         *  This internal config param is used to determine whether
   498         *  or not a copy of the memory region settings needs to be
   499         *  maintained in the module state for use by ROV. If the
   500         *  MPU registers are memory mapped then a copy is not required,
   501         *  however, if they are accessed through CP15 regs, a copy is
   502         *  required for ROV.
   503         */
   504        config Bool isMemoryMapped;
   505    
   506        /*
   507         *  ======== disableAsm ========
   508         *  Assembly function to disable the MPU.
   509         */
   510        Void disableAsm();
   511    
   512        /*
   513         *  ======== enableAsm ========
   514         *  Assembly function to enable the MPU.
   515         */
   516        Void enableAsm();
   517    
   518        /*
   519         *  ======== disableBRAsm ========
   520         *  Assembly function to disable background region
   521         */
   522        Void disableBRAsm();
   523    
   524        /*
   525         *  ======== enableBRAsm ========
   526         *  Assembly function to enable background region
   527         */
   528        Void enableBRAsm();
   529    
   530        /*!
   531         *  ======== isEnabledAsm ========
   532         *  Assembly function that determines if the MPU is enabled
   533         */
   534        Bool isEnabledAsm();
   535    
   536        /*
   537         *  ======== setRegionAsm ========
   538         *  Write MPU region base address, size, enable status and protection
   539         *  attributes to respective CP15 registers.
   540         */
   541        Void setRegionAsm(UInt8 regionId, UInt32 regionBaseAddr, UInt32 regionSize,
   542            UInt32 regionAttrs);
   543    
   544        /*! Module state */
   545        struct Module_State {
   546            RegionEntry regionEntry[];  // Array to hold a copy of MPU region
   547                                        // settings
   548        }
   549    }