Loading drivers/devfreq/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,15 @@ config DEVFREQ_GOV_MEMLAT this uses target specific counters it can conflict with existing profiling tools. config DEVFREQ_GOV_CDSPL3 tristate "QTI DEVFREQ governor for CDSP L3 requests" depends on QCOM_CDSP_RM help CDSP resource manager will use this governor to vote for L3 clock for IO-coherent traffic generated from CDSP. The driver implements a callback routine for CDSP resource manager to register a CPU L3 clock frequency level. comment "DEVFREQ Drivers" config DEVFREQ_GOV_QCOM_ADRENO_TZ Loading drivers/devfreq/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ obj-$(CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON) += governor_cache_hwmon.o obj-$(CONFIG_DEVFREQ_GOV_MEMLAT) += governor_memlat.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ) += governor_msm_adreno_tz.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON) += governor_bw_vbif.o obj-$(CONFIG_DEVFREQ_GOV_CDSPL3) += governor_cdsp_l3.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o Loading drivers/devfreq/governor_cdsp_l3.c 0 → 100644 +157 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "governor_cdspl3: " fmt #include <linux/types.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> #include <linux/err.h> #include <linux/devfreq.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/soc/qcom/cdsprm.h> #include "governor.h" struct cdspl3 { struct device_node *of_node; struct devfreq *df; unsigned int l3_freq_hz; }; static struct cdspl3 p_me; static int cdsp_l3_request_callback(unsigned int freq_khz) { if (p_me.df) { mutex_lock(&p_me.df->lock); p_me.l3_freq_hz = freq_khz * 1000; update_devfreq(p_me.df); mutex_unlock(&p_me.df->lock); } else { pr_err("CDSP L3 request for %dKHz not served\n", freq_khz); return -ENODEV; } return 0; } static struct cdsprm_l3 cdsprm = { .set_l3_freq = cdsp_l3_request_callback, }; static int devfreq_get_target_freq(struct devfreq *df, unsigned long *freq) { if (freq) *freq = (unsigned long)p_me.l3_freq_hz; return 0; } static int gov_start(struct devfreq *df) { if (p_me.of_node != df->dev.parent->of_node) { dev_err(df->dev.parent, "Device match error in CDSP L3 frequency governor\n"); return -ENODEV; } p_me.df = df; p_me.l3_freq_hz = 0; /* * Send governor start message to CDSP RM driver */ cdsprm_register_cdspl3gov(&cdsprm); return 0; } static int gov_stop(struct devfreq *df) { p_me.df = 0; p_me.l3_freq_hz = 0; /* * Send governor stop message to CDSP RM driver */ cdsprm_unregister_cdspl3gov(); return 0; } static int devfreq_event_handler(struct devfreq *df, unsigned int event, void *data) { int ret; switch (event) { case DEVFREQ_GOV_START: ret = gov_start(df); if (ret) return ret; dev_info(df->dev.parent, "Successfully started CDSP L3 governor\n"); break; case DEVFREQ_GOV_STOP: dev_info(df->dev.parent, "Received stop CDSP L3 governor event\n"); ret = gov_stop(df); if (ret) return ret; break; default: break; } return 0; } static struct devfreq_governor cdsp_l3_gov = { .name = "cdspl3", .get_target_freq = devfreq_get_target_freq, .event_handler = devfreq_event_handler, }; static int cdsp_l3_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int ret; p_me.of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); if (!p_me.of_node) { dev_err(dev, "Couldn't find a target device\n"); return -ENODEV; } ret = devfreq_add_governor(&cdsp_l3_gov); if (ret) dev_err(dev, "Failed registering CDSP L3 requests %d\n", ret); return ret; } static const struct of_device_id cdsp_l3_match_table[] = { { .compatible = "qcom,cdsp-l3" }, {} }; static struct platform_driver cdsp_l3 = { .probe = cdsp_l3_driver_probe, .driver = { .name = "cdsp-l3", .of_match_table = cdsp_l3_match_table, } }; static int __init cdsp_l3_gov_module_init(void) { return platform_driver_register(&cdsp_l3); } module_init(cdsp_l3_gov_module_init); static void __exit cdsp_l3_gov_module_exit(void) { devfreq_remove_governor(&cdsp_l3_gov); platform_driver_unregister(&cdsp_l3); } module_exit(cdsp_l3_gov_module_exit); MODULE_LICENSE("GPL v2"); drivers/soc/qcom/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -736,6 +736,17 @@ config QMP_DEBUGFS_CLIENT help This options enables a driver which allows clients to send messages to Alway On processor using QMP transport. config QCOM_CDSP_RM bool "CDSP request manager" depends on QCOM_GLINK help This driver serves CDSP requests for CPU L3 clock and CPU QoS thus improving CDSP performance. Using this driver, CDSP can set appropriate CPU L3 clock for improving IO-Coherent throughput and opt for QoS mode to improve RPC latency. The driver also registers cooling devices for CDSP subsystem and implements Cx ipeak limit management. endmenu config QCOM_HYP_CORE_CTL Loading drivers/soc/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -81,3 +81,4 @@ obj-$(CONFIG_QCOM_MEM_OFFLINE) += mem-offline.o obj-$(CONFIG_QMP_DEBUGFS_CLIENT) += qmp-debugfs-client.o obj-$(CONFIG_QCOM_HYP_CORE_CTL) += hyp_core_ctl.o obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o obj-$(CONFIG_QCOM_CDSP_RM) += cdsprm.o Loading
drivers/devfreq/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,15 @@ config DEVFREQ_GOV_MEMLAT this uses target specific counters it can conflict with existing profiling tools. config DEVFREQ_GOV_CDSPL3 tristate "QTI DEVFREQ governor for CDSP L3 requests" depends on QCOM_CDSP_RM help CDSP resource manager will use this governor to vote for L3 clock for IO-coherent traffic generated from CDSP. The driver implements a callback routine for CDSP resource manager to register a CPU L3 clock frequency level. comment "DEVFREQ Drivers" config DEVFREQ_GOV_QCOM_ADRENO_TZ Loading
drivers/devfreq/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ obj-$(CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON) += governor_cache_hwmon.o obj-$(CONFIG_DEVFREQ_GOV_MEMLAT) += governor_memlat.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ) += governor_msm_adreno_tz.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON) += governor_bw_vbif.o obj-$(CONFIG_DEVFREQ_GOV_CDSPL3) += governor_cdsp_l3.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o Loading
drivers/devfreq/governor_cdsp_l3.c 0 → 100644 +157 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "governor_cdspl3: " fmt #include <linux/types.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> #include <linux/err.h> #include <linux/devfreq.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/soc/qcom/cdsprm.h> #include "governor.h" struct cdspl3 { struct device_node *of_node; struct devfreq *df; unsigned int l3_freq_hz; }; static struct cdspl3 p_me; static int cdsp_l3_request_callback(unsigned int freq_khz) { if (p_me.df) { mutex_lock(&p_me.df->lock); p_me.l3_freq_hz = freq_khz * 1000; update_devfreq(p_me.df); mutex_unlock(&p_me.df->lock); } else { pr_err("CDSP L3 request for %dKHz not served\n", freq_khz); return -ENODEV; } return 0; } static struct cdsprm_l3 cdsprm = { .set_l3_freq = cdsp_l3_request_callback, }; static int devfreq_get_target_freq(struct devfreq *df, unsigned long *freq) { if (freq) *freq = (unsigned long)p_me.l3_freq_hz; return 0; } static int gov_start(struct devfreq *df) { if (p_me.of_node != df->dev.parent->of_node) { dev_err(df->dev.parent, "Device match error in CDSP L3 frequency governor\n"); return -ENODEV; } p_me.df = df; p_me.l3_freq_hz = 0; /* * Send governor start message to CDSP RM driver */ cdsprm_register_cdspl3gov(&cdsprm); return 0; } static int gov_stop(struct devfreq *df) { p_me.df = 0; p_me.l3_freq_hz = 0; /* * Send governor stop message to CDSP RM driver */ cdsprm_unregister_cdspl3gov(); return 0; } static int devfreq_event_handler(struct devfreq *df, unsigned int event, void *data) { int ret; switch (event) { case DEVFREQ_GOV_START: ret = gov_start(df); if (ret) return ret; dev_info(df->dev.parent, "Successfully started CDSP L3 governor\n"); break; case DEVFREQ_GOV_STOP: dev_info(df->dev.parent, "Received stop CDSP L3 governor event\n"); ret = gov_stop(df); if (ret) return ret; break; default: break; } return 0; } static struct devfreq_governor cdsp_l3_gov = { .name = "cdspl3", .get_target_freq = devfreq_get_target_freq, .event_handler = devfreq_event_handler, }; static int cdsp_l3_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int ret; p_me.of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); if (!p_me.of_node) { dev_err(dev, "Couldn't find a target device\n"); return -ENODEV; } ret = devfreq_add_governor(&cdsp_l3_gov); if (ret) dev_err(dev, "Failed registering CDSP L3 requests %d\n", ret); return ret; } static const struct of_device_id cdsp_l3_match_table[] = { { .compatible = "qcom,cdsp-l3" }, {} }; static struct platform_driver cdsp_l3 = { .probe = cdsp_l3_driver_probe, .driver = { .name = "cdsp-l3", .of_match_table = cdsp_l3_match_table, } }; static int __init cdsp_l3_gov_module_init(void) { return platform_driver_register(&cdsp_l3); } module_init(cdsp_l3_gov_module_init); static void __exit cdsp_l3_gov_module_exit(void) { devfreq_remove_governor(&cdsp_l3_gov); platform_driver_unregister(&cdsp_l3); } module_exit(cdsp_l3_gov_module_exit); MODULE_LICENSE("GPL v2");
drivers/soc/qcom/Kconfig +11 −0 Original line number Diff line number Diff line Loading @@ -736,6 +736,17 @@ config QMP_DEBUGFS_CLIENT help This options enables a driver which allows clients to send messages to Alway On processor using QMP transport. config QCOM_CDSP_RM bool "CDSP request manager" depends on QCOM_GLINK help This driver serves CDSP requests for CPU L3 clock and CPU QoS thus improving CDSP performance. Using this driver, CDSP can set appropriate CPU L3 clock for improving IO-Coherent throughput and opt for QoS mode to improve RPC latency. The driver also registers cooling devices for CDSP subsystem and implements Cx ipeak limit management. endmenu config QCOM_HYP_CORE_CTL Loading
drivers/soc/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -81,3 +81,4 @@ obj-$(CONFIG_QCOM_MEM_OFFLINE) += mem-offline.o obj-$(CONFIG_QMP_DEBUGFS_CLIENT) += qmp-debugfs-client.o obj-$(CONFIG_QCOM_HYP_CORE_CTL) += hyp_core_ctl.o obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o obj-$(CONFIG_QCOM_CDSP_RM) += cdsprm.o