Adding a new CPU governor

Let’s suppose that we want to add the two governors Smartass and Interactive. Your first step is to locate the required source code for the same class of CPU.

Next, add the source code for the governor. Eg: drivers/cpufreq/cpufreq_interactive.c and drivers/cpufreq/cpufreq_smartass.c

Then add the choice for menuconfig to drivers/cpufreq/Kconfig:

config CPU_FREQ_DEFAULT_GOV_INTERACTIVE
bool "interactive"
select CPU_FREQ_GOV_INTERACTIVE
help
Use the CPUFreq governor 'interactive' as default. This allows
you to get a full dynamic cpu frequency capable system by simply
loading your cpufreq low-level hardware driver, using the
'interactive' governor for latency-sensitive workloads.[/code]

OR

config CPU_FREQ_DEFAULT_GOV_SMARTASS
bool "smartass"
select CPU_FREQ_GOV_SMARTASS
select CPU_FREQ_GOV_PERFORMANCE
help
Use the CPUFreq governor 'smartass' as default.[/code]

and
drivers/cpufreq/Kconfig

config CPU_FREQ_GOV_SMARTASS
tristate "'smartass' cpufreq governor"
depends on CPU_FREQ
help
smartass' - a "smart" optimized governor![/code]

OR

config CPU_FREQ_GOV_SMARTASS2
tristate "'smartass2' cpufreq policy governor"
help
'smartassV2' - a "smart" governor[/code]

 

If in doubt, say N.

Then, the rules to compile the source code, in Makefile

obj-$(CONFIG_CPU_FREQ_GOV_SMARTASS) += cpufreq_smartass.o[/code]

Then, the definitions in the header file include/linux/cpufreq.h

#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTASS)[/code]

extern struct cpufreq_governor cpufreq_gov_smartass;

#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_smartass)

 

After adding these, dont forget to enable them in CPU Power Management tab of menuconfig
While compiling, check whether the .o file for the particular freq is being made. Otherwise, it may mean you have forgotten to add the rules in the drivers/cpufreq/Kconfig file

Enabling HAVS:
Dont forget:
System type:
QSD Static Voltage Scaling
PMIC default output voltage
Enable Adaptive Voltage Scaling (AVS)

How does it work?

driver/cpufreq/Kconfig contains menuitems for adding to .config. Based on the selection of these items when menuconfig is done, at build it looks for these rules within the header files located in include/linux/cpufreq.h

include/linux/cpufreq.h

/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
*********************************************************************/

/*
Performance governor is fallback governor if any other gov failed to
auto load due latency restrictions
*/
#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
extern struct cpufreq_governor cpufreq_gov_performance;
#endif
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE)
extern struct cpufreq_governor cpufreq_gov_powersave;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND)
extern struct cpufreq_governor cpufreq_gov_ondemand;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE)
extern struct cpufreq_governor cpufreq_gov_interactive;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive)
#endif[/code]

drivers/cpufreq/Kconfig

config CPU_FREQ
bool "CPU Frequency scaling"
help
CPU Frequency scaling allows you to change the clock speed of
CPUs on the fly. This is a nice method to save power, because
the lower the CPU clock speed, the less power the CPU consumes.

Note that this driver doesn't automatically change the CPU
clock speed, you need to either enable a dynamic cpufreq governor
(see below) after boot, or use a userspace tool.

For details, take a look at .

If in doubt, say N.

if CPU_FREQ

config CPU_FREQ_TABLE
tristate

config CPU_FREQ_DEBUG
bool "Enable CPUfreq debugging"
help
Say Y here to enable CPUfreq subsystem (including drivers)
debugging. You will need to activate it via the kernel
command line by passing
cpufreq.debug=

To get , add
1 to activate CPUfreq core debugging,
2 to activate CPUfreq drivers debugging, and
4 to activate CPUfreq governor debugging

config CPU_FREQ_STAT
tristate "CPU frequency translation statistics"
select CPU_FREQ_TABLE
default y
help
This driver exports CPU frequency statistics information through sysfs
file system.

To compile this driver as a module, choose M here: the
module will be called cpufreq_stats.

If in doubt, say N.

config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details"
depends on CPU_FREQ_STAT
help
This will show detail CPU frequency translation table in sysfs file
system.

If in doubt, say N.

choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at
startup. If in doubt, select 'performance'.

config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
bool "performance"
select CPU_FREQ_GOV_PERFORMANCE
help
Use the CPUFreq governor 'performance' as default. This sets
the frequency statically to the highest frequency supported by
the CPU.

config CPU_FREQ_DEFAULT_GOV_POWERSAVE
bool "powersave"
depends on EMBEDDED
select CPU_FREQ_GOV_POWERSAVE
help
Use the CPUFreq governor 'powersave' as default. This sets
the frequency statically to the lowest frequency supported by
the CPU.

config CPU_FREQ_DEFAULT_GOV_USERSPACE
bool "userspace"
select CPU_FREQ_GOV_USERSPACE
help
Use the CPUFreq governor 'userspace' as default. This allows
you to set the CPU frequency manually or when a userspace
program shall be able to set the CPU dynamically without having
to enable the userspace governor manually.

config CPU_FREQ_DEFAULT_GOV_ONDEMAND
bool "ondemand"
select CPU_FREQ_GOV_ONDEMAND
select CPU_FREQ_GOV_PERFORMANCE
help
Use the CPUFreq governor 'ondemand' as default. This allows
you to get a full dynamic frequency capable system by simply
loading your cpufreq low-level hardware driver.
Be aware that not all cpufreq drivers support the ondemand
governor. If unsure have a look at the help section of the
driver. Fallback governor will be the performance governor.

config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
bool "conservative"
select CPU_FREQ_GOV_CONSERVATIVE
select CPU_FREQ_GOV_PERFORMANCE
help
Use the CPUFreq governor 'conservative' as default. This allows
you to get a full dynamic frequency capable system by simply
loading your cpufreq low-level hardware driver.
Be aware that not all cpufreq drivers support the conservative
governor. If unsure have a look at the help section of the
driver. Fallback governor will be the performance governor.

config CPU_FREQ_DEFAULT_GOV_INTERACTIVE
bool "interactive"
select CPU_FREQ_GOV_INTERACTIVE
help
Use the CPUFreq governor 'interactive' as default. This allows
you to get a full dynamic cpu frequency capable system by simply
loading your cpufreq low-level hardware driver, using the
'interactive' governor for latency-sensitive workloads.

config CPU_FREQ_DEFAULT_GOV_SMARTASS2
bool "smartass2"
select CPU_FREQ_GOV_SMARTASS2
help
Use the CPUFreq governor 'smartass2' as default. This allows
you to get a full dynamic cpu frequency capable system by simply
loading your cpufreq low-level hardware driver, using the
'interactive' governor for latency-sensitive workloads.

endchoice

config CPU_FREQ_GOV_PERFORMANCE
tristate "'performance' governor"
help
This cpufreq governor sets the frequency statically to the
highest available CPU frequency.

To compile this driver as a module, choose M here: the
module will be called cpufreq_performance.

If in doubt, say Y.

config CPU_FREQ_GOV_POWERSAVE
tristate "'powersave' governor"
help
This cpufreq governor sets the frequency statically to the
lowest available CPU frequency.

To compile this driver as a module, choose M here: the
module will be called cpufreq_powersave.

If in doubt, say Y.

config CPU_FREQ_GOV_USERSPACE
tristate "'userspace' governor for userspace frequency scaling"
help
Enable this cpufreq governor when you either want to set the
CPU frequency manually or when a userspace program shall
be able to set the CPU dynamically, like on LART
.

To compile this driver as a module, choose M here: the
module will be called cpufreq_userspace.

For details, take a look at .

If in doubt, say Y.

config CPU_FREQ_GOV_ONDEMAND
tristate "'ondemand' cpufreq policy governor"
select CPU_FREQ_TABLE
help
'ondemand' - This driver adds a dynamic cpufreq policy governor.
The governor does a periodic polling and
changes frequency based on the CPU utilization.
The support for this governor depends on CPU capability to
do fast frequency switching (i.e, very low latency frequency
transitions).

To compile this driver as a module, choose M here: the
module will be called cpufreq_ondemand.

For details, take a look at linux/Documentation/cpu-freq.

If in doubt, say N.

config CPU_FREQ_GOV_INTERACTIVE
tristate "'interactive' cpufreq policy governor"
help
'interactive' - This driver adds a dynamic cpufreq policy governor
designed for latency-sensitive workloads.

config CPU_FREQ_GOV_SMARTASS2
tristate "'smartass2' cpufreq policy governor"
help
'smartassV2' - a "smart" governor

config CPU_FREQ_GOV_CONSERVATIVE
tristate "'conservative' cpufreq governor"
depends on CPU_FREQ
help
'conservative' - this driver is rather similar to the 'ondemand'
governor both in its source code and its purpose, the difference is
its optimisation for better suitability in a battery powered
environment. The frequency is gracefully increased and decreased
rather than jumping to 100% when speed is required.

If you have a desktop machine then you should really be considering
the 'ondemand' governor instead, however if you are using a laptop,
PDA or even an AMD64 based computer (due to the unacceptable
step-by-step latency issues between the minimum and maximum frequency
transitions in the CPU) you will probably want to use this governor.

To compile this driver as a module, choose M here: the
module will be called cpufreq_conservative.

For details, take a look at linux/Documentation/cpu-freq.

If in doubt, say N.
config CPU_FREQ_MIN_TICKS
int "Ticks between governor polling interval."
default 10
help
Minimum number of ticks between polling interval for governors.

config CPU_FREQ_SAMPLING_LATENCY_MULTIPLIER
int "Sampling rate multiplier for governors."
default 1000
help
Sampling latency rate multiplied by the cpu switch latency.
Affects governor polling.

config CPU_FREQ_VDD_LEVELS
bool "CPU Vdd levels sysfs interface"
depends on CPU_FREQ_STAT
depends on ARCH_QSD8X50
default n
help
CPU Vdd levels sysfs interface

endif # CPU_FREQ[/code]

More notes:

/*
* Notes by Droidzone
*
* General format for adding governors
* -----------------------------------
*
* ifdef/elif Condition as per value in drivers/cpufreq/Kconfig
*
* CPUFREQ_DEFAULT_GOVERNOR is the variable pointing to the default governor
*
* Reads: if configured some governor as default, then define the governor
* by an object
*
* Thus: extern struc cpufreq_governor cpufreq_gov_interactive
* is pointed here.. the target is in cpufreq_interactive.c, the specific
* code in cpufreq/
*
* [extern struct cpufreq_governor] followed by the name as defined in its
* source code:
*
* Eg In cpufreq_smartass2.c is this:
* struct cpufreq_governor cpufreq_gov_smartass2 = {
. name = "smartassV2", *
.governor = cpufreq_governor_smartass,
*
*
*/
#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
extern struct cpufreq_governor cpufreq_gov_performance;
#endif
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE)
extern struct cpufreq_governor cpufreq_gov_powersave;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
extern struct cpufreq_governor cpufreq_gov_userspace;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND)
extern struct cpufreq_governor cpufreq_gov_ondemand;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE)
extern struct cpufreq_governor cpufreq_gov_interactive;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive)
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTASS2)
extern struct cpufreq_governor cpufreq_gov_smartass2;
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_smartass2)
#endif[/code]

Joel G Mathew

Joel G Mathew, known in tech circles by the pseudonym Droidzone, is an Android and Linux enthusiast. His favorite pastime is grappling with GNU compilers, discovering newer Linux secrets, writing scripts, hacking roms, and programs (nothing illegal), reading, blogging. and testing out the latest gadgets. When away from the tech world, Joel is a practising ENT Surgeon.

1 Reply to “Adding a new CPU governor”

Comments are closed.