arm: tegra: add voltage capping thermals
Amit Kamath [Mon, 11 Mar 2013 09:52:56 +0000 (14:52 +0530)]
Voltage capping needs to use soc therm sensors to accurately measure
temperatures. This change adds voltage capping related trip points
before registering to the soc_therm driver.

bug 1042409

Change-Id: I9bebaa39f88f0142c3b8ba7e07a70d86fdbc675e
Signed-off-by: Amit Kamath <akamath@nvidia.com>
Reviewed-on: http://git-master/r/208014
(cherry picked from commit dbd872140e5be5d4a358dd77de790f17c78b1594)
Reviewed-on: http://git-master/r/214972
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

arch/arm/mach-tegra/board-common.c
arch/arm/mach-tegra/board-common.h
arch/arm/mach-tegra/tegra11_cpu_volt_cap.c

index cb69239..967bf51 100644 (file)
@@ -175,3 +175,12 @@ void tegra_add_tj_trips(struct thermal_trip_info *trips, int *num_trips)
 {
        tegra_add_trip_points(trips, num_trips, tegra_core_edp_get_cdev());
 }
+
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+void tegra_add_vc_trips(struct thermal_trip_info *trips, int *num_trips)
+{
+#ifdef CONFIG_CPU_FREQ
+       tegra_add_trip_points(trips, num_trips, tegra_vc_get_cdev());
+#endif
+}
+#endif
index 11f1622..74cf20c 100644 (file)
@@ -29,4 +29,6 @@ int  uart_console_debug_init(int defaul_debug_port);
 int tegra_vibrator_init(void);
 void tegra_add_cdev_trips(struct thermal_trip_info *trips, int *num_trips);
 void tegra_add_tj_trips(struct thermal_trip_info *trips, int *num_trips);
+struct tegra_cooling_device *tegra_vc_get_cdev(void);
+void tegra_add_vc_trips(struct thermal_trip_info *trips, int *num_trips);
 #endif
index d141c09..0406cd6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/tegra11_cpu_volt_cap.c
  *
- * Copyright (C) 2012 NVIDIA Corporation
+ * Copyright (c) 2011-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
 
 #include "cpu-tegra.h"
 
-static struct volt_cap_data {
+static int vc_temperatures[] = {20, 30, 40, 50, 60, 70, 80, 90, 100};
+
+static struct tegra_cooling_device vc_cdev = {
+                       .cdev_type = "tegra_vc",
+                       .trip_temperatures = vc_temperatures,
+                       .trip_temperatures_num = ARRAY_SIZE(vc_temperatures)
+};
+
+struct volt_cap_data {
        int capped_voltage;
        bool voltage_capping_enabled;
-} capping_data;
+       struct tegra_cooling_device *cd;
+       int thermal_idx;
+};
+
+static struct volt_cap_data capping_data = {
+                       .cd = &vc_cdev,
+                       .thermal_idx = 0,
+};
 
 static DEFINE_MUTEX(capping_lock);
 static struct kobject *volt_cap_kobj;
@@ -107,9 +122,63 @@ static int volt_cap_sysfs_init(void)
        return 0;
 }
 
+/* Cooling device limits minimum rail voltage at cold temperature in pll mode */
+static int tegra_vc_get_max_state(
+       struct thermal_cooling_device *cdev, unsigned long *max_state)
+{
+       struct volt_cap_data *vcd = (struct volt_cap_data *)cdev->devdata;
+       *max_state = vcd->cd->trip_temperatures_num;
+       return 0;
+}
+
+static int tegra_vc_get_cur_state(
+       struct thermal_cooling_device *cdev, unsigned long *cur_state)
+{
+       struct volt_cap_data *vcd = (struct volt_cap_data *)cdev->devdata;
+
+       *cur_state = vcd->thermal_idx;
+       return 0;
+}
+
+static int tegra_vc_set_cur_state(
+       struct thermal_cooling_device *cdev, unsigned long cur_state)
+{
+       struct volt_cap_data *vcd = (struct volt_cap_data *)cdev->devdata;
+
+       mutex_lock(&capping_lock);
+       if (vcd->thermal_idx != cur_state) {
+               thermal_generate_netlink_event(
+                       vcd->cd->trip_temperatures[cur_state],
+                       cur_state > vcd->thermal_idx ?
+                               THERMAL_AUX1 : THERMAL_AUX0);
+               vcd->thermal_idx = cur_state;
+       }
+       mutex_unlock(&capping_lock);
+       return 0;
+}
+
+static struct thermal_cooling_device_ops tegra_vc_notify_cooling_ops = {
+       .get_max_state = tegra_vc_get_max_state,
+       .get_cur_state = tegra_vc_get_cur_state,
+       .set_cur_state = tegra_vc_set_cur_state,
+};
+
+struct tegra_cooling_device *tegra_vc_get_cdev(void)
+{
+       return &vc_cdev;
+}
+
 static int __init tegra_volt_cap_init(void)
 {
+       struct thermal_cooling_device *tcd;
+
        volt_cap_sysfs_init();
+       tcd = thermal_cooling_device_register(
+               "tegra_vc", &capping_data,
+               &tegra_vc_notify_cooling_ops);
+       if (IS_ERR_OR_NULL(tcd))
+               pr_err("tegra cooling device %s failed to register\n",
+                      "tegra-vc");
 
        return 0;
 }