firmware: arm_scmi: Add support for plh vendor protocol

PLH vendor protocol snapshot from msm-5.10 branch
commit 975d6a6235dd ("Add support for plh vendor protocol").

Change-Id: Idb412d3bc5b0596a669bb9ec54daa978e7c11903
Signed-off-by: simran jaiswal <quic_simranja@quicinc.com>
This commit is contained in:
simran jaiswal 2023-04-05 02:57:59 +05:30
parent 4817d1d1de
commit d2d3445771
7 changed files with 306 additions and 0 deletions

View File

@ -169,6 +169,17 @@ config QTI_SCMI_C1DCVS_PROTOCOL
This driver defines the comands or message ID's used for this
communication and also exposes the ops used by clients.
config QTI_SCMI_PLH_PROTOCOL
tristate "Qualcomm Technologies, Inc. SCMI PLH vendor Protocol"
depends on ARM_SCMI_PROTOCOL && QCOM_CPUCP
help
System Control and Management Interface (SCMI) plh vendor protocol
this protocol provides interface to communicate with micro controller
which is executing the plh algorithm.
This driver defines the comands or message ID's used for this
communication and also exposes the ops used by clients.
endif #ARM_SCMI_PROTOCOL
config ARM_SCMI_POWER_DOMAIN

View File

@ -16,6 +16,7 @@ obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o
obj-$(CONFIG_QTI_SCMI_PMU_PROTOCOL) += pmu_vendor.o
obj-$(CONFIG_QTI_SCMI_C1DCVS_PROTOCOL) += c1dcvs_vendor.o
obj-$(CONFIG_QTI_SCMI_VENDOR_PROTOCOL) += qcom_scmi_vendor.o
obj-$(CONFIG_QTI_SCMI_PLH_PROTOCOL) += plh_vendor.o
ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame

View File

@ -0,0 +1,175 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/scmi_plh.h>
#include "common.h"
#define SCMI_VENDOR_MSG_MAX_TX_SIZE (100) /* in bytes */
#define SCMI_VENDOR_MSG_START (3) /* MSG 3-15 can be used for spl purpose */
#define SCMI_VENDOR_MSG_SPLH_START (16) /* Each PLH module to use MAX 16 MSG */
#define SCMI_VENDOR_MSG_SPLH_END (31)
#define SCMI_VENDOR_MSG_LPLH_START (32) /* Each PLH module to use MAX 16 MSG */
#define SCMI_VENDOR_MSG_LPLH_END (47)
enum scmi_plh_protocol_cmd {
PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_SPLH_START,
PERF_LOCK_SCROLL_START_MSG_ID,
PERF_LOCK_SCROLL_STOP_MSG_ID,
PERF_LOCK_SCROLL_SET_SAMPLE_MS,
PERF_LOCK_SCROLL_SET_LOG_LEVEL,
PERF_LOCK_SCROLL_MAX_MSG_ID = SCMI_VENDOR_MSG_SPLH_END,
PERF_LOCK_LAUNCH_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_LPLH_START,
PERF_LOCK_LAUNCH_START_MSG_ID,
PERF_LOCK_LAUNCH_STOP_MSG_ID,
PERF_LOCK_LAUNCH_SET_SAMPLE_MS,
PERF_LOCK_LAUNCH_SET_LOG_LEVEL,
PERF_LOCK_LAUNCH_MAX_MSG_ID = SCMI_VENDOR_MSG_LPLH_END,
};
static int scmi_plh_init_ipc_freq_tbl(const struct scmi_protocol_handle *ph,
u16 *p_init_args, u16 init_len, enum plh_features feature)
{
uint32_t *msg, msg_size, msg_val, align_init_len = init_len;
struct scmi_xfer *t;
int ret, i = 0;
if (init_len % 2)
align_init_len += 1; /* align in multiple of u32 */
msg_size = align_init_len * sizeof(*p_init_args);
if (msg_size > SCMI_VENDOR_MSG_MAX_TX_SIZE)
return -EINVAL;
if (feature == PERF_LOCK_SCROLL)
ret = ph->xops->xfer_get_init(ph, PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID,
(msg_size), sizeof(uint32_t), &t);
else if (feature == PERF_LOCK_LAUNCH)
ret = ph->xops->xfer_get_init(ph, PERF_LOCK_LAUNCH_INIT_IPC_FREQ_TBL_MSG_ID,
(msg_size), sizeof(uint32_t), &t);
else
return -EINVAL;
if (ret)
return ret;
msg = t->tx.buf;
for (i = 0; i < init_len/2 ; i++) {
msg_val = *p_init_args++;
msg_val |= ((*p_init_args++) << 16);
*msg++ = cpu_to_le32(msg_val);
}
if (init_len % 2)
*msg = cpu_to_le32(*p_init_args);
ret = ph->xops->do_xfer(ph, t);
ph->xops->xfer_put(ph, t);
return ret;
}
static int scmi_plh_set_u16_val(const struct scmi_protocol_handle *ph,
u16 val, u32 msg_id)
{
int ret = 0;
struct scmi_xfer *t;
uint32_t *msg;
ret = ph->xops->xfer_get_init(ph, msg_id,
sizeof(*msg), sizeof(uint32_t), &t);
if (ret)
return ret;
msg = t->tx.buf;
*msg = cpu_to_le32(val);
ret = ph->xops->do_xfer(ph, t);
ph->xops->xfer_put(ph, t);
return ret;
}
static int scmi_plh_start_cmd(const struct scmi_protocol_handle *ph,
u16 value, enum plh_features feature)
{
int ret = -EINVAL;
if (feature == PERF_LOCK_SCROLL)
ret = scmi_plh_set_u16_val(ph, value, PERF_LOCK_SCROLL_START_MSG_ID);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, value, PERF_LOCK_LAUNCH_START_MSG_ID);
return ret;
}
static int scmi_plh_stop_cmd(const struct scmi_protocol_handle *ph, enum plh_features feature)
{
int ret = -EINVAL;
if (feature == PERF_LOCK_SCROLL)
ret = scmi_plh_set_u16_val(ph, 0, PERF_LOCK_SCROLL_STOP_MSG_ID);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, 0, PERF_LOCK_LAUNCH_STOP_MSG_ID);
return ret;
}
static int scmi_plh_set_sample_ms(const struct scmi_protocol_handle *ph,
u16 sample_ms, enum plh_features feature)
{
int ret = -EINVAL;
if (feature == PERF_LOCK_SCROLL)
ret = scmi_plh_set_u16_val(ph, sample_ms, PERF_LOCK_SCROLL_SET_SAMPLE_MS);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, sample_ms, PERF_LOCK_LAUNCH_SET_SAMPLE_MS);
return ret;
}
static int scmi_plh_set_log_level(const struct scmi_protocol_handle *ph,
u16 log_level, enum plh_features feature)
{
int ret = -EINVAL;
if (feature == PERF_LOCK_SCROLL)
ret = scmi_plh_set_u16_val(ph, log_level, PERF_LOCK_SCROLL_SET_LOG_LEVEL);
else if (feature == PERF_LOCK_LAUNCH)
ret = scmi_plh_set_u16_val(ph, log_level, PERF_LOCK_LAUNCH_SET_LOG_LEVEL);
return ret;
}
static const struct scmi_plh_vendor_ops plh_proto_ops = {
.init_plh_ipc_freq_tbl = scmi_plh_init_ipc_freq_tbl,
.start_plh = scmi_plh_start_cmd,
.stop_plh = scmi_plh_stop_cmd,
.set_plh_sample_ms = scmi_plh_set_sample_ms,
.set_plh_log_level = scmi_plh_set_log_level,
};
static int scmi_plh_vendor_protocol_init(const struct scmi_protocol_handle *ph)
{
u32 version;
ph->xops->version_get(ph, &version);
dev_dbg(ph->dev, "PLH version %d.%d\n",
PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
return 0;
}
static const struct scmi_protocol scmi_plh_vendor = {
.id = SCMI_PROTOCOL_PLH,
.owner = THIS_MODULE,
.instance_init = &scmi_plh_vendor_protocol_init,
.ops = &plh_proto_ops,
};
module_scmi_protocol(scmi_plh_vendor);
MODULE_DESCRIPTION("SCMI plh vendor Protocol");
MODULE_LICENSE("GPL");

View File

@ -1018,6 +1018,19 @@ config MSM_PERFORMANCE
fmin and fmax. The user space can request the cpu freq change by
writing cpu#:freq values
config QTI_PLH_SCMI_CLIENT
tristate "Qualcomm Technologies Inc. SCMI client driver for PLH"
depends on MSM_PERFORMANCE && QTI_SCMI_PLH_PROTOCOL
default n
help
SCMI client driver registers itself with SCMI framework for PLH
vendor protocol, and also registers with the plh interface driver
msm_performance.
This driver deliver the PLH vendor protocol handle to interface
driver, and interface driver will use this handle to communicate
with CPUCP PLH.
config QCOM_PANEL_EVENT_NOTIFIER
tristate "panel event notifier"
depends on DRM

View File

@ -84,6 +84,7 @@ obj-$(CONFIG_QCOM_CPUCP) += qcom_cpucp.o
obj-$(CONFIG_QTI_CPUCP_LOG) += cpucp_log.o
obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o
obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o
obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o
obj-$(CONFIG_QCOM_WCD_USBSS_I2C) += wcd_usbss_i2c.o
obj-$(CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS) += sysmon_subsystem_stats.o
obj-$(CONFIG_QCOM_CDSP_RM) += cdsprm.o

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/scmi_plh.h>
#include <linux/scmi_protocol.h>
static struct scmi_device *scmi_dev;
static int scmi_plh_inited;
struct scmi_device *get_plh_scmi_device(void)
{
if (!scmi_plh_inited)
return ERR_PTR(-EPROBE_DEFER);
if (!scmi_dev || !scmi_dev->handle)
return ERR_PTR(-ENODEV);
return scmi_dev;
}
EXPORT_SYMBOL(get_plh_scmi_device);
static int scmi_plh_probe(struct scmi_device *sdev)
{
int ret = 0;
scmi_dev = sdev;
if (!sdev)
ret = -ENODEV;
scmi_plh_inited = 1;
return ret;
}
static const struct scmi_device_id scmi_id_table[] = {
{ .protocol_id = SCMI_PROTOCOL_PLH, .name = "scmi_protocol_plh" },
{ }
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);
static struct scmi_driver scmi_plh_drv = {
.name = "scmi-plh-driver",
.probe = scmi_plh_probe,
.id_table = scmi_id_table,
};
module_scmi_driver(scmi_plh_drv);
MODULE_SOFTDEP("pre: plh_vendor");
MODULE_DESCRIPTION("ARM SCMI PLH driver");
MODULE_LICENSE("GPL");

47
include/linux/scmi_plh.h Normal file
View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* SCMI Vendor Protocols header
*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _SCMI_PLH_VENDOR_H
#define _SCMI_PLH_VENDOR_H
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/types.h>
#define SCMI_PROTOCOL_PLH 0x81
enum plh_features {
PERF_LOCK_SCROLL,
PERF_LOCK_LAUNCH,
};
struct scmi_protocol_handle;
extern struct scmi_device *get_plh_scmi_device(void);
/**
* struct scmi_plh_vendor_ops - represents the various operations provided
* by SCMI PLH Protocol
*
* @init_plh_ipc_freq_tbl: initialize plh ipc freq voting table in cpucp
* @start_plh: starts plh in cpucp
* @stop_plh: stops plh in cpucp
* @set_plh_sample_ms: configure the sampling duration of plh in cpucp
* @set_plh_log_level: configure the supported log_level of plh in cpucp
*/
struct scmi_plh_vendor_ops {
int (*init_plh_ipc_freq_tbl)(const struct scmi_protocol_handle *ph,
u16 *p_init_args, u16 init_len, enum plh_features feature);
int (*start_plh)(const struct scmi_protocol_handle *ph, u16 fps, enum plh_features feature);
int (*stop_plh)(const struct scmi_protocol_handle *ph, enum plh_features feature);
int (*set_plh_sample_ms)(const struct scmi_protocol_handle *ph,
u16 sample_ms, enum plh_features feature);
int (*set_plh_log_level)(const struct scmi_protocol_handle *ph,
u16 log_level, enum plh_features feature);
};
#endif