Skip to content

Commit 3ef6fe9

Browse files
TomChang19nashif
authored andcommitted
mgmt: ec_host_cmd: npcx: workaround for backend SHI
There is an issue on the SHI hardware peripheral to detect CS rising/failing with bits CSnFE/CSnRE in the EVSTAT2 register in npcx9m7fb chip. This commit workarounds it by using MIWU to detect the CS rising and failing. Signed-off-by: Tom Chang <[email protected]> Signed-off-by: Jun Lin <[email protected]> (cherry picked from commit 0726198)
1 parent 46edf3b commit 3ef6fe9

File tree

3 files changed

+73
-3
lines changed

3 files changed

+73
-3
lines changed

dts/arm/nuvoton/npcx9m7fb.dtsi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@
4040
pinctrl-names = "default";
4141
};
4242
};
43+
44+
/*
45+
* Raising the interrupt priority of the MIWU group, which owns SHI CS, to the same as
46+
* SHI's priority.
47+
*/
48+
&group_f1 {
49+
irq-prio = <1>;
50+
};

subsys/mgmt/ec_host_cmd/backends/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ config EC_HOST_CMD_BACKEND_SHI_NPCX_ENHANCED_BUF_MODE
7575
single-byte output buffer can be selected/switched to generate a
7676
response to simultaneous Read/Write transactions.
7777

78+
config EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
79+
bool
80+
default y if SOC_NPCX9M7FB
81+
help
82+
Workaround the issue "CSnFE and CSnRE bits of EVSTATS2 Register (SHI)"
83+
in the npcx9m7fb SoC errata.
84+
7885
config EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST
7986
int "Max data size for the version 3 request packet"
8087
default 544 if EC_HOST_CMD_BACKEND_SHI_NPCX

subsys/mgmt/ec_host_cmd/backends/ec_host_cmd_backend_shi_npcx.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ struct shi_npcx_data {
139139
uint8_t *const out_msg;
140140
uint8_t in_msg[CONFIG_EC_HOST_CMD_BACKEND_SHI_MAX_REQUEST] __aligned(4);
141141
ATOMIC_DEFINE(pm_policy_state_flag, SHI_NPCX_PM_POLICY_FLAG_COUNT);
142+
#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
143+
struct miwu_callback shi_cs_wui_cb;
144+
/*
145+
* With the workaround, CS assertion/de-assertion INT and SHI module's INT come from
146+
* different sources. CS failing IRQ and IBHF2 IRQ may happen at the same time.
147+
* In this case, IBHF2 ISR is called first because it has lower INT number.
148+
* (with the same priority). This flag is used to guarantee CS assertion ISR is executed
149+
* first.
150+
*/
151+
bool is_entered_cs_asserted_wui_isr;
152+
#endif
142153
};
143154

144155
struct ec_host_cmd_shi_npcx_ctx {
@@ -605,7 +616,7 @@ static void shi_npcx_handle_cs_deassert(const struct device *dev)
605616

606617
/* Error state for checking*/
607618
if (data->state != SHI_STATE_SENDING) {
608-
shi_npcx_log_unexpected_state(dev, "CSNRE");
619+
shi_npcx_log_unexpected_state(dev, "CS DE-AST");
609620
}
610621

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

684+
#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
685+
struct shi_npcx_data *data = dev->data;
686+
687+
if (data->is_entered_cs_asserted_wui_isr != true) {
688+
return;
689+
}
690+
#endif
691+
673692
/* Read status register and clear interrupt status early */
674693
stat = inst->EVSTAT;
675694
inst->EVSTAT = stat;
676695
stat2 = inst->EVSTAT2;
677696

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

693713
shi_npcx_handle_cs_assert(dev);
694714
}
695-
696715
/*
697716
* End of data for read/write transaction. i.e. SHI_CS is deasserted.
698717
* Host completed or aborted transaction
@@ -712,6 +731,7 @@ static void shi_npcx_isr(const struct device *dev)
712731
LOG_DBG("CSH-");
713732
return shi_npcx_handle_cs_deassert(dev);
714733
}
734+
#endif
715735

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

823843
NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
844+
/*
845+
* Clear the pending bit because switching the pinmux (pinctrl) might casue a faking WUI
846+
* pending bit set.
847+
*/
848+
npcx_miwu_irq_get_and_clear_pending(&config->shi_cs_wui);
824849
npcx_miwu_irq_enable(&config->shi_cs_wui);
825850
irq_enable(DT_INST_IRQN(0));
826851

@@ -861,6 +886,23 @@ static int shi_npcx_disable(const struct device *dev)
861886
return 0;
862887
}
863888

889+
#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
890+
static void shi_npcx_cs_wui_isr(const struct device *dev, struct npcx_wui *wui)
891+
{
892+
893+
struct shi_reg *const inst = HAL_INSTANCE(dev);
894+
struct shi_npcx_data *data = dev->data;
895+
896+
if (IS_BIT_SET(inst->SHICFG2, NPCX_SHICFG2_BUSY)) {
897+
data->is_entered_cs_asserted_wui_isr = true;
898+
shi_npcx_handle_cs_assert(dev);
899+
} else {
900+
shi_npcx_handle_cs_deassert(dev);
901+
data->is_entered_cs_asserted_wui_isr = false;
902+
}
903+
}
904+
#endif
905+
864906
static int shi_npcx_init_registers(const struct device *dev)
865907
{
866908
int ret;
@@ -912,15 +954,17 @@ static int shi_npcx_init_registers(const struct device *dev)
912954
* [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable
913955
* [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable
914956
*/
915-
inst->EVENABLE = BIT(NPCX_EVENABLE_EOREN) | IBF_IBHF_EN_MASK;
957+
inst->EVENABLE = IBF_IBHF_EN_MASK;
916958

917959
/*
918960
* EVENABLE2 (Event Enable 2) setting
919961
* [2] - CSNFEEN = 1: SHI_CS Falling Edge Interrupt Enable
920962
* [1] - CSNREEN = 1: SHI_CS Rising Edge Interrupt Enable
921963
* [0] - IBHF2EN = 0: Input Buffer Half Full 2 Interrupt Enable
922964
*/
965+
#ifndef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
923966
inst->EVENABLE2 = BIT(NPCX_EVENABLE2_CSNREEN) | BIT(NPCX_EVENABLE2_CSNFEEN);
967+
#endif
924968

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

976+
#ifdef CONFIG_EC_HOST_CMD_BACKEND_SHI_NPCX_CS_DETECT_WORKAROUND
977+
struct shi_npcx_data *data = dev->data;
978+
979+
npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE,
980+
NPCX_MIWU_TRIG_BOTH);
981+
982+
npcx_miwu_init_dev_callback(&data->shi_cs_wui_cb, &config->shi_cs_wui, shi_npcx_cs_wui_isr,
983+
dev);
984+
npcx_miwu_manage_callback(&data->shi_cs_wui_cb, true);
985+
#else
932986
npcx_miwu_interrupt_configure(&config->shi_cs_wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_LOW);
987+
#endif
933988

934989
/* SHI interrupt installation */
935990
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), shi_npcx_isr, DEVICE_DT_INST_GET(0),

0 commit comments

Comments
 (0)