@@ -303,6 +303,8 @@ struct tegra_thermctl_zone {
struct tegra_soctherm *ts;
struct thermal_zone_device *tz;
const struct tegra_tsensor_group *sg;
+ /* instance of an internal throttle cooling device */
+ struct thermal_cooling_device *cdev;
};
struct soctherm_oc_cfg {
@@ -315,6 +317,7 @@ struct soctherm_oc_cfg {
};
struct soctherm_throt_cfg {
+ struct tegra_soctherm *soctherm;
const char *name;
unsigned int id;
u8 priority;
@@ -585,10 +588,10 @@ static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id)
static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
{
struct tegra_thermctl_zone *zone = tz->devdata;
- struct tegra_soctherm *ts = zone->ts;
- struct thermal_trip trip;
const struct tegra_tsensor_group *sg = zone->sg;
+ struct tegra_soctherm *ts = zone->ts;
struct device *dev = zone->dev;
+ struct thermal_trip trip;
int ret;
if (!tz)
@@ -610,26 +613,14 @@ static int tegra_thermctl_set_trip_temp(struct thermal_zone_device *tz, int trip
return 0;
} else if (trip.type == THERMAL_TRIP_HOT) {
- int i;
-
- for (i = 0; i < THROTTLE_SIZE; i++) {
- struct thermal_cooling_device *cdev;
- struct soctherm_throt_cfg *stc;
-
- if (!ts->throt_cfgs[i].init)
- continue;
-
- cdev = ts->throt_cfgs[i].cdev;
- if (get_thermal_instance(tz, cdev, trip_id))
- stc = find_throttle_cfg_by_name(ts, cdev->type);
- else
- continue;
+ if (zone->cdev) {
+ struct soctherm_throt_cfg *stc = zone->cdev->devdata;
return throttrip_program(dev, sg, stc, temp);
}
}
- return 0;
+ return ret;
}
static void thermal_irq_enable(struct tegra_thermctl_zone *zn)
@@ -687,26 +678,6 @@ static const struct thermal_zone_device_ops tegra_of_thermal_ops = {
.set_trips = tegra_thermctl_set_trips,
};
-static int get_hot_temp(struct thermal_zone_device *tz, int *trip_id, int *temp)
-{
- int i, ret;
- struct thermal_trip trip;
-
- for (i = 0; i < thermal_zone_get_num_trips(tz); i++) {
-
- ret = thermal_zone_get_trip(tz, i, &trip);
- if (ret)
- return -EINVAL;
-
- if (trip.type == THERMAL_TRIP_HOT) {
- *trip_id = i;
- return 0;
- }
- }
-
- return -EINVAL;
-}
-
/**
* tegra_soctherm_set_hwtrips() - set HW trip point from DT data
* @dev: struct device * of the SOC_THERM instance
@@ -736,8 +707,7 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
struct thermal_zone_device *tz)
{
struct tegra_soctherm *ts = dev_get_drvdata(dev);
- struct soctherm_throt_cfg *stc;
- int i, trip, temperature, ret;
+ int temperature, ret;
/* Get thermtrips. If missing, try to get critical trips. */
temperature = tsensor_group_thermtrip_get(ts, sg->id);
@@ -754,42 +724,6 @@ static int tegra_soctherm_set_hwtrips(struct device *dev,
dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n",
sg->name, temperature);
- ret = get_hot_temp(tz, &trip, &temperature);
- if (ret) {
- dev_info(dev, "throttrip: %s: missing hot temperature\n",
- sg->name);
- return 0;
- }
-
- for (i = 0; i < THROTTLE_OC1; i++) {
- struct thermal_cooling_device *cdev;
-
- if (!ts->throt_cfgs[i].init)
- continue;
-
- cdev = ts->throt_cfgs[i].cdev;
- if (get_thermal_instance(tz, cdev, trip))
- stc = find_throttle_cfg_by_name(ts, cdev->type);
- else
- continue;
-
- ret = throttrip_program(dev, sg, stc, temperature);
- if (ret) {
- dev_err(dev, "throttrip: %s: error during enable\n",
- sg->name);
- return ret;
- }
-
- dev_info(dev,
- "throttrip: will throttle when %s reaches %d mC\n",
- sg->name, temperature);
- break;
- }
-
- if (i == THROTTLE_SIZE)
- dev_info(dev, "throttrip: %s: missing throttle cdev\n",
- sg->name);
-
return 0;
}
@@ -1497,6 +1431,55 @@ static int soctherm_clk_enable(struct platform_device *pdev, bool enable)
return 0;
}
+static int throt_bind(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz, int trip_id,
+ unsigned long upper, unsigned long lower,
+ unsigned int weight)
+{
+ struct tegra_thermctl_zone *zone = tz->devdata;
+ struct device *dev = &cdev->device;
+ struct thermal_trip trip;
+ int err;
+
+ err = thermal_zone_get_trip(tz, trip_id, &trip);
+ if (err < 0)
+ return err;
+
+ if (trip.type == THERMAL_TRIP_HOT) {
+ struct soctherm_throt_cfg *stc = cdev->devdata;
+
+ err = throttrip_program(zone->dev, zone->sg, stc, trip.temperature);
+ if (err < 0) {
+ dev_err(dev, "throttrip: %s: error during enable\n",
+ zone->sg->name);
+ return err;
+ }
+
+ dev_info(dev, "throttrip: will throttle when %s reaches %d mC\n",
+ zone->sg->name, trip.temperature);
+
+ /* keep a reference to this for ->set_trip_temp() */
+ zone->cdev = cdev;
+ }
+
+ return 0;
+}
+
+static void throt_unbind(struct thermal_cooling_device *cdev,
+ struct thermal_zone_device *tz, int trip_id)
+{
+ struct tegra_thermctl_zone *zone = tz->devdata;
+ struct thermal_trip trip;
+ int err;
+
+ err = __thermal_zone_get_trip(tz, trip_id, &trip);
+ if (err < 0)
+ return;
+
+ if (trip.type == THERMAL_TRIP_HOT)
+ zone->cdev = NULL;
+}
+
static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,
unsigned long *max_state)
{
@@ -1507,7 +1490,8 @@ static int throt_get_cdev_max_state(struct thermal_cooling_device *cdev,
static int throt_get_cdev_cur_state(struct thermal_cooling_device *cdev,
unsigned long *cur_state)
{
- struct tegra_soctherm *ts = cdev->devdata;
+ struct soctherm_throt_cfg *stc = cdev->devdata;
+ struct tegra_soctherm *ts = stc->soctherm;
u32 r;
r = readl(ts->regs + THROT_STATUS);
@@ -1526,6 +1510,8 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
}
static const struct thermal_cooling_device_ops throt_cooling_ops = {
+ .bind = throt_bind,
+ .unbind = throt_unbind,
.get_max_state = throt_get_cdev_max_state,
.get_cur_state = throt_get_cdev_cur_state,
.set_cur_state = throt_set_cdev_state,
@@ -1576,8 +1562,8 @@ static int soctherm_thermtrips_parse(struct platform_device *pdev)
}
static void soctherm_oc_cfg_parse(struct device *dev,
- struct device_node *np_oc,
- struct soctherm_throt_cfg *stc)
+ struct device_node *np_oc,
+ struct soctherm_throt_cfg *stc)
{
u32 val;
@@ -1694,13 +1680,15 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
if (err)
continue;
+ stc->soctherm = ts;
+
if (stc->id >= THROTTLE_OC1) {
soctherm_oc_cfg_parse(dev, np_stcc, stc);
stc->init = true;
} else {
tcd = thermal_of_cooling_device_register(np_stcc,
- (char *)name, ts,
+ (char *)name, stc,
&throt_cooling_ops);
if (IS_ERR_OR_NULL(tcd)) {
dev_err(dev,