/* * interrupt.c * * Copyright (c) 2020 Semidrive Semiconductor. * All rights reserved. * * Description: interrupt driver. * * Revision History: * ----------------- */ #if CONFIG_IRQ #include #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 */