Exemplo n.º 1
0
/*
 * convert_omap_sensor_temp_to_hotspot_temp() -Convert the temperature from the
 *		OMAP on-die temp sensor into OMAP hot spot temperature.
 *		This takes care of the existing temperature gradient between
 *		the OMAP hot spot and the on-die temp sensor.
 *		When PCB sensor is used, the temperature gradient is computed
 *		from PCB and averaged on-die sensor temperatures.
 *
 * @sensor_temp: Raw temperature reported by the OMAP die temp sensor
 *
 * Returns the calculated hot spot temperature for the zone calculation
 */
static signed int convert_omap_sensor_temp_to_hotspot_temp(int sensor_temp)
{
	int absolute_delta;

	if (pcb_sensor && (omap_gov->avg_is_valid == 1)) {
		omap_gov->pcb_temp = thermal_request_temp(pcb_sensor);
		if (omap_gov->pcb_temp < 0)
			return sensor_temp + omap_gov->absolute_delta;

		absolute_delta = (
			((omap_gov->avg_cpu_sensor_temp - omap_gov->pcb_temp) *
			OMAP_GRADIENT_SLOPE_WITH_PCB / 1000) +
			OMAP_GRADIENT_CONST_WITH_PCB);

		/* Ensure that this formula never returns negative value */
		if (absolute_delta < 0)
			absolute_delta = 0;
	} else {
		absolute_delta = ((sensor_temp * OMAP_GRADIENT_SLOPE / 1000) +
			OMAP_GRADIENT_CONST);
	}

	omap_gov->absolute_delta = absolute_delta;
	pr_debug("%s:sensor %d avg sensor %d pcb %d, delta %d hot spot %d\n",
			__func__, sensor_temp, omap_gov->avg_cpu_sensor_temp,
			omap_gov->pcb_temp, omap_gov->absolute_delta,
			sensor_temp + absolute_delta);

	return sensor_temp + absolute_delta;
}
static void decrease_mpu_freq_fn(struct work_struct *work)
{
	struct omap_die_governor *omap_gov;

	omap_gov = container_of(work, struct omap_die_governor,
				decrease_mpu_freq_work.work);

	omap_gov->sensor_temp = thermal_request_temp(omap_gov->temp_sensor);
	thermal_sensor_set_temp(omap_gov->temp_sensor);
}
/*
 * Make an average of the OMAP on-die temperature
 * this is helpful to handle burst activity of OMAP when extrapolating
 * the OMAP hot spot temperature from on-die sensor and PCB temperature
 * Re-evaluate the temperature gradient between hot spot and on-die sensor
 * (See absolute_delta) and reconfigure the thresholds if needed
 */
static void average_on_die_temperature(void)
{
	int i;
	int die_temp_lower = 0;
	int die_temp_upper = 0;
	int acc_temp;

	if (omap_gov->temp_sensor == NULL)
		return;

	/* Read current temperature */
	omap_gov->sensor_temp = thermal_request_temp(omap_gov->temp_sensor);

	/* if on-die sensor does not report a correct value, then return */
	if (omap_gov->sensor_temp == -EINVAL)
		return;

	/* Update historical buffer */
	for (i = 1; i < AVERAGE_NUMBER; i++) {
		cpu_sensor_temp_table[AVERAGE_NUMBER - i] =
		cpu_sensor_temp_table[AVERAGE_NUMBER - i - 1];
	}
	cpu_sensor_temp_table[0] = omap_gov->sensor_temp;

	if (cpu_sensor_temp_table[AVERAGE_NUMBER - 1] == 0)
		omap_gov->avg_is_valid = 0;
	else
		omap_gov->avg_is_valid = 1;

	/* Compute the new average value */
	acc_temp = 0;
	for (i = 0; i < AVERAGE_NUMBER; i++)
		acc_temp += cpu_sensor_temp_table[i];

	omap_gov->avg_cpu_sensor_temp =
		(acc_temp / AVERAGE_NUMBER);

	/*
	 * Reconfigure the current temperature thresholds according
	 * to the current PCB temperature
	 */
	convert_omap_sensor_temp_to_hotspot_temp(omap_gov->sensor_temp);
	die_temp_lower = hotspot_temp_to_sensor_temp(
		omap_gov->hotspot_temp_lower);
	die_temp_upper = hotspot_temp_to_sensor_temp(
		omap_gov->hotspot_temp_upper);
	thermal_device_call(omap_gov->temp_sensor, set_temp_thresh,
					die_temp_lower, die_temp_upper);

	return;
}