1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @brief NIOS2 MPU Descriptor |
---|
5 | */ |
---|
6 | |
---|
7 | /* |
---|
8 | * Copyright (c) 2011 embedded brains GmbH. All rights reserved. |
---|
9 | * |
---|
10 | * embedded brains GmbH |
---|
11 | * Obere Lagerstr. 30 |
---|
12 | * 82178 Puchheim |
---|
13 | * Germany |
---|
14 | * <rtems@embedded-brains.de> |
---|
15 | * |
---|
16 | * The license and distribution terms for this file may be |
---|
17 | * found in the file LICENSE in this distribution or at |
---|
18 | * http://www.rtems.org/license/LICENSE. |
---|
19 | */ |
---|
20 | |
---|
21 | #ifdef HAVE_CONFIG_H |
---|
22 | #include "config.h" |
---|
23 | #endif |
---|
24 | |
---|
25 | #include <rtems/score/nios2-utility.h> |
---|
26 | |
---|
27 | static bool _Nios2_Is_power_of_two( uint32_t size ) |
---|
28 | { |
---|
29 | bool ok = false; |
---|
30 | int i = 0; |
---|
31 | |
---|
32 | for ( i = 0; !ok && i < 32; ++i ) { |
---|
33 | ok = size == (1U << i); |
---|
34 | } |
---|
35 | |
---|
36 | return ok; |
---|
37 | } |
---|
38 | |
---|
39 | static bool _Nios2_Is_valid_base_and_end( |
---|
40 | const Nios2_MPU_Configuration *config, |
---|
41 | bool data, |
---|
42 | uint32_t base, |
---|
43 | uint32_t end, |
---|
44 | uint32_t *mask_or_limit |
---|
45 | ) |
---|
46 | { |
---|
47 | uint32_t size = end - base; |
---|
48 | uint32_t end_limit = data ? |
---|
49 | (1U << config->data_address_width) |
---|
50 | : (1U << config->instruction_address_width); |
---|
51 | uint32_t mask = data ? |
---|
52 | ((1U << config->data_region_size_log2)) - 1 |
---|
53 | : ((1U << config->instruction_region_size_log2)) - 1; |
---|
54 | bool ok = base < end && end <= end_limit |
---|
55 | && (base & mask) == 0 && (end & mask) == 0; |
---|
56 | |
---|
57 | if ( config->region_uses_limit ) { |
---|
58 | *mask_or_limit = end; |
---|
59 | } else { |
---|
60 | ok = ok && _Nios2_Is_power_of_two( size ); |
---|
61 | *mask_or_limit = (~(size - 1)) & NIOS2_MPUACC_MASK_MASK; |
---|
62 | } |
---|
63 | |
---|
64 | return ok; |
---|
65 | } |
---|
66 | |
---|
67 | static bool _Nios2_Is_valid_permission( |
---|
68 | bool data, |
---|
69 | int perm |
---|
70 | ) |
---|
71 | { |
---|
72 | int max = data ? 6 : 2; |
---|
73 | |
---|
74 | return 0 <= perm && perm <= max && (!data || (data && perm != 3)); |
---|
75 | } |
---|
76 | |
---|
77 | bool _Nios2_MPU_Setup_region_registers( |
---|
78 | const Nios2_MPU_Configuration *config, |
---|
79 | const Nios2_MPU_Region_descriptor *desc, |
---|
80 | uint32_t *mpubase, |
---|
81 | uint32_t *mpuacc |
---|
82 | ) |
---|
83 | { |
---|
84 | uint32_t base = (uint32_t) desc->base; |
---|
85 | uint32_t end = (uint32_t) desc->end; |
---|
86 | uint32_t mask_or_limit = 0; |
---|
87 | bool is_valid_base_and_end = _Nios2_Is_valid_base_and_end( |
---|
88 | config, |
---|
89 | desc->data, |
---|
90 | base, |
---|
91 | end, |
---|
92 | &mask_or_limit |
---|
93 | ); |
---|
94 | bool ok = is_valid_base_and_end |
---|
95 | && _Nios2_MPU_Is_valid_index( config, desc->index, desc->data ) |
---|
96 | && _Nios2_Is_valid_permission( desc->data, desc->perm ) |
---|
97 | && !(!desc->data && desc->cacheable) |
---|
98 | && !(desc->read && desc->write); |
---|
99 | |
---|
100 | if ( ok ) { |
---|
101 | *mpubase = (base & NIOS2_MPUBASE_BASE_MASK) |
---|
102 | | ((desc->index << NIOS2_MPUBASE_INDEX_OFFSET) & NIOS2_MPUBASE_INDEX_MASK) |
---|
103 | | (desc->data ? NIOS2_MPUBASE_D : 0); |
---|
104 | *mpuacc = mask_or_limit |
---|
105 | | (desc->cacheable ? NIOS2_MPUACC_C : 0) |
---|
106 | | ((desc->perm << NIOS2_MPUACC_PERM_OFFSET) & NIOS2_MPUACC_PERM_MASK) |
---|
107 | | (desc->read ? NIOS2_MPUACC_RD : 0) |
---|
108 | | (desc->write ? NIOS2_MPUACC_WR : 0); |
---|
109 | } |
---|
110 | |
---|
111 | return ok; |
---|
112 | } |
---|
113 | |
---|
114 | bool _Nios2_MPU_Get_region_descriptor( |
---|
115 | const Nios2_MPU_Configuration *config, |
---|
116 | int index, |
---|
117 | bool data, |
---|
118 | Nios2_MPU_Region_descriptor *desc |
---|
119 | ) |
---|
120 | { |
---|
121 | bool ok = _Nios2_MPU_Is_valid_index( config, index, data ); |
---|
122 | |
---|
123 | if ( ok ) { |
---|
124 | uint32_t mpubase; |
---|
125 | uint32_t mpuacc; |
---|
126 | |
---|
127 | _Nios2_MPU_Get_region_registers( index, data, &mpubase, &mpuacc ); |
---|
128 | |
---|
129 | desc->index = index; |
---|
130 | desc->base = (void *) (mpubase & NIOS2_MPUBASE_BASE_MASK); |
---|
131 | if ( config->region_uses_limit ) { |
---|
132 | desc->end = (void *) (mpuacc & NIOS2_MPUACC_LIMIT_MASK); |
---|
133 | } else { |
---|
134 | desc->end = (void *) ((mpuacc & NIOS2_MPUACC_MASK_MASK) + 1); |
---|
135 | } |
---|
136 | desc->perm = (mpuacc & NIOS2_MPUACC_PERM_MASK) >> NIOS2_MPUACC_PERM_OFFSET; |
---|
137 | desc->data = data; |
---|
138 | desc->cacheable = (mpuacc & NIOS2_MPUACC_C) != 0; |
---|
139 | desc->read = (mpuacc & NIOS2_MPUACC_RD) != 0; |
---|
140 | desc->write = (mpuacc & NIOS2_MPUACC_WR) != 0; |
---|
141 | } |
---|
142 | |
---|
143 | return ok; |
---|
144 | } |
---|