From patchwork Thu Oct 31 18:37:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Kucheria X-Patchwork-Id: 178220 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp3242435ill; Thu, 31 Oct 2019 11:38:05 -0700 (PDT) X-Google-Smtp-Source: APXvYqxwGHykzO7tLODSWXmfqddprvDWjDOOHV1TGEmsv6Hy+K2a00PDEc2yLaAxEdmLlmt6QSis X-Received: by 2002:aa7:db48:: with SMTP id n8mr7884532edt.179.1572547085560; Thu, 31 Oct 2019 11:38:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572547085; cv=none; d=google.com; s=arc-20160816; b=l+yPotnjqhmFhGCPqwhKatJrvWzH913hFFBxuO4BzkZ+bhiFd9CWaAPTu6+dgs7odA 37+F3P+TEcgn0OrgAEvPhvpITPZZYujAwwB44q6FTarZTI+2PEY90Lqc1a5f5GSehBAj WTwalBJ4laF1l+3cRqORdWkod433EuM9fQUwLTxWbV3JcV1CrtnACcQwPA2E24vjpwwR BbbfLejDCCXC1oRPDNoQRnJUojORK+qaCx6O27htq+nyEXbGsV+ezvJJmvzdBjKRJGo0 aQkI540b9C6VmrhBpe/6RWJSaiB/9+ux1pB9EeXliDeSu4RhWpczI3kYN1TXa9yY82Yp 1Szw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=4RhmNFrAjG8zCFd7O6KRoEzlzkP2xNrQ5XZHUG6WYMo=; b=1F/HOuBT6MBvnsmFQAtUfz1E+ND4SjhkmCA6/4cMfBkwkt6QNmuUN/28ZDXHax42Oz Tjh7JUSlX7g/xhCdwi2Cgr56KQyiINTVsH3PrAOwn7h+7Mh/KDU2aSLJuGxjUo/wmmgs 9tJk9ek3Pe0ZaRAUAA4ldY65/uWe9oPJhXyTJ5EYEDqehVugPivMMGN5ON4Ip00kOBgP aD55dl21JpvCUAcRdgCzQXBVAHhLCcqnzTN6yOgcAf2iBR4axZiNyl2JRUQoIxDUJ7+Q m8qmrZlDblFPlN3eXiFT6kwK/Grd6V75ZFxC/jGnylpJ7Ehd3sxOYFNA5zmwWyXsuKJR 0OTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=qUTMy6d6; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h26si5039903edb.303.2019.10.31.11.38.05; Thu, 31 Oct 2019 11:38:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=qUTMy6d6; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729415AbfJaSiE (ORCPT + 10 others); Thu, 31 Oct 2019 14:38:04 -0400 Received: from mail-pf1-f193.google.com ([209.85.210.193]:35382 "EHLO mail-pf1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729335AbfJaSiD (ORCPT ); Thu, 31 Oct 2019 14:38:03 -0400 Received: by mail-pf1-f193.google.com with SMTP id d13so4971367pfq.2 for ; Thu, 31 Oct 2019 11:38:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=4RhmNFrAjG8zCFd7O6KRoEzlzkP2xNrQ5XZHUG6WYMo=; b=qUTMy6d6bhUIjRbVvWTqaQYff41vkGPg9vSPWk8F27OXcec8Q9P5c3YgSzKYybjKnu +XZ3zBQ19Xix2vb7u4WBk5XOk4p7QGaGdR+U5QHPr3SiB/3TqjfOOzo4lsdnAewE5BsR VAKe89jQY1I6jxtCNoHaryTCWukSAxWNBcmKlm+COUQZ+W6VjAtBT18d6B+MMC5Loy5O uu4+JFSfAfmS+aVagw6jzy8w69EwKXvzjYSLJdGFMV4/sWzE5XDijSwxI99Pdb6r6BAF BJMRHlb0I248IWLKU/C1SyvSap1LGqmU2y58VrPkBuV0Jce5FKluK6wSicJCuNyntsRR fumA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=4RhmNFrAjG8zCFd7O6KRoEzlzkP2xNrQ5XZHUG6WYMo=; b=S0kpjDCY1YLxA7rcY2ODZjCJiWt4F+f3wOaA3kKrdHoIakskFXR0SiOmyn4AaLaXPA 4BuMUZmbHIdVPEh3g30aglWSV+qHv6sRP0y5hQvSeYmfTNCWyMOGoPIcxaEfAXD+yeND V9/rFczK2aB1ZZYk9gJe3g5PSwpOB4cyFwIuzvyTI/zYR4HtnlJbYG246amr+VF3vxyR EhNBTD95tUsC/GfScC+jjvUB3aElBiymwbdoYNQ0eGOs006JKyezK1Ja95Y+IaUOybLj 3erzLuJKw90FmQKpl3WtFxQ9/EIj3L1ji495gYjmKDxOGgsMUPsU5F1xpiZ3U3mtm+na fuGQ== X-Gm-Message-State: APjAAAUCYQmMDEkLrStncDrn3NlsQAxu4/n14IbS3+7bdygK1gtSOhds zNPtWyWZiFS28LqlfHaeFy50mw== X-Received: by 2002:a17:90a:b88f:: with SMTP id o15mr9580950pjr.5.1572547082657; Thu, 31 Oct 2019 11:38:02 -0700 (PDT) Received: from localhost ([49.248.58.234]) by smtp.gmail.com with ESMTPSA id e3sm4331139pff.134.2019.10.31.11.38.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 Oct 2019 11:38:02 -0700 (PDT) From: Amit Kucheria To: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, bjorn.andersson@linaro.org, edubezval@gmail.com, agross@kernel.org, masneyb@onstation.org, swboyd@chromium.org, julia.lawall@lip6.fr, Amit Kucheria , Daniel Lezcano , Mark Rutland , Rob Herring , Zhang Rui Cc: linux-pm@vger.kernel.org Subject: [PATCH v7 03/15] drivers: thermal: tsens: Add __func__ identifier to debug statements Date: Fri, 1 Nov 2019 00:07:27 +0530 Message-Id: <18717de35f31098d3ebc12564c2767b6d54d37d8.1572526427.git.amit.kucheria@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Printing the function name when enabling debugging makes logs easier to read. Signed-off-by: Amit Kucheria Reviewed-by: Stephen Boyd Reviewed-by: Daniel Lezcano --- drivers/thermal/qcom/tsens-common.c | 8 ++++---- drivers/thermal/qcom/tsens.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) -- 2.17.1 diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index c037bdf92c66..7437bfe196e5 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -42,8 +42,8 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, for (i = 0; i < priv->num_sensors; i++) { dev_dbg(priv->dev, - "sensor%d - data_point1:%#x data_point2:%#x\n", - i, p1[i], p2[i]); + "%s: sensor%d - data_point1:%#x data_point2:%#x\n", + __func__, i, p1[i], p2[i]); priv->sensor[i].slope = SLOPE_DEFAULT; if (mode == TWO_PT_CALIB) { @@ -60,7 +60,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - (CAL_DEGC_PT1 * priv->sensor[i].slope); - dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset); + dev_dbg(priv->dev, "%s: offset:%d\n", __func__, priv->sensor[i].offset); } } @@ -209,7 +209,7 @@ int __init init_common(struct tsens_priv *priv) if (ret) goto err_put_device; if (!enabled) { - dev_err(dev, "tsens device is not enabled\n"); + dev_err(dev, "%s: device not enabled\n", __func__); ret = -ENODEV; goto err_put_device; } diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 542a7f8c3d96..06c6bbd69a1a 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -127,7 +127,7 @@ static int tsens_probe(struct platform_device *pdev) of_property_read_u32(np, "#qcom,sensors", &num_sensors); if (num_sensors <= 0) { - dev_err(dev, "invalid number of sensors\n"); + dev_err(dev, "%s: invalid number of sensors\n", __func__); return -EINVAL; } @@ -156,7 +156,7 @@ static int tsens_probe(struct platform_device *pdev) ret = priv->ops->init(priv); if (ret < 0) { - dev_err(dev, "tsens init failed\n"); + dev_err(dev, "%s: init failed\n", __func__); return ret; } @@ -164,7 +164,7 @@ static int tsens_probe(struct platform_device *pdev) ret = priv->ops->calibrate(priv); if (ret < 0) { if (ret != -EPROBE_DEFER) - dev_err(dev, "tsens calibration failed\n"); + dev_err(dev, "%s: calibration failed\n", __func__); return ret; } } From patchwork Thu Oct 31 18:37:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Kucheria X-Patchwork-Id: 178221 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp3242515ill; Thu, 31 Oct 2019 11:38:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqxgf4XE47OnW8nqbMNjdwDnew5yL7hzLmS0J/khWB5C71wLbM2waJm8HqZe9/+THAZMGrMj X-Received: by 2002:a17:906:f15:: with SMTP id z21mr5671333eji.119.1572547089774; Thu, 31 Oct 2019 11:38:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572547089; cv=none; d=google.com; s=arc-20160816; b=K6JWmlgovWKRSIk1X8ZX8NY3TJi3JtSguYi9aTo5/ksEfTBX8eTUUdelaquHLuaN1i BvBOpCW01KJ3xu/utWEWNdKK6lY5a6lVw2IpPIDkHZ0MUbLTYMpOLg5fQ1sv+Uk8zAlz TSg+dDaGLzv/QG8iaQ/Gj03oM7iBfbztretGWBfySqg7SNRp1CjWhd4tBXswdXa8uIaB avQfa6WaPFkSrGa4kir9aatvmV8m2+/jKRdS+20WMszILypgrQo/tTOt3ItiL6dTr8iD svXiQTBmRy3bONzjNPBBI8fGKONphgXFCWsJ5KwJUJie0sIN8UO8lecqQLMN9crcYjcp w71g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=X8pbmbvndxxAH4F0z0Ew7Vd1EABZ+OrJe/0vppnAxes=; b=bgGs+B9Fe43dVgNRVimTTqrgPzh+4C/DQgTKPBBjJKw0Cc6vBManq0K8FaJ6iI+5O2 ZdpFZibX4wPF6qKwfJdg68UfChiHEYyDo7N+6jsjreoMj86jjHQdYLsYHjyppddTZcEd NbICvB1nTO1lEcdqBfFc7M3tii1LRPd6s3zIdCDXdEvcu1/p3Df1yFkV4pjyX4TjHA3n porWxYUXofrNAn0kFA12Y+3tNyyJligf8XHOtXNrthBD/JJ1jX3c5lGh/nvPjRY3jHZC kzqStHVRalKxY/KhNPQRNm0E95jKTi/ZwamrsZX7gEhywouc2BZ9WWCZzI89a917URdR uElQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CDLBLbFq; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h5si5293264edj.25.2019.10.31.11.38.09; Thu, 31 Oct 2019 11:38:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CDLBLbFq; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729282AbfJaSiI (ORCPT + 10 others); Thu, 31 Oct 2019 14:38:08 -0400 Received: from mail-pg1-f195.google.com ([209.85.215.195]:33763 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729402AbfJaSiI (ORCPT ); Thu, 31 Oct 2019 14:38:08 -0400 Received: by mail-pg1-f195.google.com with SMTP id u23so4618266pgo.0 for ; Thu, 31 Oct 2019 11:38:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=X8pbmbvndxxAH4F0z0Ew7Vd1EABZ+OrJe/0vppnAxes=; b=CDLBLbFqr/0ON8o38wGiBrEar70y2rg1osFmOTQ1XeqaFGprwtUrGC/X6RsonRkOpu 6o96MexTFegENdKBXGp4gqx8C2uTAE5lamxgKl8BAlXBnKAZP2OZ4WtDWcupX5wzWQTg +evjsN+w1z+KpmKZfJ851YqgziA2Ai5vy8+DNA5XnuXpDDE8643HaBa8ZM2BUXufEKO+ i1iRd/tGS0EU0IYxlMJpWmPSkq8dfIU1L1OM7egeywMKDLzT7fhUsXU/zjk697yKS6lo Colri0UuvK8LPW+OSG9C8WYJvAZzNwuBgi3dkkca1Z7KIYggZqpb1L1ms+XXrLXhgk4c A9Uw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=X8pbmbvndxxAH4F0z0Ew7Vd1EABZ+OrJe/0vppnAxes=; b=b9BsaexYmgmvdwC9tGXr0szPl/nA/gLfPEvJhgmRJssLd8HE1RYFZmm8MVmpsw1Ch8 6U+OdHMiYm6iUzq23/w9vJ67qQ8JVMgEbsB4uZ+szqo0/UnyvwNVGpt6JLqh9OK0wEa1 YiIV0zaN34IpTJR3IgHB76DAqWZqEsTaAATZXZuBliBe8KKuT3hzAUOtnhsV6kbfVcFp F4k0dyH9q+0um1nPkDf+FwNoy2niSoXWnwzUVUb8PtLgsg6wcOGAm7WNnQMkcLVdfXin s39ptMkiTcuwXv/LlWwlsWW10w4W8AXxrzgnpadHGeXXzqSzWD5xMvFg274lOsdZLeF+ KyCw== X-Gm-Message-State: APjAAAWr7FMfBid2xzqCIVtzQ5Ve9nWes+aEGm6qX1aB5Vw+05Q8o7EQ W5i2O/tyR1rc8FZZ3UrCw+UCDg== X-Received: by 2002:a63:1b59:: with SMTP id b25mr8347745pgm.267.1572547087268; Thu, 31 Oct 2019 11:38:07 -0700 (PDT) Received: from localhost ([49.248.58.234]) by smtp.gmail.com with ESMTPSA id c12sm4812571pfp.67.2019.10.31.11.38.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 Oct 2019 11:38:06 -0700 (PDT) From: Amit Kucheria To: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, bjorn.andersson@linaro.org, edubezval@gmail.com, agross@kernel.org, masneyb@onstation.org, swboyd@chromium.org, julia.lawall@lip6.fr, Amit Kucheria , Daniel Lezcano , Mark Rutland , Rob Herring , Zhang Rui Cc: linux-pm@vger.kernel.org Subject: [PATCH v7 04/15] drivers: thermal: tsens: Add debugfs support Date: Fri, 1 Nov 2019 00:07:28 +0530 Message-Id: <16e39c1bbfc18b5cf6274620cd72cc63205f53a5.1572526427.git.amit.kucheria@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Dump some basic version info and sensor details into debugfs. Example from qcs404 below: --(/sys/kernel/debug) $ ls tsens/ 4a9000.thermal-sensor version --(/sys/kernel/debug) $ cat tsens/version 1.4.0 --(/sys/kernel/debug) $ cat tsens/4a9000.thermal-sensor/sensors max: 11 num: 10 id slope offset ------------------------ 0 3200 404000 1 3200 404000 2 3200 404000 3 3200 404000 4 3200 404000 5 3200 404000 6 3200 404000 7 3200 404000 8 3200 404000 9 3200 404000 Signed-off-by: Amit Kucheria Reviewed-by: Stephen Boyd --- drivers/thermal/qcom/tsens-common.c | 83 +++++++++++++++++++++++++++++ drivers/thermal/qcom/tsens.c | 2 + drivers/thermal/qcom/tsens.h | 6 +++ 3 files changed, 91 insertions(+) -- 2.17.1 diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index 7437bfe196e5..ea2c46cc6a66 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -3,6 +3,7 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -139,6 +140,77 @@ int get_temp_common(struct tsens_sensor *s, int *temp) return 0; } +#ifdef CONFIG_DEBUG_FS +static int dbg_sensors_show(struct seq_file *s, void *data) +{ + struct platform_device *pdev = s->private; + struct tsens_priv *priv = platform_get_drvdata(pdev); + int i; + + seq_printf(s, "max: %2d\nnum: %2d\n\n", + priv->feat->max_sensors, priv->num_sensors); + + seq_puts(s, " id slope offset\n--------------------------\n"); + for (i = 0; i < priv->num_sensors; i++) { + seq_printf(s, "%8d %8d %8d\n", priv->sensor[i].hw_id, + priv->sensor[i].slope, priv->sensor[i].offset); + } + + return 0; +} + +static int dbg_version_show(struct seq_file *s, void *data) +{ + struct platform_device *pdev = s->private; + struct tsens_priv *priv = platform_get_drvdata(pdev); + u32 maj_ver, min_ver, step_ver; + int ret; + + if (tsens_ver(priv) > VER_0_1) { + ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver); + if (ret) + return ret; + ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver); + if (ret) + return ret; + ret = regmap_field_read(priv->rf[VER_STEP], &step_ver); + if (ret) + return ret; + seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver); + } else { + seq_puts(s, "0.1.0\n"); + } + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(dbg_version); +DEFINE_SHOW_ATTRIBUTE(dbg_sensors); + +static void tsens_debug_init(struct platform_device *pdev) +{ + struct tsens_priv *priv = platform_get_drvdata(pdev); + struct dentry *root, *file; + + root = debugfs_lookup("tsens", NULL); + if (!root) + priv->debug_root = debugfs_create_dir("tsens", NULL); + else + priv->debug_root = root; + + file = debugfs_lookup("version", priv->debug_root); + if (!file) + debugfs_create_file("version", 0444, priv->debug_root, + pdev, &dbg_version_fops); + + /* A directory for each instance of the TSENS IP */ + priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); + debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); +} +#else +static inline void tsens_debug_init(struct platform_device *pdev) {} +#endif + static const struct regmap_config tsens_config = { .name = "tm", .reg_bits = 32, @@ -199,6 +271,15 @@ int __init init_common(struct tsens_priv *priv) goto err_put_device; } + if (tsens_ver(priv) > VER_0_1) { + for (i = VER_MAJOR; i <= VER_STEP; i++) { + priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, + priv->fields[i]); + if (IS_ERR(priv->rf[i])) + return PTR_ERR(priv->rf[i]); + } + } + priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[TSENS_EN]); if (IS_ERR(priv->rf[TSENS_EN])) { @@ -238,6 +319,8 @@ int __init init_common(struct tsens_priv *priv) } } + tsens_debug_init(op); + return 0; err_put_device: diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 06c6bbd69a1a..772aa76b50e1 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -3,6 +3,7 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -176,6 +177,7 @@ static int tsens_remove(struct platform_device *pdev) { struct tsens_priv *priv = platform_get_drvdata(pdev); + debugfs_remove_recursive(priv->debug_root); if (priv->ops->disable) priv->ops->disable(priv); diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 84e5447c5686..00899c17e848 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -293,6 +293,8 @@ struct tsens_context { * @feat: features of the IP * @fields: bitfield locations * @ops: pointer to list of callbacks supported by this device + * @debug_root: pointer to debugfs dentry for all tsens + * @debug: pointer to debugfs dentry for tsens controller * @sensor: list of sensors attached to this device */ struct tsens_priv { @@ -306,6 +308,10 @@ struct tsens_priv { const struct tsens_features *feat; const struct reg_field *fields; const struct tsens_ops *ops; + + struct dentry *debug_root; + struct dentry *debug; + struct tsens_sensor sensor[0]; }; From patchwork Thu Oct 31 18:37:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Kucheria X-Patchwork-Id: 178231 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp3243396ill; Thu, 31 Oct 2019 11:38:52 -0700 (PDT) X-Google-Smtp-Source: APXvYqy4+tlLFumkWrgJB4ySbGeeOlp4YLHUymjeXQOodQkThg2b7/Sn4iDjrCoz5RnJ3jyz6q89 X-Received: by 2002:a17:906:a44:: with SMTP id x4mr5604616ejf.64.1572547132021; Thu, 31 Oct 2019 11:38:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572547132; cv=none; d=google.com; s=arc-20160816; b=bTn38lsR7ACbG3VmDSAgpNGQOHb4L8/wcMK8z8tf9giEB3GaVBpAqocHMVNK9bLfo7 0oTYhOOCYrskrWL2e+7tV1jXydoVJiBygCNNTmawbdjvzspg1p00Rtm3UnKqIpzS89Fd h0j3V/NyGfz3OE+4cV4DGKA8NNUlp51FBInjZ2qFZMM/p+RhvarFlfusAXwu1GOKchjK 2VVuuDiFYeE1kmcR/TmPGy26YKoVyh0fI1K7F+WKel2uevbWD3MHZn0GIRgRB8yXjPUq wb+lOk9qsRJJbHe3zdrYfGYjT70ZODqsOaeD60jiKQy0qBn/e7P349GMGTgFAt+Z+cEg YNXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=/kNhWSzT1XF3+/kAR7Dxjp13J1ZI+CyyKCX+EYBQmx8=; b=dMTay/N3ZKRDS83Rvg2gUKMzG/igsoFZxJEQ7+us0MbQSktgBwrZNKUIZCNAsgeLhh qaKIwGkaHgV5SO2TpvX9k+JJ/1xO+PembRlDAaqIHWbWGdwNHcwjeJfXAAwHf963jQ6W nb+aLZ8HReUweZ8ddHPbDCaIVYWWyk07uMip/D27jc/SXqwKgqzWYKy9QBiilKzzGe31 iXj7+2cw+IheZW5vWoGlyqN6hB5eGl2NR/qXqqeZcGEdhl1GSukctLINHC20m/yYVfVT cF5y/z8FqFWY0GeTbTtI7lyuJjITx1gVkdxlcxCU0D3REkmmzCl3n7wC/Ix8TxsuU/mU shMg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=IFMn73uT; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f6si4483086ejw.226.2019.10.31.11.38.51; Thu, 31 Oct 2019 11:38:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=IFMn73uT; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729563AbfJaSiu (ORCPT + 10 others); Thu, 31 Oct 2019 14:38:50 -0400 Received: from mail-pg1-f195.google.com ([209.85.215.195]:45875 "EHLO mail-pg1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729558AbfJaSit (ORCPT ); Thu, 31 Oct 2019 14:38:49 -0400 Received: by mail-pg1-f195.google.com with SMTP id r1so4577593pgj.12 for ; Thu, 31 Oct 2019 11:38:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=/kNhWSzT1XF3+/kAR7Dxjp13J1ZI+CyyKCX+EYBQmx8=; b=IFMn73uTG9BbSfgEHKaiuimXMyJccsgaiQ0Oy5+kW4Y9Dt842SLGrlTH1aiwADNy6G MQyALSdfjHdvNhQ0SDYsr/VqsgzvbTwErlam0Dx1Iq2bVbIg+/BJps1PZE1OdfjLLdCM iSrh8YVzEr9KXs3vHp6kZH8bTZkisH8sEIPDIGWWQaMPXeZO3tW+Ygd4YAvRq+NxjQsb LmPQDG/fW6UB37PoERYIRAMv7Le1UHcqQKXeY1nNKXf9IAiIgxI4A0Zvle0ninOqlj3U JdpVSTsoYHvrMurJ4xDDTZ6hnYfs2ZBs9+E18iQ7Rr1VfwmWTmhwe0IsyN+M+TThaPV9 6ogA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=/kNhWSzT1XF3+/kAR7Dxjp13J1ZI+CyyKCX+EYBQmx8=; b=lhaL7T0NZMHz44OPk2nHJYY9UxIqz6mtNKTUutzNue/jNT8ZtvgTT0eqr5RkmfxMoW P+I/7DcyYvzIoHY4INhA5RDSpSlGd8u99BRI8br8RYdsLCPGP737agKQIX/SZeTNoDRU 3E3BJuqyrs6YtzZ8RIYj9afdzKqOS52zkkHwqVTbHb2ZGQsrR51WU/jYmJCM/u1mDYi4 vxO9QtAAqMo6mJLjphM3ya956IuYreW3Wzz5jcKgNNC8Pz7FEj9WqX/hzLKIMQkPHQiY lB/5J8HU6ImSEF84XjTGBBLoKEBYtIX2r/z/DtuICTCKrWxWw9SHQSKzBUT1HhXOErR9 qQLg== X-Gm-Message-State: APjAAAXlQYDYcs5RariL5TheFTPgv3bivkyApZCz4GqpYxHAgO3tyswV y4ISozXN0yuRjwOWvuWKXRgXPg== X-Received: by 2002:a17:90a:170a:: with SMTP id z10mr9670979pjd.86.1572547128652; Thu, 31 Oct 2019 11:38:48 -0700 (PDT) Received: from localhost ([49.248.58.234]) by smtp.gmail.com with ESMTPSA id 12sm8846517pjm.11.2019.10.31.11.38.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 Oct 2019 11:38:48 -0700 (PDT) From: Amit Kucheria To: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, bjorn.andersson@linaro.org, edubezval@gmail.com, agross@kernel.org, masneyb@onstation.org, swboyd@chromium.org, julia.lawall@lip6.fr, Amit Kucheria , Daniel Lezcano , Mark Rutland , Rob Herring , Zhang Rui Cc: linux-pm@vger.kernel.org Subject: [PATCH v7 14/15] drivers: thermal: tsens: Create function to return sign-extended temperature Date: Fri, 1 Nov 2019 00:07:38 +0530 Message-Id: <0689917475cf83b7e01f6978504fd37352a5e3ca.1572526427.git.amit.kucheria@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Hide the details of how to convert values read from TSENS HW to mCelsius behind a function. All versions of the IP can be supported as a result. Signed-off-by: Amit Kucheria Reviewed-by: Stephen Boyd --- drivers/thermal/qcom/tsens-common.c | 49 ++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 14 deletions(-) -- 2.17.1 diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index ea2c46cc6a66..c34a1a26ce29 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -84,13 +84,46 @@ static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) return degc; } +/** + * tsens_hw_to_mC - Return sign-extended temperature in mCelsius. + * @s: Pointer to sensor struct + * @field: Index into regmap_field array pointing to temperature data + * + * This function handles temperature returned in ADC code or deciCelsius + * depending on IP version. + * + * Return: Temperature in milliCelsius on success, a negative errno will + * be returned in error cases + */ +static int tsens_hw_to_mC(struct tsens_sensor *s, int field) +{ + struct tsens_priv *priv = s->priv; + u32 resolution; + u32 temp = 0; + int ret; + + resolution = priv->fields[LAST_TEMP_0].msb - + priv->fields[LAST_TEMP_0].lsb; + + ret = regmap_field_read(priv->rf[field], &temp); + if (ret) + return ret; + + /* Convert temperature from ADC code to milliCelsius */ + if (priv->feat->adc) + return code_to_degc(temp, s) * 1000; + + /* deciCelsius -> milliCelsius along with sign extension */ + return sign_extend32(temp, resolution) * 100; +} + int get_temp_tsens_valid(struct tsens_sensor *s, int *temp) { struct tsens_priv *priv = s->priv; int hw_id = s->hw_id; u32 temp_idx = LAST_TEMP_0 + hw_id; u32 valid_idx = VALID_0 + hw_id; - u32 last_temp = 0, valid, mask; + u32 valid; int ret; ret = regmap_field_read(priv->rf[valid_idx], &valid); @@ -108,19 +141,7 @@ int get_temp_tsens_valid(struct tsens_sensor *s, int *temp) } /* Valid bit is set, OK to read the temperature */ - ret = regmap_field_read(priv->rf[temp_idx], &last_temp); - if (ret) - return ret; - - if (priv->feat->adc) { - /* Convert temperature from ADC code to milliCelsius */ - *temp = code_to_degc(last_temp, s) * 1000; - } else { - mask = GENMASK(priv->fields[LAST_TEMP_0].msb, - priv->fields[LAST_TEMP_0].lsb); - /* Convert temperature from deciCelsius to milliCelsius */ - *temp = sign_extend32(last_temp, fls(mask) - 1) * 100; - } + *temp = tsens_hw_to_mC(s, temp_idx); return 0; } From patchwork Thu Oct 31 18:37:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Kucheria X-Patchwork-Id: 178232 Delivered-To: patch@linaro.org Received: by 2002:a92:409a:0:0:0:0:0 with SMTP id d26csp3243562ill; Thu, 31 Oct 2019 11:38:59 -0700 (PDT) X-Google-Smtp-Source: APXvYqxWpCawdD5i3hvmIxaiuQPvmIjeKB/YvDquEtrQ71oXlCLjEL3vrPgxQtqO08RHLtoXW6I9 X-Received: by 2002:a17:906:8046:: with SMTP id x6mr5561766ejw.221.1572547139085; Thu, 31 Oct 2019 11:38:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1572547139; cv=none; d=google.com; s=arc-20160816; b=aJnHqZOf4rTtaXFWHoRXKHwi7dIZV1rvY2bSBdDOqOogSDllSfzw2Uzvoye8nTWJsQ M9K+JC4jFgwaOqAsPkTOnsll3FJn0qsqzfgshOHUw5COykjiiaiVqmSs7Dns1KZUbGUo MTm2OsTAtNZixkYxYx4WRb3vmqk/ZAtmHETh/s61YMbz0DLun0oRS1p7cu1zBw75M6R9 VUOHPd1byDtAEoyGD6HWu3spjni5K8SeWkeRjCgwhSctpDvuFZe7MCydG9mxoiZ5Ld20 nWHhdG7mcaY4zrB8KGz6ESgCeb61kNxXEUDNbGXeY8lPC4SvjnQx3WGrs+vxZTRclMPf P8HA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=TOvZapyO4cbRPQHTmWqry8DZxUiOQTsDk//8wpSrcFo=; b=DIWI/Vixeq4f1TrX7+ndY8uucTO7n9esiOw06u+GYX0VZ3gtGh06sQpWiFmZ6eHCxq MlUVz0eN9PuWinmkLxA4WHSQEwyoUxAr1NwSW2oTyMMMPtqz4AdAGJMVDwLB9Wpo2y1d CANVMLxJSBx8F34KRR7gAQTd52ekbtt/xFGrU+Cz5pkk+VugPhl0Ld/bBgtZgz/ZIbuy sJkHJur3BiUbq7gup3yrGObTz1jFPZcgmDmAQLhomJ4F3TpvrRp2fghEMlpMkYNGeGNs vOFqV19lnGnRaod1ExC54tm8dOHgbDVyrA9Cl8nARHEtBhZnJbdQ9TR6uwwjlJhsCuTf F1Wg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YgqX66vR; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h13si4517859edw.72.2019.10.31.11.38.58; Thu, 31 Oct 2019 11:38:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YgqX66vR; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729576AbfJaSi5 (ORCPT + 10 others); Thu, 31 Oct 2019 14:38:57 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:34330 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729559AbfJaSiz (ORCPT ); Thu, 31 Oct 2019 14:38:55 -0400 Received: by mail-pl1-f196.google.com with SMTP id k7so3085437pll.1 for ; Thu, 31 Oct 2019 11:38:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=TOvZapyO4cbRPQHTmWqry8DZxUiOQTsDk//8wpSrcFo=; b=YgqX66vRF48/p0pxWBRYrXjFmzqTEdBSGTBmAeLWkVHqCrPLFY0VNSNj92kxWt7Gk7 r1j/Xn9/9dRDK4hdfagevW1MKJVpzcf0OMtxcPxJe4ohFKj2ioG+BxqayT+W8j+iVyyq QIJ2SMRXURXesY4gMyYu6lzMJA2OgSOvp8LEAs8shU0ia23+bCoT2eoohrDCis8CatcU ThGe/sGEbG21W2TpOJCZjtNJkfpIb4CZvO1HPIXqWGYONpMBXFrX08OAv5gbzySMPZC2 F1gBxuALc4WqZ+v7etQU86S/nxZ+SHQ7cI4TTuw/ITXNI09shMhz10//TROzLS1vkh1A ZuEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=TOvZapyO4cbRPQHTmWqry8DZxUiOQTsDk//8wpSrcFo=; b=FGgNANFvIBPJCYvv40cfl7j3FSIbwc+qtZwEOtkqFn2/UJLE91ArZ0jtDX2S6GV1t6 bBpM58+HboGtsxQ3kJqOuU+h4t0qTrNxXIVoekdCVck3hd+3x7QeSw1oqOfvZHd7gnI6 IzzXNUH+9JwIWED4jWL/78DpjyJ0/xs0NH6d8k2LbkImZr9rONZC8aV0GHLk2bpumaQh KRBtMcxI+n4l+ZTFTPM0Z+82vRiPfnYgh0GBZxLLwc6RBtQScYguhaYYCxIwHVaxYl+0 Np2rHeQ8tSrZWggDbMHZN9BFQVNh22a0y1cvxLbX3vcU92XNzUh6c9CrCGw7+GQoff2B kSsQ== X-Gm-Message-State: APjAAAUDoRMSTZxObXTdVZ/M8O+wcO/cMbtZCfeAv2Zf0tLjLnJX7m3h YVh0Uv1ksCuyxYckV6s2lYrfdw== X-Received: by 2002:a17:902:4a:: with SMTP id 68mr7968693pla.8.1572547133678; Thu, 31 Oct 2019 11:38:53 -0700 (PDT) Received: from localhost ([49.248.58.234]) by smtp.gmail.com with ESMTPSA id l11sm4236573pgf.73.2019.10.31.11.38.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 Oct 2019 11:38:53 -0700 (PDT) From: Amit Kucheria To: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, bjorn.andersson@linaro.org, edubezval@gmail.com, agross@kernel.org, masneyb@onstation.org, swboyd@chromium.org, julia.lawall@lip6.fr, Amit Kucheria , Daniel Lezcano , Mark Rutland , Rob Herring , Zhang Rui Cc: linux-pm@vger.kernel.org Subject: [PATCH v7 15/15] drivers: thermal: tsens: Add interrupt support Date: Fri, 1 Nov 2019 00:07:39 +0530 Message-Id: <7508ba143f144407e5dd546107ddae65c380a76f.1572526427.git.amit.kucheria@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Depending on the IP version, TSENS supports upper, lower and critical threshold interrupts. We only add support for upper and lower threshold interrupts for now. TSENSv2 has an irq [status|clear|mask] bit tuple for each sensor while earlier versions only have a single bit per sensor to denote status and clear. These differences are handled transparently by the interrupt handler. At each interrupt, we reprogram the new upper and lower threshold in the .set_trip callback. Signed-off-by: Amit Kucheria Reviewed-by: Stephen Boyd --- drivers/thermal/qcom/tsens-common.c | 377 ++++++++++++++++++++++++++-- drivers/thermal/qcom/tsens-v0_1.c | 11 + drivers/thermal/qcom/tsens-v1.c | 29 +++ drivers/thermal/qcom/tsens-v2.c | 13 + drivers/thermal/qcom/tsens.c | 32 ++- drivers/thermal/qcom/tsens.h | 270 ++++++++++++++++---- 6 files changed, 669 insertions(+), 63 deletions(-) -- 2.17.1 diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c index c34a1a26ce29..4359a4247ac3 100644 --- a/drivers/thermal/qcom/tsens-common.c +++ b/drivers/thermal/qcom/tsens-common.c @@ -13,6 +13,31 @@ #include #include "tsens.h" +/** + * struct tsens_irq_data - IRQ status and temperature violations + * @up_viol: upper threshold violated + * @up_thresh: upper threshold temperature value + * @up_irq_mask: mask register for upper threshold irqs + * @up_irq_clear: clear register for uppper threshold irqs + * @low_viol: lower threshold violated + * @low_thresh: lower threshold temperature value + * @low_irq_mask: mask register for lower threshold irqs + * @low_irq_clear: clear register for lower threshold irqs + * + * Structure containing data about temperature threshold settings and + * irq status if they were violated. + */ +struct tsens_irq_data { + u32 up_viol; + int up_thresh; + u32 up_irq_mask; + u32 up_irq_clear; + u32 low_viol; + int low_thresh; + u32 low_irq_mask; + u32 low_irq_clear; +}; + char *qfprom_read(struct device *dev, const char *cname) { struct nvmem_cell *cell; @@ -65,6 +90,14 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, } } +static inline u32 degc_to_code(int degc, const struct tsens_sensor *s) +{ + u64 code = (degc * s->slope + s->offset) / SLOPE_FACTOR; + + pr_debug("%s: raw_code: 0x%llx, degc:%d\n", __func__, code, degc); + return clamp_val(code, THRESHOLD_MIN_ADC_CODE, THRESHOLD_MAX_ADC_CODE); +} + static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) { int degc, num, den; @@ -117,6 +150,313 @@ static int tsens_hw_to_mC(struct tsens_sensor *s, int field) return sign_extend32(temp, resolution) * 100; } +/** + * tsens_mC_to_hw - Convert temperature to hardware register value + * @s: Pointer to sensor struct + * @temp: temperature in milliCelsius to be programmed to hardware + * + * This function outputs the value to be written to hardware in ADC code + * or deciCelsius depending on IP version. + * + * Return: ADC code or temperature in deciCelsius. + */ +static int tsens_mC_to_hw(struct tsens_sensor *s, int temp) +{ + struct tsens_priv *priv = s->priv; + + /* milliC to adc code */ + if (priv->feat->adc) + return degc_to_code(temp / 1000, s); + + /* milliC to deciC */ + return temp / 100; +} + +static inline enum tsens_ver tsens_version(struct tsens_priv *priv) +{ + return priv->feat->ver_major; +} + +static void tsens_set_interrupt_v1(struct tsens_priv *priv, u32 hw_id, + enum tsens_irq_type irq_type, bool enable) +{ + u32 index = 0; + + switch (irq_type) { + case UPPER: + index = UP_INT_CLEAR_0 + hw_id; + break; + case LOWER: + index = LOW_INT_CLEAR_0 + hw_id; + break; + } + regmap_field_write(priv->rf[index], enable ? 0 : 1); +} + +static void tsens_set_interrupt_v2(struct tsens_priv *priv, u32 hw_id, + enum tsens_irq_type irq_type, bool enable) +{ + u32 index_mask = 0, index_clear = 0; + + /* + * To enable the interrupt flag for a sensor: + * - clear the mask bit + * To disable the interrupt flag for a sensor: + * - Mask further interrupts for this sensor + * - Write 1 followed by 0 to clear the interrupt + */ + switch (irq_type) { + case UPPER: + index_mask = UP_INT_MASK_0 + hw_id; + index_clear = UP_INT_CLEAR_0 + hw_id; + break; + case LOWER: + index_mask = LOW_INT_MASK_0 + hw_id; + index_clear = LOW_INT_CLEAR_0 + hw_id; + break; + } + + if (enable) { + regmap_field_write(priv->rf[index_mask], 0); + } else { + regmap_field_write(priv->rf[index_mask], 1); + regmap_field_write(priv->rf[index_clear], 1); + regmap_field_write(priv->rf[index_clear], 0); + } +} + +/** + * tsens_set_interrupt - Set state of an interrupt + * @priv: Pointer to tsens controller private data + * @hw_id: Hardware ID aka. sensor number + * @irq_type: irq_type from enum tsens_irq_type + * @enable: false = disable, true = enable + * + * Call IP-specific function to set state of an interrupt + * + * Return: void + */ +static void tsens_set_interrupt(struct tsens_priv *priv, u32 hw_id, + enum tsens_irq_type irq_type, bool enable) +{ + dev_dbg(priv->dev, "[%u] %s: %s -> %s\n", hw_id, __func__, + irq_type ? ((irq_type == 1) ? "UP" : "CRITICAL") : "LOW", + enable ? "en" : "dis"); + if (tsens_version(priv) > VER_1_X) + tsens_set_interrupt_v2(priv, hw_id, irq_type, enable); + else + tsens_set_interrupt_v1(priv, hw_id, irq_type, enable); +} + +/** + * tsens_threshold_violated - Check if a sensor temperature violated a preset threshold + * @priv: Pointer to tsens controller private data + * @hw_id: Hardware ID aka. sensor number + * @d: Pointer to irq state data + * + * Return: 0 if threshold was not violated, 1 if it was violated and negative + * errno in case of errors + */ +static int tsens_threshold_violated(struct tsens_priv *priv, u32 hw_id, + struct tsens_irq_data *d) +{ + int ret; + + ret = regmap_field_read(priv->rf[UPPER_STATUS_0 + hw_id], &d->up_viol); + if (ret) + return ret; + ret = regmap_field_read(priv->rf[LOWER_STATUS_0 + hw_id], &d->low_viol); + if (ret) + return ret; + if (d->up_viol || d->low_viol) + return 1; + + return 0; +} + +static int tsens_read_irq_state(struct tsens_priv *priv, u32 hw_id, + struct tsens_sensor *s, struct tsens_irq_data *d) +{ + int ret; + + ret = regmap_field_read(priv->rf[UP_INT_CLEAR_0 + hw_id], &d->up_irq_clear); + if (ret) + return ret; + ret = regmap_field_read(priv->rf[LOW_INT_CLEAR_0 + hw_id], &d->low_irq_clear); + if (ret) + return ret; + if (tsens_version(priv) > VER_1_X) { + ret = regmap_field_read(priv->rf[UP_INT_MASK_0 + hw_id], &d->up_irq_mask); + if (ret) + return ret; + ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask); + if (ret) + return ret; + } else { + /* No mask register on older TSENS */ + d->up_irq_mask = 0; + d->low_irq_mask = 0; + } + + d->up_thresh = tsens_hw_to_mC(s, UP_THRESH_0 + hw_id); + d->low_thresh = tsens_hw_to_mC(s, LOW_THRESH_0 + hw_id); + + dev_dbg(priv->dev, "[%u] %s%s: status(%u|%u) | clr(%u|%u) | mask(%u|%u)\n", + hw_id, __func__, (d->up_viol || d->low_viol) ? "(V)" : "", + d->low_viol, d->up_viol, d->low_irq_clear, d->up_irq_clear, + d->low_irq_mask, d->up_irq_mask); + dev_dbg(priv->dev, "[%u] %s%s: thresh: (%d:%d)\n", hw_id, __func__, + (d->up_viol || d->low_viol) ? "(violation)" : "", + d->low_thresh, d->up_thresh); + + return 0; +} + +static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver) +{ + if (ver > VER_1_X) + return mask & (1 << hw_id); + + /* v1, v0.1 don't have a irq mask register */ + return 0; +} + +/** + * tsens_irq_thread - Threaded interrupt handler for uplow interrupts + * @irq: irq number + * @data: tsens controller private data + * + * Check all sensors to find ones that violated their threshold limits. If the + * temperature is still outside the limits, call thermal_zone_device_update() to + * update the thresholds, else re-enable the interrupts. + * + * The level-triggered interrupt might deassert if the temperature returned to + * within the threshold limits by the time the handler got scheduled. We + * consider the irq to have been handled in that case. + * + * Return: IRQ_HANDLED + */ +irqreturn_t tsens_irq_thread(int irq, void *data) +{ + struct tsens_priv *priv = data; + struct tsens_irq_data d; + bool enable = true, disable = false; + unsigned long flags; + int temp, ret, i; + + for (i = 0; i < priv->num_sensors; i++) { + bool trigger = false; + struct tsens_sensor *s = &priv->sensor[i]; + u32 hw_id = s->hw_id; + + if (IS_ERR(priv->sensor[i].tzd)) + continue; + if (!tsens_threshold_violated(priv, hw_id, &d)) + continue; + ret = get_temp_tsens_valid(s, &temp); + if (ret) { + dev_err(priv->dev, "[%u] %s: error reading sensor\n", hw_id, __func__); + continue; + } + + spin_lock_irqsave(&priv->ul_lock, flags); + + tsens_read_irq_state(priv, hw_id, s, &d); + + if (d.up_viol && + !masked_irq(hw_id, d.up_irq_mask, tsens_version(priv))) { + tsens_set_interrupt(priv, hw_id, UPPER, disable); + if (d.up_thresh > temp) { + dev_dbg(priv->dev, "[%u] %s: re-arm upper\n", + priv->sensor[i].hw_id, __func__); + tsens_set_interrupt(priv, hw_id, UPPER, enable); + } else { + trigger = true; + /* Keep irq masked */ + } + } else if (d.low_viol && + !masked_irq(hw_id, d.low_irq_mask, tsens_version(priv))) { + tsens_set_interrupt(priv, hw_id, LOWER, disable); + if (d.low_thresh < temp) { + dev_dbg(priv->dev, "[%u] %s: re-arm low\n", + priv->sensor[i].hw_id, __func__); + tsens_set_interrupt(priv, hw_id, LOWER, enable); + } else { + trigger = true; + /* Keep irq masked */ + } + } + + spin_unlock_irqrestore(&priv->ul_lock, flags); + + if (trigger) { + dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", + hw_id, __func__, temp); + thermal_zone_device_update(priv->sensor[i].tzd, + THERMAL_EVENT_UNSPECIFIED); + } else { + dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", + hw_id, __func__, temp); + } + } + + return IRQ_HANDLED; +} + +int tsens_set_trips(void *_sensor, int low, int high) +{ + struct tsens_sensor *s = _sensor; + struct tsens_priv *priv = s->priv; + struct device *dev = priv->dev; + struct tsens_irq_data d; + unsigned long flags; + int high_val, low_val, cl_high, cl_low; + u32 hw_id = s->hw_id; + + dev_dbg(dev, "[%u] %s: proposed thresholds: (%d:%d)\n", + hw_id, __func__, low, high); + + cl_high = clamp_val(high, -40000, 120000); + cl_low = clamp_val(low, -40000, 120000); + + high_val = tsens_mC_to_hw(s, cl_high); + low_val = tsens_mC_to_hw(s, cl_low); + + spin_lock_irqsave(&priv->ul_lock, flags); + + tsens_read_irq_state(priv, hw_id, s, &d); + + /* Write the new thresholds and clear the status */ + regmap_field_write(priv->rf[LOW_THRESH_0 + hw_id], low_val); + regmap_field_write(priv->rf[UP_THRESH_0 + hw_id], high_val); + tsens_set_interrupt(priv, hw_id, LOWER, true); + tsens_set_interrupt(priv, hw_id, UPPER, true); + + spin_unlock_irqrestore(&priv->ul_lock, flags); + + dev_dbg(dev, "[%u] %s: (%d:%d)->(%d:%d)\n", + s->hw_id, __func__, d.low_thresh, d.up_thresh, cl_low, cl_high); + + return 0; +} + +int tsens_enable_irq(struct tsens_priv *priv) +{ + int ret; + int val = tsens_version(priv) > VER_1_X ? 7 : 1; + + ret = regmap_field_write(priv->rf[INT_EN], val); + if (ret < 0) + dev_err(priv->dev, "%s: failed to enable interrupts\n", __func__); + + return ret; +} + +void tsens_disable_irq(struct tsens_priv *priv) +{ + regmap_field_write(priv->rf[INT_EN], 0); +} + int get_temp_tsens_valid(struct tsens_sensor *s, int *temp) { struct tsens_priv *priv = s->priv; @@ -187,7 +527,7 @@ static int dbg_version_show(struct seq_file *s, void *data) u32 maj_ver, min_ver, step_ver; int ret; - if (tsens_ver(priv) > VER_0_1) { + if (tsens_version(priv) > VER_0_1) { ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver); if (ret) return ret; @@ -292,7 +632,7 @@ int __init init_common(struct tsens_priv *priv) goto err_put_device; } - if (tsens_ver(priv) > VER_0_1) { + if (tsens_version(priv) > VER_0_1) { for (i = VER_MAJOR; i <= VER_STEP; i++) { priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[i]); @@ -322,24 +662,29 @@ int __init init_common(struct tsens_priv *priv) ret = PTR_ERR(priv->rf[SENSOR_EN]); goto err_put_device; } - /* now alloc regmap_fields in tm_map */ - for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) { - priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, - priv->fields[j]); - if (IS_ERR(priv->rf[j])) { - ret = PTR_ERR(priv->rf[j]); - goto err_put_device; - } + priv->rf[INT_EN] = devm_regmap_field_alloc(dev, priv->tm_map, + priv->fields[INT_EN]); + if (IS_ERR(priv->rf[INT_EN])) { + ret = PTR_ERR(priv->rf[INT_EN]); + goto err_put_device; } - for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) { - priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, - priv->fields[j]); - if (IS_ERR(priv->rf[j])) { - ret = PTR_ERR(priv->rf[j]); - goto err_put_device; + + /* This loop might need changes if enum regfield_ids is reordered */ + for (j = LAST_TEMP_0; j <= UP_THRESH_15; j += 16) { + for (i = 0; i < priv->feat->max_sensors; i++) { + int idx = j + i; + + priv->rf[idx] = devm_regmap_field_alloc(dev, priv->tm_map, + priv->fields[idx]); + if (IS_ERR(priv->rf[idx])) { + ret = PTR_ERR(priv->rf[idx]); + goto err_put_device; + } } } + spin_lock_init(&priv->ul_lock); + tsens_enable_irq(priv); tsens_debug_init(op); return 0; diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index 055647bcee67..4b8dd6de02ce 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -347,9 +347,20 @@ static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { /* INTERRUPT ENABLE */ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), + /* UPPER/LOWER TEMPERATURE THRESHOLDS */ + REG_FIELD_FOR_EACH_SENSOR11(LOW_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9), + REG_FIELD_FOR_EACH_SENSOR11(UP_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19), + + /* UPPER/LOWER INTERRUPTS [CLEAR/STATUS] */ + REG_FIELD_FOR_EACH_SENSOR11(LOW_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 20, 20), + REG_FIELD_FOR_EACH_SENSOR11(UP_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 21, 21), + + /* NO CRITICAL INTERRUPT SUPPORT on v0.1 */ + /* Sn_STATUS */ REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), /* No VALID field on v0.1 */ + /* xxx_STATUS bits: 1 == threshold violated */ REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c index 870f502f2cb6..7d33a0c8cd3e 100644 --- a/drivers/thermal/qcom/tsens-v1.c +++ b/drivers/thermal/qcom/tsens-v1.c @@ -17,6 +17,8 @@ #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 #define TM_Sn_STATUS_OFF 0x0044 #define TM_TRDY_OFF 0x0084 +#define TM_HIGH_LOW_INT_STATUS_OFF 0x0088 +#define TM_HIGH_LOW_Sn_INT_THRESHOLD_OFF 0x0090 /* eeprom layout data for qcs404/405 (v1) */ #define BASE0_MASK 0x000007f8 @@ -168,9 +170,36 @@ static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { /* INTERRUPT ENABLE */ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), + /* UPPER/LOWER TEMPERATURE THRESHOLDS */ + REG_FIELD_FOR_EACH_SENSOR11(LOW_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 0, 9), + REG_FIELD_FOR_EACH_SENSOR11(UP_THRESH, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 10, 19), + + /* UPPER/LOWER INTERRUPTS [CLEAR/STATUS] */ + REG_FIELD_FOR_EACH_SENSOR11(LOW_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 20, 20), + REG_FIELD_FOR_EACH_SENSOR11(UP_INT_CLEAR, TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF, 21, 21), + [LOW_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 0, 0), + [LOW_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 1, 1), + [LOW_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 2, 2), + [LOW_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 3, 3), + [LOW_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 4, 4), + [LOW_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 5, 5), + [LOW_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 6, 6), + [LOW_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 7, 7), + [UP_INT_STATUS_0] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 8, 8), + [UP_INT_STATUS_1] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 9, 9), + [UP_INT_STATUS_2] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 10, 10), + [UP_INT_STATUS_3] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 11, 11), + [UP_INT_STATUS_4] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 12, 12), + [UP_INT_STATUS_5] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 13, 13), + [UP_INT_STATUS_6] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 14, 14), + [UP_INT_STATUS_7] = REG_FIELD(TM_HIGH_LOW_INT_STATUS_OFF, 15, 15), + + /* NO CRITICAL INTERRUPT SUPPORT on v1 */ + /* Sn_STATUS */ REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14), + /* xxx_STATUS bits: 1 == threshold violated */ REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 0a4f2b8fcab6..a4d15e1abfdd 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -50,9 +50,22 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */ [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2), + /* TEMPERATURE THRESHOLDS */ + REG_FIELD_FOR_EACH_SENSOR16(LOW_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 0, 11), + REG_FIELD_FOR_EACH_SENSOR16(UP_THRESH, TM_Sn_UPPER_LOWER_THRESHOLD_OFF, 12, 23), + + /* INTERRUPTS [CLEAR/STATUS/MASK] */ + REG_FIELD_SPLIT_BITS_0_15(LOW_INT_STATUS, TM_UPPER_LOWER_INT_STATUS_OFF), + REG_FIELD_SPLIT_BITS_0_15(LOW_INT_CLEAR, TM_UPPER_LOWER_INT_CLEAR_OFF), + REG_FIELD_SPLIT_BITS_0_15(LOW_INT_MASK, TM_UPPER_LOWER_INT_MASK_OFF), + REG_FIELD_SPLIT_BITS_16_31(UP_INT_STATUS, TM_UPPER_LOWER_INT_STATUS_OFF), + REG_FIELD_SPLIT_BITS_16_31(UP_INT_CLEAR, TM_UPPER_LOWER_INT_CLEAR_OFF), + REG_FIELD_SPLIT_BITS_16_31(UP_INT_MASK, TM_UPPER_LOWER_INT_MASK_OFF), + /* Sn_STATUS */ REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11), REG_FIELD_FOR_EACH_SENSOR16(VALID, TM_Sn_STATUS_OFF, 21, 21), + /* xxx_STATUS bits: 1 == threshold violated */ REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS, TM_Sn_STATUS_OFF, 16, 16), REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS, TM_Sn_STATUS_OFF, 17, 17), REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS, TM_Sn_STATUS_OFF, 18, 18), diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 772aa76b50e1..7d317660211e 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -78,12 +79,14 @@ MODULE_DEVICE_TABLE(of, tsens_table); static const struct thermal_zone_of_device_ops tsens_of_ops = { .get_temp = tsens_get_temp, .get_trend = tsens_get_trend, + .set_trips = tsens_set_trips, }; static int tsens_register(struct tsens_priv *priv) { - int i; + int i, ret, irq; struct thermal_zone_device *tzd; + struct platform_device *pdev; for (i = 0; i < priv->num_sensors; i++) { priv->sensor[i].priv = priv; @@ -96,7 +99,31 @@ static int tsens_register(struct tsens_priv *priv) if (priv->ops->enable) priv->ops->enable(priv, i); } - return 0; + + pdev = of_find_device_by_node(priv->dev->of_node); + if (!pdev) + return -ENODEV; + + irq = platform_get_irq_byname(pdev, "uplow"); + if (irq < 0) { + ret = irq; + goto err_put_device; + } + + ret = devm_request_threaded_irq(&pdev->dev, irq, + NULL, tsens_irq_thread, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + dev_name(&pdev->dev), priv); + if (ret) { + dev_err(&pdev->dev, "%s: failed to get irq\n", __func__); + goto err_put_device; + } + + enable_irq_wake(irq); + +err_put_device: + put_device(&pdev->dev); + return ret; } static int tsens_probe(struct platform_device *pdev) @@ -178,6 +205,7 @@ static int tsens_remove(struct platform_device *pdev) struct tsens_priv *priv = platform_get_drvdata(pdev); debugfs_remove_recursive(priv->debug_root); + tsens_disable_irq(priv); if (priv->ops->disable) priv->ops->disable(priv); diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 00899c17e848..8b20f28c5c51 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -13,8 +13,10 @@ #define CAL_DEGC_PT2 120 #define SLOPE_FACTOR 1000 #define SLOPE_DEFAULT 3200 +#define THRESHOLD_MAX_ADC_CODE 0x3ff +#define THRESHOLD_MIN_ADC_CODE 0x0 - +#include #include #include #include @@ -27,6 +29,11 @@ enum tsens_ver { VER_2_X, }; +enum tsens_irq_type { + LOWER, + UPPER, +}; + /** * struct tsens_sensor - data for each sensor connected to the tsens device * @priv: tsens device instance that this sensor is connected to @@ -100,22 +107,66 @@ struct tsens_ops { [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \ [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit) -/* reg_field IDs to use as an index into an array */ +#define REG_FIELD_SPLIT_BITS_0_15(_name, _offset) \ + [_name##_##0] = REG_FIELD(_offset, 0, 0), \ + [_name##_##1] = REG_FIELD(_offset, 1, 1), \ + [_name##_##2] = REG_FIELD(_offset, 2, 2), \ + [_name##_##3] = REG_FIELD(_offset, 3, 3), \ + [_name##_##4] = REG_FIELD(_offset, 4, 4), \ + [_name##_##5] = REG_FIELD(_offset, 5, 5), \ + [_name##_##6] = REG_FIELD(_offset, 6, 6), \ + [_name##_##7] = REG_FIELD(_offset, 7, 7), \ + [_name##_##8] = REG_FIELD(_offset, 8, 8), \ + [_name##_##9] = REG_FIELD(_offset, 9, 9), \ + [_name##_##10] = REG_FIELD(_offset, 10, 10), \ + [_name##_##11] = REG_FIELD(_offset, 11, 11), \ + [_name##_##12] = REG_FIELD(_offset, 12, 12), \ + [_name##_##13] = REG_FIELD(_offset, 13, 13), \ + [_name##_##14] = REG_FIELD(_offset, 14, 14), \ + [_name##_##15] = REG_FIELD(_offset, 15, 15) + +#define REG_FIELD_SPLIT_BITS_16_31(_name, _offset) \ + [_name##_##0] = REG_FIELD(_offset, 16, 16), \ + [_name##_##1] = REG_FIELD(_offset, 17, 17), \ + [_name##_##2] = REG_FIELD(_offset, 18, 18), \ + [_name##_##3] = REG_FIELD(_offset, 19, 19), \ + [_name##_##4] = REG_FIELD(_offset, 20, 20), \ + [_name##_##5] = REG_FIELD(_offset, 21, 21), \ + [_name##_##6] = REG_FIELD(_offset, 22, 22), \ + [_name##_##7] = REG_FIELD(_offset, 23, 23), \ + [_name##_##8] = REG_FIELD(_offset, 24, 24), \ + [_name##_##9] = REG_FIELD(_offset, 25, 25), \ + [_name##_##10] = REG_FIELD(_offset, 26, 26), \ + [_name##_##11] = REG_FIELD(_offset, 27, 27), \ + [_name##_##12] = REG_FIELD(_offset, 28, 28), \ + [_name##_##13] = REG_FIELD(_offset, 29, 29), \ + [_name##_##14] = REG_FIELD(_offset, 30, 30), \ + [_name##_##15] = REG_FIELD(_offset, 31, 31) + +/* + * reg_field IDs to use as an index into an array + * If you change the order of the entries, check the devm_regmap_field_alloc() + * calls in init_common() + */ enum regfield_ids { /* ----- SROT ------ */ /* HW_VER */ - VER_MAJOR = 0, + VER_MAJOR, VER_MINOR, VER_STEP, /* CTRL_OFFSET */ - TSENS_EN = 3, + TSENS_EN, TSENS_SW_RST, SENSOR_EN, CODE_OR_TEMP, /* ----- TM ------ */ + /* TRDY */ + TRDY, + /* INTERRUPT ENABLE */ + INT_EN, /* v2+ has separate enables for crit, upper and lower irq */ /* STATUS */ - LAST_TEMP_0 = 7, /* Last temperature reading */ + LAST_TEMP_0, /* Last temperature reading */ LAST_TEMP_1, LAST_TEMP_2, LAST_TEMP_3, @@ -131,7 +182,7 @@ enum regfield_ids { LAST_TEMP_13, LAST_TEMP_14, LAST_TEMP_15, - VALID_0 = 23, /* VALID reading or not */ + VALID_0, /* VALID reading or not */ VALID_1, VALID_2, VALID_3, @@ -147,38 +198,6 @@ enum regfield_ids { VALID_13, VALID_14, VALID_15, - MIN_STATUS_0, /* MIN threshold violated */ - MIN_STATUS_1, - MIN_STATUS_2, - MIN_STATUS_3, - MIN_STATUS_4, - MIN_STATUS_5, - MIN_STATUS_6, - MIN_STATUS_7, - MIN_STATUS_8, - MIN_STATUS_9, - MIN_STATUS_10, - MIN_STATUS_11, - MIN_STATUS_12, - MIN_STATUS_13, - MIN_STATUS_14, - MIN_STATUS_15, - MAX_STATUS_0, /* MAX threshold violated */ - MAX_STATUS_1, - MAX_STATUS_2, - MAX_STATUS_3, - MAX_STATUS_4, - MAX_STATUS_5, - MAX_STATUS_6, - MAX_STATUS_7, - MAX_STATUS_8, - MAX_STATUS_9, - MAX_STATUS_10, - MAX_STATUS_11, - MAX_STATUS_12, - MAX_STATUS_13, - MAX_STATUS_14, - MAX_STATUS_15, LOWER_STATUS_0, /* LOWER threshold violated */ LOWER_STATUS_1, LOWER_STATUS_2, @@ -195,6 +214,70 @@ enum regfield_ids { LOWER_STATUS_13, LOWER_STATUS_14, LOWER_STATUS_15, + LOW_INT_STATUS_0, /* LOWER interrupt status */ + LOW_INT_STATUS_1, + LOW_INT_STATUS_2, + LOW_INT_STATUS_3, + LOW_INT_STATUS_4, + LOW_INT_STATUS_5, + LOW_INT_STATUS_6, + LOW_INT_STATUS_7, + LOW_INT_STATUS_8, + LOW_INT_STATUS_9, + LOW_INT_STATUS_10, + LOW_INT_STATUS_11, + LOW_INT_STATUS_12, + LOW_INT_STATUS_13, + LOW_INT_STATUS_14, + LOW_INT_STATUS_15, + LOW_INT_CLEAR_0, /* LOWER interrupt clear */ + LOW_INT_CLEAR_1, + LOW_INT_CLEAR_2, + LOW_INT_CLEAR_3, + LOW_INT_CLEAR_4, + LOW_INT_CLEAR_5, + LOW_INT_CLEAR_6, + LOW_INT_CLEAR_7, + LOW_INT_CLEAR_8, + LOW_INT_CLEAR_9, + LOW_INT_CLEAR_10, + LOW_INT_CLEAR_11, + LOW_INT_CLEAR_12, + LOW_INT_CLEAR_13, + LOW_INT_CLEAR_14, + LOW_INT_CLEAR_15, + LOW_INT_MASK_0, /* LOWER interrupt mask */ + LOW_INT_MASK_1, + LOW_INT_MASK_2, + LOW_INT_MASK_3, + LOW_INT_MASK_4, + LOW_INT_MASK_5, + LOW_INT_MASK_6, + LOW_INT_MASK_7, + LOW_INT_MASK_8, + LOW_INT_MASK_9, + LOW_INT_MASK_10, + LOW_INT_MASK_11, + LOW_INT_MASK_12, + LOW_INT_MASK_13, + LOW_INT_MASK_14, + LOW_INT_MASK_15, + LOW_THRESH_0, /* LOWER threshold values */ + LOW_THRESH_1, + LOW_THRESH_2, + LOW_THRESH_3, + LOW_THRESH_4, + LOW_THRESH_5, + LOW_THRESH_6, + LOW_THRESH_7, + LOW_THRESH_8, + LOW_THRESH_9, + LOW_THRESH_10, + LOW_THRESH_11, + LOW_THRESH_12, + LOW_THRESH_13, + LOW_THRESH_14, + LOW_THRESH_15, UPPER_STATUS_0, /* UPPER threshold violated */ UPPER_STATUS_1, UPPER_STATUS_2, @@ -211,6 +294,70 @@ enum regfield_ids { UPPER_STATUS_13, UPPER_STATUS_14, UPPER_STATUS_15, + UP_INT_STATUS_0, /* UPPER interrupt status */ + UP_INT_STATUS_1, + UP_INT_STATUS_2, + UP_INT_STATUS_3, + UP_INT_STATUS_4, + UP_INT_STATUS_5, + UP_INT_STATUS_6, + UP_INT_STATUS_7, + UP_INT_STATUS_8, + UP_INT_STATUS_9, + UP_INT_STATUS_10, + UP_INT_STATUS_11, + UP_INT_STATUS_12, + UP_INT_STATUS_13, + UP_INT_STATUS_14, + UP_INT_STATUS_15, + UP_INT_CLEAR_0, /* UPPER interrupt clear */ + UP_INT_CLEAR_1, + UP_INT_CLEAR_2, + UP_INT_CLEAR_3, + UP_INT_CLEAR_4, + UP_INT_CLEAR_5, + UP_INT_CLEAR_6, + UP_INT_CLEAR_7, + UP_INT_CLEAR_8, + UP_INT_CLEAR_9, + UP_INT_CLEAR_10, + UP_INT_CLEAR_11, + UP_INT_CLEAR_12, + UP_INT_CLEAR_13, + UP_INT_CLEAR_14, + UP_INT_CLEAR_15, + UP_INT_MASK_0, /* UPPER interrupt mask */ + UP_INT_MASK_1, + UP_INT_MASK_2, + UP_INT_MASK_3, + UP_INT_MASK_4, + UP_INT_MASK_5, + UP_INT_MASK_6, + UP_INT_MASK_7, + UP_INT_MASK_8, + UP_INT_MASK_9, + UP_INT_MASK_10, + UP_INT_MASK_11, + UP_INT_MASK_12, + UP_INT_MASK_13, + UP_INT_MASK_14, + UP_INT_MASK_15, + UP_THRESH_0, /* UPPER threshold values */ + UP_THRESH_1, + UP_THRESH_2, + UP_THRESH_3, + UP_THRESH_4, + UP_THRESH_5, + UP_THRESH_6, + UP_THRESH_7, + UP_THRESH_8, + UP_THRESH_9, + UP_THRESH_10, + UP_THRESH_11, + UP_THRESH_12, + UP_THRESH_13, + UP_THRESH_14, + UP_THRESH_15, CRITICAL_STATUS_0, /* CRITICAL threshold violated */ CRITICAL_STATUS_1, CRITICAL_STATUS_2, @@ -227,13 +374,38 @@ enum regfield_ids { CRITICAL_STATUS_13, CRITICAL_STATUS_14, CRITICAL_STATUS_15, - /* TRDY */ - TRDY, - /* INTERRUPT ENABLE */ - INT_EN, /* Pre-V1, V1.x */ - LOW_INT_EN, /* V2.x */ - UP_INT_EN, /* V2.x */ - CRIT_INT_EN, /* V2.x */ + MIN_STATUS_0, /* MIN threshold violated */ + MIN_STATUS_1, + MIN_STATUS_2, + MIN_STATUS_3, + MIN_STATUS_4, + MIN_STATUS_5, + MIN_STATUS_6, + MIN_STATUS_7, + MIN_STATUS_8, + MIN_STATUS_9, + MIN_STATUS_10, + MIN_STATUS_11, + MIN_STATUS_12, + MIN_STATUS_13, + MIN_STATUS_14, + MIN_STATUS_15, + MAX_STATUS_0, /* MAX threshold violated */ + MAX_STATUS_1, + MAX_STATUS_2, + MAX_STATUS_3, + MAX_STATUS_4, + MAX_STATUS_5, + MAX_STATUS_6, + MAX_STATUS_7, + MAX_STATUS_8, + MAX_STATUS_9, + MAX_STATUS_10, + MAX_STATUS_11, + MAX_STATUS_12, + MAX_STATUS_13, + MAX_STATUS_14, + MAX_STATUS_15, /* Keep last */ MAX_REGFIELDS @@ -303,6 +475,10 @@ struct tsens_priv { struct regmap *tm_map; struct regmap *srot_map; u32 tm_offset; + + /* lock for upper/lower threshold interrupts */ + spinlock_t ul_lock; + struct regmap_field *rf[MAX_REGFIELDS]; struct tsens_context ctx; const struct tsens_features *feat; @@ -320,6 +496,10 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mo int init_common(struct tsens_priv *priv); int get_temp_tsens_valid(struct tsens_sensor *s, int *temp); int get_temp_common(struct tsens_sensor *s, int *temp); +int tsens_enable_irq(struct tsens_priv *priv); +void tsens_disable_irq(struct tsens_priv *priv); +int tsens_set_trips(void *_sensor, int low, int high); +irqreturn_t tsens_irq_thread(int irq, void *data); /* TSENS target */ extern const struct tsens_plat_data data_8960;