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 <CHChang19@nuvoton.com>
This commit is contained in:
parent
8c6da49f73
commit
fe138fc246
3 changed files with 165 additions and 89 deletions
|
@ -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.len = (((uint16_t)taf_head.tag_hlen & 0xF) << 8) | taf_head.llen;
|
||||||
taf_pckt.tag = taf_head.tag_hlen >> 4;
|
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);
|
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);
|
taf_pckt.addr = sys_cpu_to_be32(taf_addr);
|
||||||
|
|
||||||
/* Get written data if eSPI TAF write */
|
/* 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));
|
roundsize = DIV_ROUND_UP(taf_pckt.len, sizeof(uint32_t));
|
||||||
for (i = 0; i < roundsize; i++) {
|
for (i = 0; i < roundsize; i++) {
|
||||||
taf_pckt.src[i] = inst->FLASHRXBUF[2 + 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
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_ESPI_FLASH_CHANNEL */
|
||||||
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
|
|
||||||
|
|
||||||
const struct espi_bus_isr espi_bus_isr_tbl[] = {
|
const struct espi_bus_isr espi_bus_isr_tbl[] = {
|
||||||
NPCX_ESPI_BUS_INT_ITEM(BERR, espi_bus_err_isr),
|
NPCX_ESPI_BUS_INT_ITEM(BERR, espi_bus_err_isr),
|
||||||
|
@ -447,7 +427,6 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1416,6 +1395,10 @@ static int espi_npcx_init(const struct device *dev)
|
||||||
/* Configure host sub-modules which HW blocks belong to core domain */
|
/* Configure host sub-modules which HW blocks belong to core domain */
|
||||||
npcx_host_init_subs_core_domain(dev, &data->callbacks);
|
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 */
|
/* eSPI Bus interrupt installation */
|
||||||
IRQ_CONNECT(DT_INST_IRQN(0),
|
IRQ_CONNECT(DT_INST_IRQN(0),
|
||||||
DT_INST_IRQ(0, priority),
|
DT_INST_IRQ(0, priority),
|
||||||
|
|
|
@ -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));
|
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 {
|
struct espi_taf_npcx_config {
|
||||||
uintptr_t base;
|
uintptr_t base;
|
||||||
uintptr_t mapped_addr;
|
uintptr_t mapped_addr;
|
||||||
|
@ -26,9 +34,19 @@ struct espi_taf_npcx_config {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct espi_taf_npcx_data {
|
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) \
|
#define HAL_INSTANCE(dev) \
|
||||||
((struct espi_reg *)((const struct espi_taf_npcx_config *) \
|
((struct espi_reg *)((const struct espi_taf_npcx_config *) \
|
||||||
(dev)->config)->base)
|
(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(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \
|
||||||
<< GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF;
|
<< 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 */
|
/* 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,
|
static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, uint32_t len,
|
||||||
uint8_t tag)
|
uint8_t tag)
|
||||||
|
@ -73,6 +109,7 @@ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr,
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check access region of write request is protected or not */
|
/* Check access region of write request is protected or not */
|
||||||
static bool espi_taf_check_write_protect(const struct device *dev, uint32_t addr,
|
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);
|
struct espi_reg *const inst = HAL_INSTANCE(dev);
|
||||||
|
|
||||||
|
if (cfg->nflash_devices == 0U) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_ESPI_TAF_AUTO_MODE)
|
#if defined(CONFIG_ESPI_TAF_AUTO_MODE)
|
||||||
inst->FLASHCTL |= BIT(NPCX_FLASHCTL_SAF_AUTO_READ);
|
inst->FLASHCTL |= BIT(NPCX_FLASHCTL_SAF_AUTO_READ);
|
||||||
#else
|
#else
|
||||||
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_AUTO_READ);
|
inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_AUTO_READ);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
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)
|
static bool espi_taf_npcx_channel_ready(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct espi_reg *const inst = HAL_INSTANCE(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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!device_is_ready(spi_dev)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,52 +263,58 @@ static void taf_release_flash_np_free(const struct device *dev)
|
||||||
inst->FLASHCTL = tmp;
|
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 espi_reg *const inst = HAL_INSTANCE(dev);
|
||||||
struct npcx_taf_head *head = (struct npcx_taf_head *)buffer;
|
struct npcx_taf_head taf_head;
|
||||||
uint8_t i;
|
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
|
/* Check the Flash Access TX Queue is empty by polling
|
||||||
* FLASH_TX_AVAIL.
|
* FLASH_TX_AVAIL.
|
||||||
*/
|
*/
|
||||||
if (WAIT_FOR(IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL),
|
if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL),
|
||||||
NPCX_FLASH_CHK_TIMEOUT, NULL)) {
|
NPCX_FLASH_CHK_TIMEOUT, NULL) == false) {
|
||||||
LOG_ERR("Check TX Queue Is Empty Timeout");
|
LOG_ERR("Check TX Queue Is Empty Timeout");
|
||||||
return -EBUSY;
|
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 */
|
/* Write packet to FLASHTXBUF */
|
||||||
|
size = DIV_ROUND_UP((uint8_t)(tx_buf[0]) + 1, sizeof(uint32_t));
|
||||||
for (i = 0; i < size; i++) {
|
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 */
|
/* Set the FLASHCTL.FLASH_TX_AVAIL bit to 1 to enqueue the packet */
|
||||||
taf_set_flash_c_avail(dev);
|
taf_set_flash_c_avail(dev);
|
||||||
|
|
||||||
/* Release FLASH_NP_FREE here to ready get next TAF request */
|
/* Release FLASH_NP_FREE here to ready get next TAF request */
|
||||||
if ((head->type != CYC_SCS_CMP_WITH_DATA_FIRST) &&
|
if ((type != CYC_SCS_CMP_WITH_DATA_FIRST) && (type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) {
|
||||||
(head->type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) {
|
|
||||||
taf_release_flash_np_free(dev);
|
taf_release_flash_np_free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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)
|
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_reg *const inst = HAL_INSTANCE(dev);
|
||||||
struct espi_taf_npcx_config *config = ((struct espi_taf_npcx_config *)(dev)->config);
|
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;
|
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;
|
uint8_t cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY;
|
||||||
uint32_t total_len = pckt->len;
|
uint32_t total_len = pckt->len;
|
||||||
uint32_t len = total_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 flash_req_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLASHREQSIZE);
|
||||||
uint8_t target_max_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP);
|
uint8_t target_max_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP);
|
||||||
uint16_t max_read_req = 32 << flash_req_size;
|
uint16_t max_read_req = 32 << flash_req_size;
|
||||||
struct npcx_taf_head taf_head;
|
uint8_t read_buf[64];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (flash_req_size > target_max_size) {
|
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 {
|
do {
|
||||||
data_ptr = (uint8_t *)taf_data_ptr->data;
|
rc = flash_read(spi_dev, addr, &read_buf[0], len);
|
||||||
|
|
||||||
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) {
|
if (rc) {
|
||||||
LOG_ERR("flash read fail 0x%x", rc);
|
LOG_ERR("flash read fail 0x%x", rc);
|
||||||
return -EIO;
|
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) {
|
if (rc) {
|
||||||
LOG_ERR("espi taf completion handler fail");
|
LOG_ERR("espi taf completion handler fail");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -330,12 +378,12 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_packet *pckt)
|
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;
|
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 *data_ptr = (uint8_t *)(taf_data_ptr->data);
|
||||||
struct npcx_taf_head taf_head;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (espi_taf_check_write_protect(dev, pckt->flash_addr,
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN;
|
rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0,
|
||||||
taf_head.type = CYC_SCS_CMP_WITHOUT_DATA;
|
NULL);
|
||||||
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) {
|
if (rc) {
|
||||||
LOG_ERR("espi taf completion handler fail");
|
LOG_ERR("espi taf completion handler fail");
|
||||||
return rc;
|
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)
|
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;
|
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 addr = pckt->flash_addr;
|
||||||
uint32_t len = pckt->len;
|
uint32_t len;
|
||||||
struct npcx_taf_head taf_head;
|
|
||||||
int rc;
|
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)) {
|
if (espi_taf_check_write_protect(dev, addr, len, taf_data_ptr->tag)) {
|
||||||
LOG_ERR("Access protection region");
|
LOG_ERR("Access protection region");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -385,13 +434,8 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN;
|
rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0,
|
||||||
taf_head.type = CYC_SCS_CMP_WITHOUT_DATA;
|
NULL);
|
||||||
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) {
|
if (rc) {
|
||||||
LOG_ERR("espi taf completion handler fail");
|
LOG_ERR("espi taf completion handler fail");
|
||||||
return rc;
|
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)
|
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 *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf;
|
||||||
= (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;
|
int rc;
|
||||||
|
|
||||||
taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN;
|
rc = taf_npcx_completion_handler(dev, CYC_UNSCS_CMP_WITHOUT_DATA_ONLY, taf_data_ptr->tag,
|
||||||
taf_head.type = CYC_UNSCS_CMP_WITHOUT_DATA_ONLY;
|
0x0, NULL);
|
||||||
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) {
|
if (rc) {
|
||||||
LOG_ERR("espi taf completion handler fail");
|
LOG_ERR("espi taf completion handler fail");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -423,6 +459,67 @@ static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_s
|
||||||
return 0;
|
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)
|
static int espi_taf_npcx_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct espi_reg *const inst = HAL_INSTANCE(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,
|
.set_protection_regions = espi_taf_npcx_set_pr,
|
||||||
.activate = espi_taf_npcx_activate,
|
.activate = espi_taf_npcx_activate,
|
||||||
.get_channel_status = espi_taf_npcx_channel_ready,
|
.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 = {
|
static const struct espi_taf_npcx_config espi_taf_npcx_config = {
|
||||||
.base = DT_INST_REG_ADDR(0),
|
.base = DT_INST_REG_ADDR(0),
|
||||||
.mapped_addr = DT_INST_PROP(0, mapped_addr),
|
.mapped_addr = DT_INST_PROP(0, mapped_addr),
|
||||||
|
|
|
@ -144,6 +144,8 @@ struct npcx_taf_head {
|
||||||
uint8_t llen;
|
uint8_t llen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue