Skip to content

Commit 9da9c90

Browse files
MulinChaocarlescufi
authored andcommitted
intc: miwu: npcx: improve interrupt latency of miwu input events
To reduce the interrupt latency of MIWU events, the driver prepares a dedicated callback function item list for each MIWU group in this PR. We needn't check the MIWU table and group of the event in ISR. And the maximum item number of each list is also limited to 8. After applying this PR, the interrupt latency reduces to ~10us consistently. Signed-off-by: Mulin Chao <[email protected]>
1 parent ac38411 commit 9da9c90

File tree

7 files changed

+116
-144
lines changed

7 files changed

+116
-144
lines changed

drivers/espi/espi_npcx.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ static const struct npcx_vw_out_config vw_out_gpio_tbl1[] = {
176176
};
177177

178178
/* Callbacks for eSPI bus reset and Virtual Wire signals. */
179-
static struct miwu_dev_callback espi_rst_callback;
180-
static struct miwu_dev_callback vw_in_callback[ARRAY_SIZE(vw_in_tbl)];
179+
static struct miwu_callback espi_rst_callback;
180+
static struct miwu_callback vw_in_callback[ARRAY_SIZE(vw_in_tbl)];
181181

182182
/* eSPI VW service function forward declarations */
183183
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);
188188

189189
/* eSPI local initialization functions */
190190
static void espi_init_wui_callback(const struct device *dev,
191-
struct miwu_dev_callback *callback, const struct npcx_wui *wui,
191+
struct miwu_callback *callback, const struct npcx_wui *wui,
192192
miwu_dev_callback_handler_t handler)
193193
{
194194
/* VW signal which has no wake-up input source */
@@ -197,7 +197,7 @@ static void espi_init_wui_callback(const struct device *dev,
197197

198198
/* Install callback function */
199199
npcx_miwu_init_dev_callback(callback, wui, handler, dev);
200-
npcx_miwu_manage_dev_callback(callback, 1);
200+
npcx_miwu_manage_callback(callback, 1);
201201

202202
/* Configure MIWU setting and enable its interrupt */
203203
npcx_miwu_interrupt_configure(wui, NPCX_MIWU_MODE_EDGE,

drivers/gpio/gpio_npcx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ static int gpio_npcx_manage_callback(const struct device *dev,
356356
struct gpio_callback *callback, bool set)
357357
{
358358
const struct gpio_npcx_config *const config = dev->config;
359-
struct miwu_io_callback *miwu_cb = (struct miwu_io_callback *)callback;
359+
struct miwu_callback *miwu_cb = (struct miwu_callback *)callback;
360360
int pin = find_lsb_set(callback->pin_mask) - 1;
361361

362362
/* pin_mask should not be zero */
@@ -376,7 +376,7 @@ static int gpio_npcx_manage_callback(const struct device *dev,
376376
config->port);
377377

378378
/* Insert or remove a IO callback which being called in MIWU ISRs */
379-
return npcx_miwu_manage_gpio_callback(miwu_cb, set);
379+
return npcx_miwu_manage_callback(miwu_cb, set);
380380
}
381381

382382
/* GPIO driver registration */

drivers/interrupt_controller/intc_miwu.c

Lines changed: 62 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -78,68 +78,53 @@ struct intc_miwu_config {
7878
uint8_t index;
7979
};
8080

81-
/* Callback functions list for GPIO wake-up inputs */
82-
sys_slist_t cb_list_gpio;
83-
84-
/*
85-
* Callback functions list for the generic hardware modules wake-up inputs
86-
* such as timer, uart, i2c, host interface and so on.
87-
*/
88-
sys_slist_t cb_list_generic;
89-
90-
BUILD_ASSERT(sizeof(struct miwu_io_callback) == sizeof(struct gpio_callback),
91-
"Size of struct miwu_io_callback must equal to struct gpio_callback");
81+
/* Driver data */
82+
struct intc_miwu_data {
83+
/* Callback functions list for each MIWU group */
84+
sys_slist_t cb_list_grp[8];
85+
};
9286

9387
BUILD_ASSERT(sizeof(struct miwu_io_params) == sizeof(gpio_port_pins_t),
9488
"Size of struct miwu_io_params must equal to struct gpio_port_pins_t");
9589

90+
BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params) +
91+
sizeof(struct miwu_io_params) == sizeof(struct gpio_callback),
92+
"Failed in size check of miwu_callback and gpio_callback structures!");
93+
94+
BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params.cb_type) ==
95+
offsetof(struct miwu_callback, dev_cb.params.cb_type),
96+
"Failed in offset check of cb_type field of miwu_callback structure");
97+
9698
/* MIWU local functions */
97-
static void intc_miwu_dispatch_gpio_isr(uint8_t wui_table,
98-
uint8_t wui_group, uint8_t wui_bit)
99+
static void intc_miwu_dispatch_isr(sys_slist_t *cb_list, uint8_t mask)
99100
{
100-
struct miwu_io_callback *cb, *tmp;
101-
102-
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cb_list_gpio, cb, tmp, node) {
103-
/* Pending bit, group and table match the wui item in list */
104-
if (cb->params.wui.table == wui_table
105-
&& cb->params.wui.group == wui_group
106-
&& cb->params.wui.bit == wui_bit) {
107-
__ASSERT(cb->handler, "No GPIO callback handler!");
108-
/*
109-
* Execute GPIO callback and the other callback might
110-
* match the same wui item.
111-
*/
112-
cb->handler(npcx_get_gpio_dev(cb->params.gpio_port),
101+
struct miwu_callback *cb, *tmp;
102+
103+
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(cb_list, cb, tmp, node) {
104+
105+
if (cb->io_cb.params.cb_type == NPCX_MIWU_CALLBACK_GPIO) {
106+
if (BIT(cb->io_cb.params.wui.bit) & mask) {
107+
__ASSERT(cb->io_cb.handler, "No GPIO callback handler!");
108+
cb->io_cb.handler(
109+
npcx_get_gpio_dev(cb->io_cb.params.gpio_port),
113110
(struct gpio_callback *)cb,
114-
cb->params.pin_mask);
115-
}
116-
}
117-
}
111+
cb->io_cb.params.pin_mask);
112+
}
113+
} else {
114+
if (BIT(cb->dev_cb.params.wui.bit) & mask) {
115+
__ASSERT(cb->dev_cb.handler, "No device callback handler!");
118116

119-
static void intc_miwu_dispatch_generic_isr(uint8_t wui_table,
120-
uint8_t wui_group, uint8_t wui_bit)
121-
{
122-
struct miwu_dev_callback *cb, *tmp;
123-
124-
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cb_list_generic, cb, tmp, node) {
125-
/* Pending bit, group and table match the wui item in list */
126-
if (cb->wui.table == wui_table
127-
&& cb->wui.group == wui_group
128-
&& cb->wui.bit == wui_bit) {
129-
__ASSERT(cb->handler, "No Generic callback handler!");
130-
/*
131-
* Execute generic callback and the other callback might
132-
* match the same wui item.
133-
*/
134-
cb->handler(cb->source, &cb->wui);
117+
cb->dev_cb.handler(cb->dev_cb.params.source,
118+
&cb->dev_cb.params.wui);
119+
}
135120
}
136121
}
137122
}
138123

139124
static void intc_miwu_isr_pri(int wui_table, int wui_group)
140125
{
141-
int wui_bit;
142126
const struct intc_miwu_config *config = miwu_devs[wui_table]->config;
127+
struct intc_miwu_data *data = miwu_devs[wui_table]->data;
143128
const uint32_t base = config->base;
144129
uint8_t mask = NPCX_WKPND(base, wui_group) & NPCX_WKEN(base, wui_group);
145130

@@ -148,17 +133,8 @@ static void intc_miwu_isr_pri(int wui_table, int wui_group)
148133
NPCX_WKPCL(base, wui_group) = mask;
149134
}
150135

151-
for (wui_bit = 0; wui_bit < 8; wui_bit++) {
152-
if (mask & BIT(wui_bit)) {
153-
LOG_DBG("miwu_isr %d %d %d!\n", wui_table,
154-
wui_group, wui_bit);
155-
/* Dispatch registered gpio and generic isrs */
156-
intc_miwu_dispatch_gpio_isr(wui_table,
157-
wui_group, wui_bit);
158-
intc_miwu_dispatch_generic_isr(wui_table,
159-
wui_group, wui_bit);
160-
}
161-
}
136+
/* Dispatch registered gpio isrs */
137+
intc_miwu_dispatch_isr(&data->cb_list_grp[wui_group], mask);
162138
}
163139

164140
/* Platform specific MIWU functions */
@@ -278,58 +254,55 @@ int npcx_miwu_interrupt_configure(const struct npcx_wui *wui,
278254
return 0;
279255
}
280256

281-
void npcx_miwu_init_gpio_callback(struct miwu_io_callback *callback,
257+
void npcx_miwu_init_gpio_callback(struct miwu_callback *callback,
282258
const struct npcx_wui *io_wui, int port)
283259
{
284260
/* Initialize WUI and GPIO settings in unused bits field */
285-
callback->params.wui.table = io_wui->table;
286-
callback->params.wui.group = io_wui->group;
287-
callback->params.wui.bit = io_wui->bit;
288-
callback->params.gpio_port = port;
261+
callback->io_cb.params.wui.table = io_wui->table;
262+
callback->io_cb.params.wui.bit = io_wui->bit;
263+
callback->io_cb.params.gpio_port = port;
264+
callback->io_cb.params.cb_type = NPCX_MIWU_CALLBACK_GPIO;
265+
callback->io_cb.params.wui.group = io_wui->group;
289266
}
290267

291-
void npcx_miwu_init_dev_callback(struct miwu_dev_callback *callback,
268+
void npcx_miwu_init_dev_callback(struct miwu_callback *callback,
292269
const struct npcx_wui *dev_wui,
293270
miwu_dev_callback_handler_t handler,
294271
const struct device *source)
295272
{
296273
/* Initialize WUI and input device settings */
297-
callback->wui.table = dev_wui->table;
298-
callback->wui.group = dev_wui->group;
299-
callback->wui.bit = dev_wui->bit;
300-
callback->handler = handler;
301-
callback->source = source;
274+
callback->dev_cb.params.wui.table = dev_wui->table;
275+
callback->dev_cb.params.wui.group = dev_wui->group;
276+
callback->dev_cb.params.wui.bit = dev_wui->bit;
277+
callback->dev_cb.params.source = source;
278+
callback->dev_cb.params.cb_type = NPCX_MIWU_CALLBACK_DEV;
279+
callback->dev_cb.handler = handler;
302280
}
303281

304-
int npcx_miwu_manage_gpio_callback(struct miwu_io_callback *cb, bool set)
282+
int npcx_miwu_manage_callback(struct miwu_callback *cb, bool set)
305283
{
306-
if (!sys_slist_is_empty(&cb_list_gpio)) {
307-
if (!sys_slist_find_and_remove(&cb_list_gpio, &cb->node)) {
308-
if (!set) {
309-
return -EINVAL;
310-
}
311-
}
312-
}
284+
struct npcx_wui *wui;
285+
struct intc_miwu_data *data;
286+
sys_slist_t *cb_list;
313287

314-
if (set) {
315-
sys_slist_prepend(&cb_list_gpio, &cb->node);
288+
if (cb->io_cb.params.cb_type == NPCX_MIWU_CALLBACK_GPIO) {
289+
wui = &cb->io_cb.params.wui;
290+
} else {
291+
wui = &cb->dev_cb.params.wui;
316292
}
317293

318-
return 0;
319-
}
320-
321-
int npcx_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set)
322-
{
323-
if (!sys_slist_is_empty(&cb_list_generic)) {
324-
if (!sys_slist_find_and_remove(&cb_list_generic, &cb->node)) {
294+
data = miwu_devs[wui->table]->data;
295+
cb_list = &data->cb_list_grp[wui->group];
296+
if (!sys_slist_is_empty(cb_list)) {
297+
if (!sys_slist_find_and_remove(cb_list, &cb->node)) {
325298
if (!set) {
326299
return -EINVAL;
327300
}
328301
}
329302
}
330303

331304
if (set) {
332-
sys_slist_prepend(&cb_list_generic, &cb->node);
305+
sys_slist_prepend(cb_list, &cb->node);
333306
}
334307

335308
return 0;
@@ -385,11 +358,12 @@ int npcx_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set)
385358
.base = DT_REG_ADDR(DT_NODELABEL(miwu##inst)), \
386359
.index = DT_PROP(DT_NODELABEL(miwu##inst), index), \
387360
}; \
361+
struct intc_miwu_data miwu_data_##inst; \
388362
\
389363
DEVICE_DT_INST_DEFINE(inst, \
390364
NPCX_MIWU_INIT_FUNC(inst), \
391365
NULL, \
392-
NULL, &miwu_config_##inst, \
366+
&miwu_data_##inst, &miwu_config_##inst, \
393367
PRE_KERNEL_1, \
394368
CONFIG_INTC_INIT_PRIORITY, NULL); \
395369
\

drivers/kscan/kscan_npcx.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct kscan_npcx_data {
5959
uint8_t matrix_new_state[KSCAN_COL_SIZE];
6060
/* Index in to the scan_clock_cycle to indicate start of debouncing */
6161
uint8_t scan_cycle_idx[KSCAN_COL_SIZE * KSCAN_ROW_SIZE];
62-
struct miwu_dev_callback ksi_callback[KSCAN_ROW_SIZE];
62+
struct miwu_callback ksi_callback[KSCAN_ROW_SIZE];
6363
/* Track previous "elapsed clock cycles" per matrix scan. This
6464
* is used to calculate the debouncing time for every key
6565
*/
@@ -393,7 +393,7 @@ static void kscan_matrix_polling_thread(const struct device *dev, void *dummy2,
393393
}
394394

395395
static void kscan_npcx_init_ksi_wui_callback(const struct device *dev,
396-
struct miwu_dev_callback *callback,
396+
struct miwu_callback *callback,
397397
const struct npcx_wui *wui,
398398
miwu_dev_callback_handler_t handler)
399399
{
@@ -404,7 +404,7 @@ static void kscan_npcx_init_ksi_wui_callback(const struct device *dev,
404404

405405
/* Install callback function */
406406
npcx_miwu_init_dev_callback(callback, wui, handler, dev);
407-
npcx_miwu_manage_dev_callback(callback, 1);
407+
npcx_miwu_manage_callback(callback, 1);
408408

409409
/* Configure MIWU setting and enable its interrupt */
410410
npcx_miwu_interrupt_configure(wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_BOTH);

drivers/serial/uart_npcx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ enum uart_pm_policy_state_flag {
4747
struct uart_npcx_data {
4848
/* Baud rate */
4949
uint32_t baud_rate;
50-
struct miwu_dev_callback uart_rx_cb;
50+
struct miwu_callback uart_rx_cb;
5151
struct k_spinlock lock;
5252
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
5353
uart_irq_callback_user_data_t user_cb;
@@ -519,7 +519,7 @@ static int uart_npcx_init(const struct device *dev)
519519
/* Initialize a miwu device input and its callback function */
520520
npcx_miwu_init_dev_callback(&data->uart_rx_cb, &config->uart_rx_wui,
521521
uart_npcx_rx_wk_isr, dev);
522-
npcx_miwu_manage_dev_callback(&data->uart_rx_cb, true);
522+
npcx_miwu_manage_callback(&data->uart_rx_cb, true);
523523
/*
524524
* Configure the UART wake-up event triggered from a falling
525525
* edge on CR_SIN pin. No need for callback function.

drivers/watchdog/wdt_npcx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct wdt_npcx_data {
8282
bool timeout_installed;
8383
};
8484

85-
struct miwu_dev_callback miwu_cb;
85+
struct miwu_callback miwu_cb;
8686

8787
/* Driver convenience defines */
8888
#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)
153153
/* Initialize a miwu device input and its callback function */
154154
npcx_miwu_init_dev_callback(&miwu_cb, &config->t0out, wdt_t0out_isr,
155155
dev);
156-
npcx_miwu_manage_dev_callback(&miwu_cb, true);
156+
npcx_miwu_manage_callback(&miwu_cb, true);
157157

158158
/*
159159
* Configure the T0 wake-up event triggered from a rising edge

0 commit comments

Comments
 (0)