]> git.karo-electronics.de Git - linux-beck.git/commitdiff
power_supply: Register battery as a thermal zone
authorJenny TC <jenny.tc@intel.com>
Wed, 9 May 2012 15:06:47 +0000 (20:36 +0530)
committerAnton Vorontsov <cbouatmailru@gmail.com>
Mon, 18 Jun 2012 04:25:39 +0000 (21:25 -0700)
Battery and charger contribute to Thermals in most of the embedded
devices. So, it makes sense to identify them as Thermal zones in a
particular platform.

This patch registers a thermal zone if the power supply is reporting
a temperature property. The thermal zone will be used by platform's
thermal management solution.

Signed-off-by: Jenny TC <jenny.tc@intel.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
drivers/power/power_supply_core.c
include/linux/power_supply.h

index 6ad612726785f48cdd8dbcc2785de8e211aae873..ff990d26a0c03c4c13bdab9c003247705847082c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/power_supply.h>
+#include <linux/thermal.h>
 #include "power_supply.h"
 
 /* exported for the APM Power driver, APM emulation */
@@ -169,6 +170,63 @@ static void power_supply_dev_release(struct device *dev)
        kfree(dev);
 }
 
+#ifdef CONFIG_THERMAL
+static int power_supply_read_temp(struct thermal_zone_device *tzd,
+               unsigned long *temp)
+{
+       struct power_supply *psy;
+       union power_supply_propval val;
+       int ret;
+
+       WARN_ON(tzd == NULL);
+       psy = tzd->devdata;
+       ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
+
+       /* Convert tenths of degree Celsius to milli degree Celsius. */
+       if (!ret)
+               *temp = val.intval * 100;
+
+       return ret;
+}
+
+static struct thermal_zone_device_ops psy_tzd_ops = {
+       .get_temp = power_supply_read_temp,
+};
+
+static int psy_register_thermal(struct power_supply *psy)
+{
+       int i;
+
+       /* Register battery zone device psy reports temperature */
+       for (i = 0; i < psy->num_properties; i++) {
+               if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
+                       psy->tzd = thermal_zone_device_register(psy->name, 0,
+                                       psy, &psy_tzd_ops, 0, 0, 0, 0);
+                       if (IS_ERR(psy->tzd))
+                               return PTR_ERR(psy->tzd);
+                       break;
+               }
+       }
+       return 0;
+}
+
+static void psy_unregister_thermal(struct power_supply *psy)
+{
+       if (IS_ERR_OR_NULL(psy->tzd))
+               return;
+       thermal_zone_device_unregister(psy->tzd);
+}
+#else
+static int psy_register_thermal(struct power_supply *psy)
+{
+       return 0;
+}
+
+static void psy_unregister_thermal(struct power_supply *psy)
+{
+}
+#endif
+
 int power_supply_register(struct device *parent, struct power_supply *psy)
 {
        struct device *dev;
@@ -197,6 +255,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto device_add_failed;
 
+       rc = psy_register_thermal(psy);
+       if (rc)
+               goto register_thermal_failed;
+
        rc = power_supply_create_triggers(psy);
        if (rc)
                goto create_triggers_failed;
@@ -206,6 +268,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        goto success;
 
 create_triggers_failed:
+       psy_unregister_thermal(psy);
+register_thermal_failed:
        device_del(dev);
 kobject_set_name_failed:
 device_add_failed:
@@ -220,6 +284,7 @@ void power_supply_unregister(struct power_supply *psy)
        cancel_work_sync(&psy->changed_work);
        sysfs_remove_link(&psy->dev->kobj, "powers");
        power_supply_remove_triggers(psy);
+       psy_unregister_thermal(psy);
        device_unregister(psy->dev);
 }
 EXPORT_SYMBOL_GPL(power_supply_unregister);
index 3b912bee28d1693b8c6617f637354ed2869d306f..59ed2dd9dba92bed0c44aeb9e71bca3a2170f2eb 100644 (file)
@@ -173,6 +173,9 @@ struct power_supply {
        /* private */
        struct device *dev;
        struct work_struct changed_work;
+#ifdef CONFIG_THERMAL
+       struct thermal_zone_device *tzd;
+#endif
 
 #ifdef CONFIG_LEDS_TRIGGERS
        struct led_trigger *charging_full_trig;