diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index 45d69f8c4c37..1d1ab64c11df 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -198,6 +198,7 @@ CONFIG_VIDEOBUF2_VMALLOC=m CONFIG_SLIMBUS_MSM_NGD=m CONFIG_QRTR_HAVEN=m CONFIG_QCOM_CDSP_RM=m +CONFIG_QCOM_SYSMON_SUBSYSTEM_STATS=m CONFIG_QCOM_PDC=m CONFIG_HEADER_TEST=y CONFIG_HEADERS_INSTALL=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index dc81f16da5e0..89f4f2b7ee52 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -1050,6 +1050,16 @@ config CDSPRM_VTCM_DYNAMIC_DEBUG enabled, the vtcm partition details are sent to the CDSP via rpmsg channel. +config QCOM_SYSMON_SUBSYSTEM_STATS + tristate "Qualcomm Technologies SysMon DSP subsystem stats" + depends on QCOM_SMEM + help + sysMon subsystem stats driver exposes API to query DSP + subsystem's load and power statistics stored in SMEM. + SMEM region for each DSP subsystem is updated periodically + by the respective subsystem. Power stats gets updated after + DSP clock change event. + config QCOM_WDT_CORE tristate "Qualcomm Technologies, Inc. Watchdog Support" depends on ARCH_QCOM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index c2eb202f561a..9e3889984ba3 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -109,6 +109,7 @@ 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_QCOM_SYSMON_SUBSYSTEM_STATS) += sysmon_subsystem_stats.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/sysmon_subsystem_stats.c b/drivers/soc/qcom/sysmon_subsystem_stats.c new file mode 100644 index 000000000000..14ff0b7b650d --- /dev/null +++ b/drivers/soc/qcom/sysmon_subsystem_stats.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#define SYSMON_SMEM_ID 634 +#define SYSMON_POWER_STATS_VERSIONID 0x1 +#define SYSMON_POWER_STATS_FEATUREID 0x3 + +/** + * sysmon_stats_query_power_residency() - * API to query requested + * DSP subsystem power residency.On success, returns power residency + * statistics in the given sysmon_smem_power_stats structure. + */ +int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id, + struct sysmon_smem_power_stats *sysmon_power_stats) +{ + u32 featureId; + int err = 0; + int feature, size_rcvd; + size_t size; + char *smem_pointer = NULL; + int size_of_u32 = sizeof(u32); + + if (!sysmon_power_stats || !dsp_id) { + pr_err("%s: Null pointer received/invalid dsp ID\n", __func__); + return -EINVAL; + } + + smem_pointer = qcom_smem_get(dsp_id, SYSMON_SMEM_ID, &size); + + if (IS_ERR_OR_NULL(smem_pointer) || !size) { + pr_err("Failed to fetch data from SMEM for ID %d: %d\n", + dsp_id, PTR_ERR(smem_pointer)); + return -ENOMEM; + } + + featureId = *(unsigned int *)smem_pointer; + + feature = featureId >> 28; + size_rcvd = (featureId >> 16) & 0xFFF; + + while (size != 0) { + switch (feature) { + + case SYSMON_POWER_STATS_FEATUREID: + + if (!IS_ERR_OR_NULL(smem_pointer + size_of_u32)) { + memcpy(sysmon_power_stats, (smem_pointer + size_of_u32), + sizeof(struct sysmon_smem_power_stats)); + size = 0; + } else { + pr_err("%s: Requested feature not found\n", __func__); + size = 0; + return -ENOMEM; + } + break; + default: + + if (!IS_ERR_OR_NULL(smem_pointer + size_rcvd) + && (size > size_rcvd)) { + + featureId = *(unsigned int *)(smem_pointer + size_rcvd); + + smem_pointer += size_rcvd; + size = size - size_rcvd; + + feature = featureId >> 28; + size_rcvd = (featureId >> 16) & 0xFFF; + } else { + pr_err("%s: Requested feature not found\n", __func__); + size = 0; + return -ENOMEM; + } + break; + } + } + return err; +} +EXPORT_SYMBOL(sysmon_stats_query_power_residency); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Sysmon subsystem Stats driver"); diff --git a/include/linux/soc/qcom/sysmon_subsystem_stats.h b/include/linux/soc/qcom/sysmon_subsystem_stats.h new file mode 100644 index 000000000000..7e8840ef1e9a --- /dev/null +++ b/include/linux/soc/qcom/sysmon_subsystem_stats.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +/* + * This header is for sysmon subsystem stats query API's in drivers. + */ + +#ifndef __QCOM_SYSMON_SUBSYSTEM_STATS_H__ +#define __QCOM_SYSMON_SUBSYSTEM_STATS_H__ + +/* + * @struct sysmon_smem_power_stats_t + * @brief Structure type to hold DSP power statistics. + */ +struct sysmon_smem_power_stats { + u32 clk_arr[8]; + /**< Core clock frequency(KHz) array */ + + u32 active_time[8]; + /**< Active time(seconds) array corresponding to core clock array */ + + u32 pc_time; + /**< DSP LPM(Low Power Mode) time(seconds) */ + + u32 lpi_time; + /**< DSP LPI(Low Power Island Mode) time(seconds) */ +}; + +/* + * @enum dsp_id_t + * @brief Enum to hold SMEM HOST ID for DSP subsystems. + */ +enum dsp_id_t { + ADSP = 2, + SLPI, + CDSP = 5 +}; + +/** + * API to query requested DSP subsystem power residency. + * On success, returns power residency statistics in the given + * sysmon_smem_power_stats structure. + * @arg: DSP_ID +.* 2 - ADSP + * 3 - SLPI + * 5 - CDSP + *sysmon_smem_power_stats + * u32 clk_arr[8]; + * u32 active_time[8]; + * u32 pc_time; + * u32 lpi_time; + *@return SUCCESS (0) if Query is succssful + * FAILURE (Non-zero) if Query could not be processed. + * + */ + +int sysmon_stats_query_power_residency(enum dsp_id_t dsp_id, + struct sysmon_smem_power_stats *sysmon_power_stats); + +#endif