From 3ae105e76b1a47c013d6982a79b3f2fa36b19963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Barna=C5=9B?= Date: Mon, 1 Aug 2022 18:06:33 +0200 Subject: [PATCH] ec_host_cmd: add NPCX SHI peripheral for the host commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the support for host commands being transported by the Serial Host Interface on the NPCX SoC. Signed-off-by: Michał Barnaś --- drivers/ec_host_cmd_periph/CMakeLists.txt | 5 + drivers/ec_host_cmd_periph/Kconfig | 39 + .../ec_host_cmd_periph_shi.h | 101 ++ .../ec_host_cmd_periph_shi_npcx.c | 976 ++++++++++++++++++ dts/arm/nuvoton/npcx.dtsi | 10 + dts/bindings/shi/nuvoton,npcx-shi.yaml | 28 + dts/bindings/shi/shi-device.yaml | 20 + soc/arm/nuvoton_npcx/common/reg/reg_def.h | 84 ++ subsys/mgmt/ec_host_cmd/Kconfig | 1 + 9 files changed, 1264 insertions(+) create mode 100644 drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi.h create mode 100644 drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi_npcx.c create mode 100644 dts/bindings/shi/nuvoton,npcx-shi.yaml create mode 100644 dts/bindings/shi/shi-device.yaml diff --git a/drivers/ec_host_cmd_periph/CMakeLists.txt b/drivers/ec_host_cmd_periph/CMakeLists.txt index 06d95efc0b5..81c95ed31c7 100644 --- a/drivers/ec_host_cmd_periph/CMakeLists.txt +++ b/drivers/ec_host_cmd_periph/CMakeLists.txt @@ -9,3 +9,8 @@ zephyr_library_sources_ifdef( zephyr_library_sources_ifdef( CONFIG_EC_HOST_CMD_PERIPH_ESPI ec_host_cmd_periph_espi.c) + +zephyr_library_sources_ifdef( + CONFIG_EC_HOST_CMD_PERIPH_SHI_NPCX + ec_host_cmd_periph_shi_npcx.c) + diff --git a/drivers/ec_host_cmd_periph/Kconfig b/drivers/ec_host_cmd_periph/Kconfig index 66e9ffa6b92..c586d55adf4 100644 --- a/drivers/ec_host_cmd_periph/Kconfig +++ b/drivers/ec_host_cmd_periph/Kconfig @@ -35,6 +35,45 @@ config EC_HOST_CMD_PERIPH_ESPI Enable support for Embedded Controller host commands using the eSPI bus. +config EC_HOST_CMD_PERIPH_SHI + bool "Host commands support using SHI" + help + Enable support for Embedded Controller host commands using + the Serial Host Interface. + endchoice +if EC_HOST_CMD_PERIPH_SHI + +choice EC_HOST_CMD_PERIPH_SHI_DRIVER + prompt "SHI driver" + default EC_HOST_CMD_PERIPH_SHI_NPCX if SOC_FAMILY_NPCX + +config EC_HOST_CMD_PERIPH_SHI_NPCX + bool "SHI by Nuvoton" + depends on DT_HAS_NUVOTON_NPCX_SHI_ENABLED + help + This option enables the driver for SHI peripheral in the + Nuvoton NPCX chip. + +endchoice + +config EC_HOST_CMD_PERIPH_SHI_MAX_REQUEST + int "Max data size for the version 3 request packet" + default 544 if EC_HOST_CMD_PERIPH_SHI_NPCX + help + This option indicates maximum data size for a version 3 request + packet. This must be big enough to handle a request header of host + command, flash write offset/size, and 512 bytes of flash data. + +config EC_HOST_CMD_PERIPH_SHI_MAX_RESPONSE + int "Max data size for the version 3 response packet" + default 544 if EC_HOST_CMD_PERIPH_SHI_NPCX + help + This option indicates maximum data size for a version 3 response + packet. This must be big enough to handle a response header of host + command, flash read offset/size, and 512 bytes of flash data. + +endif # EC_HOST_CMD_PERIPH_SHI + endif # EC_HOST_CMD_PERIPH diff --git a/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi.h b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi.h new file mode 100644 index 00000000000..0bd06324acc --- /dev/null +++ b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_EC_HOST_CMD_PERIPH_SHI_H_ +#define ZEPHYR_DRIVERS_EC_HOST_CMD_PERIPH_SHI_H_ + +#include + +/* + * Byte codes returned by EC over SPI interface. + * + * These can be used by the AP to debug the EC interface, and to determine + * when the EC is not in a state where it will ever get around to responding + * to the AP. + * + * Example of sequence of bytes read from EC for a current good transfer: + * 1. - - AP asserts chip select (CS#) + * 2. EC_SHI_OLD_READY - AP sends first byte(s) of request + * 3. - - EC starts handling CS# interrupt + * 4. EC_SHI_RECEIVING - AP sends remaining byte(s) of request + * 5. EC_SHI_PROCESSING - EC starts processing request; AP is clocking in + * bytes looking for EC_SHI_FRAME_START + * 6. - - EC finishes processing and sets up response + * 7. EC_SHI_FRAME_START - AP reads frame byte + * 8. (response packet) - AP reads response packet + * 9. EC_SHI_PAST_END - Any additional bytes read by AP + * 10 - - AP deasserts chip select + * 11 - - EC processes CS# interrupt and sets up DMA for + * next request + * + * If the AP is waiting for EC_SHI_FRAME_START and sees any value other than + * the following byte values: + * EC_SHI_OLD_READY + * EC_SHI_RX_READY + * EC_SHI_RECEIVING + * EC_SHI_PROCESSING + * + * Then the EC found an error in the request, or was not ready for the request + * and lost data. The AP should give up waiting for EC_SHI_FRAME_START, + * because the EC is unable to tell when the AP is done sending its request. + */ + +/* + * Framing byte which precedes a response packet from the EC. After sending a + * request, the AP will clock in bytes until it sees the framing byte, then + * clock in the response packet. + */ +#define EC_SHI_FRAME_START 0xec + +/* + * Padding bytes which are clocked out after the end of a response packet. + */ +#define EC_SHI_PAST_END 0xed + +/* + * EC is ready to receive, and has ignored the byte sent by the AP. EC expects + * that the AP will send a valid packet header (starting with + * EC_COMMAND_PROTOCOL_3) in the next 32 bytes. + * + * NOTE: Some SPI configurations place the Most Significant Bit on SDO when + * CS goes low. This macro has the Most Significant Bit set to zero, + * so SDO will not be driven high when CS goes low. + */ +#define EC_SHI_RX_READY 0x78 + +/* + * EC has started receiving the request from the AP, but hasn't started + * processing it yet. + */ +#define EC_SHI_RECEIVING 0xf9 + +/* EC has received the entire request from the AP and is processing it. */ +#define EC_SHI_PROCESSING 0xfa + +/* + * EC received bad data from the AP, such as a packet header with an invalid + * length. EC will ignore all data until chip select deasserts. + */ +#define EC_SHI_RX_BAD_DATA 0xfb + +/* + * EC received data from the AP before it was ready. That is, the AP asserted + * chip select and started clocking data before the EC was ready to receive it. + * EC will ignore all data until chip select deasserts. + */ +#define EC_SHI_NOT_READY 0xfc + +/* + * EC was ready to receive a request from the AP. EC has treated the byte sent + * by the AP as part of a request packet, or (for old-style ECs) is processing + * a fully received packet but is not ready to respond yet. + */ +#define EC_SHI_OLD_READY 0xfd + +/* Supported version of host commands protocol. */ +#define EC_HOST_REQUEST_VERSION 3 + +#endif /* ZEPHYR_DRIVERS_EC_HOST_CMD_PERIPH_SHI_H_ */ diff --git a/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi_npcx.c b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi_npcx.c new file mode 100644 index 00000000000..f235f24c504 --- /dev/null +++ b/drivers/ec_host_cmd_periph/ec_host_cmd_periph_shi_npcx.c @@ -0,0 +1,976 @@ +/* + * Copyright (c) 2022 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcx_shi + +#include "ec_host_cmd_periph_shi.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "Invalid number of NPCX SHI peripherals"); + +LOG_MODULE_REGISTER(host_cmd_shi_npcx, CONFIG_EC_HC_LOG_LEVEL); + +/* Driver convenience defines */ +#define HAL_INSTANCE(dev) (struct shi_reg *)(((const struct shi_npcx_config *)(dev)->config)->base) + +/* Full output buffer size */ +#define SHI_OBUF_FULL_SIZE DT_INST_PROP(0, buffer_tx_size) +/* Full input buffer size */ +#define SHI_IBUF_FULL_SIZE DT_INST_PROP(0, buffer_rx_size) +/* Configure the IBUFLVL2 = the size of V3 protocol header */ +#define SHI_IBUFLVL2_THRESHOLD (sizeof(struct ec_host_cmd_request_header)) +/* Half output buffer size */ +#define SHI_OBUF_HALF_SIZE (SHI_OBUF_FULL_SIZE / 2) +/* Half input buffer size */ +#define SHI_IBUF_HALF_SIZE (SHI_IBUF_FULL_SIZE / 2) + +/* + * Timeout to wait for SHI request packet + * + * This affects the slowest SPI clock we can support. A delay of 8192 us permits a 512-byte request + * at 500 KHz, assuming the SPI controller starts sending bytes as soon as it asserts chip select. + * That's as slow as we would practically want to run the SHI interface, since running it slower + * significantly impacts firmware update times. + */ +#define EC_SHI_CMD_RX_TIMEOUT_US 8192 + +/* + * The AP blindly clocks back bytes over the SPI interface looking for a framing byte. + * So this preamble must always precede the actual response packet. + */ +#define EC_SHI_OUT_PREAMBLE_LENGTH 2 + +/* + * Space allocation of the past-end status byte (EC_SHI_PAST_END) in the out_msg buffer. + */ +#define EC_SHI_PAST_END_LENGTH 1 + +/* + * Space allocation of the frame status byte (EC_SHI_FRAME_START) in the out_msg buffer. + */ +#define EC_SHI_FRAME_START_LENGTH 1 + +/* + * Offset of output parameters needs to account for pad and framing bytes and + * one last past-end byte at the end so any additional bytes clocked out by + * the AP will have a known and identifiable value. + */ +#define EC_SHI_PROTO3_OVERHEAD (EC_SHI_PAST_END_LENGTH + EC_SHI_FRAME_START_LENGTH) + +/* + * Our input and output msg buffers. These must be large enough for our largest + * message, including protocol overhead. The pointers after the protocol + * overhead, as passed to the host command handler, must be 32-bit aligned. + */ +#define SHI_OUT_START_PAD (4 * (EC_SHI_FRAME_START_LENGTH / 4 + 1)) +#define SHI_OUT_END_PAD (4 * (EC_SHI_PAST_END_LENGTH / 4 + 1)) + +enum shi_npcx_state { + SHI_STATE_NONE = -1, + /* SHI not enabled (initial state, and when chipset is off) */ + SHI_STATE_DISABLED = 0, + /* Ready to receive next request */ + SHI_STATE_READY_TO_RECV, + /* Receiving request */ + SHI_STATE_RECEIVING, + /* Processing request */ + SHI_STATE_PROCESSING, + /* Canceling response since CS deasserted and output NOT_READY byte */ + SHI_STATE_CNL_RESP_NOT_RDY, + /* Sending response */ + SHI_STATE_SENDING, + /* Received data is invalid */ + SHI_STATE_BAD_RECEIVED_DATA, +}; + +/* Device config */ +struct shi_npcx_config { + /* Serial Host Interface (SHI) base address */ + uintptr_t base; + /* Clock configuration */ + struct npcx_clk_cfg clk_cfg; + /* Pin control configuration */ + const struct pinctrl_dev_config *pcfg; + /* Chip-select interrupts */ + int irq; + struct npcx_wui shi_cs_wui; +}; + +struct shi_npcx_data { + /* Handler mutexes */ + struct k_sem handler_owns; + struct k_sem dev_owns; + /* Communication status */ + enum shi_npcx_state state; + enum shi_npcx_state last_error_state; + uint8_t *rx_msg; /* Entry pointer of msg rx buffer */ + uint8_t *tx_msg; /* Entry pointer of msg tx buffer */ + volatile uint8_t *rx_buf; /* Entry pointer of receive buffer */ + volatile uint8_t *tx_buf; /* Entry pointer of transmit buffer */ + uint32_t sz_received; /* Size of received data in bytes */ + uint16_t sz_sending; /* Size of sending data in bytes */ + uint16_t sz_request; /* Request bytes need to receive */ + uint16_t sz_response; /* Response bytes need to receive */ + uint64_t rx_deadline; /* Deadline of receiving */ + /* Buffers */ + uint8_t out_msg_padded[SHI_OUT_START_PAD + CONFIG_EC_HOST_CMD_PERIPH_SHI_MAX_RESPONSE + + SHI_OUT_END_PAD] __aligned(4); + uint8_t *const out_msg; + uint8_t in_msg[CONFIG_EC_HOST_CMD_PERIPH_SHI_MAX_REQUEST] __aligned(4); +}; + +/* Forward declaration */ +static void shi_npcx_reset_prepare(const struct device *dev); + +/* Read pointer of input or output buffer by consecutive reading */ +static uint32_t shi_npcx_read_buf_pointer(struct shi_reg *const inst) +{ + uint8_t stat; + + /* Wait for two consecutive equal values read */ + do { + stat = inst->IBUFSTAT; + } while (stat != inst->IBUFSTAT); + + return (uint32_t)stat; +} + +/* + * Valid offset of SHI output buffer to write. + * When SIMUL bit is set, IBUFPTR can be used instead of OBUFPTR + */ +static uint32_t shi_npcx_valid_obuf_offset(struct shi_reg *const inst) +{ + return (shi_npcx_read_buf_pointer(inst) + EC_SHI_OUT_PREAMBLE_LENGTH) % SHI_OBUF_FULL_SIZE; +} + +/* + * This routine write SHI next half output buffer from msg buffer + */ +static void shi_npcx_write_half_outbuf(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + + const uint32_t size = MIN(SHI_OBUF_HALF_SIZE, data->sz_response - data->sz_sending); + uint8_t *obuf_ptr = (uint8_t *)data->tx_buf; + const uint8_t *obuf_end = obuf_ptr + size; + uint8_t *msg_ptr = data->tx_msg; + + /* Fill half output buffer */ + while (obuf_ptr != obuf_end) { + *obuf_ptr++ = *msg_ptr++; + } + + data->sz_sending += size; + data->tx_buf = obuf_ptr; + data->tx_msg = msg_ptr; +} + +/* + * This routine read SHI input buffer to msg buffer until + * we have received a certain number of bytes + */ +static int shi_npcx_read_inbuf_wait(const struct device *dev, uint32_t szbytes) +{ + struct shi_npcx_data *data = dev->data; + struct shi_reg *const inst = HAL_INSTANCE(dev); + + /* Copy data to msg buffer from input buffer */ + for (uint32_t i = 0; i < szbytes; i++, data->sz_received++) { + /* + * If input buffer pointer equals pointer which wants to read, + * it means data is not ready. + */ + while (data->rx_buf == inst->IBUF + shi_npcx_read_buf_pointer(inst)) { + if (k_cycle_get_64() >= data->rx_deadline) { + return 0; + } + } + + /* Copy data to msg buffer */ + *data->rx_msg++ = *data->rx_buf++; + } + return 1; +} + +/* This routine fills out all SHI output buffer with status byte */ +static void shi_npcx_fill_out_status(struct shi_reg *const inst, uint8_t status) +{ + uint8_t start, end; + volatile uint8_t *fill_ptr; + volatile uint8_t *fill_end; + volatile uint8_t *obuf_end; + + /* + * Disable interrupts in case the interfere by the other interrupts. + * Use __disable_irq/__enable_irq instead of using irq_lock/irq_unlock + * here because irq_lock/irq_unlock leave some system exceptions (like + * SVC, NMI, and faults) still enabled. + */ + __disable_irq(); + + /* + * Fill out output buffer with status byte and leave a gap for PREAMBLE. + * The gap guarantees the synchronization. The critical section should + * be done within this gap. No racing happens. + */ + start = shi_npcx_valid_obuf_offset(inst); + end = (start + SHI_OBUF_FULL_SIZE - EC_SHI_OUT_PREAMBLE_LENGTH) % SHI_OBUF_FULL_SIZE; + + fill_ptr = inst->OBUF + start; + fill_end = inst->OBUF + end; + obuf_end = inst->OBUF + SHI_OBUF_FULL_SIZE; + while (fill_ptr != fill_end) { + *fill_ptr++ = status; + if (fill_ptr == obuf_end) { + fill_ptr = inst->OBUF; + } + } + + /* End of critical section */ + __enable_irq(); +} + +/* This routine handles shi received unexpected data */ +static void shi_npcx_bad_received_data(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + struct shi_reg *const inst = HAL_INSTANCE(dev); + + /* State machine mismatch, timeout, or protocol we can't handle. */ + shi_npcx_fill_out_status(inst, EC_SHI_RX_BAD_DATA); + data->state = SHI_STATE_BAD_RECEIVED_DATA; + + LOG_ERR("SHI bad data recv"); + LOG_DBG("BAD-"); + LOG_HEXDUMP_DBG(data->in_msg, data->sz_received, "in_msg="); + + /* Reset shi's state machine for error recovery */ + shi_npcx_reset_prepare(dev); + + LOG_DBG("END"); +} + +/* + * This routine write SHI output buffer from msg buffer over halt of it. + * It make sure we have enough time to handle next operations. + */ +static void shi_npcx_write_first_pkg_outbuf(const struct device *dev, uint16_t szbytes) +{ + struct shi_npcx_data *data = dev->data; + struct shi_reg *const inst = HAL_INSTANCE(dev); + uint8_t size, offset; + volatile uint8_t *obuf_ptr; + volatile uint8_t *obuf_end; + uint8_t *msg_ptr; + uint32_t half_buf_remain; /* Remains in half buffer are free to write */ + + /* Start writing at our current OBUF position */ + offset = shi_npcx_valid_obuf_offset(inst); + obuf_ptr = inst->OBUF + offset; + msg_ptr = data->tx_msg; + + /* Fill up to OBUF mid point, or OBUF end */ + half_buf_remain = SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE); + size = MIN(half_buf_remain, szbytes - data->sz_sending); + obuf_end = obuf_ptr + size; + while (obuf_ptr != obuf_end) { + *obuf_ptr++ = *msg_ptr++; + } + + /* Track bytes sent for later accounting */ + data->sz_sending += size; + + /* Write data to beginning of OBUF if we've reached the end */ + if (obuf_ptr == inst->OBUF + SHI_IBUF_FULL_SIZE) { + obuf_ptr = inst->OBUF; + } + + /* Fill next half output buffer */ + size = MIN(SHI_OBUF_HALF_SIZE, szbytes - data->sz_sending); + obuf_end = obuf_ptr + size; + while (obuf_ptr != obuf_end) { + *obuf_ptr++ = *msg_ptr++; + } + + /* Track bytes sent / last OBUF position written for later accounting */ + data->sz_sending += size; + data->tx_buf = obuf_ptr; + data->tx_msg = msg_ptr; +} + +static void shi_npcx_handle_host_package(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + struct shi_reg *const inst = HAL_INSTANCE(dev); + uint32_t sz_inbuf_int = data->sz_request / SHI_IBUF_HALF_SIZE; + uint32_t cnt_inbuf_int = data->sz_received / SHI_IBUF_HALF_SIZE; + + if (sz_inbuf_int - cnt_inbuf_int) { + /* Need to receive data from buffer */ + return; + } + + uint32_t remain_bytes = data->sz_request - data->sz_received; + + /* Read remaining bytes from input buffer */ + if (!shi_npcx_read_inbuf_wait(dev, remain_bytes)) { + return shi_npcx_bad_received_data(dev); + } + + /* Move to processing state */ + data->state = SHI_STATE_PROCESSING; + LOG_DBG("PRC-"); + + /* Fill output buffer to indicate we`re processing request */ + shi_npcx_fill_out_status(inst, EC_SHI_PROCESSING); + data->out_msg[0] = EC_SHI_FRAME_START; + + /* Wake-up the HC handler thread */ + k_sem_give(&data->handler_owns); +} + +static int shi_npcx_host_request_expected_size(const struct ec_host_cmd_request_header *r) +{ + /* Check host request version */ + if (r->prtcl_ver != EC_HOST_REQUEST_VERSION) { + return 0; + } + + /* Reserved byte should be 0 */ + if (r->reserved) { + return 0; + } + + return sizeof(*r) + r->data_len; +} + +static void shi_npcx_parse_header(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + + /* We're now inside a transaction */ + data->state = SHI_STATE_RECEIVING; + LOG_DBG("RV-"); + + /* Setup deadline time for receiving */ + data->rx_deadline = k_cycle_get_64() + k_us_to_cyc_near64(EC_SHI_CMD_RX_TIMEOUT_US); + + /* Wait for version, command, length bytes */ + if (!shi_npcx_read_inbuf_wait(dev, 3)) { + return shi_npcx_bad_received_data(dev); + } + + if (data->in_msg[0] == EC_HOST_REQUEST_VERSION) { + /* Protocol version 3 */ + struct ec_host_cmd_request_header *r = + (struct ec_host_cmd_request_header *)data->in_msg; + int pkt_size; + + /* + * If request is over half of input buffer, we need to modify the algorithm again. + */ + __ASSERT_NO_MSG(sizeof(*r) < SHI_IBUF_HALF_SIZE); + + /* Wait for the rest of the command header */ + if (!shi_npcx_read_inbuf_wait(dev, sizeof(*r) - 3)) { + return shi_npcx_bad_received_data(dev); + } + + /* Check how big the packet should be */ + pkt_size = shi_npcx_host_request_expected_size(r); + if (pkt_size == 0 || pkt_size > sizeof(data->in_msg)) { + return shi_npcx_bad_received_data(dev); + } + + /* Computing total bytes need to receive */ + data->sz_request = pkt_size; + + shi_npcx_handle_host_package(dev); + } else { + /* Invalid version number */ + return shi_npcx_bad_received_data(dev); + } +} + +static void shi_npcx_sec_ibf_int_enable(struct shi_reg *const inst, int enable) +{ + if (enable) { + /* Setup IBUFLVL2 threshold and enable it */ + inst->SHICFG5 |= BIT(NPCX_SHICFG5_IBUFLVL2DIS); + SET_FIELD(inst->SHICFG5, NPCX_SHICFG5_IBUFLVL2, SHI_IBUFLVL2_THRESHOLD); + inst->SHICFG5 &= ~BIT(NPCX_SHICFG5_IBUFLVL2DIS); + + /* Enable IBHF2 event */ + inst->EVENABLE2 |= BIT(NPCX_EVENABLE2_IBHF2EN); + } else { + /* Disable IBHF2 event first */ + inst->EVENABLE2 &= ~BIT(NPCX_EVENABLE2_IBHF2EN); + + /* Disable IBUFLVL2 and set threshold back to zero */ + inst->SHICFG5 |= BIT(NPCX_SHICFG5_IBUFLVL2DIS); + SET_FIELD(inst->SHICFG5, NPCX_SHICFG5_IBUFLVL2, 0); + } +} + +/* This routine copies SHI half input buffer data to msg buffer */ +static void shi_npcx_read_half_inbuf(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + + /* + * Copy to read buffer until reaching middle/top address of + * input buffer or completing receiving data + */ + do { + /* Restore data to msg buffer */ + *data->rx_msg++ = *data->rx_buf++; + data->sz_received++; + } while (data->sz_received % SHI_IBUF_HALF_SIZE && data->sz_received != data->sz_request); +} + +/* + * Avoid spamming the console with prints every IBF / IBHF interrupt, if + * we find ourselves in an unexpected state. + */ +static void shi_npcx_log_unexpected_state(const struct device *dev, char *isr_name) +{ + struct shi_npcx_data *data = dev->data; + + if (data->state != data->last_error_state) { + LOG_ERR("Unexpected state %d in %s ISR", data->state, isr_name); + } + + data->last_error_state = data->state; +} + +static void shi_npcx_handle_cs_assert(const struct device *dev) +{ + struct shi_reg *const inst = HAL_INSTANCE(dev); + struct shi_npcx_data *data = dev->data; + + /* If not enabled, ignore glitches on SHI_CS_L */ + if (data->state == SHI_STATE_DISABLED) { + return; + } + + /* NOT_READY should be sent and there're no spi transaction now. */ + if (data->state == SHI_STATE_CNL_RESP_NOT_RDY) { + return; + } + + /* Chip select is low = asserted */ + if (data->state != SHI_STATE_READY_TO_RECV) { + /* State machine should be reset in EVSTAT_EOR ISR */ + LOG_ERR("Unexpected state %d in CS ISR", data->state); + return; + } + + LOG_DBG("CSL-"); + + /* + * Clear possible EOR event from previous transaction since it's + * irrelevant now that CS is re-asserted. + */ + inst->EVSTAT = BIT(NPCX_EVSTAT_EOR); +} + +static void shi_npcx_handle_cs_deassert(const struct device *dev) +{ + struct shi_reg *const inst = HAL_INSTANCE(dev); + struct shi_npcx_data *data = dev->data; + + /* + * If the buffer is still used by the host command. + * Change state machine for response handler. + */ + if (data->state == SHI_STATE_PROCESSING) { + /* + * Mark not ready to prevent the other + * transaction immediately + */ + shi_npcx_fill_out_status(inst, EC_SHI_NOT_READY); + + data->state = SHI_STATE_CNL_RESP_NOT_RDY; + + /* + * Disable SHI interrupt, it will remain disabled until shi_send_response_packet() + * is called and CS is asserted for a new transaction. + */ + irq_disable(DT_INST_IRQN(0)); + + LOG_DBG("CNL-"); + return; + /* Next transaction but we're not ready */ + } else if (data->state == SHI_STATE_CNL_RESP_NOT_RDY) { + return; + } + + /* Error state for checking*/ + if (data->state != SHI_STATE_SENDING) { + shi_npcx_log_unexpected_state(dev, "CSNRE"); + } + + /* reset SHI and prepare to next transaction again */ + shi_npcx_reset_prepare(dev); + LOG_DBG("END\n"); +} + +static void shi_npcx_handle_input_buf_half_full(const struct device *dev) +{ + struct shi_reg *const inst = HAL_INSTANCE(dev); + struct shi_npcx_data *data = dev->data; + + if (data->state == SHI_STATE_RECEIVING) { + /* Read data from input to msg buffer */ + shi_npcx_read_half_inbuf(dev); + return shi_npcx_handle_host_package(dev); + } else if (data->state == SHI_STATE_SENDING) { + /* Write data from msg buffer to output buffer */ + if (data->tx_buf == inst->OBUF + SHI_OBUF_FULL_SIZE) { + /* Write data from bottom address again */ + data->tx_buf = inst->OBUF; + shi_npcx_write_half_outbuf(dev); + } + } else if (data->state == SHI_STATE_PROCESSING) { + /* Wait for host to handle request */ + } else { + /* Unexpected status */ + shi_npcx_log_unexpected_state(dev, "IBHF"); + } +} + +static void shi_npcx_handle_input_buf_full(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + struct shi_reg *const inst = HAL_INSTANCE(dev); + + if (data->state == SHI_STATE_RECEIVING) { + /* read data from input to msg buffer */ + shi_npcx_read_half_inbuf(dev); + /* Read to bottom address again */ + data->rx_buf = inst->IBUF; + return shi_npcx_handle_host_package(dev); + } else if (data->state == SHI_STATE_SENDING) { + /* Write data from msg buffer to output buffer */ + if (data->tx_buf == inst->OBUF + SHI_OBUF_HALF_SIZE) { + shi_npcx_write_half_outbuf(dev); + } + + return; + } else if (data->state == SHI_STATE_PROCESSING) { + /* Wait for host to handle request */ + return; + } + + /* Unexpected status */ + shi_npcx_log_unexpected_state(dev, "IBF"); +} + +static void shi_npcx_isr(const struct device *dev) +{ + struct shi_reg *const inst = HAL_INSTANCE(dev); + uint8_t stat; + uint8_t stat2; + + /* Read status register and clear interrupt status early */ + stat = inst->EVSTAT; + inst->EVSTAT = stat; + stat2 = inst->EVSTAT2; + + /* SHI CS pin is asserted in EVSTAT2 */ + if (IS_BIT_SET(stat2, NPCX_EVSTAT2_CSNFE)) { + /* Clear pending bit of CSNFE */ + inst->EVSTAT2 = BIT(NPCX_EVSTAT2_CSNFE); + LOG_DBG("CSNFE-"); + + /* + * BUSY bit is set when SHI_CS is asserted. If not, leave it for + * SHI_CS de-asserted event. + */ + if (!IS_BIT_SET(inst->SHICFG2, NPCX_SHICFG2_BUSY)) { + LOG_DBG("CSNB-"); + return; + } + + shi_npcx_handle_cs_assert(dev); + } + + /* + * End of data for read/write transaction. i.e. SHI_CS is deasserted. + * Host completed or aborted transaction + * + * EOR has the limitation that it will not be set even if the SHI_CS is deasserted without + * SPI clocks. The new SHI module introduce the CSNRE bit which will be set when SHI_CS is + * deasserted regardless of SPI clocks. + */ + if (IS_BIT_SET(stat2, NPCX_EVSTAT2_CSNRE)) { + /* Clear pending bit of CSNRE */ + inst->EVSTAT2 = BIT(NPCX_EVSTAT2_CSNRE); + + /* + * We're not in proper state. + * Mark not ready to abort next transaction + */ + LOG_DBG("CSH-"); + return shi_npcx_handle_cs_deassert(dev); + } + + /* + * The number of bytes received reaches the size of + * protocol V3 header(=8) after CS asserted. + */ + if (IS_BIT_SET(stat2, NPCX_EVSTAT2_IBHF2)) { + /* Clear IBHF2 */ + inst->EVSTAT2 = BIT(NPCX_EVSTAT2_IBHF2); + LOG_DBG("HDR-"); + + /* Disable second IBF interrupt and start to parse header */ + shi_npcx_sec_ibf_int_enable(inst, 0); + shi_npcx_parse_header(dev); + } + + /* + * Indicate input/output buffer pointer reaches the half buffer size. + * Transaction is processing. + */ + if (IS_BIT_SET(stat, NPCX_EVSTAT_IBHF)) { + return shi_npcx_handle_input_buf_half_full(dev); + } + + /* + * Indicate input/output buffer pointer reaches the full buffer size. + * Transaction is processing. + */ + if (IS_BIT_SET(stat, NPCX_EVSTAT_IBF)) { + return shi_npcx_handle_input_buf_full(dev); + } +} + +static void shi_npcx_reset_prepare(const struct device *dev) +{ + struct shi_reg *const inst = HAL_INSTANCE(dev); + struct shi_npcx_data *data = dev->data; + uint32_t i; + + data->state = SHI_STATE_DISABLED; + + irq_disable(DT_INST_IRQN(0)); + + /* Disable SHI unit to clear all status bits */ + inst->SHICFG1 &= ~BIT(NPCX_SHICFG1_EN); + + /* Initialize parameters of next transaction */ + data->rx_msg = data->in_msg; + data->tx_msg = data->out_msg; + data->rx_buf = inst->IBUF; + data->tx_buf = inst->OBUF; + data->sz_received = 0; + data->sz_sending = 0; + data->sz_request = 0; + data->sz_response = 0; + + /* + * Fill output buffer to indicate we`re + * ready to receive next transaction. + */ + for (i = 1; i < SHI_OBUF_FULL_SIZE; i++) { + inst->OBUF[i] = EC_SHI_RECEIVING; + } + inst->OBUF[0] = EC_SHI_RX_READY; + + /* SHI/Host Write/input buffer wrap-around enable */ + inst->SHICFG1 = BIT(NPCX_SHICFG1_IWRAP) | BIT(NPCX_SHICFG1_WEN) | BIT(NPCX_SHICFG1_EN); + + data->state = SHI_STATE_READY_TO_RECV; + data->last_error_state = SHI_STATE_NONE; + + shi_npcx_sec_ibf_int_enable(inst, 1); + irq_enable(DT_INST_IRQN(0)); + + LOG_DBG("RDY-"); +} + +static int shi_npcx_enable(const struct device *dev) +{ + const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); + const struct shi_npcx_config *const config = dev->config; + int ret; + + ret = clock_control_on(clk_dev, (clock_control_subsys_t *)&config->clk_cfg); + if (ret < 0) { + LOG_ERR("Turn on SHI clock fail %d", ret); + return ret; + } + + shi_npcx_reset_prepare(dev); + npcx_miwu_irq_disable(&config->shi_cs_wui); + + /* Configure pin control for SHI */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("shi_npcx pinctrl setup failed (%d)", ret); + return ret; + } + + NVIC_ClearPendingIRQ(DT_INST_IRQN(0)); + npcx_miwu_irq_enable(&config->shi_cs_wui); + irq_enable(DT_INST_IRQN(0)); + + return 0; +} + +static int shi_npcx_disable(const struct device *dev) +{ + const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); + const struct shi_npcx_config *const config = dev->config; + struct shi_npcx_data *data = dev->data; + int ret; + + data->state = SHI_STATE_DISABLED; + + irq_disable(DT_INST_IRQN(0)); + npcx_miwu_irq_disable(&config->shi_cs_wui); + + /* Configure pin control back to GPIO */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_ERR("KB Raw pinctrl setup failed (%d)", ret); + return ret; + } + + ret = clock_control_off(clk_dev, (clock_control_subsys_t *)&config->clk_cfg); + if (ret < 0) { + LOG_ERR("Turn off SHI clock fail %d", ret); + return ret; + } + + return 0; +} + +static int shi_npcx_init_registers(const struct device *dev) +{ + int ret; + const struct shi_npcx_config *const config = dev->config; + struct shi_reg *const inst = HAL_INSTANCE(dev); + const struct device *clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); + + /* Turn on shi device clock first */ + ret = clock_control_on(clk_dev, (clock_control_subsys_t *)&config->clk_cfg); + if (ret < 0) { + LOG_ERR("Turn on SHI clock fail %d", ret); + return ret; + } + + /* If booter doesn't set the host interface type */ + if (!NPCX_BOOTER_IS_HIF_TYPE_SET()) { + npcx_host_interface_sel(NPCX_HIF_TYPE_ESPI_SHI); + } + + /* + * SHICFG1 (SHI Configuration 1) setting + * [7] - IWRAP = 1: Wrap input buffer to the first address + * [6] - CPOL = 0: Sampling on rising edge and output on falling edge + * [5] - DAS = 0: return STATUS reg data after Status command + * [4] - AUTOBE = 0: Automatically update the OBES bit in STATUS reg + * [3] - AUTIBF = 0: Automatically update the IBFS bit in STATUS reg + * [2] - WEN = 0: Enable host write to input buffer + * [1] - Reserved 0 + * [0] - ENABLE = 0: Disable SHI at the beginning + */ + inst->SHICFG1 = BIT(NPCX_SHICFG1_IWRAP); + + /* + * SHICFG2 (SHI Configuration 2) setting + * [7] - Reserved 0 + * [6] - REEVEN = 0: Restart events are not used + * [5] - Reserved 0 + * [4] - REEN = 0: Restart transactions are not used + * [3] - SLWU = 0: Seem-less wake-up is enabled by default + * [2] - ONESHOT= 0: WEN is cleared at the end of a write transaction + * [1] - BUSY = 0: SHI bus is busy 0: idle. + * [0] - SIMUL = 1: Turn on simultaneous Read/Write + */ + inst->SHICFG2 = BIT(NPCX_SHICFG2_SIMUL); + + /* + * EVENABLE (Event Enable) setting + * [7] - IBOREN = 0: Input buffer overrun interrupt enable + * [6] - STSREN = 0: status read interrupt disable + * [5] - EOWEN = 0: End-of-Data for Write Transaction Interrupt Enable + * [4] - EOREN = 1: End-of-Data for Read Transaction Interrupt Enable + * [3] - IBHFEN = 1: Input Buffer Half Full Interrupt Enable + * [2] - IBFEN = 1: Input Buffer Full Interrupt Enable + * [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable + * [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable + */ + inst->EVENABLE = + BIT(NPCX_EVENABLE_EOREN) | BIT(NPCX_EVENABLE_IBHFEN) | BIT(NPCX_EVENABLE_IBFEN); + + /* + * EVENABLE2 (Event Enable 2) setting + * [2] - CSNFEEN = 1: SHI_CS Falling Edge Interrupt Enable + * [1] - CSNREEN = 1: SHI_CS Rising Edge Interrupt Enable + * [0] - IBHF2EN = 0: Input Buffer Half Full 2 Interrupt Enable + */ + inst->EVENABLE2 = BIT(NPCX_EVENABLE2_CSNREEN) | BIT(NPCX_EVENABLE2_CSNFEEN); + + /* Clear SHI events status register */ + inst->EVSTAT = 0xff; + + npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_LOW); + + /* SHI interrupt installation */ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), shi_npcx_isr, DEVICE_DT_INST_GET(0), + 0); + + shi_npcx_enable(dev); + + return ret; +} + +static int shi_npcx_init_peripheral(const struct device *dev) +{ + struct shi_npcx_data *data = dev->data; + + /* Allow writing to rx buff at startup and block on reading. */ + k_sem_init(&data->handler_owns, 0, 1); + k_sem_init(&data->dev_owns, 1, 1); + + return 0; +} + +static int shi_npcx_init(const struct device *dev) +{ + int ret; + + ret = shi_npcx_init_registers(dev); + if (ret) { + return ret; + } + + ret = shi_npcx_init_peripheral(dev); + if (ret) { + return ret; + } + + pm_device_init_suspended(dev); + return pm_device_runtime_enable(dev); +} + +static int shi_npcx_periph_init_context(const struct device *dev, + struct ec_host_cmd_periph_rx_ctx *rx_ctx) +{ + struct shi_npcx_data *data = dev->data; + + rx_ctx->dev_owns = &data->dev_owns; + rx_ctx->handler_owns = &data->handler_owns; + rx_ctx->buf = data->in_msg; + rx_ctx->len = &data->sz_received; + + return 0; +} + +static int shi_npcx_periph_send(const struct device *dev, + const struct ec_host_cmd_periph_tx_buf *in_buf) +{ + struct shi_npcx_data *data = dev->data; + uint8_t *out_buf = data->out_msg + EC_SHI_FRAME_START_LENGTH; + + /* + * Disable interrupts. This routine is not called from interrupt context and buffer + * underrun will likely occur if it is preempted after writing its initial reply byte. + * Also, we must be sure our state doesn't unexpectedly change, in case we're expected + * to take RESP_NOT_RDY actions. + */ + __disable_irq(); + + memcpy(out_buf, in_buf->buf, in_buf->len); + + if (data->state == SHI_STATE_PROCESSING) { + /* Append our past-end byte, which we reserved space for. */ + ((uint8_t *)out_buf)[in_buf->len] = EC_SHI_PAST_END; + + /* Computing sending bytes of response */ + data->sz_response = in_buf->len + EC_SHI_PROTO3_OVERHEAD; + + /* Start to fill output buffer with msg buffer */ + shi_npcx_write_first_pkg_outbuf(dev, data->sz_response); + + /* Transmit the reply */ + data->state = SHI_STATE_SENDING; + LOG_DBG("SND-"); + } else if (data->state == SHI_STATE_CNL_RESP_NOT_RDY) { + /* + * If we're not processing, then the AP has already terminated + * the transaction, and won't be listening for a response. + * Reset state machine for next transaction. + */ + shi_npcx_reset_prepare(dev); + LOG_DBG("END\n"); + } else { + LOG_ERR("Unexpected state %d in response handler", data->state); + } + + __enable_irq(); + return 0; +} + +static const struct ec_host_cmd_periph_api ec_host_cmd_api = { + .init = shi_npcx_periph_init_context, + .send = shi_npcx_periph_send, +}; + +#ifdef CONFIG_PM_DEVICE +static int shi_npcx_pm_cb(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + shi_npcx_disable(dev); + break; + case PM_DEVICE_ACTION_RESUME: + shi_npcx_enable(dev); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} +#endif + +/* Assume only one peripheral */ +PM_DEVICE_DT_INST_DEFINE(0, shi_npcx_pm_cb); + +PINCTRL_DT_INST_DEFINE(0); +static const struct shi_npcx_config shi_cfg = { + .base = DT_INST_REG_ADDR(0), + .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), + .irq = DT_INST_IRQN(0), + .shi_cs_wui = NPCX_DT_WUI_ITEM_BY_NAME(0, shi_cs_wui), +}; + +static struct shi_npcx_data shi_data = { + .state = SHI_STATE_DISABLED, + .last_error_state = SHI_STATE_NONE, + .out_msg = shi_data.out_msg_padded + SHI_OUT_START_PAD - EC_SHI_FRAME_START_LENGTH, +}; + +DEVICE_DT_INST_DEFINE(0, shi_npcx_init, PM_DEVICE_DT_INST_GET(0), &shi_data, &shi_cfg, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &ec_host_cmd_api); diff --git a/dts/arm/nuvoton/npcx.dtsi b/dts/arm/nuvoton/npcx.dtsi index e082823856d..aeeab4eca6f 100644 --- a/dts/arm/nuvoton/npcx.dtsi +++ b/dts/arm/nuvoton/npcx.dtsi @@ -354,6 +354,16 @@ status = "disabled"; }; + shi0: shi@4000f000 { + compatible = "nuvoton,npcx-shi"; + reg = <0x4000f000 0x120>; + interrupts = <18 1>; + clocks = <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 1>; + status = "disabled"; + buffer-rx-size = <128>; + buffer-tx-size = <128>; + }; + host_sub: lpc@400c1000 { compatible = "nuvoton,npcx-host-sub"; /* host sub-module register address & size */ diff --git a/dts/bindings/shi/nuvoton,npcx-shi.yaml b/dts/bindings/shi/nuvoton,npcx-shi.yaml new file mode 100644 index 00000000000..b24e3f3100a --- /dev/null +++ b/dts/bindings/shi/nuvoton,npcx-shi.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2022 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCX Serial Host Interface (SHI) node + +compatible: "nuvoton,npcx-shi" + +include: [pinctrl-device.yaml, shi-device.yaml] + +properties: + pinctrl-0: + required: true + + pinctrl-names: + required: true + + clocks: + required: true + description: configurations of device source clock controller + + shi-cs-wui: + type: phandle + required: true + description: | + Mapping table between Wake-Up Input (WUI) and SHI_CS signal. + + For example the WUI mapping on NPCX7 would be + shi-cs-wui = <&wui_io53>; diff --git a/dts/bindings/shi/shi-device.yaml b/dts/bindings/shi/shi-device.yaml new file mode 100644 index 00000000000..5354e16630b --- /dev/null +++ b/dts/bindings/shi/shi-device.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2022 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +include: [base.yaml] + +properties: + reg: + required: true + + buffer-rx-size: + type: int + required: true + description: | + Size of the internal buffer used for receiving data on the bus. + + buffer-tx-size: + type: int + required: true + description: | + Size of the internal buffer used for transmitting data over the bus. diff --git a/soc/arm/nuvoton_npcx/common/reg/reg_def.h b/soc/arm/nuvoton_npcx/common/reg/reg_def.h index 3971ff8f007..432786f8dfa 100644 --- a/soc/arm/nuvoton_npcx/common/reg/reg_def.h +++ b/soc/arm/nuvoton_npcx/common/reg/reg_def.h @@ -1633,4 +1633,88 @@ struct kbs_reg { #define KBS_CFG_INDX_RTYTO 2 /* Keyboard Scan Retry Timeout */ #define KBS_CFG_INDX_CNUM 3 /* Keyboard Scan Columns Number */ #define KBS_CFG_INDX_CDIV 4 /* Keyboard Scan Clock Divisor */ + +/* SHI (Serial Host Interface) registers */ +struct shi_reg { + volatile uint8_t reserved1; + /* 0x001: SHI Configuration 1 */ + volatile uint8_t SHICFG1; + /* 0x002: SHI Configuration 2 */ + volatile uint8_t SHICFG2; + volatile uint8_t reserved2[2]; + /* 0x005: Event Enable */ + volatile uint8_t EVENABLE; + /* 0x006: Event Status */ + volatile uint8_t EVSTAT; + /* 0x007: SHI Capabilities */ + volatile uint8_t CAPABILITY; + /* 0x008: Status */ + volatile uint8_t STATUS; + volatile uint8_t reserved3; + /* 0x00A: Input Buffer Status */ + volatile uint8_t IBUFSTAT; + /* 0x00B: Output Buffer Status */ + volatile uint8_t OBUFSTAT; + /* 0x00C: SHI Configuration 3 */ + volatile uint8_t SHICFG3; + /* 0x00D: SHI Configuration 4 */ + volatile uint8_t SHICFG4; + /* 0x00E: SHI Configuration 5 */ + volatile uint8_t SHICFG5; + /* 0x00F: Event Status 2 */ + volatile uint8_t EVSTAT2; + /* 0x010: Event Enable 2 */ + volatile uint8_t EVENABLE2; + volatile uint8_t reserved4[15]; + /* 0x20~0x9F: Output Buffer */ + volatile uint8_t OBUF[128]; + /* 0xA0~0x11F: Input Buffer */ + volatile uint8_t IBUF[128]; +}; + +/* SHI register fields */ +#define NPCX_SHICFG1_EN 0 +#define NPCX_SHICFG1_MODE 1 +#define NPCX_SHICFG1_WEN 2 +#define NPCX_SHICFG1_AUTIBF 3 +#define NPCX_SHICFG1_AUTOBE 4 +#define NPCX_SHICFG1_DAS 5 +#define NPCX_SHICFG1_CPOL 6 +#define NPCX_SHICFG1_IWRAP 7 +#define NPCX_SHICFG2_SIMUL 0 +#define NPCX_SHICFG2_BUSY 1 +#define NPCX_SHICFG2_ONESHOT 2 +#define NPCX_SHICFG2_SLWU 3 +#define NPCX_SHICFG2_REEN 4 +#define NPCX_SHICFG2_RESTART 5 +#define NPCX_SHICFG2_REEVEN 6 +#define NPCX_EVENABLE_OBEEN 0 +#define NPCX_EVENABLE_OBHEEN 1 +#define NPCX_EVENABLE_IBFEN 2 +#define NPCX_EVENABLE_IBHFEN 3 +#define NPCX_EVENABLE_EOREN 4 +#define NPCX_EVENABLE_EOWEN 5 +#define NPCX_EVENABLE_STSREN 6 +#define NPCX_EVENABLE_IBOREN 7 +#define NPCX_EVSTAT_OBE 0 +#define NPCX_EVSTAT_OBHE 1 +#define NPCX_EVSTAT_IBF 2 +#define NPCX_EVSTAT_IBHF 3 +#define NPCX_EVSTAT_EOR 4 +#define NPCX_EVSTAT_EOW 5 +#define NPCX_EVSTAT_STSR 6 +#define NPCX_EVSTAT_IBOR 7 +#define NPCX_STATUS_OBES 6 +#define NPCX_STATUS_IBFS 7 +#define NPCX_SHICFG3_OBUFLVLDIS 7 +#define NPCX_SHICFG4_IBUFLVLDIS 7 +#define NPCX_SHICFG5_IBUFLVL2 FIELD(0, 6) +#define NPCX_SHICFG5_IBUFLVL2DIS 7 +#define NPCX_EVSTAT2_IBHF2 0 +#define NPCX_EVSTAT2_CSNRE 1 +#define NPCX_EVSTAT2_CSNFE 2 +#define NPCX_EVENABLE2_IBHF2EN 0 +#define NPCX_EVENABLE2_CSNREEN 1 +#define NPCX_EVENABLE2_CSNFEEN 2 + #endif /* _NUVOTON_NPCX_REG_DEF_H */ diff --git a/subsys/mgmt/ec_host_cmd/Kconfig b/subsys/mgmt/ec_host_cmd/Kconfig index 799c3e711e0..72e243100de 100644 --- a/subsys/mgmt/ec_host_cmd/Kconfig +++ b/subsys/mgmt/ec_host_cmd/Kconfig @@ -21,6 +21,7 @@ config EC_HOST_CMD_HANDLER_STACK_SIZE config EC_HOST_CMD_HANDLER_TX_BUFFER int "Buffer size in bytes for TX buffer shared by all EC host commands" + default EC_HOST_CMD_PERIPH_SHI_MAX_RESPONSE if EC_HOST_CMD_PERIPH_SHI default 256 config EC_HOST_CMD_HANDLER_PRIO