RFC on cpufreq implementation
Hello,
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669
As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
Regards.
/*
* Copyright 2014 Sigma Designs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <mach/tango4_gbus.h> /* gbus_read, gbus_write */ #include "temp.h"
MODULE_LICENSE("GPL");MODULE_AUTHOR("Sigma Designs"); MODULE_DESCRIPTION("cpufreq driver for Tangox 87xx");
static struct cpufreq_frequency_table freq_table[] = {
{ .driver_data = 1 },
{ .driver_data = 2 },
{ .driver_data = 3 },
{ .driver_data = 9 },
{ .frequency = CPUFREQ_TABLE_END },
};static unsigned int tangox_get_freq(unsigned int cpu)
{
union SYS_clkgen_pll pll;
union SYS_clk_div_ctrl div;
pll.val = gbus_read_reg32(SYS_clkgen0_pll);
if (pll.f.Isel != 1 || pll.f.M != 0)
return 0;
div.val = gbus_read_reg32(SYS_cpuclk_div_ctrl);
if (div.f.BP != 0 || div.f.F != 0)
return 0;
return TANGOX_XTAL_FREQ * (pll.f.N + 1) / div.f.I >> pll.f.K;
}static int tangox_target(struct cpufreq_policy *policy, unsigned int index)
{
while (gbus_read_reg32(SYS_cpuclk_div_ctrl) >> 31)
cpu_relax();
gbus_write_reg32(SYS_cpuclk_div_ctrl, freq_table[index].driver_data);
return 0;
}static int tangox_cpu_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *p;
unsigned int freq = tangox_get_freq(0);
unsigned int transition_latency_ns = freq / SYS_FAST_RAMP_SPEED;
for (p = freq_table; p->frequency != CPUFREQ_TABLE_END; ++p) {
unsigned int I = p->driver_data;
union SYS_clk_div_ctrl div = SYS_CLK_DIV_CTRL(I);
p->driver_data = div.val;
p->frequency = freq / I;
}
return cpufreq_generic_init(policy, freq_table, transition_latency_ns);
}static struct cpufreq_driver tangox_cpufreq_driver = {
.name = "tangox-cpufreq",
.init = tangox_cpu_init,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = tangox_target,
.get = tangox_get_freq,
.exit = cpufreq_generic_exit,
.attr = cpufreq_generic_attr,
};
static int __init tangox_cpufreq_init(void)
{
return cpufreq_register_driver(&tangox_cpufreq_driver);
}static void __exit tangox_cpufreq_exit(void)
{
cpufreq_unregister_driver(&tangox_cpufreq_driver);
}module_init(tangox_cpufreq_init);module_exit(tangox_cpufreq_exit);
#define SYS_clkgen0_pll 0x10000
#define SYS_cpuclk_div_ctrl 0x10024
#define TANGOX_XTAL_FREQ 27000
#define REG(name, ...) union name { struct { u32 __VA_ARGS__; } f; u32 val; }
REG(SYS_clkgen_pll, N:7, :6, K:3, M:3, :5, Isel:3, :3, T:1, B:1); REG(SYS_clk_div_ctrl, F:4, :4, I:8, :4, RS:1, RE:2, BP:1, :7, BZ:1);
#define SYS_FAST_RAMP 1
#define SYS_FAST_RAMP_SPEED 15 /* in kHz per nanosecond */ #define SYS_CLK_DIV_CTRL(DI) {{ .I = DI, .RE = SYS_FAST_RAMP }}
Quoted 16 lines · Mason
Hello,
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
Quoted 5 lines
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
The clock framework generalizes clocks, not cpufreq. Ideally you should use clock framework in cpufreq driver. So instead manually setting divider just do something like:
ret = clk_set_rate(cpu_clk, freq_exact);
if (ret) {
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
return ret;
}For voltage scaling you should use regulator framework.
Actually I think existing cpufreq-dt could serve your purpose. Why don't you try it? Or look at it and use as an example.
Quoted 2 lines
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
cpuidle and cpufreq are different subsystems. They don't interact, yet. There are efforts to combine scheduler, cpufreq and cpuidle but this is future. If your SoC has some deeper low power states than developing cpuidle driver makes sense. If not - WFI will be used.
Quoted 2 lines
Regards.
Quoted 10 lines · Krzysztof Kozlowski
Quoted 8 lines · Mason
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
Quoted 5 lines
Quoted 5 lines
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
I'll take a closer look at other drivers, but I'd like to hear opinions on the subject.
Quoted 10 lines
Quoted 5 lines
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
The clock framework generalizes clocks, not cpufreq. Ideally you should use clock framework in cpufreq driver. So instead manually setting divider just do something like:
Quoted 5 lines
ret =
clk_set_rate(cpu_clk, freq_exact);if (ret) { dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); return ret; }
I will give clk a closer look.
Quoted 1 line
For voltage scaling you should use regulator framework.
OK. I'm also interested in frequency-throttling when temperatures rise beyond specific thresholds. What subsystem ties sensors and cpufreq together?
Quoted 2 lines
Actually I think existing cpufreq-dt could serve your purpose. Why don't you try it? Or look at it and use as an example.
Will do. I've heard of device tree, but know nothing about it.
Quoted 7 lines
Quoted 2 lines
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
cpuidle and cpufreq are different subsystems. They don't interact, yet. There are efforts to combine scheduler, cpufreq and cpuidle but this is future. If your SoC has some deeper low power states than developing cpuidle driver makes sense. If not - WFI will be used.
AFAIU, there are no deeper power states on the Cortex-A9.
I didn't find where WFI is called :-(
In kernel/cpu/idle.c (file seems to have been removed in 3.15) cpu_idle_loop() calls arch_cpu_idle()
http://lxr.free-electrons.com/source/kernel/cpu/idle.c?v=3.14#L98
In arch/kernel/process.c
http://lxr.free-electrons.com/source/arch/arm/kernel/process.c?v=3.14#L173
/*
* Called from the core idle loop.
*/
void arch_cpu_idle(void)
{
if (cpuidle_idle_call())
default_idle();
}default_idle calls cpu_do_idle (by default), a macro for cpu_v7_do_idle which executes dsb+wfi, BUT...
ifndef CONFIG_CPU_IDLE then
static inline int cpuidle_idle_call(void) { return -ENODEV; }
Does that mean I MUST define CONFIG_CPU_IDLE if I want the idle loop to call wfi (to save power), even if I don't have a cpuidle driver?
Regards.
Quoted 37 lines · Mason
Quoted 10 lines · Krzysztof Kozlowski
Quoted 8 lines · Mason
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
Quoted 5 lines
Quoted 5 lines
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
I'll take a closer look at other drivers, but I'd like to hear opinions on the subject.
Quoted 10 lines
Quoted 5 lines
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
The clock framework generalizes clocks, not cpufreq. Ideally you should use clock framework in cpufreq driver. So instead manually setting divider just do something like:
Quoted 5 lines
ret =
clk_set_rate(cpu_clk, freq_exact);if (ret) { dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); return ret; }
Quoted 7 lines
I will give clk a closer look.
Quoted 1 line
For voltage scaling you should use regulator framework.
OK. I'm also interested in frequency-throttling when temperatures rise beyond specific thresholds. What subsystem ties sensors and cpufreq together?
I believe thermal.
Quoted 5 lines
Quoted 3 lines
Actually I think existing cpufreq-dt could serve your purpose. Why don't you try it? Or look at it and use as an example.
Will do. I've heard of device tree, but know nothing about it.
Indeed it is driver meant to be used with Device Tree but beside DT code it nicely shows how to scale the frequency CPU. If you don't use DT then you can use only the set_target() as starting point.
On 3.14 the "cpufreq-dt" could be called "cpufreq-cpu0".
Quoted 31 lines
Quoted 8 lines
Quoted 3 lines
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
cpuidle and cpufreq are different subsystems. They don't interact, yet. There are efforts to combine scheduler, cpufreq and cpuidle but this is future. If your SoC has some deeper low power states than developing cpuidle driver makes sense. If not - WFI will be used.
AFAIU, there are no deeper power states on the Cortex-A9.
I didn't find where WFI is called :-(
In
kernel/cpu/idle.c(file seems to have been removed in 3.15)cpu_idle_loop()callsarch_cpu_idle()
http://lxr.free-electrons.com/source/kernel/cpu/idle.c?v=3.14#L98In
arch/kernel/process.c
http://lxr.free-electrons.com/source/arch/arm/kernel/process.c?v=3.14#L173
/*
* Called from the core idle loop.
*/
voidarch_cpu_idle(void){ if (cpuidle_idle_call()) default_idle(); }
default_idlecallscpu_do_idle(by default), a macro forcpu_v7_do_idlewhich executes dsb+wfi, BUT...
Quoted 6 lines
ifndef
CONFIG_CPU_IDLEthen
static inline intcpuidle_idle_call(void){ return-ENODEV; }Does that mean I MUST define
CONFIG_CPU_IDLEif I want the idle loop to call wfi (to save power), even if I don't have a cpuidle driver?
On current kernels you don't have to. But on 3.14... seems yes.
Best regards,
Krzysztof
Quoted 2 lines
Regards.
Hi Mason,
On Fri, Jan 16, 2015 at 11:10:23AM +0000, Mason wrote:
[...]
Quoted 3 lines
OK. I'm also interested in frequency-throttling when temperatures rise beyond specific thresholds. What subsystem ties sensors and cpufreq together?
The thermal framework. Have a look atDocumentation/thermal/sysfs-api.txt andDocumentation/thermal/cpu-cooling-api.txt
Cheers,
Javi
Quoted 20 lines · Mason
I didn't find where WFI is called :-(
In
kernel/cpu/idle.c(file seems to have been removed in 3.15)cpu_idle_loop()callsarch_cpu_idle()
http://lxr.free-electrons.com/source/kernel/cpu/idle.c?v=3.14#L98In
arch/kernel/process.c
http://lxr.free-electrons.com/source/arch/arm/kernel/process.c?v=3.14#L173
/*
* Called from the core idle loop.
*/
voidarch_cpu_idle(void){ if (cpuidle_idle_call()) default_idle(); }
default_idlecallscpu_do_idle(by default), a macro forcpu_v7_do_idlewhich executes dsb+wfi, BUT...
Quoted 6 lines
ifndef
CONFIG_CPU_IDLEthen
static inline intcpuidle_idle_call(void){ return-ENODEV; }Does that mean I MUST define
CONFIG_CPU_IDLEif I want the idle loop to call wfi (to save power), even if I don't have a cpuidle driver?
For the record, I read the code wrong.
cpuidle_idle_call() always returns -ENODEV, so the test "if (cpuidle_idle_call())" is always true, and we always call default_idle() and everything works as expected.
Sorry for the noise.
Quoted 5 lines · Mason
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
Following patch solved this issue in 3.17..
6393d6a1027e cpufreq: ondemand: Eliminate the deadband effect
Quoted 10 lines · Viresh Kumar
Quoted 5 lines · Mason
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
Following patch solved this issue in 3.17..
6393d6a1027ecpufreq: ondemand: Eliminate the deadband effect
Good to know, thanks! (I'm on 3.14)
Do you have other comments/suggestions regarding my code?
Regards.
Quoted 5 lines · Mason
Good to know, thanks! (I'm on 3.14)
Do you have other comments/suggestions regarding my code?
No. It looked fine on the first look..
Quoted 10 lines · Mason
Hello,
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
Quoted 5 lines
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
How many states are really enough depends on the main workloads running on your system. In a closed system (limited number of applications) you can easily characterise your workloads and see what operating points (OPP = voltage, frequency pair) the system spends most of its time in (CPU_FREQ_STAT_DETAILS) and optimize out the remaining OPPs.
In an open-ended system where you don't control what applications will run on the system (e.g. android phone), it is probably a good idea to expose more OPPs while keeping in mind that exposing 50 frequencies is probably overkill (and silly) since you're spending more time reaching the "optimum" OPP. Pick some high-impact ones e.g. ones that allow you to lower your voltage.
Quoted 8 lines
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
These queries have been answered by Krzysztof.
Quoted 16 lines · Amit Kucheria
Quoted 8 lines · Mason
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669As I originally wrote, I'm running 3.14 on an ARM Cortex-A9 based SoC (namely Tango4 from Sigma Designs). I'd like to get some feedback on the cpufreq driver I wrote for that platform.
Quoted 5 lines
I decided to expose only a small subset of frequencies (namely {999,500,333,111} MHz) because, in my tests, the ondemand gov chose mostly min and max, and the intermediate frequencies not so much; so I figured "2 intermediate freqs" is good enough. (I'm ready to hear otherwise.)
Quoted 6 lines
How many states are really enough depends on the main workloads running on your system. In a closed system (limited number of applications) you can easily characterise your workloads and see what operating points (OPP = voltage, frequency pair) the system spends most of its time in (
CPU_FREQ_STAT_DETAILS) and optimize out the remaining OPPs.
Testing with CPU_FREQ_STAT_DETAILS enabled is on my TODO list. Thanks for reminding me!
Quoted 6 lines
In an open-ended system where you don't control what applications will run on the system (e.g. android phone), it is probably a good idea to expose more OPPs while keeping in mind that exposing 50 frequencies is probably overkill (and silly) since you're spending more time reaching the "optimum" OPP. Pick some high-impact ones e.g. ones that allow you to lower your voltage.
The current SoC does not support dynamic voltage scaling at all. So I'm just tweaking the frequency. IIUC, if I divide freq by 4, power should be divided by 4?
Quoted 10 lines
Quoted 8 lines
I tried to use as much generic framework as possible, but I've read about the clk framework, and it looks to be an even greater generalization. Are new platforms encouraged to use that, rather than provide a cpufreq driver? Does it work when voltage scaling comes in play? (This SoC doesn't have it, but the next will.)
I'm also wondering how cpufreq and cpuidle interact? Is one a subset of the other? Are they orthogonal?
These queries have been answered by Krzysztof.
The current SoC does not support any "deep" sleep; I was told that the core just powers "itself" down after a WFI, nothing fancier.
Regards.
Quoted 3 lines · Mason
This is a follow-up to my previous thread.
"How many frequencies would cpufreq optimally like to manage?"
http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669
OK, so this is my TAKE 2 on the cpufreq driver, trying to remove some dependencies on machine-specific definitions by getting the virtual address at init via ioremap. (Is -EFAULT the right error to return if ioremap fails?)
I'm not sure where machine-specific information is supposed to be stored though? Such as register definitions, or the physical addresses/offsets. What if they need to be shared among several source files? I can't just duplicate them... (I've tentatively called it temp.h for the time being.)
Regards.
/*
* Copyright 2015 Sigma Designs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <linux/io.h>
#include "temp.h"
MODULE_LICENSE("GPL");MODULE_AUTHOR("Sigma Designs"); MODULE_DESCRIPTION("cpufreq driver for Tangox 87xx");
#define TANGOX_XTAL_FREQ 27000 /* in kHz */
#define CLKGEN_BASE 0x10000
#define SYS_clkgen0_pll (clkgen_base + 0x00)
#define SYS_cpuclk_div_ctrl (clkgen_base + 0x24)
static void __iomem *clkgen_base;
static struct cpufreq_frequency_table freq_table[] = {
{ .driver_data = 1 },
{ .driver_data = 2 },
{ .driver_data = 3 },
{ .driver_data = 5 },
{ .driver_data = 9 },
{ .frequency = CPUFREQ_TABLE_END },
};static unsigned int tangox_get_freq(unsigned int cpu)
{
union SYS_clkgen_pll pll;
union SYS_clk_div_ctrl div;
pll.val = readl_relaxed(SYS_clkgen0_pll);
if (pll.f.Isel != 1 || pll.f.M != 0) return 0;
div.val = readl_relaxed(SYS_cpuclk_div_ctrl);
if (div.f.BP != 0 || div.f.F != 0) return 0;
return TANGOX_XTAL_FREQ * (pll.f.N + 1) / div.f.I >> pll.f.K;
}static int tangox_target(struct cpufreq_policy *policy, unsigned int index)
{
while (readl_relaxed(SYS_cpuclk_div_ctrl) >> 31) cpu_relax();
writel_relaxed(freq_table[index].driver_data, SYS_cpuclk_div_ctrl);
return 0;
}static int tangox_cpu_init(struct cpufreq_policy *policy)
{
struct cpufreq_frequency_table *p;
unsigned int freq = tangox_get_freq(0);
unsigned int transition_latency_ns = freq / SYS_FAST_RAMP_SPEED;
if ((clkgen_base = ioremap(CLKGEN_BASE, 0x40)) == NULL) return -EFAULT;
for (p = freq_table; p->frequency != CPUFREQ_TABLE_END; ++p) {
unsigned int I = p->driver_data;
union SYS_clk_div_ctrl div = SYS_CLK_DIV_CTRL(I);
p->driver_data = div.val;
p->frequency = freq / I;
}
return cpufreq_generic_init(policy, freq_table, transition_latency_ns);
}static struct cpufreq_driver tangox_cpufreq_driver = {
.name = "tangox-cpufreq",
.init = tangox_cpu_init,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = tangox_target,
.get = tangox_get_freq,
.exit = cpufreq_generic_exit,
.attr = cpufreq_generic_attr,
};
static int __init tangox_cpufreq_init(void)
{
return cpufreq_register_driver(&tangox_cpufreq_driver);
}static void __exit tangox_cpufreq_exit(void)
{
cpufreq_unregister_driver(&tangox_cpufreq_driver);
}module_init(tangox_cpufreq_init);module_exit(tangox_cpufreq_exit);
Quoted 10 lines · Mason
OK, so this is my TAKE 2 on the cpufreq driver, trying to remove some dependencies on machine-specific definitions by getting the virtual address at init via ioremap. (Is
-EFAULTthe right error to return if ioremap fails?)I'm not sure where machine-specific information is supposed to be stored though? Such as register definitions, or the physical addresses/offsets. What if they need to be shared among several source files? I can't just duplicate them... (I've tentatively called it
temp.hfor the time being.)
What do you want to do with this driver? If you want to get it reviewed, please send it properly with git-send-email instead of attachments..
If its just an internal one, then sorry, the lists aren't for such reviews.
--
viresh
Quoted 4 lines · Viresh Kumar
What do you want to do with this driver? If you want to get it reviewed, please send it properly with git-send-email instead of attachments..
If its just an internal one, then sorry, the lists aren't for such reviews.
The long-term goal is to mainline the whole port, but it's rather overwhelming, and I haven't found a way to divide-and-conquer, yet. I've been reading guides and documentation for weeks, but nothing has made my brain click.
Everything seems to involve DeviceTree, and AFAIU, going down that rabbit-hole means making lots of changes all over. (But I probably misunderstood that part too.)
Right now, all I have is this cleaned up cpufreq driver. And I don't even know where to put it!
I see some platforms have it in their machine-specific folder, others are in drivers/cpufreq. (When to use mach vs plat?)
If it's supposed to go in drivers/cpufreq, I suppose there are naming conventions to follow?
Also, if it's in drivers/cpufreq, we are not supposed to include any machine-specific includes? And I'm back to my original question where am I supposed to store machine-specific information, such as register descriptions and MMIO addresses and offsets?
Quoted 4 lines · Arnd
I meant the
IO_ADDRESSstuff. Modern code usesioremap()instead since theIO_ADDRESSwas platform specific, and drivers can no longer use platform headers onCONFIG_ARCH_MULTIPLATFORM, which is used for all new code now.
Regards.
Quoted 2 lines · Mason
I see some platforms have it in their machine-specific folder, others are in
drivers/cpufreq. (When to use mach vs plat?)
drivers/cpufreq/
Quoted 2 lines
If it's supposed to go in
drivers/cpufreq, I suppose there are naming conventions to follow?
You can check existing drivers.
Quoted 4 lines
Also, if it's in
drivers/cpufreq, we are not supposed to include any machine-specific includes? And I'm back to my original question where am I supposed to store machine-specific information, such as register descriptions and MMIO addresses and offsets?
Define registers/etc in your driver only or somewhere in include/ . Also, try to see if you can reuse cpufreq-dt.c, your driver wouldn't make it to the kernel otherwise.
Quoted 6 lines · Viresh Kumar
Quoted 2 lines · Mason
If it's supposed to go in
drivers/cpufreq, I suppose there are naming conventions to follow?You can check existing drivers.
All of them?
~/linux-3.19-rc7$ wc drivers/cpufreq/*
31542 95730 813482 total
Are there perhaps 1 or 2 "golden standard" drivers that are well-written and up-to-date with respect to current conventions?
Quoted 6 lines
Quoted 4 lines
Also, if it's in
drivers/cpufreq, we are not supposed to include any machine-specific includes? And I'm back to my original question where am I supposed to store machine-specific information, such as register descriptions and MMIO addresses and offsets?Define registers/etc in your driver only or somewhere in
include/.
Like Samsung did with include/dt-bindings/clock/exynos*.h ?
Quoted 2 lines
Also, try to see if you can reuse
cpufreq-dt.c, your driver wouldn't make it to the kernel otherwise.
Are you saying that use of DeviceTree is mandatory for new ARM ports?
In other words, ports using "board files" will not be accepted into mainline, nor will drivers not using DT?
If that is correct, then my proposed cpufreq driver has exactly 0% chance of being mainlined as-is, right?
I took a look at cpufreq-dt.c but I think it doesn't quite fit my use-case. In my driver, I define "clock dividers" (typically 1,2,3,5,9) and these are used to divide some baseline frequency that the cpufreq code doesn't need to know. The baseline frequency is set by the boot loader, and Linux is not supposed to change that, only apply the dividers if necessary.
What do you think of this use-case?
Regards.
Quoted 1 line · Mason
Are you saying that use of DeviceTree is mandatory for new ARM ports?
Yes.
Signature · 2 lines
Måns Rullgård [email protected]
Quoted 7 lines · Mason
All of them?
~/linux-3.19-rc7$ wc
drivers/cpufreq/*
31542 95730 813482 totalAre there perhaps 1 or 2 "golden standard" drivers that are well-written and up-to-date with respect to current conventions?
cpufreq-dt.c
Quoted 1 line
Like Samsung did with
include/dt-bindings/clock/exynos*.h?
Yeah.
Quoted 1 line
Are you saying that use of DeviceTree is mandatory for new ARM ports?
Yes.
Quoted 2 lines
In other words, ports using "board files" will not be accepted into mainline, nor will drivers not using DT?
It wouldn't be good for you as well, that's all I can say.
Quoted 2 lines
If that is correct, then my proposed cpufreq driver has exactly 0% chance of being mainlined as-is, right?
:)
Quoted 7 lines
I took a look at
cpufreq-dt.cbut I think it doesn't quite fit my use-case. In my driver, I define "clock dividers" (typically 1,2,3,5,9) and these are used to divide some baseline frequency that the cpufreq code doesn't need to know. The baseline frequency is set by the boot loader, and Linux is not supposed to change that, only apply the dividers if necessary.What do you think of this use-case?
You need to write a backend clock driver for this. Most of the other platforms are doing this. cpufreq-dt driver does clk_get(), clk_get_rate(), clk_set_rate() and your backend driver should handle these to change the frequencies.