Microchip: MEC172x Add aggregated interrupt driver
Add driver implementation and header files for a MEC172x aggregated interrupt driver. Enable the parent(ECIA) node to have the driver initialize interrupt hardware for use. Enable child nodes for those GIRQs used for aggregation. Refer to chip documention for the list of GIRQs restricted to aggregation and those which support direct mode. Add chip level device tree node for MEC172x EC interrupt aggregator parent and GIRQ children. Each child node contains a list of sources representing the source bit position in the GIRQ registers. Add DT bindings for ECIA and GIRQ nodes. Add build file(s) and configuration items for the MEC172x ECIA aggregated interrupt driver. Add and enable the MEC172x interrupt driver on the MEC172x evaluation board(EVB). Enable parent node to initialize ECIA hardware. Child nodes are left disabled until a future driver needs them. Signed-off-by: Scott Worley <scott.worley@microchip.com>
This commit is contained in:
parent
d5af33eaf0
commit
6b3749d2ff
11 changed files with 948 additions and 3 deletions
512
drivers/interrupt_controller/intc_mchp_ecia_xec.c
Normal file
512
drivers/interrupt_controller/intc_mchp_ecia_xec.c
Normal file
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Microchip Technology Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Driver for External interrupt controller in Microchip XEC devices
|
||||
*
|
||||
* Driver is currently implemented to support MEC172x ECIA GIRQs
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT microchip_xec_ecia
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/arm/aarch32/cortex_m/cmsis.h>
|
||||
#include <device.h>
|
||||
#include <soc.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <drivers/clock_control/mchp_xec_clock_control.h>
|
||||
#include <drivers/interrupt_controller/intc_mchp_xec_ecia.h>
|
||||
|
||||
/* defined at the SoC layer */
|
||||
#define MCHP_FIRST_GIRQ MCHP_FIRST_GIRQ_NOS
|
||||
#define MCHP_LAST_GIRQ MCHP_LAST_GIRQ_NOS
|
||||
#define MCHP_XEC_DIRECT_CAPABLE MCHP_ECIA_DIRECT_BITMAP
|
||||
|
||||
#define GIRQ_ID_TO_BITPOS(id) ((id) + 8)
|
||||
|
||||
/*
|
||||
* MEC SoC's have one and only one instance of ECIA. GIRQ8 register are located
|
||||
* at the beginning of the ECIA block.
|
||||
*/
|
||||
#define ECIA_XEC_REG_BASE \
|
||||
((struct ecia_regs *)(DT_REG_ADDR(DT_NODELABEL(ecia))))
|
||||
|
||||
#define ECS_XEC_REG_BASE \
|
||||
((struct ecs_regs *)(DT_REG_ADDR(DT_NODELABEL(ecs))))
|
||||
|
||||
#define PCR_XEC_REG_BASE \
|
||||
((struct pcr_regs *)(DT_REG_ADDR(DT_NODELABEL(pcr))))
|
||||
|
||||
#define ECIA_XEC_PCR_REG_IDX DT_INST_CLOCKS_CELL(0, regidx)
|
||||
#define ECIA_XEC_PCR_BITPOS DT_INST_CLOCKS_CELL(0, bitpos)
|
||||
|
||||
#define ECIA_XEC_PCR_INFO \
|
||||
MCHP_XEC_PCR_SCR_ENCODE(DT_INST_CLOCKS_CELL(0, regidx), \
|
||||
DT_INST_CLOCKS_CELL(0, bitpos))
|
||||
|
||||
struct xec_girq_config {
|
||||
uintptr_t base;
|
||||
uint8_t girq_id;
|
||||
uint8_t num_srcs;
|
||||
uint8_t sources[32];
|
||||
};
|
||||
|
||||
struct xec_ecia_config {
|
||||
uintptr_t ecia_base;
|
||||
struct mchp_xec_pcr_clk_ctrl clk_ctrl;
|
||||
const struct device *girq_node_handles[32];
|
||||
};
|
||||
|
||||
struct xec_girq_src_data {
|
||||
mchp_xec_ecia_callback_t cb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define DEV_ECIA_CFG(ecia_dev) \
|
||||
((const struct xec_ecia_config *const)(ecia_dev)->config)
|
||||
|
||||
#define DEV_GIRQ_CFG(girq_dev) \
|
||||
((const struct xec_girq_config *const)(girq_dev)->config)
|
||||
|
||||
#define DEV_GIRQ_DATA(girq_dev) \
|
||||
((struct xec_girq_src_data *const)(girq_dev)->data)
|
||||
|
||||
/*
|
||||
* Enable/disable specified GIRQ's aggregated output. Aggrated output is the
|
||||
* bit-wise or of all the GIRQ's result bits.
|
||||
*/
|
||||
void mchp_xec_ecia_girq_aggr_en(uint8_t girq_num, uint8_t enable)
|
||||
{
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
if (enable) {
|
||||
regs->BLK_EN_SET = BIT(girq_num);
|
||||
} else {
|
||||
regs->BLK_EN_CLR = BIT(girq_num);
|
||||
}
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_clr(uint8_t girq_num, uint8_t src_bit_pos)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].SRC = BIT(src_bit_pos);
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_en(uint8_t girq_num, uint8_t src_bit_pos)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to set */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_SET = BIT(src_bit_pos);
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_dis(uint8_t girq_num, uint8_t src_bit_pos)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_CLR = BIT(src_bit_pos);
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_clr_bitmap(uint8_t girq_num, uint32_t bitmap)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].SRC = bitmap;
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_en_bitmap(uint8_t girq_num, uint32_t bitmap)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_SET = bitmap;
|
||||
}
|
||||
|
||||
void mchp_xec_ecia_girq_src_dis_bitmap(uint8_t girq_num, uint32_t bitmap)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].EN_CLR = bitmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return read-only GIRQ result register. Result is bit-wise and of source
|
||||
* and enable registers.
|
||||
*/
|
||||
uint32_t mchp_xec_ecia_girq_result(uint8_t girq_num)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
return regs->GIRQ[girq_num - MCHP_FIRST_GIRQ].RESULT;
|
||||
}
|
||||
|
||||
/* Clear NVIC pending given the external NVIC input number (zero based) */
|
||||
void mchp_xec_ecia_nvic_clr_pend(uint32_t nvic_num)
|
||||
{
|
||||
if (nvic_num >= ((SCnSCB->ICTR + 1) * 32)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_ClearPendingIRQ(nvic_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enable GIRQn interrupt for specific source
|
||||
*
|
||||
* @param girq is the GIRQ number (8 - 26)
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
*/
|
||||
int mchp_xec_ecia_enable(int girq, int src)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ) || (girq > MCHP_LAST_GIRQ) ||
|
||||
(src < 0) || (src > 31)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to set */
|
||||
regs->GIRQ[girq - MCHP_FIRST_GIRQ].EN_SET = BIT(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable EXTI interrupt for specific line
|
||||
*
|
||||
* @param girq is the GIRQ number (8 - 26)
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
*/
|
||||
int mchp_xec_ecia_disable(int girq, int src)
|
||||
{
|
||||
if ((girq < MCHP_FIRST_GIRQ) || (girq > MCHP_LAST_GIRQ) ||
|
||||
(src < 0) || (src > 31)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct ecia_regs *regs = ECIA_XEC_REG_BASE;
|
||||
|
||||
/* write 1 to clear */
|
||||
regs->GIRQ[girq - MCHP_FIRST_GIRQ].EN_CLR = BIT(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* forward reference */
|
||||
static const struct device *get_girq_dev(int girq_num);
|
||||
|
||||
/**
|
||||
* @brief set GIRQn interrupt source callback
|
||||
*
|
||||
* @param dev_girq is the GIRQn device handle
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
* @param cb user callback
|
||||
* @param data user data
|
||||
*/
|
||||
int mchp_xec_ecia_set_callback_by_dev(const struct device *dev_girq, int src,
|
||||
mchp_xec_ecia_callback_t cb, void *data)
|
||||
{
|
||||
if ((dev_girq == NULL) || (src < 0) || (src > 31)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
|
||||
struct xec_girq_src_data *girq_data = DEV_GIRQ_DATA(dev_girq);
|
||||
|
||||
/* source exists in this GIRQ? */
|
||||
if (!(cfg->sources[src] & BIT(7))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* obtain the callback array index for the source */
|
||||
int idx = (int)(cfg->sources[src] & ~BIT(7));
|
||||
|
||||
girq_data[idx].cb = cb;
|
||||
girq_data[idx].data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set GIRQn interrupt source callback
|
||||
*
|
||||
* @param girq is the GIRQ number (8 - 26)
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
* @param cb user callback
|
||||
* @param data user data
|
||||
*/
|
||||
int mchp_xec_ecia_set_callback(int girq_num, int src,
|
||||
mchp_xec_ecia_callback_t cb, void *data)
|
||||
{
|
||||
const struct device *dev = get_girq_dev(girq_num);
|
||||
|
||||
return mchp_xec_ecia_set_callback_by_dev(dev, src, cb, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unset GIRQn interrupt source callback by device handle
|
||||
*
|
||||
* @param dev_girq is the GIRQn device handle
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
*/
|
||||
int mchp_ecia_unset_callback_by_dev(const struct device *dev_girq, int src)
|
||||
{
|
||||
if ((dev_girq == NULL) || (src < 0) || (src > 31)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
|
||||
struct xec_girq_src_data *girq_data = DEV_GIRQ_DATA(dev_girq);
|
||||
|
||||
/* source exists in this GIRQ? */
|
||||
if (!(cfg->sources[src] & BIT(7))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* obtain the callback array index for the source */
|
||||
int idx = (int)(cfg->sources[src] & ~BIT(7));
|
||||
|
||||
girq_data[idx].cb = NULL;
|
||||
girq_data[idx].data = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unset GIRQn interrupt source callback
|
||||
*
|
||||
* @param girq is the GIRQ number (8 - 26)
|
||||
* @param src is the interrupt source in the GIRQ (0 - 31)
|
||||
*/
|
||||
int mchp_ecia_unset_callback(int girq_num, int src)
|
||||
{
|
||||
const struct device *dev = get_girq_dev(girq_num);
|
||||
|
||||
return mchp_ecia_unset_callback_by_dev(dev, src);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a build time flag to know if any aggregated GIRQ has been enabled.
|
||||
* We make use of DT FOREACH macro to check GIRQ node status.
|
||||
* Enabling a GIRQ node (status = "okay") implies you want it used in
|
||||
* aggregated mode. Note, GIRQ 8-12, 24-26 are aggregated only by HW design.
|
||||
* If a GIRQ node is disabled(status = "disabled") and is direct capable the
|
||||
* other driver/application may use IRQ_CONNECT, irq_enable, and the helper
|
||||
* functions in this driver to set/clear GIRQ enable bits and status.
|
||||
* Leaving a node disabled also allows another driver/application to take over
|
||||
* aggregation by managing the GIRQ itself.
|
||||
*/
|
||||
#define XEC_CHK_REQ_AGGR(n) DT_NODE_HAS_STATUS(n, okay) |
|
||||
|
||||
#define XEC_ECIA_REQUIRE_AGGR_ISR \
|
||||
( \
|
||||
DT_FOREACH_CHILD(DT_NODELABEL(ecia), XEC_CHK_REQ_AGGR) \
|
||||
0)
|
||||
|
||||
/* static const uint32_t xec_chk_req = (XEC_ECIA_REQUIRE_AGGR_ISR); */
|
||||
|
||||
#if XEC_ECIA_REQUIRE_AGGR_ISR
|
||||
/*
|
||||
* Generic ISR for aggregated GIRQ's.
|
||||
* GIRQ source(status) bits are latched (R/W1C). The peripheral status
|
||||
* connected to the GIRQ source bit must be cleared first by the callback
|
||||
* and this routine will clear the GIRQ source bit. If a callback was not
|
||||
* registered for a source the enable will also be cleared to prevent
|
||||
* interrupt storms.
|
||||
* NOTE: dev_girq is a pointer to a GIRQ child device instance.
|
||||
*/
|
||||
static void xec_girq_isr(const struct device *dev_girq)
|
||||
{
|
||||
const struct xec_girq_config *const cfg = DEV_GIRQ_CFG(dev_girq);
|
||||
struct xec_girq_src_data *data = DEV_GIRQ_DATA(dev_girq);
|
||||
struct girq_regs *girq = (struct girq_regs *)cfg->base;
|
||||
int girq_id = GIRQ_ID_TO_BITPOS(cfg->girq_id);
|
||||
uint32_t idx = 0;
|
||||
uint32_t result = girq->RESULT;
|
||||
|
||||
for (int i = 0; result && i < 32; i++) {
|
||||
uint8_t bitpos = 31 - (__builtin_clz(result) & 0x1f);
|
||||
|
||||
/* is it an implemented source? */
|
||||
if (cfg->sources[bitpos] & BIT(7)) {
|
||||
/* yes, get the index by removing bit[7] flag */
|
||||
idx = (uint32_t)cfg->sources[bitpos] & ~BIT(7);
|
||||
/* callback registered? */
|
||||
if (data[idx].cb) {
|
||||
data[idx].cb(girq_id, bitpos, data[idx].data);
|
||||
} else { /* no callback, clear the enable */
|
||||
girq->EN_CLR = BIT(bitpos);
|
||||
}
|
||||
} else { /* paranoia, we should not get here... */
|
||||
girq->EN_CLR = BIT(bitpos);
|
||||
}
|
||||
|
||||
/* clear GIRQ latched status */
|
||||
girq->SRC = BIT(bitpos);
|
||||
result &= ~BIT(bitpos);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief initialize XEC ECIA driver
|
||||
* NOTE: GIRQ22 is special used for waking the PLL from deep sleep when a
|
||||
* peripheral receives data from an external entity (eSPI, I2C, etc). Once
|
||||
* the data transfer is complete the system re-enters deep sleep unless the
|
||||
* peripheral was configured to wake CPU after reception of data or event.
|
||||
* GIRQ22 aggregated output and sources are not connected to the NVIC.
|
||||
* We enable GIRQ22 aggregated output to ensure clock asynchronous wake
|
||||
* functionality is operational.
|
||||
*/
|
||||
static int xec_ecia_init(const struct device *dev)
|
||||
{
|
||||
const struct xec_ecia_config *cfg =
|
||||
(const struct xec_ecia_config *const) (dev->config);
|
||||
const struct device *const clk_dev = DEVICE_DT_GET(DT_NODELABEL(pcr));
|
||||
struct ecs_regs *const ecs = ECS_XEC_REG_BASE;
|
||||
struct ecia_regs *const ecia = (struct ecia_regs *)cfg->ecia_base;
|
||||
uint32_t n = 0, nr = 0;
|
||||
int ret;
|
||||
|
||||
ret = clock_control_on(clk_dev,
|
||||
(clock_control_subsys_t *)&cfg->clk_ctrl);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable all direct NVIC connections */
|
||||
ecs->INTR_CTRL |= BIT(0);
|
||||
|
||||
/* gate off all aggregated outputs */
|
||||
ecia->BLK_EN_CLR = UINT32_MAX;
|
||||
|
||||
/* connect aggregated only GIRQs to NVIC */
|
||||
ecia->BLK_EN_SET = MCHP_ECIA_AGGR_BITMAP;
|
||||
|
||||
/* Clear all GIRQn source enables */
|
||||
for (n = 0; n < MCHP_GIRQS; n++) {
|
||||
ecia->GIRQ[n].EN_CLR = UINT32_MAX;
|
||||
}
|
||||
|
||||
/* Clear all external NVIC enables and pending status */
|
||||
nr = SCnSCB->ICTR;
|
||||
for (n = 0u; n <= nr; n++) {
|
||||
NVIC->ICER[n] = UINT32_MAX;
|
||||
NVIC->ICPR[n] = UINT32_MAX;
|
||||
}
|
||||
|
||||
/* ecia->BLK_ACTIVE = xec_chk_req; */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* xec_config_girq_xxx.sources[] entries from GIRQ node */
|
||||
#define XEC_GIRQ_SOURCES2(node_id, prop, idx) \
|
||||
.sources[DT_PROP_BY_IDX(node_id, prop, idx)] = \
|
||||
((uint8_t)(idx) | BIT(7)),
|
||||
|
||||
/* Parameter n is a child node-id */
|
||||
#define GIRQ_XEC_DEVICE(n) \
|
||||
static int xec_girq_init_##n(const struct device *dev); \
|
||||
\
|
||||
static struct xec_girq_src_data \
|
||||
xec_data_girq_##n[DT_PROP_LEN(n, sources)]; \
|
||||
\
|
||||
static const struct xec_girq_config xec_config_girq_##n = { \
|
||||
.base = DT_REG_ADDR(n), \
|
||||
.girq_id = DT_PROP(n, girq_id), \
|
||||
.num_srcs = DT_PROP_LEN(n, sources), \
|
||||
DT_FOREACH_PROP_ELEM(n, sources, XEC_GIRQ_SOURCES2) \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_DEFINE(n, xec_girq_init_##n, \
|
||||
NULL, &xec_data_girq_##n, &xec_config_girq_##n, \
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
NULL); \
|
||||
\
|
||||
static int xec_girq_init_##n(const struct device *dev) \
|
||||
{ \
|
||||
mchp_xec_ecia_girq_aggr_en( \
|
||||
GIRQ_ID_TO_BITPOS(DT_PROP(n, girq_id)), 1); \
|
||||
\
|
||||
IRQ_CONNECT(DT_IRQN(n), \
|
||||
DT_IRQ(n, priority), \
|
||||
xec_girq_isr, \
|
||||
DEVICE_DT_GET(n), 0); \
|
||||
\
|
||||
irq_enable(DT_IRQN(n)); \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/*
|
||||
* iterate over each enabled child node of ECIA
|
||||
* Enable means property status = "okay"
|
||||
*/
|
||||
DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(ecia), GIRQ_XEC_DEVICE)
|
||||
|
||||
/* n = GIRQ node id */
|
||||
#define XEC_GIRQ_HANDLE(n) \
|
||||
.girq_node_handles[DT_PROP(n, girq_id)] = (DEVICE_DT_GET(n)),
|
||||
|
||||
static const struct xec_ecia_config xec_config_ecia = {
|
||||
.ecia_base = DT_REG_ADDR(DT_NODELABEL(ecia)),
|
||||
.clk_ctrl = {
|
||||
.pcr_info = ECIA_XEC_PCR_INFO,
|
||||
},
|
||||
DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(ecia), XEC_GIRQ_HANDLE)
|
||||
};
|
||||
|
||||
DEVICE_DT_DEFINE(DT_NODELABEL(ecia), xec_ecia_init,
|
||||
NULL, NULL, &xec_config_ecia,
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
NULL);
|
||||
|
||||
/* look up GIRQ node handle from ECIA configuration */
|
||||
static const struct device *get_girq_dev(int girq_num)
|
||||
{
|
||||
if ((girq_num < MCHP_FIRST_GIRQ) || (girq_num > MCHP_LAST_GIRQ)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* safe to convert to zero based index */
|
||||
girq_num -= MCHP_FIRST_GIRQ;
|
||||
|
||||
return xec_config_ecia.girq_node_handles[girq_num];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue