Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0395eee authored by Amit Daniel Kachhap's avatar Amit Daniel Kachhap Committed by Eduardo Valentin
Browse files

thermal: exynos: Add driver support for exynos5440 TMU sensor



This patch modifies TMU controller to add changes needed to work with
exynos5440 platform. This sensor registers 3 instance of the tmu controller
with the thermal zone and hence reports 3 temperature output. This controller
supports upto five trip points. For critical threshold the driver uses the
core driver thermal framework for shutdown.

Acked-by: default avatarJonghwa Lee <jonghwa3.lee@samsung.com>
Acked-by: default avatarKukjin Kim <kgene.kim@samsung.com>
Signed-off-by: default avatarJungseok Lee <jays.lee@samsung.com>
Signed-off-by: default avatarAmit Daniel Kachhap <amit.daniel@samsung.com>
Acked-by: default avatarEduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: default avatarEduardo Valentin <eduardo.valentin@ti.com>
parent d9b6ee14
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
#define SENSOR_NAME_LEN	16
#define MAX_TRIP_COUNT	8
#define MAX_COOLING_DEVICE 4
#define MAX_THRESHOLD_LEVS 4
#define MAX_THRESHOLD_LEVS 5

#define ACTIVE_INTERVAL 500
#define IDLE_INTERVAL 10000
+47 −8
Original line number Diff line number Diff line
@@ -156,7 +156,26 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
		__raw_writel(1, data->base + reg->triminfo_ctrl);

	/* Save trimming info in order to perform calibration */
	if (data->soc == SOC_ARCH_EXYNOS5440) {
		/*
		 * For exynos5440 soc triminfo value is swapped between TMU0 and
		 * TMU2, so the below logic is needed.
		 */
		switch (data->id) {
		case 0:
			trim_info = readl(data->base +
			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
			break;
		case 1:
			trim_info = readl(data->base + reg->triminfo_data);
			break;
		case 2:
			trim_info = readl(data->base -
			EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
		}
	} else {
		trim_info = readl(data->base + reg->triminfo_data);
	}
	data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
	data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
				EXYNOS_TMU_TEMP_MASK);
@@ -201,7 +220,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
			reg->threshold_th0 + i * sizeof(reg->threshold_th0));

		writel(reg->inten_rise_mask, data->base + reg->tmu_intclear);
	} else if (data->soc == SOC_ARCH_EXYNOS) {
	} else {
		/* Write temperature code for rising and falling threshold */
		for (i = 0;
		i < trigger_levs && i < EXYNOS_MAX_TRIGGER_PER_REG; i++) {
@@ -241,14 +260,26 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
				ret = threshold_code;
				goto out;
			}
			if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
				/* 1-4 level to be assigned in th0 reg */
				rising_threshold |= threshold_code << 8 * i;
				writel(rising_threshold,
					data->base + reg->threshold_th0);
			} else if (i == EXYNOS_MAX_TRIGGER_PER_REG) {
				/* 5th level to be assigned in th2 reg */
				rising_threshold =
				threshold_code << reg->threshold_th3_l0_shift;
				writel(rising_threshold,
					data->base + reg->threshold_th2);
			}
			con = readl(data->base + reg->tmu_ctrl);
			con |= (1 << reg->therm_trip_en_shift);
			writel(con, data->base + reg->tmu_ctrl);
		}
	}
	/*Clear the PMIN in the common TMU register*/
	if (reg->tmu_pmin && !data->id)
		writel(0, data->base_common + reg->tmu_pmin);
out:
	clk_disable(data->clk);
	mutex_unlock(&data->lock);
@@ -377,7 +408,14 @@ static void exynos_tmu_work(struct work_struct *work)
			struct exynos_tmu_data, irq_work);
	struct exynos_tmu_platform_data *pdata = data->pdata;
	const struct exynos_tmu_registers *reg = pdata->registers;
	unsigned int val_irq;
	unsigned int val_irq, val_type;

	/* Find which sensor generated this interrupt */
	if (reg->tmu_irqstatus) {
		val_type = readl(data->base_common + reg->tmu_irqstatus);
		if (!((val_type >> data->id) & 0x1))
			goto out;
	}

	exynos_report_trigger(data->reg_conf);
	mutex_lock(&data->lock);
@@ -390,7 +428,7 @@ static void exynos_tmu_work(struct work_struct *work)

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

out:
	enable_irq(data->irq);
}

@@ -538,7 +576,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
		return ret;

	if (pdata->type == SOC_ARCH_EXYNOS ||
				pdata->type == SOC_ARCH_EXYNOS4210)
		pdata->type == SOC_ARCH_EXYNOS4210 ||
				pdata->type == SOC_ARCH_EXYNOS5440)
		data->soc = pdata->type;
	else {
		ret = -EINVAL;
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ enum calibration_mode {
enum soc_type {
	SOC_ARCH_EXYNOS4210 = 1,
	SOC_ARCH_EXYNOS,
	SOC_ARCH_EXYNOS5440,
};

/**
@@ -131,6 +132,8 @@ enum soc_type {
 * @emul_temp_shift: shift bits of emulation temperature.
 * @emul_time_shift: shift bits of emulation time.
 * @emul_time_mask: mask bits of emulation time.
 * @tmu_irqstatus: register to find which TMU generated interrupts.
 * @tmu_pmin: register to get/set the Pmin value.
 */
struct exynos_tmu_registers {
	u32	triminfo_data;
@@ -198,6 +201,9 @@ struct exynos_tmu_registers {
	u32	emul_temp_shift;
	u32	emul_time_shift;
	u32	emul_time_mask;

	u32	tmu_irqstatus;
	u32	tmu_pmin;
};

/**
+36 −0
Original line number Diff line number Diff line
@@ -93,6 +93,42 @@

#define EXYNOS_MAX_TRIGGER_PER_REG	4

/*exynos5440 specific registers*/
#define EXYNOS5440_TMU_S0_7_TRIM		0x000
#define EXYNOS5440_TMU_S0_7_CTRL		0x020
#define EXYNOS5440_TMU_S0_7_DEBUG		0x040
#define EXYNOS5440_TMU_S0_7_STATUS		0x060
#define EXYNOS5440_TMU_S0_7_TEMP		0x0f0
#define EXYNOS5440_TMU_S0_7_TH0			0x110
#define EXYNOS5440_TMU_S0_7_TH1			0x130
#define EXYNOS5440_TMU_S0_7_TH2			0x150
#define EXYNOS5440_TMU_S0_7_EVTEN		0x1F0
#define EXYNOS5440_TMU_S0_7_IRQEN		0x210
#define EXYNOS5440_TMU_S0_7_IRQ			0x230
/* exynos5440 common registers */
#define EXYNOS5440_TMU_IRQ_STATUS		0x000
#define EXYNOS5440_TMU_PMIN			0x004
#define EXYNOS5440_TMU_TEMP			0x008

#define EXYNOS5440_TMU_RISE_INT_MASK		0xf
#define EXYNOS5440_TMU_RISE_INT_SHIFT		0
#define EXYNOS5440_TMU_FALL_INT_MASK		0xf
#define EXYNOS5440_TMU_FALL_INT_SHIFT		4
#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT	0
#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT	1
#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT	2
#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT	3
#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT	4
#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT	5
#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT	6
#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT	7
#define EXYNOS5440_TMU_TH_RISE0_SHIFT		0
#define EXYNOS5440_TMU_TH_RISE1_SHIFT		8
#define EXYNOS5440_TMU_TH_RISE2_SHIFT		16
#define EXYNOS5440_TMU_TH_RISE3_SHIFT		24
#define EXYNOS5440_TMU_TH_RISE4_SHIFT		24
#define EXYNOS5440_EFUSE_SWAP_OFFSET		8

#if defined(CONFIG_CPU_EXYNOS4210)
extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)