All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lad Prabhakar" <prabhakar.mahadev-lad.rj@bp.renesas.com>
To: cip-dev@lists.cip-project.org,
	Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>,
	Pavel Machek <pavel@denx.de>
Cc: Biju Das <biju.das.jz@bp.renesas.com>
Subject: [PATCH 5.10.y-cip 26/29] thermal/drivers: Add TSU driver for RZ/G2L
Date: Mon,  4 Apr 2022 13:35:50 +0100	[thread overview]
Message-ID: <20220404123553.25851-27-prabhakar.mahadev-lad.rj@bp.renesas.com> (raw)
In-Reply-To: <20220404123553.25851-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 673c68bd48390dad01f7d17670de3e33b60860ac upstream.

The RZ/G2L SoC incorporates a thermal sensor unit (TSU) that measures the
temperature inside the LSI.

The thermal sensor in this unit measures temperatures in the range from
−40 degree Celsius to 125 degree Celsius with an accuracy of ±3°C. The
TSU repeats measurement at 20 microseconds intervals and automatically
updates the results of measurement.

The TSU has no interrupts as well as no external pins.

This patch adds Thermal Sensor Unit(TSU) driver for RZ/G2L SoC.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20211130155757.17837-3-biju.das.jz@bp.renesas.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
[PL: Dropped including math.h]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 drivers/thermal/Kconfig         |   9 ++
 drivers/thermal/Makefile        |   1 +
 drivers/thermal/rzg2l_thermal.c | 239 ++++++++++++++++++++++++++++++++
 3 files changed, 249 insertions(+)
 create mode 100644 drivers/thermal/rzg2l_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 7edc8dc6bbab..e51c8cc989d8 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -354,6 +354,15 @@ config RCAR_GEN3_THERMAL
 	  Enable this to plug the R-Car Gen3 or RZ/G2 thermal sensor driver into
 	  the Linux thermal framework.
 
+config RZG2L_THERMAL
+	tristate "Renesas RZ/G2L thermal driver"
+	depends on ARCH_RENESAS || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on OF
+	help
+	  Enable this to plug the RZ/G2L thermal sensor driver into the Linux
+	  thermal framework.
+
 config KIRKWOOD_THERMAL
 	tristate "Temperature sensor on Marvell Kirkwood SoCs"
 	depends on MACH_KIRKWOOD || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index b64dd50a6629..b71f9b88b567 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)	+= rcar_gen3_thermal.o
+obj-$(CONFIG_RZG2L_THERMAL)	+= rzg2l_thermal.o
 obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
 obj-y				+= samsung/
 obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c
new file mode 100644
index 000000000000..46f1134a6987
--- /dev/null
+++ b/drivers/thermal/rzg2l_thermal.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G2L TSU Thermal Sensor Driver
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/thermal.h>
+#include <linux/units.h>
+
+#include "thermal_hwmon.h"
+
+#define CTEMP_MASK	0xFFF
+
+/* default calibration values, if FUSE values are missing */
+#define SW_CALIB0_VAL	3148
+#define SW_CALIB1_VAL	503
+
+/* Register offsets */
+#define TSU_SM		0x00
+#define TSU_ST		0x04
+#define TSU_SAD		0x0C
+#define TSU_SS		0x10
+
+#define OTPTSUTRIM_REG(n)	(0x18 + ((n) * 0x4))
+
+/* Sensor Mode Register(TSU_SM) */
+#define TSU_SM_EN_TS		BIT(0)
+#define TSU_SM_ADC_EN_TS	BIT(1)
+#define TSU_SM_NORMAL_MODE	(TSU_SM_EN_TS | TSU_SM_ADC_EN_TS)
+
+/* TSU_ST bits */
+#define TSU_ST_START		BIT(0)
+
+#define TSU_SS_CONV_RUNNING	BIT(0)
+
+#define TS_CODE_AVE_SCALE(x)	((x) * 1000000)
+#define MCELSIUS(temp)		((temp) * MILLIDEGREE_PER_DEGREE)
+#define TS_CODE_CAP_TIMES	8	/* Capture  times */
+
+#define RZG2L_THERMAL_GRAN	500	/* milli Celsius */
+#define RZG2L_TSU_SS_TIMEOUT_US	1000
+
+#define CURVATURE_CORRECTION_CONST	13
+
+struct rzg2l_thermal_priv {
+	struct device *dev;
+	void __iomem *base;
+	struct thermal_zone_device *zone;
+	struct reset_control *rstc;
+	u32 calib0, calib1;
+};
+
+static inline u32 rzg2l_thermal_read(struct rzg2l_thermal_priv *priv, u32 reg)
+{
+	return ioread32(priv->base + reg);
+}
+
+static inline void rzg2l_thermal_write(struct rzg2l_thermal_priv *priv, u32 reg,
+				       u32 data)
+{
+	iowrite32(data, priv->base + reg);
+}
+
+static int rzg2l_thermal_get_temp(void *devdata, int *temp)
+{
+	struct rzg2l_thermal_priv *priv = devdata;
+	u32 result = 0, dsensor, ts_code_ave;
+	int val, i;
+
+	for (i = 0; i < TS_CODE_CAP_TIMES ; i++) {
+		/* TSU repeats measurement at 20 microseconds intervals and
+		 * automatically updates the results of measurement. As per
+		 * the HW manual for measuring temperature we need to read 8
+		 * values consecutively and then take the average.
+		 * ts_code_ave = (ts_code[0] + ⋯ + ts_code[7]) / 8
+		 */
+		result += rzg2l_thermal_read(priv, TSU_SAD) & CTEMP_MASK;
+		usleep_range(20, 30);
+	}
+
+	ts_code_ave = result / TS_CODE_CAP_TIMES;
+
+	/* Calculate actual sensor value by applying curvature correction formula
+	 * dsensor = ts_code_ave / (1 + ts_code_ave * 0.000013). Here we are doing
+	 * integer calculation by scaling all the values by 1000000.
+	 */
+	dsensor = TS_CODE_AVE_SCALE(ts_code_ave) /
+		(TS_CODE_AVE_SCALE(1) + (ts_code_ave * CURVATURE_CORRECTION_CONST));
+
+	/* The temperature Tj is calculated by the formula
+	 * Tj = (dsensor − calib1) * 165/ (calib0 − calib1) − 40
+	 * where calib0 and calib1 are the caliberation values.
+	 */
+	val = ((dsensor - priv->calib1) * (MCELSIUS(165) /
+		(priv->calib0 - priv->calib1))) - MCELSIUS(40);
+
+	*temp = roundup(val, RZG2L_THERMAL_GRAN);
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops rzg2l_tz_of_ops = {
+	.get_temp = rzg2l_thermal_get_temp,
+};
+
+static int rzg2l_thermal_init(struct rzg2l_thermal_priv *priv)
+{
+	u32 reg_val;
+
+	rzg2l_thermal_write(priv, TSU_SM, TSU_SM_NORMAL_MODE);
+	rzg2l_thermal_write(priv, TSU_ST, 0);
+
+	/* Before setting the START bit, TSU should be in normal operating
+	 * mode. As per the HW manual, it will take 60 µs to place the TSU
+	 * into normal operating mode.
+	 */
+	usleep_range(60, 80);
+
+	reg_val = rzg2l_thermal_read(priv, TSU_ST);
+	reg_val |= TSU_ST_START;
+	rzg2l_thermal_write(priv, TSU_ST, reg_val);
+
+	return readl_poll_timeout(priv->base + TSU_SS, reg_val,
+				  reg_val == TSU_SS_CONV_RUNNING, 50,
+				  RZG2L_TSU_SS_TIMEOUT_US);
+}
+
+static void rzg2l_thermal_reset_assert_pm_disable_put(struct platform_device *pdev)
+{
+	struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	reset_control_assert(priv->rstc);
+}
+
+static int rzg2l_thermal_remove(struct platform_device *pdev)
+{
+	struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	thermal_remove_hwmon_sysfs(priv->zone);
+	rzg2l_thermal_reset_assert_pm_disable_put(pdev);
+
+	return 0;
+}
+
+static int rzg2l_thermal_probe(struct platform_device *pdev)
+{
+	struct thermal_zone_device *zone;
+	struct rzg2l_thermal_priv *priv;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->dev = dev;
+	priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(priv->rstc))
+		return dev_err_probe(dev, PTR_ERR(priv->rstc),
+				     "failed to get cpg reset");
+
+	reset_control_deassert(priv->rstc);
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	priv->calib0 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0));
+	if (!priv->calib0)
+		priv->calib0 = SW_CALIB0_VAL;
+
+	priv->calib1 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(1));
+	if (!priv->calib1)
+		priv->calib1 = SW_CALIB1_VAL;
+
+	platform_set_drvdata(pdev, priv);
+	ret = rzg2l_thermal_init(priv);
+	if (ret) {
+		dev_err(dev, "Failed to start TSU");
+		goto err;
+	}
+
+	zone = devm_thermal_zone_of_sensor_register(dev, 0, priv,
+						    &rzg2l_tz_of_ops);
+	if (IS_ERR(zone)) {
+		dev_err(dev, "Can't register thermal zone");
+		ret = PTR_ERR(zone);
+		goto err;
+	}
+
+	priv->zone = zone;
+	priv->zone->tzp->no_hwmon = false;
+	ret = thermal_add_hwmon_sysfs(priv->zone);
+	if (ret)
+		goto err;
+
+	dev_dbg(dev, "TSU probed with %s caliberation values",
+		rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0)) ?  "hw" : "sw");
+
+	return 0;
+
+err:
+	rzg2l_thermal_reset_assert_pm_disable_put(pdev);
+	return ret;
+}
+
+static const struct of_device_id rzg2l_thermal_dt_ids[] = {
+	{ .compatible = "renesas,rzg2l-tsu", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rzg2l_thermal_dt_ids);
+
+static struct platform_driver rzg2l_thermal_driver = {
+	.driver = {
+		.name = "rzg2l_thermal",
+		.of_match_table = rzg2l_thermal_dt_ids,
+	},
+	.probe = rzg2l_thermal_probe,
+	.remove = rzg2l_thermal_remove,
+};
+module_platform_driver(rzg2l_thermal_driver);
+
+MODULE_DESCRIPTION("Renesas RZ/G2L TSU Thermal Sensor Driver");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1



  parent reply	other threads:[~2022-04-04 12:36 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-04 12:35 [PATCH 5.10.y-cip 00/29] Add RSPI/OSTM/WDT/TSU/OPP support to Renesas RZ/G2L SoC Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 01/29] clk: renesas: r9a07g044: Add RSPI clock and reset entries Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 02/29] spi: dt-bindings: renesas,rspi: Document RZ/G2L SoC Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 03/29] spi: spi-rspi: Add support to deassert/assert reset line Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 04/29] spi: spi-rspi: Drop redeclaring ret variable in qspi_transfer_in() Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 05/29] arm64: dts: renesas: r9a07g044: Add RSPI{0,1,2} nodes Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 06/29] arm64: dts: renesas: rzg2l-smarc: Enable RSPI1 on carrier board Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 07/29] clk: renesas: r9a07g044: Add WDT clock and reset entries Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 08/29] clk: renesas: r9a07g044: Rename CLK_PLL2_DIV16 and CLK_PLL2_DIV20 macros Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 09/29] dt-bindings: watchdog: renesas,wdt: Add support for RZ/G2L Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 10/29] units: Add SI metric prefix definitions Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 11/29] watchdog: Add Watchdog Timer driver for RZ/G2L Lad Prabhakar
2022-04-05 18:59   ` Pavel Machek
2022-04-06  8:52     ` Prabhakar Mahadev Lad
2022-04-04 12:35 ` [PATCH 5.10.y-cip 12/29] clk: renesas: r9a07g044: Add OSTM clock and reset entries Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 13/29] dt-bindings: timer: renesas: ostm: Document Renesas RZ/G2L OSTM Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 14/29] reset: Add of_reset_control_get_optional_exclusive() Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 15/29] clocksource/drivers/renesas-ostm: Add RZ/G2L OSTM support Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 16/29] clocksource/drivers/renesas,ostm: Make RENESAS_OSTM symbol visible Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 17/29] arm64: dts: renesas: r9a07g044: Add OSTM nodes Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 18/29] arm64: dts: renesas: rzg2l-smarc-som: Enable OSTM Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 19/29] arm64: dts: renesas: r9a07g044: Add WDT nodes Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 20/29] arm64: dts: renesas: rzg2l-smarc-som: Enable watchdog Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 21/29] clk: renesas: r9a07g044: Change core clock "I" from DEF_FIXED->DEF_DIV Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 22/29] clk: renesas: r9a07g044: Add TSU clock and reset entry Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 23/29] clk: renesas: r9a07g044: Rename CLK_PLL3_DIV4 macro Lad Prabhakar
2022-04-05 19:01   ` Pavel Machek
2022-04-06  8:54     ` Prabhakar Mahadev Lad
2022-04-04 12:35 ` [PATCH 5.10.y-cip 24/29] clk: renesas: rzg2l: Add CPG_PL1_DDIV macro Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 25/29] dt-bindings: thermal: Document Renesas RZ/G2L TSU Lad Prabhakar
2022-04-04 12:35 ` Lad Prabhakar [this message]
2022-04-05 19:06   ` [PATCH 5.10.y-cip 26/29] thermal/drivers: Add TSU driver for RZ/G2L Pavel Machek
2022-04-06  8:58     ` Prabhakar Mahadev Lad
2022-04-04 12:35 ` [PATCH 5.10.y-cip 27/29] arm64: dts: renesas: r9a07g044: Add OPP table Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 28/29] arm64: dts: renesas: r9a07g044: Add TSU node Lad Prabhakar
2022-04-04 12:35 ` [PATCH 5.10.y-cip 29/29] arm64: dts: renesas: r9a07g044: Create thermal zone to support IPA Lad Prabhakar
2022-04-04 23:10 ` [PATCH 5.10.y-cip 00/29] Add RSPI/OSTM/WDT/TSU/OPP support to Renesas RZ/G2L SoC Pavel Machek
2022-04-05  7:45 ` nobuhiro1.iwamatsu
2022-04-05  7:59   ` Prabhakar Mahadev Lad

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220404123553.25851-27-prabhakar.mahadev-lad.rj@bp.renesas.com \
    --to=prabhakar.mahadev-lad.rj@bp.renesas.com \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=cip-dev@lists.cip-project.org \
    --cc=nobuhiro1.iwamatsu@toshiba.co.jp \
    --cc=pavel@denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.