Files
android_kernel_samsung_sm86…/msm/synx/ipclite.h
Viraj Mandlekar 88d2c55b0c msm: synx: ipclite: Versioning
1. IPCLite now support downgrading of APIs
depending on the version.
2. Version can be configured from Device Tree
3. Features can be configured from Device Tree
4. FW would downgrade to compatible versions.

Change-Id: Ie6a4d94f63a5ed4bea6327ced218cfb75fb9b8e6
Signed-off-by: Viraj Mandlekar <quic_vmandlek@quicinc.com>
2023-07-10 23:22:04 -07:00

444 lines
12 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved..
*/
#include <linux/hwspinlock.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/soc/qcom,ipcc.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#include "ipclite_client.h"
/* version related entries */
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define IPCMEM_INIT_COMPLETED 0x1
#define ACTIVE_CHANNEL 0x1
#define IPCMEM_TOC_SIZE (4*1024)
#define IPCMEM_TOC_VAR_OFFSET 0x100
#define GLOBAL_ATOMIC_SUPPORT_BMSK 0x1UL
/* IPCC signal info */
#define IPCLITE_MSG_SIGNAL 0
#define IPCLITE_MEM_INIT_SIGNAL 1
#define IPCLITE_VERSION_SIGNAL 2
#define IPCLITE_TEST_SIGNAL 3
#define IPCLITE_SSR_SIGNAL 4
#define IPCLITE_DEBUG_SIGNAL 5
#define MAX_CHANNEL_SIGNALS 6
/** Flag definitions for the entries */
#define IPCMEM_FLAGS_ENABLE_READ_PROTECTION (0x01)
#define IPCMEM_FLAGS_ENABLE_WRITE_PROTECTION (0x02)
#define IPCMEM_FLAGS_ENABLE_RW_PROTECTION \
(IPCMEM_FLAGS_ENABLE_READ_PROTECTION | \
IPCMEM_FLAGS_ENABLE_WRITE_PROTECTION)
#define IPCMEM_FLAGS_IGNORE_PARTITION (0x00000004)
/*Hardcoded macro to identify local host on each core*/
#define LOCAL_HOST IPCMEM_APPS
/* Timeout (ms) for the trylock of remote spinlocks */
#define HWSPINLOCK_TIMEOUT 1000
/* queue related entries */
#define FIFO_FULL_RESERVE 8
#define FIFO_ALIGNMENT 8
/* debug related entries */
#define IPCLITE_DEBUG_INFO_SIZE 256
#define IPCLITE_CORE_DBG_LABEL "APSS:"
#define IPCLITE_LOG_MSG_SIZE 100
#define IPCLITE_LOG_BUF_SIZE 512
#define IPCLITE_DBG_LABEL_SIZE 5
#define IPCLITE_SIGNAL_LABEL_SIZE 10
#define PREV_INDEX 2
#define ADD_OFFSET(x, y) ((void *)((size_t)x + y))
/* IPCLite Logging Mechanism */
#define IPCLITE_OS_LOG(__level, __fmt, arg...) \
do { \
if (ipclite_debug_level & __level) { \
if (ipclite_debug_control & IPCLITE_DMESG_LOG) \
pr_info(IPCLITE_CORE_DBG_LABEL "%s:"__fmt, \
ipclite_dbg_label[__level], ## arg); \
if (ipclite_debug_control & IPCLITE_INMEM_LOG) \
ipclite_inmem_log(IPCLITE_CORE_DBG_LABEL "%s:"__fmt, \
ipclite_dbg_label[__level], ## arg); \
} \
} while (0)
/* IPCLite Debug enable status */
#define IS_DEBUG_CONFIG(ipclite_debug) (ipclite_debug_control & ipclite_debug)
/* IPCLite Feature enable status */
#define IS_FEATURE_CONFIG(ipclite_feature) (feature_mask & ipclite_feature)
/* Global Atomic status */
#define ATOMIC_HW_MUTEX_ACQUIRE \
(IS_FEATURE_CONFIG(IPCLITE_GLOBAL_ATOMIC) ?: ipclite_hw_mutex_acquire())
#define ATOMIC_HW_MUTEX_RELEASE \
(IS_FEATURE_CONFIG(IPCLITE_GLOBAL_ATOMIC) ?: ipclite_hw_mutex_release())
/* API Structure */
struct ipclite_api_list {
int (*init)(struct platform_device *pdev);
int32_t (*register_client)(IPCLite_Client cb_func_ptr, void *priv);
int32_t (*register_test_client)(IPCLite_Client cb_func_ptr, void *priv);
int32_t (*msg_send)(int32_t proc_id, uint64_t data);
int32_t (*test_msg_send)(int32_t proc_id, uint64_t data);
int32_t (*partition_info)(struct global_region_info *global_ipcmem);
void (*recover)(enum ipcmem_host_type core_id);
} api_list_t;
/**
* enum ipclite_channel_status - channel status
*
* INACTIVE : Channel uninitialized or init failed
* IN_PROGRESS : Channel init passed, awaiting confirmation from remote host
* ACTIVE : Channel init passed in local and remote host, thus active
*/
enum ipclite_channel_status {
INACTIVE = 0,
IN_PROGRESS = 1,
ACTIVE = 2,
};
enum ipclite_feature_mask {
IPCLITE_GLOBAL_ATOMIC = 0x0001ULL,
IPCLITE_TEST_SUITE = 0x0002ULL,
};
enum ipclite_debug_level {
IPCLITE_ERR = 0x0001,
IPCLITE_WARN = 0x0002,
IPCLITE_INFO = 0x0004,
IPCLITE_DBG = 0x0008,
};
enum ipclite_debug_control {
IPCLITE_DMESG_LOG = 0x0001,
IPCLITE_DBG_STRUCT = 0x0002,
IPCLITE_INMEM_LOG = 0x0004,
};
enum ipclite_debug_dump {
IPCLITE_DUMP_DBG_STRUCT = 0x0001,
IPCLITE_DUMP_INMEM_LOG = 0x0002,
IPCLITE_DUMP_SSR = 0x0004,
};
static const char ipclite_dbg_label[][IPCLITE_DBG_LABEL_SIZE] = {
[IPCLITE_ERR] = "err",
[IPCLITE_WARN] = "warn",
[IPCLITE_INFO] = "info",
[IPCLITE_DBG] = "dbg"
};
/**
* IPCMEM Debug Structure Definitions
* - Present in Local Memory
*/
struct ipclite_debug_info_host {
uint32_t numsig_sent; //no. of signals sent from the core
uint32_t numsig_recv; //no. of signals received on the core
uint32_t tx_wr_index; //write index of tx queue
uint32_t tx_rd_index; //read index of tx queue
uint32_t rx_wr_index; //write index of rx queue
uint32_t rx_rd_index; //read index of rx queue
uint32_t num_intr; //no. of interrupts received on the core
uint32_t prev_tx_wr_index[PREV_INDEX]; //previous write index of tx queue
uint32_t prev_tx_rd_index[PREV_INDEX]; //previous read index of tx queue
uint32_t prev_rx_wr_index[PREV_INDEX]; //previous write index of rx queue
uint32_t prev_rx_rd_index[PREV_INDEX]; //previous read index of rx queue
};
struct ipclite_debug_info_overall {
uint32_t total_numsig_sent; //total no. of signals sent
uint32_t total_numsig_recv; //total no. of signals received
uint32_t last_sent_host_id; //last signal sent to host
uint32_t last_recv_host_id; //last signal received from host
uint32_t last_sigid_sent; //last sent signal id
uint32_t last_sigid_recv; //last received signal id
};
struct ipclite_debug_info {
uint32_t debug_version;
uint32_t debug_level;
uint32_t debug_control;
uint32_t debug_dump;
uint32_t debug_log_index;
};
struct ipclite_debug_inmem_buf {
char IPCLITELog[IPCLITE_LOG_BUF_SIZE][IPCLITE_LOG_MSG_SIZE];
};
struct ipclite_debug_struct {
struct ipclite_debug_info_overall dbg_info_overall;
struct ipclite_debug_info_host dbg_info_host[IPCMEM_NUM_HOSTS];
};
/**
* IPCMEM TOC Structure Definitions
* - Present in toc in shared memory
*/
struct ipcmem_host_info {
uint32_t hwlock_owner;
uint32_t configured_host;
};
struct ipcmem_partition_entry {
uint32_t base_offset; /*partition offset from IPCMEM base*/
uint32_t size; /*partition size*/
uint32_t flags; /*partition flags if required*/
uint32_t host0; /*subsystem 0 who can access this partition*/
uint32_t host1; /*subsystem 1 who can access this partition*/
uint32_t reserved; /*legacy partition active status*/
};
struct ipcmem_partition_info {
uint32_t num_entries; /* Number of channel partitions */
uint32_t entry_size; /* Size of partition_entry structure */
};
struct ipcmem_offsets {
uint32_t host_info;
uint32_t global_entry;
uint32_t partition_info;
uint32_t partition_entry;
uint32_t debug;
uint32_t reserved; /*Padded for 64-bit alignment*/
};
/**
* Any change in TOC header size can only be accomodated with
* major version change, as it is not backward compatible.
*/
struct ipcmem_toc_header {
uint32_t magic_number; /*Checksum of TOC*/
uint32_t init_done; /*TOC initialization status*/
uint32_t major_version;
uint32_t minor_version;
uint64_t feature_mask;
uint32_t reserved[6]; /*Padded for future use and 64-bit alignment*/
};
/**
* struct ipcmem_toc - Table of contents in ipcmem
*
* @hdr : Header to check for toc integrity, version and features
* @offsets : List of offsetted structures and partition entries
* available in the toc data region (ipcmem_toc_data)
*/
struct ipcmem_toc {
struct ipcmem_toc_header hdr;
struct ipcmem_offsets offsets;
/* ---------------------------------------
* ipcmem_toc_data @ 256-byte offset
* struct ipcmem_host_info host_info;
* struct ipcmem_partition_entry global_entry;
* struct ipcmem_partition_info partition_info;
* struct ipcmem_partition_entry partition_entry[num_entries];
* ---------------------------------------
*/
};
/**
* IPCMEM Partition Structure Definitions
* - Present in partitions in shared memory
*/
struct global_partition_header {
uint32_t partition_type;
uint32_t region_offset;
uint32_t region_size;
};
struct ipcmem_global_partition {
struct global_partition_header hdr;
};
struct ipcmem_partition_header {
uint32_t type; /*partition type*/
uint32_t desc_offset; /*descriptor offset*/
uint32_t desc_size; /*descriptor size*/
uint32_t fifo0_offset; /*fifo 0 offset*/
uint32_t fifo0_size; /*fifo 0 size*/
uint32_t fifo1_offset; /*fifo 1 offset*/
uint32_t fifo1_size; /*fifo 1 size*/
uint32_t status; /*partition status*/
};
struct ipcmem_partition {
struct ipcmem_partition_header hdr;
};
/**
* IPCMEM Helper Structure Definitions
* - Present in local memory
* - Can have pointers to toc and partitions in shared memory
*/
/*Pointers to offsetted structures in TOC*/
struct ipcmem_toc_data {
struct ipcmem_host_info *host_info;
struct ipcmem_partition_entry *global_entry;
struct ipcmem_partition_info *partition_info;
struct ipcmem_partition_entry *partition_entry;
};
struct ipcmem_region {
u64 aux_base;
void __iomem *virt_base;
uint32_t size;
};
struct ipclite_mem {
struct ipcmem_toc *toc;
struct ipcmem_toc_data toc_data;
struct ipcmem_region mem;
struct ipcmem_global_partition *global_partition;
struct ipcmem_partition **partition;
};
/**
* IPCLite Structure Definitions
* - Present in local memory
* - Can have pointers to partitions in shared memory
*/
struct ipclite_fifo {
uint32_t length;
__le32 *tail;
__le32 *head;
void *fifo;
size_t (*avail)(struct ipclite_fifo *fifo);
void (*peak)(struct ipclite_fifo *fifo,
void *data, size_t count);
void (*advance)(struct ipclite_fifo *fifo,
size_t count, uint32_t core_id);
void (*write)(struct ipclite_fifo *fifo,
const void *data, size_t dlen, uint32_t core_id, uint32_t signal_id);
void (*reset)(struct ipclite_fifo *fifo);
};
struct ipclite_irq_info {
struct mbox_client mbox_client;
struct mbox_chan *mbox_chan;
int irq;
int signal_id;
char irqname[32];
};
struct ipclite_client {
IPCLite_Client callback;
void *priv_data;
int reg_complete;
};
struct ipclite_channel {
uint32_t remote_pid;
struct ipclite_fifo *tx_fifo;
struct ipclite_fifo *rx_fifo;
spinlock_t tx_lock;
struct ipclite_irq_info irq_info[MAX_CHANNEL_SIGNALS];
struct ipclite_client client;
uint32_t channel_version;
uint32_t version_finalised;
uint32_t *gstatus_ptr;
uint32_t status;
};
/*Single structure that defines everything about IPCLite*/
struct ipclite_info {
struct device *dev;
struct ipclite_channel channel[IPCMEM_NUM_HOSTS];
struct ipclite_mem ipcmem;
struct hwspinlock *hwlock;
unsigned long hw_mutex_flags;
};
/*Default partition parameters*/
#define DEFAULT_PARTITION_TYPE 0x0
#define DEFAULT_PARTITION_STATUS INACTIVE
#define DEFAULT_PARTITION_HDR_SIZE 1024
#define DEFAULT_DESCRIPTOR_OFFSET 1024
#define DEFAULT_DESCRIPTOR_SIZE (3*1024)
#define DEFAULT_FIFO0_OFFSET (4*1024)
#define DEFAULT_FIFO0_SIZE (8*1024)
#define DEFAULT_FIFO1_OFFSET (12*1024)
#define DEFAULT_FIFO1_SIZE (8*1024)
#define DEFAULT_PARTITION_SIZE (32*1024)
#define DEFAULT_PARTITION_FLAGS IPCMEM_FLAGS_ENABLE_RW_PROTECTION
/*Loopback partition parameters*/
#define LOOPBACK_PARTITION_TYPE 0x1
/*Global partition parameters*/
#define GLOBAL_PARTITION_TYPE 0xFF
#define GLOBAL_PARTITION_HDR_SIZE (4*1024)
#define GLOBAL_REGION_OFFSET (4*1024)
#define GLOBAL_REGION_SIZE (124*1024)
#define GLOBAL_PARTITION_SIZE (128*1024)
#define GLOBAL_PARTITION_FLAGS IPCMEM_FLAGS_ENABLE_RW_PROTECTION
/*Debug partition parameters*/
#define DEBUG_PARTITION_SIZE (64*1024)
const struct ipcmem_partition_header default_partition_hdr = {
DEFAULT_PARTITION_TYPE,
DEFAULT_DESCRIPTOR_OFFSET,
DEFAULT_DESCRIPTOR_SIZE,
DEFAULT_FIFO0_OFFSET,
DEFAULT_FIFO0_SIZE,
DEFAULT_FIFO1_OFFSET,
DEFAULT_FIFO1_SIZE,
DEFAULT_PARTITION_STATUS,
};
/* TX and RX FIFO point to same location for such loopback partition type
* (FIFO0 offset = FIFO1 offset)
*/
const struct ipcmem_partition_header loopback_partition_hdr = {
LOOPBACK_PARTITION_TYPE,
DEFAULT_DESCRIPTOR_OFFSET,
DEFAULT_DESCRIPTOR_SIZE,
DEFAULT_FIFO0_OFFSET,
DEFAULT_FIFO0_SIZE,
DEFAULT_FIFO0_OFFSET,
DEFAULT_FIFO0_SIZE,
DEFAULT_PARTITION_STATUS,
};
const struct global_partition_header global_partition_hdr = {
GLOBAL_PARTITION_TYPE,
GLOBAL_REGION_OFFSET,
GLOBAL_REGION_SIZE,
};