From c7887d0bf0b18ad656907001504c6f593994c298 Mon Sep 17 00:00:00 2001 From: dianacretu Date: Thu, 16 Apr 2020 10:41:33 +0300 Subject: [PATCH] hw: mu: Add mu-write implementation Add implementation for MU write in order to communicate with the host. Signed-off-by: Diana Cretu --- hw/adsp/dsp/imx8-mu.c | 64 ++++++++++++++++++++++++++++++++++++- hw/adsp/dsp/imx8.c | 1 + include/hw/adsp/mu.h | 2 ++ include/hw/audio/adsp-dev.h | 1 + 4 files changed, 67 insertions(+), 1 deletion(-) diff --git a/hw/adsp/dsp/imx8-mu.c b/hw/adsp/dsp/imx8-mu.c index 332c624b47eb..29b8926bff11 100644 --- a/hw/adsp/dsp/imx8-mu.c +++ b/hw/adsp/dsp/imx8-mu.c @@ -51,12 +51,73 @@ static void mu_write(void *opaque, hwaddr addr, struct adsp_io_info *info = opaque; struct adsp_dev *adsp = info->adsp; struct adsp_reg_space *space = info->space; + struct qemu_io_msg_irq irq; + uint64_t aux; log_write(adsp->log, space, addr, val, size, info->region[addr >> 2]); - /* set value via SHM */ + /* Interrupt arrived, check src */ info->region[addr >> 2] = val; + + switch(addr) { + case IMX_MU_xCR: + + /* send IRQ to parent */ + irq.hdr.type = QEMU_IO_TYPE_IRQ; + irq.hdr.msg = QEMU_IO_MSG_IRQ; + irq.hdr.size = sizeof(irq); + irq.irq = 0; + + /* send a new message to host */ + if (val & IMX_MU_xCR_GIRn(1)) { + /* activate pending bit on MU Side A */ + /* TODO: currently activates pending bit on MU Side B, + * so find a way to write to MU Side A regs + * aux = info->region[IMX_MU_xSR >> 2] & ~0; + * aux |= IMX_MU_xSR_GIPn(0); + * info->region[IMX_MU_xSR >> 2] = aux; + */ + qemu_io_send_msg(&irq.hdr); + } + + /* send reply to host */ + if (val & IMX_MU_xCR_GIRn(0)) { + /* TODO: currently activates pending bit on MU Side B */ + aux = info->region[IMX_MU_xSR >> 2] & ~0; + aux |= IMX_MU_xSR_GIPn(1); + info->region[IMX_MU_xSR >> 2] = aux; + qemu_io_send_msg(&irq.hdr); + } + + break; + case IMX_MU_xSR: + break; + default: + break; + } +} + +void adsp_imx8_irq_msg(struct adsp_dev *adsp, struct qemu_io_msg *msg) +{ + struct adsp_io_info *info = adsp->mu; + uint64_t aux; + + aux = info->region[IMX_MU_xCR >> 2]; + + /* reply arrived from host */ + if (aux & IMX_MU_xCR_GIRn(1)) { + /* set pending bit for reply on DSP */ + aux = info->region[IMX_MU_xSR >> 2] & ~0; + aux |= IMX_MU_xSR_GIPn(1); + info->region[IMX_MU_xSR >> 2] = aux; + } + else { + /* new message arrived from host, so activate pending bit */ + aux = info->region[IMX_MU_xSR >> 2] & ~0; + aux |= IMX_MU_xSR_GIPn(0); + info->region[IMX_MU_xSR >> 2] = aux; + } } const MemoryRegionOps imx8_mu_ops = { @@ -69,4 +130,5 @@ void adsp_imx8_mu_init(struct adsp_dev *adsp, MemoryRegion *parent, struct adsp_io_info *info) { mu_reset(info); + adsp->mu = info; } diff --git a/hw/adsp/dsp/imx8.c b/hw/adsp/dsp/imx8.c index 5124ad23734a..f5dab8f91ba2 100644 --- a/hw/adsp/dsp/imx8.c +++ b/hw/adsp/dsp/imx8.c @@ -54,6 +54,7 @@ static int bridge_cb(void *data, struct qemu_io_msg *msg) case QEMU_IO_TYPE_REG: break; case QEMU_IO_TYPE_IRQ: + adsp_imx8_irq_msg(adsp, msg); break; case QEMU_IO_TYPE_PM: adsp_pm_msg(adsp, msg); diff --git a/include/hw/adsp/mu.h b/include/hw/adsp/mu.h index 523afd2fe055..7e2c509e489f 100644 --- a/include/hw/adsp/mu.h +++ b/include/hw/adsp/mu.h @@ -31,4 +31,6 @@ /* General Purpose Interrupt Request */ #define IMX_MU_xCR_GIRn(x) BIT(16 + (3 - (x))) +#define MU_BASE_SIDEA 0x5D280000 + #endif diff --git a/include/hw/audio/adsp-dev.h b/include/hw/audio/adsp-dev.h index 555349d32f99..99d0e01a4457 100644 --- a/include/hw/audio/adsp-dev.h +++ b/include/hw/audio/adsp-dev.h @@ -43,6 +43,7 @@ struct adsp_dev_ops { struct adsp_dev { + struct adsp_io_info *mu; struct adsp_io_info *shim; int shm_idx;