blob: 4f59bd36bee7ff8a00590fd4f85750fd85c73854 [file] [log] [blame]
/* Copyright 2018 SiFive, Inc */
/* SPDX-License-Identifier: Apache-2.0 */
#ifndef METAL__INTERRUPT_H
#define METAL__INTERRUPT_H
/*! @file interrupt.h
* @brief API for registering and manipulating interrupts
*/
#include <stddef.h>
/*!
* @brief Possible interrupt controllers
*/
typedef enum metal_interrupt_controller_ {
METAL_CPU_CONTROLLER = 0,
METAL_CLINT_CONTROLLER = 1,
METAL_CLIC_CONTROLLER = 2,
METAL_PLIC_CONTROLLER = 3
} metal_intr_cntrl_type;
/*!
* @brief Possible mode of interrupts to operate
*/
typedef enum metal_vector_mode_ {
METAL_DIRECT_MODE = 0,
METAL_VECTOR_MODE = 1,
METAL_SELECTIVE_NONVECTOR_MODE = 2,
METAL_SELECTIVE_VECTOR_MODE = 3,
METAL_HARDWARE_VECTOR_MODE = 4
} metal_vector_mode;
/*!
* @brief Possible mode of privilege interrupts to operate
*/
typedef enum metal_intr_priv_mode_ {
METAL_INTR_PRIV_M_MODE = 0,
METAL_INTR_PRIV_MU_MODE = 1,
METAL_INTR_PRIV_MSU_MODE = 2
} metal_intr_priv_mode;
/*!
* @brief Function signature for interrupt callback handlers
*/
typedef void (*metal_interrupt_handler_t) (int, void *);
typedef void (*metal_interrupt_vector_handler_t) (void);
struct metal_interrupt;
struct metal_interrupt_vtable {
void (*interrupt_init)(struct metal_interrupt *controller);
int (*interrupt_set_vector_mode)(struct metal_interrupt *controller, metal_vector_mode mode);
metal_vector_mode (*interrupt_get_vector_mode)(struct metal_interrupt *controller);
int (*interrupt_set_privilege)(struct metal_interrupt *controller, metal_intr_priv_mode priv);
metal_intr_priv_mode (*interrupt_get_privilege)(struct metal_interrupt *controller);
int (*interrupt_clear)(struct metal_interrupt *controller, int id);
int (*interrupt_set)(struct metal_interrupt *controller, int id);
int (*interrupt_register)(struct metal_interrupt *controller, int id,
metal_interrupt_handler_t isr, void *priv_data);
int (*interrupt_vector_register)(struct metal_interrupt *controller, int id,
metal_interrupt_vector_handler_t isr, void *priv_data);
int (*interrupt_enable)(struct metal_interrupt *controller, int id);
int (*interrupt_disable)(struct metal_interrupt *controller, int id);
int (*interrupt_vector_enable)(struct metal_interrupt *controller, int id);
int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id);
unsigned int (*interrupt_get_threshold)(struct metal_interrupt *controller);
int (*interrupt_set_threshold)(struct metal_interrupt *controller, unsigned int threshold);
unsigned int (*interrupt_get_priority)(struct metal_interrupt *controller, int id);
int (*interrupt_set_priority)(struct metal_interrupt *controller, int id, unsigned int priority);
int (*command_request)(struct metal_interrupt *controller, int cmd, void *data);
int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time);
};
/*!
* @brief A handle for an interrupt
*/
struct metal_interrupt {
const struct metal_interrupt_vtable *vtable;
};
/*!
* @brief Initialize a given interrupt controller
*
* Initialize a given interrupt controller. This function must be called
* before any interrupts are registered or enabled with the handler. It
* is invalid to initialize an interrupt controller more than once.
*
* @param controller The handle for the interrupt controller
*/
__inline__ void metal_interrupt_init(struct metal_interrupt *controller)
{
controller->vtable->interrupt_init(controller);
}
/*!
* @brief Get the handle for an given interrupt controller type
* @param cntrl The type ofinterrupt controller
* @param id The instance of the interrupt controller
* @return A handle to the interrupt controller (CLINT, CLIC, PLIC), or
* NULL if none is found for the requested label
*/
struct metal_interrupt* metal_interrupt_get_controller(metal_intr_cntrl_type cntrl,
int id);
/*!
* @brief Configure vector mode for an interrupt controller
*
* Configure vector mode for an interrupt controller.
* This function must be called after initialization and before
* configuring individual interrupts, registering ISR.
*
* @param controller The handle for the interrupt controller
* @param mode The vector mode of the interrupt controller.
* @return 0 upon success
*/
__inline__ int metal_interrupt_set_vector_mode(struct metal_interrupt *controller,
metal_vector_mode mode)
{
return controller->vtable->interrupt_set_vector_mode(controller, mode);
}
/*!
* @brief Get vector mode of a given an interrupt controller
*
* Configure vector mode for an interrupt controller.
* This function must be called after initialization and before
* configuring individual interrupts, registering ISR.
*
* @param controller The handle for the interrupt controller
* @param mode The vector mode of the interrupt controller.
* @return The interrupt vector mode
*/
__inline__ metal_vector_mode metal_interrupt_get_vector_mode(struct metal_interrupt *controller)
{
return controller->vtable->interrupt_get_vector_mode(controller);
}
/*!
* @brief Configure privilege mode a of given interrupt controller
*
* Configure privilege mode for a given interrupt controller.
* This function must be called after initialization and before
* configuring individual interrupts, registering ISR.
*
* @param controller The handle for the interrupt controller
* @param privilege The privilege mode of the interrupt controller.
* @return 0 upon success
*/
__inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller,
metal_intr_priv_mode privilege)
{
return controller->vtable->interrupt_set_privilege(controller, privilege);
}
/*!
* @brief Get privilege mode a of given interrupt controller
*
* Get privilege mode for a given interrupt controller.
* This function must be called after initialization and before
* configuring individual interrupts, registering ISR.
*
* @param controller The handle for the interrupt controller
* @return The interrupt privilege mode
*/
__inline__ metal_intr_priv_mode metal_interrupt_get_privilege(struct metal_interrupt *controller)
{
return controller->vtable->interrupt_get_privilege(controller);
}
/*!
* @brief clear an interrupt
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to trigger
* @return 0 upon success
*/
__inline__ int metal_interrupt_clear(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_clear(controller, id);
}
/*!
* @brief Set an interrupt
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to trigger
* @return 0 upon success
*/
__inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_set(controller, id);
}
/*!
* @brief Register an interrupt handler
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to register
* @param handler The interrupt handler callback
* @param priv_data Private data for the interrupt handler
* @return 0 upon success
*/
__inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller,
int id,
metal_interrupt_handler_t handler,
void *priv_data)
{
return controller->vtable->interrupt_register(controller, id, handler, priv_data);
}
/*!
* @brief Register an interrupt vector handler
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to register
* @param handler The interrupt vector handler callback
* @param priv_data Private data for the interrupt handler
* @return 0 upon success
*/
__inline__ int metal_interrupt_register_vector_handler(struct metal_interrupt *controller,
int id,
metal_interrupt_vector_handler_t handler,
void *priv_data)
{
return controller->vtable->interrupt_vector_register(controller, id, handler, priv_data);
}
/*!
* @brief Enable an interrupt
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to enable
* @return 0 upon success
*/
__inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_enable(controller, id);
}
/*!
* @brief Disable an interrupt
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to disable
* @return 0 upon success
*/
__inline__ int metal_interrupt_disable(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_disable(controller, id);
}
/*!
* @brief Set interrupt threshold level
* @param controller The handle for the interrupt controller
* @param threshold The interrupt threshold level
* @return 0 upon success
*/
inline int metal_interrupt_set_threshold(struct metal_interrupt *controller, unsigned int level)
{
return controller->vtable->interrupt_set_threshold(controller, level);
}
/*!
* @brief Get an interrupt threshold level
* @param controller The handle for the interrupt controller
* @return The interrupt threshold level
*/
inline unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller)
{
return controller->vtable->interrupt_get_threshold(controller);
}
/*!
* @brief Set an interrupt priority level
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to enable
* @param priority The interrupt priority level
* @return 0 upon success
*/
inline int metal_interrupt_set_priority(struct metal_interrupt *controller,
int id, unsigned int priority)
{
return controller->vtable->interrupt_set_priority(controller, id, priority);
}
/*!
* @brief Get an interrupt priority level
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to enable
* @return The interrupt priority level
*/
inline unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_get_priority(controller, id);
}
/*!
* @brief Enable an interrupt vector
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to enable
* @return 0 upon success
*/
__inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_vector_enable(controller, id);
}
/*!
* @brief Disable an interrupt vector
* @param controller The handle for the interrupt controller
* @param id The interrupt ID to disable
* @return 0 upon success
*/
__inline__ int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id)
{
return controller->vtable->interrupt_vector_disable(controller, id);
}
/*!
* @brief Default interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_interrupt_vector_handler(void);
/*!
* @brief Metal Software interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler(void);
/*!
* @brief Metal Timer interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler(void);
/*!
* @brief Metal External interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler(void);
/*!
* @brief Metal Local 0 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler(void);
/*!
* @brief Metal Local 1 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler(void);
/*!
* @brief Metal Local 2 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler(void);
/*!
* @brief Metal Local 3 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler(void);
/*!
* @brief Metal Local 4 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler(void);
/*!
* @brief Metal Local 5 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler(void);
/*!
* @brief Metal Local 6 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler(void);
/*!
* @brief Metal Local 7 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler(void);
/*!
* @brief Metal Local 8 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler(void);
/*!
* @brief Metal Local 9 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler(void);
/*!
* @brief Metal Local 10 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler(void);
/*!
* @brief Metal Local 11 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler(void);
/*!
* @brief Metal Local 12 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler(void);
/*!
* @brief Metal Local 13 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler(void);
/*!
* @brief Metal Local 14 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler(void);
/*!
* @brief Metal Local 15 interrupt vector handler, that can be overriden by user
* @param None
* @return None
*/
void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler(void);
/* Utilities function to controll, manages devices via a given interrupt controller */
__inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller,
int cmd, void *data)
{
return controller->vtable->command_request(controller, cmd, data);
}
#endif