Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions dts/arm/nuvoton/npcx9m7fb.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@

/ {
flash0: flash@10070000 {
reg = <0x10070000 DT_SIZE_K(320)>;
reg = <0x10070000 DT_SIZE_K(256)>;
};

flash1: flash@64000000 {
reg = <0x64000000 DT_SIZE_K(1024)>;
reg = <0x64000000 DT_SIZE_K(512)>;
};

sram0: memory@200c0000 {
compatible = "mmio-sram";
reg = <0x200C0000 DT_SIZE_K(64)>;
reg = <0x200B0000 DT_SIZE_K(128)>;
};

soc-id {
Expand All @@ -29,7 +29,7 @@
&qspi_fiu0 {
int_flash: w25q80@0 {
compatible ="nuvoton,npcx-fiu-nor";
size = <DT_SIZE_M(1 * 8)>;
size = <DT_SIZE_K(512 * 8)>;
reg = <0>;
status = "okay";

Expand All @@ -40,3 +40,11 @@
pinctrl-names = "default";
};
};

/*
* Raising the interrupt priority of the MIWU group, which owns SHI CS, to the same as
* SHI's priority.
*/
&group_f1 {
irq-prio = <1>;
};
7 changes: 7 additions & 0 deletions subsys/mgmt/ec_host_cmd/backends/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ config EC_HOST_CMD_BACKEND_SHI_NPCX_ENHANCED_BUF_MODE
single-byte output buffer can be selected/switched to generate a
response to simultaneous Read/Write transactions.

config EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
bool
default y if SOC_NPCX9M7FB
help
Workaround the issue "CSnFE and CSnRE bits of EVSTATS2 Register (SHI)"
in the npcx9m7fb SoC errata.

config EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST
int "Max data size for the version 3 request packet"
default 544 if EC_HOST_CMD_BACKEND_SHI_NPCX
Expand Down
61 changes: 58 additions & 3 deletions subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ struct shi_npcx_data {
uint8_t *const out_msg;
uint8_t in_msg[CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST] __aligned(4);
ATOMIC_DEFINE(pm_policy_state_flag, SHI_NPCX_PM_POLICY_FLAG_COUNT);
#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
struct miwu_callback shi_cs_wui_cb;
/*
* With the workaround, CS assertion/de-assertion INT and SHI module's INT come from
* different sources. CS failing IRQ and IBHF2 IRQ may happen at the same time.
* In this case, IBHF2 ISR is called first because it has lower INT number.
* (with the same priority). This flag is used to guarantee CS assertion ISR is executed
* first.
*/
bool is_entered_cs_asserted_wui_isr;
#endif
};

struct ec_host_cmd_shi_npcx_ctx {
Expand Down Expand Up @@ -605,7 +616,7 @@ static void shi_npcx_handle_cs_deassert(const struct device *dev)

/* Error state for checking*/
if (data->state != SHI_STATE_SENDING) {
shi_npcx_log_unexpected_state(dev, "CSNRE");
shi_npcx_log_unexpected_state(dev, "CS DE-AST");
}

/* reset SHI and prepare to next transaction again */
Expand Down Expand Up @@ -670,11 +681,20 @@ static void shi_npcx_isr(const struct device *dev)
uint8_t stat;
uint8_t stat2;

#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
struct shi_npcx_data *data = dev->data;

if (data->is_entered_cs_asserted_wui_isr != true) {
return;
}
#endif

/* Read status register and clear interrupt status early */
stat = inst->EVSTAT;
inst->EVSTAT = stat;
stat2 = inst->EVSTAT2;

#ifndef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
/* SHI CS pin is asserted in EVSTAT2 */
if (IS_BIT_SET(stat2, NPCX_EVSTAT2_CSNFE)) {
/* Clear pending bit of CSNFE */
Expand All @@ -692,7 +712,6 @@ static void shi_npcx_isr(const struct device *dev)

shi_npcx_handle_cs_assert(dev);
}

/*
* End of data for read/write transaction. i.e. SHI_CS is deasserted.
* Host completed or aborted transaction
Expand All @@ -712,6 +731,7 @@ static void shi_npcx_isr(const struct device *dev)
LOG_DBG("CSH-");
return shi_npcx_handle_cs_deassert(dev);
}
#endif

/*
* The number of bytes received reaches the size of
Expand Down Expand Up @@ -821,6 +841,11 @@ static int shi_npcx_enable(const struct device *dev)
}

NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
/*
* Clear the pending bit because switching the pinmux (pinctrl) might casue a faking WUI
* pending bit set.
*/
npcx_miwu_irq_get_and_clear_pending(&config->shi_cs_wui);
npcx_miwu_irq_enable(&config->shi_cs_wui);
irq_enable(DT_INST_IRQN(0));

Expand Down Expand Up @@ -861,6 +886,23 @@ static int shi_npcx_disable(const struct device *dev)
return 0;
}

#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
static void shi_npcx_cs_wui_isr(const struct device *dev, struct npcx_wui *wui)
{

struct shi_reg *const inst = HAL_INSTANCE(dev);
struct shi_npcx_data *data = dev->data;

if (IS_BIT_SET(inst->SHICFG2, NPCX_SHICFG2_BUSY)) {
data->is_entered_cs_asserted_wui_isr = true;
shi_npcx_handle_cs_assert(dev);
} else {
shi_npcx_handle_cs_deassert(dev);
data->is_entered_cs_asserted_wui_isr = false;
}
}
#endif

static int shi_npcx_init_registers(const struct device *dev)
{
int ret;
Expand Down Expand Up @@ -912,15 +954,17 @@ static int shi_npcx_init_registers(const struct device *dev)
* [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable
* [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable
*/
inst->EVENABLE = BIT(NPCX_EVENABLE_EOREN) | IBF_IBHF_EN_MASK;
inst->EVENABLE = IBF_IBHF_EN_MASK;

/*
* 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
*/
#ifndef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
inst->EVENABLE2 = BIT(NPCX_EVENABLE2_CSNREEN) | BIT(NPCX_EVENABLE2_CSNFEEN);
#endif

/* Clear SHI events status register */
inst->EVSTAT = 0xff;
Expand All @@ -929,7 +973,18 @@ static int shi_npcx_init_registers(const struct device *dev)
inst->SHICFG6 |= BIT(NPCX_SHICFG6_EBUFMD);
}

#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
struct shi_npcx_data *data = dev->data;

npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE,
NPCX_MIWU_TRIG_BOTH);

npcx_miwu_init_dev_callback(&data->shi_cs_wui_cb, &config->shi_cs_wui, shi_npcx_cs_wui_isr,
dev);
npcx_miwu_manage_callback(&data->shi_cs_wui_cb, true);
#else
npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_LOW);
#endif

/* SHI interrupt installation */
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), shi_npcx_isr, DEVICE_DT_INST_GET(0),
Expand Down
Loading