blob: 2b55a8d5bd83cec6497569d47c69e3badf09fad3 [file] [log] [blame]
/*
* Samsung Exynos SoC series NPU driver
*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/delay.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/time.h>
#include <linux/workqueue.h>
#include "npu-interface.h"
#include "npu-util-llq.h"
#define LINE_TO_SGMT(sgmt_len, ptr) ((ptr) & ((sgmt_len) - 1))
static struct workqueue_struct *wq;
static struct work_struct work_report;
static void __rprt_manager(struct work_struct *w);
struct npu_interface interface = {
.mbox_hdr = NULL,
.sfr = NULL,
.addr = NULL,
};
void dbg_dump_mbox(void)
{
int rptr;
u32 sgmt_len;
char *base;
volatile struct mailbox_ctrl *ctrl;
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_REPORT]);
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
rptr = 0;
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)),
(u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + (8 * K_SIZE)));
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_RESPONSE]);
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
rptr = 0;
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)),
(u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + (2 * K_SIZE)));
ctrl = &(interface.mbox_hdr->h2fctrl[MAILBOX_H2FCTRL_HPRIORITY]);
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
rptr = 0;
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)),
(u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + (1 * K_SIZE)));
ctrl = &(interface.mbox_hdr->h2fctrl[MAILBOX_H2FCTRL_LPRIORITY]);
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
rptr = 0;
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)),
(u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + (1 * K_SIZE)));
//Dump mbox_hdr
npu_debug_memdump32_by_memcpy((u32 *)interface.mbox_hdr,
(u32 *)(interface.mbox_hdr + 1));
}
void dbg_print_error(void)
{
u32 nSize = 0;
u32 wptr, rptr, sgmt_len;
char buf[BUFSIZE - 1] = "";
char *base;
volatile struct mailbox_ctrl *ctrl;
if (interface.mbox_hdr == NULL)
return;
mutex_lock(&interface.lock);
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_REPORT]);
wptr = ctrl->wptr;
rptr = ctrl->rptr;
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
if (wptr < rptr) { //When wptr circled a time,
while (rptr != 0) {
if ((sgmt_len - rptr) >= BUFSIZE) {
nSize = BUFSIZE - 1;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr += nSize;
} else {
nSize = sgmt_len - rptr;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr = 0;
}
pr_err("%s\n", buf);
buf[0] = '\0';
}
}
while (wptr != rptr) {
if ((wptr - rptr) > BUFSIZE - 1) {//need more memcpy from io.
nSize = BUFSIZE - 1;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr += nSize;
} else {
nSize = wptr - rptr;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr = wptr;
}
pr_err("%s\n", buf);
buf[0] = '\0';
}
mutex_unlock(&interface.lock);
}
void dbg_print_ncp_header(struct ncp_header *nhdr)
{
npu_info("============= ncp_header at %pK =============\n", nhdr);
npu_info("mabic_number1 \t: 0X%X\n", nhdr->magic_number1);
npu_info("hdr_version \t\t: 0X%X\n", nhdr->hdr_version);
npu_info("hdr_size \t\t: 0X%X\n", nhdr->hdr_size);
npu_info("net_id \t\t: 0X%X\n", nhdr->net_id);
npu_info("unique_id \t\t: 0X%X\n", nhdr->unique_id);
npu_info("priority \t\t: 0X%X\n", nhdr->priority);
npu_info("flags \t\t: 0X%X\n", nhdr->flags);
npu_info("period \t\t: 0X%X\n", nhdr->period);
npu_info("workload \t\t: 0X%X\n", nhdr->workload);
npu_info("addr_vector_offset \t: 0X%X\n", nhdr->address_vector_offset);
npu_info("addr_vector_cnt \t: 0X%X\n", nhdr->address_vector_cnt);
npu_info("magic_number2 \t: 0X%X\n", nhdr->magic_number2);
}
void dbg_print_interface(void)
{
npu_info("============= interface at %pK =============\n", &interface);
npu_info("mbox_hdr \t\t: 0x%pK\n", interface.mbox_hdr);
npu_info("mbox_hdr.max_slot \t: %d\n", interface.mbox_hdr->max_slot);
npu_info("mbox_hdr.version \t: %d\n", interface.mbox_hdr->version);
npu_info("mbox_hdr.signature2 \t: 0X%x\n", interface.mbox_hdr->signature2);
npu_info("mbox_hdr.signature1 \t: 0X%x\n", interface.mbox_hdr->signature1);
npu_info("sfr \t\t\t: 0x%pK\n", interface.sfr);
npu_info("addr \t\t\t: 0x%pK\n", interface.addr);
}
static irqreturn_t mailbox_isr2(int irq, void *data)
{
u32 val;
val = interface.sfr->grp[3].ms;
if (val)
interface.sfr->grp[3].c = val;
if (interface.rslt_notifier != NULL)
interface.rslt_notifier(NULL);
return IRQ_HANDLED;
}
static irqreturn_t mailbox_isr3(int irq, void *data)
{
u32 val;
val = interface.sfr->grp[4].ms;
if (val)
interface.sfr->grp[4].c = val;
if (wq)
queue_work(wq, &work_report);
return IRQ_HANDLED;
}
static void __send_interrupt(u32 cmdType)
{
u32 val;
switch (cmdType) {
case COMMAND_LOAD:
case COMMAND_UNLOAD:
case COMMAND_PROFILE_CTL:
case COMMAND_PURGE:
case COMMAND_POWERDOWN:
case COMMAND_FW_TEST:
interface.sfr->grp[0].g = 0x10000;
val = interface.sfr->grp[0].g;
//npu_info("g0.g = %x\n", val);
break;
case COMMAND_PROCESS:
interface.sfr->grp[2].g = 0xFFFFFFFF;
val = interface.sfr->grp[2].g;
//npu_info("g2.g = %x\n", val);
break;
case COMMAND_DONE:
interface.sfr->grp[3].g = 0xFFFFFFFF;
val = interface.sfr->grp[3].g;
//npu_info("g3.g = %x\n", val);
break;
default:
break;
}
}
static int npu_set_cmd(struct message *msg, struct command *cmd, u32 cmdType)
{
int ret = 0;
ret = mbx_ipc_put((void *)interface.addr, &interface.mbox_hdr->h2fctrl[cmdType], msg, cmd);
if (ret)
goto I_ERR;
__send_interrupt(msg->command);
return 0;
I_ERR:
switch (ret) {
case -ERESOURCE:
npu_warn("No space left on mailbox : ret = %d\n", ret);
break;
default:
npu_err("mbx_ipc_put err with %d\n", ret);
break;
}
return ret;
}
static ssize_t get_ncp_hdr_size(const struct npu_nw *nw)
{
struct ncp_header *ncp_header;
BUG_ON(!nw);
if (nw->ncp_addr.vaddr == NULL) {
npu_err("not specified in ncp_addr.kvaddr");
return -EINVAL;
}
ncp_header = (struct ncp_header *)nw->ncp_addr.vaddr;
//dbg_print_ncp_header(ncp_header);
if (ncp_header->magic_number1 != NCP_MAGIC1) {
npu_info("invalid MAGIC of NCP header (0x%08x) at (%pK)", ncp_header->magic_number1, ncp_header);
return -EINVAL;
}
return ncp_header->hdr_size;
}
int npu_interface_probe(struct device *dev, void *regs)
{
int ret = 0;
BUG_ON(!dev);
if (!regs) {
probe_err("fail in %s\n", __func__);
ret = -EINVAL;
return ret;
}
interface.sfr = (volatile struct mailbox_sfr *)regs;
mutex_init(&interface.lock);
wq = alloc_workqueue("my work", WQ_FREEZABLE|WQ_HIGHPRI, 1);
INIT_WORK(&work_report, __rprt_manager);
probe_info("complete in %s\n", __func__);
return ret;
}
int npu_interface_open(struct npu_system *system)
{
int ret = 0;
struct npu_device *device;
struct device *dev = &system->pdev->dev;
BUG_ON(!system);
device = container_of(system, struct npu_device, system);
interface.addr = (void *)((system->tcu_sram.vaddr) + NPU_MAILBOX_BASE);
interface.mbox_hdr = system->mbox_hdr;
ret = devm_request_irq(dev, system->irq0, mailbox_isr2, 0, "exynos-npu", NULL);
if (ret) {
probe_err("fail(%d) in devm_request_irq(2)\n", ret);
goto err_exit;
}
ret = devm_request_irq(dev, system->irq1, mailbox_isr3, 0, "exynos-npu", NULL);
if (ret) {
probe_err("fail(%d) in devm_request_irq(3)\n", ret);
goto err_probe_irq2;
}
wq = create_singlethread_workqueue("rprt_manager");
if (!wq) {
npu_err("err in alloc_worqueue.\n");
goto err_exit;
}
ret = mailbox_init(interface.mbox_hdr);
if (ret) {
npu_err("error(%d) in npu_mailbox_init\n", ret);
goto err_workqueue;
}
return ret;
err_workqueue:
destroy_workqueue(wq);
err_probe_irq2:
devm_free_irq(dev, system->irq0, NULL);
err_exit:
interface.addr = NULL;
interface.mbox_hdr = NULL;
set_bit(NPU_DEVICE_ERR_STATE_EMERGENCY, &device->err_state);
npu_err("EMERGENCY_RECOVERY is triggered.\n");
return ret;
}
int npu_interface_close(struct npu_system *system)
{
int wptr, rptr;
struct device *dev = &system->pdev->dev;
if (!system) {
npu_err("fail in %s\n", __func__);
return -EINVAL;
}
devm_free_irq(dev, system->irq0, NULL);
devm_free_irq(dev, system->irq1, NULL);
queue_work(wq, &work_report);
if ((wq) && (interface.mbox_hdr)) {
if (work_pending(&work_report)) {
cancel_work_sync(&work_report);
wptr = interface.mbox_hdr->f2hctrl[1].wptr;
rptr = interface.mbox_hdr->f2hctrl[1].rptr;
npu_dbg("work was canceled due to interface close, rptr/wptr : %d/%d\n", wptr, rptr);
}
flush_workqueue(wq);
destroy_workqueue(wq);
wq = NULL;
}
interface.addr = NULL;
interface.mbox_hdr = NULL;
return 0;
}
int register_rslt_notifier(protodrv_notifier func)
{
interface.rslt_notifier = func;
return 0;
}
int register_msgid_get_type(int (*msgid_get_type_func)(int))
{
interface.msgid_get_type = msgid_get_type_func;
return 0;
}
int nw_req_manager(int msgid, struct npu_nw *nw)
{
int ret = 0;
struct command cmd = {};
struct message msg = {};
ssize_t hdr_size;
switch (nw->cmd) {
case NPU_NW_CMD_BASE:
npu_info("abnormal command type\n");
break;
case NPU_NW_CMD_LOAD:
cmd.c.load.oid = nw->uid;
cmd.c.load.tid = NPU_MAILBOX_DEFAULT_TID;
hdr_size = get_ncp_hdr_size(nw);
if (hdr_size <= 0) {
npu_info("fail in get_ncp_hdr_size: (%zd)", hdr_size);
ret = FALSE;
goto nw_req_err;
}
cmd.length = (u32)hdr_size;
cmd.payload = nw->ncp_addr.daddr;
msg.command = COMMAND_LOAD;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_UNLOAD:
cmd.c.unload.oid = nw->uid;//NPU_MAILBOX_DEFAULT_OID;
cmd.payload = 0;
cmd.length = 0;
msg.command = COMMAND_UNLOAD;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_PROFILE_START:
cmd.c.profile_ctl.ctl = PROFILE_CTL_CODE_START;
cmd.payload = nw->ncp_addr.daddr;
cmd.length = nw->ncp_addr.size;
msg.command = COMMAND_PROFILE_CTL;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_PROFILE_STOP:
cmd.c.profile_ctl.ctl = PROFILE_CTL_CODE_STOP;
cmd.payload = 0;
cmd.length = 0;
msg.command = COMMAND_PROFILE_CTL;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_STREAMOFF:
cmd.c.purge.oid = nw->uid;
cmd.payload = 0;
msg.command = COMMAND_PURGE;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_POWER_DOWN:
cmd.c.powerdown.dummy = nw->uid;
cmd.payload = 0;
msg.command = COMMAND_POWERDOWN;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_FW_TC_EXECUTE:
cmd.c.fw_test.param = nw->param0;
cmd.payload = 0;
cmd.length = 0;
msg.command = COMMAND_FW_TEST;
msg.length = sizeof(struct command);
break;
case NPU_NW_CMD_END:
break;
default:
npu_err("invalid CMD ID: (%db)", nw->cmd);
ret = FALSE;
goto nw_req_err;
}
msg.mid = msgid;
ret = npu_set_cmd(&msg, &cmd, NPU_MBOX_REQUEST_LOW);
if (ret)
goto nw_req_err;
mbx_ipc_print_dbg((void *)interface.addr, &interface.mbox_hdr->h2fctrl[0]);
return TRUE;
nw_req_err:
return ret;
}
int fr_req_manager(int msgid, struct npu_frame *frame)
{
int ret = FALSE;
struct command cmd = {};
struct message msg = {};
switch (frame->cmd) {
case NPU_FRAME_CMD_BASE:
break;
case NPU_FRAME_CMD_Q:
cmd.c.process.oid = frame->uid;
cmd.c.process.fid = frame->frame_id;
cmd.length = frame->mbox_process_dat.address_vector_cnt;
cmd.payload = frame->mbox_process_dat.address_vector_start_daddr;
msg.command = COMMAND_PROCESS;
msg.length = sizeof(struct command);
break;
case NPU_FRAME_CMD_END:
break;
}
msg.mid = msgid;
ret = npu_set_cmd(&msg, &cmd, NPU_MBOX_REQUEST_HIGH);
if (ret)
goto fr_req_err;
mbx_ipc_print_dbg((void *)interface.addr, &interface.mbox_hdr->h2fctrl[1]);
return TRUE;
fr_req_err:
return ret;
}
int nw_rslt_manager(int *ret_msgid, struct npu_nw *nw)
{
int ret;
struct message msg;
struct command cmd;
ret = mbx_ipc_peek_msg((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg);
if (ret <= 0)
return FALSE;
ret = interface.msgid_get_type(msg.mid);
if (ret != PROTO_DRV_REQ_TYPE_NW)
return FALSE;//report error content:
ret = mbx_ipc_get_msg((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg);
if (ret <= 0)
return FALSE;
ret = mbx_ipc_get_cmd((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg, &cmd);
if (ret) {
npu_err("get command error\n");
return FALSE;
}
if (msg.command == COMMAND_DONE) {
npu_info("COMMAND_DONE for mid: (%d)\n", msg.mid);
nw->result_code = NPU_ERR_NO_ERROR;
} else if (msg.command == COMMAND_NDONE) {
npu_err("COMMAND_NDONE for mid: (%d) error(%u/0x%08x)\n"
, msg.mid, cmd.c.ndone.error, cmd.c.ndone.error);
nw->result_code = cmd.c.ndone.error;
} else {
npu_err("invalid msg.command: (%d)\n", msg.command);
return FALSE;
}
fw_rprt_manager();
*ret_msgid = msg.mid;
return TRUE;
}
int fr_rslt_manager(int *ret_msgid, struct npu_frame *frame)
{
int ret = FALSE;
struct message msg;
struct command cmd;
ret = mbx_ipc_peek_msg((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg);
if (ret <= 0)
return FALSE;
ret = interface.msgid_get_type(msg.mid);
if (ret != PROTO_DRV_REQ_TYPE_FRAME) {
//npu_info("get type error: (%d)\n", ret);
return FALSE;
}
ret = mbx_ipc_get_msg((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg);
if (ret <= 0)// 0 : no msg, less than zero : Err
return FALSE;
ret = mbx_ipc_get_cmd((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0], &msg, &cmd);
if (ret)
return FALSE;
if (msg.command == COMMAND_DONE) {
npu_info("COMMAND_DONE for mid: (%d)\n", msg.mid);
frame->result_code = NPU_ERR_NO_ERROR;
} else if (msg.command == COMMAND_NDONE) {
npu_err("COMMAND_NDONE for mid: (%d) error(%u/0x%08x)\n"
, msg.mid, cmd.c.ndone.error, cmd.c.ndone.error);
frame->result_code = cmd.c.ndone.error;
} else {
npu_err("invalid msg.command: (%d)\n", msg.command);
return FALSE;
}
*ret_msgid = msg.mid;
fw_rprt_manager();
return TRUE;
}
//Print log which was written with last 128 byte.
int npu_check_unposted_mbox(int nCtrl)
{
int pos;
int ret = TRUE;
char *base;
u32 nSize, wptr, rptr, sgmt_len;
u32 *buf, *strOut;
volatile struct mailbox_ctrl *ctrl;
if (interface.mbox_hdr == NULL)
return -1;
strOut = kzalloc(LENGTHOFEVIDENCE, GFP_ATOMIC);
if (!strOut) {
ret = -ENOMEM;
goto err_exit;
}
buf = kzalloc(LENGTHOFEVIDENCE, GFP_ATOMIC);
if (!buf) {
if (strOut)
kfree(strOut);
ret = -ENOMEM;
goto err_exit;
}
mutex_lock(&interface.lock);
switch (nCtrl) {
case ECTRL_LOW:
ctrl = &(interface.mbox_hdr->h2fctrl[MAILBOX_H2FCTRL_LPRIORITY]);
pr_err("[V] H2F_MBOX[LOW] - rptr/wptr : %d/%d\n", ctrl->rptr, ctrl->wptr);
break;
case ECTRL_HIGH:
ctrl = &(interface.mbox_hdr->h2fctrl[MAILBOX_H2FCTRL_HPRIORITY]);
pr_err("[V] H2F_MBOX[HIGH] - rptr/wptr : %d/%d\n", ctrl->rptr, ctrl->wptr);
break;
case ECTRL_ACK:
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_RESPONSE]);
pr_err("[V] F2H_MBOX[RESPONSE] - rptr/wptr : %d/%d\n", ctrl->rptr, ctrl->wptr);
break;
case ECTRL_REPORT:
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_REPORT]);
pr_err("[V] F2H_MBOX[REPORT] - rptr/wptr : %d/%d\n", ctrl->rptr, ctrl->wptr);
break;
default:
BUG_ON(1);
}
wptr = ctrl->wptr;
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
pos = 0;
if (wptr < LENGTHOFEVIDENCE) {
rptr = sgmt_len - (LENGTHOFEVIDENCE - wptr);
nSize = LENGTHOFEVIDENCE - wptr;
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)), (u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + nSize));
rptr = 0;
pos = 0;
nSize = wptr;
} else {
rptr = wptr - LENGTHOFEVIDENCE;
nSize = LENGTHOFEVIDENCE;
}
if (wptr > 0)
npu_debug_memdump32_by_memcpy((u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr)), (u32 *)(base + LINE_TO_SGMT(sgmt_len, rptr) + nSize));
mutex_unlock(&interface.lock);
ret = TRUE;
if (buf)
kfree(buf);
if (strOut)
kfree(strOut);
err_exit:
return ret;
}
static void __rprt_manager(struct work_struct *w)
{
char *base;
u32 nSize;
u32 wptr, rptr, sgmt_len;
char buf[BUFSIZE - 1] = "\0";
volatile struct mailbox_ctrl *ctrl;
if (interface.mbox_hdr == NULL)
return;
mutex_lock(&interface.lock);
ctrl = &(interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_REPORT]);
wptr = ctrl->wptr;
rptr = ctrl->rptr;
sgmt_len = ctrl->sgmt_len;
base = (void *)interface.addr - ctrl->sgmt_ofs;
if (wptr < rptr) { //When wptr circled a time,
while (rptr != 0) {
if ((sgmt_len - rptr) >= BUFSIZE) {
nSize = BUFSIZE - 1;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr += nSize;
} else {
nSize = sgmt_len - rptr;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr = 0;
}
npu_fw_report_store(buf, nSize);
buf[0] = '\0';
}
}
while (wptr != rptr) {
if ((wptr - rptr) > BUFSIZE - 1) {//need more memcpy from io.
nSize = BUFSIZE - 1;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr += nSize;
} else {
nSize = wptr - rptr;
memcpy_fromio(buf, base + LINE_TO_SGMT(sgmt_len, rptr), nSize);
rptr = wptr;
}
npu_fw_report_store(buf, nSize);
buf[0] = '\0';
}
interface.mbox_hdr->f2hctrl[MAILBOX_F2HCTRL_REPORT].rptr = wptr;
mutex_unlock(&interface.lock);
return;
}
void fw_rprt_manager(void)
{
if (wq)
queue_work(wq, &work_report);
else//not opened, or already closed.
return;
}
int mbx_rslt_fault_listener(void)
{
fw_rprt_manager();
dbg_print_ctrl(&interface.mbox_hdr->h2fctrl[0]);
mbx_ipc_print((void *)interface.addr, &interface.mbox_hdr->h2fctrl[0]);
dbg_print_ctrl(&interface.mbox_hdr->h2fctrl[1]);
mbx_ipc_print((void *)interface.addr, &interface.mbox_hdr->h2fctrl[1]);
dbg_print_ctrl(&interface.mbox_hdr->f2hctrl[0]);
mbx_ipc_print((void *)interface.addr, &interface.mbox_hdr->f2hctrl[0]);
dbg_print_ctrl(&interface.mbox_hdr->f2hctrl[1]);
fw_will_note(FW_LOGSIZE);
dbg_print_error();
return 0;
}
int nw_rslt_available(void)
{
int ret;
struct message msg;
ret = mbx_ipc_peek_msg(
(void *)interface.addr,
&interface.mbox_hdr->f2hctrl[0], &msg);
return ret;
}
int fr_rslt_available(void)
{
int ret;
struct message msg;
ret = mbx_ipc_peek_msg(
(void *)interface.addr,
&interface.mbox_hdr->f2hctrl[0], &msg);
return ret;
}
/* Unit test */
#ifdef CONFIG_VISION_UNITTEST
#define IDIOT_TESTCASE_IMPL "npu-interface.idiot"
#include "idiot-def.h"
#endif