// SPDX-License-Identifier: GPL-2.0-only
/*
 *  step_wise.c - A step-by-step Thermal throttling governor
 *
 *  Copyright (C) 2012 Intel Corp
 *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
 *
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/thermal.h>
#include <linux/minmax.h>
#include "thermal_trace.h"

#include "thermal_core.h"

/*
 * If the temperature is higher than a trip point,
 *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
 *       state for this trip point
 *    b. if the trend is THERMAL_TREND_DROPPING, do nothing
 * If the temperature is lower than a trip point,
 *    a. if the trend is THERMAL_TREND_RAISING, do nothing
 *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
 *       state for this trip point, if the cooling state already
 *       equals lower limit, deactivate the thermal instance
 */
static unsigned long get_target_state(struct thermal_instance *instance,
				enum thermal_trend trend, bool throttle)
{
	struct thermal_cooling_device *cdev = instance->cdev;
	unsigned long cur_state;

	/*
	 * We keep this instance the way it is by default.
	 * Otherwise, we use the current state of the
	 * cdev in use to determine the next_target.
	 */
	cdev->ops->get_cur_state(cdev, &cur_state);
	dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);

	if (!instance->initialized) {
		if (throttle)
			return clamp(cur_state + 1, instance->lower, instance->upper);

		return THERMAL_NO_TARGET;
	}

	if (throttle) {
		if (trend == THERMAL_TREND_RAISING)
			return clamp(cur_state + 1, instance->lower, instance->upper);
	} else if (trend == THERMAL_TREND_DROPPING) {
		if (cur_state <= instance->lower)
			return THERMAL_NO_TARGET;

		/*
		 * If 'throttle' is false, no mitigation is necessary, so
		 * request the lower state for this instance.
		 */
		return instance->lower;
	}

	return instance->target;
}

static void thermal_zone_trip_update(struct thermal_zone_device *tz,
				     const struct thermal_trip *trip,
				     int trip_threshold)
{
	enum thermal_trend trend = get_tz_trend(tz, trip);
	int trip_id = thermal_zone_trip_id(tz, trip);
	struct thermal_instance *instance;
	bool throttle = false;

	if (tz->temperature >= trip_threshold) {
		throttle = true;
		trace_thermal_zone_trip(tz, trip_id, trip->type);
	}

	dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
		trip_id, trip->type, trip_threshold, trend, throttle);

	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
		int old_target;

		if (instance->trip != trip)
			continue;

		old_target = instance->target;
		instance->target = get_target_state(instance, trend, throttle);

		dev_dbg(&instance->cdev->device, "old_target=%d, target=%ld\n",
			old_target, instance->target);

		if (instance->initialized && old_target == instance->target)
			continue;

		instance->initialized = true;

		mutex_lock(&instance->cdev->lock);
		instance->cdev->updated = false; /* cdev needs update */
		mutex_unlock(&instance->cdev->lock);
	}
}

static void step_wise_manage(struct thermal_zone_device *tz)
{
	const struct thermal_trip_desc *td;
	struct thermal_instance *instance;

	lockdep_assert_held(&tz->lock);

	/*
	 * Throttling Logic: Use the trend of the thermal zone to throttle.
	 * If the thermal zone is 'heating up', throttle all of the cooling
	 * devices associated with each trip point by one step. If the zone
	 * is 'cooling down', it brings back the performance of the devices
	 * by one step.
	 */
	for_each_trip_desc(tz, td) {
		const struct thermal_trip *trip = &td->trip;

		if (trip->temperature == THERMAL_TEMP_INVALID ||
		    trip->type == THERMAL_TRIP_CRITICAL ||
		    trip->type == THERMAL_TRIP_HOT)
			continue;

		thermal_zone_trip_update(tz, trip, td->threshold);
	}

	list_for_each_entry(instance, &tz->thermal_instances, tz_node)
		thermal_cdev_update(instance->cdev);
}

static struct thermal_governor thermal_gov_step_wise = {
	.name	= "step_wise",
	.manage	= step_wise_manage,
};
THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);
