@@ -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
144155struct 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+
864906static 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