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
cb15c81a
Commit
cb15c81a
authored
May 06, 2017
by
Zhang Rui
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'thermal-soc' into next
parents
bb4d5e38
e4cb5bb2
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1061 additions
and
217 deletions
+1061
-217
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
...tion/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
+28
-4
Documentation/devicetree/bindings/thermal/brcm,ns-thermal
Documentation/devicetree/bindings/thermal/brcm,ns-thermal
+37
-0
Documentation/devicetree/bindings/thermal/da9062-thermal.txt
Documentation/devicetree/bindings/thermal/da9062-thermal.txt
+36
-0
drivers/thermal/Kconfig
drivers/thermal/Kconfig
+15
-0
drivers/thermal/Makefile
drivers/thermal/Makefile
+2
-0
drivers/thermal/broadcom/Kconfig
drivers/thermal/broadcom/Kconfig
+16
-0
drivers/thermal/broadcom/Makefile
drivers/thermal/broadcom/Makefile
+2
-0
drivers/thermal/broadcom/bcm2835_thermal.c
drivers/thermal/broadcom/bcm2835_thermal.c
+314
-0
drivers/thermal/broadcom/ns-thermal.c
drivers/thermal/broadcom/ns-thermal.c
+106
-0
drivers/thermal/da9062-thermal.c
drivers/thermal/da9062-thermal.c
+315
-0
drivers/thermal/mtk_thermal.c
drivers/thermal/mtk_thermal.c
+1
-1
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/rcar_gen3_thermal.c
+184
-15
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
+0
-10
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
+0
-4
drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
+0
-6
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
+0
-4
drivers/thermal/ti-soc-thermal/ti-bandgap.h
drivers/thermal/ti-soc-thermal/ti-bandgap.h
+0
-4
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+5
-153
drivers/thermal/ti-soc-thermal/ti-thermal.h
drivers/thermal/ti-soc-thermal/ti-thermal.h
+0
-16
No files found.
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
View file @
cb15c81a
...
...
@@ -3,15 +3,39 @@ Binding for Thermal Sensor driver for BCM2835 SoCs.
Required parameters:
-------------------
compatible: should be one of: "brcm,bcm2835-thermal",
"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
reg: Address range of the thermal registers.
clocks: Phandle of the clock used by the thermal sensor.
compatible: should be one of: "brcm,bcm2835-thermal",
"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
reg: Address range of the thermal registers.
clocks: Phandle of the clock used by the thermal sensor.
#thermal-sensor-cells: should be 0 (see thermal.txt)
Example:
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <0>;
polling-delay = <1000>;
thermal-sensors = <&thermal>;
trips {
cpu-crit {
temperature = <80000>;
hysteresis = <0>;
type = "critical";
};
};
coefficients = <(-538) 407000>;
cooling-maps {
};
};
};
thermal: thermal@7e212000 {
compatible = "brcm,bcm2835-thermal";
reg = <0x7e212000 0x8>;
clocks = <&clocks BCM2835_CLOCK_TSENS>;
#thermal-sensor-cells = <0>;
};
Documentation/devicetree/bindings/thermal/brcm,ns-thermal
0 → 100644
View file @
cb15c81a
* Broadcom Northstar Thermal
This binding describes thermal sensor that is part of Northstar's DMU (Device
Management Unit).
Required properties:
- compatible : Must be "brcm,ns-thermal"
- reg : iomem address range of PVTMON registers
- #thermal-sensor-cells : Should be <0>
Example:
thermal: thermal@1800c2c0 {
compatible = "brcm,ns-thermal";
reg = <0x1800c2c0 0x10>;
#thermal-sensor-cells = <0>;
};
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <0>;
polling-delay = <1000>;
coefficients = <(-556) 418000>;
thermal-sensors = <&thermal>;
trips {
cpu-crit {
temperature = <125000>;
hysteresis = <0>;
type = "critical";
};
};
cooling-maps {
};
};
};
Documentation/devicetree/bindings/thermal/da9062-thermal.txt
0 → 100644
View file @
cb15c81a
* Dialog DA9062/61 TJUNC Thermal Module
This module is part of the DA9061/DA9062. For more details about entire
DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
Junction temperature thermal module uses an interrupt signal to identify
high THERMAL_TRIP_HOT temperatures for the PMIC device.
Required properties:
- compatible: should be one of the following valid compatible string lines:
"dlg,da9061-thermal", "dlg,da9062-thermal"
"dlg,da9062-thermal"
Optional properties:
- polling-delay-passive : Specify the polling period, measured in
milliseconds, between thermal zone device update checks.
Example: DA9062
pmic0: da9062@58 {
thermal {
compatible = "dlg,da9062-thermal";
polling-delay-passive = <3000>;
};
};
Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
pmic0: da9061@58 {
thermal {
compatible = "dlg,da9061-thermal", "dlg,da9062-thermal";
polling-delay-passive = <3000>;
};
};
drivers/thermal/Kconfig
View file @
cb15c81a
...
...
@@ -320,6 +320,16 @@ config DB8500_CPUFREQ_COOLING
bound cpufreq cooling device turns active to set CPU frequency low to
cool down the CPU.
config DA9062_THERMAL
tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
depends on MFD_DA9062 || COMPILE_TEST
depends on OF
help
Enable this for the Dialog Semiconductor thermal sensor driver.
This will report PMIC junction over-temperature for one thermal trip
zone.
Compatible with the DA9062 and DA9061 PMICs.
config INTEL_POWERCLAMP
tristate "Intel PowerClamp idle injection driver"
depends on THERMAL
...
...
@@ -409,6 +419,11 @@ config MTK_THERMAL
Enable this option if you want to have support for thermal management
controller present in Mediatek SoCs
menu "Broadcom thermal drivers"
depends on ARCH_BCM || COMPILE_TEST
source "drivers/thermal/broadcom/Kconfig"
endmenu
menu "Texas Instruments thermal drivers"
depends on ARCH_HAS_BANDGAP || COMPILE_TEST
depends on HAS_IOMEM
...
...
drivers/thermal/Makefile
View file @
cb15c81a
...
...
@@ -27,6 +27,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
thermal_sys-$(CONFIG_DEVFREQ_THERMAL)
+=
devfreq_cooling.o
# platform thermal drivers
obj-y
+=
broadcom/
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM)
+=
qcom-spmi-temp-alarm.o
obj-$(CONFIG_SPEAR_THERMAL)
+=
spear_thermal.o
obj-$(CONFIG_ROCKCHIP_THERMAL)
+=
rockchip_thermal.o
...
...
@@ -42,6 +43,7 @@ obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_MAX77620_THERMAL)
+=
max77620_thermal.o
obj-$(CONFIG_QORIQ_THERMAL)
+=
qoriq_thermal.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING)
+=
db8500_cpufreq_cooling.o
obj-$(CONFIG_DA9062_THERMAL)
+=
da9062-thermal.o
obj-$(CONFIG_INTEL_POWERCLAMP)
+=
intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL)
+=
x86_pkg_temp_thermal.o
obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE)
+=
intel_soc_dts_iosf.o
...
...
drivers/thermal/broadcom/Kconfig
0 → 100644
View file @
cb15c81a
config BCM2835_THERMAL
tristate "Thermal sensors on bcm2835 SoC"
depends on ARCH_BCM2835 || COMPILE_TEST
depends on HAS_IOMEM
depends on THERMAL_OF
help
Support for thermal sensors on Broadcom bcm2835 SoCs.
config BCM_NS_THERMAL
tristate "Northstar thermal driver"
depends on ARCH_BCM_IPROC || COMPILE_TEST
help
Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
with a thermal sensor that allows checking CPU temperature. This
driver provides support for it.
drivers/thermal/broadcom/Makefile
0 → 100644
View file @
cb15c81a
obj-$(CONFIG_BCM2835_THERMAL)
+=
bcm2835_thermal.o
obj-$(CONFIG_BCM_NS_THERMAL)
+=
ns-thermal.o
drivers/thermal/broadcom/bcm2835_thermal.c
0 → 100644
View file @
cb15c81a
/*
* Driver for Broadcom BCM2835 SoC temperature sensor
*
* Copyright (C) 2016 Martin Sperl
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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/clk.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
#define BCM2835_TS_TSENSCTL 0x00
#define BCM2835_TS_TSENSSTAT 0x04
#define BCM2835_TS_TSENSCTL_PRWDW BIT(0)
#define BCM2835_TS_TSENSCTL_RSTB BIT(1)
/*
* bandgap reference voltage in 6 mV increments
* 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
*/
#define BCM2835_TS_TSENSCTL_CTRL_BITS 3
#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
#define BCM2835_TS_TSENSCTL_CTRL_MASK \
GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
BCM2835_TS_TSENSCTL_CTRL_SHIFT)
#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
#define BCM2835_TS_TSENSCTL_EN_INT BIT(5)
#define BCM2835_TS_TSENSCTL_DIRECT BIT(6)
#define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)
#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
#define BCM2835_TS_TSENSCTL_THOLD_BITS 10
#define BCM2835_TS_TSENSCTL_THOLD_MASK \
GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
BCM2835_TS_TSENSCTL_THOLD_SHIFT)
/*
* time how long the block to be asserted in reset
* which based on a clock counter (TSENS clock assumed)
*/
#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
#define BCM2835_TS_TSENSCTL_REGULEN BIT(26)
#define BCM2835_TS_TSENSSTAT_DATA_BITS 10
#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
#define BCM2835_TS_TSENSSTAT_DATA_MASK \
GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
BCM2835_TS_TSENSSTAT_DATA_SHIFT)
#define BCM2835_TS_TSENSSTAT_VALID BIT(10)
#define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)
struct
bcm2835_thermal_data
{
struct
thermal_zone_device
*
tz
;
void
__iomem
*
regs
;
struct
clk
*
clk
;
struct
dentry
*
debugfsdir
;
};
static
int
bcm2835_thermal_adc2temp
(
u32
adc
,
int
offset
,
int
slope
)
{
return
offset
+
slope
*
adc
;
}
static
int
bcm2835_thermal_temp2adc
(
int
temp
,
int
offset
,
int
slope
)
{
temp
-=
offset
;
temp
/=
slope
;
if
(
temp
<
0
)
temp
=
0
;
if
(
temp
>=
BIT
(
BCM2835_TS_TSENSSTAT_DATA_BITS
))
temp
=
BIT
(
BCM2835_TS_TSENSSTAT_DATA_BITS
)
-
1
;
return
temp
;
}
static
int
bcm2835_thermal_get_temp
(
void
*
d
,
int
*
temp
)
{
struct
bcm2835_thermal_data
*
data
=
d
;
u32
val
=
readl
(
data
->
regs
+
BCM2835_TS_TSENSSTAT
);
if
(
!
(
val
&
BCM2835_TS_TSENSSTAT_VALID
))
return
-
EIO
;
val
&=
BCM2835_TS_TSENSSTAT_DATA_MASK
;
*
temp
=
bcm2835_thermal_adc2temp
(
val
,
thermal_zone_get_offset
(
data
->
tz
),
thermal_zone_get_slope
(
data
->
tz
));
return
0
;
}
static
const
struct
debugfs_reg32
bcm2835_thermal_regs
[]
=
{
{
.
name
=
"ctl"
,
.
offset
=
0
},
{
.
name
=
"stat"
,
.
offset
=
4
}
};
static
void
bcm2835_thermal_debugfs
(
struct
platform_device
*
pdev
)
{
struct
thermal_zone_device
*
tz
=
platform_get_drvdata
(
pdev
);
struct
bcm2835_thermal_data
*
data
=
tz
->
devdata
;
struct
debugfs_regset32
*
regset
;
data
->
debugfsdir
=
debugfs_create_dir
(
"bcm2835_thermal"
,
NULL
);
if
(
!
data
->
debugfsdir
)
return
;
regset
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
regset
),
GFP_KERNEL
);
if
(
!
regset
)
return
;
regset
->
regs
=
bcm2835_thermal_regs
;
regset
->
nregs
=
ARRAY_SIZE
(
bcm2835_thermal_regs
);
regset
->
base
=
data
->
regs
;
debugfs_create_regset32
(
"regset"
,
0444
,
data
->
debugfsdir
,
regset
);
}
static
struct
thermal_zone_of_device_ops
bcm2835_thermal_ops
=
{
.
get_temp
=
bcm2835_thermal_get_temp
,
};
/*
* Note: as per Raspberry Foundation FAQ
* (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
* the recommended temperature range for the SoC -40C to +85C
* so the trip limit is set to 80C.
* this applies to all the BCM283X SoC
*/
static
const
struct
of_device_id
bcm2835_thermal_of_match_table
[]
=
{
{
.
compatible
=
"brcm,bcm2835-thermal"
,
},
{
.
compatible
=
"brcm,bcm2836-thermal"
,
},
{
.
compatible
=
"brcm,bcm2837-thermal"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
bcm2835_thermal_of_match_table
);
static
int
bcm2835_thermal_probe
(
struct
platform_device
*
pdev
)
{
const
struct
of_device_id
*
match
;
struct
thermal_zone_device
*
tz
;
struct
bcm2835_thermal_data
*
data
;
struct
resource
*
res
;
int
err
=
0
;
u32
val
;
unsigned
long
rate
;
data
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
!
data
)
return
-
ENOMEM
;
match
=
of_match_device
(
bcm2835_thermal_of_match_table
,
&
pdev
->
dev
);
if
(
!
match
)
return
-
EINVAL
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
data
->
regs
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
data
->
regs
))
{
err
=
PTR_ERR
(
data
->
regs
);
dev_err
(
&
pdev
->
dev
,
"Could not get registers: %d
\n
"
,
err
);
return
err
;
}
data
->
clk
=
devm_clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
data
->
clk
))
{
err
=
PTR_ERR
(
data
->
clk
);
if
(
err
!=
-
EPROBE_DEFER
)
dev_err
(
&
pdev
->
dev
,
"Could not get clk: %d
\n
"
,
err
);
return
err
;
}
err
=
clk_prepare_enable
(
data
->
clk
);
if
(
err
)
return
err
;
rate
=
clk_get_rate
(
data
->
clk
);
if
((
rate
<
1920000
)
||
(
rate
>
5000000
))
dev_warn
(
&
pdev
->
dev
,
"Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz
\n
"
,
data
->
clk
,
data
->
clk
);
/* register of thermal sensor and get info from DT */
tz
=
thermal_zone_of_sensor_register
(
&
pdev
->
dev
,
0
,
data
,
&
bcm2835_thermal_ops
);
if
(
IS_ERR
(
tz
))
{
err
=
PTR_ERR
(
tz
);
dev_err
(
&
pdev
->
dev
,
"Failed to register the thermal device: %d
\n
"
,
err
);
goto
err_clk
;
}
/*
* right now the FW does set up the HW-block, so we are not
* touching the configuration registers.
* But if the HW is not enabled, then set it up
* using "sane" values used by the firmware right now.
*/
val
=
readl
(
data
->
regs
+
BCM2835_TS_TSENSCTL
);
if
(
!
(
val
&
BCM2835_TS_TSENSCTL_RSTB
))
{
int
trip_temp
,
offset
,
slope
;
slope
=
thermal_zone_get_slope
(
tz
);
offset
=
thermal_zone_get_offset
(
tz
);
/*
* For now we deal only with critical, otherwise
* would need to iterate
*/
err
=
tz
->
ops
->
get_trip_temp
(
tz
,
0
,
&
trip_temp
);
if
(
err
<
0
)
{
err
=
PTR_ERR
(
tz
);
dev_err
(
&
pdev
->
dev
,
"Not able to read trip_temp: %d
\n
"
,
err
);
goto
err_tz
;
}
/* set bandgap reference voltage and enable voltage regulator */
val
=
(
BCM2835_TS_TSENSCTL_CTRL_DEFAULT
<<
BCM2835_TS_TSENSCTL_CTRL_SHIFT
)
|
BCM2835_TS_TSENSCTL_REGULEN
;
/* use the recommended reset duration */
val
|=
(
0xFE
<<
BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT
);
/* trip_adc value from info */
val
|=
bcm2835_thermal_temp2adc
(
trip_temp
,
offset
,
slope
)
<<
BCM2835_TS_TSENSCTL_THOLD_SHIFT
;
/* write the value back to the register as 2 steps */
writel
(
val
,
data
->
regs
+
BCM2835_TS_TSENSCTL
);
val
|=
BCM2835_TS_TSENSCTL_RSTB
;
writel
(
val
,
data
->
regs
+
BCM2835_TS_TSENSCTL
);
}
data
->
tz
=
tz
;
platform_set_drvdata
(
pdev
,
tz
);
bcm2835_thermal_debugfs
(
pdev
);
return
0
;
err_tz:
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
tz
);
err_clk:
clk_disable_unprepare
(
data
->
clk
);
return
err
;
}
static
int
bcm2835_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
thermal_zone_device
*
tz
=
platform_get_drvdata
(
pdev
);
struct
bcm2835_thermal_data
*
data
=
tz
->
devdata
;
debugfs_remove_recursive
(
data
->
debugfsdir
);
thermal_zone_of_sensor_unregister
(
&
pdev
->
dev
,
tz
);
clk_disable_unprepare
(
data
->
clk
);
return
0
;
}
static
struct
platform_driver
bcm2835_thermal_driver
=
{
.
probe
=
bcm2835_thermal_probe
,
.
remove
=
bcm2835_thermal_remove
,
.
driver
=
{
.
name
=
"bcm2835_thermal"
,
.
of_match_table
=
bcm2835_thermal_of_match_table
,
},
};
module_platform_driver
(
bcm2835_thermal_driver
);
MODULE_AUTHOR
(
"Martin Sperl"
);
MODULE_DESCRIPTION
(
"Thermal driver for bcm2835 chip"
);
MODULE_LICENSE
(
"GPL"
);
drivers/thermal/broadcom/ns-thermal.c
0 → 100644
View file @
cb15c81a
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
#define PVTMON_CONTROL0 0x00
#define PVTMON_CONTROL0_SEL_MASK 0x0000000e
#define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
#define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
#define PVTMON_STATUS 0x08
struct
ns_thermal
{
struct
thermal_zone_device
*
tz
;
void
__iomem
*
pvtmon
;
};
static
int
ns_thermal_get_temp
(
void
*
data
,
int
*
temp
)
{
struct
ns_thermal
*
ns_thermal
=
data
;
int
offset
=
thermal_zone_get_offset
(
ns_thermal
->
tz
);
int
slope
=
thermal_zone_get_slope
(
ns_thermal
->
tz
);
u32
val
;
val
=
readl
(
ns_thermal
->
pvtmon
+
PVTMON_CONTROL0
);
if
((
val
&
PVTMON_CONTROL0_SEL_MASK
)
!=
PVTMON_CONTROL0_SEL_TEMP_MONITOR
)
{
/* Clear current mode selection */
val
&=
~
PVTMON_CONTROL0_SEL_MASK
;
/* Set temp monitor mode (it's the default actually) */
val
|=
PVTMON_CONTROL0_SEL_TEMP_MONITOR
;
writel
(
val
,
ns_thermal
->
pvtmon
+
PVTMON_CONTROL0
);
}
val
=
readl
(
ns_thermal
->
pvtmon
+
PVTMON_STATUS
);
*
temp
=
slope
*
val
+
offset
;
return
0
;
}
static
const
struct
thermal_zone_of_device_ops
ns_thermal_ops
=
{
.
get_temp
=
ns_thermal_get_temp
,
};
static
int
ns_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
device
*
dev
=
&
pdev
->
dev
;
struct
ns_thermal
*
ns_thermal
;
ns_thermal
=
devm_kzalloc
(
dev
,
sizeof
(
*
ns_thermal
),
GFP_KERNEL
);
if
(
!
ns_thermal
)
return
-
ENOMEM
;
ns_thermal
->
pvtmon
=
of_iomap
(
dev_of_node
(
dev
),
0
);
if
(
WARN_ON
(
!
ns_thermal
->
pvtmon
))
return
-
ENOENT
;
ns_thermal
->
tz
=
devm_thermal_zone_of_sensor_register
(
dev
,
0
,
ns_thermal
,
&
ns_thermal_ops
);
if
(
IS_ERR
(
ns_thermal
->
tz
))
{
iounmap
(
ns_thermal
->
pvtmon
);
return
PTR_ERR
(
ns_thermal
->
tz
);
}
platform_set_drvdata
(
pdev
,
ns_thermal
);
return
0
;
}
static
int
ns_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
ns_thermal
*
ns_thermal
=
platform_get_drvdata
(
pdev
);
iounmap
(
ns_thermal
->
pvtmon
);
return
0
;
}
static
const
struct
of_device_id
ns_thermal_of_match
[]
=
{
{
.
compatible
=
"brcm,ns-thermal"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
ns_thermal_of_match
);
static
struct
platform_driver
ns_thermal_driver
=
{
.
probe
=
ns_thermal_probe
,
.
remove
=
ns_thermal_remove
,
.
driver
=
{
.
name
=
"ns-thermal"
,
.
of_match_table
=
ns_thermal_of_match
,
},
};
module_platform_driver
(
ns_thermal_driver
);
MODULE_AUTHOR
(
"Rafał Miłecki <rafal@milecki.pl>"
);
MODULE_DESCRIPTION
(
"Northstar thermal driver"
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/thermal/da9062-thermal.c
0 → 100644
View file @
cb15c81a
/*
* Thermal device driver for DA9062 and DA9061
* Copyright (C) 2017 Dialog Semiconductor
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
*/
/* When over-temperature is reached, an interrupt from the device will be
* triggered. Following this event the interrupt will be disabled and
* periodic transmission of uevents (HOT trip point) should define the
* first level of temperature supervision. It is expected that any final
* implementation of the thermal driver will include a .notify() function
* to implement these uevents to userspace.
*
* These uevents are intended to indicate non-invasive temperature control
* of the system, where the necessary measures for cooling are the
* responsibility of the host software. Once the temperature falls again,
* the IRQ is re-enabled so the start of a new over-temperature event can
* be detected without constant software monitoring.
*/
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/thermal.h>
#include <linux/workqueue.h>
#include <linux/mfd/da9062/core.h>
#include <linux/mfd/da9062/registers.h>
/* Minimum, maximum and default polling millisecond periods are provided
* here as an example. It is expected that any final implementation to also
* include a modification of these settings to match the required
* application.
*/
#define DA9062_DEFAULT_POLLING_MS_PERIOD 3000
#define DA9062_MAX_POLLING_MS_PERIOD 10000
#define DA9062_MIN_POLLING_MS_PERIOD 1000
#define DA9062_MILLI_CELSIUS(t) ((t) * 1000)
struct
da9062_thermal_config
{
const
char
*
name
;
};
struct
da9062_thermal
{
struct
da9062
*
hw
;
struct
delayed_work
work
;
struct
thermal_zone_device
*
zone
;
enum
thermal_device_mode
mode
;
struct
mutex
lock
;
/* protection for da9062_thermal temperature */
int
temperature
;
int
irq
;
const
struct
da9062_thermal_config
*
config
;
struct
device
*
dev
;
};
static
void
da9062_thermal_poll_on
(
struct
work_struct
*
work
)
{
struct
da9062_thermal
*
thermal
=
container_of
(
work
,
struct
da9062_thermal
,
work
.
work
);
unsigned
long
delay
;
unsigned
int
val
;
int
ret
;
/* clear E_TEMP */
ret
=
regmap_write
(
thermal
->
hw
->
regmap
,
DA9062AA_EVENT_B
,
DA9062AA_E_TEMP_MASK
);
if
(
ret
<
0
)
{
dev_err
(
thermal
->
dev
,
"Cannot clear the TJUNC temperature status
\n
"
);
goto
err_enable_irq
;
}
/* Now read E_TEMP again: it is acting like a status bit.
* If over-temperature, then this status will be true.
* If not over-temperature, this status will be false.
*/
ret
=
regmap_read
(
thermal
->
hw
->
regmap
,
DA9062AA_EVENT_B
,
&
val
);
if
(
ret
<
0
)
{
dev_err
(
thermal
->
dev
,
"Cannot check the TJUNC temperature status
\n
"
);
goto
err_enable_irq
;
}
if
(
val
&
DA9062AA_E_TEMP_MASK
)
{
mutex_lock
(
&
thermal
->
lock
);
thermal
->
temperature
=
DA9062_MILLI_CELSIUS
(
125
);
mutex_unlock
(
&
thermal
->
lock
);
thermal_zone_device_update
(
thermal
->
zone
,
THERMAL_EVENT_UNSPECIFIED
);
delay
=
msecs_to_jiffies
(
thermal
->
zone
->
passive_delay
);
schedule_delayed_work
(
&
thermal
->
work
,
delay
);
return
;
}
mutex_lock
(
&
thermal
->
lock
);
thermal
->
temperature
=
DA9062_MILLI_CELSIUS
(
0
);
mutex_unlock
(
&
thermal
->
lock
);
thermal_zone_device_update
(
thermal
->
zone
,
THERMAL_EVENT_UNSPECIFIED
);
err_enable_irq:
enable_irq
(
thermal
->
irq
);
}
static
irqreturn_t
da9062_thermal_irq_handler
(
int
irq
,
void
*
data
)
{
struct
da9062_thermal
*
thermal
=
data
;
disable_irq_nosync
(
thermal
->
irq
);
schedule_delayed_work
(
&
thermal
->
work
,
0
);
return
IRQ_HANDLED
;
}
static
int
da9062_thermal_get_mode
(
struct
thermal_zone_device
*
z
,
enum
thermal_device_mode
*
mode
)
{
struct
da9062_thermal
*
thermal
=
z
->
devdata
;
*
mode
=
thermal
->
mode
;
return
0
;
}
static
int
da9062_thermal_get_trip_type
(
struct
thermal_zone_device
*
z
,
int
trip
,
enum
thermal_trip_type
*
type
)
{
struct
da9062_thermal
*
thermal
=
z
->
devdata
;
switch
(
trip
)
{
case
0
:
*
type
=
THERMAL_TRIP_HOT
;
break
;
default:
dev_err
(
thermal
->
dev
,
"Driver does not support more than 1 trip-wire
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
int
da9062_thermal_get_trip_temp
(
struct
thermal_zone_device
*
z
,
int
trip
,
int
*
temp
)
{
struct
da9062_thermal
*
thermal
=
z
->
devdata
;
switch
(
trip
)
{
case
0
:
*
temp
=
DA9062_MILLI_CELSIUS
(
125
);
break
;
default:
dev_err
(
thermal
->
dev
,
"Driver does not support more than 1 trip-wire
\n
"
);
return
-
EINVAL
;
}
return
0
;
}
static
int
da9062_thermal_get_temp
(
struct
thermal_zone_device
*
z
,
int
*
temp
)
{
struct
da9062_thermal
*
thermal
=
z
->
devdata
;
mutex_lock
(
&
thermal
->
lock
);
*
temp
=
thermal
->
temperature
;
mutex_unlock
(
&
thermal
->
lock
);
return
0
;
}
static
struct
thermal_zone_device_ops
da9062_thermal_ops
=
{
.
get_temp
=
da9062_thermal_get_temp
,
.
get_mode
=
da9062_thermal_get_mode
,
.
get_trip_type
=
da9062_thermal_get_trip_type
,
.
get_trip_temp
=
da9062_thermal_get_trip_temp
,
};
static
const
struct
da9062_thermal_config
da9062_config
=
{
.
name
=
"da9062-thermal"
,
};
static
const
struct
of_device_id
da9062_compatible_reg_id_table
[]
=
{
{
.
compatible
=
"dlg,da9062-thermal"
,
.
data
=
&
da9062_config
},
{
},
};
MODULE_DEVICE_TABLE
(
of
,
da9062_compatible_reg_id_table
);
static
int
da9062_thermal_probe
(
struct
platform_device
*
pdev
)
{
struct
da9062
*
chip
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
da9062_thermal
*
thermal
;
unsigned
int
pp_tmp
=
DA9062_DEFAULT_POLLING_MS_PERIOD
;
const
struct
of_device_id
*
match
;
int
ret
=
0
;
match
=
of_match_node
(
da9062_compatible_reg_id_table
,
pdev
->
dev
.
of_node
);
if
(
!
match
)
return
-
ENXIO
;
if
(
pdev
->
dev
.
of_node
)
{
if
(
!
of_property_read_u32
(
pdev
->
dev
.
of_node
,
"polling-delay-passive"
,
&
pp_tmp
))
{
if
(
pp_tmp
<
DA9062_MIN_POLLING_MS_PERIOD
||
pp_tmp
>
DA9062_MAX_POLLING_MS_PERIOD
)
{
dev_warn
(
&
pdev
->
dev
,
"Out-of-range polling period %d ms
\n
"
,
pp_tmp
);
pp_tmp
=
DA9062_DEFAULT_POLLING_MS_PERIOD
;
}
}
}
thermal
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
struct
da9062_thermal
),
GFP_KERNEL
);
if
(
!
thermal
)
{
ret
=
-
ENOMEM
;
goto
err
;
}
thermal
->
config
=
match
->
data
;
thermal
->
hw
=
chip
;
thermal
->
mode
=
THERMAL_DEVICE_ENABLED
;
thermal
->
dev
=
&
pdev
->
dev
;
INIT_DELAYED_WORK
(
&
thermal
->
work
,
da9062_thermal_poll_on
);
mutex_init
(
&
thermal
->
lock
);
thermal
->
zone
=
thermal_zone_device_register
(
thermal
->
config
->
name
,
1
,
0
,
thermal
,
&
da9062_thermal_ops
,
NULL
,
pp_tmp
,
0
);
if
(
IS_ERR
(
thermal
->
zone
))
{
dev_err
(
&
pdev
->
dev
,
"Cannot register thermal zone device
\n
"
);
ret
=
PTR_ERR
(
thermal
->
zone
);
goto
err
;
}
dev_dbg
(
&
pdev
->
dev
,
"TJUNC temperature polling period set at %d ms
\n
"
,
thermal
->
zone
->
passive_delay
);
ret
=
platform_get_irq_byname
(
pdev
,
"THERMAL"
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to get platform IRQ.
\n
"
);
goto
err_zone
;
}
thermal
->
irq
=
ret
;
ret
=
request_threaded_irq
(
thermal
->
irq
,
NULL
,
da9062_thermal_irq_handler
,
IRQF_TRIGGER_LOW
|
IRQF_ONESHOT
,
"THERMAL"
,
thermal
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to request thermal device IRQ.
\n
"
);
goto
err_zone
;
}
platform_set_drvdata
(
pdev
,
thermal
);
return
0
;
err_zone:
thermal_zone_device_unregister
(
thermal
->
zone
);
err:
return
ret
;
}
static
int
da9062_thermal_remove
(
struct
platform_device
*
pdev
)
{
struct
da9062_thermal
*
thermal
=
platform_get_drvdata
(
pdev
);
free_irq
(
thermal
->
irq
,
thermal
);
cancel_delayed_work_sync
(
&
thermal
->
work
);
thermal_zone_device_unregister
(
thermal
->
zone
);
return
0
;
}
static
struct
platform_driver
da9062_thermal_driver
=
{
.
probe
=
da9062_thermal_probe
,
.
remove
=
da9062_thermal_remove
,
.
driver
=
{
.
name
=
"da9062-thermal"
,
.
of_match_table
=
da9062_compatible_reg_id_table
,
},
};
module_platform_driver
(
da9062_thermal_driver
);
MODULE_AUTHOR
(
"Steve Twiss"
);
MODULE_DESCRIPTION
(
"Thermal TJUNC device driver for Dialog DA9062 and DA9061"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"platform:da9062-thermal"
);
drivers/thermal/mtk_thermal.c
View file @
cb15c81a
...
...
@@ -191,7 +191,7 @@ static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
};
static
const
int
mt8173_msr
[
MT8173_NUM_SENSORS_PER_ZONE
]
=
{
TEMP_MSR0
,
TEMP_MSR1
,
TEMP_MSR2
,
TEMP_MSR
2
TEMP_MSR0
,
TEMP_MSR1
,
TEMP_MSR2
,
TEMP_MSR
3
};
static
const
int
mt8173_adcpnp
[
MT8173_NUM_SENSORS_PER_ZONE
]
=
{
...
...
drivers/thermal/rcar_gen3_thermal.c
View file @
cb15c81a
...
...
@@ -20,12 +20,14 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spinlock.h>
#include <linux/thermal.h>
#include "thermal_core.h"
/* Register offsets */
#define REG_GEN3_IRQSTR 0x04
#define REG_GEN3_IRQMSK 0x08
...
...
@@ -41,6 +43,14 @@
#define REG_GEN3_THCODE2 0x54
#define REG_GEN3_THCODE3 0x58
/* IRQ{STR,MSK,EN} bits */
#define IRQ_TEMP1 BIT(0)
#define IRQ_TEMP2 BIT(1)
#define IRQ_TEMP3 BIT(2)
#define IRQ_TEMPD1 BIT(3)
#define IRQ_TEMPD2 BIT(4)
#define IRQ_TEMPD3 BIT(5)
/* CTSR bits */
#define CTSR_PONM BIT(8)
#define CTSR_AOUT BIT(7)
...
...
@@ -72,11 +82,15 @@ struct rcar_gen3_thermal_tsc {
void
__iomem
*
base
;
struct
thermal_zone_device
*
zone
;
struct
equation_coefs
coef
;
struct
mutex
lock
;
int
low
;
int
high
;
};
struct
rcar_gen3_thermal_priv
{
struct
rcar_gen3_thermal_tsc
*
tscs
[
TSC_MAX_NUM
];
unsigned
int
num_tscs
;
spinlock_t
lock
;
/* Protect interrupts on and off */
const
struct
rcar_gen3_thermal_data
*
data
;
};
struct
rcar_gen3_thermal_data
{
...
...
@@ -114,6 +128,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
#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)
...
...
@@ -163,16 +178,12 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
u32
reg
;
/* Read register and convert to mili Celsius */
mutex_lock
(
&
tsc
->
lock
);
reg
=
rcar_gen3_thermal_read
(
tsc
,
REG_GEN3_TEMP
)
&
CTEMP_MASK
;
val1
=
FIXPT_DIV
(
FIXPT_INT
(
reg
)
-
tsc
->
coef
.
b1
,
tsc
->
coef
.
a1
);
val2
=
FIXPT_DIV
(
FIXPT_INT
(
reg
)
-
tsc
->
coef
.
b2
,
tsc
->
coef
.
a2
);
mcelsius
=
FIXPT_TO_MCELSIUS
((
val1
+
val2
)
/
2
);
mutex_unlock
(
&
tsc
->
lock
);
/* Make sure we are inside specifications */
if
((
mcelsius
<
MCELSIUS
(
-
40
))
||
(
mcelsius
>
MCELSIUS
(
125
)))
return
-
EIO
;
...
...
@@ -183,10 +194,90 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
return
0
;
}
static
int
rcar_gen3_thermal_mcelsius_to_temp
(
struct
rcar_gen3_thermal_tsc
*
tsc
,
int
mcelsius
)
{
int
celsius
,
val1
,
val2
;
celsius
=
DIV_ROUND_CLOSEST
(
mcelsius
,
1000
);
val1
=
celsius
*
tsc
->
coef
.
a1
+
tsc
->
coef
.
b1
;
val2
=
celsius
*
tsc
->
coef
.
a2
+
tsc
->
coef
.
b2
;
return
INT_FIXPT
((
val1
+
val2
)
/
2
);
}
static
int
rcar_gen3_thermal_set_trips
(
void
*
devdata
,
int
low
,
int
high
)
{
struct
rcar_gen3_thermal_tsc
*
tsc
=
devdata
;
low
=
clamp_val
(
low
,
-
40000
,
125000
);
high
=
clamp_val
(
high
,
-
40000
,
125000
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQTEMP1
,
rcar_gen3_thermal_mcelsius_to_temp
(
tsc
,
low
));
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQTEMP2
,
rcar_gen3_thermal_mcelsius_to_temp
(
tsc
,
high
));
tsc
->
low
=
low
;
tsc
->
high
=
high
;
return
0
;
}
static
struct
thermal_zone_of_device_ops
rcar_gen3_tz_of_ops
=
{
.
get_temp
=
rcar_gen3_thermal_get_temp
,
.
set_trips
=
rcar_gen3_thermal_set_trips
,
};
static
void
rcar_thermal_irq_set
(
struct
rcar_gen3_thermal_priv
*
priv
,
bool
on
)
{
unsigned
int
i
;
u32
val
=
on
?
IRQ_TEMPD1
|
IRQ_TEMP2
:
0
;
for
(
i
=
0
;
i
<
priv
->
num_tscs
;
i
++
)
rcar_gen3_thermal_write
(
priv
->
tscs
[
i
],
REG_GEN3_IRQMSK
,
val
);
}
static
irqreturn_t
rcar_gen3_thermal_irq
(
int
irq
,
void
*
data
)
{
struct
rcar_gen3_thermal_priv
*
priv
=
data
;
u32
status
;
int
i
,
ret
=
IRQ_HANDLED
;
spin_lock
(
&
priv
->
lock
);
for
(
i
=
0
;
i
<
priv
->
num_tscs
;
i
++
)
{
status
=
rcar_gen3_thermal_read
(
priv
->
tscs
[
i
],
REG_GEN3_IRQSTR
);
rcar_gen3_thermal_write
(
priv
->
tscs
[
i
],
REG_GEN3_IRQSTR
,
0
);
if
(
status
)
ret
=
IRQ_WAKE_THREAD
;
}
if
(
ret
==
IRQ_WAKE_THREAD
)
rcar_thermal_irq_set
(
priv
,
false
);
spin_unlock
(
&
priv
->
lock
);
return
ret
;
}
static
irqreturn_t
rcar_gen3_thermal_irq_thread
(
int
irq
,
void
*
data
)
{
struct
rcar_gen3_thermal_priv
*
priv
=
data
;
unsigned
long
flags
;
int
i
;
for
(
i
=
0
;
i
<
priv
->
num_tscs
;
i
++
)
thermal_zone_device_update
(
priv
->
tscs
[
i
]
->
zone
,
THERMAL_EVENT_UNSPECIFIED
);
spin_lock_irqsave
(
&
priv
->
lock
,
flags
);
rcar_thermal_irq_set
(
priv
,
true
);
spin_unlock_irqrestore
(
&
priv
->
lock
,
flags
);
return
IRQ_HANDLED
;
}
static
void
r8a7795_thermal_init
(
struct
rcar_gen3_thermal_tsc
*
tsc
)
{
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_CTSR
,
CTSR_THBGR
);
...
...
@@ -195,7 +286,11 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
usleep_range
(
1000
,
2000
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_CTSR
,
CTSR_PONM
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQCTL
,
0x3F
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQMSK
,
0
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQEN
,
IRQ_TEMPD1
|
IRQ_TEMP2
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_CTSR
,
CTSR_PONM
|
CTSR_AOUT
|
CTSR_THBGR
|
CTSR_VMEN
);
...
...
@@ -219,9 +314,14 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
usleep_range
(
1000
,
2000
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQCTL
,
0x3F
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQMSK
,
0
);
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_IRQEN
,
IRQ_TEMPD1
|
IRQ_TEMP2
);
reg_val
=
rcar_gen3_thermal_read
(
tsc
,
REG_GEN3_THCTR
);
reg_val
|=
THCTR_THSST
;
rcar_gen3_thermal_write
(
tsc
,
REG_GEN3_THCTR
,
reg_val
);
usleep_range
(
1000
,
2000
);
}
static
const
struct
rcar_gen3_thermal_data
r8a7795_data
=
{
...
...
@@ -255,9 +355,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
struct
device
*
dev
=
&
pdev
->
dev
;
struct
resource
*
res
;
struct
thermal_zone_device
*
zone
;
int
ret
,
i
;
const
struct
rcar_gen3_thermal_data
*
match_data
=
of_device_get_match_data
(
dev
);
int
ret
,
irq
,
i
;
char
*
irqname
;
/* default values if FUSEs are missing */
/* TODO: Read values from hardware on supported platforms */
...
...
@@ -272,24 +371,50 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
if
(
!
priv
)
return
-
ENOMEM
;
priv
->
data
=
of_device_get_match_data
(
dev
);
spin_lock_init
(
&
priv
->
lock
);
platform_set_drvdata
(
pdev
,
priv
);
/*
* Request 2 (of the 3 possible) IRQs, the driver only needs to
* to trigger on the low and high trip points of the current
* temp window at this point.
*/
for
(
i
=
0
;
i
<
2
;
i
++
)
{
irq
=
platform_get_irq
(
pdev
,
i
);
if
(
irq
<
0
)
return
irq
;
irqname
=
devm_kasprintf
(
dev
,
GFP_KERNEL
,
"%s:ch%d"
,
dev_name
(
dev
),
i
);
if
(
!
irqname
)
return
-
ENOMEM
;
ret
=
devm_request_threaded_irq
(
dev
,
irq
,
rcar_gen3_thermal_irq
,
rcar_gen3_thermal_irq_thread
,
IRQF_SHARED
,
irqname
,
priv
);
if
(
ret
)
return
ret
;
}
pm_runtime_enable
(
dev
);
pm_runtime_get_sync
(
dev
);
for
(
i
=
0
;
i
<
TSC_MAX_NUM
;
i
++
)
{
struct
rcar_gen3_thermal_tsc
*
tsc
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
i
);
if
(
!
res
)
break
;
tsc
=
devm_kzalloc
(
dev
,
sizeof
(
*
tsc
),
GFP_KERNEL
);
if
(
!
tsc
)
{
ret
=
-
ENOMEM
;
goto
error_unregister
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
i
);
if
(
!
res
)
break
;
tsc
->
base
=
devm_ioremap_resource
(
dev
,
res
);
if
(
IS_ERR
(
tsc
->
base
))
{
ret
=
PTR_ERR
(
tsc
->
base
);
...
...
@@ -297,9 +422,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
}
priv
->
tscs
[
i
]
=
tsc
;
mutex_init
(
&
tsc
->
lock
);
match_
data
->
thermal_init
(
tsc
);
priv
->
data
->
thermal_init
(
tsc
);
rcar_gen3_thermal_calc_coefs
(
&
tsc
->
coef
,
ptat
,
thcode
[
i
]);
zone
=
devm_thermal_zone_of_sensor_register
(
dev
,
i
,
tsc
,
...
...
@@ -310,8 +434,23 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
goto
error_unregister
;
}
tsc
->
zone
=
zone
;
ret
=
of_thermal_get_ntrips
(
tsc
->
zone
);
if
(
ret
<
0
)
goto
error_unregister
;
dev_info
(
dev
,
"TSC%d: Loaded %d trip points
\n
"
,
i
,
ret
);
}
priv
->
num_tscs
=
i
;
if
(
!
priv
->
num_tscs
)
{
ret
=
-
ENODEV
;
goto
error_unregister
;
}
rcar_thermal_irq_set
(
priv
,
true
);
return
0
;
error_unregister:
...
...
@@ -320,9 +459,39 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
return
ret
;
}
static
int
__maybe_unused
rcar_gen3_thermal_suspend
(
struct
device
*
dev
)
{
struct
rcar_gen3_thermal_priv
*
priv
=
dev_get_drvdata
(
dev
);
rcar_thermal_irq_set
(
priv
,
false
);
return
0
;
}
static
int
__maybe_unused
rcar_gen3_thermal_resume
(
struct
device
*
dev
)
{
struct
rcar_gen3_thermal_priv
*
priv
=
dev_get_drvdata
(
dev
);
unsigned
int
i
;
for
(
i
=
0
;
i
<
priv
->
num_tscs
;
i
++
)
{
struct
rcar_gen3_thermal_tsc
*
tsc
=
priv
->
tscs
[
i
];
priv
->
data
->
thermal_init
(
tsc
);
rcar_gen3_thermal_set_trips
(
tsc
,
tsc
->
low
,
tsc
->
high
);
}
rcar_thermal_irq_set
(
priv
,
true
);
return
0
;
}
static
SIMPLE_DEV_PM_OPS
(
rcar_gen3_thermal_pm_ops
,
rcar_gen3_thermal_suspend
,
rcar_gen3_thermal_resume
);
static
struct
platform_driver
rcar_gen3_thermal_driver
=
{
.
driver
=
{
.
name
=
"rcar_gen3_thermal"
,
.
pm
=
&
rcar_gen3_thermal_pm_ops
,
.
of_match_table
=
rcar_gen3_thermal_dt_ids
,
},
.
probe
=
rcar_gen3_thermal_probe
,
...
...
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
View file @
cb15c81a
...
...
@@ -410,8 +410,6 @@ const struct ti_bandgap_data dra752_data = {
.
domain
=
"cpu"
,
.
register_cooling
=
ti_thermal_register_cpu_cooling
,
.
unregister_cooling
=
ti_thermal_unregister_cpu_cooling
,
.
slope
=
DRA752_GRADIENT_SLOPE
,
.
constant
=
DRA752_GRADIENT_CONST
,
.
slope_pcb
=
DRA752_GRADIENT_SLOPE_W_PCB
,
.
constant_pcb
=
DRA752_GRADIENT_CONST_W_PCB
,
},
...
...
@@ -419,8 +417,6 @@ const struct ti_bandgap_data dra752_data = {
.
registers
=
&
dra752_gpu_temp_sensor_registers
,
.
ts_data
=
&
dra752_gpu_temp_sensor_data
,
.
domain
=
"gpu"
,
.
slope
=
DRA752_GRADIENT_SLOPE
,
.
constant
=
DRA752_GRADIENT_CONST
,
.
slope_pcb
=
DRA752_GRADIENT_SLOPE_W_PCB
,
.
constant_pcb
=
DRA752_GRADIENT_CONST_W_PCB
,
},
...
...
@@ -428,8 +424,6 @@ const struct ti_bandgap_data dra752_data = {
.
registers
=
&
dra752_core_temp_sensor_registers
,
.
ts_data
=
&
dra752_core_temp_sensor_data
,
.
domain
=
"core"
,
.
slope
=
DRA752_GRADIENT_SLOPE
,
.
constant
=
DRA752_GRADIENT_CONST
,
.
slope_pcb
=
DRA752_GRADIENT_SLOPE_W_PCB
,
.
constant_pcb
=
DRA752_GRADIENT_CONST_W_PCB
,
},
...
...
@@ -437,8 +431,6 @@ const struct ti_bandgap_data dra752_data = {
.
registers
=
&
dra752_dspeve_temp_sensor_registers
,
.
ts_data
=
&
dra752_dspeve_temp_sensor_data
,
.
domain
=
"dspeve"
,
.
slope
=
DRA752_GRADIENT_SLOPE
,
.
constant
=
DRA752_GRADIENT_CONST
,
.
slope_pcb
=
DRA752_GRADIENT_SLOPE_W_PCB
,
.
constant_pcb
=
DRA752_GRADIENT_CONST_W_PCB
,
},
...
...
@@ -446,8 +438,6 @@ const struct ti_bandgap_data dra752_data = {
.
registers
=
&
dra752_iva_temp_sensor_registers
,
.
ts_data
=
&
dra752_iva_temp_sensor_data
,
.
domain
=
"iva"
,
.
slope
=
DRA752_GRADIENT_SLOPE
,
.
constant
=
DRA752_GRADIENT_CONST
,
.
slope_pcb
=
DRA752_GRADIENT_SLOPE_W_PCB
,
.
constant_pcb
=
DRA752_GRADIENT_CONST_W_PCB
,
},
...
...
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
View file @
cb15c81a
...
...
@@ -91,8 +91,6 @@ const struct ti_bandgap_data omap34xx_data = {
.
registers
=
&
omap34xx_mpu_temp_sensor_registers
,
.
ts_data
=
&
omap34xx_mpu_temp_sensor_data
,
.
domain
=
"cpu"
,
.
slope
=
0
,
.
constant
=
20000
,
.
slope_pcb
=
0
,
.
constant_pcb
=
20000
,
.
register_cooling
=
NULL
,
...
...
@@ -164,8 +162,6 @@ const struct ti_bandgap_data omap36xx_data = {
.
registers
=
&
omap36xx_mpu_temp_sensor_registers
,
.
ts_data
=
&
omap36xx_mpu_temp_sensor_data
,
.
domain
=
"cpu"
,
.
slope
=
0
,
.
constant
=
20000
,
.
slope_pcb
=
0
,
.
constant_pcb
=
20000
,
.
register_cooling
=
NULL
,
...
...
drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
View file @
cb15c81a
...
...
@@ -82,8 +82,6 @@ const struct ti_bandgap_data omap4430_data = {
.
registers
=
&
omap4430_mpu_temp_sensor_registers
,
.
ts_data
=
&
omap4430_mpu_temp_sensor_data
,
.
domain
=
"cpu"
,
.
slope
=
OMAP_GRADIENT_SLOPE_4430
,
.
constant
=
OMAP_GRADIENT_CONST_4430
,
.
slope_pcb
=
OMAP_GRADIENT_SLOPE_W_PCB_4430
,
.
constant_pcb
=
OMAP_GRADIENT_CONST_W_PCB_4430
,
.
register_cooling
=
ti_thermal_register_cpu_cooling
,
...
...
@@ -222,8 +220,6 @@ const struct ti_bandgap_data omap4460_data = {
.
registers
=
&
omap4460_mpu_temp_sensor_registers
,
.
ts_data
=
&
omap4460_mpu_temp_sensor_data
,
.
domain
=
"cpu"
,
.
slope
=
OMAP_GRADIENT_SLOPE_4460
,
.
constant
=
OMAP_GRADIENT_CONST_4460
,
.
slope_pcb
=
OMAP_GRADIENT_SLOPE_W_PCB_4460
,
.
constant_pcb
=
OMAP_GRADIENT_CONST_W_PCB_4460
,
.
register_cooling
=
ti_thermal_register_cpu_cooling
,
...
...
@@ -255,8 +251,6 @@ const struct ti_bandgap_data omap4470_data = {
.
registers
=
&
omap4460_mpu_temp_sensor_registers
,
.
ts_data
=
&
omap4460_mpu_temp_sensor_data
,
.
domain
=
"cpu"
,
.
slope
=
OMAP_GRADIENT_SLOPE_4470
,
.
constant
=
OMAP_GRADIENT_CONST_4470
,
.
slope_pcb
=
OMAP_GRADIENT_SLOPE_W_PCB_4470
,
.
constant_pcb
=
OMAP_GRADIENT_CONST_W_PCB_4470
,
.
register_cooling
=
ti_thermal_register_cpu_cooling
,
...
...
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
View file @
cb15c81a
...
...
@@ -336,8 +336,6 @@ const struct ti_bandgap_data omap5430_data = {
.
domain
=
"cpu"
,
.
register_cooling
=
ti_thermal_register_cpu_cooling
,
.
unregister_cooling
=
ti_thermal_unregister_cpu_cooling
,
.
slope
=
OMAP_GRADIENT_SLOPE_5430_CPU
,
.
constant
=
OMAP_GRADIENT_CONST_5430_CPU
,
.
slope_pcb
=
OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU
,
.
constant_pcb
=
OMAP_GRADIENT_CONST_W_PCB_5430_CPU
,
},
...
...
@@ -345,8 +343,6 @@ const struct ti_bandgap_data omap5430_data = {
.
registers
=
&
omap5430_gpu_temp_sensor_registers
,
.
ts_data
=
&
omap5430_gpu_temp_sensor_data
,
.
domain
=
"gpu"
,
.
slope
=
OMAP_GRADIENT_SLOPE_5430_GPU
,
.
constant
=
OMAP_GRADIENT_CONST_5430_GPU
,
.
slope_pcb
=
OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU
,
.
constant_pcb
=
OMAP_GRADIENT_CONST_W_PCB_5430_GPU
,
},
...
...
drivers/thermal/ti-soc-thermal/ti-bandgap.h
View file @
cb15c81a
...
...
@@ -254,8 +254,6 @@ struct ti_bandgap {
* @ts_data: pointer to struct with thresholds, limits of temperature sensor
* @registers: pointer to the list of register offsets and bitfields
* @domain: the name of the domain where the sensor is located
* @slope: sensor gradient slope info for hotspot extrapolation equation
* @constant: sensor gradient const info for hotspot extrapolation equation
* @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
* with no external influence
* @constant_pcb: sensor gradient const info for hotspot extrapolation equation
...
...
@@ -274,8 +272,6 @@ struct ti_temp_sensor {
struct
temp_sensor_registers
*
registers
;
char
*
domain
;
/* for hotspot extrapolation */
const
int
slope
;
const
int
constant
;
const
int
slope_pcb
;
const
int
constant_pcb
;
int
(
*
register_cooling
)(
struct
ti_bandgap
*
bgp
,
int
id
);
...
...
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
View file @
cb15c81a
...
...
@@ -96,8 +96,8 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp)
return
ret
;
/* Default constants */
slope
=
s
->
slope
;
constant
=
s
->
constant
;
slope
=
thermal_zone_get_slope
(
data
->
ti_thermal
)
;
constant
=
thermal_zone_get_offset
(
data
->
ti_thermal
)
;
pcb_tz
=
data
->
pcb_tz
;
/* In case pcb zone is available, use the extrapolation rule with it */
...
...
@@ -126,119 +126,6 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
return
__ti_thermal_get_temp
(
data
,
temp
);
}
/* Bind callback functions for thermal zone */
static
int
ti_thermal_bind
(
struct
thermal_zone_device
*
thermal
,
struct
thermal_cooling_device
*
cdev
)
{
struct
ti_thermal_data
*
data
=
thermal
->
devdata
;
int
id
;
if
(
!
data
||
IS_ERR
(
data
))
return
-
ENODEV
;
/* check if this is the cooling device we registered */
if
(
data
->
cool_dev
!=
cdev
)
return
0
;
id
=
data
->
sensor_id
;
/* Simple thing, two trips, one passive another critical */
return
thermal_zone_bind_cooling_device
(
thermal
,
0
,
cdev
,
/* bind with min and max states defined by cpu_cooling */
THERMAL_NO_LIMIT
,
THERMAL_NO_LIMIT
,
THERMAL_WEIGHT_DEFAULT
);
}
/* Unbind callback functions for thermal zone */
static
int
ti_thermal_unbind
(
struct
thermal_zone_device
*
thermal
,
struct
thermal_cooling_device
*
cdev
)
{
struct
ti_thermal_data
*
data
=
thermal
->
devdata
;
if
(
!
data
||
IS_ERR
(
data
))
return
-
ENODEV
;
/* check if this is the cooling device we registered */
if
(
data
->
cool_dev
!=
cdev
)
return
0
;
/* Simple thing, two trips, one passive another critical */
return
thermal_zone_unbind_cooling_device
(
thermal
,
0
,
cdev
);
}
/* Get mode callback functions for thermal zone */
static
int
ti_thermal_get_mode
(
struct
thermal_zone_device
*
thermal
,
enum
thermal_device_mode
*
mode
)
{
struct
ti_thermal_data
*
data
=
thermal
->
devdata
;
if
(
data
)
*
mode
=
data
->
mode
;
return
0
;
}
/* Set mode callback functions for thermal zone */
static
int
ti_thermal_set_mode
(
struct
thermal_zone_device
*
thermal
,
enum
thermal_device_mode
mode
)
{
struct
ti_thermal_data
*
data
=
thermal
->
devdata
;
struct
ti_bandgap
*
bgp
;
bgp
=
data
->
bgp
;
if
(
!
data
->
ti_thermal
)
{
dev_notice
(
&
thermal
->
device
,
"thermal zone not registered
\n
"
);
return
0
;
}
mutex_lock
(
&
data
->
ti_thermal
->
lock
);
if
(
mode
==
THERMAL_DEVICE_ENABLED
)
data
->
ti_thermal
->
polling_delay
=
FAST_TEMP_MONITORING_RATE
;
else
data
->
ti_thermal
->
polling_delay
=
0
;
mutex_unlock
(
&
data
->
ti_thermal
->
lock
);
data
->
mode
=
mode
;
ti_bandgap_write_update_interval
(
bgp
,
data
->
sensor_id
,
data
->
ti_thermal
->
polling_delay
);
thermal_zone_device_update
(
data
->
ti_thermal
,
THERMAL_EVENT_UNSPECIFIED
);
dev_dbg
(
&
thermal
->
device
,
"thermal polling set for duration=%d msec
\n
"
,
data
->
ti_thermal
->
polling_delay
);
return
0
;
}
/* Get trip type callback functions for thermal zone */
static
int
ti_thermal_get_trip_type
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
enum
thermal_trip_type
*
type
)
{
if
(
!
ti_thermal_is_valid_trip
(
trip
))
return
-
EINVAL
;
if
(
trip
+
1
==
OMAP_TRIP_NUMBER
)
*
type
=
THERMAL_TRIP_CRITICAL
;
else
*
type
=
THERMAL_TRIP_PASSIVE
;
return
0
;
}
/* Get trip temperature callback functions for thermal zone */
static
int
ti_thermal_get_trip_temp
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
int
*
temp
)
{
if
(
!
ti_thermal_is_valid_trip
(
trip
))
return
-
EINVAL
;
*
temp
=
ti_thermal_get_trip_value
(
trip
);
return
0
;
}
static
int
__ti_thermal_get_trend
(
void
*
p
,
int
trip
,
enum
thermal_trend
*
trend
)
{
struct
ti_thermal_data
*
data
=
p
;
...
...
@@ -262,38 +149,11 @@ static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
return
0
;
}
/* Get the temperature trend callback functions for thermal zone */
static
int
ti_thermal_get_trend
(
struct
thermal_zone_device
*
thermal
,
int
trip
,
enum
thermal_trend
*
trend
)
{
return
__ti_thermal_get_trend
(
thermal
->
devdata
,
trip
,
trend
);
}
/* Get critical temperature callback functions for thermal zone */
static
int
ti_thermal_get_crit_temp
(
struct
thermal_zone_device
*
thermal
,
int
*
temp
)
{
/* shutdown zone */
return
ti_thermal_get_trip_temp
(
thermal
,
OMAP_TRIP_NUMBER
-
1
,
temp
);
}
static
const
struct
thermal_zone_of_device_ops
ti_of_thermal_ops
=
{
.
get_temp
=
__ti_thermal_get_temp
,
.
get_trend
=
__ti_thermal_get_trend
,
};
static
struct
thermal_zone_device_ops
ti_thermal_ops
=
{
.
get_temp
=
ti_thermal_get_temp
,
.
get_trend
=
ti_thermal_get_trend
,
.
bind
=
ti_thermal_bind
,
.
unbind
=
ti_thermal_unbind
,
.
get_mode
=
ti_thermal_get_mode
,
.
set_mode
=
ti_thermal_set_mode
,
.
get_trip_type
=
ti_thermal_get_trip_type
,
.
get_trip_temp
=
ti_thermal_get_trip_temp
,
.
get_crit_temp
=
ti_thermal_get_crit_temp
,
};
static
struct
ti_thermal_data
*
ti_thermal_build_data
(
struct
ti_bandgap
*
bgp
,
int
id
)
{
...
...
@@ -331,18 +191,10 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
data
->
ti_thermal
=
devm_thermal_zone_of_sensor_register
(
bgp
->
dev
,
id
,
data
,
&
ti_of_thermal_ops
);
if
(
IS_ERR
(
data
->
ti_thermal
))
{
/* Create thermal zone */
data
->
ti_thermal
=
thermal_zone_device_register
(
domain
,
OMAP_TRIP_NUMBER
,
0
,
data
,
&
ti_thermal_ops
,
NULL
,
FAST_TEMP_MONITORING_RATE
,
FAST_TEMP_MONITORING_RATE
);
if
(
IS_ERR
(
data
->
ti_thermal
))
{
dev_err
(
bgp
->
dev
,
"thermal zone device is NULL
\n
"
);
return
PTR_ERR
(
data
->
ti_thermal
);
}
data
->
ti_thermal
->
polling_delay
=
FAST_TEMP_MONITORING_RATE
;
data
->
our_zone
=
true
;
dev_err
(
bgp
->
dev
,
"thermal zone device is NULL
\n
"
);
return
PTR_ERR
(
data
->
ti_thermal
);
}
ti_bandgap_set_sensor_data
(
bgp
,
id
,
data
);
ti_bandgap_write_update_interval
(
bgp
,
data
->
sensor_id
,
data
->
ti_thermal
->
polling_delay
);
...
...
drivers/thermal/ti-soc-thermal/ti-thermal.h
View file @
cb15c81a
...
...
@@ -25,22 +25,6 @@
#include "ti-bandgap.h"
/* sensors gradient and offsets */
#define OMAP_GRADIENT_SLOPE_4430 0
#define OMAP_GRADIENT_CONST_4430 20000
#define OMAP_GRADIENT_SLOPE_4460 348
#define OMAP_GRADIENT_CONST_4460 -9301
#define OMAP_GRADIENT_SLOPE_4470 308
#define OMAP_GRADIENT_CONST_4470 -7896
#define OMAP_GRADIENT_SLOPE_5430_CPU 65
#define OMAP_GRADIENT_CONST_5430_CPU -1791
#define OMAP_GRADIENT_SLOPE_5430_GPU 117
#define OMAP_GRADIENT_CONST_5430_GPU -2992
#define DRA752_GRADIENT_SLOPE 0
#define DRA752_GRADIENT_CONST 2000
/* PCB sensor calculation constants */
#define OMAP_GRADIENT_SLOPE_W_PCB_4430 0
#define OMAP_GRADIENT_CONST_W_PCB_4430 20000
...
...
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