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