From patchwork Thu Nov 8 09:14:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hatim RV X-Patchwork-Id: 197810 X-Patchwork-Delegate: promsoft@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 78EB32C007C for ; Thu, 8 Nov 2012 20:22:17 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B4A774A555; Thu, 8 Nov 2012 10:22:15 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pec317443KgU; Thu, 8 Nov 2012 10:22:15 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0C2974A55A; Thu, 8 Nov 2012 10:22:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0A80F4A55A for ; Thu, 8 Nov 2012 10:22:10 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QRRqUf91N34M for ; Thu, 8 Nov 2012 10:22:08 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by theia.denx.de (Postfix) with ESMTP id 344E84A555 for ; Thu, 8 Nov 2012 10:22:05 +0100 (CET) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MD50012AWNYEE10@mailout1.samsung.com> for u-boot@lists.denx.de; Thu, 08 Nov 2012 18:21:39 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.122]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id B6.13.12699.3A97B905; Thu, 08 Nov 2012 18:21:39 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-53-509b79a35bde Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 85.13.12699.3A97B905; Thu, 08 Nov 2012 18:21:39 +0900 (KST) Received: from hatim-linux.sisodomain.com ([107.108.73.95]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MD5000KUWJF2180@mmp1.samsung.com> for u-boot@lists.denx.de; Thu, 08 Nov 2012 18:21:39 +0900 (KST) From: Hatim Ali To: u-boot@lists.denx.de Date: Thu, 08 Nov 2012 14:44:54 +0530 Message-id: <1352366100-18727-3-git-send-email-hatim.rv@samsung.com> X-Mailer: git-send-email 1.7.2.3 In-reply-to: <1352366100-18727-1-git-send-email-hatim.rv@samsung.com> References: <1352366100-18727-1-git-send-email-hatim.rv@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrDLMWRmVeSWpSXmKPExsWyRsSkSndx5ewAg9adqhZv93ayOzB6nL2z gzGAMYrLJiU1J7MstUjfLoEr4+/9s6wFl7MrNj5dxdbA+Cysi5GTQ0LARKJt5jwmCFtM4sK9 9WxdjFwcQgJLGSVOH9rJBlP07VEzI0RiEaPE67Yt7BDOEiaJiSdfsYNUsQmoSax/3QnWISIg IfGr/yojiM0sUCpxpHUbC4gtLOAjsebvGrB6FgFViR0d68HivAIuEoenXGGE2KYg8erGWqAa Dg5OAVeJpvt2IGEhoJLuFTsZIVoFJL5NPsQCUiIhICux6QAzyDkSApfZJOb9uMQCMUZS4uCK GywTGIUXMDKsYhRNLUguKE5KzzXSK07MLS7NS9dLzs/dxAgMwtP/nknvYFzVYHGIUYCDUYmH V0NydoAQa2JZcWXuIUYJDmYlEd5lzkAh3pTEyqrUovz4otKc1OJDjD5Al0xklhJNzgdGSF5J vKGxibmpsamlkZGZqSkOYSVx3maPlAAhgfTEktTs1NSC1CKYcUwcnFINjLVdDQpxi9wenpcs 2zTNKf2R5IXrfaH/X3e8FG9ydhVil653/J37qb7WLsHg5Gbr6XtmiNxyZnkp6WKwintPU/m5 MKVnS9/GynyNT3meLVC/duZs5hZfxsUNUZ5f/SZXFt71mb/uZ1ROkkEIj45U1NOW0K3ybZ6H dDaz/j2Zf/uTlsBudp+NSizFGYmGWsxFxYkA4mdCD28CAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupmkeLIzCtJLcpLzFFi42I5/e+xgO7iytkBBgfWcFu83dvJ7sDocfbO DsYAxqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wc oLFKCmWJOaVAoYDE4mIlfTtME0JD3HQtYBojdH1DguB6jAzQQMIaxoy/98+yFlzOrtj4dBVb A+OzsC5GTg4JAROJb4+aGSFsMYkL99azdTFycQgJLGKUeN22hR3CWcIkMfHkK3aQKjYBNYn1 rzvZQGwRAQmJX/1XwbqZBUoljrRuYwGxhQV8JNb8XQNWzyKgKrGjYz1YnFfAReLwlCtQ2xQk Xt1YC1TDwcEp4CrRdN8OJCwEVNK9YifjBEbeBYwMqxhFUwuSC4qT0nON9IoTc4tL89L1kvNz NzGCQ/yZ9A7GVQ0WhxgFOBiVeHg1JGcHCLEmlhVX5h5ilOBgVhLhXeYMFOJNSaysSi3Kjy8q zUktPsToA3TURGYp0eR8YPzllcQbGpuYmxqbWppYmJhZ4hBWEudt9kgJEBJITyxJzU5NLUgt ghnHxMEp1cDYK1k+N6IrUSb74tOnHF+u5FsbC96b6yV/LY2N6Wxd2feOJ9//b3Zaf2DiA9Gn ZxqLLxmkH5v85udj6eLauDyToiW8mzXFfK1i+X4KHWypLUuTuZ+x3ubUwbMnHZZUqLIa/b+Q dtbV5qLcD9Orq6T0d5798XvOKstO3Tnbm0q7vnq9jJ9nsr5MiaU4I9FQi7moOBEAJ2McAp4C AAA= X-CFilter-Loop: Reflected Cc: akshay.s@samsung.com, alim.akhtar@samsung.com Subject: [U-Boot] [PATCH 2/8 v3] EXYNOS5: TMU: Add driver for Thermal Management Unit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Akshay Saraswat Adding Exynos Thermal Management Unit driver to monitor SOC temperature and take actions corresponding to states of TMU. System will shutdown if tripping temperature is reached. Signed-off-by: Akshay Saraswat Acked-by: Simon Glass --- Changes since v2: - Replaced THERMAL with TMU in guards of tmu.h and exynos-tmu.h arch/arm/include/asm/arch-exynos/exynos-tmu.h | 58 +++++ drivers/power/Makefile | 1 + drivers/power/exynos-tmu.c | 297 +++++++++++++++++++++++++ include/tmu.h | 46 ++++ 4 files changed, 402 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-exynos/exynos-tmu.h create mode 100644 drivers/power/exynos-tmu.c create mode 100644 include/tmu.h diff --git a/arch/arm/include/asm/arch-exynos/exynos-tmu.h b/arch/arm/include/asm/arch-exynos/exynos-tmu.h new file mode 100644 index 0000000..c79a520 --- /dev/null +++ b/arch/arm/include/asm/arch-exynos/exynos-tmu.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Akshay Saraswat + * + * EXYNOS - Thermal Management Unit + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_TMU_H +#define __ASM_ARCH_TMU_H + +struct tmu_reg { + unsigned triminfo; + unsigned rsvd1; + unsigned rsvd2; + unsigned rsvd3; + unsigned rsvd4; + unsigned triminfo_control; + unsigned rsvd5; + unsigned rsvd6; + unsigned tmu_control; + unsigned rsvd7; + unsigned tmu_status; + unsigned sampling_internal; + unsigned counter_value0; + unsigned counter_value1; + unsigned rsvd8; + unsigned rsvd9; + unsigned current_temp; + unsigned rsvd10; + unsigned rsvd11; + unsigned rsvd12; + unsigned threshold_temp_rise; + unsigned threshold_temp_fall; + unsigned rsvd13; + unsigned rsvd14; + unsigned past_temp3_0; + unsigned past_temp7_4; + unsigned past_temp11_8; + unsigned past_temp15_12; + unsigned inten; + unsigned intstat; + unsigned intclear; + unsigned rsvd15; + unsigned emul_con; +}; +#endif /* __ASM_ARCH_THERMAL_H */ diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 6bf388c..192a7cb 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -30,6 +30,7 @@ COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o COBJS-$(CONFIG_TWL6030_POWER) += twl6030.o COBJS-$(CONFIG_TWL6035_POWER) += twl6035.o +COBJS-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c new file mode 100644 index 0000000..ce71408 --- /dev/null +++ b/drivers/power/exynos-tmu.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Akshay Saraswat + * + * EXYNOS - Thermal Management Unit + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define TRIMINFO_RELOAD 1 +#define CORE_EN 1 + +#define INTEN_RISE0 1 +#define INTEN_RISE1 (1 << 4) +#define INTEN_RISE2 (1 << 8) +#define INTEN_FALL0 (1 << 16) +#define INTEN_FALL1 (1 << 20) +#define INTEN_FALL2 (1 << 24) + +#define TRIM_INFO_MASK 0xff + +#define INTCLEAR_RISE0 1 +#define INTCLEAR_RISE1 (1 << 4) +#define INTCLEAR_RISE2 (1 << 8) +#define INTCLEAR_FALL0 (1 << 16) +#define INTCLEAR_FALL1 (1 << 20) +#define INTCLEAR_FALL2 (1 << 24) +#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \ + INTCLEAR_RISE2 | INTCLEAR_FALL0 | \ + INTCLEAR_FALL1 | INTCLEAR_FALL2) + +/* Tmeperature threshold values for various thermal events */ +struct temperature_params { + /* minimum value in temperature code range */ + unsigned int min_val; + /* maximum value in temperature code range */ + unsigned int max_val; + /* temperature threshold to start warning */ + unsigned int start_warning; + /* temperature threshold CPU tripping */ + unsigned int start_tripping; +}; + +/* Pre-defined values and thresholds for calibration of current temperature */ +struct tmu_data { + /* pre-defined temperature thresholds */ + struct temperature_params ts; + /* pre-defined efuse range minimum value */ + unsigned int efuse_min_value; + /* pre-defined efuse value for temperature calibration */ + unsigned int efuse_value; + /* pre-defined efuse range maximum value */ + unsigned int efuse_max_value; + /* current temperature sensing slope */ + unsigned int slope; +}; + +/* TMU device specific details and status */ +struct tmu_info { + /* base Address for the TMU */ + unsigned tmu_base; + /* mux Address for the TMU */ + int tmu_mux; + /* pre-defined values for calibration and thresholds */ + struct tmu_data data; + /* value required for triminfo_25 calibration */ + unsigned int te1; + /* value required for triminfo_85 calibration */ + unsigned int te2; + /* TMU DC value for threshold calculation */ + int dc_value; + /* enum value indicating status of the TMU */ + int tmu_state; +}; + +/* Global struct tmu_info variable to store init values */ +static struct tmu_info gbl_info; + +/* + * After reading temperature code from register, compensating + * its value and calculating celsius temperatue, + * get current temperatue. + * + * @return current temperature of the chip as sensed by TMU + */ +int get_cur_temp(struct tmu_info *info) +{ + int cur_temp; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Temperature code range between min 25 and max 125 */ + cur_temp = readl(®->current_temp) & 0xff; + + /* Calibrate current temperature */ + if (cur_temp) + cur_temp = cur_temp - info->te1 + info->dc_value; + + return cur_temp; +} + +/* + * Monitors status of the TMU device and exynos temperature + * + * @param temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + */ +enum tmu_status_t tmu_monitor(int *temp) +{ + if (gbl_info.tmu_state == TMU_STATUS_INIT) + return -1; + + int cur_temp; + struct tmu_data *data = &gbl_info.data; + + /* Read current temperature of the SOC */ + cur_temp = get_cur_temp(&gbl_info); + *temp = cur_temp; + + /* Temperature code lies between min 25 and max 125 */ + if (cur_temp >= data->ts.start_tripping && + cur_temp <= data->ts.max_val) + return TMU_STATUS_TRIPPED; + else if (cur_temp >= data->ts.start_warning) + return TMU_STATUS_WARNING; + else if (cur_temp < data->ts.start_warning && + cur_temp >= data->ts.min_val) + return TMU_STATUS_NORMAL; + /* Temperature code does not lie between min 25 and max 125 */ + else { + gbl_info.tmu_state = TMU_STATUS_INIT; + debug("EXYNOS_TMU: Thermal reading failed\n"); + return -1; + } + return 0; +} + +/* + * Get TMU specific pre-defined values from FDT + * + * @param info pointer to the tmu_info struct + * @param blob FDT blob + * @return int value, 0 for success + */ +int get_tmu_fdt_values(struct tmu_info *info, const void *blob) +{ + int node; + int error = 0; + + /* Get the node from FDT for TMU */ + node = fdtdec_next_compatible(blob, 0, + COMPAT_SAMSUNG_EXYNOS_TMU); + if (node < 0) { + debug("EXYNOS_TMU: No node for tmu in device tree\n"); + return -1; + } + + /* + * Get the pre-defined TMU specific values from FDT. + * All of these are expected to be correct otherwise + * miscalculation of register values in tmu_setup_parameters + * may result in misleading current temperature. + */ + info->tmu_base = fdtdec_get_addr(blob, node, "reg"); + if (info->tmu_base == FDT_ADDR_T_NONE) { + debug("%s: Missing tmu-base\n", __func__); + return -1; + } + info->tmu_mux = fdtdec_get_int(blob, + node, "samsung,mux", -1); + error |= info->tmu_mux; + info->data.ts.min_val = fdtdec_get_int(blob, + node, "samsung,min-temp", -1); + error |= info->data.ts.min_val; + info->data.ts.max_val = fdtdec_get_int(blob, + node, "samsung,max-temp", -1); + error |= info->data.ts.max_val; + info->data.ts.start_warning = fdtdec_get_int(blob, + node, "samsung,start-warning", -1); + error |= info->data.ts.start_warning; + info->data.ts.start_tripping = fdtdec_get_int(blob, + node, "samsung,start-tripping", -1); + error |= info->data.ts.start_tripping; + info->data.efuse_min_value = fdtdec_get_int(blob, + node, "samsung,efuse-min-value", -1); + error |= info->data.efuse_min_value; + info->data.efuse_value = fdtdec_get_int(blob, + node, "samsung,efuse-value", -1); + error |= info->data.efuse_value; + info->data.efuse_max_value = fdtdec_get_int(blob, + node, "samsung,efuse-max-value", -1); + error |= info->data.efuse_max_value; + info->data.slope = fdtdec_get_int(blob, + node, "samsung,slope", -1); + error |= info->data.slope; + info->dc_value = fdtdec_get_int(blob, + node, "samsung,dc-value", -1); + error |= info->dc_value; + + if (error == -1) { + debug("fail to get tmu node properties\n"); + return -1; + } + + return 0; +} + +/* + * Calibrate and calculate threshold values and + * enable interrupt levels + * + * @param info pointer to the tmu_info struct + */ +void tmu_setup_parameters(struct tmu_info *info) +{ + unsigned int te_temp, con; + unsigned int warning_temp, trip_temp; + unsigned int cooling_temp; + unsigned int rising_value; + struct tmu_data *data = &info->data; + struct tmu_reg *reg = (struct tmu_reg *)info->tmu_base; + + /* Must reload for using efuse value at EXYNOS */ + writel(TRIMINFO_RELOAD, ®->triminfo_control); + + /* Get the compensation parameter */ + te_temp = readl(®->triminfo); + info->te1 = te_temp & TRIM_INFO_MASK; + info->te2 = ((te_temp >> 8) & TRIM_INFO_MASK); + + if ((data->efuse_min_value > info->te1) || + (info->te1 > data->efuse_max_value) + || (info->te2 != 0)) + info->te1 = data->efuse_value; + + /* Get RISING & FALLING Threshold value */ + warning_temp = data->ts.start_warning + + info->te1 - info->dc_value; + trip_temp = data->ts.start_tripping + + info->te1 - info->dc_value; + cooling_temp = 0; + + rising_value = ((warning_temp << 8) | (trip_temp << 16)); + + /* Set interrupt level */ + writel(rising_value, ®->threshold_temp_rise); + writel(cooling_temp, ®->threshold_temp_fall); + + /* + * Need to init all regsiter setting after getting parameter info + * [28:23] vref [11:8] slope - Tunning parameter + */ + writel(data->slope, ®->tmu_control); + + writel(INTCLEARALL, ®->intclear); + /* TMU core enable */ + con = readl(®->tmu_control); + con |= (info->tmu_mux << 20) | CORE_EN; + + writel(con, ®->tmu_control); + + /* LEV0 LEV1 LEV2 interrupt enable */ + writel(INTEN_RISE0 | INTEN_RISE1 | INTEN_RISE2, ®->inten); +} + +/* + * Initialize TMU device + * + * @param blob FDT blob + * @return int value, 0 for success + */ +int tmu_init(const void *blob) +{ + gbl_info.tmu_state = TMU_STATUS_INIT; + if (get_tmu_fdt_values(&gbl_info, blob) < 0) + return -1; + + tmu_setup_parameters(&gbl_info); + gbl_info.tmu_state = TMU_STATUS_NORMAL; + + return 0; +} diff --git a/include/tmu.h b/include/tmu.h new file mode 100644 index 0000000..17e9a85 --- /dev/null +++ b/include/tmu.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Akshay Saraswat + * + * Thermal Management Unit + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _TMU_H +#define _TMU_H + +enum tmu_status_t { + TMU_STATUS_INIT = 0, + TMU_STATUS_NORMAL, + TMU_STATUS_WARNING, + TMU_STATUS_TRIPPED, +}; + +/* + * Monitors status of the TMU device and exynos temperature + * + * @param temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + * and -1 on error + */ +enum tmu_status_t tmu_monitor(int *temp); + +/* + * Initialize TMU device + * + * @param blob FDT blob + * @return int value, 0 for success + */ +int tmu_init(const void *blob); +#endif /* _THERMAL_H_ */