Beispiel #1
0
static int
temp_throttle_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
	struct imx6_anatop_softc *sc = arg1;
	int err;
	uint32_t temp;

	temp = sc->temp_throttle_val + TZ_ZEROC;
	err = sysctl_handle_int(oidp, &temp, 0, req);
	if (temp < TZ_ZEROC)
		return (ERANGE);
	temp -= TZ_ZEROC;
	if (err != 0 || req->newptr == NULL || temp == sc->temp_throttle_val)
		return (err);

	/* Value changed, update counts in softc and hardware. */
	sc->temp_throttle_val = temp;
	sc->temp_throttle_trigger_cnt = temp_to_count(sc, sc->temp_throttle_val);
	sc->temp_throttle_reset_cnt = temp_to_count(sc, sc->temp_throttle_val - 100);
	imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR,
	    IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK);
	imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET,
	    (sc->temp_throttle_trigger_cnt <<
	     IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT));
	return (err);
}
Beispiel #2
0
static void
initialize_tempmon(struct imx6_anatop_softc *sc)
{
	uint32_t cal;
	struct sysctl_ctx_list *ctx;

	/*
	 * Fetch calibration data: a sensor count at room temperature (25C),
	 * a sensor count at a high temperature, and that temperature
	 */
	cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1);
	sc->temp_room_cnt = (cal & 0xFFF00000) >> 20;
	sc->temp_high_cnt = (cal & 0x000FFF00) >> 8;
	sc->temp_high_val = (cal & 0x000000FF) * 10;

	/*
	 * Throttle to a lower cpu freq at 10C below the "hot" temperature, and
	 * reset back to max cpu freq at 5C below the trigger.
	 */
	sc->temp_throttle_val = sc->temp_high_val - 100;
	sc->temp_throttle_trigger_cnt =
	    temp_to_count(sc, sc->temp_throttle_val);
	sc->temp_throttle_reset_cnt = 
	    temp_to_count(sc, sc->temp_throttle_val - 50);

	/*
	 * Set the sensor to sample automatically at 16Hz (32.768KHz/0x800), set
	 * the throttle count, and begin making measurements.
	 */
	imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE1, 0x0800);
	imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0,
	    (sc->temp_throttle_trigger_cnt << 
	    IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) |
	    IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE);

	/*
	 * XXX Note that the alarm-interrupt feature isn't working yet, so
	 * we'll use a callout handler to check at 10Hz.  Make sure we have an
	 * initial temperature reading before starting up the callouts so we
	 * don't get a bogus reading of zero.
	 */
	while (sc->temp_last_cnt == 0)
		temp_update_count(sc);
	sc->temp_throttle_delay = 100 * SBT_1MS;
	callout_init(&sc->temp_throttle_callout, 0);
	callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay, 
	    0, tempmon_throttle_check, sc, 0);

	ctx = device_get_sysctl_ctx(sc->dev);
	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
	    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
	    temp_sysctl_handler, "IK", "Current die temperature");
	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
	    OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc,
	    0, temp_throttle_sysctl_handler, "IK", 
	    "Throttle CPU when exceeding this temperature");
}