From patchwork Wed Sep 13 11:01:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 9951051 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id ED88A603F4 for ; Wed, 13 Sep 2017 11:02:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0F6828EC0 for ; Wed, 13 Sep 2017 11:02:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D5F7028EEC; Wed, 13 Sep 2017 11:02:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E4A528EEA for ; Wed, 13 Sep 2017 11:02:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751829AbdIMLCA (ORCPT ); Wed, 13 Sep 2017 07:02:00 -0400 Received: from smtp-3.sys.kth.se ([130.237.48.192]:42036 "EHLO smtp-3.sys.kth.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751354AbdIMLB7 (ORCPT ); Wed, 13 Sep 2017 07:01:59 -0400 Received: from smtp-3.sys.kth.se (localhost.localdomain [127.0.0.1]) by smtp-3.sys.kth.se (Postfix) with ESMTP id 86B1636B6; Wed, 13 Sep 2017 13:01:57 +0200 (CEST) X-Virus-Scanned: by amavisd-new at kth.se Received: from smtp-3.sys.kth.se ([127.0.0.1]) by smtp-3.sys.kth.se (smtp-3.sys.kth.se [127.0.0.1]) (amavisd-new, port 10024) with LMTP id MZ-JtfhhIk0e; Wed, 13 Sep 2017 13:01:56 +0200 (CEST) X-KTH-Auth: niso [89.233.230.99] X-KTH-mail-from: niklas.soderlund+renesas@ragnatech.se Received: from bismarck.berto.se (unknown [89.233.230.99]) by smtp-3.sys.kth.se (Postfix) with ESMTPSA id A3D742B13; Wed, 13 Sep 2017 13:01:56 +0200 (CEST) From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= To: linux-pm@vger.kernel.org, Simon Horman , Wolfram Sang Cc: linux-renesas-soc@vger.kernel.org, =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [RFC 1/3] thermal: rcar_gen3_thermal: read calibration from hardware Date: Wed, 13 Sep 2017 13:01:35 +0200 Message-Id: <20170913110137.13490-2-niklas.soderlund+renesas@ragnatech.se> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170913110137.13490-1-niklas.soderlund+renesas@ragnatech.se> References: <20170913110137.13490-1-niklas.soderlund+renesas@ragnatech.se> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In production hardware the calibration values used to convert register values to temperatures can be read from hardware. While pre-production hardware still depends on pseudo values hard-coded in the driver. Add support for reading out calibration values from hardware if it's fused. The presence of fused calibration is indicated in the THSCP register, unfortunately this register where not present in early datasheets. The resource size used in early DT descriptions do not cover this register. This change takes this into account and fallback to the pseudo values if the resource size in DT is to small. Signed-off-by: Niklas Söderlund --- drivers/thermal/rcar_gen3_thermal.c | 70 +++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 528a65b05b304ca3..29d041d79c6856d6 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -43,6 +43,10 @@ #define REG_GEN3_THCODE1 0x50 #define REG_GEN3_THCODE2 0x54 #define REG_GEN3_THCODE3 0x58 +#define REG_GEN3_PTAT1 0x5c +#define REG_GEN3_PTAT2 0x60 +#define REG_GEN3_PTAT3 0x64 +#define REG_GEN3_THSCP 0x68 /* IRQ{STR,MSK,EN} bits */ #define IRQ_TEMP1 BIT(0) @@ -64,6 +68,9 @@ #define THCTR_PONM BIT(6) #define THCTR_THSST BIT(0) +/* THSCP bits */ +#define THSCP_COR_PARA_VLD (BIT(15) | BIT(14)) + #define CTEMP_MASK 0xFFF #define MCELSIUS(temp) ((temp) * 1000) @@ -81,6 +88,7 @@ struct equation_coefs { struct rcar_gen3_thermal_tsc { void __iomem *base; + resource_size_t size; struct thermal_zone_device *zone; struct equation_coefs coef; int low; @@ -284,6 +292,55 @@ static const struct soc_device_attribute r8a7795es1[] = { { /* sentinel */ } }; +static bool rcar_gen3_thermal_update_fuses(struct rcar_gen3_thermal_priv *priv) +{ + int i, ptat[3], thcode[3]; + u32 thscp; + + if (!priv->num_tscs) + return false; + + /* + * If resource size of TSC1 is less then 0x6c0 old DT is used, not + * possible to read all fusees, fallback to pseudo values. + */ + if (priv->tscs[0]->size < 0x6c) + return false; + + /* If fuses are not set, fallback to pseudo values. */ + thscp = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_THSCP); + if ((thscp & THSCP_COR_PARA_VLD) != THSCP_COR_PARA_VLD) + return false; + + /* + * Update the pseudo calibration points with fused values. + * PTAT is shared between all TSC:s but only fused for the first + * TSC while THCODEs are fused for each TSC. + */ + + ptat[0] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT1) & + GEN3_FUSE_MASK; + ptat[1] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT2) & + GEN3_FUSE_MASK; + ptat[2] = rcar_gen3_thermal_read(priv->tscs[0], REG_GEN3_PTAT3) & + GEN3_FUSE_MASK; + + for (i = 0; i < priv->num_tscs; i++) { + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; + + thcode[0] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE1) & + GEN3_FUSE_MASK; + thcode[1] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE2) & + GEN3_FUSE_MASK; + thcode[2] = rcar_gen3_thermal_read(tsc, REG_GEN3_THCODE3) & + GEN3_FUSE_MASK; + + rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode); + } + + return true; +} + static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc) { u32 reg_val; @@ -432,11 +489,22 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(tsc->base); goto error_unregister; } + tsc->size = resource_size(res); priv->tscs[i] = tsc; priv->data->thermal_init(tsc); + rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]); + } + + priv->num_tscs = i; + + if (rcar_gen3_thermal_update_fuses(priv)) + dev_info(dev, "Using fused calibration values\n"); + + for (i = 0; i < priv->num_tscs; i++) { + struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, &rcar_gen3_tz_of_ops); @@ -454,8 +522,6 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret); } - priv->num_tscs = i; - if (!priv->num_tscs) { ret = -ENODEV; goto error_unregister;