|
118 | 118 | #include <zephyr/drivers/clock_control.h> |
119 | 119 | #include <zephyr/drivers/pinctrl.h> |
120 | 120 | #include <zephyr/kernel.h> |
| 121 | +#include <zephyr/sys/ring_buffer.h> |
121 | 122 | #include <soc.h> |
122 | 123 | #include "espi_utils.h" |
123 | 124 | #include "soc_host.h" |
@@ -148,6 +149,18 @@ struct host_sub_npcx_data { |
148 | 149 | uint8_t plt_rst_asserted; /* current PLT_RST# status */ |
149 | 150 | uint8_t espi_rst_asserted; /* current ESPI_RST# status */ |
150 | 151 | const struct device *host_bus_dev; /* device for eSPI/LPC bus */ |
| 152 | +#ifdef CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE |
| 153 | + struct ring_buf port80_ring_buf; |
| 154 | + uint8_t port80_data[CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_RING_BUF_SIZE]; |
| 155 | + struct k_work work; |
| 156 | +#endif |
| 157 | +}; |
| 158 | + |
| 159 | +struct npcx_dp80_buf { |
| 160 | + union { |
| 161 | + uint16_t offset_code_16; |
| 162 | + uint8_t offset_code[2]; |
| 163 | + }; |
151 | 164 | }; |
152 | 165 |
|
153 | 166 | static const struct npcx_clk_cfg host_dev_clk_cfg[] = |
@@ -474,77 +487,90 @@ static void host_pmch_ibf_isr(const void *arg) |
474 | 487 |
|
475 | 488 | /* Host port80 sub-device local functions */ |
476 | 489 | #if defined(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80) |
477 | | -static void host_port80_isr(const void *arg) |
| 490 | +#if defined(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE) |
| 491 | +static void host_port80_work_handler(struct k_work *item) |
478 | 492 | { |
479 | | - ARG_UNUSED(arg); |
480 | | - struct shm_reg *const inst_shm = host_sub_cfg.inst_shm; |
481 | | - struct espi_event evt = { ESPI_BUS_PERIPHERAL_NOTIFICATION, |
482 | | - (ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80, |
483 | | - ESPI_PERIPHERAL_NODATA |
484 | | - }; |
485 | | - uint8_t status = inst_shm->DP80STS; |
486 | | - |
487 | | - if (!IS_ENABLED(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE)) { |
488 | | - LOG_DBG("%s: p80 status 0x%02X", __func__, status); |
489 | | - |
490 | | - /* Read out port80 data continuously if FIFO is not empty */ |
491 | | - while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { |
492 | | - LOG_DBG("p80: %04x", inst_shm->DP80BUF); |
493 | | - evt.evt_data = inst_shm->DP80BUF; |
| 493 | + uint32_t code = 0; |
| 494 | + struct host_sub_npcx_data *data = CONTAINER_OF(item, struct host_sub_npcx_data, work); |
| 495 | + struct ring_buf *rbuf = &data->port80_ring_buf; |
| 496 | + struct espi_event evt = {ESPI_BUS_PERIPHERAL_NOTIFICATION, |
| 497 | + (ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80, |
| 498 | + ESPI_PERIPHERAL_NODATA}; |
| 499 | + |
| 500 | + while (!ring_buf_is_empty(rbuf)) { |
| 501 | + struct npcx_dp80_buf dp80_buf; |
| 502 | + uint8_t offset; |
| 503 | + |
| 504 | + ring_buf_get(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code)); |
| 505 | + offset = dp80_buf.offset_code[1]; |
| 506 | + code |= dp80_buf.offset_code[0] << (8 * offset); |
| 507 | + if (ring_buf_is_empty(rbuf)) { |
| 508 | + evt.evt_data = code; |
494 | 509 | espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev, |
495 | 510 | evt); |
| 511 | + break; |
496 | 512 | } |
497 | | - |
498 | | - } else { |
499 | | - uint16_t port80_buf[16]; |
500 | | - uint8_t count = 0; |
501 | | - uint32_t code = 0; |
502 | | - |
503 | | - while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE) && |
504 | | - count < ARRAY_SIZE(port80_buf)) { |
505 | | - port80_buf[count++] = inst_shm->DP80BUF; |
| 513 | + /* peek the offset of the next byte */ |
| 514 | + ring_buf_peek(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code)); |
| 515 | + offset = dp80_buf.offset_code[1]; |
| 516 | + /* |
| 517 | + * If the peeked next byte's offset is 0, it is the start of the new code. |
| 518 | + * Pass the current code to the application layer to handle the Port80 code. |
| 519 | + */ |
| 520 | + if (offset == 0) { |
| 521 | + evt.evt_data = code; |
| 522 | + espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev, |
| 523 | + evt); |
| 524 | + code = 0; |
506 | 525 | } |
| 526 | + } |
| 527 | +} |
| 528 | +#endif |
507 | 529 |
|
508 | | - for (uint8_t i = 0; i < count; i++) { |
509 | | - uint8_t offset; |
510 | | - uint32_t buf_data; |
| 530 | +static void host_port80_isr(const void *arg) |
| 531 | +{ |
| 532 | + ARG_UNUSED(arg); |
| 533 | + struct shm_reg *const inst_shm = host_sub_cfg.inst_shm; |
| 534 | + uint8_t status = inst_shm->DP80STS; |
511 | 535 |
|
512 | | - buf_data = port80_buf[i]; |
513 | | - offset = GET_FIELD(buf_data, NPCX_DP80BUF_OFFS_FIELD); |
514 | | - code |= (buf_data & 0xFF) << (8 * offset); |
| 536 | +#ifdef CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE |
| 537 | + struct ring_buf *rbuf = &host_sub_data.port80_ring_buf; |
515 | 538 |
|
516 | | - if (i == count - 1) { |
517 | | - evt.evt_data = code; |
518 | | - espi_send_callbacks(host_sub_data.callbacks, |
519 | | - host_sub_data.host_bus_dev, evt); |
520 | | - break; |
521 | | - } |
| 539 | + while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { |
| 540 | + struct npcx_dp80_buf dp80_buf; |
522 | 541 |
|
523 | | - /* peek the offset of the next byte */ |
524 | | - buf_data = port80_buf[i + 1]; |
525 | | - offset = GET_FIELD(buf_data, NPCX_DP80BUF_OFFS_FIELD); |
526 | | - /* |
527 | | - * If the peeked next byte's offset is 0 means it is the start |
528 | | - * of the new code. Pass the current code to Port80 |
529 | | - * common layer. |
530 | | - */ |
531 | | - if (offset == 0) { |
532 | | - evt.evt_data = code; |
533 | | - espi_send_callbacks(host_sub_data.callbacks, |
534 | | - host_sub_data.host_bus_dev, evt); |
535 | | - code = 0; |
536 | | - } |
537 | | - } |
| 542 | + dp80_buf.offset_code_16 = inst_shm->DP80BUF; |
| 543 | + ring_buf_put(rbuf, &dp80_buf.offset_code[0], sizeof(dp80_buf.offset_code)); |
| 544 | + } |
| 545 | + k_work_submit(&host_sub_data.work); |
| 546 | +#else |
| 547 | + struct espi_event evt = {ESPI_BUS_PERIPHERAL_NOTIFICATION, |
| 548 | + (ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80, |
| 549 | + ESPI_PERIPHERAL_NODATA}; |
| 550 | + |
| 551 | + /* Read out port80 data continuously if FIFO is not empty */ |
| 552 | + while (IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { |
| 553 | + LOG_DBG("p80: %04x", inst_shm->DP80BUF); |
| 554 | + evt.evt_data = inst_shm->DP80BUF; |
| 555 | + espi_send_callbacks(host_sub_data.callbacks, host_sub_data.host_bus_dev, evt); |
538 | 556 | } |
| 557 | +#endif |
| 558 | + LOG_DBG("%s: p80 status 0x%02X", __func__, status); |
539 | 559 |
|
540 | 560 | /* If FIFO is overflow, show error msg */ |
541 | 561 | if (IS_BIT_SET(status, NPCX_DP80STS_FOR)) { |
542 | 562 | inst_shm->DP80STS |= BIT(NPCX_DP80STS_FOR); |
543 | | - LOG_ERR("Port80 FIFO Overflow!"); |
| 563 | + LOG_DBG("Port80 FIFO Overflow!"); |
544 | 564 | } |
545 | 565 |
|
546 | | - /* Clear all pending bit indicates that FIFO was written by host */ |
547 | | - inst_shm->DP80STS |= BIT(NPCX_DP80STS_FWR); |
| 566 | + /* If there are pending post codes remains in FIFO after processing and sending previous |
| 567 | + * post codes, do not clear the FNE bit. This allows this handler to be called again |
| 568 | + * immediately after it exists. |
| 569 | + */ |
| 570 | + if (!IS_BIT_SET(inst_shm->DP80STS, NPCX_DP80STS_FNE)) { |
| 571 | + /* Clear all pending bit indicates that FIFO was written by host */ |
| 572 | + inst_shm->DP80STS |= BIT(NPCX_DP80STS_FWR); |
| 573 | + } |
548 | 574 | } |
549 | 575 |
|
550 | 576 | static void host_port80_init(void) |
@@ -1101,6 +1127,11 @@ int npcx_host_init_subs_core_domain(const struct device *host_bus_dev, |
1101 | 1127 | #endif |
1102 | 1128 | #if defined(CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80) |
1103 | 1129 | host_port80_init(); |
| 1130 | +#if defined(CONFIG_ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE) |
| 1131 | + ring_buf_init(&host_sub_data.port80_ring_buf, sizeof(host_sub_data.port80_data), |
| 1132 | + host_sub_data.port80_data); |
| 1133 | + k_work_init(&host_sub_data.work, host_port80_work_handler); |
| 1134 | +#endif |
1104 | 1135 | #endif |
1105 | 1136 | #if defined(CONFIG_ESPI_PERIPHERAL_UART) |
1106 | 1137 | host_uart_init(); |
|
0 commit comments