211 lines
3.9 KiB
C
211 lines
3.9 KiB
C
/*
|
|
* interrupt.c
|
|
*
|
|
* Copyright (c) 2020 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*
|
|
* Description: interrupt driver.
|
|
*
|
|
* Revision History:
|
|
* -----------------
|
|
*/
|
|
|
|
#if CONFIG_IRQ
|
|
|
|
#include <types.h>
|
|
|
|
#include "armv7-r/cache.h"
|
|
#include "armv7-r/irq.h"
|
|
#include "core_id.h"
|
|
#include "irq.h"
|
|
#include "irq_num.h"
|
|
#include "sdrv_vic.h"
|
|
|
|
/* irq info type */
|
|
struct irq_info_s {
|
|
irq_handler handler; /* Address of the interrupt handler */
|
|
void *arg; /* The argument provided to the interrupt handler. */
|
|
};
|
|
|
|
struct irq_table {
|
|
struct irq_info_s irq_info[IRQ_MAX_INTR_NUM];
|
|
} __CACHE_ALIGN;
|
|
|
|
/* int table */
|
|
static struct irq_table g_irq_table[CORE_NUM_SMP];
|
|
|
|
static int irq_handle(uint32_t irq)
|
|
{
|
|
if (irq < IRQ_MAX_INTR_NUM) {
|
|
int core_id = get_core_id_smp();
|
|
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
|
|
if (irq_info->handler) {
|
|
return irq_info->handler(irq, irq_info->arg);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize interruppt controller.
|
|
*
|
|
* @param [in] base base address.
|
|
* @param [in] intr_num number of interrupts.
|
|
*/
|
|
void irq_initialize(uint32_t base, uint32_t intr_num)
|
|
{
|
|
irq_lld_initialize(base, intr_num, irq_handle);
|
|
arch_irq_enable();
|
|
}
|
|
|
|
/**
|
|
* @brief Interrupt attach.
|
|
*
|
|
* @param [in] irq IRQ number.
|
|
* @param [in] handler Pointer to function.
|
|
* @arg [in] arg parameter of handler.
|
|
* @return int Return zero after attach set;
|
|
*/
|
|
int irq_attach(uint32_t irq, irq_handler handler, void *arg)
|
|
{
|
|
int ret = -1;
|
|
|
|
if (irq < IRQ_MAX_INTR_NUM) {
|
|
int core_id = get_core_id_smp();
|
|
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
|
|
|
|
IRQ_SAVE
|
|
|
|
irq_info->handler = handler;
|
|
irq_info->arg = arg;
|
|
|
|
irq_lld_set_priority(irq, DEFAULT_IRQ_PRIORITY);
|
|
|
|
IRQ_RESTORE
|
|
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Interrupt datach.
|
|
*
|
|
* @param [in] irq IRQ number.
|
|
* @return int Return zero after datach set succesfully;
|
|
*/
|
|
int irq_detach(uint32_t irq)
|
|
{
|
|
int ret = -1;
|
|
|
|
if (irq < IRQ_MAX_INTR_NUM) {
|
|
int core_id = get_core_id_smp();
|
|
struct irq_info_s *irq_info = &g_irq_table[core_id].irq_info[irq];
|
|
|
|
IRQ_SAVE
|
|
|
|
irq_lld_disable(irq);
|
|
|
|
irq_info->handler = NULL;
|
|
irq_info->arg = NULL;
|
|
|
|
IRQ_RESTORE
|
|
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Interrupt disptach.
|
|
*
|
|
*/
|
|
int irq_dispatch(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
uint32_t irq = irq_lld_acknowledge();
|
|
|
|
ret = irq_handle(irq);
|
|
|
|
irq_lld_complete(irq);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief irq enable.
|
|
*
|
|
* @param [in] irq irq number.
|
|
*/
|
|
void irq_enable(uint32_t irq)
|
|
{
|
|
irq_lld_enable(irq);
|
|
}
|
|
|
|
/**
|
|
* @brief irq disable.
|
|
*
|
|
* @param [in] irq number.
|
|
*/
|
|
void irq_disable(uint32_t irq)
|
|
{
|
|
irq_lld_disable(irq);
|
|
}
|
|
|
|
/**
|
|
* @brief interrupt set priority mask.
|
|
*
|
|
* @param [in]mask int priority mask.
|
|
* @return mask old int priority mask.
|
|
*/
|
|
uint32_t irq_mask(uint32_t mask)
|
|
{
|
|
return irq_lld_mask(mask);
|
|
}
|
|
|
|
/**
|
|
* @brief interrupt unmask all int.
|
|
*/
|
|
void irq_unmask(void)
|
|
{
|
|
irq_lld_unmask();
|
|
}
|
|
|
|
/**
|
|
* @brief set irq priority.
|
|
*
|
|
* @param [in] irq irq number.
|
|
* @param [in] priority irq priority.
|
|
*/
|
|
void irq_set_priority(uint32_t irq, uint32_t priority)
|
|
{
|
|
irq_lld_set_priority(irq, priority);
|
|
}
|
|
|
|
/**
|
|
* @brief get irq priority.
|
|
*
|
|
* @param [in] irq irq number.
|
|
* @return int irq priority.
|
|
*/
|
|
int irq_get_priority(uint32_t irq)
|
|
{
|
|
return irq_lld_get_priority(irq);
|
|
}
|
|
|
|
/**
|
|
* @brief interrupt get current int priority.
|
|
*
|
|
* @return int priority.
|
|
*/
|
|
uint32_t irq_get_current_priority(void)
|
|
{
|
|
return irq_lld_get_current_priority();
|
|
}
|
|
|
|
#endif /* CONFIG_IRQ */
|