From: Abhilash Kesavan <a.kesavan@samsung.com>
To: rui.zhang@intel.com, edubezval@gmail.com, linux-pm@vger.kernel.org
Cc: b.zolnierkie@samsung.com, amit.daniel@samsung.com,
kesavan.abhilash@gmail.com
Subject: [PATCH 4/4] thermal: exynos: Add TMU support for Exynos7 SoC
Date: Fri, 14 Nov 2014 16:48:02 +0530 [thread overview]
Message-ID: <1415963882-3460-5-git-send-email-a.kesavan@samsung.com> (raw)
In-Reply-To: <1415963882-3460-1-git-send-email-a.kesavan@samsung.com>
Add registers, bit fields and compatible strings for Exynos7 TMU
(Thermal Management Unit). Following are a few of the differences
in the Exynos7 TMU from earlier SoCs:
- 8 trigger levels
- Different bit offsets and more registers for the rising
and falling thresholds.
- New power down detection bit in the TMU_CONTROL register
which does not update the CURRENT_TEMP0 when tmu power down
is detected.
- Change in bit offset for the NEXT_DATA field of EMUL_CON
register. EMUL_CON register address has also changed.
- INTSTAT and INTCLEAR registers present in earlier SoCs
have been combined into one INTPEND register. The register
address for INTCLEAR and INTPEND is also different.
- Since there are 8 rising/falling interrupts as against
at most 4 in earlier SoCs the INTEN bit offsets are different.
- Multiple probe support which is handled by a TMU_CONTROL1
register (No support for this in the current patch).
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
.../devicetree/bindings/thermal/exynos-thermal.txt | 1 +
drivers/thermal/samsung/exynos_tmu.c | 60 ++++++++++-
drivers/thermal/samsung/exynos_tmu.h | 11 +-
drivers/thermal/samsung/exynos_tmu_data.c | 111 ++++++++++++++++++++
drivers/thermal/samsung/exynos_tmu_data.h | 27 +++++
5 files changed, 204 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index 2393eac..7c1c6f1 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -12,6 +12,7 @@
"samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
Exynos5420 (Must pass triminfo base and triminfo clock)
"samsung,exynos5440-tmu"
+ "samsung,exynos7-tmu"
- interrupt-parent : The phandle for the interrupt controller
- reg : Address range of the thermal registers. For soc's which has multiple
instances of TMU and some registers are shared across all TMU's like
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 9695638..1f658d2 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -147,6 +147,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
const struct exynos_tmu_registers *reg = pdata->registers;
unsigned int status, trim_info = 0, con, ctrl;
unsigned int rising_threshold = 0, falling_threshold = 0;
+ unsigned int reg_off, bit_off;
int ret = 0, threshold_code, i;
mutex_lock(&data->lock);
@@ -214,9 +215,10 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
(pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
reg->triminfo_mask;
- rising_threshold = readl(data->base + reg->threshold_th0);
if (data->soc == SOC_ARCH_EXYNOS4210) {
+ rising_threshold = readl(data->base + reg->threshold_th0);
+
/* Write temperature code for threshold */
threshold_code = temp_to_code(data, pdata->threshold);
writeb(threshold_code,
@@ -226,7 +228,37 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
reg->threshold_th0 + i * sizeof(reg->threshold_th0));
exynos_tmu_clear_irqs(data);
+ } else if (data->soc == SOC_ARCH_EXYNOS7) {
+ /* Write temperature code for rising and falling thresholds */
+ for (i = pdata->non_hw_trigger_levels; i >= 0; i--) {
+ reg_off = ((pdata->non_hw_trigger_levels - i) / 2) * 4;
+ bit_off = ((pdata->non_hw_trigger_levels - i) % 2);
+
+ threshold_code = temp_to_code(data,
+ pdata->trigger_levels[i]);
+ rising_threshold = readl(data->base +
+ reg->threshold_th0 + reg_off);
+ rising_threshold &= ~(0x1ff << (16 * bit_off));
+ rising_threshold |= threshold_code << (16 * bit_off);
+ writel(rising_threshold,
+ data->base + reg->threshold_th0 + reg_off);
+
+ threshold_code = temp_to_code(data,
+ pdata->trigger_levels[i] -
+ pdata->threshold_falling);
+ falling_threshold |= threshold_code << (16 * bit_off);
+ writel(falling_threshold,
+ data->base + reg->threshold_th1 + reg_off);
+ }
+
+ exynos_tmu_clear_irqs(data);
+
+ con = readl(data->base + reg->tmu_ctrl);
+ con |= (1 << reg->therm_trip_en_shift);
+ writel(con, data->base + reg->tmu_ctrl);
} else {
+ rising_threshold = readl(data->base + reg->threshold_th0);
+
/* Write temperature code for rising and falling threshold */
for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
threshold_code = temp_to_code(data,
@@ -311,9 +343,16 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
}
+ if (data->soc == SOC_ARCH_EXYNOS7)
+ con |= 1 << EXYNOS7_PD_DET_EN_SHIFT;
+
if (on) {
con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
interrupt_en =
+ pdata->trigger_enable[7] << reg->inten_rise7_shift |
+ pdata->trigger_enable[6] << reg->inten_rise6_shift |
+ pdata->trigger_enable[5] << reg->inten_rise5_shift |
+ pdata->trigger_enable[4] << reg->inten_rise4_shift |
pdata->trigger_enable[3] << reg->inten_rise3_shift |
pdata->trigger_enable[2] << reg->inten_rise2_shift |
pdata->trigger_enable[1] << reg->inten_rise1_shift |
@@ -387,7 +426,11 @@ static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
}
- val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
+ if (data->soc == SOC_ARCH_EXYNOS7)
+ val &= ~(EXYNOS7_EMUL_DATA_MASK <<
+ reg->emul_temp_shift);
+ else
+ val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
EXYNOS_EMUL_ENABLE;
} else {
@@ -482,6 +525,10 @@ static const struct of_device_id exynos_tmu_match[] = {
.compatible = "samsung,exynos5440-tmu",
.data = (void *)EXYNOS5440_TMU_DRV_DATA,
},
+ {
+ .compatible = "samsung,exynos7-tmu",
+ .data = (void *)EXYNOS7_TMU_DRV_DATA,
+ },
{},
};
MODULE_DEVICE_TABLE(of, exynos_tmu_match);
@@ -644,7 +691,8 @@ static int exynos_tmu_probe(struct platform_device *pdev)
pdata->type == SOC_ARCH_EXYNOS5250 ||
pdata->type == SOC_ARCH_EXYNOS5260 ||
pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
- pdata->type == SOC_ARCH_EXYNOS5440)
+ pdata->type == SOC_ARCH_EXYNOS5440 ||
+ pdata->type == SOC_ARCH_EXYNOS7)
data->soc = pdata->type;
else {
ret = -EINVAL;
@@ -673,8 +721,10 @@ static int exynos_tmu_probe(struct platform_device *pdev)
(int (*)(void *, unsigned long))exynos_tmu_set_emulation;
sensor_conf->driver_data = data;
sensor_conf->trip_data.trip_count = pdata->trigger_enable[0] +
- pdata->trigger_enable[1] + pdata->trigger_enable[2]+
- pdata->trigger_enable[3];
+ pdata->trigger_enable[1] + pdata->trigger_enable[2] +
+ pdata->trigger_enable[3] + pdata->trigger_enable[4] +
+ pdata->trigger_enable[5] + pdata->trigger_enable[6] +
+ pdata->trigger_enable[7];
for (i = 0; i < sensor_conf->trip_data.trip_count; i++) {
sensor_conf->trip_data.trip_val[i] =
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index 70e0d961..a7e8758 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -42,6 +42,7 @@ enum soc_type {
SOC_ARCH_EXYNOS5260,
SOC_ARCH_EXYNOS5420_TRIMINFO,
SOC_ARCH_EXYNOS5440,
+ SOC_ARCH_EXYNOS7,
};
/**
@@ -98,6 +99,10 @@ enum soc_type {
* @inten_rise1_shift: shift bits of rising 1 interrupt bits.
* @inten_rise2_shift: shift bits of rising 2 interrupt bits.
* @inten_rise3_shift: shift bits of rising 3 interrupt bits.
+ * @inten_rise4_shift: shift bits of rising 4 interrupt bits.
+ * @inten_rise5_shift: shift bits of rising 5 interrupt bits.
+ * @inten_rise6_shift: shift bits of rising 6 interrupt bits.
+ * @inten_rise7_shift: shift bits of rising 7 interrupt bits.
* @inten_fall0_shift: shift bits of falling 0 interrupt bits.
* @tmu_intstat: Register containing the interrupt status values.
* @tmu_intclear: Register for clearing the raised interrupt status.
@@ -136,6 +141,10 @@ struct exynos_tmu_registers {
u32 inten_rise1_shift;
u32 inten_rise2_shift;
u32 inten_rise3_shift;
+ u32 inten_rise4_shift;
+ u32 inten_rise5_shift;
+ u32 inten_rise6_shift;
+ u32 inten_rise7_shift;
u32 inten_fall0_shift;
u32 tmu_intstat;
@@ -230,7 +239,7 @@ struct exynos_tmu_platform_data {
enum calibration_type cal_type;
enum soc_type type;
- struct freq_clip_table freq_tab[4];
+ struct freq_clip_table freq_tab[8];
unsigned int freq_tab_count;
const struct exynos_tmu_registers *registers;
unsigned int features;
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index c4f12d0..523bf4d 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -491,3 +491,114 @@ struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
.tmu_count = 3,
};
#endif
+
+#if defined(CONFIG_ARCH_EXYNOS7)
+static const struct exynos_tmu_registers exynos7_tmu_registers = {
+ .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
+ .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
+ .triminfo_mask = EXYNOS_TMU_TEMP_MASK,
+ .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
+ .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
+ .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
+ .tmu_status = EXYNOS_TMU_REG_STATUS,
+ .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
+ .threshold_th0 = EXYNOS7_THD_TEMP_RISE7_6,
+ .threshold_th1 = EXYNOS7_THD_TEMP_FALL7_6,
+ .tmu_inten = EXYNOS7_TMU_REG_INTEN,
+ .inten_rise0_shift = EXYNOS7_TMU_INTEN_RISE0_SHIFT,
+ .inten_rise1_shift = EXYNOS7_TMU_INTEN_RISE1_SHIFT,
+ .inten_rise2_shift = EXYNOS7_TMU_INTEN_RISE2_SHIFT,
+ .inten_rise3_shift = EXYNOS7_TMU_INTEN_RISE3_SHIFT,
+ .inten_rise4_shift = EXYNOS7_TMU_INTEN_RISE4_SHIFT,
+ .inten_rise5_shift = EXYNOS7_TMU_INTEN_RISE5_SHIFT,
+ .inten_rise6_shift = EXYNOS7_TMU_INTEN_RISE6_SHIFT,
+ .inten_rise7_shift = EXYNOS7_TMU_INTEN_RISE7_SHIFT,
+ .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
+ .tmu_intstat = EXYNOS7_TMU_REG_INTPEND,
+ .tmu_intclear = EXYNOS7_TMU_REG_INTPEND,
+ .emul_con = EXYNOS7_TMU_REG_EMUL_CON,
+ .emul_temp_shift = EXYNOS7_EMUL_DATA_SHIFT,
+ .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
+};
+
+#define __EXYNOS7_TMU_DATA \
+ .threshold_falling = 10, \
+ .trigger_levels[0] = 65, \
+ .trigger_levels[1] = 72, \
+ .trigger_levels[2] = 80, \
+ .trigger_levels[3] = 88, \
+ .trigger_levels[4] = 95, \
+ .trigger_levels[5] = 103, \
+ .trigger_levels[6] = 110, \
+ .trigger_levels[7] = 115, \
+ .trigger_enable[0] = true, \
+ .trigger_enable[1] = true, \
+ .trigger_enable[2] = true, \
+ .trigger_enable[3] = true, \
+ .trigger_enable[4] = true, \
+ .trigger_enable[5] = true, \
+ .trigger_enable[6] = true, \
+ .trigger_enable[7] = false, \
+ .trigger_type[0] = THROTTLE_ACTIVE, \
+ .trigger_type[1] = THROTTLE_ACTIVE, \
+ .trigger_type[2] = THROTTLE_ACTIVE, \
+ .trigger_type[3] = THROTTLE_ACTIVE, \
+ .trigger_type[4] = THROTTLE_ACTIVE, \
+ .trigger_type[5] = THROTTLE_ACTIVE, \
+ .trigger_type[6] = SW_TRIP, \
+ .trigger_type[7] = HW_TRIP, \
+ .max_trigger_level = 8, \
+ .non_hw_trigger_levels = 7, \
+ .gain = 8, \
+ .reference_voltage = 16, \
+ .noise_cancel_mode = 4, \
+ .cal_type = TYPE_ONE_POINT_TRIMMING, \
+ .efuse_value = 55, \
+ .min_efuse_value = 15, \
+ .max_efuse_value = 100, \
+ .first_point_trim = 25, \
+ .second_point_trim = 85, \
+ .default_temp_offset = 50, \
+ .freq_tab[0] = { \
+ .freq_clip_max = 1400 * 1000, \
+ .temp_level = 70, \
+ }, \
+ .freq_tab[1] = { \
+ .freq_clip_max = 1200 * 1000, \
+ .temp_level = 80, \
+ }, \
+ .freq_tab[2] = { \
+ .freq_clip_max = 1000 * 1000, \
+ .temp_level = 85, \
+ }, \
+ .freq_tab[3] = { \
+ .freq_clip_max = 800 * 1000, \
+ .temp_level = 90, \
+ }, \
+ .freq_tab[4] = { \
+ .freq_clip_max = 600 * 1000, \
+ .temp_level = 95, \
+ }, \
+ .freq_tab[5] = { \
+ .freq_clip_max = 200 * 1000, \
+ .temp_level = 100, \
+ }, \
+ .freq_tab_count = 6, \
+ .registers = &exynos7_tmu_registers, \
+
+#define EXYNOS7_TMU_DATA \
+ __EXYNOS7_TMU_DATA \
+ .type = SOC_ARCH_EXYNOS7, \
+ .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
+ TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
+
+struct exynos_tmu_init_data const exynos7_default_tmu_data = {
+ .tmu_data = {
+ { EXYNOS7_TMU_DATA },
+ { EXYNOS7_TMU_DATA },
+ { EXYNOS7_TMU_DATA },
+ { EXYNOS7_TMU_DATA },
+ },
+ .tmu_count = 4,
+};
+#endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
index 63de598..5dc9b2f 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.h
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -107,6 +107,26 @@
#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
+/* Exynos7 specific registers */
+#define EXYNOS7_THD_TEMP_RISE7_6 0x50
+#define EXYNOS7_THD_TEMP_FALL7_6 0x60
+#define EXYNOS7_TMU_REG_INTEN 0x110
+#define EXYNOS7_TMU_REG_INTPEND 0x118
+#define EXYNOS7_TMU_REG_EMUL_CON 0x160
+
+#define EXYNOS7_TMU_TEMP_MASK 0x1FF
+#define EXYNOS7_PD_DET_EN_SHIFT 23
+#define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0
+#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1
+#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2
+#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3
+#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4
+#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5
+#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6
+#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7
+#define EXYNOS7_EMUL_DATA_SHIFT 7
+#define EXYNOS7_EMUL_DATA_MASK 0x1FF
+
#if defined(CONFIG_SOC_EXYNOS3250)
extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
#define EXYNOS3250_TMU_DRV_DATA (&exynos3250_default_tmu_data)
@@ -156,4 +176,11 @@ extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
#define EXYNOS5440_TMU_DRV_DATA (NULL)
#endif
+#if defined(CONFIG_ARCH_EXYNOS7)
+extern struct exynos_tmu_init_data const exynos7_default_tmu_data;
+#define EXYNOS7_TMU_DRV_DATA (&exynos7_default_tmu_data)
+#else
+#define EXYNOS7_TMU_DRV_DATA (NULL)
+#endif
+
#endif /*_EXYNOS_TMU_DATA_H*/
--
1.7.9.5
next prev parent reply other threads:[~2014-11-14 11:20 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-14 11:17 [PATCH 0/4] Add TMU support for Exynos7 Abhilash Kesavan
2014-11-14 11:17 ` [PATCH 1/4] thermal: exynos: add optional sclk support Abhilash Kesavan
2014-11-14 11:18 ` [PATCH 2/4] thermal: exynos: add a triminfo_mask field in exynos_tmu_register structure Abhilash Kesavan
2014-11-14 11:18 ` [PATCH 3/4] thermal: exynos: modify the prototype for code_to_temp function Abhilash Kesavan
2014-11-14 11:18 ` Abhilash Kesavan [this message]
2014-11-14 12:19 ` [PATCH 0/4] Add TMU support for Exynos7 Bartlomiej Zolnierkiewicz
2014-11-14 12:30 ` Abhilash Kesavan
2014-11-14 13:02 ` Lukasz Majewski
2014-11-14 14:07 ` Abhilash Kesavan
2014-11-14 14:50 ` Lukasz Majewski
2014-11-18 8:08 ` Lukasz Majewski
2014-11-18 8:14 ` Abhilash Kesavan
2014-11-19 13:18 ` Eduardo Valentin
2014-11-20 13:05 ` Abhilash Kesavan
2014-11-20 13:22 ` Lukasz Majewski
2014-11-20 14:49 ` Abhilash Kesavan
2014-11-22 7:45 ` Abhilash Kesavan
2014-11-24 9:24 ` Lukasz Majewski
2014-11-24 10:50 ` Abhilash Kesavan
2014-11-24 11:04 ` Lukasz Majewski
2014-11-24 11:09 ` Abhilash Kesavan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1415963882-3460-5-git-send-email-a.kesavan@samsung.com \
--to=a.kesavan@samsung.com \
--cc=amit.daniel@samsung.com \
--cc=b.zolnierkie@samsung.com \
--cc=edubezval@gmail.com \
--cc=kesavan.abhilash@gmail.com \
--cc=linux-pm@vger.kernel.org \
--cc=rui.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.