125 lines
5.0 KiB
C
Executable File
125 lines
5.0 KiB
C
Executable File
// Copyright 2020-2022 Beken
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef __PLIC_H__
|
|
#define __PLIC_H__
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* PLIC Feature Flags */
|
|
#define NDS_PLIC_FEATURE_PREEMPT (1 << 0)
|
|
#define NDS_PLIC_FEATURE_VECTORED (1 << 1)
|
|
|
|
/* Priority Register - 32 bits per source */
|
|
#define PLIC_PRIORITY_OFFSET (0x00000000UL)
|
|
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
|
|
|
|
/* Pending Register - 1 bit per soirce */
|
|
#define PLIC_PENDING_OFFSET (0x00001000UL)
|
|
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
|
|
|
|
/* Enable Register - 0x80 per target */
|
|
#define PLIC_ENABLE_OFFSET (0x00002000UL)
|
|
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
|
|
|
|
/* Priority Threshold Register - 0x1000 per target */
|
|
#define PLIC_THRESHOLD_OFFSET (0x00200000UL)
|
|
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
|
|
|
|
/* Claim Register - 0x1000 per target */
|
|
#define PLIC_CLAIM_OFFSET (0x00200004UL)
|
|
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
|
|
|
|
|
|
#ifdef NDS_PLIC_BASE
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_set_feature (unsigned int feature)
|
|
{
|
|
volatile unsigned int *feature_ptr = (volatile unsigned int *)NDS_PLIC_BASE;
|
|
*feature_ptr = feature;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_set_priority (unsigned int source, unsigned int priority)
|
|
{
|
|
volatile unsigned int *priority_ptr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_PRIORITY_OFFSET +
|
|
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
|
|
*priority_ptr = priority;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_set_pending (unsigned int source)
|
|
{
|
|
volatile unsigned int *current_ptr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_PENDING_OFFSET +
|
|
((source >> 5) << 2));
|
|
*current_ptr = (1 << (source & 0x1F));
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_enable_interrupt (unsigned int target_id, unsigned int source)
|
|
{
|
|
volatile unsigned int *current_ptr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_ENABLE_OFFSET +
|
|
(target_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
|
((source >> 5) << 2));
|
|
unsigned int current = *current_ptr;
|
|
current = current | (1 << (source & 0x1F));
|
|
*current_ptr = current;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_disable_interrupt (unsigned int target_id, unsigned int source)
|
|
{
|
|
volatile unsigned int *current_ptr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_ENABLE_OFFSET +
|
|
(target_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
|
((source >> 5) << 2));
|
|
unsigned int current = *current_ptr;
|
|
current = current & ~((1 << (source & 0x1F)));
|
|
*current_ptr = current;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_set_threshold (unsigned int target_id, unsigned int threshold)
|
|
{
|
|
volatile unsigned int *threshold_ptr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_THRESHOLD_OFFSET +
|
|
(target_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
|
*threshold_ptr = threshold;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline unsigned int __nds__plic_claim_interrupt(unsigned int target_id)
|
|
{
|
|
volatile unsigned int *claim_addr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_CLAIM_OFFSET +
|
|
(target_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
|
return *claim_addr;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline void __nds__plic_complete_interrupt(unsigned int target_id, unsigned int source)
|
|
{
|
|
volatile unsigned int *claim_addr = (volatile unsigned int *)(NDS_PLIC_BASE +
|
|
PLIC_CLAIM_OFFSET +
|
|
(target_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
|
*claim_addr = source;
|
|
}
|
|
|
|
#endif // NDS_PLIC_BASE
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif // __PLIC_H__
|
|
|