]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00241739-1 thermal: providing the thermal hot notification
authorRong Dian <b38775@freescale.com>
Fri, 25 Jan 2013 05:45:01 +0000 (13:45 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:52 +0000 (08:35 +0200)
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>
drivers/mxc/thermal/cooling.c
drivers/mxc/thermal/thermal.c

index 7019d9949c8ad95e31c1f77890fdb5f09d72883b..605c1c458db80503903c6eb4bd2ff0cdacd295ef 100644 (file)
@@ -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)
index 0982a7b781bdf4c5f711af50c1a98445b3cadc2e..109ea2b6cf00094745e6416020cf95df529ed919 100644 (file)
@@ -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;