From c22f93f7186f0285aba0876e9a93d81435c88fbd 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. We add and store reference to both side A and side B's MUs in the adsp structure because write to control register of side B has to make and reflect some changes in status register of side A. Signed-off-by: Diana Cretu Signed-off-by: Shreeya Patel --- hw/adsp/dsp/imx8-mu.c | 64 ++++++++++++++++++++++++++++++++++++- hw/adsp/dsp/imx8.c | 8 ++++- include/hw/audio/adsp-dev.h | 7 ++-- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/hw/adsp/dsp/imx8-mu.c b/hw/adsp/dsp/imx8-mu.c index 332c624b47ebe..2b2f2c6d07c6c 100644 --- a/hw/adsp/dsp/imx8-mu.c +++ b/hw/adsp/dsp/imx8-mu.c @@ -51,12 +51,69 @@ 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 xsr; 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 */ + xsr = adsp->mu_a->region[IMX_MU_xSR >> 2] & ~0; + xsr |= IMX_MU_xSR_GIPn(1); + adsp->mu_a->region[IMX_MU_xSR >> 2] = xsr; + 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 */ + xsr = adsp->mu_a->region[IMX_MU_xSR >> 2] & ~0; + xsr |= IMX_MU_xSR_GIPn(0); + adsp->mu_a->region[IMX_MU_xSR >> 2] = xsr; + 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_b; + uint64_t xcr, xsr; + + xcr = info->region[IMX_MU_xCR >> 2]; + + /* reply arrived from host */ + if (xcr & IMX_MU_xCR_GIRn(1)) { + /* set pending bit for reply on DSP */ + xsr = info->region[IMX_MU_xSR >> 2] & ~0; + xsr |= IMX_MU_xSR_GIPn(1); + info->region[IMX_MU_xSR >> 2] = xsr; + } else { + /* new message arrived from host, so activate pending bit */ + xsr = info->region[IMX_MU_xSR >> 2] & ~0; + xsr |= IMX_MU_xSR_GIPn(0); + info->region[IMX_MU_xSR >> 2] = xsr; + } } const MemoryRegionOps imx8_mu_ops = { @@ -69,4 +126,9 @@ void adsp_imx8_mu_init(struct adsp_dev *adsp, MemoryRegion *parent, struct adsp_io_info *info) { mu_reset(info); + if (!strcmp(info->space->name, "mu_13a")) { + adsp->mu_a = info; + } else { + adsp->mu_b = info; + } } diff --git a/hw/adsp/dsp/imx8.c b/hw/adsp/dsp/imx8.c index 0a056bc1d2148..fcc935290fca5 100644 --- a/hw/adsp/dsp/imx8.c +++ b/hw/adsp/dsp/imx8.c @@ -56,6 +56,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); @@ -251,7 +252,12 @@ static struct adsp_reg_space imx8_io[] = { .reg = adsp_imx8_mbox_map, .init = &adsp_mbox_init, .ops = &mbox_io_ops, .desc = {.base = ADSP_IMX8_DSP_MAILBOX_BASE, .size = ADSP_IMX8_DSP_MAILBOX_SIZE},}, - { .name = "mu", .reg_count = ARRAY_SIZE(adsp_imx8_mu_map), + { .name = "mu_13a", .reg_count = ARRAY_SIZE(adsp_imx8_mu_map), + .reg = adsp_imx8_mu_map, .init = &adsp_imx8_mu_init, + .ops = &imx8_mu_ops, + .desc = {.base = ADSP_IMX8_DSP_MU_BASE, + .size = ADSP_IMX8_DSP_MU_SIZE},}, + { .name = "mu_13b", .reg_count = ARRAY_SIZE(adsp_imx8_mu_map), .reg = adsp_imx8_mu_map, .init = &adsp_imx8_mu_init, .ops = &imx8_mu_ops, .desc = {.base = ADSP_IMX8_DSP_MU_BASE, diff --git a/include/hw/audio/adsp-dev.h b/include/hw/audio/adsp-dev.h index 555349d32f99f..97afc01c98506 100644 --- a/include/hw/audio/adsp-dev.h +++ b/include/hw/audio/adsp-dev.h @@ -42,9 +42,10 @@ struct adsp_dev_ops { }; struct adsp_dev { - - struct adsp_io_info *shim; - int shm_idx; + struct adsp_io_info *mu_a; + struct adsp_io_info *mu_b; + struct adsp_io_info *shim; + int shm_idx; /* runtime CPU */ struct adsp_xtensa *xtensa[ADSP_MAX_CORES];