ipc: cavs: read set d0ix request directly from ipc registers

cavs specific set d0ix message is read directly from ipc
registers and does not use mailbox located in SRAM which is
the only safe way to send a message to the cAVS DSP when
the DSP is in a lower power state.

The message is translated to SOF_IPC_PM_PWR_GATING message.

Response always use the mailbox since there is no way to write
the *T registers back with the current bi-directional communication
implemented using a single *T register set.

Signed-off-by: Marcin Maka <marcin.maka@linux.intel.com>
This commit is contained in:
Marcin Maka 2019-09-13 13:29:37 +02:00 committed by Liam Girdwood
parent bc0cbe2a27
commit 5e6ceb0829
2 changed files with 159 additions and 2 deletions

View File

@ -19,10 +19,20 @@
#include <sof/schedule/task.h>
#include <sof/spinlock.h>
#include <ipc/header.h>
#if CAVS_VERSION >= CAVS_VERSION_1_8
#include <ipc/header-intel-cavs.h>
#include <ipc/pm.h>
#endif
#include <config.h>
#include <stddef.h>
#include <stdint.h>
#if CAVS_VERSION >= CAVS_VERSION_1_8
#define CAVS_IPC_TYPE_S(x) ((x) & CAVS_IPC_TYPE_MASK)
#endif
extern struct ipc *_ipc;
/* No private data for IPC */
@ -118,17 +128,68 @@ static void ipc_irq_handler(void *arg)
}
}
#if CAVS_VERSION >= CAVS_VERSION_1_8
static struct sof_ipc_cmd_hdr *ipc_cavs_read_set_d0ix(uint32_t dr, uint32_t dd)
{
struct sof_ipc_pm_gate *cmd = _ipc->comp_data;
cmd->hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE;
cmd->hdr.size = sizeof(*cmd);
cmd->flags = dd & CAVS_IPC_MOD_SETD0IX_BIT_MASK;
return &cmd->hdr;
}
static struct sof_ipc_cmd_hdr *ipc_cavs_read_msg(void)
{
struct sof_ipc_cmd_hdr *hdr;
uint32_t dr;
uint32_t dd;
dr = ipc_read(IPC_DIPCTDR);
dd = ipc_read(IPC_DIPCTDD);
/* if there is no cAVS module IPC in regs go the previous path */
if (!(dr & CAVS_IPC_MSG_TGT))
return mailbox_validate();
switch (CAVS_IPC_TYPE_S(dr)) {
case CAVS_IPC_MOD_SET_D0IX:
hdr = ipc_cavs_read_set_d0ix(dr, dd);
break;
default:
return NULL;
}
dcache_writeback_region(hdr, hdr->size);
return hdr;
}
#endif
static enum task_state ipc_platform_do_cmd(void *data)
{
#if !CONFIG_SUECREEK
struct ipc *ipc = data;
#endif
struct sof_ipc_cmd_hdr *hdr;
struct sof_ipc_reply reply;
#if CAVS_VERSION >= CAVS_VERSION_1_8
hdr = ipc_cavs_read_msg();
#else
hdr = mailbox_validate();
#endif
/* perform command */
ipc_cmd(hdr);
if (hdr)
ipc_cmd(hdr);
else {
/* send invalid command error in reply */
reply.error = -EINVAL;
reply.hdr.cmd = SOF_IPC_GLB_REPLY;
reply.hdr.size = sizeof(reply);
mailbox_hostbox_write(0, &reply, sizeof(reply));
}
/* are we about to enter D3 ? */
#if !CONFIG_SUECREEK

View File

@ -0,0 +1,96 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2019 Intel Corporation. All rights reserved.
*
* Author: Marcin Maka <marcin.maka@linux.intel.com>
*/
/**
* \file include/ipc/header-intel-cavs.h
* \brief IPC command header for Intel cAVS platforms
* \author Marcin Maka <marcin.maka@linux.intel.com>
*/
#ifndef __IPC_HEADER_INTEL_CAVS_H__
#define __IPC_HEADER_INTEL_CAVS_H__
#include <sof/bit.h>
/* Primary register, mapped to
* - DIPCTDR (HIPCIDR) in sideband IPC (cAVS 1.8+)
* - DIPCT in cAVS 1.5 IPC
*
* Secondary register, mapped to:
* - DIPCTDD (HIPCIDD) in sideband IPC (cAVS 1.8+)
* - DIPCTE in cAVS 1.5 IPC
*/
/* Common bits in primary register */
#define CAVS_IPC_RSVD_31 BIT(31)
/** \brief Target, 0 - global message, 1 - message to a module */
#define CAVS_IPC_MSG_TGT BIT(30)
/** \brief Direction, 0 - request, 1 - response */
#define CAVS_IPC_RSP BIT(29)
#define CAVS_IPC_TYPE_SHIFT 24
#define CAVS_IPC_TYPE_MASK MASK(28, 24)
#define CAVS_IPC_TYPE(x) ((x) << CAVS_IPC_TYPE_SHIFT)
/* Bits in primary register for Module messages (CAVS_IPC_MSG_TGT set to 1) */
/** \brief ID of the target module instance */
#define CAVS_IPC_MOD_INSTANCE_ID_MASK MASK(23, 16)
/** \brief ID of the target module */
#define CAVS_IPC_MOD_ID_MASK MASK(15, 0)
/* Definition of bits in secondary register are message specific
* and are defined for each message separately later.
*/
/* Primary register :: type value for Module messages */
#define CAVS_IPC_MOD_INIT_INSTANCE CAVS_IPC_TYPE(0x0U)
#define CAVS_IPC_MOD_CFG_GET CAVS_IPC_TYPE(0x1U)
#define CAVS_IPC_MOD_CFG_SET CAVS_IPC_TYPE(0x2U)
#define CAVS_IPC_MOD_LARGE_CFG_GET CAVS_IPC_TYPE(0x3U)
#define CAVS_IPC_MOD_LARGE_CFG_SET CAVS_IPC_TYPE(0x4U)
#define CAVS_IPC_MOD_BIND CAVS_IPC_TYPE(0x5U)
#define CAVS_IPC_MOD_UNBIND CAVS_IPC_TYPE(0x6U)
#define CAVS_IPC_MOD_SET_DX CAVS_IPC_TYPE(0x7U)
#define CAVS_IPC_MOD_SET_D0IX CAVS_IPC_TYPE(0x8U)
#define CAVS_IPC_MOD_ENTER_RESTORE CAVS_IPC_TYPE(0x9U)
#define CAVS_IPC_MOD_EXIT_RESTORE CAVS_IPC_TYPE(0xaU)
#define CAVS_IPC_MOD_DELETE_INSTANCE CAVS_IPC_TYPE(0xbU)
#define CAVS_IPC_MOD_NOTIFICATION CAVS_IPC_TYPE(0xcU)
/* Secondary register bits for Module::SetD0iX
* ( Primary
* tgt = 1 (module message)
* rsp = 0 (request)
* type = CAVS_IPC_MOD_SET_D0IX
* )
*/
/** \brief Valid bits for SetD0ix */
#define CAVS_IPC_MOD_SETD0IX_BIT_MASK MASK(7, 0)
/** \brief Disable DMA tracing (0 - keep tracing, 1 - to disable DMA trace) */
#define CAVS_IPC_MOD_SETD0IX_NO_TRACE BIT(4)
/** \brief Prevent clock gating (0 - cg allowed, 1 - DSP clock always on) */
#define CAVS_IPC_MOD_SETD0IX_PCG BIT(3)
/** \brief Prevent power gating (0 - D0ix transitions allowed) */
#define CAVS_IPC_MOD_SETD0IX_PPG BIT(2)
/** \brief Streaming active */
#define CAVS_IPC_MOD_SETD0IX_STREAMING BIT(1)
/** \brief Legacy wake type, unused in cAVS 1.8+ */
#define CAVS_IPC_MOD_SETD0IX_WAKE_TYPE BIT(0)
#endif /* __IPC_HEADER_INTEL_CAVS_H__ */