drivers: espi: npcx: workaround Global Reset issue
Apply the workaround for the issue "eSPI global reset" in the NPCX49nF_Errata Signed-off-by: Tom Chang <CHChang19@nuvoton.com>
This commit is contained in:
parent
d921659d6a
commit
0e4b5de6ca
|
@ -118,4 +118,10 @@ config ESPI_NPCX_SUPP_VW_GPIO
|
|||
help
|
||||
Selected if NPCX series supports virtual wire GPIOs in eSPI module.
|
||||
|
||||
config ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND
|
||||
bool
|
||||
default y if SOC_SERIES_NPCX4 && ESPI_FLASH_CHANNEL
|
||||
help
|
||||
Workaround the issue "Global Reset" in the npcx4 SoC errata.
|
||||
|
||||
endif #ESPI_NPCX
|
||||
|
|
|
@ -46,6 +46,10 @@ struct espi_npcx_data {
|
|||
#if defined(CONFIG_ESPI_FLASH_CHANNEL)
|
||||
struct k_sem flash_rx_lock;
|
||||
#endif
|
||||
#ifdef CONFIG_ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND
|
||||
/* tell the interrupt handler that it is a fake request */
|
||||
bool fake_req_flag;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Driver convenience defines */
|
||||
|
@ -190,6 +194,13 @@ static int espi_npcx_send_vwire(const struct device *dev,
|
|||
enum espi_vwire_signal signal, uint8_t level);
|
||||
static void espi_vw_send_bootload_done(const struct device *dev);
|
||||
|
||||
#if defined(CONFIG_ESPI_FLASH_CHANNEL)
|
||||
static int espi_npcx_flash_parse_completion_with_data(const struct device *dev,
|
||||
struct espi_flash_packet *pckt);
|
||||
static void espi_npcx_flash_prepare_tx_header(const struct device *dev, int cyc_type,
|
||||
int flash_addr, int flash_len, int tx_payload);
|
||||
#endif
|
||||
|
||||
/* eSPI local initialization functions */
|
||||
static void espi_init_wui_callback(const struct device *dev,
|
||||
struct miwu_callback *callback, const struct npcx_wui *wui,
|
||||
|
@ -232,6 +243,20 @@ static void espi_bus_reset_isr(const struct device *dev)
|
|||
/* Do nothing! This signal is handled in ESPI_RST VW signal ISR */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND)
|
||||
static void espi_npcx_flash_fake_request(const struct device *dev)
|
||||
{
|
||||
struct espi_reg *const inst = HAL_INSTANCE(dev);
|
||||
struct espi_npcx_data *const data = dev->data;
|
||||
|
||||
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_AMTEN);
|
||||
|
||||
data->fake_req_flag = true;
|
||||
|
||||
espi_npcx_flash_prepare_tx_header(dev, ESPI_FLASH_READ_CYCLE_TYPE, 0, 16, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void espi_bus_cfg_update_isr(const struct device *dev)
|
||||
{
|
||||
int chan;
|
||||
|
@ -259,6 +284,13 @@ static void espi_bus_cfg_update_isr(const struct device *dev)
|
|||
NPCX_ESPI_HOST_CH_EN(chan));
|
||||
evt.evt_details = BIT(chan);
|
||||
|
||||
#if defined(CONFIG_ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND)
|
||||
if (chan == NPCX_ESPI_CH_FLASH && evt.evt_data == 1 &&
|
||||
IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL)) {
|
||||
espi_npcx_flash_fake_request(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (evt.evt_data) {
|
||||
inst->ESPICFG |= BIT(chan);
|
||||
} else {
|
||||
|
@ -358,6 +390,17 @@ static void espi_bus_flash_rx_isr(const struct device *dev)
|
|||
|
||||
/* Controller Attached Flash Access */
|
||||
if ((inst->ESPICFG & BIT(NPCX_ESPICFG_FLCHANMODE)) == 0) {
|
||||
#ifdef CONFIG_ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND
|
||||
if (data->fake_req_flag == true) {
|
||||
uint8_t pckt_buf[16];
|
||||
struct espi_flash_packet pckt;
|
||||
|
||||
pckt.buf = &pckt_buf[0];
|
||||
espi_npcx_flash_parse_completion_with_data(dev, &pckt);
|
||||
data->fake_req_flag = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
k_sem_give(&data->flash_rx_lock);
|
||||
} else { /* Target Attached Flash Access */
|
||||
#if defined(CONFIG_ESPI_SAF)
|
||||
|
|
Loading…
Reference in a new issue