Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
7a348799
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
7a348799
编写于
9月 08, 2017
作者:
Z
Zhang Rui
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'mediatek-mt2712', 'rockchip-rk3328' and 'uniphier-thermal' into thermal-soc
上级
6760f3f7
eda519d5
86da4391
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
523 addition
and
0 deletion
+523
-0
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
...entation/devicetree/bindings/thermal/rockchip-thermal.txt
+1
-0
Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
...entation/devicetree/bindings/thermal/uniphier-thermal.txt
+64
-0
drivers/thermal/Kconfig
drivers/thermal/Kconfig
+8
-0
drivers/thermal/Makefile
drivers/thermal/Makefile
+1
-0
drivers/thermal/rockchip_thermal.c
drivers/thermal/rockchip_thermal.c
+65
-0
drivers/thermal/uniphier_thermal.c
drivers/thermal/uniphier_thermal.c
+384
-0
未找到文件。
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
浏览文件 @
7a348799
...
...
@@ -4,6 +4,7 @@ Required properties:
- compatible : should be "rockchip,<name>-tsadc"
"rockchip,rk3228-tsadc": found on RK3228 SoCs
"rockchip,rk3288-tsadc": found on RK3288 SoCs
"rockchip,rk3328-tsadc": found on RK3328 SoCs
"rockchip,rk3368-tsadc": found on RK3368 SoCs
"rockchip,rk3399-tsadc": found on RK3399 SoCs
- reg : physical base address of the controller and length of memory mapped
...
...
Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
0 → 100644
浏览文件 @
7a348799
* UniPhier Thermal bindings
This describes the devicetree bindings for thermal monitor supported by
PVT(Process, Voltage and Temperature) monitoring unit implemented on Socionext
UniPhier SoCs.
Required properties:
- compatible :
- "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC
- "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC
- interrupts : IRQ for the temperature alarm
- #thermal-sensor-cells : Should be 0. See ./thermal.txt for details.
Optional properties:
- socionext,tmod-calibration: A pair of calibrated values referred from PVT,
in case that the values aren't set on SoC,
like a reference board.
Example:
sysctrl@61840000 {
compatible = "socionext,uniphier-ld20-sysctrl",
"simple-mfd", "syscon";
reg = <0x61840000 0x10000>;
...
pvtctl: pvtctl {
compatible = "socionext,uniphier-ld20-thermal";
interrupts = <0 3 1>;
#thermal-sensor-cells = <0>;
};
...
};
thermal-zones {
cpu_thermal {
polling-delay-passive = <250>; /* 250ms */
polling-delay = <1000>; /* 1000ms */
thermal-sensors = <&pvtctl>;
trips {
cpu_crit: cpu_crit {
temperature = <110000>; /* 110C */
hysteresis = <2000>;
type = "critical";
};
cpu_alert: cpu_alert {
temperature = <100000>; /* 100C */
hysteresis = <2000>;
type = "passive";
};
};
cooling-maps {
map0 {
trip = <&cpu_alert>;
cooling-device = <&cpu0 (-1) (-1)>;
};
map1 {
trip = <&cpu_alert>;
cooling-device = <&cpu2 (-1) (-1)>;
};
};
};
};
drivers/thermal/Kconfig
浏览文件 @
7a348799
...
...
@@ -473,4 +473,12 @@ config ZX2967_THERMAL
the primitive temperature sensor embedded in zx2967 SoCs.
This sensor generates the real time die temperature.
config UNIPHIER_THERMAL
tristate "Socionext UniPhier thermal driver"
depends on ARCH_UNIPHIER || COMPILE_TEST
depends on THERMAL_OF && MFD_SYSCON
help
Enable this to plug in UniPhier on-chip PVT thermal driver into the
thermal framework. The driver supports CPU thermal zone temperature
reporting and a couple of trip points.
endif
drivers/thermal/Makefile
浏览文件 @
7a348799
...
...
@@ -59,3 +59,4 @@ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL)
+=
mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL)
+=
thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL)
+=
zx2967_thermal.o
obj-$(CONFIG_UNIPHIER_THERMAL)
+=
uniphier_thermal.o
drivers/thermal/rockchip_thermal.c
浏览文件 @
7a348799
...
...
@@ -320,6 +320,44 @@ static const struct tsadc_table rk3288_code_table[] = {
{
0
,
125000
},
};
static
const
struct
tsadc_table
rk3328_code_table
[]
=
{
{
0
,
-
40000
},
{
296
,
-
40000
},
{
304
,
-
35000
},
{
313
,
-
30000
},
{
331
,
-
20000
},
{
340
,
-
15000
},
{
349
,
-
10000
},
{
359
,
-
5000
},
{
368
,
0
},
{
378
,
5000
},
{
388
,
10000
},
{
398
,
15000
},
{
408
,
20000
},
{
418
,
25000
},
{
429
,
30000
},
{
440
,
35000
},
{
451
,
40000
},
{
462
,
45000
},
{
473
,
50000
},
{
485
,
55000
},
{
496
,
60000
},
{
508
,
65000
},
{
521
,
70000
},
{
533
,
75000
},
{
546
,
80000
},
{
559
,
85000
},
{
572
,
90000
},
{
586
,
95000
},
{
600
,
100000
},
{
614
,
105000
},
{
629
,
110000
},
{
644
,
115000
},
{
659
,
120000
},
{
675
,
125000
},
{
TSADCV2_DATA_MASK
,
125000
},
};
static
const
struct
tsadc_table
rk3368_code_table
[]
=
{
{
0
,
-
40000
},
{
106
,
-
40000
},
...
...
@@ -790,6 +828,29 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
},
};
static
const
struct
rockchip_tsadc_chip
rk3328_tsadc_data
=
{
.
chn_id
[
SENSOR_CPU
]
=
0
,
/* cpu sensor is channel 0 */
.
chn_num
=
1
,
/* one channels for tsadc */
.
tshut_mode
=
TSHUT_MODE_CRU
,
/* default TSHUT via CRU */
.
tshut_temp
=
95000
,
.
initialize
=
rk_tsadcv2_initialize
,
.
irq_ack
=
rk_tsadcv3_irq_ack
,
.
control
=
rk_tsadcv3_control
,
.
get_temp
=
rk_tsadcv2_get_temp
,
.
set_alarm_temp
=
rk_tsadcv2_alarm_temp
,
.
set_tshut_temp
=
rk_tsadcv2_tshut_temp
,
.
set_tshut_mode
=
rk_tsadcv2_tshut_mode
,
.
table
=
{
.
id
=
rk3328_code_table
,
.
length
=
ARRAY_SIZE
(
rk3328_code_table
),
.
data_mask
=
TSADCV2_DATA_MASK
,
.
mode
=
ADC_INCREMENT
,
},
};
static
const
struct
rockchip_tsadc_chip
rk3366_tsadc_data
=
{
.
chn_id
[
SENSOR_CPU
]
=
0
,
/* cpu sensor is channel 0 */
.
chn_id
[
SENSOR_GPU
]
=
1
,
/* gpu sensor is channel 1 */
...
...
@@ -874,6 +935,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
.
compatible
=
"rockchip,rk3288-tsadc"
,
.
data
=
(
void
*
)
&
rk3288_tsadc_data
,
},
{
.
compatible
=
"rockchip,rk3328-tsadc"
,
.
data
=
(
void
*
)
&
rk3328_tsadc_data
,
},
{
.
compatible
=
"rockchip,rk3366-tsadc"
,
.
data
=
(
void
*
)
&
rk3366_tsadc_data
,
...
...
drivers/thermal/uniphier_thermal.c
0 → 100644
浏览文件 @
7a348799
/**
* uniphier_thermal.c - Socionext UniPhier thermal driver
*
* Copyright 2014 Panasonic Corporation
* Copyright 2016-2017 Socionext Inc.
* All rights reserved.
*
* Author:
* Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/thermal.h>
#include "thermal_core.h"
/*
* block registers
* addresses are the offset from .block_base
*/
#define PVTCTLEN 0x0000
#define PVTCTLEN_EN BIT(0)
#define PVTCTLMODE 0x0004
#define PVTCTLMODE_MASK 0xf
#define PVTCTLMODE_TEMPMON 0x5
#define EMONREPEAT 0x0040
#define EMONREPEAT_ENDLESS BIT(24)
#define EMONREPEAT_PERIOD GENMASK(3, 0)
#define EMONREPEAT_PERIOD_1000000 0x9
/*
* common registers
* addresses are the offset from .map_base
*/
#define PVTCTLSEL 0x0900
#define PVTCTLSEL_MASK GENMASK(2, 0)
#define PVTCTLSEL_MONITOR 0
#define SETALERT0 0x0910
#define SETALERT1 0x0914
#define SETALERT2 0x0918
#define SETALERT_TEMP_OVF (GENMASK(7, 0) << 16)
#define SETALERT_TEMP_OVF_VALUE(val) (((val) & GENMASK(7, 0)) << 16)
#define SETALERT_EN BIT(0)
#define PMALERTINTCTL 0x0920
#define PMALERTINTCTL_CLR(ch) BIT(4 * (ch) + 2)
#define PMALERTINTCTL_SET(ch) BIT(4 * (ch) + 1)
#define PMALERTINTCTL_EN(ch) BIT(4 * (ch) + 0)
#define PMALERTINTCTL_MASK (GENMASK(10, 8) | GENMASK(6, 4) | \
GENMASK(2, 0))
#define TMOD 0x0928
#define TMOD_WIDTH 9
#define TMODCOEF 0x0e5c
#define TMODSETUP0_EN BIT(30)
#define TMODSETUP0_VAL(val) (((val) & GENMASK(13, 0)) << 16)
#define TMODSETUP1_EN BIT(15)
#define TMODSETUP1_VAL(val) ((val) & GENMASK(14, 0))
/* SoC critical temperature */
#define CRITICAL_TEMP_LIMIT (120 * 1000)
/* Max # of alert channels */
#define ALERT_CH_NUM 3
/* SoC specific thermal sensor data */
struct
uniphier_tm_soc_data
{
u32
map_base
;
u32
block_base
;
u32
tmod_setup_addr
;
};
struct
uniphier_tm_dev
{
struct
regmap
*
regmap
;
struct
device
*
dev
;
bool
alert_en
[
ALERT_CH_NUM
];
struct
thermal_zone_device
*
tz_dev
;
const
struct
uniphier_tm_soc_data
*
data
;
};
static
int
uniphier_tm_initialize_sensor
(
struct
uniphier_tm_dev
*
tdev
)
{
struct
regmap
*
map
=
tdev
->
regmap
;
u32
val
;
u32
tmod_calib
[
2
];
int
ret
;
/* stop PVT */
regmap_write_bits
(
map
,
tdev
->
data
->
block_base
+
PVTCTLEN
,
PVTCTLEN_EN
,
0
);
/*
* Since SoC has a calibrated value that was set in advance,
* TMODCOEF shows non-zero and PVT refers the value internally.
*
* If TMODCOEF shows zero, the boards don't have the calibrated
* value, and the driver has to set default value from DT.
*/
ret
=
regmap_read
(
map
,
tdev
->
data
->
map_base
+
TMODCOEF
,
&
val
);
if
(
ret
)
return
ret
;
if
(
!
val
)
{
/* look for the default values in DT */
ret
=
of_property_read_u32_array
(
tdev
->
dev
->
of_node
,
"socionext,tmod-calibration"
,
tmod_calib
,
ARRAY_SIZE
(
tmod_calib
));
if
(
ret
)
return
ret
;
regmap_write
(
map
,
tdev
->
data
->
tmod_setup_addr
,
TMODSETUP0_EN
|
TMODSETUP0_VAL
(
tmod_calib
[
0
])
|
TMODSETUP1_EN
|
TMODSETUP1_VAL
(
tmod_calib
[
1
]));
}
/* select temperature mode */
regmap_write_bits
(
map
,
tdev
->
data
->
block_base
+
PVTCTLMODE
,
PVTCTLMODE_MASK
,
PVTCTLMODE_TEMPMON
);
/* set monitoring period */
regmap_write_bits
(
map
,
tdev
->
data
->
block_base
+
EMONREPEAT
,
EMONREPEAT_ENDLESS
|
EMONREPEAT_PERIOD
,
EMONREPEAT_ENDLESS
|
EMONREPEAT_PERIOD_1000000
);
/* set monitor mode */
regmap_write_bits
(
map
,
tdev
->
data
->
map_base
+
PVTCTLSEL
,
PVTCTLSEL_MASK
,
PVTCTLSEL_MONITOR
);
return
0
;
}
static
void
uniphier_tm_set_alert
(
struct
uniphier_tm_dev
*
tdev
,
u32
ch
,
u32
temp
)
{
struct
regmap
*
map
=
tdev
->
regmap
;
/* set alert temperature */
regmap_write_bits
(
map
,
tdev
->
data
->
map_base
+
SETALERT0
+
(
ch
<<
2
),
SETALERT_EN
|
SETALERT_TEMP_OVF
,
SETALERT_EN
|
SETALERT_TEMP_OVF_VALUE
(
temp
/
1000
));
}
static
void
uniphier_tm_enable_sensor
(
struct
uniphier_tm_dev
*
tdev
)
{
struct
regmap
*
map
=
tdev
->
regmap
;
int
i
;
u32
bits
=
0
;
for
(
i
=
0
;
i
<
ALERT_CH_NUM
;
i
++
)
if
(
tdev
->
alert_en
[
i
])
bits
|=
PMALERTINTCTL_EN
(
i
);
/* enable alert interrupt */
regmap_write_bits
(
map
,
tdev
->
data
->
map_base
+
PMALERTINTCTL
,
PMALERTINTCTL_MASK
,
bits
);
/* start PVT */
regmap_write_bits
(
map
,
tdev
->
data
->
block_base
+
PVTCTLEN
,
PVTCTLEN_EN
,
PVTCTLEN_EN
);
usleep_range
(
700
,
1500
);
/* The spec note says at least 700us */
}
static
void
uniphier_tm_disable_sensor
(
struct
uniphier_tm_dev
*
tdev
)
{
struct
regmap
*
map
=
tdev
->
regmap
;
/* disable alert interrupt */
regmap_write_bits
(
map
,
tdev
->
data
->
map_base
+
PMALERTINTCTL
,
PMALERTINTCTL_MASK
,
0
);
/* stop PVT */
regmap_write_bits
(
map
,
tdev
->
data
->
block_base
+
PVTCTLEN
,
PVTCTLEN_EN
,
0
);
usleep_range
(
1000
,
2000
);
/* The spec note says at least 1ms */
}
static
int
uniphier_tm_get_temp
(
void
*
data
,
int
*
out_temp
)
{
struct
uniphier_tm_dev
*
tdev
=
data
;
struct
regmap
*
map
=
tdev
->
regmap
;
int
ret
;
u32
temp
;
ret
=
regmap_read
(
map
,
tdev
->
data
->
map_base
+
TMOD
,
&
temp
);
if
(
ret
)
return
ret
;
/* MSB of the TMOD field is a sign bit */
*
out_temp
=
sign_extend32
(
temp
,
TMOD_WIDTH
-
1
)
*
1000
;
return
0
;
}
static
const
struct
thermal_zone_of_device_ops
uniphier_of_thermal_ops
=
{
.
get_temp
=
uniphier_tm_get_temp
,
};
static
void
uniphier_tm_irq_clear
(
struct
uniphier_tm_dev
*
tdev
)
{
u32
mask
=
0
,
bits
=
0
;
int
i
;
for
(
i
=
0
;
i
<
ALERT_CH_NUM
;
i
++
)
{
mask
|=
(
PMALERTINTCTL_CLR
(
i
)
|
PMALERTINTCTL_SET
(
i
));
bits
|=
PMALERTINTCTL_CLR
(
i
);
}
/* clear alert interrupt */
regmap_write_bits
(
tdev
->
regmap
,
tdev
->
data
->
map_base
+
PMALERTINTCTL
,
mask
,
bits
);
}
static
irqreturn_t
uniphier_tm_alarm_irq
(
int
irq
,
void
*
_tdev
)
{
struct
uniphier_tm_dev
*
tdev
=
_tdev
;
disable_irq_nosync
(
irq
);
uniphier_tm_irq_clear
(
tdev
);
return
IRQ_WAKE_THREAD
;
}
static
irqreturn_t
uniphier_tm_alarm_irq_thread
(
int
irq
,
void
*
_tdev
)
{
struct
uniphier_tm_dev
*
tdev
=
_tdev
;
thermal_zone_device_update
(
tdev
->
tz_dev
,
THERMAL_EVENT_UNSPECIFIED
);
return
IRQ_HANDLED
;
}
static
int
uniphier_tm_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
regmap
*
regmap
;
struct
device_node
*
parent
;
struct
uniphier_tm_dev
*
tdev
;
const
struct
thermal_trip
*
trips
;
int
i
,
ret
,
irq
,
ntrips
,
crit_temp
=
INT_MAX
;
tdev
=
devm_kzalloc
(
dev
,
sizeof
(
*
tdev
),
GFP_KERNEL
);
if
(
!
tdev
)
return
-
ENOMEM
;
tdev
->
dev
=
dev
;
tdev
->
data
=
of_device_get_match_data
(
dev
);
if
(
WARN_ON
(
!
tdev
->
data
))
return
-
EINVAL
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
return
irq
;
/* get regmap from syscon node */
parent
=
of_get_parent
(
dev
->
of_node
);
/* parent should be syscon node */
regmap
=
syscon_node_to_regmap
(
parent
);
of_node_put
(
parent
);
if
(
IS_ERR
(
regmap
))
{
dev_err
(
dev
,
"failed to get regmap (error %ld)
\n
"
,
PTR_ERR
(
regmap
));
return
PTR_ERR
(
regmap
);
}
tdev
->
regmap
=
regmap
;
ret
=
uniphier_tm_initialize_sensor
(
tdev
);
if
(
ret
)
{
dev_err
(
dev
,
"failed to initialize sensor
\n
"
);
return
ret
;
}
ret
=
devm_request_threaded_irq
(
dev
,
irq
,
uniphier_tm_alarm_irq
,
uniphier_tm_alarm_irq_thread
,
0
,
"thermal"
,
tdev
);
if
(
ret
)
return
ret
;
platform_set_drvdata
(
pdev
,
tdev
);
tdev
->
tz_dev
=
devm_thermal_zone_of_sensor_register
(
dev
,
0
,
tdev
,
&
uniphier_of_thermal_ops
);
if
(
IS_ERR
(
tdev
->
tz_dev
))
{
dev_err
(
dev
,
"failed to register sensor device
\n
"
);
return
PTR_ERR
(
tdev
->
tz_dev
);
}
/* get trip points */
trips
=
of_thermal_get_trip_points
(
tdev
->
tz_dev
);
ntrips
=
of_thermal_get_ntrips
(
tdev
->
tz_dev
);
if
(
ntrips
>
ALERT_CH_NUM
)
{
dev_err
(
dev
,
"thermal zone has too many trips
\n
"
);
return
-
E2BIG
;
}
/* set alert temperatures */
for
(
i
=
0
;
i
<
ntrips
;
i
++
)
{
if
(
trips
[
i
].
type
==
THERMAL_TRIP_CRITICAL
&&
trips
[
i
].
temperature
<
crit_temp
)
crit_temp
=
trips
[
i
].
temperature
;
uniphier_tm_set_alert
(
tdev
,
i
,
trips
[
i
].
temperature
);
tdev
->
alert_en
[
i
]
=
true
;
}
if
(
crit_temp
>
CRITICAL_TEMP_LIMIT
)
{
dev_err
(
dev
,
"critical trip is over limit(>%d), or not set
\n
"
,
CRITICAL_TEMP_LIMIT
);
return
-
EINVAL
;
}
uniphier_tm_enable_sensor
(
tdev
);
return
0
;
}
static
int
uniphier_tm_remove
(
struct
platform_device
*
pdev
)
{
struct
uniphier_tm_dev
*
tdev
=
platform_get_drvdata
(
pdev
);
/* disable sensor */
uniphier_tm_disable_sensor
(
tdev
);
return
0
;
}
static
const
struct
uniphier_tm_soc_data
uniphier_pxs2_tm_data
=
{
.
map_base
=
0xe000
,
.
block_base
=
0xe000
,
.
tmod_setup_addr
=
0xe904
,
};
static
const
struct
uniphier_tm_soc_data
uniphier_ld20_tm_data
=
{
.
map_base
=
0xe000
,
.
block_base
=
0xe800
,
.
tmod_setup_addr
=
0xe938
,
};
static
const
struct
of_device_id
uniphier_tm_dt_ids
[]
=
{
{
.
compatible
=
"socionext,uniphier-pxs2-thermal"
,
.
data
=
&
uniphier_pxs2_tm_data
,
},
{
.
compatible
=
"socionext,uniphier-ld20-thermal"
,
.
data
=
&
uniphier_ld20_tm_data
,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
uniphier_tm_dt_ids
);
static
struct
platform_driver
uniphier_tm_driver
=
{
.
probe
=
uniphier_tm_probe
,
.
remove
=
uniphier_tm_remove
,
.
driver
=
{
.
name
=
"uniphier-thermal"
,
.
of_match_table
=
uniphier_tm_dt_ids
,
},
};
module_platform_driver
(
uniphier_tm_driver
);
MODULE_AUTHOR
(
"Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"
);
MODULE_DESCRIPTION
(
"UniPhier thermal driver"
);
MODULE_LICENSE
(
"GPL v2"
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录