blob: e4f67c4268ecc1cc5f432fa6501f7018c5a5c148 [file] [log] [blame]
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <xtensa_api.h>
#include <xtensa/xtruntime.h>
#include <logging/sys_log.h>
#include <board.h>
#include <irq_nextlevel.h>
void _soc_irq_enable(u32_t irq)
{
struct device *dev_cavs, *dev_ictl;
switch (XTENSA_IRQ_NUMBER(irq)) {
case CAVS_ICTL_0_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_0_NAME);
break;
case CAVS_ICTL_1_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_1_NAME);
break;
case CAVS_ICTL_2_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_2_NAME);
break;
case CAVS_ICTL_3_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_3_NAME);
break;
default:
/* regular interrupt */
_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq));
return;
}
if (!dev_cavs) {
SYS_LOG_DBG("board: CAVS device binding failed\n");
return;
}
/* If the control comes here it means the specified interrupt
* is in either CAVS interrupt logic or DW interrupt controller
*/
_xtensa_irq_enable(XTENSA_IRQ_NUMBER(irq));
switch (CAVS_IRQ_NUMBER(irq)) {
case DW_ICTL_IRQ_CAVS_OFFSET:
dev_ictl = device_get_binding(CONFIG_DW_ICTL_NAME);
break;
default:
/* The source of the interrupt is in CAVS interrupt logic */
irq_enable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq));
return;
}
if (!dev_ictl) {
SYS_LOG_DBG("board: DW intr_control device binding failed\n");
return;
}
/* If the control comes here it means the specified interrupt
* is in DW interrupt controller
*/
irq_enable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq));
/* Manipulate the relevant bit in the interrupt controller
* register as needed
*/
irq_enable_next_level(dev_ictl, INTR_CNTL_IRQ_NUM(irq));
}
void _soc_irq_disable(u32_t irq)
{
struct device *dev_cavs, *dev_ictl;
switch (XTENSA_IRQ_NUMBER(irq)) {
case CAVS_ICTL_0_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_0_NAME);
break;
case CAVS_ICTL_1_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_1_NAME);
break;
case CAVS_ICTL_2_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_2_NAME);
break;
case CAVS_ICTL_3_IRQ:
dev_cavs = device_get_binding(CONFIG_CAVS_ICTL_3_NAME);
break;
default:
/* regular interrupt */
_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
return;
}
if (!dev_cavs) {
SYS_LOG_DBG("board: CAVS device binding failed\n");
return;
}
/* If the control comes here it means the specified interrupt
* is in either CAVS interrupt logic or DW interrupt controller
*/
switch (CAVS_IRQ_NUMBER(irq)) {
case DW_ICTL_IRQ_CAVS_OFFSET:
dev_ictl = device_get_binding(CONFIG_DW_ICTL_NAME);
break;
default:
/* The source of the interrupt is in CAVS interrupt logic */
irq_disable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq));
/* Disable the parent IRQ if all children are disabled */
if (!irq_is_enabled_next_level(dev_cavs)) {
_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
}
return;
}
if (!dev_ictl) {
SYS_LOG_DBG("board: DW intr_control device binding failed\n");
return;
}
/* If the control comes here it means the specified interrupt
* is in DW interrupt controller.
* Manipulate the relevant bit in the interrupt controller
* register as needed
*/
irq_disable_next_level(dev_ictl, INTR_CNTL_IRQ_NUM(irq));
/* Disable the parent IRQ if all children are disabled */
if (!irq_is_enabled_next_level(dev_ictl)) {
irq_disable_next_level(dev_cavs, CAVS_IRQ_NUMBER(irq));
if (!irq_is_enabled_next_level(dev_cavs)) {
_xtensa_irq_disable(XTENSA_IRQ_NUMBER(irq));
}
}
}