// SPDX-License-Identifier: GPL-2.0
/*
* ZynqMP R5 Remote Processor driver
*
*/
#include <dt-bindings/power/xlnx-zynqmp-power.h>
#include <linux/dma-mapping.h>
#include <linux/firmware/xlnx-zynqmp.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox/zynqmp-ipi-message.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/remoteproc.h>
#include "remoteproc_internal.h"
/* IPI buffer MAX length */
#define IPI_BUF_LEN_MAX 32U
/* RX mailbox client buffer max length */
#define MBOX_CLIENT_BUF_MAX (IPI_BUF_LEN_MAX + \
sizeof(struct zynqmp_ipi_message))
#define RSC_TBL_XLNX_MAGIC ((uint32_t)'x' << 24 | (uint32_t)'a' << 16 | \
(uint32_t)'m' << 8 | (uint32_t)'p')
/*
* settings for RPU cluster mode which
* reflects possible values of xlnx,cluster-mode dt-property
*/
enum zynqmp_r5_cluster_mode {
SPLIT_MODE = 0, /* When cores run as separate processor */
LOCKSTEP_MODE = 1, /* cores execute same code in lockstep,clk-for-clk */
SINGLE_CPU_MODE = 2, /* core0 is held in reset and only core1 runs */
};
/**
* struct mem_bank_data - Memory Bank description
*
* @addr: Start address of memory bank
* @da: device address
* @size: Size of Memory bank
* @pm_domain_id: Power-domains id of memory bank for firmware to turn on/off
* @bank_name: name of the bank for remoteproc framework
*/
struct mem_bank_data {
phys_addr_t addr;
u32 da;
size_t size;
u32 pm_domain_id;
char *bank_name;
};
/**
* struct mbox_info
*
* @rx_mc_buf: to copy data from mailbox rx channel
* @tx_mc_buf: to copy data to mailbox tx channel
* @r5_core: this mailbox's corresponding r5_core pointer
* @mbox_work: schedule work after receiving data from mailbox
* @mbox_cl: mailbox client
* @tx_chan: mailbox tx channel
* @rx_chan: mailbox rx channel
*/
struct mbox_info {
unsigned char rx_mc_buf[MBOX_CLIENT_BUF_MAX];
unsigned char tx_mc_buf[MBOX_CLIENT_BUF_MAX];
struct zynqmp_r5_core *r5_core;
struct work_struct mbox_work;
struct mbox_client mbox_cl;
struct mbox_chan *tx_chan;
struct mbox_chan *rx_chan;
};
/**
* struct rsc_tbl_data
*
* Platform specific data structure used to sync resource table address.
* It's important to maintain order and size of each field on remote side.
*
* @version: version of data structure
* @magic_num: 32-bit magic number.
* @comp_magic_num: complement of above magic number
* @rsc_tbl_size: resource table size
* @rsc_tbl: resource table address
*/
struct rsc_tbl_data {
const int version;
const u32 magic_num;
const u32 comp_magic_num;
const u32 rsc_tbl_size;
const uintptr_t rsc_tbl;
} __packed;
/*
* Hardcoded TCM bank values. This will stay in driver to maintain backward
* compatibility with device-tree that does not have TCM information.
*/
static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
{0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
{0xffe20000UL, 0x20000, 0x10000UL, PD_R5_0_BTCM, "btcm0"},
{0xffe90000UL, 0x0, 0x10000UL, PD_R5_1_ATCM, "atcm1"},
{0xffeb0000UL, 0x20000, 0x10000UL, PD_R5_1_BTCM, "btcm1"},
};
/* In lockstep mode cluster uses each 64KB TCM from second core as well */
static cons