diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 7a43e815dd1..17bf4577bae 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -176,8 +176,8 @@ static const struct npcx_vw_out_config vw_out_gpio_tbl1[] = { }; /* Callbacks for eSPI bus reset and Virtual Wire signals. */ -static struct miwu_dev_callback espi_rst_callback; -static struct miwu_dev_callback vw_in_callback[ARRAY_SIZE(vw_in_tbl)]; +static struct miwu_callback espi_rst_callback; +static struct miwu_callback vw_in_callback[ARRAY_SIZE(vw_in_tbl)]; /* eSPI VW service function forward declarations */ static int espi_npcx_receive_vwire(const struct device *dev, @@ -188,7 +188,7 @@ static void espi_vw_send_bootload_done(const struct device *dev); /* eSPI local initialization functions */ static void espi_init_wui_callback(const struct device *dev, - struct miwu_dev_callback *callback, const struct npcx_wui *wui, + struct miwu_callback *callback, const struct npcx_wui *wui, miwu_dev_callback_handler_t handler) { /* VW signal which has no wake-up input source */ @@ -197,7 +197,7 @@ static void espi_init_wui_callback(const struct device *dev, /* Install callback function */ npcx_miwu_init_dev_callback(callback, wui, handler, dev); - npcx_miwu_manage_dev_callback(callback, 1); + npcx_miwu_manage_callback(callback, 1); /* Configure MIWU setting and enable its interrupt */ npcx_miwu_interrupt_configure(wui, NPCX_MIWU_MODE_EDGE, diff --git a/drivers/gpio/gpio_npcx.c b/drivers/gpio/gpio_npcx.c index cbf9c21044c..08287dd9076 100644 --- a/drivers/gpio/gpio_npcx.c +++ b/drivers/gpio/gpio_npcx.c @@ -356,7 +356,7 @@ static int gpio_npcx_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) { const struct gpio_npcx_config *const config = dev->config; - struct miwu_io_callback *miwu_cb = (struct miwu_io_callback *)callback; + struct miwu_callback *miwu_cb = (struct miwu_callback *)callback; int pin = find_lsb_set(callback->pin_mask) - 1; /* pin_mask should not be zero */ @@ -376,7 +376,7 @@ static int gpio_npcx_manage_callback(const struct device *dev, config->port); /* Insert or remove a IO callback which being called in MIWU ISRs */ - return npcx_miwu_manage_gpio_callback(miwu_cb, set); + return npcx_miwu_manage_callback(miwu_cb, set); } /* GPIO driver registration */ diff --git a/drivers/interrupt_controller/intc_miwu.c b/drivers/interrupt_controller/intc_miwu.c index 6290cb5f6a9..81c5c515b17 100644 --- a/drivers/interrupt_controller/intc_miwu.c +++ b/drivers/interrupt_controller/intc_miwu.c @@ -78,68 +78,53 @@ struct intc_miwu_config { uint8_t index; }; -/* Callback functions list for GPIO wake-up inputs */ -sys_slist_t cb_list_gpio; - -/* - * Callback functions list for the generic hardware modules wake-up inputs - * such as timer, uart, i2c, host interface and so on. - */ -sys_slist_t cb_list_generic; - -BUILD_ASSERT(sizeof(struct miwu_io_callback) == sizeof(struct gpio_callback), - "Size of struct miwu_io_callback must equal to struct gpio_callback"); +/* Driver data */ +struct intc_miwu_data { + /* Callback functions list for each MIWU group */ + sys_slist_t cb_list_grp[8]; +}; BUILD_ASSERT(sizeof(struct miwu_io_params) == sizeof(gpio_port_pins_t), "Size of struct miwu_io_params must equal to struct gpio_port_pins_t"); +BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params) + + sizeof(struct miwu_io_params) == sizeof(struct gpio_callback), + "Failed in size check of miwu_callback and gpio_callback structures!"); + +BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params.cb_type) == + offsetof(struct miwu_callback, dev_cb.params.cb_type), + "Failed in offset check of cb_type field of miwu_callback structure"); + /* MIWU local functions */ -static void intc_miwu_dispatch_gpio_isr(uint8_t wui_table, - uint8_t wui_group, uint8_t wui_bit) +static void intc_miwu_dispatch_isr(sys_slist_t *cb_list, uint8_t mask) { - struct miwu_io_callback *cb, *tmp; + struct miwu_callback *cb, *tmp; - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cb_list_gpio, cb, tmp, node) { - /* Pending bit, group and table match the wui item in list */ - if (cb->params.wui.table == wui_table - && cb->params.wui.group == wui_group - && cb->params.wui.bit == wui_bit) { - __ASSERT(cb->handler, "No GPIO callback handler!"); - /* - * Execute GPIO callback and the other callback might - * match the same wui item. - */ - cb->handler(npcx_get_gpio_dev(cb->params.gpio_port), + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(cb_list, cb, tmp, node) { + + if (cb->io_cb.params.cb_type == NPCX_MIWU_CALLBACK_GPIO) { + if (BIT(cb->io_cb.params.wui.bit) & mask) { + __ASSERT(cb->io_cb.handler, "No GPIO callback handler!"); + cb->io_cb.handler( + npcx_get_gpio_dev(cb->io_cb.params.gpio_port), (struct gpio_callback *)cb, - cb->params.pin_mask); - } - } -} + cb->io_cb.params.pin_mask); + } + } else { + if (BIT(cb->dev_cb.params.wui.bit) & mask) { + __ASSERT(cb->dev_cb.handler, "No device callback handler!"); -static void intc_miwu_dispatch_generic_isr(uint8_t wui_table, - uint8_t wui_group, uint8_t wui_bit) -{ - struct miwu_dev_callback *cb, *tmp; - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cb_list_generic, cb, tmp, node) { - /* Pending bit, group and table match the wui item in list */ - if (cb->wui.table == wui_table - && cb->wui.group == wui_group - && cb->wui.bit == wui_bit) { - __ASSERT(cb->handler, "No Generic callback handler!"); - /* - * Execute generic callback and the other callback might - * match the same wui item. - */ - cb->handler(cb->source, &cb->wui); + cb->dev_cb.handler(cb->dev_cb.params.source, + &cb->dev_cb.params.wui); + } } } } static void intc_miwu_isr_pri(int wui_table, int wui_group) { - int wui_bit; const struct intc_miwu_config *config = miwu_devs[wui_table]->config; + struct intc_miwu_data *data = miwu_devs[wui_table]->data; const uint32_t base = config->base; uint8_t mask = NPCX_WKPND(base, wui_group) & NPCX_WKEN(base, wui_group); @@ -148,17 +133,8 @@ static void intc_miwu_isr_pri(int wui_table, int wui_group) NPCX_WKPCL(base, wui_group) = mask; } - for (wui_bit = 0; wui_bit < 8; wui_bit++) { - if (mask & BIT(wui_bit)) { - LOG_DBG("miwu_isr %d %d %d!\n", wui_table, - wui_group, wui_bit); - /* Dispatch registered gpio and generic isrs */ - intc_miwu_dispatch_gpio_isr(wui_table, - wui_group, wui_bit); - intc_miwu_dispatch_generic_isr(wui_table, - wui_group, wui_bit); - } - } + /* Dispatch registered gpio isrs */ + intc_miwu_dispatch_isr(&data->cb_list_grp[wui_group], mask); } /* Platform specific MIWU functions */ @@ -278,33 +254,47 @@ int npcx_miwu_interrupt_configure(const struct npcx_wui *wui, return 0; } -void npcx_miwu_init_gpio_callback(struct miwu_io_callback *callback, +void npcx_miwu_init_gpio_callback(struct miwu_callback *callback, const struct npcx_wui *io_wui, int port) { /* Initialize WUI and GPIO settings in unused bits field */ - callback->params.wui.table = io_wui->table; - callback->params.wui.group = io_wui->group; - callback->params.wui.bit = io_wui->bit; - callback->params.gpio_port = port; + callback->io_cb.params.wui.table = io_wui->table; + callback->io_cb.params.wui.bit = io_wui->bit; + callback->io_cb.params.gpio_port = port; + callback->io_cb.params.cb_type = NPCX_MIWU_CALLBACK_GPIO; + callback->io_cb.params.wui.group = io_wui->group; } -void npcx_miwu_init_dev_callback(struct miwu_dev_callback *callback, +void npcx_miwu_init_dev_callback(struct miwu_callback *callback, const struct npcx_wui *dev_wui, miwu_dev_callback_handler_t handler, const struct device *source) { /* Initialize WUI and input device settings */ - callback->wui.table = dev_wui->table; - callback->wui.group = dev_wui->group; - callback->wui.bit = dev_wui->bit; - callback->handler = handler; - callback->source = source; + callback->dev_cb.params.wui.table = dev_wui->table; + callback->dev_cb.params.wui.group = dev_wui->group; + callback->dev_cb.params.wui.bit = dev_wui->bit; + callback->dev_cb.params.source = source; + callback->dev_cb.params.cb_type = NPCX_MIWU_CALLBACK_DEV; + callback->dev_cb.handler = handler; } -int npcx_miwu_manage_gpio_callback(struct miwu_io_callback *cb, bool set) +int npcx_miwu_manage_callback(struct miwu_callback *cb, bool set) { - if (!sys_slist_is_empty(&cb_list_gpio)) { - if (!sys_slist_find_and_remove(&cb_list_gpio, &cb->node)) { + struct npcx_wui *wui; + struct intc_miwu_data *data; + sys_slist_t *cb_list; + + if (cb->io_cb.params.cb_type == NPCX_MIWU_CALLBACK_GPIO) { + wui = &cb->io_cb.params.wui; + } else { + wui = &cb->dev_cb.params.wui; + } + + data = miwu_devs[wui->table]->data; + cb_list = &data->cb_list_grp[wui->group]; + if (!sys_slist_is_empty(cb_list)) { + if (!sys_slist_find_and_remove(cb_list, &cb->node)) { if (!set) { return -EINVAL; } @@ -312,24 +302,7 @@ int npcx_miwu_manage_gpio_callback(struct miwu_io_callback *cb, bool set) } if (set) { - sys_slist_prepend(&cb_list_gpio, &cb->node); - } - - return 0; -} - -int npcx_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set) -{ - if (!sys_slist_is_empty(&cb_list_generic)) { - if (!sys_slist_find_and_remove(&cb_list_generic, &cb->node)) { - if (!set) { - return -EINVAL; - } - } - } - - if (set) { - sys_slist_prepend(&cb_list_generic, &cb->node); + sys_slist_prepend(cb_list, &cb->node); } return 0; @@ -385,11 +358,12 @@ int npcx_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set) .base = DT_REG_ADDR(DT_NODELABEL(miwu##inst)), \ .index = DT_PROP(DT_NODELABEL(miwu##inst), index), \ }; \ + struct intc_miwu_data miwu_data_##inst; \ \ DEVICE_DT_INST_DEFINE(inst, \ NPCX_MIWU_INIT_FUNC(inst), \ NULL, \ - NULL, &miwu_config_##inst, \ + &miwu_data_##inst, &miwu_config_##inst, \ PRE_KERNEL_1, \ CONFIG_INTC_INIT_PRIORITY, NULL); \ \ diff --git a/drivers/kscan/kscan_npcx.c b/drivers/kscan/kscan_npcx.c index 79720aa8623..109f4dd9969 100644 --- a/drivers/kscan/kscan_npcx.c +++ b/drivers/kscan/kscan_npcx.c @@ -59,7 +59,7 @@ struct kscan_npcx_data { uint8_t matrix_new_state[KSCAN_COL_SIZE]; /* Index in to the scan_clock_cycle to indicate start of debouncing */ uint8_t scan_cycle_idx[KSCAN_COL_SIZE * KSCAN_ROW_SIZE]; - struct miwu_dev_callback ksi_callback[KSCAN_ROW_SIZE]; + struct miwu_callback ksi_callback[KSCAN_ROW_SIZE]; /* Track previous "elapsed clock cycles" per matrix scan. This * is used to calculate the debouncing time for every key */ @@ -393,7 +393,7 @@ static void kscan_matrix_polling_thread(const struct device *dev, void *dummy2, } static void kscan_npcx_init_ksi_wui_callback(const struct device *dev, - struct miwu_dev_callback *callback, + struct miwu_callback *callback, const struct npcx_wui *wui, miwu_dev_callback_handler_t handler) { @@ -404,7 +404,7 @@ static void kscan_npcx_init_ksi_wui_callback(const struct device *dev, /* Install callback function */ npcx_miwu_init_dev_callback(callback, wui, handler, dev); - npcx_miwu_manage_dev_callback(callback, 1); + npcx_miwu_manage_callback(callback, 1); /* Configure MIWU setting and enable its interrupt */ npcx_miwu_interrupt_configure(wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_BOTH); diff --git a/drivers/serial/uart_npcx.c b/drivers/serial/uart_npcx.c index 0cc89457f8e..acec579cdf7 100644 --- a/drivers/serial/uart_npcx.c +++ b/drivers/serial/uart_npcx.c @@ -47,7 +47,7 @@ enum uart_pm_policy_state_flag { struct uart_npcx_data { /* Baud rate */ uint32_t baud_rate; - struct miwu_dev_callback uart_rx_cb; + struct miwu_callback uart_rx_cb; struct k_spinlock lock; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t user_cb; @@ -519,7 +519,7 @@ static int uart_npcx_init(const struct device *dev) /* Initialize a miwu device input and its callback function */ npcx_miwu_init_dev_callback(&data->uart_rx_cb, &config->uart_rx_wui, uart_npcx_rx_wk_isr, dev); - npcx_miwu_manage_dev_callback(&data->uart_rx_cb, true); + npcx_miwu_manage_callback(&data->uart_rx_cb, true); /* * Configure the UART wake-up event triggered from a falling * edge on CR_SIN pin. No need for callback function. diff --git a/drivers/watchdog/wdt_npcx.c b/drivers/watchdog/wdt_npcx.c index 85e675e7103..4af2659e5a4 100644 --- a/drivers/watchdog/wdt_npcx.c +++ b/drivers/watchdog/wdt_npcx.c @@ -82,7 +82,7 @@ struct wdt_npcx_data { bool timeout_installed; }; -struct miwu_dev_callback miwu_cb; +struct miwu_callback miwu_cb; /* Driver convenience defines */ #define HAL_INSTANCE(dev) ((struct twd_reg *)((const struct wdt_npcx_config *)(dev)->config)->base) @@ -153,7 +153,7 @@ static void wdt_config_t0out_interrupt(const struct device *dev) /* Initialize a miwu device input and its callback function */ npcx_miwu_init_dev_callback(&miwu_cb, &config->t0out, wdt_t0out_isr, dev); - npcx_miwu_manage_dev_callback(&miwu_cb, true); + npcx_miwu_manage_callback(&miwu_cb, true); /* * Configure the T0 wake-up event triggered from a rising edge diff --git a/soc/arm/nuvoton_npcx/common/soc_miwu.h b/soc/arm/nuvoton_npcx/common/soc_miwu.h index c7b51b4f211..2284e9d6190 100644 --- a/soc/arm/nuvoton_npcx/common/soc_miwu.h +++ b/soc/arm/nuvoton_npcx/common/soc_miwu.h @@ -50,6 +50,12 @@ enum miwu_int_trig { NPCX_MIWU_TRIG_BOTH, /** Both edge rising and failing detection */ }; +/* NPCX miwu driver callback type */ +enum { + NPCX_MIWU_CALLBACK_GPIO, + NPCX_MIWU_CALLBACK_DEV, +}; + /** * @brief NPCX wake-up input source structure * @@ -79,46 +85,50 @@ typedef void (*miwu_dev_callback_handler_t)(const struct device *source, */ struct miwu_io_params { uint8_t pin_mask; /** A mask of pins the callback is interested in. */ - uint8_t reserved; uint8_t gpio_port; /** GPIO device index */ + uint8_t cb_type; /** Callback type */ struct npcx_wui wui; /** Wake-up input source of GPIO */ }; /** - * @brief MIWU callback structure for a GPIO input + * @brief MIWU/generic device information structure * - * Used to register a GPIO callback in the driver instance callback list. - * Beware such structure should not be allocated on stack and its size must - * equal struct gpio_callback. - * - * Note: To help setting it, see npcx_miwu_init_gpio_callback() below + * It contains the information used for MIWU generic device event. Please notice + * the offset of cb_type must be the same as cb_type in struct miwu_io_params. */ -struct miwu_io_callback { - /** Node of single-linked list */ - sys_snode_t node; - /** Callback function being called when GPIO event occurred */ - gpio_callback_handler_t handler; - /** GPIO callback parameters used in MIWU ISR */ - struct miwu_io_params params; +struct miwu_dev_params { + uint8_t reserve1; + uint8_t reserve2; + uint8_t cb_type; /** Callback type */ + struct npcx_wui wui; /** Device instance register callback function */ + const struct device *source; /** Wake-up input source */ }; /** - * @brief MIWU callback structure for a device input + * @brief MIWU callback structure for a gpio or device input * - * Used to register a generic hardware device callback in the driver instance + * Used to register a generic gpio/device callback in the driver instance * callback list. Beware such structure should not be allocated on stack. * - * Note: To help setting it, see npcx_miwu_init_dev_callback() below + * Note: To help setting it, see npcx_miwu_init_dev_callback() and + * npcx_miwu_manage_callback() below */ -struct miwu_dev_callback { +struct miwu_callback { /** Node of single-linked list */ sys_snode_t node; - /** Callback function being called when device event occurred */ - miwu_dev_callback_handler_t handler; - /** Device instance register callback function */ - const struct device *source; - /* Wake-up input source */ - struct npcx_wui wui; + union { + struct { + /** Callback function being called when GPIO event occurred */ + gpio_callback_handler_t handler; + struct miwu_io_params params; + } io_cb; + + struct { + /** Callback function being called when device event occurred */ + miwu_dev_callback_handler_t handler; + struct miwu_dev_params params; + } dev_cb; + }; }; /** @@ -181,50 +191,38 @@ int npcx_miwu_interrupt_configure(const struct npcx_wui *wui, enum miwu_int_mode mode, enum miwu_int_trig trig); /** - * @brief Function to initialize a struct miwu_io_callback properly + * @brief Function to initialize a struct miwu_callback with gpio properly * * @param callback Pointer to io callback structure for initialization * @param io_wui Pointer to wake-up input IO source * @param port GPIO port issued a callback function */ -void npcx_miwu_init_gpio_callback(struct miwu_io_callback *callback, +void npcx_miwu_init_gpio_callback(struct miwu_callback *callback, const struct npcx_wui *io_wui, int port); /** - * @brief Function to initialize a struct miwu_dev_callback properly + * @brief Function to initialize a struct miwu_callback with device properly * * @param callback Pointer to device callback structure for initialization * @param dev_wui Pointer to wake-up input device source * @param handler A function called when its device input event issued * @param source Pointer to device instance issued a callback function */ -void npcx_miwu_init_dev_callback(struct miwu_dev_callback *callback, +void npcx_miwu_init_dev_callback(struct miwu_callback *callback, const struct npcx_wui *dev_wui, miwu_dev_callback_handler_t handler, const struct device *source); /** - * @brief Function to insert or remove a IO callback from a callback list + * @brief Function to insert or remove a miwu callback from a callback list * - * @param callback Pointer to io callback structure + * @param callback Pointer to miwu callback structure * @param set A boolean indicating insertion or removal of the callback * * @retval 0 If successful. * @retval -EINVAL Invalid parameters */ -int npcx_miwu_manage_gpio_callback(struct miwu_io_callback *callback, bool set); - - -/** - * @brief Function to insert or remove a device callback from a callback list - * - * @param callback Pointer to device callback structure - * @param set A boolean indicating insertion or removal of the callback - * - * @retval 0 If successful. - * @retval -EINVAL Invalid parameters - */ -int npcx_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set); +int npcx_miwu_manage_callback(struct miwu_callback *cb, bool set); #ifdef __cplusplus }