From patchwork Fri Jul 1 14:58:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhupesh Sharma X-Patchwork-Id: 12903505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E24A7CCA479 for ; Fri, 1 Jul 2022 14:58:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232086AbiGAO6i (ORCPT ); Fri, 1 Jul 2022 10:58:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231745AbiGAO6i (ORCPT ); Fri, 1 Jul 2022 10:58:38 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CA3D205FD for ; Fri, 1 Jul 2022 07:58:37 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id m14-20020a17090a668e00b001ee6ece8368so6657302pjj.3 for ; Fri, 01 Jul 2022 07:58:37 -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 :mime-version:content-transfer-encoding; bh=y95vOAUApepxdfAS6VCO8MeeZD3qR/4xU+0HXt3Q4Pc=; b=PPFEpDRgJRyElvbUXlO/CnhqMUwwV6Pghk11+qPIMMwowcfexUKv1oBSm+0QMl0b+z 1mBEJl2l9TgFiWvEbf/4+Yml6MWZPUmdTS60wjdzprIlHD7sQBY1YrNgYWB2QGALg/A/ p5OljYAFccl9U8043eE/E1ZZpiB4IAL24N11Dhhmp0JaSAZXAOHVHB4wLVFzOj2v+JG9 X4EZJ7P/+PWxsKEcZzf4pnS3DIfR4keP0jq5L9gPs2L9kbn5KzJkfsVXpO0/i9CGtjVX 9L7k5lcgmICyR8vbzJOIqPnmJyrekapLcjPTlSUI72UJ2CgKrW/+hBm8oMAOCPwDDmVH LgEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=y95vOAUApepxdfAS6VCO8MeeZD3qR/4xU+0HXt3Q4Pc=; b=ywB28dWlKJlzg9KVfpPUXELqDYy5AVPpFTL60dGCSftFCO9hNurXpGT/tNs5U0/pbv bnGBl9BchYm1T5iuFwGtGCi3R8wsB5nBmWGQlwXnyX9RQr+O6L6deX3yFqk3K6v+yQBM zVjkLaLnxOWBo1deX3D2JRnoYoudv5nFpviKYR4GMzLflnwn8HjpsZ83WEitRgbQZGwX Kl8LsMpvpnTsue7I4lNbC0hN+3e7FfpdLxHClCwx9cJMDD5Mz4Bcm7CJ//jLm05q/Sqp TZw+cM6GF4cBHXoqoMGZ6QVH97dvPB7InEv0DvDKzE+UoLknWyzn92Iffv/6fXkMam4V LcuQ== X-Gm-Message-State: AJIora/cRB8suDnMFbqVKpDIqc713n0Jcq+MYbjXkqyFggp+i4Owo5ZS SVYFaWV+60JupLuqT29hgM2jlg== X-Google-Smtp-Source: AGRyM1vzmrIzZf2BDabs1hjTuSEkiX8S8C1+x6OgqG+TemmvKKhNYWXUJxztzdTtoCkW8xbq3wQfsg== X-Received: by 2002:a17:90a:f8c2:b0:1ec:d690:a269 with SMTP id l2-20020a17090af8c200b001ecd690a269mr17108875pjd.190.1656687516832; Fri, 01 Jul 2022 07:58:36 -0700 (PDT) Received: from localhost.localdomain ([2401:4900:1c5e:e6c0:8e75:c988:f80f:8bec]) by smtp.gmail.com with ESMTPSA id y19-20020a170902e19300b0016b844cd7e9sm9641399pla.115.2022.07.01.07.58.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Jul 2022 07:58:36 -0700 (PDT) From: Bhupesh Sharma To: linux-pm@vger.kernel.org Cc: bhupesh.sharma@linaro.org, bhupesh.linux@gmail.com, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, Amit Kucheria , Thara Gopinath , linux-arm-msm@vger.kernel.org Subject: [PATCH 1/3] firmware: qcom_scm: Add support for tsens reinit workaround Date: Fri, 1 Jul 2022 20:28:13 +0530 Message-Id: <20220701145815.2037993-2-bhupesh.sharma@linaro.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> References: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Some versions of QCoM tsens controller might enter a 'bad state' while running stability tests causing sensor temperatures/interrupts status to be in an 'invalid' state. It is recommended to re-initialize the tsens controller via trustzone (secure registers) using scm call(s) when that happens. Add support for the same in the qcom_scm driver. Cc: Amit Kucheria Cc: Thara Gopinath Cc: linux-pm@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Bhupesh Sharma --- drivers/firmware/qcom_scm.c | 17 +++++++++++++++++ drivers/firmware/qcom_scm.h | 4 ++++ include/linux/qcom_scm.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 3163660fa8e2..0bc7cc466218 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -796,6 +796,23 @@ int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size, } EXPORT_SYMBOL(qcom_scm_mem_protect_video_var); +int qcom_scm_tsens_reinit(int *tsens_ret) +{ + unsigned int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_TSENS, + .cmd = QCOM_SCM_TSENS_INIT_ID, + }; + struct qcom_scm_res res; + + ret = qcom_scm_call(__scm->dev, &desc, &res); + if (tsens_ret) + *tsens_ret = res.result[0]; + + return ret; +} +EXPORT_SYMBOL(qcom_scm_tsens_reinit); + static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, size_t mem_sz, phys_addr_t src, size_t src_sz, phys_addr_t dest, size_t dest_sz) diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 0d51eef2472f..495fa00230c7 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -94,6 +94,10 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 #define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a +/* TSENS Services and Function IDs */ +#define QCOM_SCM_SVC_TSENS 0x1E +#define QCOM_SCM_TSENS_INIT_ID 0x5 + #define QCOM_SCM_SVC_IO 0x05 #define QCOM_SCM_IO_READ 0x01 #define QCOM_SCM_IO_WRITE 0x02 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index f8335644a01a..f8c9eb739df1 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -124,4 +124,6 @@ extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val, extern int qcom_scm_lmh_profile_change(u32 profile_id); extern bool qcom_scm_lmh_dcvsh_available(void); +extern int qcom_scm_tsens_reinit(int *tsens_ret); + #endif From patchwork Fri Jul 1 14:58:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhupesh Sharma X-Patchwork-Id: 12903506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 419E4CCA479 for ; Fri, 1 Jul 2022 14:58:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232615AbiGAO6n (ORCPT ); Fri, 1 Jul 2022 10:58:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232302AbiGAO6l (ORCPT ); Fri, 1 Jul 2022 10:58:41 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF54922B3A for ; Fri, 1 Jul 2022 07:58:40 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id c4so2599021plc.8 for ; Fri, 01 Jul 2022 07:58:40 -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 :mime-version:content-transfer-encoding; bh=9QtXv+dZtlgm6HhECfGhA6Ldyd18a0f5mRfAQaK65pM=; b=NChGv5zKePfICEsTb+zLWaxX0nFbB09r45Fa20a8VG8xqbvcm+3emPJxopN9k43Ty2 kqW5kpngN1dYSuhrSzIKtyzZSoHtVbjYygHD0YRlmcoEph6T9QPaYtWHuUwEum+0MG1i 5irl0mYhfZOYiX5lM4xLsBRqegnqvjPEg2NPqU632Hd25Sa4yQMRb2TTKbAiVA8Tn1tS czTOq66dANxKtxxnZ+EmngkKQNBTUejSBiXexJNeLnkcDUyCopQS5xGPxpb8I3LI4d+b p0fv7kMHBSlZCm+vWF242RN/L1iK9Sn91wvErlCvnlZlkAvm8DHO01hV3IdysyUa3crH aT6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9QtXv+dZtlgm6HhECfGhA6Ldyd18a0f5mRfAQaK65pM=; b=kEuBVzxQdXQ67lpKhH258baavO5fRihrDcc2b9MbkEzKv/MB6xZBdBxDvmVDRT/AKz aNw433XQXcJKnWVMJQBJeYwFAlYOj54UDtKD0H4OpjuL+GzH0F1O4iwjsUlNsT8r0TGZ TSypOANxzq3JRuE99pCSlys44cdO01mGHlRiAUQBTbjEf4P0PFZIToGbYE5U4nNNvm7a HWpIUHWy3CEL+TQsxNp9J7vpeLAkqH+n3WJolZOzirt/VMFm2HD6xFeIARITI2chTJ+b uSrHf+s7yn1Txa5dEoyrgJ+/uSAJXno6zEUOId0KUaggFA20okPBQo0G9/ZR8YqCQO4a g5dg== X-Gm-Message-State: AJIora9r4Vq0re1mL2nyefR8iRotNo6Qyc8T975uj4Zq7WNSrGEG6yps Xy6gVi5yp9TC0ReZp0Uh6wcRiQ== X-Google-Smtp-Source: AGRyM1uNr5BumNBOeW2BsNpLv3/vyY1Q7Vs22yHhwqqQqPUV5TmuVwRJfKY3ueLUMALMScd3oss+9g== X-Received: by 2002:a17:902:d411:b0:169:2eb:1b79 with SMTP id b17-20020a170902d41100b0016902eb1b79mr21586757ple.61.1656687520229; Fri, 01 Jul 2022 07:58:40 -0700 (PDT) Received: from localhost.localdomain ([2401:4900:1c5e:e6c0:8e75:c988:f80f:8bec]) by smtp.gmail.com with ESMTPSA id y19-20020a170902e19300b0016b844cd7e9sm9641399pla.115.2022.07.01.07.58.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Jul 2022 07:58:39 -0700 (PDT) From: Bhupesh Sharma To: linux-pm@vger.kernel.org Cc: bhupesh.sharma@linaro.org, bhupesh.linux@gmail.com, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, Amit Kucheria , Thara Gopinath , linux-arm-msm@vger.kernel.org Subject: [PATCH 2/3] thermal: qcom: tsens: Add support for 'needs_reinit_wa' for sm8150 Date: Fri, 1 Jul 2022 20:28:14 +0530 Message-Id: <20220701145815.2037993-3-bhupesh.sharma@linaro.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> References: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org QCoM sm8150 tsens controller might require re-initialization via trustzone [via scm call(s)] when it enters a 'bad state' causing sensor temperatures/interrupts status to be in an 'invalid' state. Add hooks for the same in the qcom tsens driver which can be used by followup patch(es). Cc: Amit Kucheria Cc: Thara Gopinath Cc: linux-pm@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Bhupesh Sharma --- drivers/thermal/qcom/tsens-v2.c | 11 +++++++++++ drivers/thermal/qcom/tsens.c | 4 ++++ drivers/thermal/qcom/tsens.h | 6 +++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index b293ed32174b..61d38a56d29a 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -101,6 +101,17 @@ struct tsens_plat_data data_tsens_v2 = { .fields = tsens_v2_regfields, }; +/* For sm8150 tsens, its suggested to monitor the controller health + * periodically and in case an issue is detected to reinit tsens + * controller via trustzone. + */ +struct tsens_plat_data data_tsens_sm8150 = { + .ops = &ops_generic_v2, + .feat = &tsens_v2_feat, + .needs_reinit_wa = true, + .fields = tsens_v2_regfields, +}; + /* Kept around for backward compatibility with old msm8996.dtsi */ struct tsens_plat_data data_8996 = { .num_sensors = 13, diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 7963ee33bf75..97f4d4454f20 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -991,6 +991,9 @@ static const struct of_device_id tsens_table[] = { }, { .compatible = "qcom,msm8996-tsens", .data = &data_8996, + }, { + .compatible = "qcom,sm8150-tsens", + .data = &data_tsens_sm8150, }, { .compatible = "qcom,tsens-v1", .data = &data_tsens_v1, @@ -1135,6 +1138,7 @@ static int tsens_probe(struct platform_device *pdev) priv->dev = dev; priv->num_sensors = num_sensors; + priv->needs_reinit_wa = data->needs_reinit_wa; priv->ops = data->ops; for (i = 0; i < priv->num_sensors; i++) { if (data->hw_ids) diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 1471a2c00f15..48a7bda902c1 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -515,6 +515,7 @@ struct tsens_features { * @num_sensors: Number of sensors supported by platform * @ops: operations the tsens instance supports * @hw_ids: Subset of sensors ids supported by platform, if not the first n + * @needs_reinit_wa: tsens controller might need reinit via trustzone * @feat: features of the IP * @fields: bitfield locations */ @@ -522,6 +523,7 @@ struct tsens_plat_data { const u32 num_sensors; const struct tsens_ops *ops; unsigned int *hw_ids; + bool needs_reinit_wa; struct tsens_features *feat; const struct reg_field *fields; }; @@ -544,6 +546,7 @@ struct tsens_context { * @srot_map: pointer to SROT register address space * @tm_offset: deal with old device trees that don't address TM and SROT * address space separately + * @needs_reinit_wa: tsens controller might need reinit via trustzone * @ul_lock: lock while processing upper/lower threshold interrupts * @crit_lock: lock while processing critical threshold interrupts * @rf: array of regmap_fields used to store value of the field @@ -561,6 +564,7 @@ struct tsens_priv { struct regmap *tm_map; struct regmap *srot_map; u32 tm_offset; + bool needs_reinit_wa; /* lock for upper/lower threshold interrupts */ spinlock_t ul_lock; @@ -593,6 +597,6 @@ extern struct tsens_plat_data data_8916, data_8939, data_8974, data_9607; extern struct tsens_plat_data data_tsens_v1, data_8976; /* TSENS v2 targets */ -extern struct tsens_plat_data data_8996, data_tsens_v2; +extern struct tsens_plat_data data_8996, data_tsens_sm8150, data_tsens_v2; #endif /* __QCOM_TSENS_H__ */ From patchwork Fri Jul 1 14:58:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhupesh Sharma X-Patchwork-Id: 12903507 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D9ABC43334 for ; Fri, 1 Jul 2022 14:58:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233108AbiGAO64 (ORCPT ); Fri, 1 Jul 2022 10:58:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230272AbiGAO6p (ORCPT ); Fri, 1 Jul 2022 10:58:45 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBF2C22B1A for ; Fri, 1 Jul 2022 07:58:43 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id k14so2618105plh.4 for ; Fri, 01 Jul 2022 07:58:43 -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 :mime-version:content-transfer-encoding; bh=3hIdc06536EvjjLsoqRfohQ/ZCe/C8j+YPNHn85t6hM=; b=q7HWIMZvh60Apx4LQTpxKWOE9Dj+2VLr/WjgoxYJVQbxtAfKniIJTNEZOGBor5b259 to2xcpGKJOZ0WGpGDFVMUxBOuVKQm7bUqIfLBDIjEfUaMLBHpFiN6HVsV+oiBWKiCFgC E32Zvk8/w9QPCrCyO6DpQTJXvk8NyecUo9YL99/bfUHVdSJZEDyO5DpCXbi99M7L2e47 5zzSIFD3IugLHDmSYp/kd0jL0KtZUgaQSJXFZ/XTQ8A/65Gb1IYzlIDOptJMJsYoHdth mHQDKE6CfqOtDiYqgIR/MAXo78FpHFsQW79CHleg9mDB+t60loU86Lr8t0yxm3acjY/U 0+1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3hIdc06536EvjjLsoqRfohQ/ZCe/C8j+YPNHn85t6hM=; b=77NUlWQLL8cVoIcj56DdnWftiAcUNwtHUZfQhQLVYBMMf9jH6Lt017o6UOcvgLKKjE bQtN3/9DaTVfXz42a+jkWBj3VhGizd7LMmoZo60ZYsmwSmJtV8jlOSwy8fro1rIS6C5P hbJNCTNLbcfIA9Xs+Bz9zihdDSQAFDszh0TQ8CGT4ylEBBLiy+idUBgzaFoChfRBOfXt aikduQKuaMY/jETHI5+GZ/6nZ37p3ZHXRQosKjCeozeZH7N2IX1zW33htSZqtJEVj7Ev 1bvciiNd8hyR8D52xvvsVWa9JVZQTe+GtcjqpisuBMfwkXpgkK2sqbVBlhVlK5ft5F1e 6drg== X-Gm-Message-State: AJIora/HiY8lsYBkgwWpMeOOjH66FeoNuiRjzPx+fgDpw41opMxU7kVM lDpo5ANmQj+FLO5minsXVytGkQ== X-Google-Smtp-Source: AGRyM1s6jUyThf3G/awD0LL8w9JOibyTggJ9r61XRVP4tSdpRtCH7ARM7+JuOcI1IOzbj56ZpQuUNg== X-Received: by 2002:a17:90b:33cc:b0:1ec:b279:69fa with SMTP id lk12-20020a17090b33cc00b001ecb27969famr19551091pjb.70.1656687523352; Fri, 01 Jul 2022 07:58:43 -0700 (PDT) Received: from localhost.localdomain ([2401:4900:1c5e:e6c0:8e75:c988:f80f:8bec]) by smtp.gmail.com with ESMTPSA id y19-20020a170902e19300b0016b844cd7e9sm9641399pla.115.2022.07.01.07.58.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Jul 2022 07:58:43 -0700 (PDT) From: Bhupesh Sharma To: linux-pm@vger.kernel.org Cc: bhupesh.sharma@linaro.org, bhupesh.linux@gmail.com, linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org, Amit Kucheria , Thara Gopinath , linux-arm-msm@vger.kernel.org Subject: [PATCH 3/3] thermal: qcom: tsens: Implement re-initialization workaround quirk Date: Fri, 1 Jul 2022 20:28:15 +0530 Message-Id: <20220701145815.2037993-4-bhupesh.sharma@linaro.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> References: <20220701145815.2037993-1-bhupesh.sharma@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Since for some QCoM tsens controllers, its suggested to monitor the controller health periodically and in case an issue is detected, to re-initialize the tsens controller via trustzone, add the support for the same in the qcom tsens driver. Note that Once the tsens controller is reset using scm call, all SROT and TM region registers will enter the reset mode. While all the SROT registers will be re-programmed and re-enabled in trustzone prior to the scm call exit, the TM region registers will not re-initialized in trustzone and thus need to be handled by the tsens driver. Cc: Amit Kucheria Cc: Thara Gopinath Cc: linux-pm@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org Signed-off-by: Bhupesh Sharma Reported-by: kernel test robot --- drivers/thermal/qcom/tsens-v2.c | 3 + drivers/thermal/qcom/tsens.c | 237 +++++++++++++++++++++++++++++++- drivers/thermal/qcom/tsens.h | 6 + 3 files changed, 239 insertions(+), 7 deletions(-) diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c index 61d38a56d29a..9bb542f16482 100644 --- a/drivers/thermal/qcom/tsens-v2.c +++ b/drivers/thermal/qcom/tsens-v2.c @@ -88,6 +88,9 @@ static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { /* TRDY: 1=ready, 0=in progress */ [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), + + /* FIRST_ROUND_COMPLETE: 1=complete, 0=not complete */ + [FIRST_ROUND_COMPLETE] = REG_FIELD(TM_TRDY_OFF, 3, 3), }; static const struct tsens_ops ops_generic_v2 = { diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 97f4d4454f20..28d42ae0eb47 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,8 @@ #include "../thermal_hwmon.h" #include "tsens.h" +LIST_HEAD(tsens_device_list); + /** * struct tsens_irq_data - IRQ status and temperature violations * @up_viol: upper threshold violated @@ -594,19 +597,159 @@ static void tsens_disable_irq(struct tsens_priv *priv) regmap_field_write(priv->rf[INT_EN], 0); } +static int tsens_reenable_hw_after_scm(struct tsens_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->ul_lock, flags); + + /* Re-enable watchdog, unmask the bark and + * disable cycle completion monitoring. + */ + regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 1); + regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 0); + regmap_field_write(priv->rf[WDOG_BARK_MASK], 0); + regmap_field_write(priv->rf[CC_MON_MASK], 1); + + /* Re-enable interrupts */ + tsens_enable_irq(priv); + + spin_unlock_irqrestore(&priv->ul_lock, flags); + + return 0; +} + int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp) { - struct tsens_priv *priv = s->priv; + struct tsens_priv *priv = s->priv, *priv_reinit; int hw_id = s->hw_id; u32 temp_idx = LAST_TEMP_0 + hw_id; u32 valid_idx = VALID_0 + hw_id; u32 valid; - int ret; + int ret, trdy, first_round, tsens_ret, sw_reg; + unsigned long timeout; + static atomic_t in_tsens_reinit; /* VER_0 doesn't have VALID bit */ if (tsens_version(priv) == VER_0) goto get_temp; + /* For some tsens controllers, its suggested to + * monitor the controller health periodically + * and in case an issue is detected to reinit + * tsens controller via trustzone. + */ + if (priv->needs_reinit_wa) { + /* First check if TRDY is SET */ + timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); + do { + ret = regmap_field_read(priv->rf[TRDY], &trdy); + if (ret) + goto err; + if (!trdy) + continue; + } while (time_before(jiffies, timeout)); + + if (!trdy) { + ret = regmap_field_read(priv->rf[FIRST_ROUND_COMPLETE], &first_round); + if (ret) + goto err; + + if (!first_round) { + if (atomic_read(&in_tsens_reinit)) { + dev_dbg(priv->dev, "tsens re-init is in progress\n"); + ret = -EAGAIN; + goto err; + } + + /* Wait for 2 ms for tsens controller to recover */ + timeout = jiffies + msecs_to_jiffies(RESET_TIMEOUT_MS); + do { + ret = regmap_field_read(priv->rf[FIRST_ROUND_COMPLETE], + &first_round); + if (ret) + goto err; + + if (first_round) { + dev_dbg(priv->dev, "tsens controller recovered\n"); + goto sensor_read; + } + } while (time_before(jiffies, timeout)); + + /* + * tsens controller did not recover, + * proceed with SCM call to re-init it + */ + if (atomic_read(&in_tsens_reinit)) { + dev_dbg(priv->dev, "tsens re-init is in progress\n"); + ret = -EAGAIN; + goto err; + } + + atomic_set(&in_tsens_reinit, 1); + + /* + * Invoke scm call only if SW register write is + * reflecting in controller. Try it for 2 ms. + */ + timeout = jiffies + msecs_to_jiffies(RESET_TIMEOUT_MS); + do { + ret = regmap_field_write(priv->rf[INT_EN], BIT(2)); + if (ret) + goto err_unset; + + ret = regmap_field_read(priv->rf[INT_EN], &sw_reg); + if (ret) + goto err_unset; + + if (!(sw_reg & BIT(2))) + continue; + } while (time_before(jiffies, timeout)); + + if (!(sw_reg & BIT(2))) { + ret = -ENOTRECOVERABLE; + goto err_unset; + } + + ret = qcom_scm_tsens_reinit(&tsens_ret); + if (ret || tsens_ret) { + dev_err(priv->dev, "tsens reinit scm call failed (%d : %d)\n", + ret, tsens_ret); + if (tsens_ret) + ret = -ENOTRECOVERABLE; + + goto err_unset; + } + + /* After the SCM call, we need to re-enable + * the interrupts and also set active threshold + * for each sensor. + */ + list_for_each_entry(priv_reinit, + &tsens_device_list, list) { + ret = tsens_reenable_hw_after_scm(priv_reinit); + if (ret) { + dev_err(priv->dev, + "tsens re-enable after scm call failed (%d)\n", + ret); + ret = -ENOTRECOVERABLE; + goto err_unset; + } + } + + atomic_set(&in_tsens_reinit, 0); + + /* Notify reinit wa worker */ + list_for_each_entry(priv_reinit, + &tsens_device_list, list) { + queue_work(priv_reinit->reinit_wa_worker, + &priv_reinit->reinit_wa_notify); + } + } + } + } + +sensor_read: /* Valid bit is 0 for 6 AHB clock cycles. * At 19.2MHz, 1 AHB clock is ~60ns. * We should enter this loop very, very rarely. @@ -623,6 +766,12 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp) *temp = tsens_hw_to_mC(s, temp_idx); return 0; + +err_unset: + atomic_set(&in_tsens_reinit, 0); + +err: + return ret; } int get_temp_common(const struct tsens_sensor *s, int *temp) @@ -860,6 +1009,14 @@ int __init init_common(struct tsens_priv *priv) goto err_put_device; } + priv->rf[FIRST_ROUND_COMPLETE] = devm_regmap_field_alloc(dev, + priv->tm_map, + priv->fields[FIRST_ROUND_COMPLETE]); + if (IS_ERR(priv->rf[FIRST_ROUND_COMPLETE])) { + ret = PTR_ERR(priv->rf[FIRST_ROUND_COMPLETE]); + 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++) { @@ -1097,6 +1254,43 @@ static int tsens_register(struct tsens_priv *priv) return ret; } +static void tsens_reinit_worker_notify(struct work_struct *work) +{ + int i, ret, temp; + struct tsens_irq_data d; + struct tsens_priv *priv = container_of(work, struct tsens_priv, + reinit_wa_notify); + + for (i = 0; i < priv->num_sensors; i++) { + const struct tsens_sensor *s = &priv->sensor[i]; + u32 hw_id = s->hw_id; + + if (!s->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; + } + + tsens_read_irq_state(priv, hw_id, s, &d); + + if ((d.up_thresh < temp) || (d.low_thresh > temp)) { + dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", + hw_id, __func__, temp); + thermal_zone_device_update(s->tzd, + THERMAL_EVENT_UNSPECIFIED); + } else { + dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", + hw_id, __func__, temp); + } + } +} + static int tsens_probe(struct platform_device *pdev) { int ret, i; @@ -1139,6 +1333,19 @@ static int tsens_probe(struct platform_device *pdev) priv->dev = dev; priv->num_sensors = num_sensors; priv->needs_reinit_wa = data->needs_reinit_wa; + + if (priv->needs_reinit_wa && !qcom_scm_is_available()) + return -EPROBE_DEFER; + + if (priv->needs_reinit_wa) { + priv->reinit_wa_worker = alloc_workqueue("tsens_reinit_work", + WQ_HIGHPRI, 0); + if (!priv->reinit_wa_worker) + return -ENOMEM; + + INIT_WORK(&priv->reinit_wa_notify, tsens_reinit_worker_notify); + } + priv->ops = data->ops; for (i = 0; i < priv->num_sensors; i++) { if (data->hw_ids) @@ -1151,13 +1358,15 @@ static int tsens_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - if (!priv->ops || !priv->ops->init || !priv->ops->get_temp) - return -EINVAL; + if (!priv->ops || !priv->ops->init || !priv->ops->get_temp) { + ret = -EINVAL; + goto free_wq; + } ret = priv->ops->init(priv); if (ret < 0) { dev_err(dev, "%s: init failed\n", __func__); - return ret; + goto free_wq; } if (priv->ops->calibrate) { @@ -1165,11 +1374,23 @@ static int tsens_probe(struct platform_device *pdev) if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "%s: calibration failed\n", __func__); - return ret; + + goto free_wq; } } - return tsens_register(priv); + ret = tsens_register(priv); + if (ret < 0) { + dev_err(dev, "%s: registration failed\n", __func__); + goto free_wq; + } + + list_add_tail(&priv->list, &tsens_device_list); + return 0; + +free_wq: + destroy_workqueue(priv->reinit_wa_worker); + return ret; } static int tsens_remove(struct platform_device *pdev) @@ -1181,6 +1402,8 @@ static int tsens_remove(struct platform_device *pdev) if (priv->ops->disable) priv->ops->disable(priv); + destroy_workqueue(priv->reinit_wa_worker); + return 0; } diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 48a7bda902c1..c7279a50cf9b 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -14,6 +14,7 @@ #define SLOPE_FACTOR 1000 #define SLOPE_DEFAULT 3200 #define TIMEOUT_US 100 +#define RESET_TIMEOUT_MS 2 #define THRESHOLD_MAX_ADC_CODE 0x3ff #define THRESHOLD_MIN_ADC_CODE 0x0 @@ -167,6 +168,7 @@ enum regfield_ids { /* ----- TM ------ */ /* TRDY */ TRDY, + FIRST_ROUND_COMPLETE, /* INTERRUPT ENABLE */ INT_EN, /* v2+ has separate enables for crit, upper and lower irq */ /* STATUS */ @@ -565,6 +567,10 @@ struct tsens_priv { struct regmap *srot_map; u32 tm_offset; bool needs_reinit_wa; + struct workqueue_struct *reinit_wa_worker; + struct work_struct reinit_wa_notify; + + struct list_head list; /* lock for upper/lower threshold interrupts */ spinlock_t ul_lock;