Add samsung specific changes

This commit is contained in:
2025-08-11 14:29:00 +02:00
parent c66122e619
commit 4d134a1294
2688 changed files with 1127995 additions and 11475 deletions

View File

@@ -0,0 +1,419 @@
/* SPDX-License-Identifier: GPL-2.0
*
* cl_dsp.h -- DSP control for non-ALSA Cirrus Logic devices
*
* Copyright 2021 Cirrus Logic, Inc.
*
* Author: Fred Treven <fred.treven@cirrus.com>
*/
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/regmap.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
#ifndef __CL_DSP_H__
#define __CL_DSP_H__
#define CL_DSP_BYTES_PER_WORD 4
#define CL_DSP_BITS_PER_BYTE 8
#define CL_DSP_BYTE_MASK GENMASK(7, 0)
#define CL_DSP_NIBBLE_MASK GENMASK(15, 0)
#define CL_DSP_FW_FILE_HEADER_SIZE 40
#define CL_DSP_COEFF_FILE_HEADER_SIZE 16
#define CL_DSP_MAGIC_ID_SIZE 4
#define CL_DSP_WMFW_MAGIC_ID "WMFW"
#define CL_DSP_WMDR_MAGIC_ID "WMDR"
#define CL_DSP_DBLK_HEADER_SIZE 8
#define CL_DSP_COEFF_DBLK_HEADER_SIZE 20
#define CL_DSP_ALIGN 0x00000003
#define CL_DSP_TARGET_CORE_ADSP1 0x01
#define CL_DSP_TARGET_CORE_ADSP2 0x02
#define CL_DSP_TARGET_CORE_HALO 0x04
#define CL_DSP_TARGET_CORE_WARP2 0x12
#define CL_DSP_TARGET_CORE_MCU 0x45
#define CL_DSP_MIN_FORMAT_VERSION 0x03
#define CL_DSP_API_REVISION 0x0300
#define CL_DSP_ALGO_NAME_LEN_SIZE 1
#define CL_DSP_ALGO_DESC_LEN_SIZE 2
#define CL_DSP_ALGO_ID_SIZE 4
#define CL_DSP_COEFF_COUNT_SIZE 4
#define CL_DSP_COEFF_OFFSET_SIZE 2
#define CL_DSP_COEFF_TYPE_SIZE 2
#define CL_DSP_COEFF_NAME_LEN_SIZE 1
#define CL_DSP_COEFF_FULLNAME_LEN_SIZE 1
#define CL_DSP_COEFF_DESC_LEN_SIZE 2
#define CL_DSP_COEFF_LEN_SIZE 4
#define CL_DSP_COEFF_FLAGS_SIZE 4
#define CL_DSP_COEFF_FLAGS_SHIFT 16
#define CL_DSP_COEFF_NAME_LEN_MAX 32
#define CL_DSP_COEFF_MIN_FORMAT_VERSION 0x01
#define CL_DSP_COEFF_API_REV_HALO 0x030000
#define CL_DSP_COEFF_API_REV_ADSP2 0x000500
#define CL_DSP_ALGO_LIST_TERM 0xBEDEAD
#define CL_DSP_REV_OFFSET_SHIFT 8
#define CL_DSP_REV_MAJOR_MASK GENMASK(23, 16)
#define CL_DSP_REV_MAJOR_SHIFT 16
#define CL_DSP_REV_MINOR_MASK GENMASK(15, 8)
#define CL_DSP_REV_MINOR_SHIFT 8
#define CL_DSP_REV_PATCH_MASK GENMASK(7, 0)
#define CL_DSP_NUM_ALGOS_MAX 32
#ifndef CONFIG_CS40L26_SAMSUNG_USE_MAX_DATA_TX_SIZE
#define CL_DSP_MAX_WLEN 32
#else
#define CL_DSP_MAX_WLEN 4096
#endif
#define CL_DSP_XM_UNPACKED_TYPE 0x0005
#define CL_DSP_YM_UNPACKED_TYPE 0x0006
#define CL_DSP_PM_PACKED_TYPE 0x0010
#define CL_DSP_XM_PACKED_TYPE 0x0011
#define CL_DSP_YM_PACKED_TYPE 0x0012
#define CL_DSP_ALGO_INFO_TYPE 0x00F2
#define CL_DSP_WMFW_INFO_TYPE 0x00FF
#define CL_DSP_MEM_REG_TYPE_MASK GENMASK(27, 20)
#define CL_DSP_MEM_REG_TYPE_SHIFT 20
#define CL_DSP_PM_NUM_BYTES 5
#define CL_DSP_PACKED_NUM_BYTES 3
#define CL_DSP_UNPACKED_NUM_BYTES 4
#define CL_DSP_WMDR_DBLK_OFFSET_SIZE 2
#define CL_DSP_WMDR_DBLK_TYPE_SIZE 2
#define CL_DSP_WMDR_ALGO_ID_SIZE 4
#define CL_DSP_WMDR_ALGO_REV_SIZE 4
#define CL_DSP_WMDR_SAMPLE_RATE_SIZE 4
#define CL_DSP_WMDR_DBLK_LEN_SIZE 4
#define CL_DSP_WMDR_NAME_LEN 32
#define CL_DSP_WMDR_DATE_LEN 16
#define CL_DSP_WMDR_HEADER_LEN_SIZE 4
#define CL_DSP_WMDR_DATE_PREFIX "Date: "
#define CL_DSP_WMDR_DATE_PREFIX_LEN 6
#define CL_DSP_WMDR_FILE_NAME_MISSING "N/A"
#define CL_DSP_WMDR_FILE_DATE_MISSING "N/A"
#define CL_DSP_WMDR_NAME_TYPE 0xFE00
#define CL_DSP_WMDR_INFO_TYPE 0xFF00
/* HALO core */
#define CL_DSP_HALO_XMEM_PACKED_BASE 0x02000000
#define CL_DSP_HALO_XROM_PACKED_BASE 0x02006000
#define CL_DSP_HALO_XMEM_UNPACKED32_BASE 0x02400000
#define CL_DSP_HALO_XMEM_UNPACKED24_BASE 0x02800000
#define CL_DSP_HALO_XROM_UNPACKED24_BASE 0x02808000
#define CL_DSP_HALO_YMEM_PACKED_BASE 0x02C00000
#define CL_DSP_HALO_YMEM_UNPACKED32_BASE 0x03000000
#define CL_DSP_HALO_YMEM_UNPACKED24_BASE 0x03400000
#define CL_DSP_HALO_PMEM_BASE 0x03800000
#define CL_DSP_HALO_PROM_BASE 0x03C60000
#define CL_DSP_HALO_XM_FW_ID_REG 0x0280000C
#define CL_DSP_HALO_NUM_ALGOS_REG 0x02800024
#define CL_DSP_HALO_ALGO_REV_OFFSET 4
#define CL_DSP_HALO_ALGO_XM_BASE_OFFSET 8
#define CL_DSP_HALO_ALGO_XM_SIZE_OFFSET 12
#define CL_DSP_HALO_ALGO_YM_BASE_OFFSET 16
#define CL_DSP_HALO_ALGO_YM_SIZE_OFFSET 20
#define CL_DSP_ALGO_ENTRY_SIZE 24
#define CL_DSP_HALO_FLAG_READ BIT(0)
#define CL_DSP_HALO_FLAG_WRITE BIT(1)
#define CL_DSP_HALO_FLAG_VOLATILE BIT(2)
/* open wavetable */
#define CL_DSP_OWT_HEADER_MAX_LEN 254
#define CL_DSP_OWT_HEADER_ENTRY_SIZE 12
/* Waveform metadata */
#define CL_DSP_SVC_ID 1
#define CL_DSP_SVC_LEN 1
#define CL_DSP_MD_SIZE_MAX_BYTES 28
#define CL_DSP_MD_PRESENT BIT(10)
#define CL_DSP_MD_TERMINATOR 0xFFFFFF
#define CL_DSP_MD_TYPE_MASK GENMASK(23, 16)
#define CL_DSP_MD_LENGTH_MASK GENMASK(15, 8)
/* macros */
#define CL_DSP_WORD_ALIGN(n) (CL_DSP_BYTES_PER_WORD +\
(((n) / CL_DSP_BYTES_PER_WORD) *\
CL_DSP_BYTES_PER_WORD))
#define CL_DSP_GET_MAJOR(n) (((n) & CL_DSP_REV_MAJOR_MASK) >>\
CL_DSP_REV_MAJOR_SHIFT)
#define CL_DSP_GET_MINOR(n) (((n) & CL_DSP_REV_MINOR_MASK) >>\
CL_DSP_REV_MINOR_SHIFT)
#define CL_DSP_GET_PATCH(n) ((n) & CL_DSP_REV_PATCH_MASK)
#define CL_DSP_MEM_REGION_PREFIX(n) (((n) & CL_DSP_MEM_REG_TYPE_MASK) >>\
CL_DSP_MEM_REG_TYPE_SHIFT)
enum cl_dsp_wt_type {
WT_TYPE_V4_PCM = 0,
WT_TYPE_V4_PWLE = 1,
WT_TYPE_V4_PCM_F0_REDC = 2,
WT_TYPE_V4_PCM_F0_REDC_VAR = 3,
WT_TYPE_V4_COMPOSITE = 4,
WT_TYPE_V5_PCM_PCM_F0_REDC_Q = 5,
WT_TYPE_V5_PWLE_LONG = 6,
WT_TYPE_V5_PWLE_LINEAR = 7,
WT_TYPE_V6_PCM_F0_REDC = 8,
WT_TYPE_V6_PCM_F0_REDC_VAR = 9,
WT_TYPE_V6_COMPOSITE = 10,
WT_TYPE_V6_PCM_F0_REDC_Q = 11,
WT_TYPE_V6_PWLE = 12,
WT_TYPE_TERMINATOR = 0xFF,
};
union cl_dsp_wmdr_header {
struct {
char magic[CL_DSP_BYTES_PER_WORD];
u32 header_len;
u32 fw_revision : 24;
u8 file_format_version;
u32 api_revision : 24;
u8 target_core;
} __attribute__((__packed__));
u8 data[CL_DSP_COEFF_FILE_HEADER_SIZE];
};
union cl_dsp_wmfw_header {
struct {
char magic[CL_DSP_BYTES_PER_WORD];
u32 header_len;
u16 api_revision;
u8 target_core;
u8 file_format_version;
u32 xm_size;
u32 ym_size;
u32 pm_size;
u32 zm_size;
u32 timestamp[2];
u32 checksum;
} __attribute__((__packed__));
u8 data[CL_DSP_FW_FILE_HEADER_SIZE];
};
union cl_dsp_data_block_header {
struct {
u32 start_offset : 24;
u8 block_type;
u32 data_len;
} __attribute__((__packed__));
u8 data[CL_DSP_DBLK_HEADER_SIZE];
};
union cl_dsp_coeff_data_block_header {
struct {
u16 start_offset;
u16 block_type;
u32 algo_id;
u32 algo_rev;
u32 sample_rate;
u32 data_len;
} __attribute__((__packed__));
u8 data[CL_DSP_COEFF_DBLK_HEADER_SIZE];
};
struct cl_dsp_data_block {
union cl_dsp_data_block_header header;
u8 *payload;
};
struct cl_dsp_coeff_data_block {
union cl_dsp_coeff_data_block_header header;
u8 *payload;
};
struct cl_dsp_coeff_desc {
u32 parent_id;
char *parent_name;
u16 block_offset;
u16 block_type;
unsigned char name[CL_DSP_COEFF_NAME_LEN_MAX];
unsigned int reg;
unsigned int flags;
unsigned int length;
struct list_head list;
};
struct cl_dsp_memchunk {
u8 *data;
u8 *max;
int bytes;
u32 cache;
int cachebits;
};
struct cl_dsp_owt_header {
enum cl_dsp_wt_type type;
u16 flags;
u32 offset;
u32 size;
void *data;
u32 braking_time;
};
struct cl_dsp_owt_desc {
struct cl_dsp_owt_header waves[CL_DSP_OWT_HEADER_MAX_LEN];
int nwaves;
int bytes;
u8 *raw_data;
};
struct cl_dsp_wt_desc {
unsigned int id;
char wt_name_xm[CL_DSP_WMDR_NAME_LEN];
char wt_name_ym[CL_DSP_WMDR_NAME_LEN];
unsigned int wt_limit_xm;
unsigned int wt_limit_ym;
char wt_file[CL_DSP_WMDR_NAME_LEN];
char wt_date[CL_DSP_WMDR_DATE_LEN];
struct cl_dsp_owt_desc owt;
bool is_xm;
};
struct cl_dsp_algo_info {
unsigned int id;
unsigned int rev;
unsigned int xm_base;
unsigned int xm_size;
unsigned int ym_base;
unsigned int ym_size;
};
struct cl_dsp {
struct device *dev;
struct regmap *regmap;
struct list_head coeff_desc_head;
unsigned int num_algos;
struct cl_dsp_algo_info algo_info[CL_DSP_NUM_ALGOS_MAX + 1];
const struct cl_dsp_fw_desc *fw_desc;
const struct cl_dsp_mem_reg_desc *mem_reg_desc;
const struct cl_dsp_algo_params *algo_params;
struct cl_dsp_wt_desc *wt_desc;
};
#ifdef CONFIG_DEBUG_FS
/* Debug Logger */
struct cl_dsp_host_buffer {
__be32 buf1_base;
__be32 buf1_size;
__be32 buf2_base;
__be32 buf1_buf2_size;
__be32 buf3_base;
__be32 buf_total_size;
__be32 high_water_mark;
__be32 irq_count;
__be32 irq_ack;
__be32 next_write_index;
__be32 next_read_index;
__be32 error;
__be32 oldest_block_index;
__be32 requested_rewind;
__be32 reserved_space;
__be32 min_free;
__be32 blocks_written[2];
__be32 words_written[2];
} __packed;
struct cl_dsp_logger {
u32 *buf_data;
u32 buf_data_size;
u32 algo_id;
u32 host_buf_ptr;
u32 host_buf_base;
int host_buf_size_words;
u32 high_watermark;
};
struct cl_dsp_debugfs {
struct cl_dsp *core;
struct dentry *debugfs_root;
struct dentry *debugfs_node;
struct mutex lock;
struct cl_dsp_logger dl;
};
#define CL_DSP_DEBUGFS_NUM_CONTROLS 3
#define CL_DSP_DEBUGFS_RW_FILE_MODE 0600
#define CL_DSP_DEBUGFS_RO_FILE_MODE 0400
#define CL_DSP_DEBUGFS_WO_FILE_MOADE 0200
#define CL_DSP_DEBUGFS_TRACE_LOG_STRING_SIZE 3
#define CL_DSP_DEBUGFS_TRACE_LOG_DISABLE 0
#define CL_DSP_DEBUGFS_TRACE_LOG_ENABLE 1
#define CL_DSP_HOST_BUFFER_DATA_MASK 0x00FFFFFFu
#define CL_DSP_HOST_BUFFER_ERROR_OVERFLOW BIT(0)
#define CL_DSP_HOST_BUFFER_READ_INDEX_RESET 0x00FFFFFF
#define CL_DSP_HOST_BUFFER_IRQ_MASK BIT(0)
#define CL_DSP_HOST_BUFFER_DATA_SLOT_SIZE 10
#define HOST_BUFFER_FIELD(field) (offsetof(struct cl_dsp_host_buffer, field) / sizeof(__be32))
int cl_dsp_logger_update(struct cl_dsp_debugfs *db);
struct cl_dsp_debugfs *cl_dsp_debugfs_create(struct cl_dsp *dsp,
struct dentry *parent_node, u32 event_log_algo_id);
void cl_dsp_debugfs_destroy(struct cl_dsp_debugfs *db);
#endif /* CONFIG_DEBUG_FS */
/* Exported Functions */
struct cl_dsp *cl_dsp_create(struct device *dev, struct regmap *regmap);
int cl_dsp_destroy(struct cl_dsp *dsp);
int cl_dsp_wavetable_create(struct cl_dsp *dsp, unsigned int id,
const char *wt_name_xm, const char *wt_name_ym,
const char *wt_file);
int cl_dsp_firmware_parse(struct cl_dsp *dsp, const struct firmware *fw,
bool write_fw);
int cl_dsp_coeff_file_parse(struct cl_dsp *dsp, const struct firmware *fw);
int cl_dsp_get_reg(struct cl_dsp *dsp, const char *coeff_name,
const unsigned int block_type, const unsigned int algo_id,
unsigned int *reg);
int cl_dsp_get_flags(struct cl_dsp *dsp, const char *coeff_name,
const unsigned int block_type, const unsigned int algo_id,
unsigned int *flags);
int cl_dsp_get_length(struct cl_dsp *dsp, const char *coeff_name,
const unsigned int block_type, const unsigned int algo_id,
size_t *length);
bool cl_dsp_algo_is_present(struct cl_dsp *dsp, const unsigned int algo_id);
struct cl_dsp_memchunk cl_dsp_memchunk_create(void *data, int size);
int cl_dsp_memchunk_write(struct cl_dsp_memchunk *ch, int nbits, u32 val);
inline bool cl_dsp_memchunk_end(struct cl_dsp_memchunk *ch);
int cl_dsp_memchunk_read(struct cl_dsp *dsp, struct cl_dsp_memchunk *ch,
int nbits, void *val);
int cl_dsp_memchunk_flush(struct cl_dsp_memchunk *ch);
int cl_dsp_raw_write(struct cl_dsp *dsp, unsigned int reg,
const void *val, size_t val_len, size_t limit);
int cl_dsp_fw_id_get(struct cl_dsp *dsp, unsigned int *id);
int cl_dsp_fw_rev_get(struct cl_dsp *dsp, unsigned int *rev);
#endif /* __CL_DSP_H */

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2010-2015, 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (C) 2015 Linaro Ltd.
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __QCOM_SCM_H
#define __QCOM_SCM_H
@@ -15,6 +16,19 @@
#define QCOM_SCM_CPU_PWR_DOWN_L2_ON 0x0
#define QCOM_SCM_CPU_PWR_DOWN_L2_OFF 0x1
#define QCOM_SCM_HDCP_MAX_REQ_CNT 5
#define QCOM_SCM_CAMERA_MAX_QOS_CNT 20
struct qcom_scm_camera_qos {
u32 offset;
u32 val;
};
enum qcom_download_mode {
QCOM_DOWNLOAD_NODUMP = 0x00,
QCOM_DOWNLOAD_EDL = 0x01,
QCOM_DOWNLOAD_FULLDUMP = 0x10,
QCOM_DOWNLOAD_MINIDUMP = 0x20,
};
struct qcom_scm_hdcp_req {
u32 addr;
@@ -46,6 +60,19 @@ enum qcom_scm_sec_dev_id {
QCOM_SCM_ICE_DEV_ID = 20,
};
struct qcom_scm_current_perm_info {
__le32 vmid;
__le32 perm;
__le64 ctx;
__le32 ctx_size;
__le32 unused;
};
struct qcom_scm_mem_map_info {
__le64 mem_addr;
__le64 mem_size;
};
enum qcom_scm_ice_cipher {
QCOM_SCM_ICE_CIPHER_AES_128_XTS = 0,
QCOM_SCM_ICE_CIPHER_AES_128_CBC = 1,
@@ -56,16 +83,75 @@ enum qcom_scm_ice_cipher {
#define QCOM_SCM_PERM_READ 0x4
#define QCOM_SCM_PERM_WRITE 0x2
#define QCOM_SCM_PERM_EXEC 0x1
#define QCOM_SCM_VMID_TZ 0x1
#define QCOM_SCM_VMID_HLOS 0x3
#define QCOM_SCM_VMID_CP_TOUCH 0x8
#define QCOM_SCM_VMID_CP_BITSTREAM 0x9
#define QCOM_SCM_VMID_CP_PIXEL 0xA
#define QCOM_SCM_VMID_CP_NON_PIXEL 0xB
#define QCOM_SCM_VMID_CP_CAMERA 0xD
#define QCOM_SCM_VMID_HLOS_FREE 0xE
#define QCOM_SCM_VMID_MSS_MSA 0xF
#define QCOM_SCM_VMID_MSS_NONMSA 0x10
#define QCOM_SCM_VMID_CP_SEC_DISPLAY 0x11
#define QCOM_SCM_VMID_CP_APP 0x12
#define QCOM_SCM_VMID_LPASS 0x16
#define QCOM_SCM_VMID_WLAN 0x18
#define QCOM_SCM_VMID_WLAN_CE 0x19
#define QCOM_SCM_VMID_CP_SPSS_SP 0x1A
#define QCOM_SCM_VMID_CP_CAMERA_PREVIEW 0x1D
#define QCOM_SCM_VMID_CDSP 0x1E
#define QCOM_SCM_VMID_CP_SPSS_SP_SHARED 0x22
#define QCOM_SCM_VMID_CP_SPSS_HLOS_SHARED 0x24
#define QCOM_SCM_VMID_ADSP_HEAP 0x25
#define QCOM_SCM_VMID_CP_CDSP 0x2A
#define QCOM_SCM_VMID_NAV 0x2B
#define QCOM_SCM_VMID_TVM 0x2D
#define QCOM_SCM_VMID_OEMVM 0x31
#define QCOM_SCM_VMID_SOCCP 0x3C
#define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE)
#define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC)
static inline void qcom_scm_populate_vmperm_info(
struct qcom_scm_current_perm_info *destvm, int vmid, int perm)
{
if (!destvm)
return;
destvm->vmid = cpu_to_le32(vmid);
destvm->perm = cpu_to_le32(perm);
destvm->ctx = 0;
destvm->ctx_size = 0;
}
static inline void qcom_scm_populate_mem_map_info(
struct qcom_scm_mem_map_info *mem_to_map,
phys_addr_t mem_addr, size_t mem_size)
{
if (!mem_to_map)
return;
mem_to_map->mem_addr = cpu_to_le64(mem_addr);
mem_to_map->mem_size = cpu_to_le64(mem_size);
}
extern bool qcom_scm_is_available(void);
extern int qcom_scm_set_cold_boot_addr(void *entry);
extern int qcom_scm_set_warm_boot_addr(void *entry);
extern void qcom_scm_cpu_power_down(u32 flags);
extern int qcom_scm_sec_wdog_deactivate(void);
extern int qcom_scm_sec_wdog_trigger(void);
extern void qcom_scm_disable_sdi(void);
extern int qcom_scm_set_remote_state(u32 state, u32 id);
extern int qcom_scm_spin_cpu(void);
extern void qcom_scm_set_download_mode(enum qcom_download_mode mode);
extern int qcom_scm_get_download_mode(unsigned int *mode);
extern int qcom_scm_config_cpu_errata(void);
struct qcom_scm_pas_metadata {
void *ptr;
dma_addr_t phys;
@@ -74,16 +160,27 @@ struct qcom_scm_pas_metadata {
extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata,
size_t size,
struct qcom_scm_pas_metadata *ctx);
extern void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx);
struct qcom_scm_pas_metadata *ctx,
struct device *dev);
extern void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx,
struct device *dev);
extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr,
phys_addr_t size);
extern int qcom_scm_pas_auth_and_reset(u32 peripheral);
extern int qcom_scm_pas_shutdown(u32 peripheral);
extern int qcom_scm_pas_shutdown_retry(u32 peripheral);
extern bool qcom_scm_pas_supported(u32 peripheral);
extern int qcom_scm_get_sec_dump_state(u32 *dump_state);
extern int qcom_scm_assign_dump_table_region(bool is_assign, phys_addr_t addr, size_t size);
extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
extern int qcom_scm_io_reset(void);
extern bool qcom_scm_is_secure_wdog_trigger_available(void);
extern bool qcom_scm_is_mode_switch_available(void);
extern bool qcom_scm_restore_sec_cfg_available(void);
extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
@@ -93,10 +190,39 @@ extern int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size);
extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
u32 cp_nonpixel_start,
u32 cp_nonpixel_size);
extern int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size);
extern int
qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions,
size_t mem_regions_sz, u32 *srcvms, size_t src_sz,
struct qcom_scm_current_perm_info *newvms,
size_t newvms_sz);
extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
u64 *src,
const struct qcom_scm_vmperm *newvm,
unsigned int dest_cnt);
extern int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr,
u64 mem_size, u32 vmid);
extern int qcom_scm_kgsl_set_smmu_aperture(
unsigned int num_context_bank);
extern int qcom_scm_kgsl_set_smmu_lpac_aperture(
unsigned int num_context_bank);
extern int qcom_scm_kgsl_init_regs(u32 gpu_req);
extern int qcom_scm_kgsl_dcvs_tuning(u32 mingap, u32 penalty, u32 numbusy);
extern int qcom_scm_enable_shm_bridge(void);
extern int qcom_scm_delete_shm_bridge(u64 handle);
extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags,
u64 ipfn_and_s_perm_flags, u64 size_and_flags,
u64 ns_vmids, u64 *handle);
extern bool qcom_scm_dcvs_core_available(void);
extern bool qcom_scm_dcvs_ca_available(void);
extern int qcom_scm_dcvs_reset(void);
extern int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, int *version);
extern int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size);
extern int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time);
extern int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time);
extern int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time,
int context_count);
extern bool qcom_scm_ocmem_lock_available(void);
extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
@@ -104,6 +230,13 @@ extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
extern int qcom_scm_ocmem_unlock(enum qcom_scm_ocmem_client id, u32 offset,
u32 size);
extern int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr,
size_t size, uint32_t cipher,
unsigned int data_unit,
unsigned int ce);
extern int qcom_scm_clear_ice_key(uint32_t index, unsigned int ce);
extern int qcom_scm_derive_sw_secret(phys_addr_t paddr_key, size_t size_key,
phys_addr_t paddr_secret, size_t size_secret);
extern bool qcom_scm_ice_available(void);
extern int qcom_scm_ice_invalidate_key(u32 index);
extern int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
@@ -114,12 +247,41 @@ extern bool qcom_scm_hdcp_available(void);
extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
u32 *resp);
extern int qcom_scm_lmh_fetch_data(u32 node_id, u32 debug_type, uint32_t *peak,
uint32_t *avg);
extern int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt);
extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en);
extern int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure);
extern int qcom_scm_camera_update_camnoc_qos(uint32_t use_case_id,
uint32_t qos_cnt, struct qcom_scm_camera_qos *scm_buf);
extern int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param);
extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask);
extern int qcom_scm_get_tz_log_feat_id(u64 *version);
extern int qcom_scm_get_tz_feat_id_version(u64 feat_id, u64 *version);
extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len);
extern int qcom_scm_query_encrypted_log_feature(u64 *enabled);
extern int qcom_scm_request_encrypted_log(phys_addr_t buf, size_t len,
uint32_t log_id, bool is_full_encrypted_tz_logs_supported,
bool is_full_encrypted_tz_logs_enabled);
extern int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size,
phys_addr_t out_buf, size_t out_buf_size, int32_t *result,
u64 *response_type, unsigned int *data);
extern int qcom_scm_invoke_smc_legacy(phys_addr_t in_buf, size_t in_buf_size,
phys_addr_t out_buf, size_t out_buf_size, int32_t *result,
u64 *response_type, unsigned int *data);
extern int qcom_scm_invoke_callback_response(phys_addr_t out_buf,
size_t out_buf_size, int32_t *result, u64 *response_type,
unsigned int *data);
extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
u64 limit_node, u32 node_id, u64 version);
extern int qcom_scm_lmh_profile_change(u32 profile_id);
extern bool qcom_scm_lmh_dcvsh_available(void);
extern int qcom_scm_tsens_reinit(int *tsens_ret);
#endif

View File

@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _LINUX_SI_CORE_XTS_H__
#define _LINUX_SI_CORE_XTS_H__
#include <linux/firmware/qcom/si_object.h>
struct si_object *init_si_mem_object_user(struct dma_buf *dma_buf,
void (*release)(void *), void *private);
/* For 'mem_object_to_dma_buf' and 'is_mem_object' caller should own the 'object',
* (i.e. someone should have already called '__get_si_object').
*/
int is_mem_object(struct si_object *object);
struct dma_buf *mem_object_to_dma_buf(struct si_object *object);
#endif /* _LINUX_SI_CORE_XTS_H__ */

View File

@@ -0,0 +1,231 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _LINUX_SI_OBJECT_H__
#define _LINUX_SI_OBJECT_H__
#include <linux/kref.h>
#include <linux/completion.h>
/* Primordial Object */
/* It is used for bootstrapping the Mink IPC connection between a VM and QTEE.
*
* Each side (both the VM and the QTEE) starts up with no object received from the
* other side. They both ''assume'' the other side implements a permanent initial
* object in the object table.
*
* QTEE's initial object is typically called the ''root client env'', and it's
* invoked by VMs when they want to get a new clientEnv. The initial object created
* by the VMs is invoked by QTEE, it's typically called the ''primordial object''.
*
* To gracefully SWITCH the primordial object, use 'init_si_object_user' with
* 'SI_OT_ROOT' type and 'put_si_object' on the previous primordial object. si-core
* will issue the release on the old primordial object if QTEE is not using it.
*/
enum si_object_type {
SI_OT_USER = 0x1, /* QTEE object. */
SI_OT_CB_OBJECT = 0x2, /* Callback Object. */
SI_OT_ROOT = 0x8, /* ''Root client env.'' or 'primordial' Object. */
SI_OT_NULL = 0x10, /* NULL object. */
};
/* Maximum number of argument that can fit in a QTEE message. */
#define MAX_ARGS 64
struct si_object;
/**
* struct si_arg - argument for QTEE object invocation.
* @type: type of argument
* @flags: extra flags.
* @b: address and size if type of argument is buffer
* @o: si_object instance if type of argument is object
*/
struct si_arg {
enum arg_type {
SI_AT_END = 0,
SI_AT_IB, /* Input Buffer. */
SI_AT_OB, /* Output Buffer. */
SI_AT_IO, /* Input Object. */
SI_AT_OO /* Output Object. */
} type;
/* 'uaddr' holds a __user address. */
#define SI_ARG_FLAGS_UADDR 1
char flags;
union {
struct si_buffer {
union {
void *addr;
void __user *uaddr;
};
size_t size;
} b;
struct si_object *o;
};
};
static inline int size_of_arg(struct si_arg u[])
{
int i = 0;
while (u[i].type != SI_AT_END)
i++;
return i;
}
/* Context ID - It is a unique ID assigned to a invocation which is in progress.
* Objects's dispatcher can use the ID to differentiate between concurrent calls.
* ID [0 .. 10) are reserved, i.e. never passed to object's dispatcher.
*/
struct si_object_invoke_ctx {
unsigned int context_id;
#define OIC_FLAG_BUSY 1 /* Context is busy. */
#define OIC_FLAG_NOTIFY 2 /* Context needs to notify the current object. */
#define OIC_FLAG_QTEE 4 /* Context has objects shared with QTEE. */
unsigned int flags;
/* Current object invoked in this callback context. */
struct si_object *object;
/* Arguments passed to dispatch callback. */
struct si_arg u[MAX_ARGS + 1];
/* Objects that are used in async buffer request on this context. */
struct list_head objects_head;
int errno;
/* inbound and outbound buffers. */
struct {
struct si_buffer msg;
phys_addr_t paddr;
/* TODO. remove after moving to tzmem allocator. */
struct qtee_shm shm;
} in, out;
};
int si_object_do_invoke(struct si_object_invoke_ctx *oic,
struct si_object *object, unsigned long op, struct si_arg u[], int *result);
/* Reserved Operations. */
#define SI_OBJECT_OP_METHOD_MASK 0x0000FFFFU
#define SI_OBJECT_OP_METHOD_ID(op) ((op) & SI_OBJECT_OP_METHOD_MASK)
#define SI_OBJECT_OP_RELEASE (SI_OBJECT_OP_METHOD_MASK - 0)
#define SI_OBJECT_OP_RETAIN (SI_OBJECT_OP_METHOD_MASK - 1)
#define SI_OBJECT_OP_NO_OP (SI_OBJECT_OP_METHOD_MASK - 2)
struct si_object_operations {
void (*release)(struct si_object *object);
/**
* @op_supported:
*
* Query made to make sure the requested operation is supported. If defined,
* it is called before marshaling of the arguments (as optimisation).
*/
int (*op_supported)(unsigned long op);
/**
* @dispatch:
*
* Object's dispatch function called on object invocation.
* Multiple operations can be dispatched concurrently.
*/
int (*dispatch)(unsigned int context_id,
struct si_object *object, unsigned long op, struct si_arg args[]);
/**
* @notify:
*
* Notify the change in status of the pervious invocation to the driver;
* i.e. transport errors or success (status is zero).
*/
void (*notify)(unsigned int context_id, struct si_object *object, int status);
/**
* @prepare:
*
* Called on object of type AT_IO on direct call (or AT_OO on callback
* response) to QTEE. The object provider can return (1) a buffer argument
* and (2) an object. @args is { { .type == AT_OB }, { .type == AT_OO },
* { .type == AT_END } }. On failour, returns SI_OBJECT_OP_NO_OP, otherwise
* an operation that provider has done on @object.
*/
unsigned long (*prepare)(struct si_object *object, struct si_arg args[]);
};
struct si_object {
const char *name;
struct kref refcount;
enum si_object_type object_type;
union object_info {
unsigned long object_ptr;
} info;
struct si_object_operations *ops;
/* see si_core_async.c. */
struct list_head node;
/* see si_core_wq.c. */
struct work_struct work;
/* Callback for any internal cleanup before the object's release. */
void (*release)(struct si_object *object);
};
#define NULL_SI_OBJECT ((struct si_object *)(0))
#define ROOT_SI_OBJECT ((struct si_object *)(1))
static inline enum si_object_type typeof_si_object(struct si_object *object)
{
if (object == NULL_SI_OBJECT)
return SI_OT_NULL;
if (object == ROOT_SI_OBJECT)
return SI_OT_ROOT;
return object->object_type;
}
static inline const char *si_object_name(struct si_object *object)
{
if (object == NULL_SI_OBJECT)
return "null";
if (object == ROOT_SI_OBJECT)
return "root";
if (!object->name)
return "noname";
return object->name;
}
#define INIT_NULL_SI_OBJECT { .object_type = SI_OT_NULL }
#define SI_OBJECT(name, ...) __SI_OBJECT(name, ##__VA_ARGS__, 1)
#define __SI_OBJECT(name, n, ...) struct si_object name[(n)] = { INIT_NULL_SI_OBJECT }
struct si_object *allocate_si_object(void);
void free_si_object(struct si_object *object);
int init_si_object_user(struct si_object *object, enum si_object_type ot,
struct si_object_operations *ops, const char *fmt, ...);
int get_si_object(struct si_object *object);
void put_si_object(struct si_object *object);
int get_async_proto_version(void);
#endif /* _LINUX_SI_OBJECT_H__ */