Files
android_kernel_samsung_sm86…/qcom/opensource/synx-kernel/msm/synx/ipclite.h
David Wronek 51ff30338b Add 'qcom/opensource/synx-kernel/' from commit '2657c18a7869feec83f4383bf72623b8d6a2ef18'
git-subtree-dir: qcom/opensource/synx-kernel
git-subtree-mainline: fe7b3b613f
git-subtree-split: 2657c18a78
Change-Id:
repo: https://git.codelinaro.org/clo/la/platform/vendor/opensource/synx-kernel
tag: LA.VENDOR.14.3.0.r1-17300-lanai.QSSI15.0
2024-10-06 16:45:32 +02:00

444 行
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,
};