From patchwork Wed Feb 6 13:18:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akshay Saraswat X-Patchwork-Id: 218589 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 E2C082C02C5 for ; Thu, 7 Feb 2013 00:00:20 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0DE444A105; Wed, 6 Feb 2013 14:00:19 +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 2NL3fC9UMUgX; Wed, 6 Feb 2013 14:00:18 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 15A554A0FA; Wed, 6 Feb 2013 14:00:17 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7C29A4A0FA for ; Wed, 6 Feb 2013 14:00: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 nN54fjHzjMZk for ; Wed, 6 Feb 2013 14:00:13 +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 mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by theia.denx.de (Postfix) with ESMTP id 1A8204A04C for ; Wed, 6 Feb 2013 14:00:11 +0100 (CET) Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MHS00831URGF700@mailout4.samsung.com> for u-boot@lists.denx.de; Wed, 06 Feb 2013 21:59:48 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.123]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 19.34.03918.4C352115; Wed, 06 Feb 2013 21:59:48 +0900 (KST) X-AuditID: cbfee61a-b7f7d6d000000f4e-0d-511253c44e32 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id A8.34.03918.4C352115; Wed, 06 Feb 2013 21:59:48 +0900 (KST) Received: from chrome-ubuntu.sisodomain.com ([107.108.73.106]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MHS00KYVUNSCJ50@mmp1.samsung.com> for u-boot@lists.denx.de; Wed, 06 Feb 2013 21:59:48 +0900 (KST) From: Akshay Saraswat To: u-boot@lists.denx.de Date: Wed, 06 Feb 2013 08:18:38 -0500 Message-id: <1360156726-13315-2-git-send-email-akshay.s@samsung.com> X-Mailer: git-send-email 1.8.0 In-reply-to: <1360156726-13315-1-git-send-email-akshay.s@samsung.com> References: <1360156726-13315-1-git-send-email-akshay.s@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCLMWRmVeSWpSXmKPExsWyRsSkWvdIsFCgwaLXahZv93ayOzB6nL2z gzGAMYrLJiU1J7MstUjfLoEr48yOE0wFh7Mr5rbPYmpgPB7WxcjJISFgItH3ZRILhC0mceHe erYuRi4OIYGljBI9xxqZYYo+LznFDpFYxCjR8LiPEcJZxiTR2fMDrIpNQEdi+5Lv7CC2iICE xK/+q4wgNrOAi8S6m9fAbGEBH4l1L3eygtgsAqoSl9/fAbN5gWoub/kIdYacxIc9j8DmcAq4 SrTNOg5mCwHV/N7eCLZYQuAMm8TJbz+ZIAYJSHybfAiomQMoISux6QDU1ZISB1fcYJnAKLyA kWEVo2hqQXJBcVJ6rqFecWJucWleul5yfu4mRmAYnv73TGoH48oGi0OMAhyMSjy8N/QEA4VY E8uKK3MPMUpwMCuJ8OY5CQUK8aYkVlalFuXHF5XmpBYfYkwGWj6RWUo0OR8YI3kl8YbGJuam xqaWRkZmpqakCSuJ8zKeehIgJJCeWJKanZpakFoEs4WJg1OqgXFVfS+L7roOU1vG69kvvIqv CNWk+0srZkZr/Hrqa3RwyfPTccs3W71ieBBw8EfhY2+9wH1PV2qpPrcuWt5mwryrlfvGEuuN PboTD5z7OT3kUPP7k1+8LmVWLi7LElo3+bq5FpMn08qJZ06sOCaz8sgm9Y0rlsYdWh9aaL9P 9mSHvc59G/+62VOUWIozEg21mIuKEwEfayk5hwIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrMIsWRmVeSWpSXmKPExsVy+t9jAd0jwUKBBo/uCFm83dvJ7sDocfbO DsYAxqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wc oLFKCmWJOaVAoYDE4mIlfTtME0JD3HQtYBojdH1DguB6jAzQQMIaxowzO04wFRzOrpjbPoup gfF4WBcjJ4eEgInE5yWn2CFsMYkL99azdTFycQgJLGKUaHjcxwjhLGOS6Oz5wQxSxSagI7F9 yXewDhEBCYlf/VcZQWxmAReJdTevgdnCAj4S617uZAWxWQRUJS6/vwNm8wLVXN7ykQVim5zE hz2PwOZwCrhKtM06DmYLAdX83t7IOIGRdwEjwypG0dSC5ILipPRcQ73ixNzi0rx0veT83E2M 4CB/JrWDcWWDxSFGAQ5GJR7eG3qCgUKsiWXFlbmHGCU4mJVEePOchAKFeFMSK6tSi/Lji0pz UosPMSYDXTWRWUo0OR8YgXkl8YbGJuamxqaWJhYmZpakCSuJ8zKeehIgJJCeWJKanZpakFoE s4WJg1OqgdGbhTM99JMY0za9im0iHK5HRQRPr2O9f1VBqonZXsZLJrPFlDfksbzUdCWdq6zC nS/k/Vx/mFjUfryzIIsv9WWpxgZXBRPT3/HcobG7NloYyhu3VoprrpwqtejOwnfqi7fOKJpy mPdJc+3s3Ktx/8psV689eON6k8KFfnY2mVfCizKPFbcbKbEUZyQaajEXFScCALbX9GO2AgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Subject: [U-Boot] [PATCH 1/9 v9] 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 Adding Exynos Thermal Management Unit driver to monitor SOC temperature and take actions corresponding to states of TMU. Signed-off-by: Akshay Saraswat Acked-by: Simon Glass --- Changes since v8: - None. arch/arm/include/asm/arch-exynos/exynos-tmu.h | 58 +++++ drivers/power/Makefile | 1 + drivers/power/exynos-tmu.c | 302 +++++++++++++++++++++++++ include/tmu.h | 46 ++++ 4 files changed, 407 insertions(+) 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 8c71901..1dac16a 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libpower.o +COBJS-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o COBJS-$(CONFIG_FTPMU010_POWER) += ftpmu010.o COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c new file mode 100644 index 0000000..b010883 --- /dev/null +++ b/drivers/power/exynos-tmu.c @@ -0,0 +1,302 @@ +/* + * 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; + /* 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; + /* Value for measured data calibration */ + 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; + +/* + * Get current temperature code from register, + * then calculate and calibrate it's value + * in degree celsius. + * + * @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. + * May run more than once for first call as initial sensing + * has not yet happened. + */ + do { + cur_temp = readl(®->current_temp) & 0xff; + } while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL); + + /* Calibrate current temperature */ + 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 TMU_STATUS_INIT; + + 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 TMU_STATUS_INIT; + } +} + +/* + * 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->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_code, con; + unsigned int warning_code, trip_code; + 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 reading efuse value from triminfo register */ + writel(TRIMINFO_RELOAD, ®->triminfo_control); + + /* Get the compensation parameter */ + te_code = readl(®->triminfo); + info->te1 = te_code & TRIM_INFO_MASK; + info->te2 = ((te_code >> 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_code = data->ts.start_warning + + info->te1 - info->dc_value; + trip_code = data->ts.start_tripping + + info->te1 - info->dc_value; + cooling_temp = 0; + + rising_value = ((warning_code << 8) | (trip_code << 16)); + + /* Set interrupt level */ + writel(rising_value, ®->threshold_temp_rise); + writel(cooling_temp, ®->threshold_temp_fall); + + /* + * Init TMU control tuning parameters + * [28:24] VREF - Voltage reference + * [15:13] THERM_TRIP_MODE - Tripping mode + * [12] THERM_TRIP_EN - Thermal tripping enable + * [11:8] BUF_SLOPE_SEL - Gain of amplifier + * [6] THERM_TRIP_BY_TQ_EN - Tripping by TQ pin + */ + writel(data->slope, ®->tmu_control); + + writel(INTCLEARALL, ®->intclear); + + /* TMU core enable */ + con = readl(®->tmu_control); + con |= 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; + debug("EXYNOS_TMU: Available\n"); + + 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_ */