From fe138fc2467c50319cc3fc03f7a1ee0fb02b3dd7 Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Mon, 22 Apr 2024 18:18:24 +0800 Subject: [PATCH] drivers: espi: npcx: update espi taf driver This CL updates the read, write, erase, and get_channel_status implementations of NPCX chip. Signed-off-by: Tom Chang --- drivers/espi/espi_npcx.c | 31 +--- drivers/espi/espi_taf_npcx.c | 221 +++++++++++++++++-------- soc/nuvoton/npcx/common/soc_espi_taf.h | 2 + 3 files changed, 165 insertions(+), 89 deletions(-) diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index d7cece4eb07..05d7b60e2ea 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -363,7 +363,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.len = (((uint16_t)taf_head.tag_hlen & 0xF) << 8) | taf_head.llen; taf_pckt.tag = taf_head.tag_hlen >> 4; - if ((taf_pckt.len == 0) && ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_READ)) { + if ((taf_pckt.len == 0) && (taf_pckt.type == NPCX_ESPI_TAF_REQ_READ)) { taf_pckt.len = KB(4); } @@ -372,7 +372,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.addr = sys_cpu_to_be32(taf_addr); /* Get written data if eSPI TAF write */ - if ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_WRITE) { + if (taf_pckt.type == NPCX_ESPI_TAF_REQ_WRITE) { roundsize = DIV_ROUND_UP(taf_pckt.len, sizeof(uint32_t)); for (i = 0; i < roundsize; i++) { taf_pckt.src[i] = inst->FLASHRXBUF[2 + i]; @@ -415,27 +415,7 @@ static void espi_bus_flash_rx_isr(const struct device *dev) #endif } } - -static void espi_bus_completion_sent_isr(const struct device *dev) -{ - struct espi_reg *const inst = HAL_INSTANCE(dev); - - /* check that ESPISTS.FLNACS is clear. */ - if (IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS)) { - LOG_ERR("ESPISTS_FLNACS not clear\r\n"); - } - - /* flash operation is done, Make sure the TAFS transmit buffer is empty */ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL)) { - LOG_ERR("FLASH_TX_AVAIL not clear\r\n"); - } - - /* In auto mode, release FLASH_NP_FREE here to get next SAF request.*/ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_SAF_AUTO_READ)) { - inst->FLASHCTL |= BIT(NPCX_FLASHCTL_FLASH_NP_FREE); - } -} -#endif +#endif /* CONFIG_ESPI_FLASH_CHANNEL */ const struct espi_bus_isr espi_bus_isr_tbl[] = { NPCX_ESPI_BUS_INT_ITEM(BERR, espi_bus_err_isr), @@ -447,7 +427,6 @@ const struct espi_bus_isr espi_bus_isr_tbl[] = { #endif #if defined(CONFIG_ESPI_FLASH_CHANNEL) NPCX_ESPI_BUS_INT_ITEM(FLASHRX, espi_bus_flash_rx_isr), - NPCX_ESPI_BUS_INT_ITEM(FLNACS, espi_bus_completion_sent_isr), #endif }; @@ -1416,6 +1395,10 @@ static int espi_npcx_init(const struct device *dev) /* Configure host sub-modules which HW blocks belong to core domain */ npcx_host_init_subs_core_domain(dev, &data->callbacks); +#if defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_SAF) + npcx_init_taf(dev, &data->callbacks); +#endif + /* eSPI Bus interrupt installation */ IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), diff --git a/drivers/espi/espi_taf_npcx.c b/drivers/espi/espi_taf_npcx.c index 722b26730e8..c1760f7adf9 100644 --- a/drivers/espi/espi_taf_npcx.c +++ b/drivers/espi/espi_taf_npcx.c @@ -17,6 +17,14 @@ LOG_MODULE_REGISTER(espi_taf, CONFIG_ESPI_LOG_LEVEL); static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(taf_flash)); +enum ESPI_TAF_ERASE_LEN { + NPCX_ESPI_TAF_ERASE_LEN_4KB, + NPCX_ESPI_TAF_ERASE_LEN_32KB, + NPCX_ESPI_TAF_ERASE_LEN_64KB, + NPCX_ESPI_TAF_ERASE_LEN_128KB, + NPCX_ESPI_TAF_ERASE_LEN_MAX, +}; + struct espi_taf_npcx_config { uintptr_t base; uintptr_t mapped_addr; @@ -26,9 +34,19 @@ struct espi_taf_npcx_config { }; struct espi_taf_npcx_data { - sys_slist_t callbacks; + sys_slist_t *callbacks; + const struct device *host_dev; + uint8_t taf_type; + uint8_t taf_tag; + uint32_t address; + uint16_t length; + uint32_t src[16]; + struct k_work work; }; +static struct espi_taf_npcx_data npcx_espi_taf_data; +static struct espi_callback espi_taf_cb; + #define HAL_INSTANCE(dev) \ ((struct espi_reg *)((const struct espi_taf_npcx_config *) \ (dev)->config)->base) @@ -45,6 +63,24 @@ struct espi_taf_npcx_data { GET_FIELD(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \ << GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF; +static void espi_taf_get_pckt(const struct device *dev, struct espi_taf_npcx_data *pckt, + struct espi_event event) +{ + struct espi_taf_pckt *data_ptr; + + data_ptr = (struct espi_taf_pckt *)event.evt_data; + + pckt->taf_type = data_ptr->type; + 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) { + memcpy(pckt->src, data_ptr->src, sizeof(pckt->src)); + } +} + +#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, uint8_t tag) @@ -73,6 +109,7 @@ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, return false; } +#endif /* Check access region of write request is protected or not */ static bool espi_taf_check_write_protect(const struct device *dev, uint32_t addr, @@ -107,11 +144,16 @@ static int espi_taf_npcx_configure(const struct device *dev, const struct espi_s { struct espi_reg *const inst = HAL_INSTANCE(dev); + if (cfg->nflash_devices == 0U) { + return -EINVAL; + } + #if defined(CONFIG_ESPI_TAF_AUTO_MODE) inst->FLASHCTL |= BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #else inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #endif + return 0; } @@ -173,10 +215,17 @@ static int espi_taf_npcx_activate(const struct device *dev) static bool espi_taf_npcx_channel_ready(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); + uint8_t ret = + GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLCAPA) & NPCX_FLASH_SHARING_CAP_SUPP_TAF; - if (!IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) { + if (ret != NPCX_FLASH_SHARING_CAP_SUPP_TAF) { return false; } + + if (!device_is_ready(spi_dev)) { + return false; + } + return true; } @@ -214,52 +263,58 @@ static void taf_release_flash_np_free(const struct device *dev) inst->FLASHCTL = tmp; } -static int taf_npcx_completion_handler(const struct device *dev, uint32_t *buffer) +static int taf_npcx_completion_handler(const struct device *dev, uint8_t type, uint8_t tag, + uint16_t len, uint32_t *buffer) { - uint16_t size = DIV_ROUND_UP((uint8_t)(buffer[0]) + 1, sizeof(uint32_t)); struct espi_reg *const inst = HAL_INSTANCE(dev); - struct npcx_taf_head *head = (struct npcx_taf_head *)buffer; - uint8_t i; + struct npcx_taf_head taf_head; + uint16_t i, size; + uint32_t tx_buf[16]; + + taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN + len; + taf_head.type = type; + taf_head.tag_hlen = (tag << 4) | ((len & 0xF00) >> 8); + taf_head.llen = len & 0xFF; + + memcpy(&tx_buf[0], &taf_head, sizeof(struct npcx_taf_head)); + + if (type == CYC_SCS_CMP_WITH_DATA_ONLY || type == CYC_SCS_CMP_WITH_DATA_FIRST || + type == CYC_SCS_CMP_WITH_DATA_MIDDLE || type == CYC_SCS_CMP_WITH_DATA_LAST) { + memcpy(&tx_buf[1], buffer, (uint8_t)(len)); + } /* Check the Flash Access TX Queue is empty by polling * FLASH_TX_AVAIL. */ - if (WAIT_FOR(IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { + if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), + NPCX_FLASH_CHK_TIMEOUT, NULL) == false) { LOG_ERR("Check TX Queue Is Empty Timeout"); return -EBUSY; } - /* Check ESPISTS.FLNACS is clear (no slave completion is detected) */ - if (WAIT_FOR(IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { - LOG_ERR("Check Slave Completion Timeout"); - return -EBUSY; - } - /* Write packet to FLASHTXBUF */ + size = DIV_ROUND_UP((uint8_t)(tx_buf[0]) + 1, sizeof(uint32_t)); for (i = 0; i < size; i++) { - inst->FLASHTXBUF[i] = buffer[i]; + inst->FLASHTXBUF[i] = tx_buf[i]; } /* Set the FLASHCTL.FLASH_TX_AVAIL bit to 1 to enqueue the packet */ taf_set_flash_c_avail(dev); /* Release FLASH_NP_FREE here to ready get next TAF request */ - if ((head->type != CYC_SCS_CMP_WITH_DATA_FIRST) && - (head->type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { + if ((type != CYC_SCS_CMP_WITH_DATA_FIRST) && (type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { taf_release_flash_np_free(dev); } return 0; } +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) 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 *data_ptr = (uint8_t *)taf_data_ptr->data; uint8_t cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY; uint32_t total_len = pckt->len; uint32_t len = total_len; @@ -267,7 +322,7 @@ 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; - struct npcx_taf_head taf_head; + uint8_t read_buf[64]; int rc; if (flash_req_size > target_max_size) { @@ -297,21 +352,14 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa } do { - data_ptr = (uint8_t *)taf_data_ptr->data; - - taf_head.pkt_len = len + NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = cycle_type; - taf_head.tag_hlen = (taf_data_ptr->tag << 4) | ((len & 0xF00) >> 8); - taf_head.llen = len & 0xFF; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = flash_read(spi_dev, addr, data_ptr + 4, len); + rc = flash_read(spi_dev, addr, &read_buf[0], len); if (rc) { LOG_ERR("flash read fail 0x%x", rc); return -EIO; } - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, cycle_type, taf_data_ptr->tag, len, + (uint32_t *)&read_buf[0]); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -330,12 +378,12 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa return 0; } +#endif static int espi_taf_npcx_flash_write(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 = (uint8_t *)(taf_data_ptr->data); - struct npcx_taf_head taf_head; int rc; if (espi_taf_check_write_protect(dev, pckt->flash_addr, @@ -350,13 +398,8 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + 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; @@ -367,13 +410,19 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_packet *pckt) { + int erase_blk[] = {KB(4), KB(32), KB(64), KB(128)}; struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; uint32_t addr = pckt->flash_addr; - uint32_t len = pckt->len; - struct npcx_taf_head taf_head; + uint32_t len; int rc; + if ((pckt->len < 0) || (pckt->len >= NPCX_ESPI_TAF_ERASE_LEN_MAX)) { + LOG_ERR("Invalid erase block size"); + return -EINVAL; + } + + len = erase_blk[pckt->len]; + if (espi_taf_check_write_protect(dev, addr, len, taf_data_ptr->tag)) { LOG_ERR("Access protection region"); return -EINVAL; @@ -385,13 +434,8 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + 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; @@ -402,19 +446,11 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p 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; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; - struct npcx_taf_head taf_head; + struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; int rc; - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_UNSCS_CMP_WITHOUT_DATA_ONLY; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_UNSCS_CMP_WITHOUT_DATA_ONLY, taf_data_ptr->tag, + 0x0, NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -423,6 +459,67 @@ static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_s return 0; } +static void espi_taf_work(struct k_work *item) +{ + struct espi_taf_npcx_data *info = CONTAINER_OF(item, struct espi_taf_npcx_data, work); + int ret = 0; + + struct espi_taf_npcx_pckt taf_data; + struct espi_saf_packet pckt_taf; + + 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) { + taf_data.data = (uint8_t *)info->src; + } else { + taf_data.data = NULL; + } + pckt_taf.buf = (uint8_t *)&taf_data; + + switch (info->taf_type) { +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) + case NPCX_ESPI_TAF_REQ_READ: + ret = espi_taf_npcx_flash_read(info->host_dev, &pckt_taf); + break; +#endif + case NPCX_ESPI_TAF_REQ_ERASE: + ret = espi_taf_npcx_flash_erase(info->host_dev, &pckt_taf); + break; + case NPCX_ESPI_TAF_REQ_WRITE: + ret = espi_taf_npcx_flash_write(info->host_dev, &pckt_taf); + break; + } + + if (ret != 0) { + ret = espi_taf_npcx_flash_unsuccess(info->host_dev, &pckt_taf); + } +} + +static void espi_taf_event_handler(const struct device *dev, struct espi_callback *cb, + struct espi_event event) +{ + if ((event.evt_type != ESPI_BUS_SAF_NOTIFICATION) || + (event.evt_details != ESPI_CHANNEL_FLASH)) { + return; + } + + espi_taf_get_pckt(dev, &npcx_espi_taf_data, event); + k_work_submit(&npcx_espi_taf_data.work); +} + +int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks) +{ + espi_init_callback(&espi_taf_cb, espi_taf_event_handler, ESPI_BUS_SAF_NOTIFICATION); + espi_add_callback(dev, &espi_taf_cb); + + npcx_espi_taf_data.host_dev = dev; + npcx_espi_taf_data.callbacks = callbacks; + k_work_init(&npcx_espi_taf_data.work, espi_taf_work); + + return 0; +} + static int espi_taf_npcx_init(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); @@ -444,14 +541,8 @@ static const struct espi_saf_driver_api espi_taf_npcx_driver_api = { .set_protection_regions = espi_taf_npcx_set_pr, .activate = espi_taf_npcx_activate, .get_channel_status = espi_taf_npcx_channel_ready, - .flash_read = espi_taf_npcx_flash_read, - .flash_write = espi_taf_npcx_flash_write, - .flash_erase = espi_taf_npcx_flash_erase, - .flash_unsuccess = espi_taf_npcx_flash_unsuccess, }; -static struct espi_taf_npcx_data npcx_espi_taf_data; - 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), diff --git a/soc/nuvoton/npcx/common/soc_espi_taf.h b/soc/nuvoton/npcx/common/soc_espi_taf.h index a8755e080f7..90b98cbb62d 100644 --- a/soc/nuvoton/npcx/common/soc_espi_taf.h +++ b/soc/nuvoton/npcx/common/soc_espi_taf.h @@ -144,6 +144,8 @@ struct npcx_taf_head { uint8_t llen; }; +int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks); + #ifdef __cplusplus } #endif