source: rtems/cpukit/score/cpu/nios2/include/rtems/score/nios2-utility.h @ 4b5e64a

Last change on this file since 4b5e64a was 4b5e64a, checked in by Joel Sherrill <joel@…>, on 02/16/22 at 22:51:56

score/cpu/nios2: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 14.6 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @brief NIOS II Utility
7 */
8/*
9 * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
10 *
11 *  embedded brains GmbH
12 *  Obere Lagerstr. 30
13 *  82178 Puchheim
14 *  Germany
15 *  <rtems@embedded-brains.de>
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#ifndef _RTEMS_SCORE_NIOS2_UTILITY_H
40#define _RTEMS_SCORE_NIOS2_UTILITY_H
41
42#define NIOS2_CTLREG_INDEX_STATUS 0
43#define NIOS2_CTLREG_INDEX_ESTATUS 1
44#define NIOS2_CTLREG_INDEX_BSTATUS 2
45#define NIOS2_CTLREG_INDEX_IENABLE 3
46#define NIOS2_CTLREG_INDEX_IPENDING 4
47#define NIOS2_CTLREG_INDEX_CPUID 5
48#define NIOS2_CTLREG_INDEX_EXCEPTION 7
49#define NIOS2_CTLREG_INDEX_PTEADDR 8
50#define NIOS2_CTLREG_INDEX_TLBACC 9
51#define NIOS2_CTLREG_INDEX_TLBMISC 10
52#define NIOS2_CTLREG_INDEX_BADADDR 12
53#define NIOS2_CTLREG_INDEX_CONFIG 13
54#define NIOS2_CTLREG_INDEX_MPUBASE 14
55#define NIOS2_CTLREG_INDEX_MPUACC 15
56
57#define NIOS2_CONTEXT_OFFSET_R16 0
58#define NIOS2_CONTEXT_OFFSET_R17 4
59#define NIOS2_CONTEXT_OFFSET_R18 8
60#define NIOS2_CONTEXT_OFFSET_R19 12
61#define NIOS2_CONTEXT_OFFSET_R20 16
62#define NIOS2_CONTEXT_OFFSET_R21 20
63#define NIOS2_CONTEXT_OFFSET_R22 24
64#define NIOS2_CONTEXT_OFFSET_R23 28
65#define NIOS2_CONTEXT_OFFSET_FP 32
66#define NIOS2_CONTEXT_OFFSET_STATUS 36
67#define NIOS2_CONTEXT_OFFSET_SP 40
68#define NIOS2_CONTEXT_OFFSET_RA 44
69#define NIOS2_CONTEXT_OFFSET_ISR_DISPATCH_DISABLE 48
70#define NIOS2_CONTEXT_OFFSET_STACK_MPUBASE 52
71#define NIOS2_CONTEXT_OFFSET_STACK_MPUACC 56
72
73#define NIOS2_ISR_STATUS_MASK_IIC 0xfffffffe
74#define NIOS2_ISR_STATUS_BITS_IIC 0x00000000
75
76#define NIOS2_ISR_STATUS_MASK_EIC_IL 0xfffffc0f
77#define NIOS2_ISR_STATUS_BITS_EIC_IL 0x000003f0
78
79#define NIOS2_ISR_STATUS_MASK_EIC_RSIE 0xf7ffffff
80#define NIOS2_ISR_STATUS_BITS_EIC_RSIE 0x00000000
81
82#define NIOS2_STATUS_RSIE (1 << 23)
83#define NIOS2_STATUS_NMI (1 << 22)
84#define NIOS2_STATUS_PRS_OFFSET 16
85#define NIOS2_STATUS_PRS_MASK (0x3f << NIOS2_STATUS_PRS_OFFSET)
86#define NIOS2_STATUS_CRS_OFFSET 10
87#define NIOS2_STATUS_CRS_MASK (0x3f << NIOS2_STATUS_CRS_OFFSET)
88#define NIOS2_STATUS_IL_OFFSET 4
89#define NIOS2_STATUS_IL_MASK (0x3f << NIOS2_STATUS_IL_OFFSET)
90#define NIOS2_STATUS_IH (1 << 3)
91#define NIOS2_STATUS_EH (1 << 2)
92#define NIOS2_STATUS_U (1 << 1)
93#define NIOS2_STATUS_PIE (1 << 0)
94
95#define NIOS2_EXCEPTION_CAUSE_OFFSET 2
96#define NIOS2_EXCEPTION_CAUSE_MASK (0x1f << NIOS2_EXCEPTION_CAUSE_OFFSET)
97
98#define NIOS2_PTEADDR_PTBASE_OFFSET 22
99#define NIOS2_PTEADDR_PTBASE_MASK (0x3ff << NIOS2_PTEADDR_PTBASE_OFFSET)
100#define NIOS2_PTEADDR_VPN_OFFSET 2
101#define NIOS2_PTEADDR_VPN_MASK (0xfffff << NIOS2_PTEADDR_VPN_OFFSET)
102
103#define NIOS2_TLBACC_IG_OFFSET 25
104#define NIOS2_TLBACC_IG_MASK (0x3ff << NIOS2_TLBACC_IG_OFFSET)
105#define NIOS2_TLBACC_C (1 << 24)
106#define NIOS2_TLBACC_R (1 << 23)
107#define NIOS2_TLBACC_W (1 << 22)
108#define NIOS2_TLBACC_X (1 << 21)
109#define NIOS2_TLBACC_G (1 << 20)
110#define NIOS2_TLBACC_PFN_OFFSET 2
111#define NIOS2_TLBACC_PFN_MASK (0xfffff << NIOS2_TLBACC_PFN_OFFSET)
112
113#define NIOS2_TLBMISC_WAY_OFFSET 20
114#define NIOS2_TLBMISC_WAY_MASK (0xf << NIOS2_TLBMISC_WAY_OFFSET)
115#define NIOS2_TLBMISC_RD (1 << 19)
116#define NIOS2_TLBMISC_WE (1 << 18)
117#define NIOS2_TLBMISC_PID_OFFSET 5
118#define NIOS2_TLBMISC_PID_MASK (0x3fff << NIOS2_TLBMISC_PID_OFFSET)
119#define NIOS2_TLBMISC_DBL (1 << 3)
120#define NIOS2_TLBMISC_BAD (1 << 2)
121#define NIOS2_TLBMISC_PERM (1 << 1)
122#define NIOS2_TLBMISC_D (1 << 0)
123
124#define NIOS2_CONFIG_ANI (1 << 1)
125#define NIOS2_CONFIG_PE (1 << 0)
126
127#define NIOS2_MPUBASE_BASE_OFFSET 6
128#define NIOS2_MPUBASE_BASE_MASK (0x1ffffff << NIOS2_MPUBASE_BASE_OFFSET)
129#define NIOS2_MPUBASE_INDEX_OFFSET 1
130
131/* Avoid redefines with Altera HAL */
132#define NIOS2_MPUBASE_INDEX_MASK (0x0000003e)
133
134#define NIOS2_MPUBASE_D (1 << 0)
135
136#define NIOS2_MPUACC_MASK_OFFSET 6
137
138/* Avoid redefines with Altera HAL */
139#define NIOS2_MPUACC_MASK_MASK (0x7fffffc0)
140
141#define NIOS2_MPUACC_LIMIT_OFFSET 6
142
143/* Avoid redefines with Altera HAL */
144#define NIOS2_MPUACC_LIMIT_MASK (0xffffffc0)
145
146#define NIOS2_MPUACC_C (1 << 5)
147#define NIOS2_MPUACC_PERM_OFFSET 2
148
149/* Avoid redefines with Altera HAL */
150#define NIOS2_MPUACC_PERM_MASK (0x0000001c)
151
152#define NIOS2_MPUACC_RD (1 << 1)
153#define NIOS2_MPUACC_WR (1 << 0)
154
155#ifndef ASM
156
157#include <stddef.h>
158#include <stdint.h>
159#include <stdbool.h>
160
161#ifdef __cplusplus
162extern "C" {
163#endif /* __cplusplus */
164
165/**
166 * @brief This global symbol specifies the status register mask used to disable
167 * interrupts.
168 *
169 * The board support package must provide a global symbol with this name to
170 * specify the status register mask used in _CPU_ISR_Disable().
171 */
172extern char _Nios2_ISR_Status_mask [];
173
174/**
175 * @brief This symbol specifies the status register bits used to disable
176 * interrupts.
177 *
178 * The board support package must provide a global symbol with this name to
179 * specify the status register bits used in _CPU_ISR_Disable().
180 */
181extern char _Nios2_ISR_Status_bits [];
182
183static inline void _Nios2_Flush_pipeline( void )
184{
185  __asm__ volatile ("flushp");
186}
187
188static inline uint32_t _Nios2_Get_ctlreg_status( void )
189{
190  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_STATUS );
191}
192
193static inline void _Nios2_Set_ctlreg_status( uint32_t value )
194{
195  __builtin_wrctl( NIOS2_CTLREG_INDEX_STATUS, (int) value );
196}
197
198static inline uint32_t _Nios2_Get_ctlreg_estatus( void )
199{
200  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_ESTATUS );
201}
202
203static inline void _Nios2_Set_ctlreg_estatus( uint32_t value )
204{
205  __builtin_wrctl( NIOS2_CTLREG_INDEX_ESTATUS, (int) value );
206}
207
208static inline uint32_t _Nios2_Get_ctlreg_bstatus( void )
209{
210  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_BSTATUS );
211}
212
213static inline void _Nios2_Set_ctlreg_bstatus( uint32_t value )
214{
215  __builtin_wrctl( NIOS2_CTLREG_INDEX_BSTATUS, (int) value );
216}
217
218static inline uint32_t _Nios2_Get_ctlreg_ienable( void )
219{
220  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_IENABLE );
221}
222
223static inline void _Nios2_Set_ctlreg_ienable( uint32_t value )
224{
225  __builtin_wrctl( NIOS2_CTLREG_INDEX_IENABLE, (int) value );
226}
227
228static inline uint32_t _Nios2_Get_ctlreg_ipending( void )
229{
230  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_IPENDING );
231}
232
233static inline uint32_t _Nios2_Get_ctlreg_cpuid( void )
234{
235  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_CPUID );
236}
237
238static inline uint32_t _Nios2_Get_ctlreg_exception( void )
239{
240  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_EXCEPTION );
241}
242
243static inline uint32_t _Nios2_Get_ctlreg_pteaddr( void )
244{
245  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_PTEADDR );
246}
247
248static inline void _Nios2_Set_ctlreg_pteaddr( uint32_t value )
249{
250  __builtin_wrctl( NIOS2_CTLREG_INDEX_PTEADDR, (int) value );
251}
252
253static inline uint32_t _Nios2_Get_ctlreg_tlbacc( void )
254{
255  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_TLBACC );
256}
257
258static inline void _Nios2_Set_ctlreg_tlbacc( uint32_t value )
259{
260  __builtin_wrctl( NIOS2_CTLREG_INDEX_TLBACC, (int) value );
261}
262
263static inline uint32_t _Nios2_Get_ctlreg_tlbmisc( void )
264{
265  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_TLBMISC );
266}
267
268static inline void _Nios2_Set_ctlreg_tlbmisc( uint32_t value )
269{
270  __builtin_wrctl( NIOS2_CTLREG_INDEX_TLBMISC, (int) value );
271}
272
273static inline uint32_t _Nios2_Get_ctlreg_badaddr( void )
274{
275  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_BADADDR );
276}
277
278static inline uint32_t _Nios2_Get_ctlreg_config( void )
279{
280  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_CONFIG );
281}
282
283static inline void _Nios2_Set_ctlreg_config( uint32_t value )
284{
285  __builtin_wrctl( NIOS2_CTLREG_INDEX_CONFIG, (int) value );
286}
287
288static inline uint32_t _Nios2_Get_ctlreg_mpubase( void )
289{
290  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_MPUBASE );
291}
292
293static inline void _Nios2_Set_ctlreg_mpubase( uint32_t value )
294{
295  __builtin_wrctl( NIOS2_CTLREG_INDEX_MPUBASE, (int) value );
296}
297
298static inline uint32_t _Nios2_Get_ctlreg_mpuacc( void )
299{
300  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_MPUACC );
301}
302
303static inline void _Nios2_Set_ctlreg_mpuacc( uint32_t value )
304{
305  __builtin_wrctl( NIOS2_CTLREG_INDEX_MPUACC, (int) value );
306}
307
308static inline uint32_t _Nios2_ISR_Get_status_mask( void )
309{
310  return (uint32_t) &_Nios2_ISR_Status_mask [0];
311}
312
313static inline uint32_t _Nios2_ISR_Get_status_bits( void )
314{
315  return (uint32_t) &_Nios2_ISR_Status_bits [0];
316}
317
318static inline bool _Nios2_Has_internal_interrupt_controller( void )
319{
320  return _Nios2_ISR_Get_status_mask() == NIOS2_ISR_STATUS_MASK_IIC;
321}
322
323uint32_t _Nios2_ISR_Set_level( uint32_t new_level, uint32_t status );
324
325typedef struct {
326  int data_address_width;
327  int instruction_address_width;
328  int data_region_size_log2;
329  int instruction_region_size_log2;
330  int data_region_count;
331  int instruction_region_count;
332  int data_index_for_stack_protection;
333  bool region_uses_limit;
334  bool enable_data_cache_for_stack;
335} Nios2_MPU_Configuration;
336
337void _Nios2_MPU_Set_configuration( const Nios2_MPU_Configuration *config );
338
339const Nios2_MPU_Configuration *_Nios2_MPU_Get_configuration( void );
340
341typedef enum {
342  NIOS2_MPU_INST_PERM_SVR_NONE_USER_NONE = 0,
343  NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_NONE,
344  NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_EXECUTE,
345  NIOS2_MPU_DATA_PERM_SVR_NONE_USER_NONE = 0,
346  NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_NONE,
347  NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_READONLY,
348  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE = 4,
349  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_READONLY,
350  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_READWRITE
351} Nios2_MPU_Region_permissions;
352
353typedef struct {
354  int index;
355  const void *base;
356  const void *end;
357  Nios2_MPU_Region_permissions perm;
358  bool data;
359  bool cacheable;
360  bool read;
361  bool write;
362} Nios2_MPU_Region_descriptor;
363
364#define NIOS2_MPU_REGION_DESC_INST( index, base, end ) \
365  { \
366    (index), (base), (end), NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_NONE, \
367    false, false, false, true \
368  }
369
370#define NIOS2_MPU_REGION_DESC_DATA_RO( index, base, end ) \
371  { \
372    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_NONE, \
373    true, true, false, true \
374  }
375
376#define NIOS2_MPU_REGION_DESC_DATA_RW( index, base, end ) \
377  { \
378    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE, \
379    true, true, false, true \
380  }
381
382#define NIOS2_MPU_REGION_DESC_DATA_IO( index, base, end ) \
383  { \
384    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE, \
385    true, false, false, true \
386  }
387
388static inline int _Nios2_MPU_Get_region_count(
389  const Nios2_MPU_Configuration *config,
390  bool data
391)
392{
393  return data ?
394    config->data_region_count
395      : config->instruction_region_count;
396}
397
398static inline bool _Nios2_MPU_Is_valid_index(
399  const Nios2_MPU_Configuration *config,
400  int index,
401  bool data
402)
403{
404  return 0 <= index
405    && index < _Nios2_MPU_Get_region_count( config, data );
406}
407
408bool _Nios2_MPU_Setup_region_registers(
409  const Nios2_MPU_Configuration *config,
410  const Nios2_MPU_Region_descriptor *desc,
411  uint32_t *mpubase,
412  uint32_t *mpuacc
413);
414
415bool _Nios2_MPU_Get_region_descriptor(
416  const Nios2_MPU_Configuration *config,
417  int index,
418  bool data,
419  Nios2_MPU_Region_descriptor *desc
420);
421
422/**
423 * @brief Searches the region table part for a disabled region.
424 *
425 * The table will be searched between indices @a begin and @a end.  The @a end
426 * index is not part of the search range.  If @a end is negative, then the
427 * region count will be used.  Thus a @a begin of 0 and a @a end of -1 will
428 * specify the complete table.
429 *
430 * @retval -1 No disabled region is available.
431 * @retval other Index of disabled region.
432 */
433int _Nios2_MPU_Get_disabled_region_index(
434  const Nios2_MPU_Configuration *config,
435  bool data,
436  int begin,
437  int end
438);
439
440/**
441 * @brief Adds a region according to region descriptor @a desc.
442 *
443 * If @a force is true, then an enabled region will be overwritten.
444 *
445 * @retval true Successful operation.
446 * @retval false Invalid region descriptor or region already in use.
447 */
448bool _Nios2_MPU_Add_region(
449  const Nios2_MPU_Configuration *config,
450  const Nios2_MPU_Region_descriptor *desc,
451  bool force
452);
453
454static inline void _Nios2_MPU_Get_region_registers(
455  int index,
456  bool data,
457  uint32_t *mpubase,
458  uint32_t *mpuacc
459)
460{
461  uint32_t base = (uint32_t)
462    (((index << NIOS2_MPUBASE_INDEX_OFFSET) & NIOS2_MPUBASE_INDEX_MASK)
463      | (data ? NIOS2_MPUBASE_D : 0));
464
465  _Nios2_Set_ctlreg_mpubase( base );
466  _Nios2_Set_ctlreg_mpuacc( NIOS2_MPUACC_RD );
467  _Nios2_Flush_pipeline();
468  *mpubase = _Nios2_Get_ctlreg_mpubase() | base;
469  *mpuacc = _Nios2_Get_ctlreg_mpuacc();
470}
471
472static inline void _Nios2_MPU_Set_region_registers(
473  uint32_t mpubase,
474  uint32_t mpuacc
475)
476{
477  _Nios2_Set_ctlreg_mpubase( mpubase );
478  _Nios2_Set_ctlreg_mpuacc( mpuacc );
479  _Nios2_Flush_pipeline();
480}
481
482static inline void _Nios2_MPU_Enable( void )
483{
484  uint32_t config = _Nios2_Get_ctlreg_config();
485
486  _Nios2_Set_ctlreg_config( config | NIOS2_CONFIG_PE );
487}
488
489static inline uint32_t _Nios2_MPU_Disable( void )
490{
491  uint32_t config = _Nios2_Get_ctlreg_config();
492  uint32_t config_pe = NIOS2_CONFIG_PE;
493
494  _Nios2_Set_ctlreg_config( config & ~config_pe );
495
496  return config;
497}
498
499static inline void _Nios2_MPU_Restore( uint32_t config )
500{
501  _Nios2_Set_ctlreg_config( config );
502}
503
504uint32_t _Nios2_MPU_Disable_protected( void );
505
506void _Nios2_MPU_Reset( const Nios2_MPU_Configuration *config );
507
508#ifdef __cplusplus
509}
510#endif /* __cplusplus */
511
512#else /* ASM */
513
514        .macro  NIOS2_ASM_DISABLE_INTERRUPTS new_status, current_status
515        movhi   \new_status, %hiadj(_Nios2_ISR_Status_mask)
516        addi    \new_status, \new_status, %lo(_Nios2_ISR_Status_mask)
517        and     \new_status, \current_status, \new_status
518        ori     \new_status, \new_status, %lo(_Nios2_ISR_Status_bits)
519        wrctl   status, \new_status
520        .endm
521
522#endif /* ASM */
523
524#endif /* _RTEMS_SCORE_NIOS2_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.