summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRong Dian <b38775@freescale.com>2013-01-25 13:45:01 +0800
committerRong Dian <b38775@freescale.com>2013-01-28 18:27:42 +0800
commit59e50e83324fbb3315d973a17f00e07bcec2040d (patch)
treee3e0535be4de26d8e671f52f5b8c6f7efb881b35 /drivers
parent87a9758b9e153ff955aeb141e67b6023c7077791 (diff)
ENGR00241739-1 thermal: providing the thermal hot notification
Create thermal hot's own hot notificaiton callback register and unregister function. Provide the thermal notification broadcast enable and disable through /sys fs. Signed-off-by: Rong Dian <b38775@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mxc/thermal/cooling.c11
-rw-r--r--drivers/mxc/thermal/thermal.c64
2 files changed, 66 insertions, 9 deletions
diff --git a/drivers/mxc/thermal/cooling.c b/drivers/mxc/thermal/cooling.c
index 7019d9949c8a..605c1c458db8 100644
--- a/drivers/mxc/thermal/cooling.c
+++ b/drivers/mxc/thermal/cooling.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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
@@ -57,7 +57,8 @@ cpufreq, it minor 1, and when we promote cpufreq, it add 1, so
if it is 0, mean we didn't change the cpufreq */
static int cpufreq_change_count;
-extern int thermal_hot;
+extern atomic_t thermal_on;
+extern int thermal_notifier_call_chain(unsigned long val);
int anatop_thermal_get_cpufreq_cur(void)
{
int ret = -EINVAL;
@@ -238,7 +239,8 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev,
secondary CPUs that detached by thermal driver */
if (cooling_cpuhotplug) {
if (!state) {
- thermal_hot = 0;
+ if (atomic_read(&thermal_on))
+ thermal_notifier_call_chain(0);
for (i = 1; i < 4; i++) {
if (cpu_mask && (0x1 << i)) {
anatop_thermal_cpu_hotplug(true);
@@ -249,7 +251,8 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev,
}
} else {
if (!state) {
- thermal_hot = 0;
+ if (atomic_read(&thermal_on))
+ thermal_notifier_call_chain(0);
if (cpufreq_change_count < 0)
anatop_thermal_cpufreq_up();
else if (cpufreq_change_count > 0)
diff --git a/drivers/mxc/thermal/thermal.c b/drivers/mxc/thermal/thermal.c
index 0982a7b781bd..109ea2b6cf00 100644
--- a/drivers/mxc/thermal/thermal.c
+++ b/drivers/mxc/thermal/thermal.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
@@ -152,8 +152,7 @@ static const struct anatop_device_id thermal_device_ids[] = {
{ANATOP_THERMAL_HID},
{""},
};
-int thermal_hot;
-EXPORT_SYMBOL(thermal_hot);
+atomic_t thermal_on = ATOMIC_INIT(1);
enum {
DEBUG_USER_STATE = 1U << 0,
@@ -568,6 +567,27 @@ static int anatop_thermal_get_crit_temp(struct thermal_zone_device *thermal,
return -EINVAL;
}
+static BLOCKING_NOTIFIER_HEAD(thermal_chain_head);
+
+int register_thermal_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&thermal_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_thermal_notifier);
+
+int unregister_thermal_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&thermal_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_thermal_notifier);
+
+int thermal_notifier_call_chain(unsigned long val)
+{
+ return (blocking_notifier_call_chain(&thermal_chain_head, val, NULL)
+ == NOTIFY_BAD) ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(thermal_notifier_call_chain);
+
static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip,
enum thermal_trip_type trip_type)
{
@@ -585,7 +605,8 @@ static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip,
printk(KERN_WARNING "thermal_notify: trip_critical reached!\n");
arch_reset(mode, cmd);
} else if (trip_type == THERMAL_TRIP_HOT) {
- thermal_hot = 1;
+ if (atomic_read(&thermal_on))
+ thermal_notifier_call_chain(1);
printk(KERN_DEBUG "thermal_notify: trip_hot reached!\n");
type = ANATOP_THERMAL_NOTIFY_HOT;
/* if temperature increase, continue to detach secondary CPUs*/
@@ -600,7 +621,8 @@ static int anatop_thermal_notify(struct thermal_zone_device *thermal, int trip,
printk(KERN_INFO "No secondary CPUs detached!\n");
full_run = false;
} else {
- thermal_hot = 0;
+ if (atomic_read(&thermal_on))
+ thermal_notifier_call_chain(0);
if (!full_run) {
temperature_cooling = 0;
if (cooling_cpuhotplug)
@@ -871,6 +893,35 @@ static irqreturn_t anatop_thermal_alarm_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static ssize_t anatop_thermal_flag_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ return sprintf(buf, "read thermal_hot_flag:%d\n",
+ atomic_read(&thermal_on));
+}
+
+static ssize_t anatop_thermal_flag_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ unsigned long data;
+ ret = strict_strtoul(buf, 10, &data);
+ if (data == 0)
+ atomic_set(&thermal_on, 0);
+ else
+ atomic_set(&thermal_on, 1);
+ return count;
+}
+
+static struct device_attribute anatop_thermal_flag_dev_attr = {
+ .attr = {
+ .name = "thermal_hot_flag",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .show = anatop_thermal_flag_show,
+ .store = anatop_thermal_flag_store,
+};
+
static int anatop_thermal_probe(struct platform_device *pdev)
{
int retval = 0;
@@ -935,6 +986,9 @@ static int anatop_thermal_probe(struct platform_device *pdev)
anatop_thermal_add(device);
anatop_thermal_cpufreq_init();
+ retval = device_create_file(&pdev->dev, &anatop_thermal_flag_dev_attr);
+ if (retval)
+ dev_err(&pdev->dev, "create device file failed!\n");
pr_info("%s: default cooling device is cpufreq!\n", __func__);
goto success;