From 1efbc7e96699465a9f9c6b5e2883b5bc4085d4a4 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Mon, 19 Oct 2020 14:59:52 +0530 Subject: [PATCH 1/2] Firmware: arm_scmi: initial support for plh vendor protocol The perf lock hardening protocol is intended for the management of perf lock hardening on RIMPS. The commands in this protocol provide functionality to configure plh details, plh tunables, configuring the log levels and debugging support. Change-Id: I9f5292ee3e32a038160e66d38ec15637a55458fd Signed-off-by: Gaurav Singh --- drivers/firmware/Kconfig | 11 ++ drivers/firmware/arm_scmi/Makefile | 1 + drivers/firmware/arm_scmi/plh_vendor.c | 136 +++++++++++++++++++++++++ include/linux/scmi_protocol.h | 26 +++++ 4 files changed, 174 insertions(+) create mode 100644 drivers/firmware/arm_scmi/plh_vendor.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index e92975bc8d31..cfe983d86512 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -39,6 +39,17 @@ config QTI_SCMI_MEMLAT_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_RIMPS && QGKI + 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. + config ARM_SCMI_POWER_DOMAIN tristate "SCMI power domain driver" depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index eeabc570042d..3a463ac60fca 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,3 +5,4 @@ scmi-driver-y = driver.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o obj-$(CONFIG_QTI_SCMI_MEMLAT_PROTOCOL) += memlat_vendor.o +obj-$(CONFIG_QTI_SCMI_PLH_PROTOCOL) += plh_vendor.o diff --git a/drivers/firmware/arm_scmi/plh_vendor.c b/drivers/firmware/arm_scmi/plh_vendor.c new file mode 100644 index 000000000000..710244eb176b --- /dev/null +++ b/drivers/firmware/arm_scmi/plh_vendor.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "common.h" + +#define SCMI_VENDOR_MSG_MAX_TX_SIZE (100) /* in bytes */ +#define SCMI_VENDOR_MSG_START (3) +#define SCMI_VENDOR_MSG_PLH_START (16) + +enum scmi_plh_protocol_cmd { + PERF_LOCK_SET_LOG_LEVEL = SCMI_VENDOR_MSG_START, + PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_PLH_START, + PERF_LOCK_SCROLL_START_MSG_ID, + PERF_LOCK_SCROLL_STOP_MSG_ID, + PERF_LOCK_MAX_MSG_ID, +}; + + +static int scmi_plh_scroll_init_ipc_freq_tbl(const struct scmi_handle *handle, + u16 *p_init_args, u16 init_len) +{ + int ret, i = 0; + struct scmi_xfer *t; + uint32_t *msg, msg_size, msg_val, align_init_len = init_len; + + 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; + + ret = scmi_xfer_get_init(handle, PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID, + SCMI_PROTOCOL_PLH, + (msg_size), sizeof(uint32_t), &t); + 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 = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + + +static int scmi_send_start_stop(const struct scmi_handle *handle, + u16 fps, u32 msg_id) +{ + int ret = 0; + struct scmi_xfer *t; + uint32_t *msg; + + ret = scmi_xfer_get_init(handle, msg_id, + SCMI_PROTOCOL_PLH, + sizeof(*msg), sizeof(uint32_t), &t); + if (ret) + return ret; + + msg = t->tx.buf; + *msg = cpu_to_le32(fps); + ret = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_plh_scroll_start_cmd(const struct scmi_handle *handle, + u16 fps) +{ + return scmi_send_start_stop(handle, fps, PERF_LOCK_SCROLL_START_MSG_ID); +} + +static int scmi_plh_scroll_stop_cmd(const struct scmi_handle *handle) +{ + return scmi_send_start_stop(handle, 0, PERF_LOCK_SCROLL_STOP_MSG_ID); +} + +static int scmi_plh_set_log_level(const struct scmi_handle *handle, + u16 val) +{ + int ret = 0; + struct scmi_xfer *t; + uint32_t *msg; + + ret = scmi_xfer_get_init(handle, PERF_LOCK_SET_LOG_LEVEL, + SCMI_PROTOCOL_PLH, sizeof(*msg), + sizeof(uint32_t), &t); + if (ret) + return ret; + + msg = t->tx.buf; + *msg = cpu_to_le32(val); + ret = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + +static struct scmi_plh_vendor_ops plh_ops = { + .init_splh_ipc_freq_tbl = scmi_plh_scroll_init_ipc_freq_tbl, + .start_splh = scmi_plh_scroll_start_cmd, + .stop_splh = scmi_plh_scroll_stop_cmd, + .set_plh_log_level = scmi_plh_set_log_level, +}; + +static int scmi_plh_vendor_protocol_init(struct scmi_handle *handle) +{ + u32 version; + + scmi_version_get(handle, SCMI_PROTOCOL_PLH, &version); + + dev_dbg(handle->dev, "PLH version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + handle->plh_ops = &plh_ops; + + return 0; +} + +static int __init scmi_plh_init(void) +{ + return scmi_protocol_register(SCMI_PROTOCOL_PLH, + &scmi_plh_vendor_protocol_init); +} +subsys_initcall(scmi_plh_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 63c5a8edcd20..65ebd4f01223 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -266,6 +266,26 @@ struct scmi_memlat_vendor_ops { }; #endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL +/** + * struct scmi_plh_vendor_ops - represents the various operations provided + * by SCMI PLH Protocol + * + * @init_splh_ipc_freq_tbl: initialize scroll plh ipc freq voting table in rimps + * @start_splh: starts scroll plh in rimps + * @stop_splh: stops scroll plh in rimps + * @set_plh_log_level: configure the supported log_level in plh module of rimps + */ +struct scmi_plh_vendor_ops { + int (*init_splh_ipc_freq_tbl)(const struct scmi_handle *handle, + u16 *p_init_args, u16 init_len); + int (*start_splh)(const struct scmi_handle *handle, u16 fps); + int (*stop_splh)(const struct scmi_handle *handle); + int (*set_plh_log_level)(const struct scmi_handle *handle, + u16 log_level); +}; +#endif + /** * struct scmi_handle - Handle returned to ARM SCMI clients for usage. * @@ -297,6 +317,9 @@ struct scmi_handle { struct scmi_reset_ops *reset_ops; #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL struct scmi_memlat_vendor_ops *memlat_ops; +#endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL + struct scmi_plh_vendor_ops *plh_ops; #endif /* for protocol internal use */ void *perf_priv; @@ -317,6 +340,9 @@ enum scmi_std_protocol { #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL SCMI_PROTOCOL_MEMLAT = 0x80, #endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL + SCMI_PROTOCOL_PLH = 0x81, +#endif }; struct scmi_device { From 1a96b0ead88edd21422f31bda8228e05c6c24757 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Mon, 19 Oct 2020 17:35:47 +0530 Subject: [PATCH 2/2] drivers: soc: qcom: initial support for plh scmi client driver Add initial support for plh scmi client driver which registers into scmi framework for plh vendor protocol extension. Also registers with plh interface driver msm_performance. Change-Id: I448a714486ff4c7ea38cbeeec1ddb5e183b76e65 Signed-off-by: Gaurav Singh --- drivers/soc/qcom/Kconfig | 13 ++++++++++++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/plh_scmi.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 drivers/soc/qcom/plh_scmi.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6f0c03b0b8f6..ac125cd94bb6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -747,6 +747,19 @@ config QTI_SYSTEM_PM config QTI_SYSTEM_PM_RPM bool +config QTI_PLH_SCMI_CLIENT + tristate "Qualcomm Technologies Inc. SCMI client driver for PLH" + depends on QTI_PLH + 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 RIMPS PLH. + config QTI_HW_MEMLAT tristate "Qualcomm Technologies Inc. RIMPS memlat interface driver" depends on PERF_EVENTS diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 98557a7f9b35..66207079ef97 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o endif obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o obj-$(CONFIG_ICNSS2) += icnss2/ +obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o diff --git a/drivers/soc/qcom/plh_scmi.c b/drivers/soc/qcom/plh_scmi.c new file mode 100644 index 000000000000..67ddad6413a5 --- /dev/null +++ b/drivers/soc/qcom/plh_scmi.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +extern void rimps_plh_init(struct scmi_handle *handle); + +static int scmi_plh_probe(struct scmi_device *sdev) +{ + struct scmi_handle *handle = sdev->handle; + + if (!handle || !handle->plh_ops) + return -ENODEV; + + rimps_plh_init(handle); + return 0; +} + +static const struct scmi_device_id scmi_id_table[] = { + { 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_DESCRIPTION("ARM SCMI PLH driver"); +MODULE_LICENSE("GPL v2");