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:
parent
6cb1ff6560
commit
4dc7c89f40
16 changed files with 928 additions and 13 deletions
|
@ -7,6 +7,7 @@ zephyr_library()
|
|||
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 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_ESPI_EMUL espi_emul.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ESPI_SAF_XEC espi_saf_mchp_xec.c)
|
||||
|
|
|
@ -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
|
||||
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.
|
||||
if ESPI_NPCX
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define DT_DRV_COMPAT nuvoton_npcx_espi
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/drivers/espi.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
|
@ -74,8 +75,8 @@ struct espi_npcx_data {
|
|||
((hdr & 0xf0000) >> 8))
|
||||
|
||||
/* Flash channel maximum payload size */
|
||||
#define NPCX_ESPI_FLASH_MAX_RX_PAYLOAD 64
|
||||
#define NPCX_ESPI_FLASH_MAX_TX_PAYLOAD 16
|
||||
#define NPCX_ESPI_FLASH_MAX_RX_PAYLOAD DT_INST_PROP(0, rx_plsize)
|
||||
#define NPCX_ESPI_FLASH_MAX_TX_PAYLOAD DT_INST_PROP(0, tx_plsize)
|
||||
|
||||
/* eSPI cycle type field for OOB and FLASH channels */
|
||||
#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))) {
|
||||
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)
|
||||
|
@ -288,12 +302,82 @@ static void espi_bus_oob_rx_isr(const struct device *dev)
|
|||
#endif
|
||||
|
||||
#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)
|
||||
{
|
||||
struct espi_reg *const inst = HAL_INSTANCE(dev);
|
||||
struct espi_npcx_data *const data = dev->data;
|
||||
|
||||
LOG_DBG("%s", __func__);
|
||||
k_sem_give(&data->flash_rx_lock);
|
||||
/* Controller Attached Flash Access */
|
||||
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
|
||||
|
||||
|
@ -307,6 +391,7 @@ 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
|
||||
};
|
||||
|
||||
|
|
466
drivers/espi/espi_taf_npcx.c
Normal file
466
drivers/espi/espi_taf_npcx.c
Normal 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);
|
|
@ -306,6 +306,17 @@
|
|||
buffer-tx-size = <128>;
|
||||
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 {
|
||||
|
|
|
@ -255,6 +255,11 @@
|
|||
buffer-tx-size = <128>;
|
||||
shi-cs-wui =<&wui_io53>;
|
||||
};
|
||||
|
||||
espi0: espi@4000a000 {
|
||||
rx-plsize = <64>;
|
||||
tx-plsize = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
soc-id {
|
||||
|
|
|
@ -283,6 +283,11 @@
|
|||
buffer-tx-size = <128>;
|
||||
shi-cs-wui =<&wui_io53>;
|
||||
};
|
||||
|
||||
espi0: espi@4000a000 {
|
||||
rx-plsize = <64>;
|
||||
tx-plsize = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
soc-id {
|
||||
|
|
60
dts/bindings/espi/nuvoton,npcx-espi-taf.yaml
Normal file
60
dts/bindings/espi/nuvoton,npcx-espi-taf.yaml
Normal 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"
|
|
@ -30,3 +30,13 @@ properties:
|
|||
|
||||
For example the WUI mapping on NPCX7 would be
|
||||
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.
|
||||
|
|
|
@ -145,6 +145,8 @@ typedef int (*espi_saf_api_flash_write)(const struct device *dev,
|
|||
struct espi_saf_packet *pckt);
|
||||
typedef int (*espi_saf_api_flash_erase)(const struct device *dev,
|
||||
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 */
|
||||
typedef int (*espi_saf_api_manage_callback)(const struct device *dev,
|
||||
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_write flash_write;
|
||||
espi_saf_api_flash_erase flash_erase;
|
||||
espi_saf_api_flash_unsuccess flash_unsuccess;
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
|
@ -27,4 +27,12 @@
|
|||
((reg) = ((reg) & (~(((1 << (f_size))-1) << (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 */
|
||||
|
|
|
@ -625,14 +625,35 @@ struct espi_reg {
|
|||
volatile uint32_t reserved8[11];
|
||||
/* 0x3FC: OOB Channel Control used in 'direct' mode */
|
||||
volatile uint32_t OOBCTL_DIRECT;
|
||||
/* 0x400 - 443: Flash Receive Buffer 0-16 */
|
||||
volatile uint32_t FLASHRXBUF[17];
|
||||
volatile uint32_t reserved9[15];
|
||||
/* 0x480 - 497: Flash Transmit Buffer 0-5 */
|
||||
volatile uint32_t FLASHTXBUF[6];
|
||||
volatile uint32_t reserved10[25];
|
||||
/* 0x400 - 443: Flash Receive Buffer 0-17 */
|
||||
volatile uint32_t FLASHRXBUF[18];
|
||||
volatile uint32_t reserved9[14];
|
||||
/* 0x480 - 497: Flash Transmit Buffer 0-16 */
|
||||
volatile uint32_t FLASHTXBUF[17];
|
||||
volatile uint32_t reserved10[14];
|
||||
/* 0x4FC: Flash Channel Control used in 'direct' mode */
|
||||
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 */
|
||||
|
@ -648,6 +669,7 @@ struct espi_reg {
|
|||
#define NPCX_ESPICFG_HCHANS_FIELD FIELD(4, 4)
|
||||
#define NPCX_ESPICFG_IOMODE_FIELD FIELD(8, 2)
|
||||
#define NPCX_ESPICFG_MAXFREQ_FIELD FIELD(10, 3)
|
||||
#define NPCX_ESPICFG_FLCHANMODE 16
|
||||
#define NPCX_ESPICFG_PCCHN_SUPP 24
|
||||
#define NPCX_ESPICFG_VWCHN_SUPP 25
|
||||
#define NPCX_ESPICFG_OOBCHN_SUPP 26
|
||||
|
@ -657,7 +679,7 @@ struct espi_reg {
|
|||
#define NPCX_ESPIIE_BERRIE 2
|
||||
#define NPCX_ESPIIE_OOBRXIE 3
|
||||
#define NPCX_ESPIIE_FLASHRXIE 4
|
||||
#define NPCX_ESPIIE_SFLASHRDIE 5
|
||||
#define NPCX_ESPIIE_FLNACSIE 5
|
||||
#define NPCX_ESPIIE_PERACCIE 6
|
||||
#define NPCX_ESPIIE_DFRDIE 7
|
||||
#define NPCX_ESPIIE_VWUPDIE 8
|
||||
|
@ -675,6 +697,7 @@ struct espi_reg {
|
|||
#define NPCX_ESPIWE_BERRWE 2
|
||||
#define NPCX_ESPIWE_OOBRXWE 3
|
||||
#define NPCX_ESPIWE_FLASHRXWE 4
|
||||
#define NPCX_ESPIWE_FLNACSWE 5
|
||||
#define NPCX_ESPIWE_PERACCWE 6
|
||||
#define NPCX_ESPIWE_DFRDWE 7
|
||||
#define NPCX_ESPIWE_VWUPDWE 8
|
||||
|
@ -686,6 +709,7 @@ struct espi_reg {
|
|||
#define NPCX_ESPISTS_BERR 2
|
||||
#define NPCX_ESPISTS_OOBRX 3
|
||||
#define NPCX_ESPISTS_FLASHRX 4
|
||||
#define NPCX_ESPISTS_FLNACS 5
|
||||
#define NPCX_ESPISTS_PERACC 6
|
||||
#define NPCX_ESPISTS_DFRD 7
|
||||
#define NPCX_ESPISTS_VWUPD 8
|
||||
|
@ -700,6 +724,14 @@ struct espi_reg {
|
|||
#define NPCX_ESPISTS_BMBURSTERR 22
|
||||
#define NPCX_ESPISTS_BMBURSTDONE 23
|
||||
#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_VALID FIELD(4, 4)
|
||||
#define NPCX_VWEVMS_IE 18
|
||||
|
@ -716,6 +748,9 @@ struct espi_reg {
|
|||
#define NPCX_FLASHCFG_FLASHBLERSSIZE FIELD(7, 3)
|
||||
#define NPCX_FLASHCFG_FLASHPLSIZE FIELD(10, 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_TX_AVAIL 1
|
||||
#define NPCX_FLASHCTL_STRPHDR 2
|
||||
|
@ -725,10 +760,21 @@ struct espi_reg {
|
|||
#define NPCX_FLASHCTL_CRCEN 14
|
||||
#define NPCX_FLASHCTL_CHKSUMSEL 15
|
||||
#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_LOCK_REG2 0
|
||||
#define NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG 4
|
||||
|
||||
/*
|
||||
* Mobile System Wake-Up Control (MSWC) device registers
|
||||
*/
|
||||
|
|
|
@ -62,7 +62,7 @@ NPCX_REG_OFFSET_CHECK(twd_reg, TWMWD, 0x00e);
|
|||
NPCX_REG_OFFSET_CHECK(twd_reg, WDCP, 0x010);
|
||||
|
||||
/* 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, NPCX_ONLY_ESPI_REG1, 0x0f0);
|
||||
NPCX_REG_OFFSET_CHECK(espi_reg, VWEVMS, 0x140);
|
||||
|
|
151
soc/arm/nuvoton_npcx/common/soc_espi_taf.h
Normal file
151
soc/arm/nuvoton_npcx/common/soc_espi_taf.h
Normal 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
|
|
@ -14,6 +14,10 @@ config NUM_IRQS
|
|||
config CORTEX_M_SYSTICK
|
||||
default !NPCX_ITIM_TIMER
|
||||
|
||||
config ESPI_TAF_NPCX
|
||||
default y
|
||||
depends on ESPI_SAF
|
||||
|
||||
source "soc/arm/nuvoton_npcx/npcx4/Kconfig.defconfig.npcx4*"
|
||||
|
||||
endif # SOC_SERIES_NPCX4
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include <reg/reg_def.h>
|
||||
#include <soc_dt.h>
|
||||
#include <soc_clock.h>
|
||||
#include <soc_espi_taf.h>
|
||||
#include <soc_pins.h>
|
||||
#include <soc_power.h>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue