Commit 5314b154 authored by Mateusz Majewski's avatar Mateusz Majewski Committed by Daniel Lezcano
Browse files

thermal/drivers/exynos: Use set_trips ops



Currently, each trip point defined in the device tree corresponds to a
single hardware interrupt. This commit instead switches to using two
hardware interrupts, whose values are set dynamically using the
set_trips callback. Additionally, the critical temperature threshold is
handled specifically.

Setting interrupts in this way also fixes a long-standing lockdep
warning, which was caused by calling thermal_zone_get_trips with our
lock being held. Do note that this requires TMU initialization to be
split into two parts, as done by the parent commit: parts of the
initialization call into the thermal_zone_device structure and so must
be done after its registration, but the initialization is also
responsible for setting up calibration, which must be done before
thermal_zone_device registration, which will call set_trips for the
first time; if the calibration is not done in time, the interrupt values
will be silently wrong!

Reviewed-by: default avatarLukasz Luba <lukasz.luba@arm.com>
Signed-off-by: default avatarMateusz Majewski <m.majewski2@samsung.com>
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20231201095625.301884-10-m.majewski2@samsung.com
parent af00d488
Loading
Loading
Loading
Loading
+205 −180
Original line number Diff line number Diff line
@@ -158,10 +158,12 @@ enum soc_type {
 *	in the positive-TC generator block
 *	0 < reference_voltage <= 31
 * @tzd: pointer to thermal_zone_device structure
 * @ntrip: number of supported trip points.
 * @enabled: current status of TMU device
 * @tmu_set_trip_temp: SoC specific method to set trip (rising threshold)
 * @tmu_set_trip_hyst: SoC specific to set hysteresis (falling threshold)
 * @tmu_set_low_temp: SoC specific method to set trip (falling threshold)
 * @tmu_set_high_temp: SoC specific method to set trip (rising threshold)
 * @tmu_set_crit_temp: SoC specific method to set critical temperature
 * @tmu_disable_low: SoC specific method to disable an interrupt (falling threshold)
 * @tmu_disable_high: SoC specific method to disable an interrupt (rising threshold)
 * @tmu_initialize: SoC specific TMU initialization method
 * @tmu_control: SoC specific TMU control method
 * @tmu_read: SoC specific TMU temperature read method
@@ -183,13 +185,13 @@ struct exynos_tmu_data {
	u8 gain;
	u8 reference_voltage;
	struct thermal_zone_device *tzd;
	unsigned int ntrip;
	bool enabled;

	void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip,
				 u8 temp);
	void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip,
				 u8 temp, u8 hyst);
	void (*tmu_set_low_temp)(struct exynos_tmu_data *data, u8 temp);
	void (*tmu_set_high_temp)(struct exynos_tmu_data *data, u8 temp);
	void (*tmu_set_crit_temp)(struct exynos_tmu_data *data, u8 temp);
	void (*tmu_disable_low)(struct exynos_tmu_data *data);
	void (*tmu_disable_high)(struct exynos_tmu_data *data);
	void (*tmu_initialize)(struct platform_device *pdev);
	void (*tmu_control)(struct platform_device *pdev, bool on);
	int (*tmu_read)(struct exynos_tmu_data *data);
@@ -279,49 +281,28 @@ static int exynos_thermal_zone_configure(struct platform_device *pdev)
{
	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
	struct thermal_zone_device *tzd = data->tzd;
	int i, num_trips = thermal_zone_get_num_trips(tzd);
	int ret = 0, temp;
	int ret, temp;

	ret = thermal_zone_get_crit_temp(tzd, &temp);
	if (ret) {
		/* FIXME: Remove this special case */
		if (data->soc == SOC_ARCH_EXYNOS5433)
			return 0;

	if (ret && data->soc != SOC_ARCH_EXYNOS5433) { /* FIXME */
		dev_err(&pdev->dev,
			"No CRITICAL trip point defined in device tree!\n");
		goto out;
		return ret;
	}

	mutex_lock(&data->lock);

	if (num_trips > data->ntrip) {
		dev_info(&pdev->dev,
			 "More trip points than supported by this TMU.\n");
		dev_info(&pdev->dev,
			 "%d trip points should be configured in polling mode.\n",
			 num_trips - data->ntrip);
	}

	clk_enable(data->clk);

	num_trips = min_t(int, num_trips, data->ntrip);
	data->tmu_set_crit_temp(data, temp / MCELSIUS);

	/* Write temperature code for rising and falling threshold */
	for (i = 0; i < num_trips; i++) {
		struct thermal_trip trip;

		ret = thermal_zone_get_trip(tzd, i, &trip);
		if (ret)
			goto err;

		data->tmu_set_trip_temp(data, i, trip.temperature / MCELSIUS);
		data->tmu_set_trip_hyst(data, i, trip.temperature / MCELSIUS,
					trip.hysteresis / MCELSIUS);
	}

err:
	clk_disable(data->clk);
	mutex_unlock(&data->lock);
out:
	return ret;

	return 0;
}

static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
@@ -354,17 +335,74 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
	mutex_unlock(&data->lock);
}

static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data,
					 int trip_id, u8 temp)
static void exynos_tmu_update_bit(struct exynos_tmu_data *data, int reg_off,
				  int bit_off, bool enable)
{
	u32 interrupt_en;

	interrupt_en = readl(data->base + reg_off);
	if (enable)
		interrupt_en |= BIT(bit_off);
	else
		interrupt_en &= ~BIT(bit_off);
	writel(interrupt_en, data->base + reg_off);
}

static void exynos_tmu_update_temp(struct exynos_tmu_data *data, int reg_off,
				   int bit_off, u8 temp)
{
	u16 tmu_temp_mask;
	u32 th;

	tmu_temp_mask =
		(data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK
						: EXYNOS_TMU_TEMP_MASK;

	th = readl(data->base + reg_off);
	th &= ~(tmu_temp_mask << bit_off);
	th |= temp_to_code(data, temp) << bit_off;
	writel(th, data->base + reg_off);
}

static void exynos4210_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
{
	/*
	 * Failing thresholds are not supported on Exynos 4210.
	 * We use polling instead.
	 */
}

static void exynos4210_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
{
	temp = temp_to_code(data, temp);
	writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip_id * 4);
	writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + 4);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, true);
}

static void exynos4210_tmu_disable_low(struct exynos_tmu_data *data)
{
	/* Again, this is handled by polling. */
}

static void exynos4210_tmu_disable_high(struct exynos_tmu_data *data)
{
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, false);
}

/* failing thresholds are not supported on Exynos4210 */
static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data,
					 int trip, u8 temp, u8 hyst)
static void exynos4210_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
{
	/*
	 * Hardware critical temperature handling is not supported on Exynos 4210.
	 * We still set the critical temperature threshold, but this is only to
	 * make sure it is handled as soon as possible. It is just a normal interrupt.
	 */

	temp = temp_to_code(data, temp);
	writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + 12);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_RISE0_SHIFT + 12, true);
}

static void exynos4210_tmu_initialize(struct platform_device *pdev)
@@ -376,33 +414,31 @@ static void exynos4210_tmu_initialize(struct platform_device *pdev)
	writeb(0, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
}

static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data,
					 int trip, u8 temp)
static void exynos4412_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
{
	u32 th, con;

	th = readl(data->base + EXYNOS_THD_TEMP_RISE);
	th &= ~(0xff << 8 * trip);
	th |= temp_to_code(data, temp) << 8 * trip;
	writel(th, data->base + EXYNOS_THD_TEMP_RISE);

	if (trip == 3) {
		con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
		con |= BIT(EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
		writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
	exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_FALL, 0, temp);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT, true);
}

static void exynos4412_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
{
	exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_RISE, 8, temp);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_RISE0_SHIFT + 4, true);
}

static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data,
					 int trip, u8 temp, u8 hyst)
static void exynos4412_tmu_disable_low(struct exynos_tmu_data *data)
{
	u32 th;
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT, false);
}

	th = readl(data->base + EXYNOS_THD_TEMP_FALL);
	th &= ~(0xff << 8 * trip);
	if (hyst)
		th |= temp_to_code(data, temp - hyst) << 8 * trip;
	writel(th, data->base + EXYNOS_THD_TEMP_FALL);
static void exynos4412_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
{
	exynos_tmu_update_temp(data, EXYNOS_THD_TEMP_RISE, 24, temp);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_CONTROL,
			      EXYNOS_TMU_THERM_TRIP_EN_SHIFT, true);
}

static void exynos4412_tmu_initialize(struct platform_device *pdev)
@@ -432,44 +468,39 @@ static void exynos4412_tmu_initialize(struct platform_device *pdev)
	sanitize_temp_error(data, trim_info);
}

static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data,
					 int trip, u8 temp)
static void exynos5433_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
{
	unsigned int reg_off, j;
	u32 th;

	if (trip > 3) {
		reg_off = EXYNOS5433_THD_TEMP_RISE7_4;
		j = trip - 4;
	} else {
		reg_off = EXYNOS5433_THD_TEMP_RISE3_0;
		j = trip;
	exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_FALL3_0, 0, temp);
	exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT, true);
}

	th = readl(data->base + reg_off);
	th &= ~(0xff << j * 8);
	th |= (temp_to_code(data, temp) << j * 8);
	writel(th, data->base + reg_off);
static void exynos5433_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
{
	exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_RISE3_0, 8, temp);
	exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, true);
}

static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data,
					 int trip, u8 temp, u8 hyst)
static void exynos5433_tmu_disable_low(struct exynos_tmu_data *data)
{
	unsigned int reg_off, j;
	u32 th;
	exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT, false);
}

	if (trip > 3) {
		reg_off = EXYNOS5433_THD_TEMP_FALL7_4;
		j = trip - 4;
	} else {
		reg_off = EXYNOS5433_THD_TEMP_FALL3_0;
		j = trip;
static void exynos5433_tmu_disable_high(struct exynos_tmu_data *data)
{
	exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, false);
}

	th = readl(data->base + reg_off);
	th &= ~(0xff << j * 8);
	th |= (temp_to_code(data, temp - hyst) << j * 8);
	writel(th, data->base + reg_off);
static void exynos5433_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
{
	exynos_tmu_update_temp(data, EXYNOS5433_THD_TEMP_RISE7_4, 24, temp);
	exynos_tmu_update_bit(data, EXYNOS_TMU_REG_CONTROL,
			      EXYNOS_TMU_THERM_TRIP_EN_SHIFT, true);
	exynos_tmu_update_bit(data, EXYNOS5433_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 7, true);
}

static void exynos5433_tmu_initialize(struct platform_device *pdev)
@@ -505,34 +536,41 @@ static void exynos5433_tmu_initialize(struct platform_device *pdev)
			cal_type ?  2 : 1);
}

static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data,
				      int trip, u8 temp)
static void exynos7_tmu_set_low_temp(struct exynos_tmu_data *data, u8 temp)
{
	unsigned int reg_off, bit_off;
	u32 th;

	reg_off = ((7 - trip) / 2) * 4;
	bit_off = ((8 - trip) % 2);
	exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_FALL7_6 + 12, 0, temp);
	exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT + 0, true);
}

	th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
	th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
	th |= temp_to_code(data, temp) << (16 * bit_off);
	writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
static void exynos7_tmu_set_high_temp(struct exynos_tmu_data *data, u8 temp)
{
	exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_RISE7_6 + 12, 16, temp);
	exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, true);
}

static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data,
				      int trip, u8 temp, u8 hyst)
static void exynos7_tmu_disable_low(struct exynos_tmu_data *data)
{
	unsigned int reg_off, bit_off;
	u32 th;
	exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
			      EXYNOS_TMU_INTEN_FALL0_SHIFT + 0, false);
}

	reg_off = ((7 - trip) / 2) * 4;
	bit_off = ((8 - trip) % 2);
static void exynos7_tmu_disable_high(struct exynos_tmu_data *data)
{
	exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 1, false);
}

	th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
	th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
	th |= temp_to_code(data, temp - hyst) << (16 * bit_off);
	writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
static void exynos7_tmu_set_crit_temp(struct exynos_tmu_data *data, u8 temp)
{
	/*
	 * Like Exynos 4210, Exynos 7 does not seem to support critical temperature
	 * handling in hardware. Again, we still set a separate interrupt for it.
	 */
	exynos_tmu_update_temp(data, EXYNOS7_THD_TEMP_RISE7_6 + 0, 16, temp);
	exynos_tmu_update_bit(data, EXYNOS7_TMU_REG_INTEN,
			      EXYNOS7_TMU_INTEN_RISE0_SHIFT + 7, true);
}

static void exynos7_tmu_initialize(struct platform_device *pdev)
@@ -547,87 +585,44 @@ static void exynos7_tmu_initialize(struct platform_device *pdev)
static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
{
	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
	struct thermal_zone_device *tz = data->tzd;
	struct thermal_trip trip;
	unsigned int con, interrupt_en = 0, i;
	unsigned int con;

	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));

	if (on) {
		for (i = 0; i < data->ntrip; i++) {
			if (thermal_zone_get_trip(tz, i, &trip))
				continue;

			interrupt_en |=
				BIT(EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4);
		}

		if (data->soc != SOC_ARCH_EXYNOS4210)
			interrupt_en |=
				interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;

	if (on)
		con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
	} else {
	else
		con &= ~BIT(EXYNOS_TMU_CORE_EN_SHIFT);
	}

	writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}

static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
{
	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
	struct thermal_zone_device *tz = data->tzd;
	struct thermal_trip trip;
	unsigned int con, interrupt_en = 0, pd_det_en, i;
	unsigned int con, pd_det_en;

	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));

	if (on) {
		for (i = 0; i < data->ntrip; i++) {
			if (thermal_zone_get_trip(tz, i, &trip))
				continue;

			interrupt_en |=
				BIT(EXYNOS7_TMU_INTEN_RISE0_SHIFT + i);
		}

		interrupt_en |=
			interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;

	if (on)
		con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
	} else
	else
		con &= ~BIT(EXYNOS_TMU_CORE_EN_SHIFT);

	pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0;

	writel(pd_det_en, data->base + EXYNOS5433_TMU_PD_DET_EN);
	writel(interrupt_en, data->base + EXYNOS5433_TMU_REG_INTEN);
	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}

static void exynos7_tmu_control(struct platform_device *pdev, bool on)
{
	struct exynos_tmu_data *data = platform_get_drvdata(pdev);
	struct thermal_zone_device *tz = data->tzd;
	struct thermal_trip trip;
	unsigned int con, interrupt_en = 0, i;
	unsigned int con;

	con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));

	if (on) {
		for (i = 0; i < data->ntrip; i++) {
			if (thermal_zone_get_trip(tz, i, &trip))
				continue;

			interrupt_en |=
				BIT(EXYNOS7_TMU_INTEN_RISE0_SHIFT + i);
		}

		interrupt_en |=
			interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;

		con |= BIT(EXYNOS_TMU_CORE_EN_SHIFT);
		con |= BIT(EXYNOS7_PD_DET_EN_SHIFT);
	} else {
@@ -635,7 +630,6 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
		con &= ~BIT(EXYNOS7_PD_DET_EN_SHIFT);
	}

	writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
	writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}

@@ -873,13 +867,15 @@ static int exynos_map_dt_data(struct platform_device *pdev)

	switch (data->soc) {
	case SOC_ARCH_EXYNOS4210:
		data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp;
		data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst;
		data->tmu_set_low_temp = exynos4210_tmu_set_low_temp;
		data->tmu_set_high_temp = exynos4210_tmu_set_high_temp;
		data->tmu_disable_low = exynos4210_tmu_disable_low;
		data->tmu_disable_high = exynos4210_tmu_disable_high;
		data->tmu_set_crit_temp = exynos4210_tmu_set_crit_temp;
		data->tmu_initialize = exynos4210_tmu_initialize;
		data->tmu_control = exynos4210_tmu_control;
		data->tmu_read = exynos4210_tmu_read;
		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
		data->ntrip = 4;
		data->gain = 15;
		data->reference_voltage = 7;
		data->efuse_value = 55;
@@ -892,14 +888,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
	case SOC_ARCH_EXYNOS5260:
	case SOC_ARCH_EXYNOS5420:
	case SOC_ARCH_EXYNOS5420_TRIMINFO:
		data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp;
		data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst;
		data->tmu_set_low_temp = exynos4412_tmu_set_low_temp;
		data->tmu_set_high_temp = exynos4412_tmu_set_high_temp;
		data->tmu_disable_low = exynos4412_tmu_disable_low;
		data->tmu_disable_high = exynos4210_tmu_disable_high;
		data->tmu_set_crit_temp = exynos4412_tmu_set_crit_temp;
		data->tmu_initialize = exynos4412_tmu_initialize;
		data->tmu_control = exynos4210_tmu_control;
		data->tmu_read = exynos4412_tmu_read;
		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
		data->ntrip = 4;
		data->gain = 8;
		data->reference_voltage = 16;
		data->efuse_value = 55;
@@ -911,14 +909,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
		data->max_efuse_value = 100;
		break;
	case SOC_ARCH_EXYNOS5433:
		data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp;
		data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst;
		data->tmu_set_low_temp = exynos5433_tmu_set_low_temp;
		data->tmu_set_high_temp = exynos5433_tmu_set_high_temp;
		data->tmu_disable_low = exynos5433_tmu_disable_low;
		data->tmu_disable_high = exynos5433_tmu_disable_high;
		data->tmu_set_crit_temp = exynos5433_tmu_set_crit_temp;
		data->tmu_initialize = exynos5433_tmu_initialize;
		data->tmu_control = exynos5433_tmu_control;
		data->tmu_read = exynos4412_tmu_read;
		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
		data->ntrip = 8;
		data->gain = 8;
		if (res.start == EXYNOS5433_G3D_BASE)
			data->reference_voltage = 23;
@@ -929,14 +929,16 @@ static int exynos_map_dt_data(struct platform_device *pdev)
		data->max_efuse_value = 150;
		break;
	case SOC_ARCH_EXYNOS7:
		data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp;
		data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst;
		data->tmu_set_low_temp = exynos7_tmu_set_low_temp;
		data->tmu_set_high_temp = exynos7_tmu_set_high_temp;
		data->tmu_disable_low = exynos7_tmu_disable_low;
		data->tmu_disable_high = exynos7_tmu_disable_high;
		data->tmu_set_crit_temp = exynos7_tmu_set_crit_temp;
		data->tmu_initialize = exynos7_tmu_initialize;
		data->tmu_control = exynos7_tmu_control;
		data->tmu_read = exynos7_tmu_read;
		data->tmu_set_emulation = exynos4412_tmu_set_emulation;
		data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
		data->ntrip = 8;
		data->gain = 9;
		data->reference_voltage = 17;
		data->efuse_value = 75;
@@ -972,9 +974,32 @@ static int exynos_map_dt_data(struct platform_device *pdev)
	return 0;
}

static int exynos_set_trips(struct thermal_zone_device *tz, int low, int high)
{
	struct exynos_tmu_data *data = thermal_zone_device_priv(tz);

	mutex_lock(&data->lock);
	clk_enable(data->clk);

	if (low > INT_MIN)
		data->tmu_set_low_temp(data, low / MCELSIUS);
	else
		data->tmu_disable_low(data);
	if (high < INT_MAX)
		data->tmu_set_high_temp(data, high / MCELSIUS);
	else
		data->tmu_disable_high(data);

	clk_disable(data->clk);
	mutex_unlock(&data->lock);

	return 0;
}

static const struct thermal_zone_device_ops exynos_sensor_ops = {
	.get_temp = exynos_get_temp,
	.set_emul_temp = exynos_tmu_set_emulation,
	.set_trips = exynos_set_trips,
};

static int exynos_tmu_probe(struct platform_device *pdev)