|
@@ -133,47 +133,62 @@ static int exynos_get_crit_temp(struct thermal_zone_device *thermal,
|
|
|
static int exynos_bind(struct thermal_zone_device *thermal,
|
|
|
struct thermal_cooling_device *cdev)
|
|
|
{
|
|
|
- int ret = 0, i, tab_size, level;
|
|
|
- struct freq_clip_table *tab_ptr, *clip_data;
|
|
|
struct exynos_thermal_zone *th_zone = thermal->devdata;
|
|
|
struct thermal_sensor_conf *data = th_zone->sensor_conf;
|
|
|
+ struct device_node *child, *gchild, *np;
|
|
|
+ struct of_phandle_args cooling_spec;
|
|
|
+ unsigned long max, state = 0;
|
|
|
+ int ret = 0, i = 0;
|
|
|
|
|
|
- tab_ptr = (struct freq_clip_table *)data->cooling_data.freq_data;
|
|
|
- tab_size = data->cooling_data.freq_clip_count;
|
|
|
-
|
|
|
- if (tab_ptr == NULL || tab_size == 0)
|
|
|
+ /*
|
|
|
+ * Below code is necessary to skip binding when cpufreq's
|
|
|
+ * frequency table is not yet initialized.
|
|
|
+ */
|
|
|
+ cdev->ops->get_max_state(cdev, &state);
|
|
|
+ if (!state && !th_zone->cool_dev_size) {
|
|
|
+ th_zone->cool_dev_size = 1;
|
|
|
+ th_zone->cool_dev[0] = cdev;
|
|
|
+ th_zone->bind = false;
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
- /* find the cooling device registered*/
|
|
|
- for (i = 0; i < th_zone->cool_dev_size; i++)
|
|
|
- if (cdev == th_zone->cool_dev[i])
|
|
|
- break;
|
|
|
+ np = of_find_node_by_path("/thermal-zones/cpu-thermal");
|
|
|
+ if (!np) {
|
|
|
+ pr_err("failed to find thmerla-zones/cpu-thermal node\n");
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
|
|
|
- /* No matching cooling device */
|
|
|
- if (i == th_zone->cool_dev_size)
|
|
|
- return 0;
|
|
|
+ child = of_get_child_by_name(np, "cooling-maps");
|
|
|
|
|
|
- /* Bind the thermal zone to the cpufreq cooling device */
|
|
|
- for (i = 0; i < tab_size; i++) {
|
|
|
- clip_data = (struct freq_clip_table *)&(tab_ptr[i]);
|
|
|
- level = cpufreq_cooling_get_level(0, clip_data->freq_clip_max);
|
|
|
- if (level == THERMAL_CSTATE_INVALID)
|
|
|
- return 0;
|
|
|
- switch (GET_ZONE(i)) {
|
|
|
- case MONITOR_ZONE:
|
|
|
- case WARN_ZONE:
|
|
|
- if (thermal_zone_bind_cooling_device(thermal, i, cdev,
|
|
|
- level, 0)) {
|
|
|
- dev_err(data->dev,
|
|
|
- "error unbinding cdev inst=%d\n", i);
|
|
|
- ret = -EINVAL;
|
|
|
- }
|
|
|
- th_zone->bind = true;
|
|
|
- break;
|
|
|
- default:
|
|
|
+ for_each_child_of_node(child, gchild) {
|
|
|
+ ret = of_parse_phandle_with_args(gchild, "cooling-device",
|
|
|
+ "#cooling-cells",
|
|
|
+ 0, &cooling_spec);
|
|
|
+ if (ret < 0) {
|
|
|
+ pr_err("missing cooling_device property\n");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cooling_spec.args_count < 2) {
|
|
|
ret = -EINVAL;
|
|
|
+ goto end;
|
|
|
}
|
|
|
+
|
|
|
+ max = cooling_spec.args[0];
|
|
|
+ if (thermal_zone_bind_cooling_device(thermal, i, cdev,
|
|
|
+ max, 0)) {
|
|
|
+ dev_err(data->dev,
|
|
|
+ "thermal error unbinding cdev inst=%d\n", i);
|
|
|
+
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ i++;
|
|
|
}
|
|
|
+ th_zone->bind = true;
|
|
|
+end:
|
|
|
+ of_node_put(child);
|
|
|
+ of_node_put(np);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
@@ -182,16 +197,12 @@ static int exynos_bind(struct thermal_zone_device *thermal,
|
|
|
static int exynos_unbind(struct thermal_zone_device *thermal,
|
|
|
struct thermal_cooling_device *cdev)
|
|
|
{
|
|
|
- int ret = 0, i, tab_size;
|
|
|
+ int ret = 0, i;
|
|
|
struct exynos_thermal_zone *th_zone = thermal->devdata;
|
|
|
struct thermal_sensor_conf *data = th_zone->sensor_conf;
|
|
|
+ struct device_node *child, *gchild, *np;
|
|
|
|
|
|
- if (th_zone->bind == false)
|
|
|
- return 0;
|
|
|
-
|
|
|
- tab_size = data->cooling_data.freq_clip_count;
|
|
|
-
|
|
|
- if (tab_size == 0)
|
|
|
+ if (th_zone->bind == false || !th_zone->cool_dev_size)
|
|
|
return 0;
|
|
|
|
|
|
/* find the cooling device registered*/
|
|
@@ -203,23 +214,30 @@ static int exynos_unbind(struct thermal_zone_device *thermal,
|
|
|
if (i == th_zone->cool_dev_size)
|
|
|
return 0;
|
|
|
|
|
|
- /* Bind the thermal zone to the cpufreq cooling device */
|
|
|
- for (i = 0; i < tab_size; i++) {
|
|
|
- switch (GET_ZONE(i)) {
|
|
|
- case MONITOR_ZONE:
|
|
|
- case WARN_ZONE:
|
|
|
- if (thermal_zone_unbind_cooling_device(thermal, i,
|
|
|
- cdev)) {
|
|
|
- dev_err(data->dev,
|
|
|
- "error unbinding cdev inst=%d\n", i);
|
|
|
- ret = -EINVAL;
|
|
|
- }
|
|
|
- th_zone->bind = false;
|
|
|
- break;
|
|
|
- default:
|
|
|
+ np = of_find_node_by_path("/thermal-zones/cpu-thermal");
|
|
|
+ if (!np) {
|
|
|
+ pr_err("failed to find thmerla-zones/cpu-thermal node\n");
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
+
|
|
|
+ child = of_get_child_by_name(np, "cooling-maps");
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ for_each_child_of_node(child, gchild) {
|
|
|
+ if (thermal_zone_unbind_cooling_device(thermal, i,
|
|
|
+ cdev)) {
|
|
|
+ dev_err(data->dev,
|
|
|
+ "error unbinding cdev inst=%d\n", i);
|
|
|
ret = -EINVAL;
|
|
|
+ goto end;
|
|
|
}
|
|
|
+ i++;
|
|
|
}
|
|
|
+ th_zone->bind = false;
|
|
|
+end:
|
|
|
+ of_node_put(child);
|
|
|
+ of_node_put(np);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|