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: Jonghwa Lee <jonghwa3.lee@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Jungseok Lee <jays.lee@samsung.com>
Signed-off-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Acked-by: Eduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
This commit is contained in:
Amit Daniel Kachhap 2013-06-24 16:20:43 +05:30 committed by Eduardo Valentin
parent d9b6ee148d
commit a0395eee7c
4 changed files with 90 additions and 9 deletions

View file

@ -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

View file

@ -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 */
trim_info = readl(data->base + reg->triminfo_data);
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;
}
rising_threshold |= threshold_code << 8 * i;
writel(rising_threshold,
data->base + reg->threshold_th0);
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;

View file

@ -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;
};
/**

View file

@ -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)