Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui: "There are not too many changes this time, except two new platform thermal drivers, ti-soc-thermal driver and x86_pkg_temp_thermal driver, and a couple of small fixes. Highlights: - move the ti-soc-thermal driver out of the staging tree to the thermal tree. - introduce the x86_pkg_temp_thermal driver. This driver registers CPU digital temperature package level sensor as a thermal zone. - small fixes/cleanups including removing redundant use of platform_set_drvdata() and of_match_ptr for all platform thermal drivers" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (34 commits) thermal: cpu_cooling: fix stub function thermal: ti-soc-thermal: use standard GPIO DT bindings thermal: MAINTAINERS: Add git tree path for SoC specific updates thermal: fix x86_pkg_temp_thermal.c build and Kconfig Thermal: Documentation for x86 package temperature thermal driver Thermal: CPU Package temperature thermal thermal: consider emul_temperature while computing trend thermal: ti-soc-thermal: add DT example for DRA752 chip thermal: ti-soc-thermal: add dra752 chip to device table thermal: ti-soc-thermal: add thermal data for DRA752 chips thermal: ti-soc-thermal: remove usage of IS_ERR_OR_NULL thermal: ti-soc-thermal: freeze FSM while computing trend thermal: ti-soc-thermal: remove external heat while extrapolating hotspot thermal: ti-soc-thermal: update DT reference for OMAP5430 x86, mcheck, therm_throt: Process package thresholds thermal: cpu_cooling: fix 'descend' check in get_property() Thermal: spear: Remove redundant use of of_match_ptr Thermal: kirkwood: Remove redundant use of of_match_ptr Thermal: dove: Remove redundant use of of_match_ptr Thermal: armada: Remove redundant use of of_match_ptr ...
This commit is contained in:
commit
8cbd0eefca
|
@ -17,8 +17,9 @@ Required properties:
|
|||
- interrupts : this entry should indicate which interrupt line
|
||||
the talert signal is routed to;
|
||||
Specific:
|
||||
- ti,tshut-gpio : this entry should be used to inform which GPIO
|
||||
line the tshut signal is routed to;
|
||||
- gpios : this entry should be used to inform which GPIO
|
||||
line the tshut signal is routed to. The informed GPIO will
|
||||
be treated as an IRQ;
|
||||
- regs : this entry must also be specified and it is specific
|
||||
to each bandgap version, because the mapping may change from
|
||||
soc to soc, apart of depending on available features.
|
||||
|
@ -37,7 +38,7 @@ bandgap {
|
|||
0x4a002378 0x18>;
|
||||
compatible = "ti,omap4460-bandgap";
|
||||
interrupts = <0 126 4>; /* talert */
|
||||
ti,tshut-gpio = <86>;
|
||||
gpios = <&gpio3 22 0>; /* tshut */
|
||||
};
|
||||
|
||||
OMAP4470:
|
||||
|
@ -47,7 +48,7 @@ bandgap {
|
|||
0x4a002378 0x18>;
|
||||
compatible = "ti,omap4470-bandgap";
|
||||
interrupts = <0 126 4>; /* talert */
|
||||
ti,tshut-gpio = <86>;
|
||||
gpios = <&gpio3 22 0>; /* tshut */
|
||||
};
|
||||
|
||||
OMAP5430:
|
||||
|
@ -59,3 +60,15 @@ bandgap {
|
|||
compatible = "ti,omap5430-bandgap";
|
||||
interrupts = <0 126 4>; /* talert */
|
||||
};
|
||||
|
||||
DRA752:
|
||||
bandgap {
|
||||
reg = <0x4a0021e0 0xc
|
||||
0x4a00232c 0xc
|
||||
0x4a002380 0x2c
|
||||
0x4a0023C0 0x3c
|
||||
0x4a002564 0x8
|
||||
0x4a002574 0x50>;
|
||||
compatible = "ti,dra752-bandgap";
|
||||
interrupts = <0 126 4>; /* talert */
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
Kernel driver: x86_pkg_temp_thermal
|
||||
===================
|
||||
|
||||
Supported chips:
|
||||
* x86: with package level thermal management
|
||||
(Verify using: CPUID.06H:EAX[bit 6] =1)
|
||||
|
||||
Authors: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
|
||||
Reference
|
||||
---
|
||||
Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013):
|
||||
Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT
|
||||
|
||||
Description
|
||||
---------
|
||||
|
||||
This driver register CPU digital temperature package level sensor as a thermal
|
||||
zone with maximum two user mode configurable trip points. Number of trip points
|
||||
depends on the capability of the package. Once the trip point is violated,
|
||||
user mode can receive notification via thermal notification mechanism and can
|
||||
take any action to control temperature.
|
||||
|
||||
|
||||
Threshold management
|
||||
--------------------
|
||||
Each package will register as a thermal zone under /sys/class/thermal.
|
||||
Example:
|
||||
/sys/class/thermal/thermal_zone1
|
||||
|
||||
This contains two trip points:
|
||||
- trip_point_0_temp
|
||||
- trip_point_1_temp
|
||||
|
||||
User can set any temperature between 0 to TJ-Max temperature. Temperature units
|
||||
are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.txt" for
|
||||
thermal sys-fs details.
|
||||
|
||||
Any value other than 0 in these trip points, can trigger thermal notifications.
|
||||
Setting 0, stops sending thermal notifications.
|
||||
|
||||
Thermal notifications: To get kobject-uevent notifications, set the thermal zone
|
||||
policy to "user_space". For example: echo -n "user_space" > policy
|
||||
|
||||
|
||||
|
||||
|
|
@ -8159,6 +8159,7 @@ M: Zhang Rui <rui.zhang@intel.com>
|
|||
M: Eduardo Valentin <eduardo.valentin@ti.com>
|
||||
L: linux-pm@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
|
||||
Q: https://patchwork.kernel.org/project/linux-pm/list/
|
||||
S: Supported
|
||||
F: drivers/thermal/
|
||||
|
@ -8183,8 +8184,8 @@ F: drivers/platform/x86/thinkpad_acpi.c
|
|||
TI BANDGAP AND THERMAL DRIVER
|
||||
M: Eduardo Valentin <eduardo.valentin@ti.com>
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/staging/omap-thermal/
|
||||
S: Supported
|
||||
F: drivers/thermal/ti-soc-thermal/
|
||||
|
||||
TI FLASH MEDIA INTERFACE DRIVER
|
||||
M: Alex Dubov <oakad@yahoo.com>
|
||||
|
|
|
@ -214,6 +214,13 @@ void mce_log_therm_throt_event(__u64 status);
|
|||
/* Interrupt Handler for core thermal thresholds */
|
||||
extern int (*platform_thermal_notify)(__u64 msr_val);
|
||||
|
||||
/* Interrupt Handler for package thermal thresholds */
|
||||
extern int (*platform_thermal_package_notify)(__u64 msr_val);
|
||||
|
||||
/* Callback support of rate control, return true, if
|
||||
* callback has rate control */
|
||||
extern bool (*platform_thermal_package_rate_control)(void);
|
||||
|
||||
#ifdef CONFIG_X86_THERMAL_VECTOR
|
||||
extern void mcheck_intel_therm_init(void);
|
||||
#else
|
||||
|
|
|
@ -55,12 +55,24 @@ struct thermal_state {
|
|||
struct _thermal_state package_power_limit;
|
||||
struct _thermal_state core_thresh0;
|
||||
struct _thermal_state core_thresh1;
|
||||
struct _thermal_state pkg_thresh0;
|
||||
struct _thermal_state pkg_thresh1;
|
||||
};
|
||||
|
||||
/* Callback to handle core threshold interrupts */
|
||||
int (*platform_thermal_notify)(__u64 msr_val);
|
||||
EXPORT_SYMBOL(platform_thermal_notify);
|
||||
|
||||
/* Callback to handle core package threshold_interrupts */
|
||||
int (*platform_thermal_package_notify)(__u64 msr_val);
|
||||
EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
|
||||
|
||||
/* Callback support of rate control, return true, if
|
||||
* callback has rate control */
|
||||
bool (*platform_thermal_package_rate_control)(void);
|
||||
EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
|
||||
|
||||
|
||||
static DEFINE_PER_CPU(struct thermal_state, thermal_state);
|
||||
|
||||
static atomic_t therm_throt_en = ATOMIC_INIT(0);
|
||||
|
@ -195,19 +207,25 @@ static int therm_throt_process(bool new_event, int event, int level)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int thresh_event_valid(int event)
|
||||
static int thresh_event_valid(int level, int event)
|
||||
{
|
||||
struct _thermal_state *state;
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
|
||||
u64 now = get_jiffies_64();
|
||||
|
||||
state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1;
|
||||
if (level == PACKAGE_LEVEL)
|
||||
state = (event == 0) ? &pstate->pkg_thresh0 :
|
||||
&pstate->pkg_thresh1;
|
||||
else
|
||||
state = (event == 0) ? &pstate->core_thresh0 :
|
||||
&pstate->core_thresh1;
|
||||
|
||||
if (time_before64(now, state->next_check))
|
||||
return 0;
|
||||
|
||||
state->next_check = now + CHECK_INTERVAL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -322,6 +340,39 @@ device_initcall(thermal_throttle_init_device);
|
|||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
static void notify_package_thresholds(__u64 msr_val)
|
||||
{
|
||||
bool notify_thres_0 = false;
|
||||
bool notify_thres_1 = false;
|
||||
|
||||
if (!platform_thermal_package_notify)
|
||||
return;
|
||||
|
||||
/* lower threshold check */
|
||||
if (msr_val & THERM_LOG_THRESHOLD0)
|
||||
notify_thres_0 = true;
|
||||
/* higher threshold check */
|
||||
if (msr_val & THERM_LOG_THRESHOLD1)
|
||||
notify_thres_1 = true;
|
||||
|
||||
if (!notify_thres_0 && !notify_thres_1)
|
||||
return;
|
||||
|
||||
if (platform_thermal_package_rate_control &&
|
||||
platform_thermal_package_rate_control()) {
|
||||
/* Rate control is implemented in callback */
|
||||
platform_thermal_package_notify(msr_val);
|
||||
return;
|
||||
}
|
||||
|
||||
/* lower threshold reached */
|
||||
if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
|
||||
platform_thermal_package_notify(msr_val);
|
||||
/* higher threshold reached */
|
||||
if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
|
||||
platform_thermal_package_notify(msr_val);
|
||||
}
|
||||
|
||||
static void notify_thresholds(__u64 msr_val)
|
||||
{
|
||||
/* check whether the interrupt handler is defined;
|
||||
|
@ -331,10 +382,12 @@ static void notify_thresholds(__u64 msr_val)
|
|||
return;
|
||||
|
||||
/* lower threshold reached */
|
||||
if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0))
|
||||
if ((msr_val & THERM_LOG_THRESHOLD0) &&
|
||||
thresh_event_valid(CORE_LEVEL, 0))
|
||||
platform_thermal_notify(msr_val);
|
||||
/* higher threshold reached */
|
||||
if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1))
|
||||
if ((msr_val & THERM_LOG_THRESHOLD1) &&
|
||||
thresh_event_valid(CORE_LEVEL, 1))
|
||||
platform_thermal_notify(msr_val);
|
||||
}
|
||||
|
||||
|
@ -360,6 +413,8 @@ static void intel_thermal_interrupt(void)
|
|||
|
||||
if (this_cpu_has(X86_FEATURE_PTS)) {
|
||||
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
|
||||
/* check violations of package thermal thresholds */
|
||||
notify_package_thresholds(msr_val);
|
||||
therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
|
||||
THERMAL_THROTTLING_EVENT,
|
||||
PACKAGE_LEVEL);
|
||||
|
|
|
@ -120,8 +120,6 @@ source "drivers/staging/gdm72xx/Kconfig"
|
|||
|
||||
source "drivers/staging/csr/Kconfig"
|
||||
|
||||
source "drivers/staging/ti-soc-thermal/Kconfig"
|
||||
|
||||
source "drivers/staging/silicom/Kconfig"
|
||||
|
||||
source "drivers/staging/ced1401/Kconfig"
|
||||
|
|
|
@ -53,7 +53,6 @@ obj-$(CONFIG_ANDROID) += android/
|
|||
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
|
||||
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
|
||||
obj-$(CONFIG_CSR_WIFI) += csr/
|
||||
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
|
||||
obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/
|
||||
obj-$(CONFIG_CED1401) += ced1401/
|
||||
obj-$(CONFIG_DRM_IMX) += imx-drm/
|
||||
|
|
|
@ -169,4 +169,19 @@ config INTEL_POWERCLAMP
|
|||
enforce idle time which results in more package C-state residency. The
|
||||
user interface is exposed via generic thermal framework.
|
||||
|
||||
config X86_PKG_TEMP_THERMAL
|
||||
tristate "X86 package temperature thermal driver"
|
||||
depends on X86_THERMAL_VECTOR
|
||||
select THERMAL_GOV_USER_SPACE
|
||||
default m
|
||||
help
|
||||
Enable this to register CPU digital sensor for package temperature as
|
||||
thermal zone. Each package will have its own thermal zone. There are
|
||||
two trip points which can be set by user to get notifications via thermal
|
||||
notification methods.
|
||||
|
||||
menu "Texas Instruments thermal drivers"
|
||||
source "drivers/thermal/ti-soc-thermal/Kconfig"
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
|
|
@ -23,4 +23,5 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
|
|||
obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
|
||||
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
|
||||
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
|
||||
|
||||
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
|
||||
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
|
||||
|
|
|
@ -200,7 +200,6 @@ static int armada_thermal_exit(struct platform_device *pdev)
|
|||
platform_get_drvdata(pdev);
|
||||
|
||||
thermal_zone_device_unregister(armada_thermal);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,7 +210,7 @@ static struct platform_driver armada_thermal_driver = {
|
|||
.driver = {
|
||||
.name = "armada_thermal",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(armada_thermal_id_table),
|
||||
.of_match_table = armada_thermal_id_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ static int get_property(unsigned int cpu, unsigned long input,
|
|||
continue;
|
||||
|
||||
/* get the frequency order */
|
||||
if (freq != CPUFREQ_ENTRY_INVALID && descend != -1)
|
||||
if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
|
||||
descend = !!(freq > table[i].frequency);
|
||||
|
||||
freq = table[i].frequency;
|
||||
|
|
|
@ -134,16 +134,11 @@ static int dove_thermal_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get platform resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->sensor = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(priv->sensor))
|
||||
return PTR_ERR(priv->sensor);
|
||||
|
@ -178,7 +173,6 @@ static int dove_thermal_exit(struct platform_device *pdev)
|
|||
platform_get_drvdata(pdev);
|
||||
|
||||
thermal_zone_device_unregister(dove_thermal);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -191,7 +185,7 @@ static struct platform_driver dove_thermal_driver = {
|
|||
.driver = {
|
||||
.name = "dove_thermal",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(dove_thermal_id_table),
|
||||
.of_match_table = dove_thermal_id_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -997,7 +997,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
err_clk:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
clk_unprepare(data->clk);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1012,8 +1011,6 @@ static int exynos_tmu_remove(struct platform_device *pdev)
|
|||
|
||||
clk_unprepare(data->clk);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,16 +75,11 @@ static int kirkwood_thermal_probe(struct platform_device *pdev)
|
|||
struct kirkwood_thermal_priv *priv;
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get platform resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->sensor = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(priv->sensor))
|
||||
return PTR_ERR(priv->sensor);
|
||||
|
@ -108,7 +103,6 @@ static int kirkwood_thermal_exit(struct platform_device *pdev)
|
|||
platform_get_drvdata(pdev);
|
||||
|
||||
thermal_zone_device_unregister(kirkwood_thermal);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -121,7 +115,7 @@ static struct platform_driver kirkwood_thermal_driver = {
|
|||
.driver = {
|
||||
.name = "kirkwood_thermal",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(kirkwood_thermal_id_table),
|
||||
.of_match_table = kirkwood_thermal_id_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -389,11 +389,6 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||
* platform has IRQ support.
|
||||
* Then, drier use common register
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
|
||||
if (!res) {
|
||||
dev_err(dev, "Could not get platform resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
|
||||
dev_name(dev), common);
|
||||
|
@ -405,6 +400,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||
/*
|
||||
* rcar_has_irq_support() will be enabled
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
|
||||
common->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(common->base))
|
||||
return PTR_ERR(common->base);
|
||||
|
@ -458,7 +454,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, common);
|
||||
|
||||
dev_info(dev, "%d sensor proved\n", i);
|
||||
dev_info(dev, "%d sensor probed\n", i);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -487,8 +483,6 @@ static int rcar_thermal_remove(struct platform_device *pdev)
|
|||
rcar_thermal_irq_disable(priv);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
|
|||
struct thermal_zone_device *spear_thermal = NULL;
|
||||
struct spear_thermal_dev *stdev;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *res;
|
||||
int ret = 0, val;
|
||||
|
||||
if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
|
||||
|
@ -112,11 +112,6 @@ static int spear_thermal_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!stres) {
|
||||
dev_err(&pdev->dev, "memory resource missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL);
|
||||
if (!stdev) {
|
||||
dev_err(&pdev->dev, "kzalloc fail\n");
|
||||
|
@ -124,12 +119,10 @@ static int spear_thermal_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Enable thermal sensor */
|
||||
stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start,
|
||||
resource_size(stres));
|
||||
if (!stdev->thermal_base) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(stdev->thermal_base))
|
||||
return PTR_ERR(stdev->thermal_base);
|
||||
|
||||
stdev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(stdev->clk)) {
|
||||
|
@ -174,7 +167,6 @@ static int spear_thermal_exit(struct platform_device *pdev)
|
|||
struct spear_thermal_dev *stdev = spear_thermal->devdata;
|
||||
|
||||
thermal_zone_device_unregister(spear_thermal);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
/* Disable SPEAr Thermal Sensor */
|
||||
actual_mask = readl_relaxed(stdev->thermal_base);
|
||||
|
@ -198,7 +190,7 @@ static struct platform_driver spear_thermal_driver = {
|
|||
.name = "spear_thermal",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &spear_thermal_pm_ops,
|
||||
.of_match_table = of_match_ptr(spear_thermal_id_table),
|
||||
.of_match_table = spear_thermal_id_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/idr.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/string.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/genetlink.h>
|
||||
|
||||
|
@ -155,7 +156,8 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip)
|
|||
{
|
||||
enum thermal_trend trend;
|
||||
|
||||
if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
|
||||
if (tz->emul_temperature || !tz->ops->get_trend ||
|
||||
tz->ops->get_trend(tz, trip, &trend)) {
|
||||
if (tz->temperature > tz->last_temperature)
|
||||
trend = THERMAL_TREND_RAISING;
|
||||
else if (tz->temperature < tz->last_temperature)
|
||||
|
@ -713,10 +715,13 @@ policy_store(struct device *dev, struct device_attribute *attr,
|
|||
int ret = -EINVAL;
|
||||
struct thermal_zone_device *tz = to_thermal_zone(dev);
|
||||
struct thermal_governor *gov;
|
||||
char name[THERMAL_NAME_LENGTH];
|
||||
|
||||
snprintf(name, sizeof(name), "%s", buf);
|
||||
|
||||
mutex_lock(&thermal_governor_lock);
|
||||
|
||||
gov = __find_governor(buf);
|
||||
gov = __find_governor(strim(name));
|
||||
if (!gov)
|
||||
goto exit;
|
||||
|
||||
|
@ -1624,7 +1629,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
|
|||
if (!ops || !ops->get_temp)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (trips > 0 && !ops->get_trip_type)
|
||||
if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
|
||||
|
|
|
@ -46,3 +46,15 @@ config OMAP5_THERMAL
|
|||
|
||||
This includes alert interrupts generation and also the TSHUT
|
||||
support.
|
||||
|
||||
config DRA752_THERMAL
|
||||
bool "Texas Instruments DRA752 thermal support"
|
||||
depends on TI_SOC_THERMAL
|
||||
depends on SOC_DRA7XX
|
||||
help
|
||||
If you say yes here you get thermal support for the Texas Instruments
|
||||
DRA752 SoC family. The current chip supported are:
|
||||
- DRA752
|
||||
|
||||
This includes alert interrupts generation and also the TSHUT
|
||||
support.
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o
|
||||
ti-soc-thermal-y := ti-bandgap.o
|
||||
ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o
|
||||
ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o
|
||||
ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o
|
||||
ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* DRA752 bandgap registers, bitfields and temperature definitions
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Contact:
|
||||
* Eduardo Valentin <eduardo.valentin@ti.com>
|
||||
* Tero Kristo <t-kristo@ti.com>
|
||||
*
|
||||
* This is an auto generated file.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __DRA752_BANDGAP_H
|
||||
#define __DRA752_BANDGAP_H
|
||||
|
||||
/**
|
||||
* *** DRA752 ***
|
||||
*
|
||||
* Below, in sequence, are the Register definitions,
|
||||
* the bitfields and the temperature definitions for DRA752.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DRA752 register definitions
|
||||
*
|
||||
* Registers are defined as offsets. The offsets are
|
||||
* relative to FUSE_OPP_BGAP_GPU on DRA752.
|
||||
* DRA752_BANDGAP_BASE 0x4a0021e0
|
||||
*
|
||||
* Register below are grouped by domain (not necessarily in offset order)
|
||||
*/
|
||||
|
||||
|
||||
/* DRA752.common register offsets */
|
||||
#define DRA752_BANDGAP_CTRL_1_OFFSET 0x1a0
|
||||
#define DRA752_BANDGAP_STATUS_1_OFFSET 0x1c8
|
||||
#define DRA752_BANDGAP_CTRL_2_OFFSET 0x39c
|
||||
#define DRA752_BANDGAP_STATUS_2_OFFSET 0x3b8
|
||||
|
||||
/* DRA752.core register offsets */
|
||||
#define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8
|
||||
#define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154
|
||||
#define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac
|
||||
#define DRA752_BANDGAP_TSHUT_CORE_OFFSET 0x1b8
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4
|
||||
#define DRA752_DTEMP_CORE_0_OFFSET 0x208
|
||||
#define DRA752_DTEMP_CORE_1_OFFSET 0x20c
|
||||
#define DRA752_DTEMP_CORE_2_OFFSET 0x210
|
||||
#define DRA752_DTEMP_CORE_3_OFFSET 0x214
|
||||
#define DRA752_DTEMP_CORE_4_OFFSET 0x218
|
||||
|
||||
/* DRA752.iva register offsets */
|
||||
#define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388
|
||||
#define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398
|
||||
#define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4
|
||||
#define DRA752_BANDGAP_TSHUT_IVA_OFFSET 0x3ac
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4
|
||||
#define DRA752_DTEMP_IVA_0_OFFSET 0x3d0
|
||||
#define DRA752_DTEMP_IVA_1_OFFSET 0x3d4
|
||||
#define DRA752_DTEMP_IVA_2_OFFSET 0x3d8
|
||||
#define DRA752_DTEMP_IVA_3_OFFSET 0x3dc
|
||||
#define DRA752_DTEMP_IVA_4_OFFSET 0x3e0
|
||||
|
||||
/* DRA752.mpu register offsets */
|
||||
#define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4
|
||||
#define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c
|
||||
#define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4
|
||||
#define DRA752_BANDGAP_TSHUT_MPU_OFFSET 0x1b0
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc
|
||||
#define DRA752_DTEMP_MPU_0_OFFSET 0x1e0
|
||||
#define DRA752_DTEMP_MPU_1_OFFSET 0x1e4
|
||||
#define DRA752_DTEMP_MPU_2_OFFSET 0x1e8
|
||||
#define DRA752_DTEMP_MPU_3_OFFSET 0x1ec
|
||||
#define DRA752_DTEMP_MPU_4_OFFSET 0x1f0
|
||||
|
||||
/* DRA752.dspeve register offsets */
|
||||
#define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384
|
||||
#define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394
|
||||
#define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0
|
||||
#define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET 0x3a8
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0
|
||||
#define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc
|
||||
#define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0
|
||||
#define DRA752_DTEMP_DSPEVE_2_OFFSET 0x3c4
|
||||
#define DRA752_DTEMP_DSPEVE_3_OFFSET 0x3c8
|
||||
#define DRA752_DTEMP_DSPEVE_4_OFFSET 0x3cc
|
||||
|
||||
/* DRA752.gpu register offsets */
|
||||
#define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0
|
||||
#define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150
|
||||
#define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8
|
||||
#define DRA752_BANDGAP_TSHUT_GPU_OFFSET 0x1b4
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0
|
||||
#define DRA752_DTEMP_GPU_0_OFFSET 0x1f4
|
||||
#define DRA752_DTEMP_GPU_1_OFFSET 0x1f8
|
||||
#define DRA752_DTEMP_GPU_2_OFFSET 0x1fc
|
||||
#define DRA752_DTEMP_GPU_3_OFFSET 0x200
|
||||
#define DRA752_DTEMP_GPU_4_OFFSET 0x204
|
||||
|
||||
/**
|
||||
* Register bitfields for DRA752
|
||||
*
|
||||
* All the macros bellow define the required bits for
|
||||
* controlling temperature on DRA752. Bit defines are
|
||||
* grouped by register.
|
||||
*/
|
||||
|
||||
/* DRA752.BANDGAP_STATUS_1 */
|
||||
#define DRA752_BANDGAP_STATUS_1_ALERT_MASK BIT(31)
|
||||
#define DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK BIT(5)
|
||||
#define DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK BIT(4)
|
||||
#define DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK BIT(3)
|
||||
#define DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK BIT(2)
|
||||
#define DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK BIT(1)
|
||||
#define DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK BIT(0)
|
||||
|
||||
/* DRA752.BANDGAP_CTRL_2 */
|
||||
#define DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK BIT(22)
|
||||
#define DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK BIT(21)
|
||||
#define DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK BIT(19)
|
||||
#define DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK BIT(18)
|
||||
#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK BIT(16)
|
||||
#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK BIT(15)
|
||||
#define DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK BIT(3)
|
||||
#define DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK BIT(2)
|
||||
#define DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK BIT(1)
|
||||
#define DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK BIT(0)
|
||||
|
||||
/* DRA752.BANDGAP_STATUS_2 */
|
||||
#define DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK BIT(3)
|
||||
#define DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK BIT(2)
|
||||
#define DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK BIT(1)
|
||||
#define DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK BIT(0)
|
||||
|
||||
/* DRA752.BANDGAP_CTRL_1 */
|
||||
#define DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK (0x3 << 30)
|
||||
#define DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK (0x7 << 27)
|
||||
#define DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK BIT(23)
|
||||
#define DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK BIT(22)
|
||||
#define DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK BIT(21)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK BIT(20)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK BIT(19)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK BIT(18)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK BIT(17)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK BIT(16)
|
||||
#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK BIT(15)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK BIT(5)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK BIT(4)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK BIT(3)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK BIT(2)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK BIT(1)
|
||||
#define DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK BIT(0)
|
||||
|
||||
/* DRA752.TEMP_SENSOR */
|
||||
#define DRA752_TEMP_SENSOR_TMPSOFF_MASK BIT(11)
|
||||
#define DRA752_TEMP_SENSOR_EOCZ_MASK BIT(10)
|
||||
#define DRA752_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_THRESHOLD */
|
||||
#define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16)
|
||||
#define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0)
|
||||
|
||||
/* DRA752.TSHUT_THRESHOLD */
|
||||
#define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK BIT(31)
|
||||
#define DRA752_TSHUT_THRESHOLD_HOT_MASK (0x3ff << 16)
|
||||
#define DRA752_TSHUT_THRESHOLD_COLD_MASK (0x3ff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_CUMUL_DTEMP_IVA */
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_MASK (0xffffffff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_CUMUL_DTEMP_MPU */
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_CUMUL_DTEMP_DSPEVE */
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_MASK (0xffffffff << 0)
|
||||
|
||||
/* DRA752.BANDGAP_CUMUL_DTEMP_GPU */
|
||||
#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0)
|
||||
|
||||
/**
|
||||
* Temperature limits and thresholds for DRA752
|
||||
*
|
||||
* All the macros bellow are definitions for handling the
|
||||
* ADC conversions and representation of temperature limits
|
||||
* and thresholds for DRA752. Definitions are grouped
|
||||
* by temperature domain.
|
||||
*/
|
||||
|
||||
/* DRA752.common temperature definitions */
|
||||
/* ADC conversion table limits */
|
||||
#define DRA752_ADC_START_VALUE 540
|
||||
#define DRA752_ADC_END_VALUE 945
|
||||
|
||||
/* DRA752.GPU temperature definitions */
|
||||
/* bandgap clock limits */
|
||||
#define DRA752_GPU_MAX_FREQ 1500000
|
||||
#define DRA752_GPU_MIN_FREQ 1000000
|
||||
/* sensor limits */
|
||||
#define DRA752_GPU_MIN_TEMP -40000
|
||||
#define DRA752_GPU_MAX_TEMP 125000
|
||||
#define DRA752_GPU_HYST_VAL 5000
|
||||
/* interrupts thresholds */
|
||||
#define DRA752_GPU_TSHUT_HOT 915
|
||||
#define DRA752_GPU_TSHUT_COLD 900
|
||||
#define DRA752_GPU_T_HOT 800
|
||||
#define DRA752_GPU_T_COLD 795
|
||||
|
||||
/* DRA752.MPU temperature definitions */
|
||||
/* bandgap clock limits */
|
||||
#define DRA752_MPU_MAX_FREQ 1500000
|
||||
#define DRA752_MPU_MIN_FREQ 1000000
|
||||
/* sensor limits */
|
||||
#define DRA752_MPU_MIN_TEMP -40000
|
||||
#define DRA752_MPU_MAX_TEMP 125000
|
||||
#define DRA752_MPU_HYST_VAL 5000
|
||||
/* interrupts thresholds */
|
||||
#define DRA752_MPU_TSHUT_HOT 915
|
||||
#define DRA752_MPU_TSHUT_COLD 900
|
||||
#define DRA752_MPU_T_HOT 800
|
||||
#define DRA752_MPU_T_COLD 795
|
||||
|
||||
/* DRA752.CORE temperature definitions */
|
||||
/* bandgap clock limits */
|
||||
#define DRA752_CORE_MAX_FREQ 1500000
|
||||
#define DRA752_CORE_MIN_FREQ 1000000
|
||||
/* sensor limits */
|
||||
#define DRA752_CORE_MIN_TEMP -40000
|
||||
#define DRA752_CORE_MAX_TEMP 125000
|
||||
#define DRA752_CORE_HYST_VAL 5000
|
||||
/* interrupts thresholds */
|
||||
#define DRA752_CORE_TSHUT_HOT 915
|
||||
#define DRA752_CORE_TSHUT_COLD 900
|
||||
#define DRA752_CORE_T_HOT 800
|
||||
#define DRA752_CORE_T_COLD 795
|
||||
|
||||
/* DRA752.DSPEVE temperature definitions */
|
||||
/* bandgap clock limits */
|
||||
#define DRA752_DSPEVE_MAX_FREQ 1500000
|
||||
#define DRA752_DSPEVE_MIN_FREQ 1000000
|
||||
/* sensor limits */
|
||||
#define DRA752_DSPEVE_MIN_TEMP -40000
|
||||
#define DRA752_DSPEVE_MAX_TEMP 125000
|
||||
#define DRA752_DSPEVE_HYST_VAL 5000
|
||||
/* interrupts thresholds */
|
||||
#define DRA752_DSPEVE_TSHUT_HOT 915
|
||||
#define DRA752_DSPEVE_TSHUT_COLD 900
|
||||
#define DRA752_DSPEVE_T_HOT 800
|
||||
#define DRA752_DSPEVE_T_COLD 795
|
||||
|
||||
/* DRA752.IVA temperature definitions */
|
||||
/* bandgap clock limits */
|
||||
#define DRA752_IVA_MAX_FREQ 1500000
|
||||
#define DRA752_IVA_MIN_FREQ 1000000
|
||||
/* sensor limits */
|
||||
#define DRA752_IVA_MIN_TEMP -40000
|
||||
#define DRA752_IVA_MAX_TEMP 125000
|
||||
#define DRA752_IVA_HYST_VAL 5000
|
||||
/* interrupts thresholds */
|
||||
#define DRA752_IVA_TSHUT_HOT 915
|
||||
#define DRA752_IVA_TSHUT_COLD 900
|
||||
#define DRA752_IVA_T_HOT 800
|
||||
#define DRA752_IVA_T_COLD 795
|
||||
|
||||
#endif /* __DRA752_BANDGAP_H */
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* DRA752 thermal data.
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Inc.
|
||||
* Contact:
|
||||
* Eduardo Valentin <eduardo.valentin@ti.com>
|
||||
* Tero Kristo <t-kristo@ti.com>
|
||||
*
|
||||
* This file is partially autogenerated.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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 "ti-thermal.h"
|
||||
#include "ti-bandgap.h"
|
||||
#include "dra752-bandgap.h"
|
||||
|
||||
/*
|
||||
* DRA752 has five instances of thermal sensor: MPU, GPU, CORE,
|
||||
* IVA and DSPEVE need to describe the individual registers and
|
||||
* bit fields.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DRA752 CORE thermal sensor register offsets and bit-fields
|
||||
*/
|
||||
static struct temp_sensor_registers
|
||||
dra752_core_temp_sensor_registers = {
|
||||
.temp_sensor_ctrl = DRA752_TEMP_SENSOR_CORE_OFFSET,
|
||||
.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
|
||||
.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
|
||||
.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
|
||||
.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
|
||||
.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK,
|
||||
.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK,
|
||||
.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
|
||||
.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK,
|
||||
.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK,
|
||||
.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK,
|
||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET,
|
||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET,
|
||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK,
|
||||
.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK,
|
||||
.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET,
|
||||
.ctrl_dtemp_0 = DRA752_DTEMP_CORE_0_OFFSET,
|
||||
.ctrl_dtemp_1 = DRA752_DTEMP_CORE_1_OFFSET,
|
||||
.ctrl_dtemp_2 = DRA752_DTEMP_CORE_2_OFFSET,
|
||||
.ctrl_dtemp_3 = DRA752_DTEMP_CORE_3_OFFSET,
|
||||
.ctrl_dtemp_4 = DRA752_DTEMP_CORE_4_OFFSET,
|
||||
.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET,
|
||||
};
|
||||
|
||||
/*
|
||||
* DRA752 IVA thermal sensor register offsets and bit-fields
|
||||
*/
|
||||
static struct temp_sensor_registers
|
||||
dra752_iva_temp_sensor_registers = {
|
||||
.temp_sensor_ctrl = DRA752_TEMP_SENSOR_IVA_OFFSET,
|
||||
.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
|
||||
.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
|
||||
.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
|
||||
.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET,
|
||||
.mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK,
|
||||
.mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK,
|
||||
.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
|
||||
.mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK,
|
||||
.mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK,
|
||||
.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK,
|
||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET,
|
||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET,
|
||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
||||
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK,
|
||||
.status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK,
|
||||
.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET,
|
||||
.ctrl_dtemp_0 = DRA752_DTEMP_IVA_0_OFFSET,
|
||||
.ctrl_dtemp_1 = DRA752_DTEMP_IVA_1_OFFSET,
|
||||
.ctrl_dtemp_2 = DRA752_DTEMP_IVA_2_OFFSET,
|
||||
.ctrl_dtemp_3 = DRA752_DTEMP_IVA_3_OFFSET,
|
||||
.ctrl_dtemp_4 = DRA752_DTEMP_IVA_4_OFFSET,
|
||||
.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET,
|
||||
};
|
||||
|
||||
/*
|
||||
* DRA752 MPU thermal sensor register offsets and bit-fields
|
||||
*/
|
||||
static struct temp_sensor_registers
|
||||
dra752_mpu_temp_sensor_registers = {
|
||||
.temp_sensor_ctrl = DRA752_TEMP_SENSOR_MPU_OFFSET,
|
||||
.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
|
||||
.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
|
||||
.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
|
||||
.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
|
||||
.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK,
|
||||
.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK,
|
||||
.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
|
||||
.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK,
|
||||
.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK,
|
||||
.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK,
|
||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET,
|
||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET,
|
||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK,
|
||||
.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK,
|
||||
.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET,
|
||||
.ctrl_dtemp_0 = DRA752_DTEMP_MPU_0_OFFSET,
|
||||
.ctrl_dtemp_1 = DRA752_DTEMP_MPU_1_OFFSET,
|
||||
.ctrl_dtemp_2 = DRA752_DTEMP_MPU_2_OFFSET,
|
||||
.ctrl_dtemp_3 = DRA752_DTEMP_MPU_3_OFFSET,
|
||||
.ctrl_dtemp_4 = DRA752_DTEMP_MPU_4_OFFSET,
|
||||
.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET,
|
||||
};
|
||||
|
||||
/*
|
||||
* DRA752 DSPEVE thermal sensor register offsets and bit-fields
|
||||
*/
|
||||
static struct temp_sensor_registers
|
||||
dra752_dspeve_temp_sensor_registers = {
|
||||
.temp_sensor_ctrl = DRA752_TEMP_SENSOR_DSPEVE_OFFSET,
|
||||
.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
|
||||
.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
|
||||
.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
|
||||
.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET,
|
||||
.mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK,
|
||||
.mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK,
|
||||
.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
|
||||
.mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK,
|
||||
.mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK,
|
||||
.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK,
|
||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET,
|
||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET,
|
||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
||||
.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
|
||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||
.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK,
|
||||
.status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK,
|
||||
.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET,
|
||||
.ctrl_dtemp_0 = DRA752_DTEMP_DSPEVE_0_OFFSET,
|
||||
.ctrl_dtemp_1 = DRA752_DTEMP_DSPEVE_1_OFFSET,
|
||||
.ctrl_dtemp_2 = DRA752_DTEMP_DSPEVE_2_OFFSET,
|
||||
.ctrl_dtemp_3 = DRA752_DTEMP_DSPEVE_3_OFFSET,
|
||||
.ctrl_dtemp_4 = DRA752_DTEMP_DSPEVE_4_OFFSET,
|
||||
.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET,
|
||||
};
|
||||
|
||||
/*
|
||||
* DRA752 GPU thermal sensor register offsets and bit-fields
|
||||
*/
|
||||
static struct temp_sensor_registers
|
||||
dra752_gpu_temp_sensor_registers = {
|
||||
.temp_sensor_ctrl = DRA752_TEMP_SENSOR_GPU_OFFSET,
|
||||
.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
|
||||
.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
|
||||
.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
|
||||
.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
|
||||
.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK,
|
||||
.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK,
|
||||
.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
|
||||
.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK,
|
||||
.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK,
|
||||
.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK,
|
||||
.bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET,
|
||||
.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
|
||||
.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
|
||||
.tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET,
|
||||
.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
|
||||
.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
|
||||
.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
|
||||
.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
|
||||
.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK,
|
||||
.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK,
|
||||
.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET,
|
||||
.ctrl_dtemp_0 = DRA752_DTEMP_GPU_0_OFFSET,
|
||||
.ctrl_dtemp_1 = DRA752_DTEMP_GPU_1_OFFSET,
|
||||
.ctrl_dtemp_2 = DRA752_DTEMP_GPU_2_OFFSET,
|
||||
.ctrl_dtemp_3 = DRA752_DTEMP_GPU_3_OFFSET,
|
||||
.ctrl_dtemp_4 = DRA752_DTEMP_GPU_4_OFFSET,
|
||||
.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET,
|
||||
};
|
||||
|
||||
/* Thresholds and limits for DRA752 MPU temperature sensor */
|
||||
static struct temp_sensor_data dra752_mpu_temp_sensor_data = {
|
||||
.tshut_hot = DRA752_MPU_TSHUT_HOT,
|
||||
.tshut_cold = DRA752_MPU_TSHUT_COLD,
|
||||
.t_hot = DRA752_MPU_T_HOT,
|
||||
.t_cold = DRA752_MPU_T_COLD,
|
||||
.min_freq = DRA752_MPU_MIN_FREQ,
|
||||
.max_freq = DRA752_MPU_MAX_FREQ,
|
||||
.max_temp = DRA752_MPU_MAX_TEMP,
|
||||
.min_temp = DRA752_MPU_MIN_TEMP,
|
||||
.hyst_val = DRA752_MPU_HYST_VAL,
|
||||
.update_int1 = 1000,
|
||||
.update_int2 = 2000,
|
||||
};
|
||||
|
||||
/* Thresholds and limits for DRA752 GPU temperature sensor */
|
||||
static struct temp_sensor_data dra752_gpu_temp_sensor_data = {
|
||||
.tshut_hot = DRA752_GPU_TSHUT_HOT,
|
||||
.tshut_cold = DRA752_GPU_TSHUT_COLD,
|
||||
.t_hot = DRA752_GPU_T_HOT,
|
||||
.t_cold = DRA752_GPU_T_COLD,
|
||||
.min_freq = DRA752_GPU_MIN_FREQ,
|
||||
.max_freq = DRA752_GPU_MAX_FREQ,
|
||||
.max_temp = DRA752_GPU_MAX_TEMP,
|
||||
.min_temp = DRA752_GPU_MIN_TEMP,
|
||||
.hyst_val = DRA752_GPU_HYST_VAL,
|
||||
.update_int1 = 1000,
|
||||
.update_int2 = 2000,
|
||||
};
|
||||
|
||||
/* Thresholds and limits for DRA752 CORE temperature sensor */
|
||||
static struct temp_sensor_data dra752_core_temp_sensor_data = {
|
||||
.tshut_hot = DRA752_CORE_TSHUT_HOT,
|
||||
.tshut_cold = DRA752_CORE_TSHUT_COLD,
|
||||
.t_hot = DRA752_CORE_T_HOT,
|
||||
.t_cold = DRA752_CORE_T_COLD,
|
||||
.min_freq = DRA752_CORE_MIN_FREQ,
|
||||
.max_freq = DRA752_CORE_MAX_FREQ,
|
||||
.max_temp = DRA752_CORE_MAX_TEMP,
|
||||
.min_temp = DRA752_CORE_MIN_TEMP,
|
||||
.hyst_val = DRA752_CORE_HYST_VAL,
|
||||
.update_int1 = 1000,
|
||||
.update_int2 = 2000,
|
||||
};
|
||||
|
||||
/* Thresholds and limits for DRA752 DSPEVE temperature sensor */
|
||||
static struct temp_sensor_data dra752_dspeve_temp_sensor_data = {
|
||||
.tshut_hot = DRA752_DSPEVE_TSHUT_HOT,
|
||||
.tshut_cold = DRA752_DSPEVE_TSHUT_COLD,
|
||||
.t_hot = DRA752_DSPEVE_T_HOT,
|
||||
.t_cold = DRA752_DSPEVE_T_COLD,
|
||||
.min_freq = DRA752_DSPEVE_MIN_FREQ,
|
||||
.max_freq = DRA752_DSPEVE_MAX_FREQ,
|
||||
.max_temp = DRA752_DSPEVE_MAX_TEMP,
|
||||
.min_temp = DRA752_DSPEVE_MIN_TEMP,
|
||||
.hyst_val = DRA752_DSPEVE_HYST_VAL,
|
||||
.update_int1 = 1000,
|
||||
.update_int2 = 2000,
|
||||
};
|
||||
|
||||
/* Thresholds and limits for DRA752 IVA temperature sensor */
|
||||
static struct temp_sensor_data dra752_iva_temp_sensor_data = {
|
||||
.tshut_hot = DRA752_IVA_TSHUT_HOT,
|
||||
.tshut_cold = DRA752_IVA_TSHUT_COLD,
|
||||
.t_hot = DRA752_IVA_T_HOT,
|
||||
.t_cold = DRA752_IVA_T_COLD,
|
||||
.min_freq = DRA752_IVA_MIN_FREQ,
|
||||
.max_freq = DRA752_IVA_MAX_FREQ,
|
||||
.max_temp = DRA752_IVA_MAX_TEMP,
|
||||
.min_temp = DRA752_IVA_MIN_TEMP,
|
||||
.hyst_val = DRA752_IVA_HYST_VAL,
|
||||
.update_int1 = 1000,
|
||||
.update_int2 = 2000,
|
||||
};
|
||||
|
||||
/*
|
||||
* DRA752 : Temperature values in milli degree celsius
|
||||
* ADC code values from 540 to 945
|
||||
*/
|
||||
static
|
||||
int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = {
|
||||
/* Index 540 - 549 */
|
||||
-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
|
||||
-37800,
|
||||
/* Index 550 - 559 */
|
||||
-37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800,
|
||||
-33400,
|
||||
/* Index 560 - 569 */
|
||||
-33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800,
|
||||
-29400,
|
||||
/* Index 570 - 579 */
|
||||
-29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400,
|
||||
-25000,
|
||||
/* Index 580 - 589 */
|
||||
-24600, -24200, -23800, -23400, -23000, -22600, -22200, -21800, -21400,
|
||||
-21000,
|
||||
/* Index 590 - 599 */
|
||||
-20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000,
|
||||
-16600,
|
||||
/* Index 600 - 609 */
|
||||
-16200, -15800, -15400, -15000, -14600, -14200, -13800, -13400, -13000,
|
||||
-12500,
|
||||
/* Index 610 - 619 */
|
||||
-11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600,
|
||||
-8200,
|
||||
/* Index 620 - 629 */
|
||||
-7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500,
|
||||
-3900,
|
||||
/* Index 630 - 639 */
|
||||
-3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200,
|
||||
200,
|
||||
/* Index 640 - 649 */
|
||||
600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900,
|
||||
4500,
|
||||
/* Index 650 - 659 */
|
||||
5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200,
|
||||
8600,
|
||||
/* Index 660 - 669 */
|
||||
9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200,
|
||||
12700,
|
||||
/* Index 670 - 679 */
|
||||
13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600,
|
||||
17000,
|
||||
/* Index 680 - 689 */
|
||||
17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600,
|
||||
21000,
|
||||
/* Index 690 - 699 */
|
||||
21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000,
|
||||
25400,
|
||||
/* Index 700 - 709 */
|
||||
25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000,
|
||||
29400,
|
||||
/* Index 710 - 719 */
|
||||
29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400,
|
||||
33800,
|
||||
/* Index 720 - 729 */
|
||||
34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400,
|
||||
37800,
|
||||
/* Index 730 - 739 */
|
||||
38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400,
|
||||
41800,
|
||||
/* Index 740 - 749 */
|
||||
42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800,
|
||||
46200,
|
||||
/* Index 750 - 759 */
|
||||
46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800,
|
||||
50200,
|
||||
/* Index 760 - 769 */
|
||||
50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800,
|
||||
54200,
|
||||
/* Index 770 - 779 */
|
||||
54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200,
|
||||
58600,
|
||||
/* Index 780 - 789 */
|
||||
59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200,
|
||||
62600,
|
||||
/* Index 790 - 799 */
|
||||
63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
|
||||
66600,
|
||||
/* Index 800 - 809 */
|
||||
67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200,
|
||||
70600,
|
||||
/* Index 810 - 819 */
|
||||
71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600,
|
||||
75000,
|
||||
/* Index 820 - 829 */
|
||||
75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600,
|
||||
79000,
|
||||
/* Index 830 - 839 */
|
||||
79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600,
|
||||
83000,
|
||||
/* Index 840 - 849 */
|
||||
83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600,
|
||||
87000,
|
||||
/* Index 850 - 859 */
|
||||
87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600,
|
||||
91000,
|
||||
/* Index 860 - 869 */
|
||||
91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600,
|
||||
95000,
|
||||
/* Index 870 - 879 */
|
||||
95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000,
|
||||
99400,
|
||||
/* Index 880 - 889 */
|
||||
99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000,
|
||||
103400,
|
||||
/* Index 890 - 899 */
|
||||
103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000,
|
||||
107400,
|
||||
/* Index 900 - 909 */
|
||||
107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
|
||||
111400,
|
||||
/* Index 910 - 919 */
|
||||
111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000,
|
||||
115400,
|
||||
/* Index 920 - 929 */
|
||||
115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000,
|
||||
119400,
|
||||
/* Index 930 - 939 */
|
||||
119800, 120200, 120600, 121000, 121400, 121800, 122200, 122600, 123000,
|
||||
123400,
|
||||
/* Index 940 - 945 */
|
||||
123800, 124200, 124600, 124900, 125000, 125000,
|
||||
};
|
||||
|
||||
/* DRA752 data */
|
||||
const struct ti_bandgap_data dra752_data = {
|
||||
.features = TI_BANDGAP_FEATURE_TSHUT_CONFIG |
|
||||
TI_BANDGAP_FEATURE_FREEZE_BIT |
|
||||
TI_BANDGAP_FEATURE_TALERT |
|
||||
TI_BANDGAP_FEATURE_COUNTER_DELAY |
|
||||
TI_BANDGAP_FEATURE_HISTORY_BUFFER,
|
||||
.fclock_name = "l3instr_ts_gclk_div",
|
||||
.div_ck_name = "l3instr_ts_gclk_div",
|
||||
.conv_table = dra752_adc_to_temp,
|
||||
.adc_start_val = DRA752_ADC_START_VALUE,
|
||||
.adc_end_val = DRA752_ADC_END_VALUE,
|
||||
.expose_sensor = ti_thermal_expose_sensor,
|
||||
.remove_sensor = ti_thermal_remove_sensor,
|
||||
.sensors = {
|
||||
{
|
||||
.registers = &dra752_mpu_temp_sensor_registers,
|
||||
.ts_data = &dra752_mpu_temp_sensor_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,
|
||||
},
|
||||
{
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.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,
|
||||
},
|
||||
},
|
||||
.sensor_count = 5,
|
||||
};
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "ti-bandgap.h"
|
||||
|
@ -469,7 +470,7 @@ static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(bgp)) {
|
||||
if (!bgp || IS_ERR(bgp)) {
|
||||
pr_err("%s: invalid bandgap pointer\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
|
@ -992,9 +993,12 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
spin_lock(&bgp->lock);
|
||||
|
||||
tsr = bgp->conf->sensors[id].registers;
|
||||
|
||||
/* Freeze and read the last 2 valid readings */
|
||||
RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
|
||||
reg1 = tsr->ctrl_dtemp_1;
|
||||
reg2 = tsr->ctrl_dtemp_2;
|
||||
|
||||
|
@ -1008,22 +1012,25 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend)
|
|||
/* Convert from adc values to mCelsius temperature */
|
||||
ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
|
||||
if (ret)
|
||||
goto exit;
|
||||
goto unfreeze;
|
||||
|
||||
ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
|
||||
if (ret)
|
||||
goto exit;
|
||||
goto unfreeze;
|
||||
|
||||
/* Fetch the update interval */
|
||||
ret = ti_bandgap_read_update_interval(bgp, id, &interval);
|
||||
if (ret || !interval)
|
||||
goto exit;
|
||||
goto unfreeze;
|
||||
|
||||
*trend = (t1 - t2) / interval;
|
||||
|
||||
dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
|
||||
t1, t2, *trend);
|
||||
|
||||
unfreeze:
|
||||
RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
|
||||
spin_unlock(&bgp->lock);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1123,7 +1130,6 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
|
|||
const struct of_device_id *of_id;
|
||||
struct ti_bandgap *bgp;
|
||||
struct resource *res;
|
||||
u32 prop;
|
||||
int i;
|
||||
|
||||
/* just for the sake */
|
||||
|
@ -1167,11 +1173,7 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
|
|||
} while (res);
|
||||
|
||||
if (TI_BANDGAP_HAS(bgp, TSHUT)) {
|
||||
if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
|
||||
dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
bgp->tshut_gpio = prop;
|
||||
bgp->tshut_gpio = of_get_gpio(node, 0);
|
||||
if (!gpio_is_valid(bgp->tshut_gpio)) {
|
||||
dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
|
||||
bgp->tshut_gpio);
|
||||
|
@ -1191,7 +1193,7 @@ int ti_bandgap_probe(struct platform_device *pdev)
|
|||
int clk_rate, ret = 0, i;
|
||||
|
||||
bgp = ti_bandgap_build(pdev);
|
||||
if (IS_ERR_OR_NULL(bgp)) {
|
||||
if (IS_ERR(bgp)) {
|
||||
dev_err(&pdev->dev, "failed to fetch platform data\n");
|
||||
return PTR_ERR(bgp);
|
||||
}
|
||||
|
@ -1207,17 +1209,19 @@ int ti_bandgap_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
|
||||
ret = IS_ERR_OR_NULL(bgp->fclock);
|
||||
ret = IS_ERR(bgp->fclock);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request fclock reference\n");
|
||||
ret = PTR_ERR(bgp->fclock);
|
||||
goto free_irqs;
|
||||
}
|
||||
|
||||
bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
|
||||
ret = IS_ERR_OR_NULL(bgp->div_clk);
|
||||
ret = IS_ERR(bgp->div_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to request div_ts_ck clock ref\n");
|
||||
ret = PTR_ERR(bgp->div_clk);
|
||||
goto free_irqs;
|
||||
}
|
||||
|
||||
|
@ -1522,6 +1526,12 @@ static const struct of_device_id of_ti_bandgap_match[] = {
|
|||
.compatible = "ti,omap5430-bandgap",
|
||||
.data = (void *)&omap5430_data,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_DRA752_THERMAL
|
||||
{
|
||||
.compatible = "ti,dra752-bandgap",
|
||||
.data = (void *)&dra752_data,
|
||||
},
|
||||
#endif
|
||||
/* Sentinel */
|
||||
{ },
|
|
@ -400,4 +400,9 @@ extern const struct ti_bandgap_data omap5430_data;
|
|||
#define omap5430_data NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRA752_THERMAL
|
||||
extern const struct ti_bandgap_data dra752_data;
|
||||
#else
|
||||
#define dra752_data NULL
|
||||
#endif
|
||||
#endif
|
|
@ -101,7 +101,7 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
|
|||
|
||||
pcb_tz = data->pcb_tz;
|
||||
/* In case pcb zone is available, use the extrapolation rule with it */
|
||||
if (!IS_ERR_OR_NULL(pcb_tz)) {
|
||||
if (!IS_ERR(pcb_tz)) {
|
||||
ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
|
||||
if (!ret) {
|
||||
tmp -= pcb_temp; /* got a valid PCB temp */
|
||||
|
@ -124,7 +124,7 @@ static int ti_thermal_bind(struct thermal_zone_device *thermal,
|
|||
struct ti_thermal_data *data = thermal->devdata;
|
||||
int id;
|
||||
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
if (!data || IS_ERR(data))
|
||||
return -ENODEV;
|
||||
|
||||
/* check if this is the cooling device we registered */
|
||||
|
@ -146,7 +146,7 @@ static int ti_thermal_unbind(struct thermal_zone_device *thermal,
|
|||
{
|
||||
struct ti_thermal_data *data = thermal->devdata;
|
||||
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
if (!data || IS_ERR(data))
|
||||
return -ENODEV;
|
||||
|
||||
/* check if this is the cooling device we registered */
|
||||
|
@ -282,6 +282,7 @@ static struct ti_thermal_data
|
|||
data->sensor_id = id;
|
||||
data->bgp = bgp;
|
||||
data->mode = THERMAL_DEVICE_ENABLED;
|
||||
/* pcb_tz will be either valid or PTR_ERR() */
|
||||
data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
|
||||
INIT_WORK(&data->thermal_wq, ti_thermal_work);
|
||||
|
||||
|
@ -295,7 +296,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
|
|||
|
||||
data = ti_bandgap_get_sensor_data(bgp, id);
|
||||
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
if (!data || IS_ERR(data))
|
||||
data = ti_thermal_build_data(bgp, id);
|
||||
|
||||
if (!data)
|
||||
|
@ -306,7 +307,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
|
|||
OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
|
||||
NULL, FAST_TEMP_MONITORING_RATE,
|
||||
FAST_TEMP_MONITORING_RATE);
|
||||
if (IS_ERR_OR_NULL(data->ti_thermal)) {
|
||||
if (IS_ERR(data->ti_thermal)) {
|
||||
dev_err(bgp->dev, "thermal zone device is NULL\n");
|
||||
return PTR_ERR(data->ti_thermal);
|
||||
}
|
||||
|
@ -343,7 +344,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
|
|||
struct ti_thermal_data *data;
|
||||
|
||||
data = ti_bandgap_get_sensor_data(bgp, id);
|
||||
if (IS_ERR_OR_NULL(data))
|
||||
if (!data || IS_ERR(data))
|
||||
data = ti_thermal_build_data(bgp, id);
|
||||
|
||||
if (!data)
|
||||
|
@ -356,7 +357,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
|
|||
|
||||
/* Register cooling device */
|
||||
data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
|
||||
if (IS_ERR_OR_NULL(data->cool_dev)) {
|
||||
if (IS_ERR(data->cool_dev)) {
|
||||
dev_err(bgp->dev,
|
||||
"Failed to register cpufreq cooling device\n");
|
||||
return PTR_ERR(data->cool_dev);
|
|
@ -38,6 +38,9 @@
|
|||
#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
|
||||
|
@ -51,6 +54,9 @@
|
|||
#define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464
|
||||
#define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102
|
||||
|
||||
#define DRA752_GRADIENT_SLOPE_W_PCB 0
|
||||
#define DRA752_GRADIENT_CONST_W_PCB 2000
|
||||
|
||||
/* trip points of interest in milicelsius (at hotspot level) */
|
||||
#define OMAP_TRIP_COLD 100000
|
||||
#define OMAP_TRIP_HOT 110000
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* x86_pkg_temp_thermal driver
|
||||
* Copyright (c) 2013, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.
|
||||
*
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/mce.h>
|
||||
|
||||
/*
|
||||
* Rate control delay: Idea is to introduce denounce effect
|
||||
* This should be long enough to avoid reduce events, when
|
||||
* threshold is set to a temperature, which is constantly
|
||||
* violated, but at the short enough to take any action.
|
||||
* The action can be remove threshold or change it to next
|
||||
* interesting setting. Based on experiments, in around
|
||||
* every 5 seconds under load will give us a significant
|
||||
* temperature change.
|
||||
*/
|
||||
#define PKG_TEMP_THERMAL_NOTIFY_DELAY 5000
|
||||
static int notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY;
|
||||
module_param(notify_delay_ms, int, 0644);
|
||||
MODULE_PARM_DESC(notify_delay_ms,
|
||||
"User space notification delay in milli seconds.");
|
||||
|
||||
/* Number of trip points in thermal zone. Currently it can't
|
||||
* be more than 2. MSR can allow setting and getting notifications
|
||||
* for only 2 thresholds. This define enforces this, if there
|
||||
* is some wrong values returned by cpuid for number of thresholds.
|
||||
*/
|
||||
#define MAX_NUMBER_OF_TRIPS 2
|
||||
|
||||
struct phy_dev_entry {
|
||||
struct list_head list;
|
||||
u16 phys_proc_id;
|
||||
u16 first_cpu;
|
||||
u32 tj_max;
|
||||
int ref_cnt;
|
||||
u32 start_pkg_therm_low;
|
||||
u32 start_pkg_therm_high;
|
||||
struct thermal_zone_device *tzone;
|
||||
};
|
||||
|
||||
/* List maintaining number of package instances */
|
||||
static LIST_HEAD(phy_dev_list);
|
||||
static DEFINE_MUTEX(phy_dev_list_mutex);
|
||||
|
||||
/* Interrupt to work function schedule queue */
|
||||
static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work);
|
||||
|
||||
/* To track if the work is already scheduled on a package */
|
||||
static u8 *pkg_work_scheduled;
|
||||
|
||||
/* Spin lock to prevent races with pkg_work_scheduled */
|
||||
static spinlock_t pkg_work_lock;
|
||||
static u16 max_phy_id;
|
||||
|
||||
/* Debug counters to show using debugfs */
|
||||
static struct dentry *debugfs;
|
||||
static unsigned int pkg_interrupt_cnt;
|
||||
static unsigned int pkg_work_cnt;
|
||||
|
||||
static int pkg_temp_debugfs_init(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
debugfs = debugfs_create_dir("pkg_temp_thermal", NULL);
|
||||
if (!debugfs)
|
||||
return -ENOENT;
|
||||
|
||||
d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs,
|
||||
(u32 *)&pkg_interrupt_cnt);
|
||||
if (!d)
|
||||
goto err_out;
|
||||
|
||||
d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs,
|
||||
(u32 *)&pkg_work_cnt);
|
||||
if (!d)
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
debugfs_remove_recursive(debugfs);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static struct phy_dev_entry
|
||||
*pkg_temp_thermal_get_phy_entry(unsigned int cpu)
|
||||
{
|
||||
u16 phys_proc_id = topology_physical_package_id(cpu);
|
||||
struct phy_dev_entry *phy_ptr;
|
||||
|
||||
mutex_lock(&phy_dev_list_mutex);
|
||||
|
||||
list_for_each_entry(phy_ptr, &phy_dev_list, list)
|
||||
if (phy_ptr->phys_proc_id == phys_proc_id) {
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
return phy_ptr;
|
||||
}
|
||||
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* tj-max is is interesting because threshold is set relative to this
|
||||
* temperature.
|
||||
*/
|
||||
static int get_tj_max(int cpu, u32 *tj_max)
|
||||
{
|
||||
u32 eax, edx;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
|
||||
if (err)
|
||||
goto err_ret;
|
||||
else {
|
||||
val = (eax >> 16) & 0xff;
|
||||
if (val)
|
||||
*tj_max = val * 1000;
|
||||
else {
|
||||
err = -EINVAL;
|
||||
goto err_ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_ret:
|
||||
*tj_max = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
|
||||
{
|
||||
u32 eax, edx;
|
||||
struct phy_dev_entry *phy_dev_entry;
|
||||
|
||||
phy_dev_entry = tzd->devdata;
|
||||
rdmsr_on_cpu(phy_dev_entry->first_cpu, MSR_IA32_PACKAGE_THERM_STATUS,
|
||||
&eax, &edx);
|
||||
if (eax & 0x80000000) {
|
||||
*temp = phy_dev_entry->tj_max -
|
||||
((eax >> 16) & 0x7f) * 1000;
|
||||
pr_debug("sys_get_curr_temp %ld\n", *temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int sys_get_trip_temp(struct thermal_zone_device *tzd,
|
||||
int trip, unsigned long *temp)
|
||||
{
|
||||
u32 eax, edx;
|
||||
struct phy_dev_entry *phy_dev_entry;
|
||||
u32 mask, shift;
|
||||
unsigned long thres_reg_value;
|
||||
int ret;
|
||||
|
||||
if (trip >= MAX_NUMBER_OF_TRIPS)
|
||||
return -EINVAL;
|
||||
|
||||
phy_dev_entry = tzd->devdata;
|
||||
|
||||
if (trip) {
|
||||
mask = THERM_MASK_THRESHOLD1;
|
||||
shift = THERM_SHIFT_THRESHOLD1;
|
||||
} else {
|
||||
mask = THERM_MASK_THRESHOLD0;
|
||||
shift = THERM_SHIFT_THRESHOLD0;
|
||||
}
|
||||
|
||||
ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
|
||||
MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
thres_reg_value = (eax & mask) >> shift;
|
||||
if (thres_reg_value)
|
||||
*temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
|
||||
else
|
||||
*temp = 0;
|
||||
pr_debug("sys_get_trip_temp %ld\n", *temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
|
||||
unsigned long temp)
|
||||
{
|
||||
u32 l, h;
|
||||
struct phy_dev_entry *phy_dev_entry;
|
||||
u32 mask, shift, intr;
|
||||
int ret;
|
||||
|
||||
phy_dev_entry = tzd->devdata;
|
||||
|
||||
if (trip >= MAX_NUMBER_OF_TRIPS || temp >= phy_dev_entry->tj_max)
|
||||
return -EINVAL;
|
||||
|
||||
ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
|
||||
MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
&l, &h);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (trip) {
|
||||
mask = THERM_MASK_THRESHOLD1;
|
||||
shift = THERM_SHIFT_THRESHOLD1;
|
||||
intr = THERM_INT_THRESHOLD1_ENABLE;
|
||||
} else {
|
||||
mask = THERM_MASK_THRESHOLD0;
|
||||
shift = THERM_SHIFT_THRESHOLD0;
|
||||
intr = THERM_INT_THRESHOLD0_ENABLE;
|
||||
}
|
||||
l &= ~mask;
|
||||
/*
|
||||
* When users space sets a trip temperature == 0, which is indication
|
||||
* that, it is no longer interested in receiving notifications.
|
||||
*/
|
||||
if (!temp)
|
||||
l &= ~intr;
|
||||
else {
|
||||
l |= (phy_dev_entry->tj_max - temp)/1000 << shift;
|
||||
l |= intr;
|
||||
}
|
||||
|
||||
return wrmsr_on_cpu(phy_dev_entry->first_cpu,
|
||||
MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
l, h);
|
||||
}
|
||||
|
||||
static int sys_get_trip_type(struct thermal_zone_device *thermal,
|
||||
int trip, enum thermal_trip_type *type)
|
||||
{
|
||||
|
||||
*type = THERMAL_TRIP_PASSIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Thermal zone callback registry */
|
||||
static struct thermal_zone_device_ops tzone_ops = {
|
||||
.get_temp = sys_get_curr_temp,
|
||||
.get_trip_temp = sys_get_trip_temp,
|
||||
.get_trip_type = sys_get_trip_type,
|
||||
.set_trip_temp = sys_set_trip_temp,
|
||||
};
|
||||
|
||||
static bool pkg_temp_thermal_platform_thermal_rate_control(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Enable threshold interrupt on local package/cpu */
|
||||
static inline void enable_pkg_thres_interrupt(void)
|
||||
{
|
||||
u32 l, h;
|
||||
u8 thres_0, thres_1;
|
||||
|
||||
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
|
||||
/* only enable/disable if it had valid threshold value */
|
||||
thres_0 = (l & THERM_MASK_THRESHOLD0) >> THERM_SHIFT_THRESHOLD0;
|
||||
thres_1 = (l & THERM_MASK_THRESHOLD1) >> THERM_SHIFT_THRESHOLD1;
|
||||
if (thres_0)
|
||||
l |= THERM_INT_THRESHOLD0_ENABLE;
|
||||
if (thres_1)
|
||||
l |= THERM_INT_THRESHOLD1_ENABLE;
|
||||
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
|
||||
}
|
||||
|
||||
/* Disable threshold interrupt on local package/cpu */
|
||||
static inline void disable_pkg_thres_interrupt(void)
|
||||
{
|
||||
u32 l, h;
|
||||
rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
|
||||
wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
l & (~THERM_INT_THRESHOLD0_ENABLE) &
|
||||
(~THERM_INT_THRESHOLD1_ENABLE), h);
|
||||
}
|
||||
|
||||
static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
|
||||
{
|
||||
__u64 msr_val;
|
||||
int cpu = smp_processor_id();
|
||||
int phy_id = topology_physical_package_id(cpu);
|
||||
struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
|
||||
bool notify = false;
|
||||
|
||||
if (!phdev)
|
||||
return;
|
||||
|
||||
spin_lock(&pkg_work_lock);
|
||||
++pkg_work_cnt;
|
||||
if (unlikely(phy_id > max_phy_id)) {
|
||||
spin_unlock(&pkg_work_lock);
|
||||
return;
|
||||
}
|
||||
pkg_work_scheduled[phy_id] = 0;
|
||||
spin_unlock(&pkg_work_lock);
|
||||
|
||||
enable_pkg_thres_interrupt();
|
||||
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
|
||||
if (msr_val & THERM_LOG_THRESHOLD0) {
|
||||
wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
|
||||
msr_val & ~THERM_LOG_THRESHOLD0);
|
||||
notify = true;
|
||||
}
|
||||
if (msr_val & THERM_LOG_THRESHOLD1) {
|
||||
wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
|
||||
msr_val & ~THERM_LOG_THRESHOLD1);
|
||||
notify = true;
|
||||
}
|
||||
if (notify) {
|
||||
pr_debug("thermal_zone_device_update\n");
|
||||
thermal_zone_device_update(phdev->tzone);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
|
||||
{
|
||||
unsigned long flags;
|
||||
int cpu = smp_processor_id();
|
||||
int phy_id = topology_physical_package_id(cpu);
|
||||
|
||||
/*
|
||||
* When a package is in interrupted state, all CPU's in that package
|
||||
* are in the same interrupt state. So scheduling on any one CPU in
|
||||
* the package is enough and simply return for others.
|
||||
*/
|
||||
spin_lock_irqsave(&pkg_work_lock, flags);
|
||||
++pkg_interrupt_cnt;
|
||||
if (unlikely(phy_id > max_phy_id) || unlikely(!pkg_work_scheduled) ||
|
||||
pkg_work_scheduled[phy_id]) {
|
||||
disable_pkg_thres_interrupt();
|
||||
spin_unlock_irqrestore(&pkg_work_lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
pkg_work_scheduled[phy_id] = 1;
|
||||
spin_unlock_irqrestore(&pkg_work_lock, flags);
|
||||
|
||||
disable_pkg_thres_interrupt();
|
||||
schedule_delayed_work_on(cpu,
|
||||
&per_cpu(pkg_temp_thermal_threshold_work, cpu),
|
||||
msecs_to_jiffies(notify_delay_ms));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_siblings_cpu(int cpu)
|
||||
{
|
||||
int i;
|
||||
int id = topology_physical_package_id(cpu);
|
||||
|
||||
for_each_online_cpu(i)
|
||||
if (i != cpu && topology_physical_package_id(i) == id)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pkg_temp_thermal_device_add(unsigned int cpu)
|
||||
{
|
||||
int err;
|
||||
u32 tj_max;
|
||||
struct phy_dev_entry *phy_dev_entry;
|
||||
char buffer[30];
|
||||
int thres_count;
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
cpuid(6, &eax, &ebx, &ecx, &edx);
|
||||
thres_count = ebx & 0x07;
|
||||
if (!thres_count)
|
||||
return -ENODEV;
|
||||
|
||||
thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
|
||||
|
||||
err = get_tj_max(cpu, &tj_max);
|
||||
if (err)
|
||||
goto err_ret;
|
||||
|
||||
mutex_lock(&phy_dev_list_mutex);
|
||||
|
||||
phy_dev_entry = kzalloc(sizeof(*phy_dev_entry), GFP_KERNEL);
|
||||
if (!phy_dev_entry) {
|
||||
err = -ENOMEM;
|
||||
goto err_ret_unlock;
|
||||
}
|
||||
|
||||
spin_lock(&pkg_work_lock);
|
||||
if (topology_physical_package_id(cpu) > max_phy_id)
|
||||
max_phy_id = topology_physical_package_id(cpu);
|
||||
pkg_work_scheduled = krealloc(pkg_work_scheduled,
|
||||
(max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
|
||||
if (!pkg_work_scheduled) {
|
||||
spin_unlock(&pkg_work_lock);
|
||||
err = -ENOMEM;
|
||||
goto err_ret_free;
|
||||
}
|
||||
pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
|
||||
spin_unlock(&pkg_work_lock);
|
||||
|
||||
phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
|
||||
phy_dev_entry->first_cpu = cpu;
|
||||
phy_dev_entry->tj_max = tj_max;
|
||||
phy_dev_entry->ref_cnt = 1;
|
||||
snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n",
|
||||
phy_dev_entry->phys_proc_id);
|
||||
phy_dev_entry->tzone = thermal_zone_device_register(buffer,
|
||||
thres_count,
|
||||
(thres_count == MAX_NUMBER_OF_TRIPS) ?
|
||||
0x03 : 0x01,
|
||||
phy_dev_entry, &tzone_ops, NULL, 0, 0);
|
||||
if (IS_ERR(phy_dev_entry->tzone)) {
|
||||
err = PTR_ERR(phy_dev_entry->tzone);
|
||||
goto err_ret_free;
|
||||
}
|
||||
/* Store MSR value for package thermal interrupt, to restore at exit */
|
||||
rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
&phy_dev_entry->start_pkg_therm_low,
|
||||
&phy_dev_entry->start_pkg_therm_high);
|
||||
|
||||
list_add_tail(&phy_dev_entry->list, &phy_dev_list);
|
||||
pr_debug("pkg_temp_thermal_device_add :phy_id %d cpu %d\n",
|
||||
phy_dev_entry->phys_proc_id, cpu);
|
||||
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err_ret_free:
|
||||
kfree(phy_dev_entry);
|
||||
err_ret_unlock:
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
|
||||
err_ret:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int pkg_temp_thermal_device_remove(unsigned int cpu)
|
||||
{
|
||||
struct phy_dev_entry *n;
|
||||
u16 phys_proc_id = topology_physical_package_id(cpu);
|
||||
struct phy_dev_entry *phdev =
|
||||
pkg_temp_thermal_get_phy_entry(cpu);
|
||||
|
||||
if (!phdev)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&phy_dev_list_mutex);
|
||||
/* If we are loosing the first cpu for this package, we need change */
|
||||
if (phdev->first_cpu == cpu) {
|
||||
phdev->first_cpu = find_siblings_cpu(cpu);
|
||||
pr_debug("thermal_device_remove: first cpu switched %d\n",
|
||||
phdev->first_cpu);
|
||||
}
|
||||
/*
|
||||
* It is possible that no siblings left as this was the last cpu
|
||||
* going offline. We don't need to worry about this assignment
|
||||
* as the phydev entry will be removed in this case and
|
||||
* thermal zone is removed.
|
||||
*/
|
||||
--phdev->ref_cnt;
|
||||
pr_debug("thermal_device_remove: pkg: %d cpu %d ref_cnt %d\n",
|
||||
phys_proc_id, cpu, phdev->ref_cnt);
|
||||
if (!phdev->ref_cnt)
|
||||
list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
|
||||
if (phdev->phys_proc_id == phys_proc_id) {
|
||||
thermal_zone_device_unregister(phdev->tzone);
|
||||
list_del(&phdev->list);
|
||||
kfree(phdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_core_online(unsigned int cpu)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
|
||||
|
||||
/* Check if there is already an instance for this package */
|
||||
if (!phdev) {
|
||||
if (!cpu_has(c, X86_FEATURE_DTHERM) &&
|
||||
!cpu_has(c, X86_FEATURE_PTS))
|
||||
return -ENODEV;
|
||||
if (pkg_temp_thermal_device_add(cpu))
|
||||
return -ENODEV;
|
||||
} else {
|
||||
mutex_lock(&phy_dev_list_mutex);
|
||||
++phdev->ref_cnt;
|
||||
pr_debug("get_core_online: cpu %d ref_cnt %d\n",
|
||||
cpu, phdev->ref_cnt);
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
}
|
||||
INIT_DELAYED_WORK(&per_cpu(pkg_temp_thermal_threshold_work, cpu),
|
||||
pkg_temp_thermal_threshold_work_fn);
|
||||
|
||||
pr_debug("get_core_online: cpu %d successful\n", cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void put_core_offline(unsigned int cpu)
|
||||
{
|
||||
if (!pkg_temp_thermal_device_remove(cpu))
|
||||
cancel_delayed_work_sync(
|
||||
&per_cpu(pkg_temp_thermal_threshold_work, cpu));
|
||||
|
||||
pr_debug("put_core_offline: cpu %d\n", cpu);
|
||||
}
|
||||
|
||||
static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long) hcpu;
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
case CPU_DOWN_FAILED:
|
||||
get_core_online(cpu);
|
||||
break;
|
||||
case CPU_DOWN_PREPARE:
|
||||
put_core_offline(cpu);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block pkg_temp_thermal_notifier __refdata = {
|
||||
.notifier_call = pkg_temp_thermal_cpu_callback,
|
||||
};
|
||||
|
||||
static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = {
|
||||
{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids);
|
||||
|
||||
static int __init pkg_temp_thermal_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!x86_match_cpu(pkg_temp_thermal_ids))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_init(&pkg_work_lock);
|
||||
platform_thermal_package_notify =
|
||||
pkg_temp_thermal_platform_thermal_notify;
|
||||
platform_thermal_package_rate_control =
|
||||
pkg_temp_thermal_platform_thermal_rate_control;
|
||||
|
||||
get_online_cpus();
|
||||
for_each_online_cpu(i)
|
||||
if (get_core_online(i))
|
||||
goto err_ret;
|
||||
register_hotcpu_notifier(&pkg_temp_thermal_notifier);
|
||||
put_online_cpus();
|
||||
|
||||
pkg_temp_debugfs_init(); /* Don't care if fails */
|
||||
|
||||
return 0;
|
||||
|
||||
err_ret:
|
||||
get_online_cpus();
|
||||
for_each_online_cpu(i)
|
||||
put_core_offline(i);
|
||||
put_online_cpus();
|
||||
kfree(pkg_work_scheduled);
|
||||
platform_thermal_package_notify = NULL;
|
||||
platform_thermal_package_rate_control = NULL;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit pkg_temp_thermal_exit(void)
|
||||
{
|
||||
struct phy_dev_entry *phdev, *n;
|
||||
int i;
|
||||
|
||||
get_online_cpus();
|
||||
unregister_hotcpu_notifier(&pkg_temp_thermal_notifier);
|
||||
mutex_lock(&phy_dev_list_mutex);
|
||||
list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
|
||||
/* Retore old MSR value for package thermal interrupt */
|
||||
wrmsr_on_cpu(phdev->first_cpu,
|
||||
MSR_IA32_PACKAGE_THERM_INTERRUPT,
|
||||
phdev->start_pkg_therm_low,
|
||||
phdev->start_pkg_therm_high);
|
||||
thermal_zone_device_unregister(phdev->tzone);
|
||||
list_del(&phdev->list);
|
||||
kfree(phdev);
|
||||
}
|
||||
mutex_unlock(&phy_dev_list_mutex);
|
||||
platform_thermal_package_notify = NULL;
|
||||
platform_thermal_package_rate_control = NULL;
|
||||
for_each_online_cpu(i)
|
||||
cancel_delayed_work_sync(
|
||||
&per_cpu(pkg_temp_thermal_threshold_work, i));
|
||||
put_online_cpus();
|
||||
|
||||
kfree(pkg_work_scheduled);
|
||||
|
||||
debugfs_remove_recursive(debugfs);
|
||||
}
|
||||
|
||||
module_init(pkg_temp_thermal_init)
|
||||
module_exit(pkg_temp_thermal_exit)
|
||||
|
||||
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
|
||||
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -41,7 +41,7 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus);
|
|||
*/
|
||||
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
|
||||
|
||||
unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int);
|
||||
unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq);
|
||||
#else /* !CONFIG_CPU_THERMAL */
|
||||
static inline struct thermal_cooling_device *
|
||||
cpufreq_cooling_register(const struct cpumask *clip_cpus)
|
||||
|
@ -54,7 +54,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
|||
return;
|
||||
}
|
||||
static inline
|
||||
unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int)
|
||||
unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
|
||||
{
|
||||
return THERMAL_CSTATE_INVALID;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue