From patchwork Mon Jan 21 11:11:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akshay Saraswat X-Patchwork-Id: 214115 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 5C27A2C0089 for ; Mon, 21 Jan 2013 23:05:57 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id AD9B94A09D; Mon, 21 Jan 2013 13:05:53 +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 v+sH6my68D2r; Mon, 21 Jan 2013 13:05:53 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 13FEF4A0A5; Mon, 21 Jan 2013 13:05:44 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A9BB44A047 for ; Mon, 21 Jan 2013 11:52: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 w5xNiAt6YVUj for ; Mon, 21 Jan 2013 11:52: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 mailout3.samsung.com (mailout3.samsung.com [203.254.224.33]) by theia.denx.de (Postfix) with ESMTP id 5112C4A02F for ; Mon, 21 Jan 2013 11:52:10 +0100 (CET) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MGZ0006H26PQX40@mailout3.samsung.com> for u-boot@lists.denx.de; Mon, 21 Jan 2013 19:52:08 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.125]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 02.14.03880.8DD1DF05; Mon, 21 Jan 2013 19:52:08 +0900 (KST) X-AuditID: cbfee61b-b7fb06d000000f28-8e-50fd1dd8d6f5 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 51.14.03880.8DD1DF05; Mon, 21 Jan 2013 19:52:08 +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 <0MGZ0098E23DT650@mmp1.samsung.com> for u-boot@lists.denx.de; Mon, 21 Jan 2013 19:52:07 +0900 (KST) From: Akshay Saraswat To: u-boot@lists.denx.de Date: Mon, 21 Jan 2013 06:11:39 -0500 Message-id: <1358766705-2118-2-git-send-email-akshay.s@samsung.com> X-Mailer: git-send-email 1.8.0 In-reply-to: <1358766705-2118-1-git-send-email-akshay.s@samsung.com> References: <1358766705-2118-1-git-send-email-akshay.s@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCLMWRmVeSWpSXmKPExsWyRsSkVveG7N8Ag4lzFS3e7u1kd2D0OHtn B2MAYxSXTUpqTmZZapG+XQJXxqcJ+1gL9mRXrL1/j7WB8U5YFyMnh4SAicT6yU2sELaYxIV7 69m6GLk4hASWMkrcXPmPFabo3o0mRojEIkaJ88+aoaqWMUksnt/PDlLFJqAjsX3JdzBbREBC 4lf/VUYQm1mgTOLRrgYwW1jAR2Lept9gNSwCqhKTP88Hs3kFnCUmrnvBDLFNTuLDnkdgcU4B F4nlH6aCXSEEVPPg83xWkMUSAmfYJF4de80IMUhA4tvkQyxdjBxACVmJTQeg5khKHFxxg2UC o/ACRoZVjKKpBckFxUnpuUZ6xYm5xaV56XrJ+bmbGIFhePrfM+kdjKsaLA4xCnAwKvHwJvT9 CRBiTSwrrsw9xCjBwawkwvtzBlCINyWxsiq1KD++qDQntfgQYzLQ8onMUqLJ+cAYySuJNzQ2 MTc1NrU0MjIzNSVNWEmcl/HUkwAhgfTEktTs1NSC1CKYLUwcnFINjDUJLPJ6K6cdjZY11LkW I8asqfTi36I/7+/qMH6sX3b6wvky37b2loAzGQ++RE1pyRB7qHNo8UpRractLCVbb3X8e3oh PH9NmMmLpbc5TufNf33Zr7S0S7D2P5eXj6mVxpQNat2ixtInduYI/57UY3Wnb3lo2FsutZ2s K9YybYpJMr2YuEXOS4mlOCPRUIu5qDgRAKQcjuqHAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrMIsWRmVeSWpSXmKPExsVy+t9jAd0bsn8DDCa/4rB4u7eT3YHR4+yd HYwBjFENjDYZqYkpqUUKqXnJ+SmZeem2St7B8c7xpmYGhrqGlhbmSgp5ibmptkouPgG6bpk5 QGOVFMoSc0qBQgGJxcVK+naYJoSGuOlawDRG6PqGBMH1GBmggYQ1jBmfJuxjLdiTXbH2/j3W BsY7YV2MnBwSAiYS9240MULYYhIX7q1n62Lk4hASWMQocf5ZM5SzjEli8fx+dpAqNgEdie1L voPZIgISEr/6r4J1MwuUSTza1QBmCwv4SMzb9BushkVAVWLy5/lgNq+As8TEdS+YIbbJSXzY 8wgszingIrH8w1RWEFsIqObB5/msExh5FzAyrGIUTS1ILihOSs810itOzC0uzUvXS87P3cQI DvJn0jsYVzVYHGIU4GBU4uFN6PsTIMSaWFZcmXuIUYKDWUmE9+cMoBBvSmJlVWpRfnxRaU5q 8SHGZKCrJjJLiSbnAyMwryTe0NjE3NTY1NLEwsTMkjRhJXFexlNPAoQE0hNLUrNTUwtSi2C2 MHFwSjUwNj6e/SorI6jrsMG9IinTlXmOB782rfPi5ajKFHVfxx+W/S7i0hHVyKW/PNLDZqs5 ucnesfyyt83QKyHVasfiPVe7sncev/zj+2NdLuntAqHqjLp19vKLpHcU/bnxOe5axa1j7Ptz cje17tqiIB+i8VlR9vG3bzvlP0pHhbVF7poodPTguh83lViKMxINtZiLihMBIkQ6VLYCAAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected X-Mailman-Approved-At: Mon, 21 Jan 2013 13:05:42 +0100 Cc: hatim.rv@samsung.com, rajeshwari.s@samsung.com Subject: [U-Boot] [PATCH 1/7 v5] 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 v4: - Changed return value of get_cur_temp in case of 0 degree temp from -1 to TMU_STATUS_INIT because return value should be enum tmu_status_t. 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(+) 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..a5c7027 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-$(CONFIG_POWER) += power_core.o COBJS-$(CONFIG_DIALOG_POWER) += power_dialog.o diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c new file mode 100644 index 0000000..c48fe28 --- /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; + +/* + * 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 */ + 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 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->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; + puts("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_ */