drivers: espi: npcx: introduce espi taf driver

This CL implements espi taf read/write/erase function for NPCX.

Signed-off-by: Tom Chang <CHChang19@nuvoton.com>
This commit is contained in:
Tom Chang 2023-12-08 17:25:35 +08:00 committed by Carles Cufí
commit 4dc7c89f40
16 changed files with 928 additions and 13 deletions

View file

@ -7,6 +7,7 @@ zephyr_library()
zephyr_library_sources_ifdef(CONFIG_ESPI_XEC espi_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_ESPI_XEC espi_mchp_xec.c)
zephyr_library_sources_ifdef(CONFIG_ESPI_NPCX espi_npcx.c) zephyr_library_sources_ifdef(CONFIG_ESPI_NPCX espi_npcx.c)
zephyr_library_sources_ifdef(CONFIG_ESPI_NPCX host_subs_npcx.c) zephyr_library_sources_ifdef(CONFIG_ESPI_NPCX host_subs_npcx.c)
zephyr_library_sources_ifdef(CONFIG_ESPI_TAF_NPCX espi_taf_npcx.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE espi_handlers.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE espi_handlers.c)
zephyr_library_sources_ifdef(CONFIG_ESPI_EMUL espi_emul.c) zephyr_library_sources_ifdef(CONFIG_ESPI_EMUL espi_emul.c)
zephyr_library_sources_ifdef(CONFIG_ESPI_SAF_XEC espi_saf_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_ESPI_SAF_XEC espi_saf_mchp_xec.c)

View file

@ -58,6 +58,36 @@ config ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_RING_BUF_SIZE
The size of the ring buffer in byte used by the Port80 ISR to store The size of the ring buffer in byte used by the Port80 ISR to store
Postcodes from Host. Postcodes from Host.
config ESPI_TAF_NPCX
bool "Nuvoton NPCX embedded controller (EC) ESPI TAF driver"
depends on SOC_SERIES_NPCX4
help
This option enables the Intel Enhanced Serial Peripheral Interface
Target Attached Flash (eSPI TAF) for NPCX4 family of processors.
choice ESPI_TAF_ACCESS_MODE_CHOICE
prompt "eSPI TAF Read Access Mode"
default ESPI_TAF_AUTO_MODE
config ESPI_TAF_AUTO_MODE
bool "eSPI TAF Automatic Mode"
help
This is the setting to use auto mode for eSPI TAF read.
config ESPI_TAF_MANUAL_MODE
bool "eSPI TAF Manual Mode"
help
This is the setting to use manual mode for eSPI TAF read.
endchoice
config ESPI_TAF_PR_NUM
int "Sets of protection region settings"
default 16
help
This size is display how many group of slave attached flash protection
region.
# The default value 'y' for the existing options if ESPI_NPCX is selected. # The default value 'y' for the existing options if ESPI_NPCX is selected.
if ESPI_NPCX if ESPI_NPCX

View file

@ -7,6 +7,7 @@
#define DT_DRV_COMPAT nuvoton_npcx_espi #define DT_DRV_COMPAT nuvoton_npcx_espi
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <zephyr/drivers/espi.h> #include <zephyr/drivers/espi.h>
#include <zephyr/drivers/gpio.h> #include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/clock_control.h> #include <zephyr/drivers/clock_control.h>
@ -74,8 +75,8 @@ struct espi_npcx_data {
((hdr & 0xf0000) >> 8)) ((hdr & 0xf0000) >> 8))
/* Flash channel maximum payload size */ /* Flash channel maximum payload size */
#define NPCX_ESPI_FLASH_MAX_RX_PAYLOAD 64 #define NPCX_ESPI_FLASH_MAX_RX_PAYLOAD DT_INST_PROP(0, rx_plsize)
#define NPCX_ESPI_FLASH_MAX_TX_PAYLOAD 16 #define NPCX_ESPI_FLASH_MAX_TX_PAYLOAD DT_INST_PROP(0, tx_plsize)
/* eSPI cycle type field for OOB and FLASH channels */ /* eSPI cycle type field for OOB and FLASH channels */
#define ESPI_FLASH_READ_CYCLE_TYPE 0x00 #define ESPI_FLASH_READ_CYCLE_TYPE 0x00
@ -275,6 +276,19 @@ static void espi_bus_cfg_update_isr(const struct device *dev)
NPCX_ESPI_HOST_CH_EN(NPCX_ESPI_CH_VW))) { NPCX_ESPI_HOST_CH_EN(NPCX_ESPI_CH_VW))) {
espi_vw_send_bootload_done(dev); espi_vw_send_bootload_done(dev);
} }
#if (defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_SAF))
/* If CONFIG_ESPI_SAF is set, set to auto or manual mode accroding
* to configuration.
*/
if (IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) {
#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
}
#endif
} }
#if defined(CONFIG_ESPI_OOB_CHANNEL) #if defined(CONFIG_ESPI_OOB_CHANNEL)
@ -288,12 +302,82 @@ static void espi_bus_oob_rx_isr(const struct device *dev)
#endif #endif
#if defined(CONFIG_ESPI_FLASH_CHANNEL) #if defined(CONFIG_ESPI_FLASH_CHANNEL)
#if defined(CONFIG_ESPI_SAF)
static struct espi_taf_pckt taf_pckt;
static uint32_t espi_taf_parse(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
struct npcx_taf_head taf_head;
uint32_t taf_addr;
uint8_t i, roundsize;
/* Get type, length and tag from RX buffer */
memcpy(&taf_head, (void *)&inst->FLASHRXBUF[0], sizeof(taf_head));
taf_pckt.type = taf_head.type;
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)) {
taf_pckt.len = KB(4);
}
/* Get address from RX buffer */
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 & 0xF) == 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];
}
}
return (uint32_t)&taf_pckt;
}
#endif /* CONFIG_ESPI_SAF */
static void espi_bus_flash_rx_isr(const struct device *dev) static void espi_bus_flash_rx_isr(const struct device *dev)
{ {
struct espi_reg *const inst = HAL_INSTANCE(dev);
struct espi_npcx_data *const data = dev->data; struct espi_npcx_data *const data = dev->data;
LOG_DBG("%s", __func__); /* Controller Attached Flash Access */
k_sem_give(&data->flash_rx_lock); if ((inst->ESPICFG & BIT(NPCX_ESPICFG_FLCHANMODE)) == 0) {
k_sem_give(&data->flash_rx_lock);
} else { /* Target Attached Flash Access */
#if defined(CONFIG_ESPI_SAF)
struct espi_event evt = {
.evt_type = ESPI_BUS_SAF_NOTIFICATION,
.evt_details = ESPI_CHANNEL_FLASH,
.evt_data = espi_taf_parse(dev),
};
espi_send_callbacks(&data->callbacks, dev, evt);
#else
LOG_WRN("ESPI TAF not supported");
#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
@ -307,6 +391,7 @@ const struct espi_bus_isr espi_bus_isr_tbl[] = {
#endif #endif
#if defined(CONFIG_ESPI_FLASH_CHANNEL) #if defined(CONFIG_ESPI_FLASH_CHANNEL)
NPCX_ESPI_BUS_INT_ITEM(FLASHRX, espi_bus_flash_rx_isr), NPCX_ESPI_BUS_INT_ITEM(FLASHRX, espi_bus_flash_rx_isr),
NPCX_ESPI_BUS_INT_ITEM(FLNACS, espi_bus_completion_sent_isr),
#endif #endif
}; };

View file

@ -0,0 +1,466 @@
/*
* Copyright (c) 2023 Nuvoton Technology Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nuvoton_npcx_espi_taf
#include <soc.h>
#include <zephyr/drivers/espi.h>
#include <zephyr/drivers/espi_saf.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(espi_taf, CONFIG_ESPI_LOG_LEVEL);
static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(taf_flash));
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;
};
struct espi_taf_npcx_data {
sys_slist_t callbacks;
};
#define HAL_INSTANCE(dev) \
((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 PRTR_BADDR(i) ( \
GET_FIELD(inst->FLASH_PRTR_BADDR[i], NPCX_FLASH_PRTR_BADDR) \
<< GET_FIELD_POS(NPCX_FLASH_PRTR_BADDR))
#define PRTR_HADDR(i) ( \
GET_FIELD(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \
<< GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF;
/* 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)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
uint32_t flash_addr = addr;
uint8_t i;
uint16_t override_rd;
uint32_t base, high;
bool rdpr;
flash_addr += FLBASE_ADDR;
for (i = 0; i < CONFIG_ESPI_TAF_PR_NUM; i++) {
base = PRTR_BADDR(i);
high = PRTR_HADDR(i);
rdpr = IS_BIT_SET(inst->FLASH_PRTR_BADDR[i], NPCX_FRGN_RPR);
override_rd = GET_FIELD(inst->FLASH_RGN_TAG_OVR[i], NPCX_FLASH_TAG_OVR_RPR);
if (rdpr && !IS_BIT_SET(override_rd, tag) &&
(base <= flash_addr + len - 1 && flash_addr <= high)) {
return true;
}
}
return false;
}
/* Check access region of write request is protected or not */
static bool espi_taf_check_write_protect(const struct device *dev, uint32_t addr,
uint32_t len, uint8_t tag)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
uint32_t flash_addr = addr;
uint8_t i;
uint16_t override_wr;
uint32_t base, high;
bool wrpr;
flash_addr += FLBASE_ADDR;
for (i = 0; i < CONFIG_ESPI_TAF_PR_NUM; i++) {
base = PRTR_BADDR(i);
high = PRTR_HADDR(i);
wrpr = IS_BIT_SET(inst->FLASH_PRTR_BADDR[i], NPCX_FRGN_WPR);
override_wr = GET_FIELD(inst->FLASH_RGN_TAG_OVR[i], NPCX_FLASH_TAG_OVR_WPR);
if (wrpr && !IS_BIT_SET(override_wr, tag) &&
(base <= flash_addr + len - 1 && flash_addr <= high)) {
return true;
}
}
return false;
}
static int espi_taf_npcx_configure(const struct device *dev, const struct espi_saf_cfg *cfg)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
#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;
}
static int espi_taf_npcx_set_pr(const struct device *dev, const struct espi_saf_protection *pr)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
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;
if ((dev == NULL) || (pr == NULL)) {
return -EINVAL;
}
if (pr->nregions >= CONFIG_ESPI_TAF_PR_NUM) {
return -EINVAL;
}
while (n--) {
regnum = preg->pr_num;
if (regnum >= CONFIG_ESPI_TAF_PR_NUM) {
return -EINVAL;
}
rw_pr = preg->master_bm_we << NPCX_FRGN_WPR;
rw_pr = rw_pr | (preg->master_bm_rd << NPCX_FRGN_RPR);
if (preg->flags) {
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;
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;
}
override_rw = (preg->override_r << 16) | preg->override_w;
inst->FLASH_RGN_TAG_OVR[regnum] = override_rw;
preg++;
}
return 0;
}
static int espi_taf_npcx_activate(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_AUTO_RD_DIS_CTL);
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_BLK_FLASH_NP_FREE);
return 0;
}
static bool espi_taf_npcx_channel_ready(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
if (!IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) {
return false;
}
return true;
}
/* This routine set FLASH_C_AVAIL for standard request */
static void taf_set_flash_c_avail(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
uint32_t tmp = inst->FLASHCTL;
/*
* Clear FLASHCTL_FLASH_NP_FREE to avoid host puts a flash
* standard request command at here.
*/
tmp &= NPCX_FLASHCTL_ACCESS_MASK;
/* Set FLASHCTL_FLASH_TX_AVAIL */
tmp |= BIT(NPCX_FLASHCTL_FLASH_TX_AVAIL);
inst->FLASHCTL = tmp;
}
/* This routine release FLASH_NP_FREE for standard request */
static void taf_release_flash_np_free(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
uint32_t tmp = inst->FLASHCTL;
/*
* Clear FLASHCTL_FLASH_TX_AVAIL to avoid host puts a
* GET_FLASH_C command at here.
*/
tmp &= NPCX_FLASHCTL_ACCESS_MASK;
/* Release FLASH_NP_FREE */
tmp |= BIT(NPCX_FLASHCTL_FLASH_NP_FREE);
inst->FLASHCTL = tmp;
}
static int taf_npcx_completion_handler(const struct device *dev, 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;
/* 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)) {
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 */
for (i = 0; i < size; i++) {
inst->FLASHTXBUF[i] = buffer[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)) {
taf_release_flash_np_free(dev);
}
return 0;
}
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;
uint32_t addr = pckt->flash_addr;
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;
int rc;
if (flash_req_size > target_max_size) {
LOG_DBG("Exceeded the maximum supported length");
if (target_max_size == 0) {
target_max_size = 1;
}
max_read_req = 32 << target_max_size;
}
if (total_len > max_read_req) {
LOG_ERR("Exceeded the limitation of read length");
return -EINVAL;
}
if (espi_taf_check_read_protect(dev, addr, len, taf_data_ptr->tag)) {
LOG_ERR("Access protect region");
return -EINVAL;
}
if (total_len <= config->rx_plsz) {
cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY;
len = total_len;
} else {
cycle_type = CYC_SCS_CMP_WITH_DATA_FIRST;
len = config->rx_plsz;
}
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);
if (rc) {
LOG_ERR("flash read fail 0x%x", rc);
return -EIO;
}
rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data);
if (rc) {
LOG_ERR("espi taf completion handler fail");
return rc;
}
total_len -= len;
addr += len;
if (total_len <= config->rx_plsz) {
cycle_type = CYC_SCS_CMP_WITH_DATA_LAST;
len = total_len;
} else {
cycle_type = CYC_SCS_CMP_WITH_DATA_MIDDLE;
}
} while (total_len);
return 0;
}
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,
pckt->len, taf_data_ptr->tag)) {
LOG_ERR("Access protection region");
return -EINVAL;
}
rc = flash_write(spi_dev, pckt->flash_addr, data_ptr, pckt->len);
if (rc) {
LOG_ERR("flash write fail 0x%x", rc);
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);
if (rc) {
LOG_ERR("espi taf completion handler fail");
return rc;
}
return 0;
}
static int espi_taf_npcx_flash_erase(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;
uint32_t addr = pckt->flash_addr;
uint32_t len = pckt->len;
struct npcx_taf_head taf_head;
int rc;
if (espi_taf_check_write_protect(dev, addr, len, taf_data_ptr->tag)) {
LOG_ERR("Access protection region");
return -EINVAL;
}
rc = flash_erase(spi_dev, addr, len);
if (rc) {
LOG_ERR("flash erase fail");
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);
if (rc) {
LOG_ERR("espi taf completion handler fail");
return rc;
}
return 0;
}
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;
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);
if (rc) {
LOG_ERR("espi taf completion handler fail");
return rc;
}
return 0;
}
static int espi_taf_npcx_init(const struct device *dev)
{
struct espi_reg *const inst = HAL_INSTANCE(dev);
struct espi_taf_npcx_config *config = ((struct espi_taf_npcx_config *)(dev)->config);
SET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLCAPA,
NPCX_FLASH_SHARING_CAP_SUPP_TAF_AND_CAF);
SET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_TRGFLEBLKSIZE,
BIT(config->erase_sz));
SET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP,
config->max_rd_sz);
inst->FLASHBASE = config->mapped_addr;
return 0;
}
static const struct espi_saf_driver_api espi_taf_npcx_driver_api = {
.config = espi_taf_npcx_configure,
.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),
.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),
};
DEVICE_DT_INST_DEFINE(0, &espi_taf_npcx_init, NULL,
&npcx_espi_taf_data, &espi_taf_npcx_config,
PRE_KERNEL_2, CONFIG_ESPI_INIT_PRIORITY,
&espi_taf_npcx_driver_api);

View file

@ -306,6 +306,17 @@
buffer-tx-size = <128>; buffer-tx-size = <128>;
shi-cs-wui =<&wui_io53>; shi-cs-wui =<&wui_io53>;
}; };
espi0: espi@4000a000 {
rx-plsize = <64>;
tx-plsize = <64>;
espi_taf: espitaf@4000a000 {
compatible = "nuvoton,npcx-espi-taf";
reg = <0x4000a000 0x2000>;
status = "disabled";
};
};
}; };
soc-if { soc-if {

View file

@ -255,6 +255,11 @@
buffer-tx-size = <128>; buffer-tx-size = <128>;
shi-cs-wui =<&wui_io53>; shi-cs-wui =<&wui_io53>;
}; };
espi0: espi@4000a000 {
rx-plsize = <64>;
tx-plsize = <16>;
};
}; };
soc-id { soc-id {

View file

@ -283,6 +283,11 @@
buffer-tx-size = <128>; buffer-tx-size = <128>;
shi-cs-wui =<&wui_io53>; shi-cs-wui =<&wui_io53>;
}; };
espi0: espi@4000a000 {
rx-plsize = <64>;
tx-plsize = <16>;
};
}; };
soc-id { soc-id {

View file

@ -0,0 +1,60 @@
# Copyright (c) 2023 Nuvoton Technology Corporation.
# SPDX-License-Identifier: Apache-2.0
description: |
The target flash devices accessed by Nuvoton eSPI TAF controller.
Representation:
espi_taf: espitaf@4000a000 {
compatible = "nuvoton,npcx-espi-taf";
reg = <0x4000a000 0x2000>;
mapped-addr = <0x68000000>;
max-read-sz = "NPCX_ESPI_TAF_MAX_READ_REQ_64B";
erase-sz = "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_4KB";
#address-cells = <1>;
#size-cells = <1>;
status = "okay";
};
compatible: "nuvoton,npcx-espi-taf"
include: [espi-controller.yaml, pinctrl-device.yaml]
properties:
mapped-addr:
type: int
description: |
Mapped memory address of direct read access for flash.
required: true
erase-sz:
type: string
required: true
description: |
Erase block size of target flash. The default was 4KB Erase Block Size.
All Intel platforms require support for at least 4 KB Erase Block Size.
default: "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_4KB"
enum:
- "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_4KB"
- "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_32KB"
- "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_64KB"
- "NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_128KB"
max-read-sz:
type: string
required: true
description: |
Maximum read request size of flash access channel. The default was 64 bytes.
This value is recommended in datasheet.
default: "NPCX_ESPI_TAF_MAX_READ_REQ_64B"
enum:
- "NPCX_ESPI_TAF_MAX_READ_REQ_64B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_128B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_256B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_512B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_1024B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_2048B"
- "NPCX_ESPI_TAF_MAX_READ_REQ_4096B"

View file

@ -30,3 +30,13 @@ properties:
For example the WUI mapping on NPCX7 would be For example the WUI mapping on NPCX7 would be
espi-rst-wui = <&wui_cr_sin1>; espi-rst-wui = <&wui_cr_sin1>;
rx-plsize:
type: int
required: true
description: The maximum receive channel payload size.
tx-plsize:
type: int
required: true
description: The maximum transmit channel payload size.

View file

@ -145,6 +145,8 @@ typedef int (*espi_saf_api_flash_write)(const struct device *dev,
struct espi_saf_packet *pckt); struct espi_saf_packet *pckt);
typedef int (*espi_saf_api_flash_erase)(const struct device *dev, typedef int (*espi_saf_api_flash_erase)(const struct device *dev,
struct espi_saf_packet *pckt); struct espi_saf_packet *pckt);
typedef int (*espi_saf_api_flash_unsuccess)(const struct device *dev,
struct espi_saf_packet *pckt);
/* Callbacks and traffic intercept */ /* Callbacks and traffic intercept */
typedef int (*espi_saf_api_manage_callback)(const struct device *dev, typedef int (*espi_saf_api_manage_callback)(const struct device *dev,
struct espi_callback *callback, struct espi_callback *callback,
@ -158,6 +160,7 @@ __subsystem struct espi_saf_driver_api {
espi_saf_api_flash_read flash_read; espi_saf_api_flash_read flash_read;
espi_saf_api_flash_write flash_write; espi_saf_api_flash_write flash_write;
espi_saf_api_flash_erase flash_erase; espi_saf_api_flash_erase flash_erase;
espi_saf_api_flash_unsuccess flash_unsuccess;
espi_saf_api_manage_callback manage_callback; espi_saf_api_manage_callback manage_callback;
}; };
@ -383,6 +386,35 @@ static inline int z_impl_espi_saf_flash_erase(const struct device *dev,
return api->flash_erase(dev, pckt); return api->flash_erase(dev, pckt);
} }
/**
* @brief Response unsuccessful completion for slave attached flash.
*
* This routines provides an interface to response that transaction is
* invalid and return unsuccessful completion from target to controller.
*
* @param dev Pointer to the device structure for the driver instance.
* @param pckt Address of the representation of flash transaction.
*
* @retval -ENOTSUP eSPI flash logical channel transactions not supported.
* @retval -EBUSY eSPI flash channel is not ready or disabled by master.
* @retval -EIO General input / output error, failed request to master.
*/
__syscall int espi_saf_flash_unsuccess(const struct device *dev,
struct espi_saf_packet *pckt);
static inline int z_impl_espi_saf_flash_unsuccess(const struct device *dev,
struct espi_saf_packet *pckt)
{
const struct espi_saf_driver_api *api =
(const struct espi_saf_driver_api *)dev->api;
if (!api->flash_unsuccess) {
return -ENOTSUP;
}
return api->flash_unsuccess(dev, pckt);
}
/** /**
* Callback model * Callback model
* *

View file

@ -27,4 +27,12 @@
((reg) = ((reg) & (~(((1 << (f_size))-1) << (f_pos)))) \ ((reg) = ((reg) & (~(((1 << (f_size))-1) << (f_pos)))) \
| ((value) << (f_pos))) | ((value) << (f_pos)))
#define GET_FIELD_POS(field) \
_GET_FIELD_POS_(FIELD_POS(field))
#define _GET_FIELD_POS_(f_ops) f_ops
#define GET_FIELD_SZ(field) \
_GET_FIELD_SZ_(FIELD_SIZE(field))
#define _GET_FIELD_SZ_(f_ops) f_ops
#endif /* _NUVOTON_NPCX_REG_ACCESS_H */ #endif /* _NUVOTON_NPCX_REG_ACCESS_H */

View file

@ -625,14 +625,35 @@ struct espi_reg {
volatile uint32_t reserved8[11]; volatile uint32_t reserved8[11];
/* 0x3FC: OOB Channel Control used in 'direct' mode */ /* 0x3FC: OOB Channel Control used in 'direct' mode */
volatile uint32_t OOBCTL_DIRECT; volatile uint32_t OOBCTL_DIRECT;
/* 0x400 - 443: Flash Receive Buffer 0-16 */ /* 0x400 - 443: Flash Receive Buffer 0-17 */
volatile uint32_t FLASHRXBUF[17]; volatile uint32_t FLASHRXBUF[18];
volatile uint32_t reserved9[15]; volatile uint32_t reserved9[14];
/* 0x480 - 497: Flash Transmit Buffer 0-5 */ /* 0x480 - 497: Flash Transmit Buffer 0-16 */
volatile uint32_t FLASHTXBUF[6]; volatile uint32_t FLASHTXBUF[17];
volatile uint32_t reserved10[25]; volatile uint32_t reserved10[14];
/* 0x4FC: Flash Channel Control used in 'direct' mode */ /* 0x4FC: Flash Channel Control used in 'direct' mode */
volatile uint32_t FLASHCTL_DIRECT; volatile uint32_t FLASHCTL_DIRECT;
volatile uint32_t reserved12[64];
/* 0x600 - 63F */
volatile uint32_t FLASH_PRTR_BADDR[16];
/* 0x640 - 67F */
volatile uint32_t FLASH_PRTR_HADDR[16];
/* 0x680 - 6BF */
volatile uint32_t FLASH_RGN_TAG_OVR[16];
volatile uint32_t reserved13[80];
/* 0x800 */
volatile uint32_t FLASH_RPMC_CFG_1;
/* 0x804 */
volatile uint32_t FLASH_RPMC_CFG_2;
/* 0x808 */
volatile uint32_t RMAP_FLASH_OFFS;
/* 0x80C */
volatile uint32_t RMAP_DST_BASE;
/* 0x810 */
volatile uint32_t RMAP_WIN_SIZE;
/* 0x814 */
volatile uint32_t FLASHBASE;
volatile uint32_t reserved14[58];
}; };
/* eSPI register fields */ /* eSPI register fields */
@ -648,6 +669,7 @@ struct espi_reg {
#define NPCX_ESPICFG_HCHANS_FIELD FIELD(4, 4) #define NPCX_ESPICFG_HCHANS_FIELD FIELD(4, 4)
#define NPCX_ESPICFG_IOMODE_FIELD FIELD(8, 2) #define NPCX_ESPICFG_IOMODE_FIELD FIELD(8, 2)
#define NPCX_ESPICFG_MAXFREQ_FIELD FIELD(10, 3) #define NPCX_ESPICFG_MAXFREQ_FIELD FIELD(10, 3)
#define NPCX_ESPICFG_FLCHANMODE 16
#define NPCX_ESPICFG_PCCHN_SUPP 24 #define NPCX_ESPICFG_PCCHN_SUPP 24
#define NPCX_ESPICFG_VWCHN_SUPP 25 #define NPCX_ESPICFG_VWCHN_SUPP 25
#define NPCX_ESPICFG_OOBCHN_SUPP 26 #define NPCX_ESPICFG_OOBCHN_SUPP 26
@ -657,7 +679,7 @@ struct espi_reg {
#define NPCX_ESPIIE_BERRIE 2 #define NPCX_ESPIIE_BERRIE 2
#define NPCX_ESPIIE_OOBRXIE 3 #define NPCX_ESPIIE_OOBRXIE 3
#define NPCX_ESPIIE_FLASHRXIE 4 #define NPCX_ESPIIE_FLASHRXIE 4
#define NPCX_ESPIIE_SFLASHRDIE 5 #define NPCX_ESPIIE_FLNACSIE 5
#define NPCX_ESPIIE_PERACCIE 6 #define NPCX_ESPIIE_PERACCIE 6
#define NPCX_ESPIIE_DFRDIE 7 #define NPCX_ESPIIE_DFRDIE 7
#define NPCX_ESPIIE_VWUPDIE 8 #define NPCX_ESPIIE_VWUPDIE 8
@ -675,6 +697,7 @@ struct espi_reg {
#define NPCX_ESPIWE_BERRWE 2 #define NPCX_ESPIWE_BERRWE 2
#define NPCX_ESPIWE_OOBRXWE 3 #define NPCX_ESPIWE_OOBRXWE 3
#define NPCX_ESPIWE_FLASHRXWE 4 #define NPCX_ESPIWE_FLASHRXWE 4
#define NPCX_ESPIWE_FLNACSWE 5
#define NPCX_ESPIWE_PERACCWE 6 #define NPCX_ESPIWE_PERACCWE 6
#define NPCX_ESPIWE_DFRDWE 7 #define NPCX_ESPIWE_DFRDWE 7
#define NPCX_ESPIWE_VWUPDWE 8 #define NPCX_ESPIWE_VWUPDWE 8
@ -686,6 +709,7 @@ struct espi_reg {
#define NPCX_ESPISTS_BERR 2 #define NPCX_ESPISTS_BERR 2
#define NPCX_ESPISTS_OOBRX 3 #define NPCX_ESPISTS_OOBRX 3
#define NPCX_ESPISTS_FLASHRX 4 #define NPCX_ESPISTS_FLASHRX 4
#define NPCX_ESPISTS_FLNACS 5
#define NPCX_ESPISTS_PERACC 6 #define NPCX_ESPISTS_PERACC 6
#define NPCX_ESPISTS_DFRD 7 #define NPCX_ESPISTS_DFRD 7
#define NPCX_ESPISTS_VWUPD 8 #define NPCX_ESPISTS_VWUPD 8
@ -700,6 +724,14 @@ struct espi_reg {
#define NPCX_ESPISTS_BMBURSTERR 22 #define NPCX_ESPISTS_BMBURSTERR 22
#define NPCX_ESPISTS_BMBURSTDONE 23 #define NPCX_ESPISTS_BMBURSTDONE 23
#define NPCX_ESPISTS_ESPIRST_LVL 24 #define NPCX_ESPISTS_ESPIRST_LVL 24
#define NPCX_VWSWIRQ_IRQ_NUM FIELD(0, 7)
#define NPCX_VWSWIRQ_IRQ_LVL 7
#define NPCX_VWSWIRQ_INDEX FIELD(8, 7)
#define NPCX_VWSWIRQ_INDEX_EN 15
#define NPCX_VWSWIRQ_DIRTY 16
#define NPCX_VWSWIRQ_ENPLTRST 17
#define NPCX_VWSWIRQ_ENCDRST 19
#define NPCX_VWSWIRQ_EDGE_IRQ 28
#define NPCX_VWEVMS_WIRE FIELD(0, 4) #define NPCX_VWEVMS_WIRE FIELD(0, 4)
#define NPCX_VWEVMS_VALID FIELD(4, 4) #define NPCX_VWEVMS_VALID FIELD(4, 4)
#define NPCX_VWEVMS_IE 18 #define NPCX_VWEVMS_IE 18
@ -716,6 +748,9 @@ struct espi_reg {
#define NPCX_FLASHCFG_FLASHBLERSSIZE FIELD(7, 3) #define NPCX_FLASHCFG_FLASHBLERSSIZE FIELD(7, 3)
#define NPCX_FLASHCFG_FLASHPLSIZE FIELD(10, 3) #define NPCX_FLASHCFG_FLASHPLSIZE FIELD(10, 3)
#define NPCX_FLASHCFG_FLASHREQSIZE FIELD(13, 3) #define NPCX_FLASHCFG_FLASHREQSIZE FIELD(13, 3)
#define NPCX_FLASHCFG_FLCAPA FIELD(24, 2)
#define NPCX_FLASHCFG_TRGFLEBLKSIZE FIELD(16, 8)
#define NPCX_FLASHCFG_FLREQSUP FIELD(0, 3)
#define NPCX_FLASHCTL_FLASH_NP_FREE 0 #define NPCX_FLASHCTL_FLASH_NP_FREE 0
#define NPCX_FLASHCTL_FLASH_TX_AVAIL 1 #define NPCX_FLASHCTL_FLASH_TX_AVAIL 1
#define NPCX_FLASHCTL_STRPHDR 2 #define NPCX_FLASHCTL_STRPHDR 2
@ -725,10 +760,21 @@ struct espi_reg {
#define NPCX_FLASHCTL_CRCEN 14 #define NPCX_FLASHCTL_CRCEN 14
#define NPCX_FLASHCTL_CHKSUMSEL 15 #define NPCX_FLASHCTL_CHKSUMSEL 15
#define NPCX_FLASHCTL_AMTEN 16 #define NPCX_FLASHCTL_AMTEN 16
#define NPCX_FLASHCTL_SAF_AUTO_READ 18
#define NPCX_FLASHCTL_AUTO_RD_DIS_CTL 19
#define NPCX_FLASHCTL_BLK_FLASH_NP_FREE 20
#define NPCX_FLASHBASE_FLBASE_ADDR FIELD(12, 15)
#define NPCX_FLASH_PRTR_BADDR FIELD(12, 15)
#define NPCX_FRGN_WPR 29
#define SAF_PROT_LCK 31
#define NPCX_FRGN_RPR 30
#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_ONLY_ESPI_REG1_UNLOCK_REG2 0x55 #define NPCX_ONLY_ESPI_REG1_UNLOCK_REG2 0x55
#define NPCX_ONLY_ESPI_REG1_LOCK_REG2 0 #define NPCX_ONLY_ESPI_REG1_LOCK_REG2 0
#define NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG 4 #define NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG 4
/* /*
* Mobile System Wake-Up Control (MSWC) device registers * Mobile System Wake-Up Control (MSWC) device registers
*/ */

View file

@ -62,7 +62,7 @@ NPCX_REG_OFFSET_CHECK(twd_reg, TWMWD, 0x00e);
NPCX_REG_OFFSET_CHECK(twd_reg, WDCP, 0x010); NPCX_REG_OFFSET_CHECK(twd_reg, WDCP, 0x010);
/* ESPI register structure check */ /* ESPI register structure check */
NPCX_REG_SIZE_CHECK(espi_reg, 0x500); NPCX_REG_SIZE_CHECK(espi_reg, 0x900);
NPCX_REG_OFFSET_CHECK(espi_reg, FLASHCFG, 0x034); NPCX_REG_OFFSET_CHECK(espi_reg, FLASHCFG, 0x034);
NPCX_REG_OFFSET_CHECK(espi_reg, NPCX_ONLY_ESPI_REG1, 0x0f0); NPCX_REG_OFFSET_CHECK(espi_reg, NPCX_ONLY_ESPI_REG1, 0x0f0);
NPCX_REG_OFFSET_CHECK(espi_reg, VWEVMS, 0x140); NPCX_REG_OFFSET_CHECK(espi_reg, VWEVMS, 0x140);

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2023 Nuvoton Technology Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _NUVOTON_NPCX_SOC_ESPI_TAF_H_
#define _NUVOTON_NPCX_SOC_ESPI_TAF_H_
#include <zephyr/device.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Transmit buffer for eSPI TAF transaction on NPCX */
/* +-------------+--------------+--------------+---------------+ */
/* | Byte 3 | Byte 2 | Byte 1 | Byte 0 | */
/* +-------------+--------------+--------------+---------------+ */
/* | Length | Tag |Length | Type | PKT_LEN | */
/* | [7:0] | |[11:8] | | | */
/* +-------------+--------------+--------------+---------------+ */
/* | Data 3 | Data 2 | Data 1 | Data 0 | */
/* +-------------+--------------+--------------+---------------+ */
/* | Data 7 | Data 6 | Data 5 | Data 4 | */
/* +-------------+--------------+--------------+---------------+ */
/* | ... | ... | ... | ... | */
/* +-------------+--------------+--------------+---------------+ */
/* | Data 63 | Data 62 | Data 61 | Data 60 | */
/* +-------------+--------------+--------------+---------------+ */
/* PKT_LEN holds the sum of header (Type, Tag and Length) length */
/* and data length */
/*
* NPCX_TAF_CMP_HEADER_LEN is the preamble length of Type, Length
* and Tag (i.e. byte 1~byte 3) for flash access completion packet
* on NPCX
*/
#define NPCX_TAF_CMP_HEADER_LEN 3
/* Successful Completion Without Data */
#define CYC_SCS_CMP_WITHOUT_DATA 0x06
/* Successful middle Completion With Data */
#define CYC_SCS_CMP_WITH_DATA_MIDDLE 0x09
/* Successful first Completion With Data */
#define CYC_SCS_CMP_WITH_DATA_FIRST 0x0B
/* Successful last Completion With Data */
#define CYC_SCS_CMP_WITH_DATA_LAST 0x0D
/* Successful only Completion With Data */
#define CYC_SCS_CMP_WITH_DATA_ONLY 0x0F
/* Unsuccessful Completion Without Data */
#define CYC_UNSCS_CMP_WITHOUT_DATA 0x08
/* Unsuccessful Last Completion Without Data */
#define CYC_UNSCS_CMP_WITHOUT_DATA_LAST 0x0C
/* Unsuccessful Only Completion Without Data */
#define CYC_UNSCS_CMP_WITHOUT_DATA_ONLY 0x0E
/* 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) | \
BIT(NPCX_FLASHCTL_FLASH_TX_AVAIL)))
/* Flash Sharing Capability Support */
#define NPCX_FLASH_SHARING_CAP_SUPP_CAF 0
#define NPCX_FLASH_SHARING_CAP_SUPP_TAF 2
#define NPCX_FLASH_SHARING_CAP_SUPP_TAF_AND_CAF 3
enum NPCX_ESPI_TAF_REQ {
NPCX_ESPI_TAF_REQ_READ,
NPCX_ESPI_TAF_REQ_WRITE,
NPCX_ESPI_TAF_REQ_ERASE,
NPCX_ESPI_TAF_REQ_RPMC_OP1,
NPCX_ESPI_TAF_REQ_RPMC_OP2,
NPCX_ESPI_TAF_REQ_UNKNOWN,
};
/* NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_4KB is default */
enum NPCX_ESPI_TAF_ERASE_BLOCK_SIZE {
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_1KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_2KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_4KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_8KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_16KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_32KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_64KB,
NPCX_ESPI_TAF_ERASE_BLOCK_SIZE_128KB,
};
/* NPCX_ESPI_TAF_MAX_READ_REQ_64B is default */
enum NPCX_ESPI_TAF_MAX_READ_REQ {
NPCX_ESPI_TAF_MAX_READ_REQ_64B = 1,
NPCX_ESPI_TAF_MAX_READ_REQ_128B,
NPCX_ESPI_TAF_MAX_READ_REQ_256B,
NPCX_ESPI_TAF_MAX_READ_REQ_512B,
NPCX_ESPI_TAF_MAX_READ_REQ_1024B,
NPCX_ESPI_TAF_MAX_READ_REQ_2048B,
NPCX_ESPI_TAF_MAX_READ_REQ_4096B,
};
/*
* The configurations of SPI flash are set in FIU module.
* Thus, eSPI TAF driver of NPCX does not need additional hardware configuarations.
* Therefore, define an empty structure here to comply with espi_saf.h
*/
struct espi_saf_hw_cfg {
};
struct espi_saf_pr {
uint32_t start;
uint32_t end;
uint16_t override_r;
uint16_t override_w;
uint8_t master_bm_we;
uint8_t master_bm_rd;
uint8_t pr_num;
uint8_t flags;
};
struct espi_saf_protection {
size_t nregions;
const struct espi_saf_pr *pregions;
};
struct espi_taf_npcx_pckt {
uint8_t tag;
uint8_t *data;
};
struct espi_taf_pckt {
uint8_t type;
uint8_t tag;
uint32_t addr;
uint16_t len;
uint32_t src[16];
};
struct npcx_taf_head {
uint8_t pkt_len;
uint8_t type;
uint8_t tag_hlen;
uint8_t llen;
};
#ifdef __cplusplus
}
#endif
#endif

View file

@ -14,6 +14,10 @@ config NUM_IRQS
config CORTEX_M_SYSTICK config CORTEX_M_SYSTICK
default !NPCX_ITIM_TIMER default !NPCX_ITIM_TIMER
config ESPI_TAF_NPCX
default y
depends on ESPI_SAF
source "soc/arm/nuvoton_npcx/npcx4/Kconfig.defconfig.npcx4*" source "soc/arm/nuvoton_npcx/npcx4/Kconfig.defconfig.npcx4*"
endif # SOC_SERIES_NPCX4 endif # SOC_SERIES_NPCX4

View file

@ -53,6 +53,7 @@
#include <reg/reg_def.h> #include <reg/reg_def.h>
#include <soc_dt.h> #include <soc_dt.h>
#include <soc_clock.h> #include <soc_clock.h>
#include <soc_espi_taf.h>
#include <soc_pins.h> #include <soc_pins.h>
#include <soc_power.h> #include <soc_power.h>