ARM: tegra: thermal: Edp into cooling device
[linux-2.6.git] / arch / arm / mach-tegra / tegra3_thermal.c
index f36f84c..32c817c 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/thermal.h>
+#include <linux/module.h>
 #include <mach/thermal.h>
-#include <mach/edp.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 
 #include "dvfs.h"
 
 static struct tegra_thermal_data *therm;
+static struct tegra_skin_data *skin_therm;
 static LIST_HEAD(tegra_therm_list);
 static DEFINE_MUTEX(tegra_therm_mutex);
 
 static struct balanced_throttle *throttle_list;
 static int throttle_list_size;
 
-#ifdef CONFIG_TEGRA_EDP_LIMITS
-static long edp_thermal_zone_val;
-#endif
+#define MAX_TEMP (120000)
 
 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
 static int skin_devs_bitmap;
@@ -73,58 +72,63 @@ static int tegra_thermal_get_temp_unlocked(long *tj_temp, bool offsetted)
        struct tegra_thermal_device *dev = NULL;
        int ret = 0;
 
-#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
        list_for_each_entry(dev, &tegra_therm_list, node)
                if (dev->id == therm->throttle_edp_device_id)
                        break;
-#endif
 
        if (dev) {
                dev->get_temp(dev->data, tj_temp);
                if (offsetted)
                        *tj_temp = dev2tj(dev, *tj_temp);
        } else {
+               *tj_temp = 0xdeadbeef;
                ret = -1;
        }
 
        return ret;
 }
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-
 static int tegra_thermal_zone_bind(struct thermal_zone_device *thz,
-                               struct thermal_cooling_device *cdevice) {
-
-       struct balanced_throttle *bthrot = cdevice->devdata;
+                               struct thermal_cooling_device *cdevice)
+{
+       int i, j, trip=0, trip_size, index;
+       struct tegra_cooling_device *tegra_cdev = cdevice->devdata;
        struct tegra_thermal_device *device = thz->devdata;
 
-       if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
-               (device->id == therm->throttle_edp_device_id))
-               return thermal_zone_bind_cooling_device(thz, 0, cdevice);
+       for (i=0; therm->binds[i].tdev_id; i++) {
+               if(device->id == therm->binds[i].tdev_id) {
+                       trip_size = therm->binds[i].get_trip_size();
+                       index = tegra_cdev->id & 0xffff;
+
+                       if (therm->binds[i].cdev_id  == (tegra_cdev->id & 0xffff0000)) {
+                               for (j=0; j < trip_size; j++) {
+                                       thermal_zone_bind_cooling_device(
+                                                       thz,
+                                                       trip + index,
+                                                       cdevice);
+                               }
+                       }
 
-#ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
-               (device->id == therm->skin_device_id))
-               return thermal_zone_bind_cooling_device(thz, 0, cdevice);
-#endif
+                       trip += trip_size;
+               }
+       }
 
        return 0;
 }
 
 static int tegra_thermal_zone_unbind(struct thermal_zone_device *thz,
                                struct thermal_cooling_device *cdevice) {
-       struct balanced_throttle *bthrot = cdevice->devdata;
+       int i, trip = 0;
+       struct tegra_cooling_device *tegra_cdev = cdevice->devdata;
        struct tegra_thermal_device *device = thz->devdata;
 
-       if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
-               (device->id == therm->throttle_edp_device_id))
-               return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
-
-#ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
-               (device->id == therm->skin_device_id))
-               return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
-#endif
+       for (i=0; therm->binds[i].tdev_id; i++) {
+               if(device->id == therm->binds[i].tdev_id) {
+                       if (tegra_cdev->id == therm->binds[i].cdev_id)
+                               thermal_zone_unbind_cooling_device(thz, trip, cdevice);
+                       trip += therm->binds[i].get_trip_size();
+               }
+       }
 
        return 0;
 }
@@ -141,35 +145,46 @@ static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
 }
 
 static int tegra_thermal_zone_get_trip_type(
-                       struct thermal_zone_device *thermal,
+                       struct thermal_zone_device *thz,
                        int trip,
                        enum thermal_trip_type *type) {
-       if (trip != 0)
-               return -EINVAL;
+       int i, trip_count = 0;
+       struct tegra_thermal_device *device = thz->devdata;
 
-       *type = THERMAL_TRIP_PASSIVE;
+       for (i=0; therm->binds[i].tdev_id; i++) {
+               if(device->id == therm->binds[i].tdev_id) {
+                       trip_count += therm->binds[i].get_trip_size();
+                       if (trip < trip_count) {
+                               *type = therm->binds[i].type;
+                               return 0;
+                       }
+               }
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thz,
                                        int trip,
                                        unsigned long *temp) {
+       int i, j, trip_size, trip_count = 0;
        struct tegra_thermal_device *device = thz->devdata;
 
-       if (trip != 0)
-               return -EINVAL;
-
-       if (device->id == therm->throttle_edp_device_id)
-               *temp = therm->temp_throttle;
-#ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       else if (device->id == therm->skin_device_id)
-               *temp = therm->temp_throttle_skin;
-#endif
-       else
-               return -EINVAL;
+       for (i=0; therm->binds[i].tdev_id; i++) {
+               if(device->id == therm->binds[i].tdev_id) {
+                       trip_size = therm->binds[i].get_trip_size();
+                       for (j=0; j < trip_size; j++) {
+                               if (trip == trip_count) {
+                                       *temp = therm->binds[i].get_trip_temp(
+                                                       &therm->binds[i], j);
+                                       return 0;
+                               }
+                               trip_count++;
+                       }
+               }
+       }
 
-       return 0;
+       return -EINVAL;
 }
 
 static struct thermal_zone_device_ops tegra_thermal_zone_ops = {
@@ -179,7 +194,6 @@ static struct thermal_zone_device_ops tegra_thermal_zone_ops = {
        .get_trip_type = tegra_thermal_zone_get_trip_type,
        .get_trip_temp = tegra_thermal_zone_get_trip_temp,
 };
-#endif
 
 static int tegra_thermal_pm_notify(struct notifier_block *nb,
                                unsigned long event, void *data)
@@ -200,7 +214,7 @@ static struct notifier_block tegra_thermal_nb = {
        .notifier_call = tegra_thermal_pm_notify,
 };
 
-static void tegra_thermal_alert_unlocked(void *data)
+static void tegra_thermal_alert(void *data)
 {
        struct tegra_thermal_device *device = data;
        long temp_tj;
@@ -214,45 +228,40 @@ static void tegra_thermal_alert_unlocked(void *data)
        int i;
 #endif
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-       if (device->thz) {
+       mutex_lock(&tegra_therm_mutex);
+
+       if (device->thz)
                if ((!device->thz->passive) && (!tegra_thermal_suspend))
                        thermal_zone_device_update(device->thz);
-       }
-#endif
 
        /* Convert all temps to tj and then do all work/logic in terms of
           tj in order to avoid confusion */
        if (tegra_thermal_get_temp_unlocked(&temp_tj, true))
-               return;
+               goto done;
+
        device->get_temp_low(device, &temp_low_dev);
        temp_low_tj = dev2tj(device, temp_low_dev);
 
        lo_limit_throttle_tj = temp_low_tj;
-       hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
+       hi_limit_throttle_tj = dev2tj(device, MAX_TEMP);
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
        hi_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
 
        if (temp_tj > dev2tj(device, therm->temp_throttle)) {
                lo_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
-               hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
+               hi_limit_throttle_tj = dev2tj(device, MAX_TEMP);
        }
-#endif
 
 #ifdef CONFIG_TEGRA_EDP_LIMITS
-       tegra_get_cpu_edp_limits(&z, &zones_sz);
-
-/* edp table based off of tdiode measurements */
 #define EDP_TEMP_TJ(_index) (z[_index].temperature * 1000 + therm->edp_offset)
-
+       tegra_get_cpu_edp_limits(&z, &zones_sz);
        if (temp_tj < EDP_TEMP_TJ(0)) {
                lo_limit_edp_tj = temp_low_tj;
                hi_limit_edp_tj = EDP_TEMP_TJ(0);
        } else if (temp_tj >= EDP_TEMP_TJ(zones_sz-1)) {
                lo_limit_edp_tj = EDP_TEMP_TJ(zones_sz-1) -
                                        therm->hysteresis_edp;
-               hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
+               hi_limit_edp_tj = dev2tj(device, MAX_TEMP);
        } else {
                for (i = 0; (i + 1) < zones_sz; i++) {
                        if ((temp_tj >= EDP_TEMP_TJ(i)) &&
@@ -267,7 +276,7 @@ static void tegra_thermal_alert_unlocked(void *data)
 #undef EDP_TEMP_TJ
 #else
        lo_limit_edp_tj = temp_low_tj;
-       hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
+       hi_limit_edp_tj = dev2tj(device, MAX_TEMP);
 #endif
 
        /* Get smallest window size */
@@ -277,26 +286,11 @@ static void tegra_thermal_alert_unlocked(void *data)
        device->set_limits(device->data,
                                tj2dev(device, lo_limit_tj),
                                tj2dev(device, hi_limit_tj));
-
-#ifdef CONFIG_TEGRA_EDP_LIMITS
-       /* inform edp governor */
-       if (edp_thermal_zone_val != temp_tj) {
-               long temp_edp = (dev2tj(device, temp_tj) - therm->edp_offset) / 1000;
-               tegra_edp_update_thermal_zone(temp_edp);
-               edp_thermal_zone_val = temp_edp;
-       }
-#endif
 }
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-/* Make sure this function remains stateless */
-static void tegra_thermal_alert(void *data)
-{
-       mutex_lock(&tegra_therm_mutex);
-       tegra_thermal_alert_unlocked(data);
+done:
        mutex_unlock(&tegra_therm_mutex);
 }
-#endif
 
 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
 static void tegra_skin_thermal_alert(void *data)
@@ -313,10 +307,10 @@ static int tegra_skin_device_register(struct tegra_thermal_device *device)
        struct therm_est_subdevice *skin_dev =
                kzalloc(sizeof(struct therm_est_subdevice), GFP_KERNEL);
 
-       for (i = 0; i < therm->skin_devs_size; i++) {
-               if (therm->skin_devs[i].id == device->id) {
+       for (i = 0; i < skin_therm->skin_devs_size; i++) {
+               if (skin_therm->skin_devs[i].id == device->id) {
                        memcpy(skin_dev->coeffs,
-                               therm->skin_devs[i].coeffs,
+                               skin_therm->skin_devs[i].coeffs,
                                sizeof(skin_devs[i]->coeffs));
                        break;
                }
@@ -328,15 +322,15 @@ static int tegra_skin_device_register(struct tegra_thermal_device *device)
        skin_devs[skin_devs_count++] = skin_dev;
 
        /* Create skin thermal device */
-       if (skin_devs_count == therm->skin_devs_size) {
+       if (skin_devs_count == skin_therm->skin_devs_size) {
                struct tegra_thermal_device *thermal_skin_device;
                struct therm_estimator *skin_estimator;
 
                skin_estimator = therm_est_register(
                                        skin_devs,
                                        skin_devs_count,
-                                       therm->skin_temp_offset,
-                                       therm->skin_period);
+                                       skin_therm->skin_temp_offset,
+                                       skin_therm->skin_period);
                thermal_skin_device = kzalloc(sizeof(struct tegra_thermal_device),
                                                        GFP_KERNEL);
                thermal_skin_device->name = "skin_pred";
@@ -357,14 +351,22 @@ static int tegra_skin_device_register(struct tegra_thermal_device *device)
 }
 #endif
 
+static int passive_get_trip_temp(void *data, long trip)
+{
+       struct tegra_thermal_bind *bind = data;
+       return bind->passive.trip_temp;
+}
+
+static int passive_get_trip_size(void)
+{
+       return 1;
+}
+
 int tegra_thermal_device_register(struct tegra_thermal_device *device)
 {
        struct tegra_thermal_device *dev;
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
        struct thermal_zone_device *thz;
-       int t1 = 0, t2 = 0, pdelay = 0;
-       bool create_thz = false;
-#endif
+       int i, t1 = 0, t2 = 0, pdelay = 0, trips=0;
 
        mutex_lock(&tegra_therm_mutex);
        list_for_each_entry(dev, &tegra_therm_list, node) {
@@ -374,74 +376,74 @@ int tegra_thermal_device_register(struct tegra_thermal_device *device)
                }
        }
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-       if (device->id == therm->throttle_edp_device_id) {
-               t1 = therm->tc1;
-               t2 = therm->tc2;
-               pdelay = therm->passive_delay;
-               create_thz = true;
-       }
-#endif
-#ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       if (device->id == therm->skin_device_id) {
-               t1 = 0;
-               t2 = 1;
-               pdelay = 5000;
-               create_thz = true;
+       for (i=0; therm->binds[i].tdev_id; i++) {
+               if(device->id == therm->binds[i].tdev_id) {
+                       switch(therm->binds[i].type) {
+                       case THERMAL_TRIP_PASSIVE:
+                               /* only one passive type allowed for now */
+                               if (pdelay)
+                                       return -EINVAL;
+
+                               /* These should be set only for ACTIVE types */
+                               if (therm->binds[i].get_trip_temp ||
+                                       therm->binds[i].get_trip_size)
+                                       return -EINVAL;
+
+                               t1 = therm->binds[i].passive.tc1;
+                               t2 = therm->binds[i].passive.tc2;
+                               pdelay = therm->binds[i].passive.passive_delay;
+
+                               therm->binds[i].get_trip_temp = passive_get_trip_temp;
+                               therm->binds[i].get_trip_size = passive_get_trip_size;
+                               break;
+                       }
+
+                       trips += therm->binds[i].get_trip_size();
+               }
        }
-#endif
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-       if (create_thz) {
+       if (trips) {
                thz = thermal_zone_device_register(
-                                               device->name,
-                                               1, /* trips */
-                                               device,
-                                               &tegra_thermal_zone_ops,
-                                               t1, /* dT/dt */
-                                               t2, /* throttle */
-                                               pdelay,
-                                               0); /* polling delay */
+                                       device->name,
+                                       trips, /* trips */
+                                       device,
+                                       &tegra_thermal_zone_ops,
+                                       t1, /* dT/dt */
+                                       t2, /* throttle */
+                                       pdelay,
+                                       0); /* polling delay */
                if (IS_ERR_OR_NULL(thz))
                        return -ENODEV;
 
                device->thz = thz;
        }
-#endif
 
        list_add(&device->node, &tegra_therm_list);
        mutex_unlock(&tegra_therm_mutex);
 
-       if (device->id == therm->shutdown_device_id) {
-               device->set_shutdown_temp(device->data, therm->temp_shutdown);
-       }
-
 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       if (device->id == therm->skin_device_id) {
+       if (device->id == skin_therm->skin_device_id) {
                if (create_thz)
                        device->set_alert(device->data,
                                tegra_skin_thermal_alert,
                                device);
-               device->set_limits(device->data, 0, therm->temp_throttle_skin);
+               device->set_limits(device->data, 0, skin_therm->temp_throttle_skin);
        }
 #endif
 
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
        if (device->id == therm->throttle_edp_device_id) {
                device->set_alert(device->data, tegra_thermal_alert, device);
 
                /* initialize limits */
                tegra_thermal_alert(device);
        }
-#endif
 
 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
-       if ((therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) &&
+       if ((skin_therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) &&
                device->id && skin_devs_bitmap)
                tegra_skin_device_register(device);
 #endif
 
-       register_pm_notifier(&tegra_thermal_nb);
        return 0;
 }
 
@@ -458,10 +460,12 @@ static int __init throttle_list_init(void)
 late_initcall(throttle_list_init);
 
 int __init tegra_thermal_init(struct tegra_thermal_data *data,
+                               struct tegra_skin_data *skin_data,
                                struct balanced_throttle *tlist,
                                int tlist_size)
 {
        therm = data;
+       skin_therm = skin_data;
 #ifdef CONFIG_DEBUG_FS
        thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0);
 #endif
@@ -469,27 +473,27 @@ int __init tegra_thermal_init(struct tegra_thermal_data *data,
 #ifdef CONFIG_TEGRA_SKIN_THROTTLE
        {
                int i;
-               for (i = 0; i < therm->skin_devs_size; i++)
-                       skin_devs_bitmap |= therm->skin_devs[i].id;
+               for (i = 0; i < skin_therm->skin_devs_size; i++)
+                       skin_devs_bitmap |= skin_therm->skin_devs[i].id;
        }
 #endif
 
        throttle_list = tlist;
        throttle_list_size = tlist_size;
 
+       register_pm_notifier(&tegra_thermal_nb);
+
        return 0;
 }
 
 int tegra_thermal_exit(void)
 {
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
        struct tegra_thermal_device *dev;
        mutex_lock(&tegra_therm_mutex);
        list_for_each_entry(dev, &tegra_therm_list, node) {
                thermal_zone_device_unregister(dev->thz);
        }
        mutex_unlock(&tegra_therm_mutex);
-#endif
 
        return 0;
 }
@@ -522,53 +526,6 @@ static int __init temp_tj_debug_init(void)
 }
 late_initcall(temp_tj_debug_init);
 
-
-#define TEGRA_THERM_DEBUGFS(_name, _device_id, throttle, shutdown) \
-       static int tegra_thermal_##_name##_set(void *data, u64 val) \
-       { \
-               struct tegra_thermal_device *dev; \
-               mutex_lock(&tegra_therm_mutex); \
-               therm->_name = val; \
-               list_for_each_entry(dev, &tegra_therm_list, node) \
-                       if (dev->id == therm->_device_id) \
-                               break; \
-               if (dev) { \
-                       if (throttle) \
-                               tegra_thermal_alert_unlocked(dev); \
-                       if (shutdown) \
-                               dev->set_shutdown_temp(dev->data, \
-                                                       therm->temp_shutdown); \
-               } \
-               mutex_unlock(&tegra_therm_mutex); \
-               return 0; \
-       } \
-       static int tegra_thermal_##_name##_get(void *data, u64 *val) \
-       { \
-               *val = (u64)therm->_name; \
-               return 0; \
-       } \
-       DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
-                               tegra_thermal_##_name##_get, \
-                               tegra_thermal_##_name##_set, \
-                               "%llu\n"); \
-       static int __init _name##_debug_init(void) \
-       { \
-               debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
-                       NULL, &_name##_fops); \
-               return 0; \
-       } \
-       late_initcall(_name##_debug_init);
-
-
-TEGRA_THERM_DEBUGFS(temp_shutdown, shutdown_device_id, false, true);
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-TEGRA_THERM_DEBUGFS(temp_throttle, throttle_edp_device_id, true, false);
-#endif
-#ifdef CONFIG_TEGRA_SKIN_THROTTLE
-TEGRA_THERM_DEBUGFS(temp_throttle_skin, skin_device_id, false, false);
-#endif
-
-#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
 #define THERM_DEBUGFS(_name) \
        static int tegra_thermal_##_name##_set(void *data, u64 val) \
        { \
@@ -611,4 +568,3 @@ THERM_DEBUGFS(tc1);
 THERM_DEBUGFS(tc2);
 THERM_DEBUGFS(passive_delay);
 #endif
-#endif