Thermal/int340x/int3403: Fix memory leak
[cascardo/linux.git] / drivers / thermal / of-thermal.c
index 62143ba..e145b66 100644 (file)
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/string.h>
+#include <linux/thermal.h>
 
 #include "thermal_core.h"
 
 /***   Private data structures to represent thermal device tree data ***/
 
-/**
- * struct __thermal_trip - representation of a point in temperature domain
- * @np: pointer to struct device_node that this trip point was created from
- * @temperature: temperature value in miliCelsius
- * @hysteresis: relative hysteresis in miliCelsius
- * @type: trip point type
- */
-
-struct __thermal_trip {
-       struct device_node *np;
-       unsigned long int temperature;
-       unsigned long int hysteresis;
-       enum thermal_trip_type type;
-};
-
 /**
  * struct __thermal_bind_param - a match between trip and cooling device
  * @cooling_device: a pointer to identify the referred cooling device
@@ -77,8 +63,7 @@ struct __thermal_bind_params {
  * @num_tbps: number of thermal bind params
  * @tbps: an array of thermal bind params (0..num_tbps - 1)
  * @sensor_data: sensor private data used while reading temperature and trend
- * @get_temp: sensor callback to read temperature
- * @get_trend: sensor callback to read temperature trend
+ * @ops: set of callbacks to handle the thermal zone based on DT
  */
 
 struct __thermal_zone {
@@ -88,7 +73,7 @@ struct __thermal_zone {
 
        /* trip data */
        int ntrips;
-       struct __thermal_trip *trips;
+       struct thermal_trip *trips;
 
        /* cooling binding data */
        int num_tbps;
@@ -96,8 +81,7 @@ struct __thermal_zone {
 
        /* sensor interface */
        void *sensor_data;
-       int (*get_temp)(void *, long *);
-       int (*get_trend)(void *, long *);
+       const struct thermal_zone_of_device_ops *ops;
 };
 
 /***   DT thermal zone device callbacks   ***/
@@ -107,10 +91,96 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
 {
        struct __thermal_zone *data = tz->devdata;
 
-       if (!data->get_temp)
+       if (!data->ops->get_temp)
                return -EINVAL;
 
-       return data->get_temp(data->sensor_data, temp);
+       return data->ops->get_temp(data->sensor_data, temp);
+}
+
+/**
+ * of_thermal_get_ntrips - function to export number of available trip
+ *                        points.
+ * @tz: pointer to a thermal zone
+ *
+ * This function is a globally visible wrapper to get number of trip points
+ * stored in the local struct __thermal_zone
+ *
+ * Return: number of available trip points, -ENODEV when data not available
+ */
+int of_thermal_get_ntrips(struct thermal_zone_device *tz)
+{
+       struct __thermal_zone *data = tz->devdata;
+
+       if (!data || IS_ERR(data))
+               return -ENODEV;
+
+       return data->ntrips;
+}
+EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
+
+/**
+ * of_thermal_is_trip_valid - function to check if trip point is valid
+ *
+ * @tz:        pointer to a thermal zone
+ * @trip:      trip point to evaluate
+ *
+ * This function is responsible for checking if passed trip point is valid
+ *
+ * Return: true if trip point is valid, false otherwise
+ */
+bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
+{
+       struct __thermal_zone *data = tz->devdata;
+
+       if (!data || trip >= data->ntrips || trip < 0)
+               return false;
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
+
+/**
+ * of_thermal_get_trip_points - function to get access to a globally exported
+ *                             trip points
+ *
+ * @tz:        pointer to a thermal zone
+ *
+ * This function provides a pointer to trip points table
+ *
+ * Return: pointer to trip points table, NULL otherwise
+ */
+const struct thermal_trip * const
+of_thermal_get_trip_points(struct thermal_zone_device *tz)
+{
+       struct __thermal_zone *data = tz->devdata;
+
+       if (!data)
+               return NULL;
+
+       return data->trips;
+}
+EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
+
+/**
+ * of_thermal_set_emul_temp - function to set emulated temperature
+ *
+ * @tz:        pointer to a thermal zone
+ * @temp:      temperature to set
+ *
+ * This function gives the ability to set emulated value of temperature,
+ * which is handy for debugging
+ *
+ * Return: zero on success, error code otherwise
+ */
+static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
+                                   unsigned long temp)
+{
+       struct __thermal_zone *data = tz->devdata;
+
+       if (!data->ops || !data->ops->set_emul_temp)
+               return -EINVAL;
+
+       return data->ops->set_emul_temp(data->sensor_data, temp);
 }
 
 static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
@@ -120,10 +190,10 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
        long dev_trend;
        int r;
 
-       if (!data->get_trend)
+       if (!data->ops->get_trend)
                return -EINVAL;
 
-       r = data->get_trend(data->sensor_data, &dev_trend);
+       r = data->ops->get_trend(data->sensor_data, &dev_trend);
        if (r)
                return r;
 
@@ -324,8 +394,7 @@ static struct thermal_zone_device_ops of_thermal_ops = {
 static struct thermal_zone_device *
 thermal_zone_of_add_sensor(struct device_node *zone,
                           struct device_node *sensor, void *data,
-                          int (*get_temp)(void *, long *),
-                          int (*get_trend)(void *, long *))
+                          const struct thermal_zone_of_device_ops *ops)
 {
        struct thermal_zone_device *tzd;
        struct __thermal_zone *tz;
@@ -336,13 +405,16 @@ thermal_zone_of_add_sensor(struct device_node *zone,
 
        tz = tzd->devdata;
 
+       if (!ops)
+               return ERR_PTR(-EINVAL);
+
        mutex_lock(&tzd->lock);
-       tz->get_temp = get_temp;
-       tz->get_trend = get_trend;
+       tz->ops = ops;
        tz->sensor_data = data;
 
        tzd->ops->get_temp = of_thermal_get_temp;
        tzd->ops->get_trend = of_thermal_get_trend;
+       tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
        mutex_unlock(&tzd->lock);
 
        return tzd;
@@ -356,8 +428,7 @@ thermal_zone_of_add_sensor(struct device_node *zone,
  *             than one sensors
  * @data: a private pointer (owned by the caller) that will be passed
  *        back, when a temperature reading is needed.
- * @get_temp: a pointer to a function that reads the sensor temperature.
- * @get_trend: a pointer to a function that reads the sensor temperature trend.
+ * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
  *
  * This function will search the list of thermal zones described in device
  * tree and look for the zone that refer to the sensor device pointed by
@@ -382,9 +453,8 @@ thermal_zone_of_add_sensor(struct device_node *zone,
  * check the return value with help of IS_ERR() helper.
  */
 struct thermal_zone_device *
-thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
-                               void *data, int (*get_temp)(void *, long *),
-                               int (*get_trend)(void *, long *))
+thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
+                               const struct thermal_zone_of_device_ops *ops)
 {
        struct device_node *np, *child, *sensor_np;
        struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
@@ -426,9 +496,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
 
                if (sensor_specs.np == sensor_np && id == sensor_id) {
                        tzd = thermal_zone_of_add_sensor(child, sensor_np,
-                                                        data,
-                                                        get_temp,
-                                                        get_trend);
+                                                        data, ops);
                        of_node_put(sensor_specs.np);
                        of_node_put(child);
                        goto exit;
@@ -475,9 +543,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
        mutex_lock(&tzd->lock);
        tzd->ops->get_temp = NULL;
        tzd->ops->get_trend = NULL;
+       tzd->ops->set_emul_temp = NULL;
 
-       tz->get_temp = NULL;
-       tz->get_trend = NULL;
+       tz->ops = NULL;
        tz->sensor_data = NULL;
        mutex_unlock(&tzd->lock);
 }
@@ -501,7 +569,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
  */
 static int thermal_of_populate_bind_params(struct device_node *np,
                                           struct __thermal_bind_params *__tbp,
-                                          struct __thermal_trip *trips,
+                                          struct thermal_trip *trips,
                                           int ntrips)
 {
        struct of_phandle_args cooling_spec;
@@ -604,7 +672,7 @@ static int thermal_of_get_trip_type(struct device_node *np,
  * Return: 0 on success, proper error code otherwise
  */
 static int thermal_of_populate_trip(struct device_node *np,
-                                   struct __thermal_trip *trip)
+                                   struct thermal_trip *trip)
 {
        int prop;
        int ret;