diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index 884b5cdd4d9..94624c9a26e 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -90,6 +90,13 @@ config ESPI_TAF_PR_NUM This size is display how many group of slave attached flash protection region. +config ESPI_TAF_NPCX_RPMC_SUPPORT + bool "eSPI TAF RPMC support" + depends on ESPI_TAF_NPCX + select FLASH_EX_OP_ENABLED + help + This option enable the handler for eSPI TAF RPMC request. + # The default value 'y' for the existing options if ESPI_NPCX is selected. if ESPI_NPCX diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index b134efadefa..28c88b7fc6a 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -402,8 +402,10 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_addr = inst->FLASHRXBUF[1]; taf_pckt.addr = sys_cpu_to_be32(taf_addr); - /* Get written data if eSPI TAF write */ - if (taf_pckt.type == NPCX_ESPI_TAF_REQ_WRITE) { + /* Get written data if eSPI TAF write or RPMC OP1 */ + if ((taf_pckt.type == NPCX_ESPI_TAF_REQ_WRITE) || + (IS_ENABLED(CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT) && + (taf_pckt.type == NPCX_ESPI_TAF_REQ_RPMC_OP1))) { roundsize = DIV_ROUND_UP(taf_pckt.len, sizeof(uint32_t)); for (i = 0; i < roundsize; i++) { taf_pckt.src[i] = inst->FLASHRXBUF[2 + i]; diff --git a/drivers/espi/espi_taf_npcx.c b/drivers/espi/espi_taf_npcx.c index 7878df2b123..997c5364fd5 100644 --- a/drivers/espi/espi_taf_npcx.c +++ b/drivers/espi/espi_taf_npcx.c @@ -10,6 +10,9 @@ #include #include #include +#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT +#include +#endif #include #include @@ -31,8 +34,14 @@ struct espi_taf_npcx_config { 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 + uint8_t rpmc_cnt_num; + uint8_t rpmc_op1_code; +#endif }; +#define MAX_TX_PAYLOAD_SIZE DT_PROP(DT_INST_PARENT(0), tx_plsize) + struct espi_taf_npcx_data { sys_slist_t *callbacks; const struct device *host_dev; @@ -41,6 +50,7 @@ struct espi_taf_npcx_data { uint32_t address; uint16_t length; uint32_t src[16]; + uint8_t read_buf[MAX_TX_PAYLOAD_SIZE]; struct k_work work; }; @@ -74,8 +84,9 @@ static void espi_taf_get_pckt(const struct device *dev, struct espi_taf_npcx_dat pckt->length = data_ptr->len; pckt->taf_tag = data_ptr->tag; pckt->address = data_ptr->addr; - - if (data_ptr->type == NPCX_ESPI_TAF_REQ_WRITE) { + if ((data_ptr->type == NPCX_ESPI_TAF_REQ_WRITE) || + (IS_ENABLED(CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT) && + (data_ptr->type == NPCX_ESPI_TAF_REQ_RPMC_OP1))) { memcpy(pckt->src, data_ptr->src, sizeof(pckt->src)); } } @@ -322,7 +333,6 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa uint8_t flash_req_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLASHREQSIZE); uint8_t target_max_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP); uint16_t max_read_req = 32 << flash_req_size; - uint8_t read_buf[64]; int rc; if (flash_req_size > target_max_size) { @@ -352,14 +362,14 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa } do { - rc = flash_read(spi_dev, addr, &read_buf[0], len); + rc = flash_read(spi_dev, addr, npcx_espi_taf_data.read_buf, len); if (rc) { LOG_ERR("flash read fail 0x%x", rc); return -EIO; } rc = taf_npcx_completion_handler(dev, cycle_type, taf_data_ptr->tag, len, - (uint32_t *)&read_buf[0]); + (uint32_t *)npcx_espi_taf_data.read_buf); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -444,6 +454,73 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p return 0; } +#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT +static int espi_taf_npcx_rpmc_op1(const struct device *dev, struct espi_saf_packet *pckt) +{ + struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; + uint8_t *data_ptr = taf_data_ptr->data; + struct npcx_ex_ops_uma_in op_in = { + .opcode = ESPI_TAF_RPMC_OP1_CMD, + .tx_buf = data_ptr + 1, + .tx_count = (pckt->len) - 1, + .rx_count = 0, + }; + int rc; + + rc = flash_ex_op(spi_dev, FLASH_NPCX_EX_OP_EXEC_UMA, (uintptr_t)&op_in, NULL); + if (rc) { + LOG_ERR("flash RPMC OP1 fail"); + return -EIO; + } + + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0, + NULL); + if (rc) { + LOG_ERR("espi taf completion handler fail"); + return rc; + } + + return 0; +} + +static int espi_taf_npcx_rpmc_op2(const struct device *dev, struct espi_saf_packet *pckt) +{ + struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; + uint8_t dummy_byte = 0; + struct npcx_ex_ops_uma_in op_in = { + .opcode = ESPI_TAF_RPMC_OP2_CMD, + .tx_buf = &dummy_byte, + .tx_count = 1, + .rx_count = pckt->len, + }; + struct npcx_ex_ops_uma_out op_out = { + .rx_buf = npcx_espi_taf_data.read_buf, + }; + + int rc; + + if (pckt->len > MAX_TX_PAYLOAD_SIZE) { + LOG_ERR("Invalid size"); + return -EINVAL; + } + + rc = flash_ex_op(spi_dev, FLASH_NPCX_EX_OP_EXEC_UMA, (uintptr_t)&op_in, &op_out); + if (rc) { + LOG_ERR("flash RPMC OP2 fail"); + return -EIO; + } + + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITH_DATA_ONLY, taf_data_ptr->tag, + pckt->len, (uint32_t *)npcx_espi_taf_data.read_buf); + if (rc) { + LOG_ERR("espi taf completion handler fail"); + return rc; + } + + return 0; +} +#endif + static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_saf_packet *pckt) { struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; @@ -470,7 +547,9 @@ static void espi_taf_work(struct k_work *item) pckt_taf.flash_addr = info->address; pckt_taf.len = info->length; taf_data.tag = info->taf_tag; - if (info->taf_type == NPCX_ESPI_TAF_REQ_WRITE) { + if ((info->taf_type == NPCX_ESPI_TAF_REQ_WRITE) || + (IS_ENABLED(CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT) && + (info->taf_type == NPCX_ESPI_TAF_REQ_RPMC_OP1))) { taf_data.data = (uint8_t *)info->src; } else { taf_data.data = NULL; @@ -489,6 +568,14 @@ static void espi_taf_work(struct k_work *item) case NPCX_ESPI_TAF_REQ_WRITE: ret = espi_taf_npcx_flash_write(info->host_dev, &pckt_taf); break; +#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT + case NPCX_ESPI_TAF_REQ_RPMC_OP1: + ret = espi_taf_npcx_rpmc_op1(info->host_dev, &pckt_taf); + break; + case NPCX_ESPI_TAF_REQ_RPMC_OP2: + ret = espi_taf_npcx_rpmc_op2(info->host_dev, &pckt_taf); + break; +#endif } if (ret != 0) { @@ -533,6 +620,21 @@ static int espi_taf_npcx_init(const struct device *dev) config->max_rd_sz); inst->FLASHBASE = config->mapped_addr; +#ifdef CONFIG_ESPI_TAF_NPCX_RPMC_SUPPORT + uint8_t count_num = 0; + + /* RPMC_CFG1_CNTR is 0-based number, e.g. 0 indicates that 1 counter is supported, 1 + * indicates 2 counters, etc. + */ + if (config->rpmc_cnt_num > 0) { + count_num = config->rpmc_cnt_num - 1; + } + + 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); +#endif + return 0; } @@ -549,6 +651,10 @@ static const struct espi_taf_npcx_config espi_taf_npcx_config = { .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 + .rpmc_cnt_num = DT_INST_PROP(0, rpmc_cntr), + .rpmc_op1_code = DT_INST_PROP(0, rpmc_op1_code), +#endif }; DEVICE_DT_INST_DEFINE(0, &espi_taf_npcx_init, NULL, diff --git a/dts/bindings/espi/nuvoton,npcx-espi-taf.yaml b/dts/bindings/espi/nuvoton,npcx-espi-taf.yaml index 115f8e5e4a4..8a065abf618 100644 --- a/dts/bindings/espi/nuvoton,npcx-espi-taf.yaml +++ b/dts/bindings/espi/nuvoton,npcx-espi-taf.yaml @@ -58,3 +58,15 @@ properties: - "NPCX_ESPI_TAF_MAX_READ_REQ_1024B" - "NPCX_ESPI_TAF_MAX_READ_REQ_2048B" - "NPCX_ESPI_TAF_MAX_READ_REQ_4096B" + + rpmc-cntr: + type: int + description: | + RPMC counter on RPMC flash devices. + default: 0 + + rpmc-op1-code: + type: int + description: | + RPMC OP1 opcode on RPMC flash devices. + default: 0 diff --git a/soc/nuvoton/npcx/common/reg/reg_def.h b/soc/nuvoton/npcx/common/reg/reg_def.h index 915694ba606..9bbd37bedba 100644 --- a/soc/nuvoton/npcx/common/reg/reg_def.h +++ b/soc/nuvoton/npcx/common/reg/reg_def.h @@ -791,6 +791,9 @@ struct espi_reg { #define NPCX_FLASH_PRTR_HADDR FIELD(12, 15) #define NPCX_FLASH_TAG_OVR_RPR FIELD(16, 16) #define NPCX_FLASH_TAG_OVR_WPR FIELD(0, 16) +#define NPCX_FLASH_RPMC_CFG1_CNTR FIELD(0, 4) +#define NPCX_FLASH_RPMC_CFG1_OP1 FIELD(4, 8) +#define NPCX_FLASH_RPMC_CFG1_TRGRPMCSUP FIELD(26, 6) #define NPCX_ONLY_ESPI_REG1_UNLOCK_REG2 0x55 #define NPCX_ONLY_ESPI_REG1_LOCK_REG2 0 #define NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG 4 diff --git a/soc/nuvoton/npcx/common/soc_espi_taf.h b/soc/nuvoton/npcx/common/soc_espi_taf.h index 90b98cbb62d..f4a80a22896 100644 --- a/soc/nuvoton/npcx/common/soc_espi_taf.h +++ b/soc/nuvoton/npcx/common/soc_espi_taf.h @@ -55,6 +55,11 @@ extern "C" { /* Unsuccessful Only Completion Without Data */ #define CYC_UNSCS_CMP_WITHOUT_DATA_ONLY 0x0E +/* ESPI TAF RPMC OP1 instruction */ +#define ESPI_TAF_RPMC_OP1_CMD 0x9B +/* 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