// SPDX-License-Identifier: GPL-2.0-only
/* Copyright 2021 NXP */
#include <dt-bindings/firmware/imx/rsrc.h>
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/firmware.h>
#include <linux/firmware/imx/sci.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/remoteproc.h>
#include <linux/slab.h>
#include "imx_rproc.h"
#include "remoteproc_elf_helpers.h"
#include "remoteproc_internal.h"
#define DSP_RPROC_CLK_MAX 5
/*
* Module parameters
*/
static unsigned int no_mailboxes;
module_param_named(no_mailboxes, no_mailboxes, int, 0644);
MODULE_PARM_DESC(no_mailboxes,
"There is no mailbox between cores, so ignore remote proc reply after start, default is 0 (off).");
#define REMOTE_IS_READY BIT(0)
#define REMOTE_READY_WAIT_MAX_RETRIES 500
/* att flags */
/* DSP own area */
#define ATT_OWN BIT(31)
/* DSP instruction area */
#define ATT_IRAM BIT(30)
/* Definitions for i.MX8MP */
/* DAP registers */
#define IMX8M_DAP_DEBUG 0x28800000
#define IMX8M_DAP_DEBUG_SIZE (64 * 1024)
#define IMX8M_DAP_PWRCTL (0x4000 + 0x3020)
#define IMX8M_PWRCTL_CORERESET BIT(16)
/* DSP audio mix registers */
#define IMX8M_AudioDSP_REG0 0x100
#define IMX8M_AudioDSP_REG1 0x104
#define IMX8M_AudioDSP_REG2 0x108
#define IMX8M_AudioDSP_REG3 0x10c
#define IMX8M_AudioDSP_REG2_RUNSTALL BIT(5)
#define IMX8M_AudioDSP_REG2_PWAITMODE BIT(1)
/* Definitions for i.MX8ULP */
#define IMX8ULP_SIM_LPAV_REG_SYSCTRL0 0x8
#define IMX8ULP_SYSCTRL0_DSP_DBG_RST BIT(25)
#define IMX8ULP_SYSCTRL0_DSP_PLAT_CLK_EN BIT(19)
#define IMX8ULP_SYSCTRL0_DSP_PBCLK_EN BIT(18)
#define IMX8ULP_SYSCTRL0_DSP_CLK_EN BIT(17)
#define IMX8ULP_SYSCTRL0_DSP_RST BIT(16)
#define IMX8ULP_SYSCTRL0_DSP_OCD_HALT BIT(14)
#define IMX8ULP_SYSCTRL0_DSP_STALL BIT(13)
#define IMX8ULP_SIP_HIFI_XRDC 0xc200000e
/*
* enum - Predefined Mailbox Messages
*
* @RP_MBOX_SUSPEND_SYSTEM: system suspend request for the remote processor
*
* @RP_MBOX_SUSPEND_ACK: successful response from remote processor for a
* suspend request
*
* @RP_MBOX_RESUME_SYSTEM: system resume request for the remote processor
*
* @RP_MBOX_RESUME_ACK: successful response from remote processor for a
* resume request
*/
enum imx_dsp_rp_mbox_messages {
RP_MBOX_SUSPEND_SYSTEM = 0xFF11,
RP_MBOX_SUSPEND_ACK = 0xFF12,
RP_MBOX_RESUME_SYSTEM = 0xFF13,
RP_MBOX_RESUME_ACK = 0xFF14,
};
/**
* struct imx_dsp_rproc - DSP remote processor state
* @regmap: regmap handler
* @rproc: rproc handler
* @dsp_dcfg: device configuration pointer
* @clks: clocks needed by this device
* @cl: mailbox client to request the mailbox channel
* @cl_rxdb: mailbox client to request the mailbox channel for doorbell
* @tx_ch: mailbox tx channel handle
* @rx_ch: mailbox rx channel handle
* @rxdb_ch: mailbox rx doorbell channel handle
* @pd_list: power domain list
* @ipc_handle: System Control Unit ipc handle
* @rproc_work: work for processing virtio interrupts
* @pm_comp: completion primitive to sync for suspend response
* @flags: control flags
*/
struct imx_dsp_rproc {
struct regmap *regmap;
struct rproc *rproc;
const struct imx_dsp_rproc_dcfg *dsp_dcfg;
struct clk_bulk_data clks[DSP_RPROC_CLK_MAX];
struct mbox_client cl;
struct mbox_client cl_rxdb;
struct mbox_chan *tx_ch;
struct mbox_chan *rx_ch;
struct mbox_chan *rxdb_ch;
struct dev_pm_domain_list *pd_list;
struct imx_sc_ipc *ipc_handle;
struct work_struct rproc_work;
struct completion pm_comp;
u32 flags;
};
/**
* struct imx_dsp_rproc_dcfg - DSP remote processor configuration
* @dcfg: imx_rproc_dcfg handler
* @reset: reset callback function
*/
struct imx_dsp_rproc_dcfg {
const struct imx_rproc_dcfg *dcfg;
int (*reset)(struct imx_dsp_rproc *priv);
};
static const struct imx_rproc_att imx_dsp_rproc_att_imx8qm[] = {
/* dev addr , sys addr , size , flags */
{ 0x596e8000, 0x556e8000, 0x00008000, ATT_OWN },
{ 0x596f0000, 0x556f0000, 0x00008000, ATT_OWN },
{ 0x596f8000, 0x556f8000, 0x00000800, ATT_OWN | ATT_IRAM},
{ 0x55700000, 0x55700000, 0x00070000, ATT_OWN },
/* DDR (Data) */
{ 0x80000000, 0x80000000, 0x60000000, 0},
};
static const struct imx_rproc_att imx_dsp_rproc_att_imx8qxp[] = {
/* dev addr , sys addr , size , flags */
{ 0x596e8000, 0x596e8000, 0x00008000, ATT_OWN },
{ 0x596f0000, 0x596f0000