drivers: espi: npcx: add espi taf support for npck3
This commit adds eSPI TAF support for npck3, including initialization
settings for flash operation mode. It also updates the mechanism to
release FLASH_NP_FREE, preventing a possible race condition between
automatic and standard requests.
Signed-off-by: Tom Chang <CHChang19@nuvoton.com>
diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx
index 684a34c..c5c4e7b 100644
--- a/drivers/espi/Kconfig.npcx
+++ b/drivers/espi/Kconfig.npcx
@@ -103,11 +103,11 @@
config ESPI_TAF_NPCX
bool "Nuvoton NPCX embedded controller (EC) ESPI TAF driver"
- depends on ESPI_NPCX_NPCXN_V3
+ depends on ESPI_NPCX_NPCXN_V3 || ESPI_NPCX_NPCKN_V1
depends on FLASH
help
This option enables the Intel Enhanced Serial Peripheral Interface
- Target Attached Flash (eSPI TAF) for NPCX4 family of processors.
+ Target Attached Flash (eSPI TAF) for NPCX4/NPCK3 family of processors.
choice ESPI_TAF_ACCESS_MODE_CHOICE
prompt "eSPI TAF Read Access Mode"
@@ -125,6 +125,15 @@
endchoice
+config ESPI_TAF_TX_AVAIL_CHECK_TIME
+ int "Flash TX Available Check Time (microseconds)"
+ default 1000000
+ depends on ESPI_TAF_NPCX
+ help
+ This option sets the time interval (in microseconds) for checking
+ whether the host has sent a GET_FLASH_C command to retrieve the
+ result.
+
config ESPI_TAF_PR_NUM
int "Sets of protection region settings"
default 16
diff --git a/drivers/espi/espi_taf_npcx.c b/drivers/espi/espi_taf_npcx.c
index 665c8e0b..316f7ef 100644
--- a/drivers/espi/espi_taf_npcx.c
+++ b/drivers/espi/espi_taf_npcx.c
@@ -10,6 +10,7 @@
#include <zephyr/drivers/espi.h>
#include <zephyr/drivers/espi_saf.h>
#include <zephyr/drivers/flash.h>
+#include <zephyr/dt-bindings/flash_controller/npcx_fiu_qspi.h>
#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT
#include <zephyr/drivers/flash/npcx_flash_api_ex.h>
#endif
@@ -39,7 +40,6 @@
struct espi_taf_npcx_config {
uintptr_t base;
uintptr_t mapped_addr;
- uintptr_t rx_plsz;
enum NPCX_ESPI_TAF_ERASE_BLOCK_SIZE erase_sz;
enum NPCX_ESPI_TAF_MAX_READ_REQ max_rd_sz;
#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT
@@ -74,9 +74,9 @@
((struct espi_reg *)((const struct espi_taf_npcx_config *) \
(dev)->config)->base)
-#define FLBASE_ADDR ( \
- GET_FIELD(inst->FLASHBASE, NPCX_FLASHBASE_FLBASE_ADDR) \
- << GET_FIELD_POS(NPCX_FLASHBASE_FLBASE_ADDR))
+#define PROT_FLBASE_ADDR ( \
+ GET_FIELD(inst->FLASHBASE, NPCX_FLASH_PRTR_BADDR) \
+ << GET_FIELD_POS(NPCX_FLASH_PRTR_BADDR))
#define PRTR_BADDR(i) ( \
GET_FIELD(inst->FLASH_PRTR_BADDR[i], NPCX_FLASH_PRTR_BADDR) \
@@ -86,6 +86,11 @@
GET_FIELD(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \
<< GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF;
+#define DT_NODE_QUAD_PROP_OR(node) \
+ COND_CODE_1(DT_NODE_HAS_PROP(node, quad_enable_requirements), \
+ (DT_PROP(node, quad_enable_requirements)), \
+ (("NONE")))
+
static void espi_taf_get_pckt(const struct device *dev, struct espi_taf_npcx_data *pckt,
struct espi_event event)
{
@@ -104,6 +109,34 @@
}
}
+#if defined(CONFIG_ESPI_NPCX_NPCKN_V1)
+static void espi_taf_fiu_mode_set(void)
+{
+ struct fiu_reg *const inst = (struct fiu_reg *)DT_INST_REG_ADDR_BY_NAME(0, fiu1);
+
+ if (strcmp(DT_NODE_QUAD_PROP_OR(NPCX_TAF_PRIME_FLASH_NODE), "NONE") != 0) {
+ /* Set quad read for FIU1 */
+ SET_FIELD(inst->SPI_FL_CFG, NPCX_SPI_FL_CFG_RD_MODE, NPCX_RD_MODE_FAST_DUAL);
+ inst->RESP_CFG |= BIT(NPCX_RESP_CFG_QUAD_EN);
+ }
+
+ if (DT_PROP(NPCX_TAF_PRIME_FLASH_NODE, enter_4byte_addr) != 0) {
+ int flags = DT_PROP(NPCX_TAF_PRIME_FLASH_NODE, qspi_flags);
+
+ /* Enable 4 byte address mode for FIU1 */
+ if ((flags & NPCX_QSPI_SHD_FLASH_SL) != 0) {
+ inst->FIU_4B_EN |= BIT(NPCX_MSR_FIU_4B_EN_SHD_4B);
+ } else if ((flags & NPCX_QSPI_PVT_FLASH_SL) != 0) {
+ inst->FIU_4B_EN |= BIT(NPCX_MSR_FIU_4B_EN_PVT_4B);
+ } else if ((flags & NPCX_QSPI_BKP_FLASH_SL) != 0) {
+ inst->FIU_4B_EN |= BIT(NPCX_MSR_FIU_4B_EN_BKP_4B);
+ } else {
+ LOG_ERR("No valid flash selected");
+ }
+ }
+}
+#endif
+
#if defined(CONFIG_ESPI_TAF_MANUAL_MODE)
/* Check access region of read request is protected or not */
static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, uint32_t len,
@@ -116,7 +149,7 @@
uint32_t base, high;
bool rdpr;
- flash_addr += FLBASE_ADDR;
+ flash_addr += PROT_FLBASE_ADDR;
for (i = 0; i < CONFIG_ESPI_TAF_PR_NUM; i++) {
base = PRTR_BADDR(i);
@@ -146,7 +179,7 @@
uint32_t base, high;
bool wrpr;
- flash_addr += FLBASE_ADDR;
+ flash_addr += PROT_FLBASE_ADDR;
for (i = 0; i < CONFIG_ESPI_TAF_PR_NUM; i++) {
base = PRTR_BADDR(i);
@@ -187,8 +220,8 @@
const struct espi_saf_pr *preg = pr->pregions;
size_t n = pr->nregions;
uint8_t regnum;
- uint16_t bitmask, offset;
- uint32_t rw_pr, override_rw;
+ uint16_t offset;
+ uint32_t bitmask, rw_pr, override_rw;
if ((dev == NULL) || (pr == NULL)) {
return -EINVAL;
@@ -212,10 +245,11 @@
bitmask = BIT_MASK(GET_FIELD_SZ(NPCX_FLASH_PRTR_BADDR));
offset = GET_FIELD_POS(NPCX_FLASH_PRTR_BADDR);
inst->FLASH_PRTR_BADDR[regnum] = ((preg->start & bitmask) << offset)
- | rw_pr;
+ | rw_pr | PROT_FLBASE_ADDR;
bitmask = BIT_MASK(GET_FIELD_SZ(NPCX_FLASH_PRTR_HADDR));
offset = GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR);
- inst->FLASH_PRTR_HADDR[regnum] = (preg->end & bitmask) << offset;
+ inst->FLASH_PRTR_HADDR[regnum] = (preg->end & bitmask) << offset
+ | PROT_FLBASE_ADDR;
}
override_rw = (preg->override_r << 16) | preg->override_w;
@@ -230,8 +264,12 @@
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
+#ifdef CONFIG_ESPI_NPCX_NPCKN_V1
+ inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_PROT_LOCK);
+#else
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_AUTO_RD_DIS_CTL);
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_BLK_FLASH_NP_FREE);
+#endif
return 0;
}
@@ -279,12 +317,14 @@
static void taf_release_flash_np_free(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
- uint32_t tmp = inst->FLASHCTL;
+ uint32_t tmp;
- /*
- * Clear FLASHCTL_FLASH_ACC_TX_AVAIL to avoid host puts a
- * GET_FLASH_C command at here.
- */
+ if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_ACC_TX_AVAIL),
+ CONFIG_ESPI_TAF_TX_AVAIL_CHECK_TIME, NULL) == false) {
+ LOG_ERR("Flash_ACC_TX_AVAIL is not cleared");
+ }
+
+ tmp = inst->FLASHCTL;
tmp &= NPCX_FLASHCTL_ACCESS_MASK;
/* Release FLASH_NP_FREE */
@@ -316,7 +356,7 @@
* FLASH_ACC_TX_AVAIL.
*/
if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_ACC_TX_AVAIL),
- NPCX_FLASH_CHK_TIMEOUT, NULL) == false) {
+ CONFIG_ESPI_TAF_TX_AVAIL_CHECK_TIME, NULL) == false) {
LOG_ERR("Check TX Queue Is Empty Timeout");
return -EBUSY;
}
@@ -342,7 +382,6 @@
static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_packet *pckt)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
- struct espi_taf_npcx_config *config = ((struct espi_taf_npcx_config *)(dev)->config);
struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf;
uint8_t cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY;
uint32_t total_len = pckt->len;
@@ -371,12 +410,12 @@
return -EINVAL;
}
- if (total_len <= config->rx_plsz) {
+ if (total_len <= MAX_TX_PAYLOAD_SIZE) {
cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY;
len = total_len;
} else {
cycle_type = CYC_SCS_CMP_WITH_DATA_FIRST;
- len = config->rx_plsz;
+ len = MAX_TX_PAYLOAD_SIZE;
}
do {
@@ -423,7 +462,7 @@
total_len -= len;
addr += len;
- if (total_len <= config->rx_plsz) {
+ if (total_len <= MAX_TX_PAYLOAD_SIZE) {
cycle_type = CYC_SCS_CMP_WITH_DATA_LAST;
len = total_len;
} else {
@@ -668,6 +707,7 @@
int espi_taf_npcx_block(const struct device *dev, bool en_block)
{
+#ifdef CONFIG_ESPI_NPCX_NPCXN_V3
struct espi_reg *const inst = HAL_INSTANCE(dev);
if (!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_SAF_AUTO_READ)) {
@@ -694,7 +734,7 @@
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_AUTO_RD_DIS_CTL);
inst->ESPISTS |= BIT(NPCX_ESPISTS_AUTO_RD_DIS_STS);
}
-
+#endif
return 0;
}
@@ -745,9 +785,19 @@
count_num = config->rpmc_cnt_num - 1;
}
+#if defined(CONFIG_ESPI_NPCX_NPCXN_V3)
SET_FIELD(inst->FLASH_RPMC_CFG_1, NPCX_FLASH_RPMC_CFG1_CNTR, count_num);
SET_FIELD(inst->FLASH_RPMC_CFG_1, NPCX_FLASH_RPMC_CFG1_OP1, config->rpmc_op1_code);
SET_FIELD(inst->FLASH_RPMC_CFG_1, NPCX_FLASH_RPMC_CFG1_TRGRPMCSUP, config->rpmc_cnt_num);
+#elif defined(CONFIG_ESPI_NPCX_NPCKN_V1)
+ SET_FIELD(inst->FLASHCFG2, NPCX_FLASHCFG2_RPMC1COUNT, count_num);
+ SET_FIELD(inst->FLASHCFG2, NPCX_FLASHCFG2_RPMC1OP1CODE, config->rpmc_op1_code);
+ SET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_TRGRPMCSUPP, config->rpmc_cnt_num);
+#endif
+#endif
+
+#if defined(CONFIG_ESPI_NPCX_NPCKN_V1)
+ espi_taf_fiu_mode_set();
#endif
return 0;
@@ -763,7 +813,6 @@
static const struct espi_taf_npcx_config espi_taf_npcx_config = {
.base = DT_INST_REG_ADDR(0),
.mapped_addr = DT_INST_PROP(0, mapped_addr),
- .rx_plsz = DT_PROP(DT_INST_PARENT(0), rx_plsize),
.erase_sz = DT_INST_STRING_TOKEN(0, erase_sz),
.max_rd_sz = DT_INST_STRING_TOKEN(0, max_read_sz),
#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT
diff --git a/soc/nuvoton/npcx/common/npckn/include/reg_def.h b/soc/nuvoton/npcx/common/npckn/include/reg_def.h
index d1ce638..e7bef8f 100644
--- a/soc/nuvoton/npcx/common/npckn/include/reg_def.h
+++ b/soc/nuvoton/npcx/common/npckn/include/reg_def.h
@@ -762,7 +762,10 @@
#define NPCX_FLASHCFG_FLASHREQSIZE FIELD(13, 3)
#define NPCX_FLASHCFG_FLCAPA FIELD(16, 2)
#define NPCX_FLASHCFG_TRGFLEBLKSIZE FIELD(18, 8)
+#define NPCX_FLASHCFG_TRGRPMCSUPP FIELD(26, 6)
#define NPCX_FLASHCFG_FLREQSUP FIELD(0, 3)
+#define NPCX_FLASHCFG2_RPMC1OP1CODE FIELD(24, 8)
+#define NPCX_FLASHCFG2_RPMC1COUNT FIELD(20, 4)
#define NPCX_FLASHCTL_FLASH_NP_FREE 0
#define NPCX_FLASHCTL_FLASH_ACC_TX_AVAIL 1
#define NPCX_FLASHCTL_STRPHDR 2
diff --git a/soc/nuvoton/npcx/common/soc_espi_taf.h b/soc/nuvoton/npcx/common/soc_espi_taf.h
index a838673..badfb9a 100644
--- a/soc/nuvoton/npcx/common/soc_espi_taf.h
+++ b/soc/nuvoton/npcx/common/soc_espi_taf.h
@@ -60,9 +60,6 @@
/* ESPI TAF RPMC OP2 instruction */
#define ESPI_TAF_RPMC_OP2_CMD 0x96
-/* Timeout for checking transmit buffer available and no completion was sent */
-#define NPCX_FLASH_CHK_TIMEOUT 10000
-
/* Clear RSTBUFHEADS, FLASH_ACC_TX_AVAIL, and FLASH_ACC_NP_FREE */
#define NPCX_FLASHCTL_ACCESS_MASK (~(BIT(NPCX_FLASHCTL_RSTBUFHEADS) | \
BIT(NPCX_FLASHCTL_FLASH_NP_FREE) | \