Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions arch/arm64/boot/dts/qcom/hamoa.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@
reg = <0x13>;
#power-domain-cells = <1>;
};

scmi_vendor: protocol@80 {
reg = <0x80>;
};
};
};

Expand Down
4 changes: 4 additions & 0 deletions arch/arm64/configs/qcom.config
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ CONFIG_POWERCAP=y
CONFIG_PROC_EVENTS=y
CONFIG_QCA808X_PHY=m
CONFIG_QCOM_QMI_COOLING=y
CONFIG_QCOM_SCMI_GENERIC_EXT=y
CONFIG_REMOTEPROC_THERMAL=y
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
Expand Down Expand Up @@ -109,6 +110,9 @@ CONFIG_SCSI_AACRAID=m
CONFIG_SCSI_SMARTPQI=m
# Support performance profiling
CONFIG_FTRACE=y
# QCOM SCMI memlat bus scaling
CONFIG_DEVFREQ_GOV_REMOTE=y
CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ=m
# Kubernetes support
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_FAVOR_DYNMODS=y
Expand Down
21 changes: 21 additions & 0 deletions drivers/devfreq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ config DEVFREQ_GOV_POWERSAVE
the DEVFREQ framework returns the lowest frequency available
at any time.

config DEVFREQ_GOV_REMOTE
tristate "Remote"
help
A simple governor to track the frequency of devices whose
dvfs control lies outside the kernel. This governor acts
as an observer and provides for ways to track frequency and
set/get information related to the remote dvfs device.

config DEVFREQ_GOV_USERSPACE
tristate "Userspace"
help
Expand Down Expand Up @@ -161,6 +169,19 @@ config ARM_SUN8I_A33_MBUS_DEVFREQ
This adds the DEVFREQ driver for the MBUS controller in some
Allwinner sun8i (A33 through H3) and sun50i (A64 and H5) SoCs.

config SCMI_QCOM_MEMLAT_DEVFREQ
tristate "Qualcomm Technologies Inc. SCMI client driver"
depends on QCOM_SCMI_GENERIC_EXT || COMPILE_TEST
select DEVFREQ_GOV_REMOTE
help
This driver uses the MEMLAT (memory latency) algorithm string
hosted on QCOM SCMI Vendor Protocol to detect memory latency
workloads and control frequency/level of the various memory
buses (DDR/LLCC/DDR_QOS).

This driver defines/documents the parameter IDs used while configuring
the memory buses.

source "drivers/devfreq/event/Kconfig"

endif # PM_DEVFREQ
2 changes: 2 additions & 0 deletions drivers/devfreq/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ obj-$(CONFIG_PM_DEVFREQ_EVENT) += devfreq-event.o
obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o
obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o
obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o
obj-$(CONFIG_DEVFREQ_GOV_REMOTE) += governor_remote.o
obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o

Expand All @@ -16,6 +17,7 @@ obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o
obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
obj-$(CONFIG_SCMI_QCOM_MEMLAT_DEVFREQ) += scmi-qcom-memlat-devfreq.o

# DEVFREQ Event Drivers
obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
11 changes: 10 additions & 1 deletion drivers/devfreq/devfreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/stat.h>
#include <linux/pm_opp.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/list.h>
Expand All @@ -28,7 +29,6 @@
#include <linux/of.h>
#include <linux/pm_qos.h>
#include <linux/units.h>
#include "governor.h"

#define CREATE_TRACE_POINTS
#include <trace/events/devfreq.h>
Expand Down Expand Up @@ -348,6 +348,10 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
unsigned long cur_freq;
int err = 0;

/* Frequency already updated, update trans-stat info */
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, TRACK_REMOTE))
goto update_status;

if (devfreq->profile->get_cur_freq)
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
else
Expand Down Expand Up @@ -375,6 +379,7 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
freqs.new = new_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);

update_status:
if (devfreq_update_status(devfreq, new_freq))
dev_warn(&devfreq->dev,
"Couldn't update frequency transition information.\n");
Expand Down Expand Up @@ -1568,6 +1573,10 @@ static ssize_t target_freq_show(struct device *dev,
{
struct devfreq *df = to_devfreq(dev);

if (!df->profile || !df->governor ||
!IS_SUPPORTED_ATTR(df->governor->attrs, TARGET_FREQ))
return -EINVAL;

return sprintf(buf, "%lu\n", df->previous_freq);
}
static DEVICE_ATTR_RO(target_freq);
Expand Down
28 changes: 27 additions & 1 deletion drivers/devfreq/governor_passive.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,33 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/units.h>
#include "governor.h"

/**
* struct devfreq_cpu_data - Hold the per-cpu data
* @node: list node
* @dev: reference to cpu device.
* @first_cpu: the cpumask of the first cpu of a policy.
* @opp_table: reference to cpu opp table.
* @cur_freq: the current frequency of the cpu.
* @min_freq: the min frequency of the cpu.
* @max_freq: the max frequency of the cpu.
*
* This structure stores the required cpu_data of a cpu.
* This is auto-populated by the governor.
*/
struct devfreq_cpu_data {
struct list_head node;

struct device *dev;
unsigned int first_cpu;

struct opp_table *opp_table;
unsigned int cur_freq;
unsigned int min_freq;
unsigned int max_freq;
};

static struct devfreq_cpu_data *
get_parent_cpu_data(struct devfreq_passive_data *p_data,
Expand Down Expand Up @@ -424,6 +449,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,

static struct devfreq_governor devfreq_passive = {
.name = DEVFREQ_GOV_PASSIVE,
.attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ,
.flags = DEVFREQ_GOV_FLAG_IMMUTABLE,
.get_target_freq = devfreq_passive_get_target_freq,
.event_handler = devfreq_passive_event_handler,
Expand Down
3 changes: 2 additions & 1 deletion drivers/devfreq/governor_performance.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/

#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/module.h>
#include "governor.h"

static int devfreq_performance_func(struct devfreq *df,
unsigned long *freq)
Expand Down Expand Up @@ -37,6 +37,7 @@ static int devfreq_performance_handler(struct devfreq *devfreq,

static struct devfreq_governor devfreq_performance = {
.name = DEVFREQ_GOV_PERFORMANCE,
.attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ,
.get_target_freq = devfreq_performance_func,
.event_handler = devfreq_performance_handler,
};
Expand Down
3 changes: 2 additions & 1 deletion drivers/devfreq/governor_powersave.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/

#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/module.h>
#include "governor.h"

static int devfreq_powersave_func(struct devfreq *df,
unsigned long *freq)
Expand Down Expand Up @@ -37,6 +37,7 @@ static int devfreq_powersave_handler(struct devfreq *devfreq,

static struct devfreq_governor devfreq_powersave = {
.name = DEVFREQ_GOV_POWERSAVE,
.attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ,
.get_target_freq = devfreq_powersave_func,
.event_handler = devfreq_powersave_handler,
};
Expand Down
80 changes: 80 additions & 0 deletions drivers/devfreq/governor_remote.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved.
*/

#include <linux/errno.h>
#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>

static int devfreq_remote_track_func(struct devfreq *devfreq, unsigned long *freq)
{
unsigned long cur_freq = 0;

if (devfreq->profile->get_cur_freq)
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);

*freq = cur_freq;

return 0;
}

static int devfreq_remote_track_handler(struct devfreq *devfreq, unsigned int event, void *data)
{
switch (event) {
case DEVFREQ_GOV_START:
devfreq_monitor_start(devfreq);
break;

case DEVFREQ_GOV_STOP:
devfreq_monitor_stop(devfreq);
break;

case DEVFREQ_GOV_UPDATE_INTERVAL:
devfreq_update_interval(devfreq, (unsigned int *)data);
break;

case DEVFREQ_GOV_SUSPEND:
devfreq_monitor_suspend(devfreq);
break;

case DEVFREQ_GOV_RESUME:
devfreq_monitor_resume(devfreq);
break;

default:
break;
}

return 0;
}

static struct devfreq_governor devfreq_remote_track = {
.name = DEVFREQ_GOV_REMOTE,
.attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL
| DEVFREQ_GOV_ATTR_TIMER,
.flags = DEVFREQ_GOV_FLAG_IMMUTABLE
| DEVFREQ_GOV_FLAG_TRACK_REMOTE,
.get_target_freq = devfreq_remote_track_func,
.event_handler = devfreq_remote_track_handler,
};

static int __init devfreq_remote_track_init(void)
{
return devfreq_add_governor(&devfreq_remote_track);
}
subsys_initcall(devfreq_remote_track_init);

static void __exit devfreq_remote_track_exit(void)
{
int ret;

ret = devfreq_remove_governor(&devfreq_remote_track);
if (ret)
pr_err("%s: failed remove governor %d\n", __func__, ret);
}
module_exit(devfreq_remote_track_exit);

MODULE_DESCRIPTION("DEVFREQ Remote Tracking governor");
MODULE_LICENSE("GPL");
3 changes: 2 additions & 1 deletion drivers/devfreq/governor_simpleondemand.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/math64.h>
#include "governor.h"

/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
#define DFSO_UPTHRESHOLD (90)
Expand Down Expand Up @@ -118,6 +118,7 @@ static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
static struct devfreq_governor devfreq_simple_ondemand = {
.name = DEVFREQ_GOV_SIMPLE_ONDEMAND,
.attrs = DEVFREQ_GOV_ATTR_POLLING_INTERVAL
| DEVFREQ_GOV_ATTR_TARGET_FREQ
| DEVFREQ_GOV_ATTR_TIMER,
.get_target_freq = devfreq_simple_ondemand_func,
.event_handler = devfreq_simple_ondemand_handler,
Expand Down
3 changes: 2 additions & 1 deletion drivers/devfreq/governor_userspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/kstrtox.h>
#include <linux/pm.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include "governor.h"

struct userspace_data {
unsigned long user_frequency;
Expand Down Expand Up @@ -136,6 +136,7 @@ static int devfreq_userspace_handler(struct devfreq *devfreq,

static struct devfreq_governor devfreq_userspace = {
.name = DEVFREQ_GOV_USERSPACE,
.attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ,
.get_target_freq = devfreq_userspace_func,
.event_handler = devfreq_userspace_handler,
};
Expand Down
4 changes: 2 additions & 2 deletions drivers/devfreq/hisi_uncore_freq.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/devfreq.h>
#include <linux/devfreq-governor.h>
#include <linux/device.h>
#include <linux/dev_printk.h>
#include <linux/errno.h>
Expand All @@ -26,8 +27,6 @@
#include <linux/units.h>
#include <acpi/pcc.h>

#include "governor.h"

struct hisi_uncore_pcc_data {
u16 status;
u16 resv;
Expand Down Expand Up @@ -400,6 +399,7 @@ static struct devfreq_governor hisi_platform_governor = {
* Set interrupt_driven to skip the devfreq monitor mechanism, though
* this governor is not interrupt-driven.
*/
.attrs = DEVFREQ_GOV_ATTR_TARGET_FREQ,
.flags = DEVFREQ_GOV_FLAG_IRQ_DRIVEN,
.get_target_freq = hisi_platform_gov_func,
.event_handler = hisi_platform_gov_handler,
Expand Down
Loading