Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
6e926363
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6e926363
编写于
7月 25, 2018
作者:
R
Rafael J. Wysocki
浏览文件
操作
浏览文件
下载
差异文件
Merge back cpufreq material for 4.19.
上级
95d6c085
eea033d0
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
299 addition
and
18 deletion
+299
-18
Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
...mentation/devicetree/bindings/arm/marvell/armada-37xx.txt
+15
-0
drivers/cpufreq/armada-37xx-cpufreq.c
drivers/cpufreq/armada-37xx-cpufreq.c
+160
-3
drivers/cpufreq/cppc_cpufreq.c
drivers/cpufreq/cppc_cpufreq.c
+52
-0
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
+21
-0
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/intel_pstate.c
+15
-9
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/pcc-cpufreq.c
+9
-0
drivers/cpufreq/qcom-cpufreq-kryo.c
drivers/cpufreq/qcom-cpufreq-kryo.c
+3
-2
drivers/thermal/imx_thermal.c
drivers/thermal/imx_thermal.c
+24
-4
未找到文件。
Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
浏览文件 @
6e926363
...
...
@@ -33,3 +33,18 @@ nb_pm: syscon@14000 {
compatible = "marvell,armada-3700-nb-pm", "syscon";
reg = <0x14000 0x60>;
}
AVS
---
For AVS an other component is needed:
Required properties:
- compatible : should contain "marvell,armada-3700-avs", "syscon";
- reg : the register start and length for the AVS
Example:
avs: avs@11500 {
compatible = "marvell,armada-3700-avs", "syscon";
reg = <0x11500 0x40>;
}
drivers/cpufreq/armada-37xx-cpufreq.c
浏览文件 @
6e926363
...
...
@@ -51,6 +51,16 @@
#define ARMADA_37XX_DVFS_LOAD_2 2
#define ARMADA_37XX_DVFS_LOAD_3 3
/* AVS register set */
#define ARMADA_37XX_AVS_CTL0 0x0
#define ARMADA_37XX_AVS_ENABLE BIT(30)
#define ARMADA_37XX_AVS_HIGH_VDD_LIMIT 16
#define ARMADA_37XX_AVS_LOW_VDD_LIMIT 22
#define ARMADA_37XX_AVS_VDD_MASK 0x3F
#define ARMADA_37XX_AVS_CTL2 0x8
#define ARMADA_37XX_AVS_LOW_VDD_EN BIT(6)
#define ARMADA_37XX_AVS_VSET(x) (0x1C + 4 * (x))
/*
* On Armada 37xx the Power management manages 4 level of CPU load,
* each level can be associated with a CPU clock source, a CPU
...
...
@@ -58,6 +68,17 @@
*/
#define LOAD_LEVEL_NR 4
#define MIN_VOLT_MV 1000
/* AVS value for the corresponding voltage (in mV) */
static
int
avs_map
[]
=
{
747
,
758
,
770
,
782
,
793
,
805
,
817
,
828
,
840
,
852
,
863
,
875
,
887
,
898
,
910
,
922
,
933
,
945
,
957
,
968
,
980
,
992
,
1003
,
1015
,
1027
,
1038
,
1050
,
1062
,
1073
,
1085
,
1097
,
1108
,
1120
,
1132
,
1143
,
1155
,
1167
,
1178
,
1190
,
1202
,
1213
,
1225
,
1237
,
1248
,
1260
,
1272
,
1283
,
1295
,
1307
,
1318
,
1330
,
1342
};
struct
armada37xx_cpufreq_state
{
struct
regmap
*
regmap
;
u32
nb_l0l1
;
...
...
@@ -71,6 +92,7 @@ static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state;
struct
armada_37xx_dvfs
{
u32
cpu_freq_max
;
u8
divider
[
LOAD_LEVEL_NR
];
u32
avs
[
LOAD_LEVEL_NR
];
};
static
struct
armada_37xx_dvfs
armada_37xx_dvfs
[]
=
{
...
...
@@ -148,6 +170,128 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
clk_set_parent
(
clk
,
parent
);
}
/*
* Find out the armada 37x supported AVS value whose voltage value is
* the round-up closest to the target voltage value.
*/
static
u32
armada_37xx_avs_val_match
(
int
target_vm
)
{
u32
avs
;
/* Find out the round-up closest supported voltage value */
for
(
avs
=
0
;
avs
<
ARRAY_SIZE
(
avs_map
);
avs
++
)
if
(
avs_map
[
avs
]
>=
target_vm
)
break
;
/*
* If all supported voltages are smaller than target one,
* choose the largest supported voltage
*/
if
(
avs
==
ARRAY_SIZE
(
avs_map
))
avs
=
ARRAY_SIZE
(
avs_map
)
-
1
;
return
avs
;
}
/*
* For Armada 37xx soc, L0(VSET0) VDD AVS value is set to SVC revision
* value or a default value when SVC is not supported.
* - L0 can be read out from the register of AVS_CTRL_0 and L0 voltage
* can be got from the mapping table of avs_map.
* - L1 voltage should be about 100mv smaller than L0 voltage
* - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
* This function calculates L1 & L2 & L3 AVS values dynamically based
* on L0 voltage and fill all AVS values to the AVS value table.
*/
static
void
__init
armada37xx_cpufreq_avs_configure
(
struct
regmap
*
base
,
struct
armada_37xx_dvfs
*
dvfs
)
{
unsigned
int
target_vm
;
int
load_level
=
0
;
u32
l0_vdd_min
;
if
(
base
==
NULL
)
return
;
/* Get L0 VDD min value */
regmap_read
(
base
,
ARMADA_37XX_AVS_CTL0
,
&
l0_vdd_min
);
l0_vdd_min
=
(
l0_vdd_min
>>
ARMADA_37XX_AVS_LOW_VDD_LIMIT
)
&
ARMADA_37XX_AVS_VDD_MASK
;
if
(
l0_vdd_min
>=
ARRAY_SIZE
(
avs_map
))
{
pr_err
(
"L0 VDD MIN %d is not correct.
\n
"
,
l0_vdd_min
);
return
;
}
dvfs
->
avs
[
0
]
=
l0_vdd_min
;
if
(
avs_map
[
l0_vdd_min
]
<=
MIN_VOLT_MV
)
{
/*
* If L0 voltage is smaller than 1000mv, then all VDD sets
* use L0 voltage;
*/
u32
avs_min
=
armada_37xx_avs_val_match
(
MIN_VOLT_MV
);
for
(
load_level
=
1
;
load_level
<
LOAD_LEVEL_NR
;
load_level
++
)
dvfs
->
avs
[
load_level
]
=
avs_min
;
return
;
}
/*
* L1 voltage is equal to L0 voltage - 100mv and it must be
* larger than 1000mv
*/
target_vm
=
avs_map
[
l0_vdd_min
]
-
100
;
target_vm
=
target_vm
>
MIN_VOLT_MV
?
target_vm
:
MIN_VOLT_MV
;
dvfs
->
avs
[
1
]
=
armada_37xx_avs_val_match
(
target_vm
);
/*
* L2 & L3 voltage is equal to L0 voltage - 150mv and it must
* be larger than 1000mv
*/
target_vm
=
avs_map
[
l0_vdd_min
]
-
150
;
target_vm
=
target_vm
>
MIN_VOLT_MV
?
target_vm
:
MIN_VOLT_MV
;
dvfs
->
avs
[
2
]
=
dvfs
->
avs
[
3
]
=
armada_37xx_avs_val_match
(
target_vm
);
}
static
void
__init
armada37xx_cpufreq_avs_setup
(
struct
regmap
*
base
,
struct
armada_37xx_dvfs
*
dvfs
)
{
unsigned
int
avs_val
=
0
,
freq
;
int
load_level
=
0
;
if
(
base
==
NULL
)
return
;
/* Disable AVS before the configuration */
regmap_update_bits
(
base
,
ARMADA_37XX_AVS_CTL0
,
ARMADA_37XX_AVS_ENABLE
,
0
);
/* Enable low voltage mode */
regmap_update_bits
(
base
,
ARMADA_37XX_AVS_CTL2
,
ARMADA_37XX_AVS_LOW_VDD_EN
,
ARMADA_37XX_AVS_LOW_VDD_EN
);
for
(
load_level
=
1
;
load_level
<
LOAD_LEVEL_NR
;
load_level
++
)
{
freq
=
dvfs
->
cpu_freq_max
/
dvfs
->
divider
[
load_level
];
avs_val
=
dvfs
->
avs
[
load_level
];
regmap_update_bits
(
base
,
ARMADA_37XX_AVS_VSET
(
load_level
-
1
),
ARMADA_37XX_AVS_VDD_MASK
<<
ARMADA_37XX_AVS_HIGH_VDD_LIMIT
|
ARMADA_37XX_AVS_VDD_MASK
<<
ARMADA_37XX_AVS_LOW_VDD_LIMIT
,
avs_val
<<
ARMADA_37XX_AVS_HIGH_VDD_LIMIT
|
avs_val
<<
ARMADA_37XX_AVS_LOW_VDD_LIMIT
);
}
/* Enable AVS after the configuration */
regmap_update_bits
(
base
,
ARMADA_37XX_AVS_CTL0
,
ARMADA_37XX_AVS_ENABLE
,
ARMADA_37XX_AVS_ENABLE
);
}
static
void
armada37xx_cpufreq_disable_dvfs
(
struct
regmap
*
base
)
{
unsigned
int
reg
=
ARMADA_37XX_NB_DYN_MOD
,
...
...
@@ -216,7 +360,7 @@ static int __init armada37xx_cpufreq_driver_init(void)
struct
platform_device
*
pdev
;
unsigned
long
freq
;
unsigned
int
cur_frequency
;
struct
regmap
*
nb_pm_base
;
struct
regmap
*
nb_pm_base
,
*
avs_base
;
struct
device
*
cpu_dev
;
int
load_lvl
,
ret
;
struct
clk
*
clk
;
...
...
@@ -227,6 +371,14 @@ static int __init armada37xx_cpufreq_driver_init(void)
if
(
IS_ERR
(
nb_pm_base
))
return
-
ENODEV
;
avs_base
=
syscon_regmap_lookup_by_compatible
(
"marvell,armada-3700-avs"
);
/* if AVS is not present don't use it but still try to setup dvfs */
if
(
IS_ERR
(
avs_base
))
{
pr_info
(
"Syscon failed for Adapting Voltage Scaling: skip it
\n
"
);
avs_base
=
NULL
;
}
/* Before doing any configuration on the DVFS first, disable it */
armada37xx_cpufreq_disable_dvfs
(
nb_pm_base
);
...
...
@@ -270,16 +422,21 @@ static int __init armada37xx_cpufreq_driver_init(void)
armada37xx_cpufreq_state
->
regmap
=
nb_pm_base
;
armada37xx_cpufreq_avs_configure
(
avs_base
,
dvfs
);
armada37xx_cpufreq_avs_setup
(
avs_base
,
dvfs
);
armada37xx_cpufreq_dvfs_setup
(
nb_pm_base
,
clk
,
dvfs
->
divider
);
clk_put
(
clk
);
for
(
load_lvl
=
ARMADA_37XX_DVFS_LOAD_0
;
load_lvl
<
LOAD_LEVEL_NR
;
load_lvl
++
)
{
unsigned
long
u_volt
=
avs_map
[
dvfs
->
avs
[
load_lvl
]]
*
1000
;
freq
=
cur_frequency
/
dvfs
->
divider
[
load_lvl
];
ret
=
dev_pm_opp_add
(
cpu_dev
,
freq
,
0
);
ret
=
dev_pm_opp_add
(
cpu_dev
,
freq
,
u_volt
);
if
(
ret
)
goto
remove_opp
;
}
/* Now that everything is setup, enable the DVFS at hardware level */
...
...
drivers/cpufreq/cppc_cpufreq.c
浏览文件 @
6e926363
...
...
@@ -296,10 +296,62 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
return
ret
;
}
static
inline
u64
get_delta
(
u64
t1
,
u64
t0
)
{
if
(
t1
>
t0
||
t0
>
~
(
u32
)
0
)
return
t1
-
t0
;
return
(
u32
)
t1
-
(
u32
)
t0
;
}
static
int
cppc_get_rate_from_fbctrs
(
struct
cppc_cpudata
*
cpu
,
struct
cppc_perf_fb_ctrs
fb_ctrs_t0
,
struct
cppc_perf_fb_ctrs
fb_ctrs_t1
)
{
u64
delta_reference
,
delta_delivered
;
u64
reference_perf
,
delivered_perf
;
reference_perf
=
fb_ctrs_t0
.
reference_perf
;
delta_reference
=
get_delta
(
fb_ctrs_t1
.
reference
,
fb_ctrs_t0
.
reference
);
delta_delivered
=
get_delta
(
fb_ctrs_t1
.
delivered
,
fb_ctrs_t0
.
delivered
);
/* Check to avoid divide-by zero */
if
(
delta_reference
||
delta_delivered
)
delivered_perf
=
(
reference_perf
*
delta_delivered
)
/
delta_reference
;
else
delivered_perf
=
cpu
->
perf_ctrls
.
desired_perf
;
return
cppc_cpufreq_perf_to_khz
(
cpu
,
delivered_perf
);
}
static
unsigned
int
cppc_cpufreq_get_rate
(
unsigned
int
cpunum
)
{
struct
cppc_perf_fb_ctrs
fb_ctrs_t0
=
{
0
},
fb_ctrs_t1
=
{
0
};
struct
cppc_cpudata
*
cpu
=
all_cpu_data
[
cpunum
];
int
ret
;
ret
=
cppc_get_perf_ctrs
(
cpunum
,
&
fb_ctrs_t0
);
if
(
ret
)
return
ret
;
udelay
(
2
);
/* 2usec delay between sampling */
ret
=
cppc_get_perf_ctrs
(
cpunum
,
&
fb_ctrs_t1
);
if
(
ret
)
return
ret
;
return
cppc_get_rate_from_fbctrs
(
cpu
,
fb_ctrs_t0
,
fb_ctrs_t1
);
}
static
struct
cpufreq_driver
cppc_cpufreq_driver
=
{
.
flags
=
CPUFREQ_CONST_LOOPS
,
.
verify
=
cppc_verify_policy
,
.
target
=
cppc_cpufreq_set_target
,
.
get
=
cppc_cpufreq_get_rate
,
.
init
=
cppc_cpufreq_cpu_init
,
.
stop_cpu
=
cppc_cpufreq_stop_cpu
,
.
name
=
"cppc_cpufreq"
,
...
...
drivers/cpufreq/imx6q-cpufreq.c
浏览文件 @
6e926363
...
...
@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpu_cooling.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
...
...
@@ -50,6 +51,7 @@ static struct clk_bulk_data clks[] = {
};
static
struct
device
*
cpu_dev
;
static
struct
thermal_cooling_device
*
cdev
;
static
bool
free_opp
;
static
struct
cpufreq_frequency_table
*
freq_table
;
static
unsigned
int
max_freq
;
...
...
@@ -191,6 +193,16 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
return
0
;
}
static
void
imx6q_cpufreq_ready
(
struct
cpufreq_policy
*
policy
)
{
cdev
=
of_cpufreq_cooling_register
(
policy
);
if
(
!
cdev
)
dev_err
(
cpu_dev
,
"running cpufreq without cooling device: %ld
\n
"
,
PTR_ERR
(
cdev
));
}
static
int
imx6q_cpufreq_init
(
struct
cpufreq_policy
*
policy
)
{
int
ret
;
...
...
@@ -202,13 +214,22 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
return
ret
;
}
static
int
imx6q_cpufreq_exit
(
struct
cpufreq_policy
*
policy
)
{
cpufreq_cooling_unregister
(
cdev
);
return
0
;
}
static
struct
cpufreq_driver
imx6q_cpufreq_driver
=
{
.
flags
=
CPUFREQ_NEED_INITIAL_FREQ_CHECK
,
.
verify
=
cpufreq_generic_frequency_table_verify
,
.
target_index
=
imx6q_set_target
,
.
get
=
cpufreq_generic_get
,
.
init
=
imx6q_cpufreq_init
,
.
exit
=
imx6q_cpufreq_exit
,
.
name
=
"imx6q-cpufreq"
,
.
ready
=
imx6q_cpufreq_ready
,
.
attr
=
cpufreq_generic_attr
,
.
suspend
=
cpufreq_generic_suspend
,
};
...
...
drivers/cpufreq/intel_pstate.c
浏览文件 @
6e926363
...
...
@@ -657,21 +657,18 @@ static ssize_t store_energy_performance_preference(
{
struct
cpudata
*
cpu_data
=
all_cpu_data
[
policy
->
cpu
];
char
str_preference
[
21
];
int
ret
,
i
=
0
;
int
ret
;
ret
=
sscanf
(
buf
,
"%20s"
,
str_preference
);
if
(
ret
!=
1
)
return
-
EINVAL
;
while
(
energy_perf_strings
[
i
]
!=
NULL
)
{
if
(
!
strcmp
(
str_preference
,
energy_perf_strings
[
i
]))
{
intel_pstate_set_energy_pref_index
(
cpu_data
,
i
);
return
count
;
}
++
i
;
}
ret
=
match_string
(
energy_perf_strings
,
-
1
,
str_preference
);
if
(
ret
<
0
)
return
ret
;
return
-
EINVAL
;
intel_pstate_set_energy_pref_index
(
cpu_data
,
ret
);
return
count
;
}
static
ssize_t
show_energy_performance_preference
(
...
...
@@ -2072,6 +2069,15 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
cpu
->
pstate
.
max_pstate
:
cpu
->
pstate
.
turbo_pstate
;
policy
->
cpuinfo
.
max_freq
*=
cpu
->
pstate
.
scaling
;
if
(
hwp_active
)
{
unsigned
int
max_freq
;
max_freq
=
global
.
turbo_disabled
?
cpu
->
pstate
.
max_freq
:
cpu
->
pstate
.
turbo_freq
;
if
(
max_freq
<
policy
->
cpuinfo
.
max_freq
)
policy
->
cpuinfo
.
max_freq
=
max_freq
;
}
intel_pstate_init_acpi_perf_limits
(
policy
);
policy
->
fast_switch_possible
=
true
;
...
...
drivers/cpufreq/pcc-cpufreq.c
浏览文件 @
6e926363
...
...
@@ -593,6 +593,15 @@ static int __init pcc_cpufreq_init(void)
return
ret
;
}
if
(
num_present_cpus
()
>
4
)
{
pcc_cpufreq_driver
.
flags
|=
CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING
;
pr_err
(
"%s: Too many CPUs, dynamic performance scaling disabled
\n
"
,
__func__
);
pr_err
(
"%s: Try to enable another scaling driver through BIOS settings
\n
"
,
__func__
);
pr_err
(
"%s: and complain to the system vendor
\n
"
,
__func__
);
}
ret
=
cpufreq_register_driver
(
&
pcc_cpufreq_driver
);
return
ret
;
...
...
drivers/cpufreq/qcom-cpufreq-kryo.c
浏览文件 @
6e926363
...
...
@@ -109,8 +109,9 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
speedbin_nvmem
=
of_nvmem_cell_get
(
np
,
NULL
);
of_node_put
(
np
);
if
(
IS_ERR
(
speedbin_nvmem
))
{
dev_err
(
cpu_dev
,
"Could not get nvmem cell: %ld
\n
"
,
PTR_ERR
(
speedbin_nvmem
));
if
(
PTR_ERR
(
speedbin_nvmem
)
!=
-
EPROBE_DEFER
)
dev_err
(
cpu_dev
,
"Could not get nvmem cell: %ld
\n
"
,
PTR_ERR
(
speedbin_nvmem
));
return
PTR_ERR
(
speedbin_nvmem
);
}
...
...
drivers/thermal/imx_thermal.c
浏览文件 @
6e926363
...
...
@@ -3,6 +3,7 @@
// Copyright 2013 Freescale Semiconductor, Inc.
#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpu_cooling.h>
#include <linux/delay.h>
...
...
@@ -644,6 +645,27 @@ static const struct of_device_id of_imx_thermal_match[] = {
};
MODULE_DEVICE_TABLE
(
of
,
of_imx_thermal_match
);
/*
* Create cooling device in case no #cooling-cells property is available in
* CPU node
*/
static
int
imx_thermal_register_legacy_cooling
(
struct
imx_thermal_data
*
data
)
{
struct
device_node
*
np
=
of_get_cpu_node
(
data
->
policy
->
cpu
,
NULL
);
int
ret
;
if
(
!
np
||
!
of_find_property
(
np
,
"#cooling-cells"
,
NULL
))
{
data
->
cdev
=
cpufreq_cooling_register
(
data
->
policy
);
if
(
IS_ERR
(
data
->
cdev
))
{
ret
=
PTR_ERR
(
data
->
cdev
);
cpufreq_cpu_put
(
data
->
policy
);
return
ret
;
}
}
return
0
;
}
static
int
imx_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
imx_thermal_data
*
data
;
...
...
@@ -724,12 +746,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
return
-
EPROBE_DEFER
;
}
data
->
cdev
=
cpufreq_cooling_register
(
data
->
policy
);
if
(
IS_ERR
(
data
->
cdev
))
{
ret
=
PTR_ERR
(
data
->
cdev
);
ret
=
imx_thermal_register_legacy_cooling
(
data
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register cpufreq cooling device: %d
\n
"
,
ret
);
cpufreq_cpu_put
(
data
->
policy
);
return
ret
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录