Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
00211025
Commit
00211025
authored
May 06, 2024
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge back thermal cotntrol material for v6.10.
parents
d351eb0a
e1242ff0
Changes
34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
1084 additions
and
517 deletions
+1084
-517
Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
...entation/devicetree/bindings/thermal/amlogic,thermal.yaml
+7
-5
Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
...on/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
+22
-2
Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
...on/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
+6
-0
Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
+8
-4
Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml
...ation/devicetree/bindings/thermal/st,stih407-thermal.yaml
+58
-0
Documentation/devicetree/bindings/thermal/st-thermal.txt
Documentation/devicetree/bindings/thermal/st-thermal.txt
+0
-32
drivers/thermal/amlogic_thermal.c
drivers/thermal/amlogic_thermal.c
+10
-0
drivers/thermal/armada_thermal.c
drivers/thermal/armada_thermal.c
+2
-7
drivers/thermal/gov_fair_share.c
drivers/thermal/gov_fair_share.c
+5
-2
drivers/thermal/gov_power_allocator.c
drivers/thermal/gov_power_allocator.c
+4
-2
drivers/thermal/gov_step_wise.c
drivers/thermal/gov_step_wise.c
+16
-25
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
+2
-2
drivers/thermal/intel/intel_hfi.c
drivers/thermal/intel/intel_hfi.c
+89
-8
drivers/thermal/k3_bandgap.c
drivers/thermal/k3_bandgap.c
+0
-1
drivers/thermal/loongson2_thermal.c
drivers/thermal/loongson2_thermal.c
+79
-38
drivers/thermal/mediatek/lvts_thermal.c
drivers/thermal/mediatek/lvts_thermal.c
+320
-118
drivers/thermal/qcom/lmh.c
drivers/thermal/qcom/lmh.c
+3
-0
drivers/thermal/qcom/qcom-spmi-temp-alarm.c
drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+0
-1
drivers/thermal/qcom/tsens-v2.c
drivers/thermal/qcom/tsens-v2.c
+1
-0
drivers/thermal/qcom/tsens.c
drivers/thermal/qcom/tsens.c
+32
-1
drivers/thermal/qcom/tsens.h
drivers/thermal/qcom/tsens.h
+5
-0
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/rcar_gen3_thermal.c
+88
-77
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.c
+75
-43
drivers/thermal/thermal_core.h
drivers/thermal/thermal_core.h
+117
-2
drivers/thermal/thermal_debugfs.c
drivers/thermal/thermal_debugfs.c
+4
-2
drivers/thermal/thermal_helpers.c
drivers/thermal/thermal_helpers.c
+5
-3
drivers/thermal/thermal_netlink.c
drivers/thermal/thermal_netlink.c
+50
-18
drivers/thermal/thermal_netlink.h
drivers/thermal/thermal_netlink.h
+26
-0
drivers/thermal/thermal_sysfs.c
drivers/thermal/thermal_sysfs.c
+10
-10
drivers/thermal/thermal_trace.h
drivers/thermal/thermal_trace.h
+2
-0
drivers/thermal/thermal_trace_ipa.h
drivers/thermal/thermal_trace_ipa.h
+2
-0
drivers/thermal/thermal_trip.c
drivers/thermal/thermal_trip.c
+8
-7
include/dt-bindings/thermal/mediatek,lvts-thermal.h
include/dt-bindings/thermal/mediatek,lvts-thermal.h
+26
-0
include/linux/thermal.h
include/linux/thermal.h
+2
-107
No files found.
Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
View file @
00211025
...
...
@@ -13,11 +13,13 @@ description: Binding for Amlogic Thermal
properties
:
compatible
:
items
:
-
enum
:
-
amlogic,g12a-cpu-thermal
-
amlogic,g12a-ddr-thermal
-
const
:
amlogic,g12a-thermal
oneOf
:
-
items
:
-
enum
:
-
amlogic,g12a-cpu-thermal
-
amlogic,g12a-ddr-thermal
-
const
:
amlogic,g12a-thermal
-
const
:
amlogic,a1-cpu-thermal
reg
:
maxItems
:
1
...
...
Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
View file @
00211025
...
...
@@ -18,13 +18,15 @@ properties:
oneOf
:
-
enum
:
-
loongson,ls2k1000-thermal
-
loongson,ls2k2000-thermal
-
items
:
-
enum
:
-
loongson,ls2k
20
00-thermal
-
loongson,ls2k
05
00-thermal
-
const
:
loongson,ls2k1000-thermal
reg
:
maxItems
:
1
minItems
:
1
maxItems
:
2
interrupts
:
maxItems
:
1
...
...
@@ -38,6 +40,24 @@ required:
-
interrupts
-
'
#thermal-sensor-cells'
if
:
properties
:
compatible
:
contains
:
enum
:
-
loongson,ls2k2000-thermal
then
:
properties
:
reg
:
minItems
:
2
maxItems
:
2
else
:
properties
:
reg
:
maxItems
:
1
unevaluatedProperties
:
false
examples
:
...
...
Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
View file @
00211025
...
...
@@ -19,6 +19,9 @@ properties:
compatible
:
enum
:
-
mediatek,mt7988-lvts-ap
-
mediatek,mt8186-lvts
-
mediatek,mt8188-lvts-ap
-
mediatek,mt8188-lvts-mcu
-
mediatek,mt8192-lvts-ap
-
mediatek,mt8192-lvts-mcu
-
mediatek,mt8195-lvts-ap
...
...
@@ -60,6 +63,8 @@ allOf:
compatible
:
contains
:
enum
:
-
mediatek,mt8188-lvts-ap
-
mediatek,mt8188-lvts-mcu
-
mediatek,mt8192-lvts-ap
-
mediatek,mt8192-lvts-mcu
then
:
...
...
@@ -75,6 +80,7 @@ allOf:
compatible
:
contains
:
enum
:
-
mediatek,mt8186-lvts
-
mediatek,mt8195-lvts-ap
-
mediatek,mt8195-lvts-mcu
then
:
...
...
Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
View file @
00211025
...
...
@@ -17,10 +17,14 @@ description:
properties
:
compatible
:
enum
:
-
qcom,sc8180x-lmh
-
qcom,sdm845-lmh
-
qcom,sm8150-lmh
oneOf
:
-
enum
:
-
qcom,sc8180x-lmh
-
qcom,sdm845-lmh
-
qcom,sm8150-lmh
-
items
:
-
const
:
qcom,qcm2290-lmh
-
const
:
qcom,sm8150-lmh
reg
:
items
:
...
...
Documentation/devicetree/bindings/thermal/st,stih407-thermal.yaml
0 → 100644
View file @
00211025
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML
1.2
---
$id
:
http://devicetree.org/schemas/thermal/st,stih407-thermal.yaml#
$schema
:
http://devicetree.org/meta-schemas/core.yaml#
title
:
STMicroelectronics STi digital thermal sensor (DTS)
maintainers
:
-
Patrice Chotard <patrice.chotard@foss.st.com>
-
Lee Jones <lee@kernel.org>
allOf
:
-
$ref
:
thermal-sensor.yaml
properties
:
compatible
:
const
:
st,stih407-thermal
reg
:
maxItems
:
1
clocks
:
maxItems
:
1
clock-names
:
items
:
-
const
:
thermal
interrupts
:
description
:
For thermal sensors for which no interrupt has been defined, a polling
delay of 1000ms will be used to read the temperature from device.
maxItems
:
1
'
#thermal-sensor-cells'
:
const
:
0
required
:
-
compatible
-
reg
-
clocks
-
clock-names
unevaluatedProperties
:
false
examples
:
-
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
temperature-sensor@91a0000 {
compatible = "st,stih407-thermal";
reg = <0x91a0000 0x28>;
clock-names = "thermal";
clocks = <&CLK_SYSIN>;
interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
#thermal-sensor-cells = <0>;
};
...
Documentation/devicetree/bindings/thermal/st-thermal.txt
deleted
100644 → 0
View file @
d351eb0a
Binding for Thermal Sensor driver for STMicroelectronics STi series of SoCs.
Required parameters:
-------------------
compatible : Should be "st,stih407-thermal"
clock-names : Should be "thermal".
See: Documentation/devicetree/bindings/resource-names.txt
clocks : Phandle of the clock used by the thermal sensor.
See: Documentation/devicetree/bindings/clock/clock-bindings.txt
Optional parameters:
-------------------
reg : For non-sysconf based sensors, this should be the physical base
address and length of the sensor's registers.
interrupts : Standard way to define interrupt number.
NB: For thermal sensor's for which no interrupt has been
defined, a polling delay of 1000ms will be used to read the
temperature from device.
Example:
temp0@91a0000 {
compatible = "st,stih407-thermal";
reg = <0x91a0000 0x28>;
clock-names = "thermal";
clocks = <&CLK_SYSIN>;
interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
st,passive_cooling_temp = <110>;
};
drivers/thermal/amlogic_thermal.c
View file @
00211025
...
...
@@ -220,6 +220,12 @@ static const struct amlogic_thermal_data amlogic_thermal_g12a_ddr_param = {
.
regmap_config
=
&
amlogic_thermal_regmap_config_g12a
,
};
static
const
struct
amlogic_thermal_data
amlogic_thermal_a1_cpu_param
=
{
.
u_efuse_off
=
0x114
,
.
calibration_parameters
=
&
amlogic_thermal_g12a
,
.
regmap_config
=
&
amlogic_thermal_regmap_config_g12a
,
};
static
const
struct
of_device_id
of_amlogic_thermal_match
[]
=
{
{
.
compatible
=
"amlogic,g12a-ddr-thermal"
,
...
...
@@ -229,6 +235,10 @@ static const struct of_device_id of_amlogic_thermal_match[] = {
.
compatible
=
"amlogic,g12a-cpu-thermal"
,
.
data
=
&
amlogic_thermal_g12a_cpu_param
,
},
{
.
compatible
=
"amlogic,a1-cpu-thermal"
,
.
data
=
&
amlogic_thermal_a1_cpu_param
,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE
(
of
,
of_amlogic_thermal_match
);
...
...
drivers/thermal/armada_thermal.c
View file @
00211025
...
...
@@ -763,7 +763,6 @@ static void armada_set_sane_name(struct platform_device *pdev,
struct
armada_thermal_priv
*
priv
)
{
const
char
*
name
=
dev_name
(
&
pdev
->
dev
);
char
*
insane_char
;
if
(
strlen
(
name
)
>
THERMAL_NAME_LENGTH
)
{
/*
...
...
@@ -781,12 +780,8 @@ static void armada_set_sane_name(struct platform_device *pdev,
/* Save the name locally */
strscpy
(
priv
->
zone_name
,
name
,
THERMAL_NAME_LENGTH
);
/* Then check there are no '-' or hwmon core will complain */
do
{
insane_char
=
strpbrk
(
priv
->
zone_name
,
"-"
);
if
(
insane_char
)
*
insane_char
=
'_'
;
}
while
(
insane_char
);
/* Then ensure there are no '-' or hwmon core will complain */
strreplace
(
priv
->
zone_name
,
'-'
,
'_'
);
}
/*
...
...
drivers/thermal/gov_fair_share.c
View file @
00211025
...
...
@@ -17,10 +17,13 @@
static
int
get_trip_level
(
struct
thermal_zone_device
*
tz
)
{
const
struct
thermal_trip
*
trip
,
*
level_trip
=
NULL
;
const
struct
thermal_trip
*
level_trip
=
NULL
;
const
struct
thermal_trip_desc
*
td
;
int
trip_level
=
-
1
;
for_each_trip
(
tz
,
trip
)
{
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
if
(
trip
->
temperature
>=
tz
->
temperature
)
continue
;
...
...
drivers/thermal/gov_power_allocator.c
View file @
00211025
...
...
@@ -496,9 +496,11 @@ static void get_governor_trips(struct thermal_zone_device *tz,
const
struct
thermal_trip
*
first_passive
=
NULL
;
const
struct
thermal_trip
*
last_passive
=
NULL
;
const
struct
thermal_trip
*
last_active
=
NULL
;
const
struct
thermal_trip
*
trip
;
const
struct
thermal_trip_desc
*
td
;
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
for_each_trip
(
tz
,
trip
)
{
switch
(
trip
->
type
)
{
case
THERMAL_TRIP_PASSIVE
:
if
(
!
first_passive
)
{
...
...
drivers/thermal/gov_step_wise.c
View file @
00211025
...
...
@@ -32,7 +32,6 @@ static unsigned long get_target_state(struct thermal_instance *instance,
{
struct
thermal_cooling_device
*
cdev
=
instance
->
cdev
;
unsigned
long
cur_state
;
unsigned
long
next_target
;
/*
* We keep this instance the way it is by default.
...
...
@@ -40,32 +39,26 @@ static unsigned long get_target_state(struct thermal_instance *instance,
* cdev in use to determine the next_target.
*/
cdev
->
ops
->
get_cur_state
(
cdev
,
&
cur_state
);
next_target
=
instance
->
target
;
dev_dbg
(
&
cdev
->
device
,
"cur_state=%ld
\n
"
,
cur_state
);
if
(
!
instance
->
initialized
)
{
if
(
throttle
)
{
next_target
=
clamp
((
cur_state
+
1
),
instance
->
lower
,
instance
->
upper
);
}
else
{
next_target
=
THERMAL_NO_TARGET
;
}
if
(
throttle
)
return
clamp
(
cur_state
+
1
,
instance
->
lower
,
instance
->
upper
);
return
next_target
;
return
THERMAL_NO_TARGET
;
}
if
(
throttle
)
{
if
(
trend
==
THERMAL_TREND_RAISING
)
next_target
=
clamp
((
cur_state
+
1
),
instance
->
lower
,
instance
->
upper
);
}
else
{
if
(
trend
==
THERMAL_TREND_DROPPING
)
{
if
(
cur_state
<=
instance
->
lower
)
next_target
=
THERMAL_NO_TARGET
;
else
next_target
=
clamp
((
cur_state
-
1
),
instance
->
lower
,
instance
->
upper
);
}
return
clamp
(
cur_state
+
1
,
instance
->
lower
,
instance
->
upper
);
}
else
if
(
trend
==
THERMAL_TREND_DROPPING
)
{
if
(
cur_state
<=
instance
->
lower
)
return
THERMAL_NO_TARGET
;
return
clamp
(
cur_state
-
1
,
instance
->
lower
,
instance
->
upper
);
}
return
next_
target
;
return
instance
->
target
;
}
static
void
thermal_zone_trip_update
(
struct
thermal_zone_device
*
tz
,
...
...
@@ -99,15 +92,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
if
(
instance
->
initialized
&&
old_target
==
instance
->
target
)
continue
;
if
(
old_target
==
THERMAL_NO_TARGET
&&
instance
->
target
!=
THERMAL_NO_TARGET
)
{
/* Activate a passive thermal instance */
if
(
trip
->
type
==
THERMAL_TRIP_PASSIVE
)
if
(
trip
->
type
==
THERMAL_TRIP_PASSIVE
)
{
/* If needed, update the status of passive polling. */
if
(
old_target
==
THERMAL_NO_TARGET
&&
instance
->
target
!=
THERMAL_NO_TARGET
)
tz
->
passive
++
;
}
else
if
(
old_target
!=
THERMAL_NO_TARGET
&&
instance
->
target
==
THERMAL_NO_TARGET
)
{
/* Deactivate a passive thermal instance */
if
(
trip
->
type
==
THERMAL_TRIP_PASSIVE
)
else
if
(
old_target
!=
THERMAL_NO_TARGET
&&
instance
->
target
==
THERMAL_NO_TARGET
)
tz
->
passive
--
;
}
...
...
drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
View file @
00211025
...
...
@@ -309,7 +309,7 @@ static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **ps
if
(
knob
->
type
==
ACPI_TYPE_STRING
)
{
memset
(
&
psvt
->
limit
,
0
,
sizeof
(
u64
));
str
ncpy
(
psvt
->
limit
.
string
,
psvt_ptr
->
limit
.
str_ptr
,
knob
->
string
.
length
);
str
scpy
(
psvt
->
limit
.
string
,
psvt_ptr
->
limit
.
str_ptr
,
ACPI_LIMIT_STR_MAX_LEN
);
}
else
{
psvt
->
limit
.
integer
=
psvt_ptr
->
limit
.
integer
;
}
...
...
@@ -468,7 +468,7 @@ static int fill_psvt(char __user *ubuf)
psvt_user
[
i
].
unlimit_coeff
=
psvts
[
i
].
unlimit_coeff
;
psvt_user
[
i
].
control_knob_type
=
psvts
[
i
].
control_knob_type
;
if
(
psvt_user
[
i
].
control_knob_type
==
ACPI_TYPE_STRING
)
str
n
cpy
(
psvt_user
[
i
].
limit
.
string
,
psvts
[
i
].
limit
.
string
,
str
s
cpy
(
psvt_user
[
i
].
limit
.
string
,
psvts
[
i
].
limit
.
string
,
ACPI_LIMIT_STR_MAX_LEN
);
else
psvt_user
[
i
].
limit
.
integer
=
psvts
[
i
].
limit
.
integer
;
...
...
drivers/thermal/intel/intel_hfi.c
View file @
00211025
...
...
@@ -159,6 +159,7 @@ struct hfi_cpu_info {
static
DEFINE_PER_CPU
(
struct
hfi_cpu_info
,
hfi_cpu_info
)
=
{
.
index
=
-
1
};
static
int
max_hfi_instances
;
static
int
hfi_clients_nr
;
static
struct
hfi_instance
*
hfi_instances
;
static
struct
hfi_features
hfi_features
;
...
...
@@ -477,8 +478,11 @@ void intel_hfi_online(unsigned int cpu)
enable:
cpumask_set_cpu
(
cpu
,
hfi_instance
->
cpus
);
/* Enable this HFI instance if this is its first online CPU. */
if
(
cpumask_weight
(
hfi_instance
->
cpus
)
==
1
)
{
/*
* Enable this HFI instance if this is its first online CPU and
* there are user-space clients of thermal events.
*/
if
(
cpumask_weight
(
hfi_instance
->
cpus
)
==
1
&&
hfi_clients_nr
>
0
)
{
hfi_set_hw_table
(
hfi_instance
);
hfi_enable
();
}
...
...
@@ -573,18 +577,33 @@ static __init int hfi_parse_features(void)
return
0
;
}
static
void
hfi_do_enable
(
void
)
/*
* If concurrency is not prevented by other means, the HFI enable/disable
* routines must be called under hfi_instance_lock."
*/
static
void
hfi_enable_instance
(
void
*
ptr
)
{
hfi_set_hw_table
(
ptr
);
hfi_enable
();
}
static
void
hfi_disable_instance
(
void
*
ptr
)
{
hfi_disable
();
}
static
void
hfi_syscore_resume
(
void
)
{
/* This code runs only on the boot CPU. */
struct
hfi_cpu_info
*
info
=
&
per_cpu
(
hfi_cpu_info
,
0
);
struct
hfi_instance
*
hfi_instance
=
info
->
hfi_instance
;
/* No locking needed. There is no concurrency with CPU online. */
hfi_set_hw_table
(
hfi_instance
);
hfi_enable
(
);
if
(
hfi_clients_nr
>
0
)
hfi_enable_instance
(
hfi_instance
);
}
static
int
hfi_
do_disable
(
void
)
static
int
hfi_
syscore_suspend
(
void
)
{
/* No locking needed. There is no concurrency with CPU offline. */
hfi_disable
();
...
...
@@ -593,8 +612,58 @@ static int hfi_do_disable(void)
}
static
struct
syscore_ops
hfi_pm_ops
=
{
.
resume
=
hfi_do_enable
,
.
suspend
=
hfi_do_disable
,
.
resume
=
hfi_syscore_resume
,
.
suspend
=
hfi_syscore_suspend
,
};
static
int
hfi_thermal_notify
(
struct
notifier_block
*
nb
,
unsigned
long
state
,
void
*
_notify
)
{
struct
thermal_genl_notify
*
notify
=
_notify
;
struct
hfi_instance
*
hfi_instance
;
smp_call_func_t
func
=
NULL
;
unsigned
int
cpu
;
int
i
;
if
(
notify
->
mcgrp
!=
THERMAL_GENL_EVENT_GROUP
)
return
NOTIFY_DONE
;
if
(
state
!=
THERMAL_NOTIFY_BIND
&&
state
!=
THERMAL_NOTIFY_UNBIND
)
return
NOTIFY_DONE
;
mutex_lock
(
&
hfi_instance_lock
);
switch
(
state
)
{
case
THERMAL_NOTIFY_BIND
:
if
(
++
hfi_clients_nr
==
1
)
func
=
hfi_enable_instance
;
break
;
case
THERMAL_NOTIFY_UNBIND
:
if
(
--
hfi_clients_nr
==
0
)
func
=
hfi_disable_instance
;
break
;
}
if
(
!
func
)
goto
out
;
for
(
i
=
0
;
i
<
max_hfi_instances
;
i
++
)
{
hfi_instance
=
&
hfi_instances
[
i
];
if
(
cpumask_empty
(
hfi_instance
->
cpus
))
continue
;
cpu
=
cpumask_any
(
hfi_instance
->
cpus
);
smp_call_function_single
(
cpu
,
func
,
hfi_instance
,
true
);
}
out:
mutex_unlock
(
&
hfi_instance_lock
);
return
NOTIFY_OK
;
}
static
struct
notifier_block
hfi_thermal_nb
=
{
.
notifier_call
=
hfi_thermal_notify
,
};
void
__init
intel_hfi_init
(
void
)
...
...
@@ -628,10 +697,22 @@ void __init intel_hfi_init(void)
if
(
!
hfi_updates_wq
)
goto
err_nomem
;
/*
* Both thermal core and Intel HFI can not be build as modules.
* As kernel build-in drivers they are initialized before user-space
* starts, hence we can not miss BIND/UNBIND events when applications
* add/remove thermal multicast group to/from a netlink socket.
*/
if
(
thermal_genl_register_notifier
(
&
hfi_thermal_nb
))
goto
err_nl_notif
;
register_syscore_ops
(
&
hfi_pm_ops
);
return
;
err_nl_notif:
destroy_workqueue
(
hfi_updates_wq
);
err_nomem:
for
(
j
=
0
;
j
<
i
;
++
j
)
{
hfi_instance
=
&
hfi_instances
[
j
];
...
...
drivers/thermal/k3_bandgap.c
View file @
00211025
...
...
@@ -78,7 +78,6 @@ static const int k3_adc_to_temp[] = {
struct
k3_bandgap
{
void
__iomem
*
base
;
const
struct
k3_bandgap_data
*
conf
;
};
/* common data structures */
...
...
drivers/thermal/loongson2_thermal.c
View file @
00211025
...
...
@@ -14,58 +14,81 @@
#include <linux/property.h>
#include <linux/thermal.h>
#include <linux/units.h>
#include "thermal_hwmon.h"
#define LOONGSON2_MAX_SENSOR_SEL_NUM 3
#define LOONGSON2_MAX_SENSOR_SEL_NUM 3
#define LOONGSON2_THSENS_CTRL_HI_REG 0x0
#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8
#define LOONGSON2_THSENS_STATUS_REG 0x10
#define LOONGSON2_THSENS_OUT_REG 0x14
#define LOONGSON2_THSENS_CTRL_HI_REG 0x0
#define LOONGSON2_THSENS_CTRL_LOW_REG 0x8
#define LOONGSON2_THSENS_STATUS_REG 0x10
#define LOONGSON2_THSENS_OUT_REG 0x14
#define LOONGSON2_THSENS_INT_LO BIT(0)
#define LOONGSON2_THSENS_INT_HIGH BIT(1)
#define LOONGSON2_THSENS_INT_EN (LOONGSON2_THSENS_INT_LO | \
LOONGSON2_THSENS_INT_HIGH)
#define LOONGSON2_THSENS_OUT_MASK 0xFF
#define LOONGSON2_THSENS_INT_LO BIT(0)
#define LOONGSON2_THSENS_INT_HIGH BIT(1)
#define LOONGSON2_THSENS_OUT_MASK 0xFF
/*
* This flag is used to indicate the temperature reading
* method of the Loongson-2K2000
*/
#define LS2K2000_THSENS_OUT_FLAG BIT(0)
struct
loongson2_thermal_chip_data
{
unsigned
int
thermal_sensor_sel
;
unsigned
int
thermal_sensor_sel
;
unsigned
int
flags
;
};
struct
loongson2_thermal_data
{
void
__iomem
*
regs
;
void
__iomem
*
ctrl_reg
;
void
__iomem
*
temp_reg
;
const
struct
loongson2_thermal_chip_data
*
chip_data
;
};
static
void
loongson2_set_ctrl_regs
(
struct
loongson2_thermal_data
*
data
,
int
ctrl_data
,
bool
low
,
bool
enable
)
{
int
reg_ctrl
=
0
;
int
reg_off
=
data
->
chip_data
->
thermal_sensor_sel
*
2
;
int
ctrl_reg
=
low
?
LOONGSON2_THSENS_CTRL_LOW_REG
:
LOONGSON2_THSENS_CTRL_HI_REG
;
reg_ctrl
=
ctrl_data
+
HECTO
;
reg_ctrl
|=
enable
?
0x100
:
0
;
writew
(
reg_ctrl
,
data
->
ctrl_reg
+
ctrl_reg
+
reg_off
);
}
static
int
loongson2_thermal_set
(
struct
loongson2_thermal_data
*
data
,
int
low
,
int
high
,
bool
enable
)
int
low
,
int
high
,
bool
enable
)
{
u64
reg_ctrl
=
0
;
int
reg_off
=
data
->
chip_data
->
thermal_sensor_sel
*
2
;
/* Set low temperature threshold */
loongson2_set_ctrl_regs
(
data
,
clamp
(
-
40
,
low
,
high
),
true
,
enable
)
;
low
=
clamp
(
-
40
,
low
,
high
);
high
=
clamp
(
125
,
low
,
high
);
/* Set high temperature threshold */
loongson2_set_ctrl_regs
(
data
,
clamp
(
125
,
low
,
high
),
false
,
enable
);
low
+=
HECTO
;
high
+=
HECTO
;
return
0
;
}
reg_ctrl
=
low
;
reg_ctrl
|=
enable
?
0x100
:
0
;
writew
(
reg_ctrl
,
data
->
regs
+
LOONGSON2_THSENS_CTRL_LOW_REG
+
reg_off
);
static
int
loongson2_2k1000_get_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
{
int
val
;
struct
loongson2_thermal_data
*
data
=
thermal_zone_device_priv
(
tz
);
reg_ctrl
=
high
;
reg_ctrl
|=
enable
?
0x100
:
0
;
writew
(
reg_ctrl
,
data
->
regs
+
LOONGSON2_THSENS_CTRL_HI_REG
+
reg_off
);
val
=
readl
(
data
->
ctrl_reg
+
LOONGSON2_THSENS_OUT_REG
);
*
temp
=
((
val
&
LOONGSON2_THSENS_OUT_MASK
)
-
HECTO
)
*
KILO
;
return
0
;
}
static
int
loongson2_
thermal
_get_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
static
int
loongson2_
2k2000
_get_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
{
u32
reg_
val
;
int
val
;
struct
loongson2_thermal_data
*
data
=
thermal_zone_device_priv
(
tz
);
reg_val
=
readl
(
data
->
regs
+
LOONGSON2_THSENS_OUT_REG
);
*
temp
=
((
reg_val
&
LOONGSON2_THSENS_OUT_MASK
)
-
HECTO
)
*
KILO
;
val
=
readl
(
data
->
temp_reg
);
*
temp
=
((
val
&
0xffff
)
*
820
/
0x4000
-
311
)
*
KILO
;
return
0
;
}
...
...
@@ -75,8 +98,7 @@ static irqreturn_t loongson2_thermal_irq_thread(int irq, void *dev)
struct
thermal_zone_device
*
tzd
=
dev
;
struct
loongson2_thermal_data
*
data
=
thermal_zone_device_priv
(
tzd
);
writeb
(
LOONGSON2_THSENS_INT_LO
|
LOONGSON2_THSENS_INT_HIGH
,
data
->
regs
+
LOONGSON2_THSENS_STATUS_REG
);
writeb
(
LOONGSON2_THSENS_INT_EN
,
data
->
ctrl_reg
+
LOONGSON2_THSENS_STATUS_REG
);
thermal_zone_device_update
(
tzd
,
THERMAL_EVENT_UNSPECIFIED
);
...
...
@@ -90,8 +112,8 @@ static int loongson2_thermal_set_trips(struct thermal_zone_device *tz, int low,
return
loongson2_thermal_set
(
data
,
low
/
MILLI
,
high
/
MILLI
,
true
);
}
static
const
struct
thermal_zone_device_ops
loongson2_of_thermal_ops
=
{
.
get_temp
=
loongson2_
thermal
_get_temp
,
static
struct
thermal_zone_device_ops
loongson2_of_thermal_ops
=
{
.
get_temp
=
loongson2_
2k1000
_get_temp
,
.
set_trips
=
loongson2_thermal_set_trips
,
};
...
...
@@ -108,22 +130,30 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
data
->
chip_data
=
device_get_match_data
(
dev
);
data
->
regs
=
devm_platform_ioremap_resource
(
pdev
,
0
);
if
(
IS_ERR
(
data
->
regs
))
return
PTR_ERR
(
data
->
regs
);
data
->
ctrl_reg
=
devm_platform_ioremap_resource
(
pdev
,
0
);
if
(
IS_ERR
(
data
->
ctrl_reg
))
return
PTR_ERR
(
data
->
ctrl_reg
);
/* The temperature output register is separate for Loongson-2K2000 */
if
(
data
->
chip_data
->
flags
&
LS2K2000_THSENS_OUT_FLAG
)
{
data
->
temp_reg
=
devm_platform_ioremap_resource
(
pdev
,
1
);
if
(
IS_ERR
(
data
->
temp_reg
))
return
PTR_ERR
(
data
->
temp_reg
);
loongson2_of_thermal_ops
.
get_temp
=
loongson2_2k2000_get_temp
;
}
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
return
irq
;
writeb
(
LOONGSON2_THSENS_INT_LO
|
LOONGSON2_THSENS_INT_HIGH
,
data
->
regs
+
LOONGSON2_THSENS_STATUS_REG
);
writeb
(
LOONGSON2_THSENS_INT_EN
,
data
->
ctrl_reg
+
LOONGSON2_THSENS_STATUS_REG
);
loongson2_thermal_set
(
data
,
0
,
0
,
false
);
for
(
i
=
0
;
i
<=
LOONGSON2_MAX_SENSOR_SEL_NUM
;
i
++
)
{
tzd
=
devm_thermal_of_zone_register
(
dev
,
i
,
data
,
&
loongson2_of_thermal_ops
);
&
loongson2_of_thermal_ops
);
if
(
!
IS_ERR
(
tzd
))
break
;
...
...
@@ -135,7 +165,7 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
}
ret
=
devm_request_threaded_irq
(
dev
,
irq
,
NULL
,
loongson2_thermal_irq_thread
,
IRQF_ONESHOT
,
"loongson2_thermal"
,
tzd
);
IRQF_ONESHOT
,
"loongson2_thermal"
,
tzd
);
if
(
ret
<
0
)
return
dev_err_probe
(
dev
,
ret
,
"failed to request alarm irq
\n
"
);
...
...
@@ -146,6 +176,12 @@ static int loongson2_thermal_probe(struct platform_device *pdev)
static
const
struct
loongson2_thermal_chip_data
loongson2_thermal_ls2k1000_data
=
{
.
thermal_sensor_sel
=
0
,
.
flags
=
0
,
};
static
const
struct
loongson2_thermal_chip_data
loongson2_thermal_ls2k2000_data
=
{
.
thermal_sensor_sel
=
0
,
.
flags
=
LS2K2000_THSENS_OUT_FLAG
,
};
static
const
struct
of_device_id
of_loongson2_thermal_match
[]
=
{
...
...
@@ -153,6 +189,10 @@ static const struct of_device_id of_loongson2_thermal_match[] = {
.
compatible
=
"loongson,ls2k1000-thermal"
,
.
data
=
&
loongson2_thermal_ls2k1000_data
,
},
{
.
compatible
=
"loongson,ls2k2000-thermal"
,
.
data
=
&
loongson2_thermal_ls2k2000_data
,
},
{
/* end */
}
};
MODULE_DEVICE_TABLE
(
of
,
of_loongson2_thermal_match
);
...
...
@@ -167,4 +207,5 @@ static struct platform_driver loongson2_thermal_driver = {
module_platform_driver
(
loongson2_thermal_driver
);
MODULE_DESCRIPTION
(
"Loongson2 thermal driver"
);
MODULE_AUTHOR
(
"Loongson Technology Corporation Limited"
);
MODULE_LICENSE
(
"GPL"
);
drivers/thermal/mediatek/lvts_thermal.c
View file @
00211025
This diff is collapsed.
Click to expand it.
drivers/thermal/qcom/lmh.c
View file @
00211025
...
...
@@ -95,6 +95,9 @@ static int lmh_probe(struct platform_device *pdev)
unsigned
int
enable_alg
;
u32
node_id
;
if
(
!
qcom_scm_is_available
())
return
-
EPROBE_DEFER
;
lmh_data
=
devm_kzalloc
(
dev
,
sizeof
(
*
lmh_data
),
GFP_KERNEL
);
if
(
!
lmh_data
)
return
-
ENOMEM
;
...
...
drivers/thermal/qcom/qcom-spmi-temp-alarm.c
View file @
00211025
...
...
@@ -74,7 +74,6 @@ struct qpnp_tm_chip {
long
temp
;
unsigned
int
thresh
;
unsigned
int
stage
;
unsigned
int
prev_stage
;
unsigned
int
base
;
/* protects .thresh, .stage and chip registers */
struct
mutex
lock
;
...
...
drivers/thermal/qcom/tsens-v2.c
View file @
00211025
...
...
@@ -107,6 +107,7 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
static
const
struct
tsens_ops
ops_generic_v2
=
{
.
init
=
init_common
,
.
get_temp
=
get_temp_tsens_valid
,
.
resume
=
tsens_resume_common
,
};
struct
tsens_plat_data
data_tsens_v2
=
{
...
...
drivers/thermal/qcom/tsens.c
View file @
00211025
...
...
@@ -17,6 +17,7 @@
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/thermal.h>
#include "../thermal_hwmon.h"
#include "tsens.h"
...
...
@@ -264,7 +265,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
for
(
i
=
0
;
i
<
priv
->
num_sensors
;
i
++
)
{
dev_dbg
(
priv
->
dev
,
"%s: sensor%d - data_point1:%#x data_point2:%#x
\n
"
,
__func__
,
i
,
p1
[
i
],
p2
[
i
]
);
__func__
,
i
,
p1
[
i
],
p2
?
p2
[
i
]
:
0
);
if
(
!
priv
->
sensor
[
i
].
slope
)
priv
->
sensor
[
i
].
slope
=
SLOPE_DEFAULT
;
...
...
@@ -1193,6 +1194,36 @@ static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
return
ret
;
}
#ifdef CONFIG_SUSPEND
static
int
tsens_reinit
(
struct
tsens_priv
*
priv
)
{
if
(
tsens_version
(
priv
)
>=
VER_2_X
)
{
/*
* Re-enable the watchdog, unmask the bark.
* Disable cycle completion monitoring
*/
if
(
priv
->
feat
->
has_watchdog
)
{
regmap_field_write
(
priv
->
rf
[
WDOG_BARK_MASK
],
0
);
regmap_field_write
(
priv
->
rf
[
CC_MON_MASK
],
1
);
}
/* Re-enable interrupts */
tsens_enable_irq
(
priv
);
}
return
0
;
}
int
tsens_resume_common
(
struct
tsens_priv
*
priv
)
{
if
(
pm_suspend_target_state
==
PM_SUSPEND_MEM
)
tsens_reinit
(
priv
);
return
0
;
}
#endif
/* !CONFIG_SUSPEND */
static
int
tsens_register
(
struct
tsens_priv
*
priv
)
{
int
i
,
ret
;
...
...
drivers/thermal/qcom/tsens.h
View file @
00211025
...
...
@@ -634,6 +634,11 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mo
int
init_common
(
struct
tsens_priv
*
priv
);
int
get_temp_tsens_valid
(
const
struct
tsens_sensor
*
s
,
int
*
temp
);
int
get_temp_common
(
const
struct
tsens_sensor
*
s
,
int
*
temp
);
#ifdef CONFIG_SUSPEND
int
tsens_resume_common
(
struct
tsens_priv
*
priv
);
#else
#define tsens_resume_common NULL
#endif
/* TSENS target */
extern
struct
tsens_plat_data
data_8960
;
...
...
drivers/thermal/rcar_gen3_thermal.c
View file @
00211025
...
...
@@ -65,26 +65,29 @@
#define TSC_MAX_NUM 5
/* Structure for thermal temperature calculation */
struct
equation_coefs
{
int
a1
;
int
b1
;
int
a2
;
int
b2
;
};
struct
rcar_gen3_thermal_priv
;
struct
rcar_thermal_info
{
int
ths_tj_1
;
int
scale
;
int
adj_below
;
int
adj_above
;
void
(
*
read_fuses
)(
struct
rcar_gen3_thermal_priv
*
priv
);
};
struct
equation_set_coef
{
int
a
;
int
b
;
};
struct
rcar_gen3_thermal_tsc
{
struct
rcar_gen3_thermal_priv
*
priv
;
void
__iomem
*
base
;
struct
thermal_zone_device
*
zone
;
struct
equation_coefs
coef
;
int
tj_t
;
/* Different coefficients are used depending on a threshold. */
struct
{
struct
equation_set_coef
below
;
struct
equation_set_coef
above
;
}
coef
;
int
thcode
[
3
];
};
...
...
@@ -93,6 +96,7 @@ struct rcar_gen3_thermal_priv {
struct
thermal_zone_device_ops
ops
;
unsigned
int
num_tscs
;
int
ptat
[
3
];
int
tj_t
;
const
struct
rcar_thermal_info
*
info
;
};
...
...
@@ -111,84 +115,75 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
/*
* Linear approximation for temperature
*
* [reg] = [temp] * a + b => [temp] = ([reg] - b) / a
* [temp] = ((thadj - [reg]) * a) / b + adj
* [reg] = thadj - ([temp] - adj) * b / a
*
* The constants a and b are calculated using two triplets of int values PTAT
* and THCODE. PTAT and THCODE can either be read from hardware or use hard
* coded values from driver. The formula to calculate a and b are taken from
* BSP and sparsely documented and understood.
* coded values from the driver. The formula to calculate a and b are taken from
* the datasheet. Different calculations are needed for a and b depending on
* if the input variables ([temp] or [reg]) are above or below a threshold. The
* threshold is also calculated from PTAT and THCODE using formulas from the
* datasheet.
*
* The constant thadj is one of the THCODE values, which one to use depends on
* the threshold and input value.
*
* Examining the linear formula and the formula used to calculate constants a
* and b while knowing that the span for PTAT and THCODE values are between
* 0x000 and 0xfff the largest integer possible is 0xfff * 0xfff == 0xffe001.
* Integer also needs to be signed so that leaves 7 bits for binary
* fixed point scaling.
* The constants adj is taken verbatim from the datasheet. Two values exists,
* which one to use depends on the input value and the calculated threshold.
* Furthermore different SoC models supported by the driver have different sets
* of values. The values for each model are stored in the device match data.
*/
#define FIXPT_SHIFT 7
#define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT)
#define INT_FIXPT(_x) ((_x) >> FIXPT_SHIFT)
#define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b))
#define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT)
#define RCAR3_THERMAL_GRAN 500
/* mili Celsius */
/* no idea where these constants come from */
#define TJ_3 -41
static
void
rcar_gen3_thermal_calc_coefs
(
struct
rcar_gen3_thermal_priv
*
priv
,
struct
rcar_gen3_thermal_tsc
*
tsc
,
int
ths_tj_1
)
static
void
rcar_gen3_thermal_shared_coefs
(
struct
rcar_gen3_thermal_priv
*
priv
)
{
/* TODO: Find documentation and document constant calculation formula */
/*
* Division is not scaled in BSP and if scaled it might overflow
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
*/
tsc
->
tj_t
=
(
FIXPT_INT
((
priv
->
ptat
[
1
]
-
priv
->
ptat
[
2
])
*
(
ths_tj_1
-
TJ_3
))
/
(
priv
->
ptat
[
0
]
-
priv
->
ptat
[
2
]))
+
FIXPT_INT
(
TJ_3
);
tsc
->
coef
.
a1
=
FIXPT_DIV
(
FIXPT_INT
(
tsc
->
thcode
[
1
]
-
tsc
->
thcode
[
2
]),
tsc
->
tj_t
-
FIXPT_INT
(
TJ_3
));
tsc
->
coef
.
b1
=
FIXPT_INT
(
tsc
->
thcode
[
2
])
-
tsc
->
coef
.
a1
*
TJ_3
;
tsc
->
coef
.
a2
=
FIXPT_DIV
(
FIXPT_INT
(
tsc
->
thcode
[
1
]
-
tsc
->
thcode
[
0
]),
tsc
->
tj_t
-
FIXPT_INT
(
ths_tj_1
));
tsc
->
coef
.
b2
=
FIXPT_INT
(
tsc
->
thcode
[
0
])
-
tsc
->
coef
.
a2
*
ths_tj_1
;
priv
->
tj_t
=
DIV_ROUND_CLOSEST
((
priv
->
ptat
[
1
]
-
priv
->
ptat
[
2
])
*
priv
->
info
->
scale
,
priv
->
ptat
[
0
]
-
priv
->
ptat
[
2
])
+
priv
->
info
->
adj_below
;
}
static
int
rcar_gen3_thermal_round
(
int
temp
)
static
void
rcar_gen3_thermal_tsc_coefs
(
struct
rcar_gen3_thermal_priv
*
priv
,
struct
rcar_gen3_thermal_tsc
*
tsc
)
{
int
result
,
round_offs
;
tsc
->
coef
.
below
.
a
=
priv
->
info
->
scale
*
(
priv
->
ptat
[
2
]
-
priv
->
ptat
[
1
]);
tsc
->
coef
.
above
.
a
=
priv
->
info
->
scale
*
(
priv
->
ptat
[
0
]
-
priv
->
ptat
[
1
]);
round_offs
=
temp
>=
0
?
RCAR3_THERMAL_GRAN
/
2
:
-
RCAR3_THERMAL_GRAN
/
2
;
result
=
(
temp
+
round_offs
)
/
RCAR3_THERMAL_GRAN
;
return
result
*
RCAR3_THERMAL_GRAN
;
tsc
->
coef
.
below
.
b
=
(
priv
->
ptat
[
2
]
-
priv
->
ptat
[
0
])
*
(
tsc
->
thcode
[
2
]
-
tsc
->
thcode
[
1
]);
tsc
->
coef
.
above
.
b
=
(
priv
->
ptat
[
0
]
-
priv
->
ptat
[
2
])
*
(
tsc
->
thcode
[
1
]
-
tsc
->
thcode
[
0
]);
}
static
int
rcar_gen3_thermal_get_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
{
struct
rcar_gen3_thermal_tsc
*
tsc
=
thermal_zone_device_priv
(
tz
);
int
mcelsius
,
val
;
int
reg
;
struct
rcar_gen3_thermal_priv
*
priv
=
tsc
->
priv
;
const
struct
equation_set_coef
*
coef
;
int
adj
,
decicelsius
,
reg
,
thcode
;
/* Read register and convert to mili Celsius */
reg
=
rcar_gen3_thermal_read
(
tsc
,
REG_GEN3_TEMP
)
&
CTEMP_MASK
;
if
(
reg
<=
tsc
->
thcode
[
1
])
val
=
FIXPT_DIV
(
FIXPT_INT
(
reg
)
-
tsc
->
coef
.
b1
,
tsc
->
coef
.
a1
);
else
val
=
FIXPT_DIV
(
FIXPT_INT
(
reg
)
-
tsc
->
coef
.
b2
,
tsc
->
coef
.
a2
);
mcelsius
=
FIXPT_TO_MCELSIUS
(
val
);
if
(
reg
<
tsc
->
thcode
[
1
])
{
adj
=
priv
->
info
->
adj_below
;
coef
=
&
tsc
->
coef
.
below
;
thcode
=
tsc
->
thcode
[
2
];
}
else
{
adj
=
priv
->
info
->
adj_above
;
coef
=
&
tsc
->
coef
.
above
;
thcode
=
tsc
->
thcode
[
0
];
}
/*
* The dividend can't be grown as it might overflow, instead shorten the
* divisor to convert to decidegree Celsius. If we convert after the
* division precision is lost as we will scale up from whole degrees
* Celsius.
*/
decicelsius
=
DIV_ROUND_CLOSEST
(
coef
->
a
*
(
thcode
-
reg
),
coef
->
b
/
10
);
/* Guaranteed operating range is -40C to 125C. */
/* R
ound value to device granularity setting
*/
*
temp
=
rcar_gen3_thermal_round
(
mcelsius
)
;
/* R
eporting is done in millidegree Celsius
*/
*
temp
=
decicelsius
*
100
+
adj
*
1000
;
return
0
;
}
...
...
@@ -196,15 +191,22 @@ static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
static
int
rcar_gen3_thermal_mcelsius_to_temp
(
struct
rcar_gen3_thermal_tsc
*
tsc
,
int
mcelsius
)
{
int
celsius
,
val
;
struct
rcar_gen3_thermal_priv
*
priv
=
tsc
->
priv
;
const
struct
equation_set_coef
*
coef
;
int
adj
,
celsius
,
thcode
;
celsius
=
DIV_ROUND_CLOSEST
(
mcelsius
,
1000
);
if
(
celsius
<=
INT_FIXPT
(
tsc
->
tj_t
))
val
=
celsius
*
tsc
->
coef
.
a1
+
tsc
->
coef
.
b1
;
else
val
=
celsius
*
tsc
->
coef
.
a2
+
tsc
->
coef
.
b2
;
if
(
celsius
<
priv
->
tj_t
)
{
coef
=
&
tsc
->
coef
.
below
;
adj
=
priv
->
info
->
adj_below
;
thcode
=
tsc
->
thcode
[
2
];
}
else
{
coef
=
&
tsc
->
coef
.
above
;
adj
=
priv
->
info
->
adj_above
;
thcode
=
tsc
->
thcode
[
0
];
}
return
INT_FIXPT
(
val
);
return
thcode
-
DIV_ROUND_CLOSEST
((
celsius
-
adj
)
*
coef
->
b
,
coef
->
a
);
}
static
int
rcar_gen3_thermal_set_trips
(
struct
thermal_zone_device
*
tz
,
int
low
,
int
high
)
...
...
@@ -369,17 +371,23 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
}
static
const
struct
rcar_thermal_info
rcar_m3w_thermal_info
=
{
.
ths_tj_1
=
116
,
.
scale
=
157
,
.
adj_below
=
-
41
,
.
adj_above
=
116
,
.
read_fuses
=
rcar_gen3_thermal_read_fuses_gen3
,
};
static
const
struct
rcar_thermal_info
rcar_gen3_thermal_info
=
{
.
ths_tj_1
=
126
,
.
scale
=
167
,
.
adj_below
=
-
41
,
.
adj_above
=
126
,
.
read_fuses
=
rcar_gen3_thermal_read_fuses_gen3
,
};
static
const
struct
rcar_thermal_info
rcar_gen4_thermal_info
=
{
.
ths_tj_1
=
126
,
.
scale
=
167
,
.
adj_below
=
-
41
,
.
adj_above
=
126
,
.
read_fuses
=
rcar_gen3_thermal_read_fuses_gen4
,
};
...
...
@@ -516,6 +524,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
goto
error_unregister
;
}
tsc
->
priv
=
priv
;
tsc
->
base
=
devm_ioremap_resource
(
dev
,
res
);
if
(
IS_ERR
(
tsc
->
base
))
{
ret
=
PTR_ERR
(
tsc
->
base
);
...
...
@@ -530,11 +539,13 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if
(
!
rcar_gen3_thermal_read_fuses
(
priv
))
dev_info
(
dev
,
"No calibration values fused, fallback to driver values
\n
"
);
rcar_gen3_thermal_shared_coefs
(
priv
);
for
(
i
=
0
;
i
<
priv
->
num_tscs
;
i
++
)
{
struct
rcar_gen3_thermal_tsc
*
tsc
=
priv
->
tscs
[
i
];
rcar_gen3_thermal_init
(
priv
,
tsc
);
rcar_gen3_thermal_
calc_coefs
(
priv
,
tsc
,
priv
->
info
->
ths_tj_1
);
rcar_gen3_thermal_
tsc_coefs
(
priv
,
tsc
);
zone
=
devm_thermal_of_zone_register
(
dev
,
i
,
tsc
,
&
priv
->
ops
);
if
(
IS_ERR
(
zone
))
{
...
...
drivers/thermal/thermal_core.c
View file @
00211025
...
...
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kdev_t.h>
#include <linux/idr.h>
#include <linux/list_sort.h>
#include <linux/thermal.h>
#include <linux/reboot.h>
#include <linux/string.h>
...
...
@@ -361,49 +362,48 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
}
static
void
handle_thermal_trip
(
struct
thermal_zone_device
*
tz
,
struct
thermal_trip
*
trip
)
struct
thermal_trip_desc
*
td
,
struct
list_head
*
way_up_list
,
struct
list_head
*
way_down_list
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
int
old_threshold
;
if
(
trip
->
temperature
==
THERMAL_TEMP_INVALID
)
return
;
if
(
tz
->
last_temperature
==
THERMAL_TEMP_INVALID
)
{
/* Initialization. */
trip
->
threshold
=
trip
->
temperature
;
if
(
tz
->
temperature
>=
trip
->
threshold
)
trip
->
threshold
-=
trip
->
hysteresis
;
}
else
if
(
tz
->
last_temperature
<
trip
->
threshold
)
{
/*
* If the trip temperature or hysteresis has been updated recently,
* the threshold needs to be computed again using the new values.
* However, its initial value still reflects the old ones and that
* is what needs to be compared with the previous zone temperature
* to decide which action to take.
*/
old_threshold
=
td
->
threshold
;
td
->
threshold
=
trip
->
temperature
;
if
(
tz
->
last_temperature
>=
old_threshold
&&
tz
->
last_temperature
!=
THERMAL_TEMP_INVALID
)
{
/*
* The trip threshold is equal to the trip temperature, unless
* the latter has changed in the meantime. In either case,
* the trip is crossed if the current zone temperature is at
* least equal to its temperature, but otherwise ensure that
* the threshold and the trip temperature will be equal.
* Mitigation is under way, so it needs to stop if the zone
* temperature falls below the low temperature of the trip.
* In that case, the trip temperature becomes the new threshold.
*/
if
(
tz
->
temperature
>=
trip
->
temperature
)
{
thermal_notify_tz_trip_up
(
tz
,
trip
);
thermal_debug_tz_trip_up
(
tz
,
trip
);
trip
->
threshold
=
trip
->
temperature
-
trip
->
hysteresis
;
if
(
tz
->
temperature
<
trip
->
temperature
-
trip
->
hysteresis
)
{
list_add
(
&
td
->
notify_list_node
,
way_down_list
);
td
->
notify_temp
=
trip
->
temperature
-
trip
->
hysteresis
;
}
else
{
t
rip
->
threshold
=
trip
->
temperature
;
t
d
->
threshold
-=
trip
->
hysteresis
;
}
}
else
{
}
else
if
(
tz
->
temperature
>=
trip
->
temperature
)
{
/*
* The previous zone temperature was above or equal to the trip
* threshold, which would be equal to the "low temperature" of
* the trip (its temperature minus its hysteresis), unless the
* trip temperature or hysteresis had changed. In either case,
* the trip is crossed if the current zone temperature is below
* the low temperature of the trip, but otherwise ensure that
* the trip threshold will be equal to the low temperature of
* the trip.
* There is no mitigation under way, so it needs to be started
* if the zone temperature exceeds the trip one. The new
* threshold is then set to the low temperature of the trip.
*/
if
(
tz
->
temperature
<
trip
->
temperature
-
trip
->
hysteresis
)
{
thermal_notify_tz_trip_down
(
tz
,
trip
);
thermal_debug_tz_trip_down
(
tz
,
trip
);
trip
->
threshold
=
trip
->
temperature
;
}
else
{
trip
->
threshold
=
trip
->
temperature
-
trip
->
hysteresis
;
}
list_add_tail
(
&
td
->
notify_list_node
,
way_up_list
);
td
->
notify_temp
=
trip
->
temperature
;
td
->
threshold
-=
trip
->
hysteresis
;
}
if
(
trip
->
type
==
THERMAL_TRIP_CRITICAL
||
trip
->
type
==
THERMAL_TRIP_HOT
)
...
...
@@ -455,10 +455,24 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
pos
->
initialized
=
false
;
}
static
int
thermal_trip_notify_cmp
(
void
*
ascending
,
const
struct
list_head
*
a
,
const
struct
list_head
*
b
)
{
struct
thermal_trip_desc
*
tda
=
container_of
(
a
,
struct
thermal_trip_desc
,
notify_list_node
);
struct
thermal_trip_desc
*
tdb
=
container_of
(
b
,
struct
thermal_trip_desc
,
notify_list_node
);
int
ret
=
tdb
->
notify_temp
-
tda
->
notify_temp
;
return
ascending
?
ret
:
-
ret
;
}
void
__thermal_zone_device_update
(
struct
thermal_zone_device
*
tz
,
enum
thermal_notify_event
event
)
{
struct
thermal_trip
*
trip
;
struct
thermal_trip_desc
*
td
;
LIST_HEAD
(
way_down_list
);
LIST_HEAD
(
way_up_list
);
if
(
tz
->
suspended
)
return
;
...
...
@@ -472,8 +486,20 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
tz
->
notify_event
=
event
;
for_each_trip
(
tz
,
trip
)
handle_thermal_trip
(
tz
,
trip
);
for_each_trip_desc
(
tz
,
td
)
handle_thermal_trip
(
tz
,
td
,
&
way_up_list
,
&
way_down_list
);
list_sort
(
&
way_up_list
,
&
way_up_list
,
thermal_trip_notify_cmp
);
list_for_each_entry
(
td
,
&
way_up_list
,
notify_list_node
)
{
thermal_notify_tz_trip_up
(
tz
,
&
td
->
trip
);
thermal_debug_tz_trip_up
(
tz
,
&
td
->
trip
);
}
list_sort
(
NULL
,
&
way_down_list
,
thermal_trip_notify_cmp
);
list_for_each_entry
(
td
,
&
way_down_list
,
notify_list_node
)
{
thermal_notify_tz_trip_down
(
tz
,
&
td
->
trip
);
thermal_debug_tz_trip_down
(
tz
,
&
td
->
trip
);
}
monitor_thermal_zone
(
tz
);
}
...
...
@@ -766,7 +792,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
if
(
trip_index
<
0
||
trip_index
>=
tz
->
num_trips
)
return
-
EINVAL
;
return
thermal_bind_cdev_to_trip
(
tz
,
&
tz
->
trips
[
trip_index
],
cdev
,
return
thermal_bind_cdev_to_trip
(
tz
,
&
tz
->
trips
[
trip_index
]
.
trip
,
cdev
,
upper
,
lower
,
weight
);
}
EXPORT_SYMBOL_GPL
(
thermal_zone_bind_cooling_device
);
...
...
@@ -825,7 +851,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
if
(
trip_index
<
0
||
trip_index
>=
tz
->
num_trips
)
return
-
EINVAL
;
return
thermal_unbind_cdev_from_trip
(
tz
,
&
tz
->
trips
[
trip_index
],
cdev
);
return
thermal_unbind_cdev_from_trip
(
tz
,
&
tz
->
trips
[
trip_index
]
.
trip
,
cdev
);
}
EXPORT_SYMBOL_GPL
(
thermal_zone_unbind_cooling_device
);
...
...
@@ -1221,16 +1247,19 @@ static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms
int
thermal_zone_get_crit_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
{
int
i
,
ret
=
-
EINVAL
;
const
struct
thermal_trip_desc
*
td
;
int
ret
=
-
EINVAL
;
if
(
tz
->
ops
.
get_crit_temp
)
return
tz
->
ops
.
get_crit_temp
(
tz
,
temp
);
mutex_lock
(
&
tz
->
lock
);
for
(
i
=
0
;
i
<
tz
->
num_trips
;
i
++
)
{
if
(
tz
->
trips
[
i
].
type
==
THERMAL_TRIP_CRITICAL
)
{
*
temp
=
tz
->
trips
[
i
].
temperature
;
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
if
(
trip
->
type
==
THERMAL_TRIP_CRITICAL
)
{
*
temp
=
trip
->
temperature
;
ret
=
0
;
break
;
}
...
...
@@ -1274,7 +1303,9 @@ thermal_zone_device_register_with_trips(const char *type,
const
struct
thermal_zone_params
*
tzp
,
int
passive_delay
,
int
polling_delay
)
{
const
struct
thermal_trip
*
trip
=
trips
;
struct
thermal_zone_device
*
tz
;
struct
thermal_trip_desc
*
td
;
int
id
;
int
result
;
struct
thermal_governor
*
governor
;
...
...
@@ -1339,7 +1370,8 @@ thermal_zone_device_register_with_trips(const char *type,
tz
->
device
.
class
=
thermal_class
;
tz
->
devdata
=
devdata
;
tz
->
num_trips
=
num_trips
;
memcpy
(
tz
->
trips
,
trips
,
num_trips
*
sizeof
(
*
trips
));
for_each_trip_desc
(
tz
,
td
)
td
->
trip
=
*
trip
++
;
thermal_set_delay_jiffies
(
&
tz
->
passive_delay_jiffies
,
passive_delay
);
thermal_set_delay_jiffies
(
&
tz
->
polling_delay_jiffies
,
polling_delay
);
...
...
drivers/thermal/thermal_core.h
View file @
00211025
...
...
@@ -15,6 +15,118 @@
#include "thermal_netlink.h"
#include "thermal_debugfs.h"
struct
thermal_trip_desc
{
struct
thermal_trip
trip
;
struct
list_head
notify_list_node
;
int
notify_temp
;
int
threshold
;
};
/**
* struct thermal_governor - structure that holds thermal governor information
* @name: name of the governor
* @bind_to_tz: callback called when binding to a thermal zone. If it
* returns 0, the governor is bound to the thermal zone,
* otherwise it fails.
* @unbind_from_tz: callback called when a governor is unbound from a
* thermal zone.
* @throttle: callback called for every trip point even if temperature is
* below the trip point temperature
* @update_tz: callback called when thermal zone internals have changed, e.g.
* thermal cooling instance was added/removed
* @governor_list: node in thermal_governor_list (in thermal_core.c)
*/
struct
thermal_governor
{
const
char
*
name
;
int
(
*
bind_to_tz
)(
struct
thermal_zone_device
*
tz
);
void
(
*
unbind_from_tz
)(
struct
thermal_zone_device
*
tz
);
int
(
*
throttle
)(
struct
thermal_zone_device
*
tz
,
const
struct
thermal_trip
*
trip
);
void
(
*
update_tz
)(
struct
thermal_zone_device
*
tz
,
enum
thermal_notify_event
reason
);
struct
list_head
governor_list
;
};
/**
* struct thermal_zone_device - structure for a thermal zone
* @id: unique id number for each thermal zone
* @type: the thermal zone device type
* @device: &struct device for this thermal zone
* @removal: removal completion
* @trip_temp_attrs: attributes for trip points for sysfs: trip temperature
* @trip_type_attrs: attributes for trip points for sysfs: trip type
* @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
* @mode: current mode of this thermal zone
* @devdata: private pointer for device private data
* @num_trips: number of trip points the thermal zone supports
* @passive_delay_jiffies: number of jiffies to wait between polls when
* performing passive cooling.
* @polling_delay_jiffies: number of jiffies to wait between polls when
* checking whether trip points have been crossed (0 for
* interrupt driven systems)
* @temperature: current temperature. This is only for core code,
* drivers should use thermal_zone_get_temp() to get the
* current temperature
* @last_temperature: previous temperature read
* @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
* @passive: 1 if you've crossed a passive trip point, 0 otherwise.
* @prev_low_trip: the low current temperature if you've crossed a passive
trip point.
* @prev_high_trip: the above current temperature if you've crossed a
passive trip point.
* @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
* @ops: operations this &thermal_zone_device supports
* @tzp: thermal zone parameters
* @governor: pointer to the governor for this thermal zone
* @governor_data: private pointer for governor data
* @thermal_instances: list of &struct thermal_instance of this thermal zone
* @ida: &struct ida to generate unique id for this zone's cooling
* devices
* @lock: lock to protect thermal_instances list
* @node: node in thermal_tz_list (in thermal_core.c)
* @poll_queue: delayed work for polling
* @notify_event: Last notification event
* @suspended: thermal zone suspend indicator
* @trips: array of struct thermal_trip objects
*/
struct
thermal_zone_device
{
int
id
;
char
type
[
THERMAL_NAME_LENGTH
];
struct
device
device
;
struct
completion
removal
;
struct
attribute_group
trips_attribute_group
;
struct
thermal_attr
*
trip_temp_attrs
;
struct
thermal_attr
*
trip_type_attrs
;
struct
thermal_attr
*
trip_hyst_attrs
;
enum
thermal_device_mode
mode
;
void
*
devdata
;
int
num_trips
;
unsigned
long
passive_delay_jiffies
;
unsigned
long
polling_delay_jiffies
;
int
temperature
;
int
last_temperature
;
int
emul_temperature
;
int
passive
;
int
prev_low_trip
;
int
prev_high_trip
;
atomic_t
need_update
;
struct
thermal_zone_device_ops
ops
;
struct
thermal_zone_params
*
tzp
;
struct
thermal_governor
*
governor
;
void
*
governor_data
;
struct
list_head
thermal_instances
;
struct
ida
ida
;
struct
mutex
lock
;
struct
list_head
node
;
struct
delayed_work
poll_queue
;
enum
thermal_notify_event
notify_event
;
bool
suspended
;
#ifdef CONFIG_THERMAL_DEBUGFS
struct
thermal_debugfs
*
debugfs
;
#endif
struct
thermal_trip_desc
trips
[]
__counted_by
(
num_trips
);
};
/* Default Thermal Governor */
#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
#define DEFAULT_THERMAL_GOVERNOR "step_wise"
...
...
@@ -120,8 +232,11 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz,
enum
thermal_notify_event
reason
);
/* Helpers */
#define for_each_trip(__tz, __trip) \
for (__trip = __tz->trips; __trip - __tz->trips < __tz->num_trips; __trip++)
#define for_each_trip_desc(__tz, __td) \
for (__td = __tz->trips; __td - __tz->trips < __tz->num_trips; __td++)
#define trip_to_trip_desc(__trip) \
container_of(__trip, struct thermal_trip_desc, trip)
void
__thermal_zone_set_trips
(
struct
thermal_zone_device
*
tz
);
int
thermal_zone_trip_id
(
const
struct
thermal_zone_device
*
tz
,
...
...
drivers/thermal/thermal_debugfs.c
View file @
00211025
...
...
@@ -753,7 +753,7 @@ static int tze_seq_show(struct seq_file *s, void *v)
{
struct
thermal_debugfs
*
thermal_dbg
=
s
->
private
;
struct
thermal_zone_device
*
tz
=
thermal_dbg
->
tz_dbg
.
tz
;
struct
thermal_trip
*
trip
;
struct
thermal_trip
_desc
*
td
;
struct
tz_episode
*
tze
;
const
char
*
type
;
int
trip_id
;
...
...
@@ -766,7 +766,9 @@ static int tze_seq_show(struct seq_file *s, void *v)
seq_printf
(
s
,
"| trip | type | temp(°mC) | hyst(°mC) | duration | avg(°mC) | min(°mC) | max(°mC) |
\n
"
);
for_each_trip
(
tz
,
trip
)
{
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
/*
* There is no possible mitigation happening at the
* critical trip point, so the stats will be always
...
...
drivers/thermal/thermal_helpers.c
View file @
00211025
...
...
@@ -50,7 +50,7 @@ get_thermal_instance(struct thermal_zone_device *tz,
mutex_lock
(
&
tz
->
lock
);
mutex_lock
(
&
cdev
->
lock
);
trip
=
&
tz
->
trips
[
trip_index
];
trip
=
&
tz
->
trips
[
trip_index
]
.
trip
;
list_for_each_entry
(
pos
,
&
tz
->
thermal_instances
,
tz_node
)
{
if
(
pos
->
tz
==
tz
&&
pos
->
trip
==
trip
&&
pos
->
cdev
==
cdev
)
{
...
...
@@ -82,7 +82,7 @@ EXPORT_SYMBOL(get_thermal_instance);
*/
int
__thermal_zone_get_temp
(
struct
thermal_zone_device
*
tz
,
int
*
temp
)
{
const
struct
thermal_trip
*
trip
;
const
struct
thermal_trip
_desc
*
td
;
int
crit_temp
=
INT_MAX
;
int
ret
=
-
EINVAL
;
...
...
@@ -91,7 +91,9 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
ret
=
tz
->
ops
.
get_temp
(
tz
,
temp
);
if
(
IS_ENABLED
(
CONFIG_THERMAL_EMULATION
)
&&
tz
->
emul_temperature
)
{
for_each_trip
(
tz
,
trip
)
{
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
if
(
trip
->
type
==
THERMAL_TRIP_CRITICAL
)
{
crit_temp
=
trip
->
temperature
;
break
;
...
...
drivers/thermal/thermal_netlink.c
View file @
00211025
...
...
@@ -7,17 +7,13 @@
* Generic netlink for thermal management framework
*/
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/kernel.h>
#include <net/genetlink.h>
#include <uapi/linux/thermal.h>
#include "thermal_core.h"
enum
thermal_genl_multicast_groups
{
THERMAL_GENL_SAMPLING_GROUP
=
0
,
THERMAL_GENL_EVENT_GROUP
=
1
,
};
static
const
struct
genl_multicast_group
thermal_genl_mcgrps
[]
=
{
[
THERMAL_GENL_SAMPLING_GROUP
]
=
{
.
name
=
THERMAL_GENL_SAMPLING_GROUP_NAME
,
},
[
THERMAL_GENL_EVENT_GROUP
]
=
{
.
name
=
THERMAL_GENL_EVENT_GROUP_NAME
,
},
...
...
@@ -74,11 +70,12 @@ struct param {
typedef
int
(
*
cb_t
)(
struct
param
*
);
static
struct
genl_family
thermal_gnl_family
;
static
struct
genl_family
thermal_genl_family
;
static
BLOCKING_NOTIFIER_HEAD
(
thermal_genl_chain
);
static
int
thermal_group_has_listeners
(
enum
thermal_genl_multicast_groups
group
)
{
return
genl_has_listeners
(
&
thermal_gnl_family
,
&
init_net
,
group
);
return
genl_has_listeners
(
&
thermal_g
e
nl_family
,
&
init_net
,
group
);
}
/************************** Sampling encoding *******************************/
...
...
@@ -95,7 +92,7 @@ int thermal_genl_sampling_temp(int id, int temp)
if
(
!
skb
)
return
-
ENOMEM
;
hdr
=
genlmsg_put
(
skb
,
0
,
0
,
&
thermal_gnl_family
,
0
,
hdr
=
genlmsg_put
(
skb
,
0
,
0
,
&
thermal_g
e
nl_family
,
0
,
THERMAL_GENL_SAMPLING_TEMP
);
if
(
!
hdr
)
goto
out_free
;
...
...
@@ -108,7 +105,7 @@ int thermal_genl_sampling_temp(int id, int temp)
genlmsg_end
(
skb
,
hdr
);
genlmsg_multicast
(
&
thermal_gnl_family
,
skb
,
0
,
THERMAL_GENL_SAMPLING_GROUP
,
GFP_KERNEL
);
genlmsg_multicast
(
&
thermal_g
e
nl_family
,
skb
,
0
,
THERMAL_GENL_SAMPLING_GROUP
,
GFP_KERNEL
);
return
0
;
out_cancel:
...
...
@@ -282,7 +279,7 @@ static int thermal_genl_send_event(enum thermal_genl_event event,
return
-
ENOMEM
;
p
->
msg
=
msg
;
hdr
=
genlmsg_put
(
msg
,
0
,
0
,
&
thermal_gnl_family
,
0
,
event
);
hdr
=
genlmsg_put
(
msg
,
0
,
0
,
&
thermal_g
e
nl_family
,
0
,
event
);
if
(
!
hdr
)
goto
out_free_msg
;
...
...
@@ -292,7 +289,7 @@ static int thermal_genl_send_event(enum thermal_genl_event event,
genlmsg_end
(
msg
,
hdr
);
genlmsg_multicast
(
&
thermal_gnl_family
,
msg
,
0
,
THERMAL_GENL_EVENT_GROUP
,
GFP_KERNEL
);
genlmsg_multicast
(
&
thermal_g
e
nl_family
,
msg
,
0
,
THERMAL_GENL_EVENT_GROUP
,
GFP_KERNEL
);
return
0
;
...
...
@@ -445,7 +442,7 @@ static int thermal_genl_cmd_tz_get_id(struct param *p)
static
int
thermal_genl_cmd_tz_get_trip
(
struct
param
*
p
)
{
struct
sk_buff
*
msg
=
p
->
msg
;
const
struct
thermal_trip
*
trip
;
const
struct
thermal_trip
_desc
*
td
;
struct
thermal_zone_device
*
tz
;
struct
nlattr
*
start_trip
;
int
id
;
...
...
@@ -465,7 +462,9 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p)
mutex_lock
(
&
tz
->
lock
);
for_each_trip
(
tz
,
trip
)
{
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
if
(
nla_put_u32
(
msg
,
THERMAL_GENL_ATTR_TZ_TRIP_ID
,
thermal_zone_trip_id
(
tz
,
trip
))
||
nla_put_u32
(
msg
,
THERMAL_GENL_ATTR_TZ_TRIP_TYPE
,
trip
->
type
)
||
...
...
@@ -593,7 +592,7 @@ static int thermal_genl_cmd_dumpit(struct sk_buff *skb,
int
ret
;
void
*
hdr
;
hdr
=
genlmsg_put
(
skb
,
0
,
0
,
&
thermal_gnl_family
,
0
,
cmd
);
hdr
=
genlmsg_put
(
skb
,
0
,
0
,
&
thermal_g
e
nl_family
,
0
,
cmd
);
if
(
!
hdr
)
return
-
EMSGSIZE
;
...
...
@@ -625,7 +624,7 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
return
-
ENOMEM
;
p
.
msg
=
msg
;
hdr
=
genlmsg_put_reply
(
msg
,
info
,
&
thermal_gnl_family
,
0
,
cmd
);
hdr
=
genlmsg_put_reply
(
msg
,
info
,
&
thermal_g
e
nl_family
,
0
,
cmd
);
if
(
!
hdr
)
goto
out_free_msg
;
...
...
@@ -645,6 +644,27 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
return
ret
;
}
static
int
thermal_genl_bind
(
int
mcgrp
)
{
struct
thermal_genl_notify
n
=
{
.
mcgrp
=
mcgrp
};
if
(
WARN_ON_ONCE
(
mcgrp
>
THERMAL_GENL_MAX_GROUP
))
return
-
EINVAL
;
blocking_notifier_call_chain
(
&
thermal_genl_chain
,
THERMAL_NOTIFY_BIND
,
&
n
);
return
0
;
}
static
void
thermal_genl_unbind
(
int
mcgrp
)
{
struct
thermal_genl_notify
n
=
{
.
mcgrp
=
mcgrp
};
if
(
WARN_ON_ONCE
(
mcgrp
>
THERMAL_GENL_MAX_GROUP
))
return
;
blocking_notifier_call_chain
(
&
thermal_genl_chain
,
THERMAL_NOTIFY_UNBIND
,
&
n
);
}
static
const
struct
genl_small_ops
thermal_genl_ops
[]
=
{
{
.
cmd
=
THERMAL_GENL_CMD_TZ_GET_ID
,
...
...
@@ -673,12 +693,14 @@ static const struct genl_small_ops thermal_genl_ops[] = {
},
};
static
struct
genl_family
thermal_gnl_family
__ro_after_init
=
{
static
struct
genl_family
thermal_g
e
nl_family
__ro_after_init
=
{
.
hdrsize
=
0
,
.
name
=
THERMAL_GENL_FAMILY_NAME
,
.
version
=
THERMAL_GENL_VERSION
,
.
maxattr
=
THERMAL_GENL_ATTR_MAX
,
.
policy
=
thermal_genl_policy
,
.
bind
=
thermal_genl_bind
,
.
unbind
=
thermal_genl_unbind
,
.
small_ops
=
thermal_genl_ops
,
.
n_small_ops
=
ARRAY_SIZE
(
thermal_genl_ops
),
.
resv_start_op
=
THERMAL_GENL_CMD_CDEV_GET
+
1
,
...
...
@@ -686,12 +708,22 @@ static struct genl_family thermal_gnl_family __ro_after_init = {
.
n_mcgrps
=
ARRAY_SIZE
(
thermal_genl_mcgrps
),
};
int
thermal_genl_register_notifier
(
struct
notifier_block
*
nb
)
{
return
blocking_notifier_chain_register
(
&
thermal_genl_chain
,
nb
);
}
int
thermal_genl_unregister_notifier
(
struct
notifier_block
*
nb
)
{
return
blocking_notifier_chain_unregister
(
&
thermal_genl_chain
,
nb
);
}
int
__init
thermal_netlink_init
(
void
)
{
return
genl_register_family
(
&
thermal_gnl_family
);
return
genl_register_family
(
&
thermal_g
e
nl_family
);
}
void
__init
thermal_netlink_exit
(
void
)
{
genl_unregister_family
(
&
thermal_gnl_family
);
genl_unregister_family
(
&
thermal_g
e
nl_family
);
}
drivers/thermal/thermal_netlink.h
View file @
00211025
...
...
@@ -10,6 +10,19 @@ struct thermal_genl_cpu_caps {
int
efficiency
;
};
enum
thermal_genl_multicast_groups
{
THERMAL_GENL_SAMPLING_GROUP
=
0
,
THERMAL_GENL_EVENT_GROUP
=
1
,
THERMAL_GENL_MAX_GROUP
=
THERMAL_GENL_EVENT_GROUP
,
};
#define THERMAL_NOTIFY_BIND 0
#define THERMAL_NOTIFY_UNBIND 1
struct
thermal_genl_notify
{
int
mcgrp
;
};
struct
thermal_zone_device
;
struct
thermal_trip
;
struct
thermal_cooling_device
;
...
...
@@ -18,6 +31,9 @@ struct thermal_cooling_device;
#ifdef CONFIG_THERMAL_NETLINK
int
__init
thermal_netlink_init
(
void
);
void
__init
thermal_netlink_exit
(
void
);
int
thermal_genl_register_notifier
(
struct
notifier_block
*
nb
);
int
thermal_genl_unregister_notifier
(
struct
notifier_block
*
nb
);
int
thermal_notify_tz_create
(
const
struct
thermal_zone_device
*
tz
);
int
thermal_notify_tz_delete
(
const
struct
thermal_zone_device
*
tz
);
int
thermal_notify_tz_enable
(
const
struct
thermal_zone_device
*
tz
);
...
...
@@ -48,6 +64,16 @@ static inline int thermal_notify_tz_create(const struct thermal_zone_device *tz)
return
0
;
}
static
inline
int
thermal_genl_register_notifier
(
struct
notifier_block
*
nb
)
{
return
0
;
}
static
inline
int
thermal_genl_unregister_notifier
(
struct
notifier_block
*
nb
)
{
return
0
;
}
static
inline
int
thermal_notify_tz_delete
(
const
struct
thermal_zone_device
*
tz
)
{
return
0
;
...
...
drivers/thermal/thermal_sysfs.c
View file @
00211025
...
...
@@ -88,7 +88,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if
(
sscanf
(
attr
->
attr
.
name
,
"trip_point_%d_type"
,
&
trip_id
)
!=
1
)
return
-
EINVAL
;
switch
(
tz
->
trips
[
trip_id
].
type
)
{
switch
(
tz
->
trips
[
trip_id
].
t
rip
.
t
ype
)
{
case
THERMAL_TRIP_CRITICAL
:
return
sprintf
(
buf
,
"critical
\n
"
);
case
THERMAL_TRIP_HOT
:
...
...
@@ -120,7 +120,7 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
mutex_lock
(
&
tz
->
lock
);
trip
=
&
tz
->
trips
[
trip_id
];
trip
=
&
tz
->
trips
[
trip_id
]
.
trip
;
if
(
temp
!=
trip
->
temperature
)
{
if
(
tz
->
ops
.
set_trip_temp
)
{
...
...
@@ -150,7 +150,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if
(
sscanf
(
attr
->
attr
.
name
,
"trip_point_%d_temp"
,
&
trip_id
)
!=
1
)
return
-
EINVAL
;
return
sprintf
(
buf
,
"%d
\n
"
,
tz
->
trips
[
trip_id
].
temperature
);
return
sprintf
(
buf
,
"%d
\n
"
,
tz
->
trips
[
trip_id
].
t
rip
.
t
emperature
);
}
static
ssize_t
...
...
@@ -171,7 +171,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
mutex_lock
(
&
tz
->
lock
);
trip
=
&
tz
->
trips
[
trip_id
];
trip
=
&
tz
->
trips
[
trip_id
]
.
trip
;
if
(
hyst
!=
trip
->
hysteresis
)
{
trip
->
hysteresis
=
hyst
;
...
...
@@ -194,7 +194,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
if
(
sscanf
(
attr
->
attr
.
name
,
"trip_point_%d_hyst"
,
&
trip_id
)
!=
1
)
return
-
EINVAL
;
return
sprintf
(
buf
,
"%d
\n
"
,
tz
->
trips
[
trip_id
].
hysteresis
);
return
sprintf
(
buf
,
"%d
\n
"
,
tz
->
trips
[
trip_id
].
trip
.
hysteresis
);
}
static
ssize_t
...
...
@@ -393,7 +393,7 @@ static const struct attribute_group *thermal_zone_attribute_groups[] = {
*/
static
int
create_trip_attrs
(
struct
thermal_zone_device
*
tz
)
{
const
struct
thermal_trip
*
trip
;
const
struct
thermal_trip
_desc
*
td
;
struct
attribute
**
attrs
;
/* This function works only for zones with at least one trip */
...
...
@@ -429,8 +429,8 @@ static int create_trip_attrs(struct thermal_zone_device *tz)
return
-
ENOMEM
;
}
for_each_trip
(
tz
,
trip
)
{
int
indx
=
thermal_zone_trip_id
(
tz
,
trip
);
for_each_trip
_desc
(
tz
,
td
)
{
int
indx
=
thermal_zone_trip_id
(
tz
,
&
td
->
trip
);
/* create trip type attribute */
snprintf
(
tz
->
trip_type_attrs
[
indx
].
name
,
THERMAL_NAME_LENGTH
,
...
...
@@ -452,7 +452,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz)
tz
->
trip_temp_attrs
[
indx
].
name
;
tz
->
trip_temp_attrs
[
indx
].
attr
.
attr
.
mode
=
S_IRUGO
;
tz
->
trip_temp_attrs
[
indx
].
attr
.
show
=
trip_point_temp_show
;
if
(
t
rip
->
flags
&
THERMAL_TRIP_FLAG_RW_TEMP
)
{
if
(
t
d
->
trip
.
flags
&
THERMAL_TRIP_FLAG_RW_TEMP
)
{
tz
->
trip_temp_attrs
[
indx
].
attr
.
attr
.
mode
|=
S_IWUSR
;
tz
->
trip_temp_attrs
[
indx
].
attr
.
store
=
trip_point_temp_store
;
...
...
@@ -467,7 +467,7 @@ static int create_trip_attrs(struct thermal_zone_device *tz)
tz
->
trip_hyst_attrs
[
indx
].
name
;
tz
->
trip_hyst_attrs
[
indx
].
attr
.
attr
.
mode
=
S_IRUGO
;
tz
->
trip_hyst_attrs
[
indx
].
attr
.
show
=
trip_point_hyst_show
;
if
(
t
rip
->
flags
&
THERMAL_TRIP_FLAG_RW_HYST
)
{
if
(
t
d
->
trip
.
flags
&
THERMAL_TRIP_FLAG_RW_HYST
)
{
tz
->
trip_hyst_attrs
[
indx
].
attr
.
attr
.
mode
|=
S_IWUSR
;
tz
->
trip_hyst_attrs
[
indx
].
attr
.
store
=
trip_point_hyst_store
;
...
...
drivers/thermal/thermal_trace.h
View file @
00211025
...
...
@@ -9,6 +9,8 @@
#include <linux/thermal.h>
#include <linux/tracepoint.h>
#include "thermal_core.h"
TRACE_DEFINE_ENUM
(
THERMAL_TRIP_CRITICAL
);
TRACE_DEFINE_ENUM
(
THERMAL_TRIP_HOT
);
TRACE_DEFINE_ENUM
(
THERMAL_TRIP_PASSIVE
);
...
...
drivers/thermal/thermal_trace_ipa.h
View file @
00211025
...
...
@@ -7,6 +7,8 @@
#include <linux/tracepoint.h>
#include "thermal_core.h"
TRACE_EVENT
(
thermal_power_allocator
,
TP_PROTO
(
struct
thermal_zone_device
*
tz
,
u32
total_req_power
,
u32
total_granted_power
,
int
num_actors
,
u32
power_range
,
...
...
drivers/thermal/thermal_trip.c
View file @
00211025
...
...
@@ -13,11 +13,11 @@ int for_each_thermal_trip(struct thermal_zone_device *tz,
int
(
*
cb
)(
struct
thermal_trip
*
,
void
*
),
void
*
data
)
{
struct
thermal_trip
*
trip
;
struct
thermal_trip
_desc
*
td
;
int
ret
;
for_each_trip
(
tz
,
trip
)
{
ret
=
cb
(
trip
,
data
);
for_each_trip
_desc
(
tz
,
td
)
{
ret
=
cb
(
&
td
->
trip
,
data
);
if
(
ret
)
return
ret
;
}
...
...
@@ -63,7 +63,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
*/
void
__thermal_zone_set_trips
(
struct
thermal_zone_device
*
tz
)
{
const
struct
thermal_trip
*
trip
;
const
struct
thermal_trip
_desc
*
td
;
int
low
=
-
INT_MAX
,
high
=
INT_MAX
;
int
ret
;
...
...
@@ -72,7 +72,8 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
if
(
!
tz
->
ops
.
set_trips
)
return
;
for_each_trip
(
tz
,
trip
)
{
for_each_trip_desc
(
tz
,
td
)
{
const
struct
thermal_trip
*
trip
=
&
td
->
trip
;
int
trip_low
;
trip_low
=
trip
->
temperature
-
trip
->
hysteresis
;
...
...
@@ -110,7 +111,7 @@ int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
if
(
!
tz
||
trip_id
<
0
||
trip_id
>=
tz
->
num_trips
||
!
trip
)
return
-
EINVAL
;
*
trip
=
tz
->
trips
[
trip_id
];
*
trip
=
tz
->
trips
[
trip_id
]
.
trip
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
__thermal_zone_get_trip
);
...
...
@@ -135,7 +136,7 @@ int thermal_zone_trip_id(const struct thermal_zone_device *tz,
* Assume the trip to be located within the bounds of the thermal
* zone's trips[] table.
*/
return
trip
-
tz
->
trips
;
return
trip
_to_trip_desc
(
trip
)
-
tz
->
trips
;
}
void
thermal_zone_trip_updated
(
struct
thermal_zone_device
*
tz
,
const
struct
thermal_trip
*
trip
)
...
...
include/dt-bindings/thermal/mediatek,lvts-thermal.h
View file @
00211025
...
...
@@ -16,6 +16,32 @@
#define MT7988_ETHWARP_0 6
#define MT7988_ETHWARP_1 7
#define MT8186_LITTLE_CPU0 0
#define MT8186_LITTLE_CPU1 1
#define MT8186_LITTLE_CPU2 2
#define MT8186_CAM 3
#define MT8186_BIG_CPU0 4
#define MT8186_BIG_CPU1 5
#define MT8186_NNA 6
#define MT8186_ADSP 7
#define MT8186_MFG 8
#define MT8188_MCU_LITTLE_CPU0 0
#define MT8188_MCU_LITTLE_CPU1 1
#define MT8188_MCU_LITTLE_CPU2 2
#define MT8188_MCU_LITTLE_CPU3 3
#define MT8188_MCU_BIG_CPU0 4
#define MT8188_MCU_BIG_CPU1 5
#define MT8188_AP_APU 0
#define MT8188_AP_GPU1 1
#define MT8188_AP_GPU2 2
#define MT8188_AP_SOC1 3
#define MT8188_AP_SOC2 4
#define MT8188_AP_SOC3 5
#define MT8188_AP_CAM1 6
#define MT8188_AP_CAM2 7
#define MT8195_MCU_BIG_CPU0 0
#define MT8195_MCU_BIG_CPU1 1
#define MT8195_MCU_BIG_CPU2 2
...
...
include/linux/thermal.h
View file @
00211025
...
...
@@ -61,7 +61,6 @@ enum thermal_notify_event {
* struct thermal_trip - representation of a point in temperature domain
* @temperature: temperature value in miliCelsius
* @hysteresis: relative hysteresis in miliCelsius
* @threshold: trip crossing notification threshold miliCelsius
* @type: trip point type
* @priv: pointer to driver data associated with this trip
* @flags: flags representing binary properties of the trip
...
...
@@ -69,7 +68,6 @@ enum thermal_notify_event {
struct
thermal_trip
{
int
temperature
;
int
hysteresis
;
int
threshold
;
enum
thermal_trip_type
type
;
u8
flags
;
void
*
priv
;
...
...
@@ -81,6 +79,8 @@ struct thermal_trip {
#define THERMAL_TRIP_FLAG_RW (THERMAL_TRIP_FLAG_RW_TEMP | \
THERMAL_TRIP_FLAG_RW_HYST)
struct
thermal_zone_device
;
struct
thermal_zone_device_ops
{
int
(
*
bind
)
(
struct
thermal_zone_device
*
,
struct
thermal_cooling_device
*
);
...
...
@@ -126,111 +126,6 @@ struct thermal_cooling_device {
#endif
};
/**
* struct thermal_zone_device - structure for a thermal zone
* @id: unique id number for each thermal zone
* @type: the thermal zone device type
* @device: &struct device for this thermal zone
* @removal: removal completion
* @trip_temp_attrs: attributes for trip points for sysfs: trip temperature
* @trip_type_attrs: attributes for trip points for sysfs: trip type
* @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
* @mode: current mode of this thermal zone
* @devdata: private pointer for device private data
* @num_trips: number of trip points the thermal zone supports
* @passive_delay_jiffies: number of jiffies to wait between polls when
* performing passive cooling.
* @polling_delay_jiffies: number of jiffies to wait between polls when
* checking whether trip points have been crossed (0 for
* interrupt driven systems)
* @temperature: current temperature. This is only for core code,
* drivers should use thermal_zone_get_temp() to get the
* current temperature
* @last_temperature: previous temperature read
* @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
* @passive: 1 if you've crossed a passive trip point, 0 otherwise.
* @prev_low_trip: the low current temperature if you've crossed a passive
trip point.
* @prev_high_trip: the above current temperature if you've crossed a
passive trip point.
* @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
* @ops: operations this &thermal_zone_device supports
* @tzp: thermal zone parameters
* @governor: pointer to the governor for this thermal zone
* @governor_data: private pointer for governor data
* @thermal_instances: list of &struct thermal_instance of this thermal zone
* @ida: &struct ida to generate unique id for this zone's cooling
* devices
* @lock: lock to protect thermal_instances list
* @node: node in thermal_tz_list (in thermal_core.c)
* @poll_queue: delayed work for polling
* @notify_event: Last notification event
* @suspended: thermal zone suspend indicator
* @trips: array of struct thermal_trip objects
*/
struct
thermal_zone_device
{
int
id
;
char
type
[
THERMAL_NAME_LENGTH
];
struct
device
device
;
struct
completion
removal
;
struct
attribute_group
trips_attribute_group
;
struct
thermal_attr
*
trip_temp_attrs
;
struct
thermal_attr
*
trip_type_attrs
;
struct
thermal_attr
*
trip_hyst_attrs
;
enum
thermal_device_mode
mode
;
void
*
devdata
;
int
num_trips
;
unsigned
long
passive_delay_jiffies
;
unsigned
long
polling_delay_jiffies
;
int
temperature
;
int
last_temperature
;
int
emul_temperature
;
int
passive
;
int
prev_low_trip
;
int
prev_high_trip
;
atomic_t
need_update
;
struct
thermal_zone_device_ops
ops
;
struct
thermal_zone_params
*
tzp
;
struct
thermal_governor
*
governor
;
void
*
governor_data
;
struct
list_head
thermal_instances
;
struct
ida
ida
;
struct
mutex
lock
;
struct
list_head
node
;
struct
delayed_work
poll_queue
;
enum
thermal_notify_event
notify_event
;
bool
suspended
;
#ifdef CONFIG_THERMAL_DEBUGFS
struct
thermal_debugfs
*
debugfs
;
#endif
struct
thermal_trip
trips
[]
__counted_by
(
num_trips
);
};
/**
* struct thermal_governor - structure that holds thermal governor information
* @name: name of the governor
* @bind_to_tz: callback called when binding to a thermal zone. If it
* returns 0, the governor is bound to the thermal zone,
* otherwise it fails.
* @unbind_from_tz: callback called when a governor is unbound from a
* thermal zone.
* @throttle: callback called for every trip point even if temperature is
* below the trip point temperature
* @update_tz: callback called when thermal zone internals have changed, e.g.
* thermal cooling instance was added/removed
* @governor_list: node in thermal_governor_list (in thermal_core.c)
*/
struct
thermal_governor
{
const
char
*
name
;
int
(
*
bind_to_tz
)(
struct
thermal_zone_device
*
tz
);
void
(
*
unbind_from_tz
)(
struct
thermal_zone_device
*
tz
);
int
(
*
throttle
)(
struct
thermal_zone_device
*
tz
,
const
struct
thermal_trip
*
trip
);
void
(
*
update_tz
)(
struct
thermal_zone_device
*
tz
,
enum
thermal_notify_event
reason
);
struct
list_head
governor_list
;
};
/* Structure to define Thermal Zone parameters */
struct
thermal_zone_params
{
const
char
*
governor_name
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment