Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:25

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief NIOS2 MPU Descriptor
0007  */
0008 
0009 /*
0010  * Copyright (c) 2011 embedded brains GmbH & Co. KG
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 #ifdef HAVE_CONFIG_H
0035 #include "config.h"
0036 #endif
0037 
0038 #include <rtems/score/nios2-utility.h>
0039 
0040 static bool _Nios2_Is_power_of_two( uint32_t size )
0041 {
0042   bool ok = false;
0043   int i = 0;
0044 
0045   for ( i = 0; !ok && i < 32; ++i ) {
0046     ok = size == (1U << i);
0047   }
0048 
0049   return ok;
0050 }
0051 
0052 static bool _Nios2_Is_valid_base_and_end(
0053   const Nios2_MPU_Configuration *config,
0054   bool data,
0055   uint32_t base,
0056   uint32_t end,
0057   uint32_t *mask_or_limit
0058 )
0059 {
0060   uint32_t size = end - base;
0061   uint32_t end_limit = data ?
0062     (1U << config->data_address_width)
0063       : (1U << config->instruction_address_width);
0064   uint32_t mask = data ?
0065     ((1U << config->data_region_size_log2)) - 1
0066       : ((1U << config->instruction_region_size_log2)) - 1;
0067   bool ok = base < end && end <= end_limit
0068     && (base & mask) == 0 && (end & mask) == 0;
0069 
0070   if ( config->region_uses_limit ) {
0071     *mask_or_limit = end;
0072   } else {
0073     ok = ok && _Nios2_Is_power_of_two( size );
0074     *mask_or_limit = (~(size - 1)) & NIOS2_MPUACC_MASK_MASK;
0075   }
0076 
0077   return ok;
0078 }
0079 
0080 static bool _Nios2_Is_valid_permission(
0081   bool data,
0082   int perm
0083 )
0084 {
0085   int max = data ? 6 : 2;
0086 
0087   return 0 <= perm && perm <= max && (!data || (data && perm != 3));
0088 }
0089 
0090 bool _Nios2_MPU_Setup_region_registers(
0091   const Nios2_MPU_Configuration *config,
0092   const Nios2_MPU_Region_descriptor *desc,
0093   uint32_t *mpubase,
0094   uint32_t *mpuacc
0095 )
0096 {
0097   uint32_t base = (uint32_t) desc->base;
0098   uint32_t end = (uint32_t) desc->end;
0099   uint32_t mask_or_limit = 0;
0100   bool is_valid_base_and_end = _Nios2_Is_valid_base_and_end(
0101     config,
0102     desc->data,
0103     base,
0104     end,
0105     &mask_or_limit
0106   );
0107   bool ok = is_valid_base_and_end
0108     && _Nios2_MPU_Is_valid_index( config, desc->index, desc->data )
0109     && _Nios2_Is_valid_permission( desc->data, desc->perm )
0110     && !(!desc->data && desc->cacheable)
0111     && !(desc->read && desc->write);
0112 
0113   if ( ok ) {
0114     *mpubase = (base & NIOS2_MPUBASE_BASE_MASK)
0115       | ((desc->index << NIOS2_MPUBASE_INDEX_OFFSET) & NIOS2_MPUBASE_INDEX_MASK)
0116       | (desc->data ? NIOS2_MPUBASE_D : 0);
0117     *mpuacc = mask_or_limit
0118       | (desc->cacheable ? NIOS2_MPUACC_C : 0)
0119       | ((desc->perm << NIOS2_MPUACC_PERM_OFFSET) & NIOS2_MPUACC_PERM_MASK)
0120       | (desc->read ? NIOS2_MPUACC_RD : 0)
0121       | (desc->write ? NIOS2_MPUACC_WR : 0);
0122   }
0123 
0124   return ok;
0125 }
0126 
0127 bool _Nios2_MPU_Get_region_descriptor(
0128   const Nios2_MPU_Configuration *config,
0129   int index,
0130   bool data,
0131   Nios2_MPU_Region_descriptor *desc
0132 )
0133 {
0134   bool ok = _Nios2_MPU_Is_valid_index( config, index, data );
0135 
0136   if ( ok ) {
0137     uint32_t mpubase;
0138     uint32_t mpuacc;
0139 
0140     _Nios2_MPU_Get_region_registers( index, data, &mpubase, &mpuacc );
0141 
0142     desc->index = index;
0143     desc->base = (void *) (mpubase & NIOS2_MPUBASE_BASE_MASK);
0144     if ( config->region_uses_limit ) {
0145       desc->end = (void *) (mpuacc & NIOS2_MPUACC_LIMIT_MASK);
0146     } else {
0147       desc->end = (void *) ((mpuacc & NIOS2_MPUACC_MASK_MASK) + 1);
0148     }
0149     desc->perm = (mpuacc & NIOS2_MPUACC_PERM_MASK) >> NIOS2_MPUACC_PERM_OFFSET;
0150     desc->data = data;
0151     desc->cacheable = (mpuacc & NIOS2_MPUACC_C) != 0;
0152     desc->read = (mpuacc & NIOS2_MPUACC_RD) != 0;
0153     desc->write = (mpuacc & NIOS2_MPUACC_WR) != 0;
0154   }
0155 
0156   return ok;
0157 }