From patchwork Wed Jan 23 15:24:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akshay Saraswat X-Patchwork-Id: 214980 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 07BD82C0084 for ; Thu, 24 Jan 2013 02:03:47 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2D20F4A136; Wed, 23 Jan 2013 16:03:45 +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 DrXmfnZGKH8G; Wed, 23 Jan 2013 16:03:44 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 263C34A143; Wed, 23 Jan 2013 16:03:40 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 29CA64A131 for ; Wed, 23 Jan 2013 16:03:37 +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 9clQqwgBr6c6 for ; Wed, 23 Jan 2013 16:03:35 +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 6B4564A137 for ; Wed, 23 Jan 2013 16:03:28 +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 <0MH300DBW35K77V0@mailout1.samsung.com> for u-boot@lists.denx.de; Thu, 24 Jan 2013 00:03:27 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.124]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 2B.1A.03880.EBBFFF05; Thu, 24 Jan 2013 00:03:27 +0900 (KST) X-AuditID: cbfee61b-b7fb06d000000f28-5b-50fffbbefb22 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id EA.1A.03880.EBBFFF05; Thu, 24 Jan 2013 00:03:26 +0900 (KST) Received: from chrome-ubuntu.sisodomain.com ([107.108.73.106]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MH300D9M3505S40@mmp2.samsung.com> for u-boot@lists.denx.de; Thu, 24 Jan 2013 00:03:26 +0900 (KST) From: Akshay Saraswat To: u-boot@lists.denx.de Date: Wed, 23 Jan 2013 10:24:33 -0500 Message-id: <1358954681-6217-2-git-send-email-akshay.s@samsung.com> X-Mailer: git-send-email 1.8.0 In-reply-to: <1358954681-6217-1-git-send-email-akshay.s@samsung.com> References: <1358954681-6217-1-git-send-email-akshay.s@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCLMWRmVeSWpSXmKPExsWyRsSkRnf/7/8BBmffsFi83dvJ7sDocfbO DsYAxigum5TUnMyy1CJ9uwSujLWTGpkLHuZWbJl2hbGBcV1EFyMnh4SAicT1Rb+ZIGwxiQv3 1rN1MXJxCAksZZTobpjGBlPUfXwvVGI6o8SV4+dZIZxlTBKtmztYQKrYBHQkti/5zg5iiwhI SPzqv8oIYjMLuEisu3kNzBYW8JGY+P0GWA2LgKrEmfs/mEFsXgFniTOPj7JAbJOT+LDnEVgN J1DvtL5PYHEhoJqHvx+CXSEhcJlNYkbrU1aIQQIS3yYfAiriAErISmw6wAwxR1Li4IobLBMY hRcwMqxiFE0tSC4oTkrPNdIrTswtLs1L10vOz93ECAzD0/+eSe9gXNVgcYhRgINRiYc34dm/ ACHWxLLiytxDjBIczEoivLJP/wcI8aYkVlalFuXHF5XmpBYfYkwGWj6RWUo0OR8YI3kl8YbG JuamxqaWRkZmpqakCSuJ8zKeehIgJJCeWJKanZpakFoEs4WJg1OqgTGIOXG1tOrsdO7Y00zb rr2aPStl1fz9Nhqd18QLyhhjNyZNnvHX/mViRNKypbM8/ursfTHLhodjw7emuKk7Ps7dvOWy 5uYna6Z8uO7Ub3Isj+H3D5s6w9XPCjOzf1+ZKhQ016L03BLmV9N/HU9ao8uxOO2MQ4jgtLiZ 731nun0091+U0mEv1n5QiaU4I9FQi7moOBEA1v1/J4cCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrMIsWRmVeSWpSXmKPExsVy+t9jQd19v/8HGNx9a2Dxdm8nuwOjx9k7 OxgDGKMaGG0yUhNTUosUUvOS81My89JtlbyD453jTc0MDHUNLS3MlRTyEnNTbZVcfAJ03TJz gMYqKZQl5pQChQISi4uV9O0wTQgNcdO1gGmM0PUNCYLrMTJAAwlrGDPWTmpkLniYW7Fl2hXG BsZ1EV2MnBwSAiYS3cf3skHYYhIX7q0Hsrk4hASmM0pcOX6eFcJZxiTRurmDBaSKTUBHYvuS 7+wgtoiAhMSv/quMIDazgIvEupvXwGxhAR+Jid9vgNWwCKhKnLn/gxnE5hVwljjz+CgLxDY5 iQ97HoHVcAL1Tuv7BBYXAqp5+Psh2wRG3gWMDKsYRVMLkguKk9JzjfSKE3OLS/PS9ZLzczcx goP8mfQOxlUNFocYBTgYlXh4E579CxBiTSwrrsw9xCjBwawkwiv79H+AEG9KYmVValF+fFFp TmrxIcZkoKsmMkuJJucDIzCvJN7Q2MTc1NjU0sTCxMySNGElcV7GU08ChATSE0tSs1NTC1KL YLYwcXBKNTCqHVD9K1kjvvv/sneNATnLo/4JSWzhfaxxfW+cyvkaqXPRc75OcfbQ0e3UUvwg suiJVsuzM8uK/7vynmG9w7NApVHh8aVPhpOmGRtl6lcuPxKxp76vo9Zxt2ypYJr38t3ZLyvV Hu++8szI3z5OZ886l4yQM60eEh7eT7ZqhgeVvG5cPKejao8SS3FGoqEWc1FxIgDMHXjvtgIA AA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Subject: [U-Boot] [PATCH 1/9 v6] 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 v5: - Added Acked-by. - Changed position of config in makefile. - Added {} braces for one liner if-else. - Changed 'puts' to 'debug' int tmu_init. - Removed 'tmu_mux' from 'tmu_info' struct. - Removed 'if' and added 'while' in get_cur_temp because first temperature sensing takes time. 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..83a2572 --- /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_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 reading efuse value from triminfo register */ + 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); + + /* + * 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_ */