linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
@ 2016-09-03  5:25 Khiem Nguyen
  2016-09-05  1:09 ` Kuninori Morimoto
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Khiem Nguyen @ 2016-09-03  5:25 UTC (permalink / raw)
  To: Kuninori Morimoto
  Cc: Wolfram Sang, Geert Uytterhoeven, Magnus Damm, Zhang Rui,
	Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
	devicetree, linux-kernel, Thao Phuong Le. Nguyen, Hien Dang,
	Toru Oishi, Khiem Nguyen


Signed-off-by: Hien Dang <hien.dang.eb@renesas.com>
Signed-off-by: Thao Nguyen <thao.nguyen.yb@rvc.renesas.com>
Signed-off-by: Khiem Nguyen <khiem.nguyen.xt@renesas.com>
---

v2:
 * Set static function for _linear_temp_converter().
 * Update the compatible string following new format.
 * Add newline to improve readability.
 * Change thermal_init callbacks to void functions.
 * Improve the processing to register thermal_zones.
 
 drivers/thermal/Kconfig             |   9 +
 drivers/thermal/Makefile            |   1 +
 drivers/thermal/rcar_gen3_thermal.c | 539 ++++++++++++++++++++++++++++++++++++
 3 files changed, 549 insertions(+)
 create mode 100644 drivers/thermal/rcar_gen3_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 900d505..8500a0a 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -233,6 +233,15 @@ config RCAR_THERMAL
 	  Enable this to plug the R-Car thermal sensor driver into the Linux
 	  thermal framework.
 
+config RCAR_GEN3_THERMAL
+	tristate "Renesas R-Car Gen3 thermal driver"
+	depends on ARCH_RENESAS || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on OF
+	help
+	  Enable this to plug the R-Car Gen3 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 d091134..b7e7082 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM)	+= qcom-spmi-temp-alarm.o
 obj-$(CONFIG_SPEAR_THERMAL)	+= spear_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_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
 obj-y				+= samsung/
 obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
new file mode 100644
index 0000000..cdaaa75
--- /dev/null
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -0,0 +1,539 @@
+/*
+ *  R-Car Gen3 THS thermal sensor driver
+ *  Based on drivers/thermal/rcar_thermal.c
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/spinlock.h>
+#include <linux/thermal.h>
+
+/* Register offset */
+#define REG_GEN3_CTSR		0x20
+#define REG_GEN3_THCTR		0x20
+#define REG_GEN3_IRQSTR		0x04
+#define REG_GEN3_IRQMSK		0x08
+#define REG_GEN3_IRQCTL		0x0C
+#define REG_GEN3_IRQEN		0x10
+#define REG_GEN3_IRQTEMP1	0x14
+#define REG_GEN3_IRQTEMP2	0x18
+#define REG_GEN3_IRQTEMP3	0x1C
+#define REG_GEN3_TEMP		0x28
+#define REG_GEN3_THCODE1	0x50
+#define REG_GEN3_THCODE2	0x54
+#define REG_GEN3_THCODE3	0x58
+
+#define PTAT_BASE		0xE6198000
+#define REG_GEN3_PTAT1		0x5C
+#define REG_GEN3_PTAT2		0x60
+#define REG_GEN3_PTAT3		0x64
+#define PTAT_SIZE		REG_GEN3_PTAT3
+
+/* CTSR bit */
+#define PONM            (0x1 << 8)
+#define AOUT            (0x1 << 7)
+#define THBGR           (0x1 << 5)
+#define VMEN            (0x1 << 4)
+#define VMST            (0x1 << 1)
+#define THSST           (0x1 << 0)
+
+/* THCTR bit */
+#define CTCTL		(0x1 << 24)
+#define THCNTSEN(x)	(x << 16)
+
+#define BIT_LEN_12	0x1
+
+#define CTEMP_MASK	0xFFF
+
+#define MCELSIUS(temp)			((temp) * 1000)
+#define TEMP_IRQ_SHIFT(tsc_id)	(0x1 << tsc_id)
+#define TEMPD_IRQ_SHIFT(tsc_id)	(0x1 << (tsc_id + 3))
+#define GEN3_FUSE_MASK	0xFFF
+
+/* Structure for thermal temperature calculation */
+struct equation_coefs {
+	long a1;
+	long b1;
+	long a2;
+	long b2;
+};
+
+struct fuse_factors {
+	int thcode_1;
+	int thcode_2;
+	int thcode_3;
+	int ptat_1;
+	int ptat_2;
+	int ptat_3;
+};
+
+struct rcar_gen3_thermal_priv {
+	void __iomem *base;
+	struct device *dev;
+	struct thermal_zone_device *zone;
+	struct delayed_work work;
+	struct fuse_factors factor;
+	struct equation_coefs coef;
+	spinlock_t lock;
+	int id;
+	int irq;
+	u32 ctemp;
+	const struct rcar_gen3_thermal_data *data;
+};
+
+struct rcar_gen3_thermal_data {
+	void (*thermal_init)(struct rcar_gen3_thermal_priv *priv);
+};
+
+#define rcar_priv_to_dev(priv)		((priv)->dev)
+#define rcar_has_irq_support(priv)	((priv)->irq)
+
+/* Temperature calculation  */
+#define CODETSD(x)		((x) * 1000)
+#define TJ_1 96000L
+#define TJ_3 (-41000L)
+#define PW2(x) ((x)*(x))
+
+static u32 thermal_reg_read(struct rcar_gen3_thermal_priv *priv, u32 reg)
+{
+	return ioread32(priv->base + reg);
+}
+
+static void thermal_reg_write(struct rcar_gen3_thermal_priv *priv,
+				u32 reg, u32 data)
+{
+	iowrite32(data, priv->base + reg);
+}
+
+static int _round_temp(int temp)
+{
+	int tmp1, tmp2;
+	int result = 0;
+
+	tmp1 = abs(temp) % 1000;
+	tmp2 = abs(temp) / 1000;
+
+	if (tmp1 < 250)
+		result = CODETSD(tmp2);
+	else if (tmp1 < 750 && tmp1 >= 250)
+		result = CODETSD(tmp2) + 500;
+	else
+		result = CODETSD(tmp2) + 1000;
+
+	return ((temp < 0) ? (result * (-1)) : result);
+}
+
+static int _read_fuse_factor(struct rcar_gen3_thermal_priv *priv)
+{
+	/*
+	 * FIXME: The value should be read from some FUSE registers.
+	 * For available SoC, these registers have not been supported yet.
+	 * The pre-defined value will be applied for now.
+	 */
+	priv->factor.ptat_1 = 2351;
+	priv->factor.ptat_2 = 1509;
+	priv->factor.ptat_3 = 435;
+	switch (priv->id) {
+	case 0:
+		priv->factor.thcode_1 = 3248;
+		priv->factor.thcode_2 = 2800;
+		priv->factor.thcode_3 = 2221;
+		break;
+	case 1:
+		priv->factor.thcode_1 = 3245;
+		priv->factor.thcode_2 = 2795;
+		priv->factor.thcode_3 = 2216;
+		break;
+	case 2:
+		priv->factor.thcode_1 = 3250;
+		priv->factor.thcode_2 = 2805;
+		priv->factor.thcode_3 = 2237;
+		break;
+	}
+
+	return 0;
+}
+
+static void _linear_coefficient_calculation(struct rcar_gen3_thermal_priv *priv)
+{
+	int tj_2 = 0;
+	long a1, b1;
+	long a2, b2;
+	long a1_num, a1_den;
+	long a2_num, a2_den;
+
+	tj_2 = (CODETSD((priv->factor.ptat_2 - priv->factor.ptat_3) * 137)
+		/ (priv->factor.ptat_1 - priv->factor.ptat_3)) - CODETSD(41);
+
+	/*
+	 * The following code is to calculate coefficients for linear equation.
+	 */
+	/* Coefficient a1 and b1 */
+	a1_num = CODETSD(priv->factor.thcode_2 - priv->factor.thcode_3);
+	a1_den = tj_2 - TJ_3;
+	a1 = (10000 * a1_num) / a1_den;
+	b1 = (10000 * priv->factor.thcode_3) - ((a1 * TJ_3) / 1000);
+
+	/* Coefficient a2 and b2 */
+	a2_num = CODETSD(priv->factor.thcode_2 - priv->factor.thcode_1);
+	a2_den = tj_2 - TJ_1;
+	a2 = (10000 * a2_num) / a2_den;
+	b2 = (10000 * priv->factor.thcode_1) - ((a2 * TJ_1) / 1000);
+
+	priv->coef.a1 = DIV_ROUND_CLOSEST(a1, 10);
+	priv->coef.b1 = DIV_ROUND_CLOSEST(b1, 10);
+	priv->coef.a2 = DIV_ROUND_CLOSEST(a2, 10);
+	priv->coef.b2 = DIV_ROUND_CLOSEST(b2, 10);
+}
+
+static int _linear_temp_converter(struct equation_coefs coef,
+					int temp_code)
+{
+	int temp, temp1, temp2;
+
+	temp1 = MCELSIUS((CODETSD(temp_code) - coef.b1)) / coef.a1;
+	temp2 = MCELSIUS((CODETSD(temp_code) - coef.b2)) / coef.a2;
+	temp = (temp1 + temp2) / 2;
+
+	return _round_temp(temp);
+}
+
+/*
+ *		Zone device functions
+ */
+static int rcar_gen3_thermal_update_temp(struct rcar_gen3_thermal_priv *priv)
+{
+	u32 ctemp;
+	int i;
+	unsigned long flags;
+	u32 reg = REG_GEN3_IRQTEMP1 + (priv->id * 4);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	for (i = 0; i < 256; i++) {
+		ctemp = thermal_reg_read(priv, REG_GEN3_TEMP) & CTEMP_MASK;
+
+		if (rcar_has_irq_support(priv)) {
+			thermal_reg_write(priv, reg, ctemp);
+
+			if (thermal_reg_read(priv, REG_GEN3_IRQSTR) != 0)
+				break;
+		} else
+			break;
+
+		udelay(150);
+	}
+
+	priv->ctemp = ctemp;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
+{
+	struct rcar_gen3_thermal_priv *priv = devdata;
+	int ctemp;
+	unsigned long flags;
+
+	rcar_gen3_thermal_update_temp(priv);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	ctemp = _linear_temp_converter(priv->coef, priv->ctemp);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if ((ctemp < MCELSIUS(-40)) || (ctemp > MCELSIUS(125))) {
+		struct device *dev = rcar_priv_to_dev(priv);
+
+		dev_dbg(dev, "Temperature is not measured correctly!\n");
+		return -EIO;
+	}
+
+	*temp = ctemp;
+
+	return 0;
+}
+
+static void r8a7795_thermal_init(struct rcar_gen3_thermal_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	thermal_reg_write(priv, REG_GEN3_CTSR,  THBGR);
+	thermal_reg_write(priv, REG_GEN3_CTSR,  0x0);
+
+	udelay(1000);
+
+	thermal_reg_write(priv, REG_GEN3_CTSR, PONM);
+	thermal_reg_write(priv, REG_GEN3_IRQCTL, 0x3F);
+	thermal_reg_write(priv, REG_GEN3_IRQEN, TEMP_IRQ_SHIFT(priv->id) |
+						TEMPD_IRQ_SHIFT(priv->id));
+	thermal_reg_write(priv, REG_GEN3_CTSR,
+			PONM | AOUT | THBGR | VMEN);
+
+	udelay(100);
+
+	thermal_reg_write(priv, REG_GEN3_CTSR,
+			PONM | AOUT | THBGR | VMEN | VMST | THSST);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void r8a7796_thermal_init(struct rcar_gen3_thermal_priv *priv)
+{
+	unsigned long flags;
+	unsigned long reg_val;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	thermal_reg_write(priv, REG_GEN3_THCTR,  0x0);
+
+	udelay(1000);
+
+	thermal_reg_write(priv, REG_GEN3_IRQCTL, 0x3F);
+	thermal_reg_write(priv, REG_GEN3_IRQEN, TEMP_IRQ_SHIFT(priv->id) |
+						TEMPD_IRQ_SHIFT(priv->id));
+	thermal_reg_write(priv, REG_GEN3_THCTR,
+						CTCTL | THCNTSEN(BIT_LEN_12));
+	reg_val = thermal_reg_read(priv, REG_GEN3_THCTR);
+	reg_val &= ~CTCTL;
+	reg_val |= THSST;
+	thermal_reg_write(priv, REG_GEN3_THCTR, reg_val);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/*
+ *		Interrupt
+ */
+#define rcar_gen3_thermal_irq_enable(p)		_thermal_irq_ctrl(p, 1)
+#define rcar_gen3_thermal_irq_disable(p)	_thermal_irq_ctrl(p, 0)
+static void _thermal_irq_ctrl(struct rcar_gen3_thermal_priv *priv, int enable)
+{
+	unsigned long flags;
+
+	if (!rcar_has_irq_support(priv))
+		return;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	thermal_reg_write(priv, REG_GEN3_IRQMSK,
+		enable ? (TEMP_IRQ_SHIFT(priv->id) |
+			TEMPD_IRQ_SHIFT(priv->id)) : 0);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void rcar_gen3_thermal_work(struct work_struct *work)
+{
+	struct rcar_gen3_thermal_priv *priv;
+
+	priv = container_of(work, struct rcar_gen3_thermal_priv, work.work);
+
+	thermal_zone_device_update(priv->zone);
+
+	rcar_gen3_thermal_irq_enable(priv);
+}
+
+static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
+{
+	struct rcar_gen3_thermal_priv *priv = data;
+	unsigned long flags;
+	int status;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	status = thermal_reg_read(priv, REG_GEN3_IRQSTR);
+	thermal_reg_write(priv, REG_GEN3_IRQSTR, 0);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if ((status & TEMP_IRQ_SHIFT(priv->id)) ||
+		(status & TEMPD_IRQ_SHIFT(priv->id))) {
+		rcar_gen3_thermal_irq_disable(priv);
+		schedule_delayed_work(&priv->work,
+				      msecs_to_jiffies(300));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
+	.get_temp	= rcar_gen3_thermal_get_temp,
+};
+
+/*
+ *		Platform functions
+ */
+static int rcar_gen3_thermal_remove(struct platform_device *pdev)
+{
+	struct rcar_gen3_thermal_priv *priv = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	rcar_gen3_thermal_irq_disable(priv);
+	thermal_zone_of_sensor_unregister(dev, priv->zone);
+
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+
+	return 0;
+}
+
+static const struct rcar_gen3_thermal_data r8a7795_data = {
+	.thermal_init = r8a7795_thermal_init,
+};
+
+static const struct rcar_gen3_thermal_data r8a7796_data = {
+	.thermal_init = r8a7796_thermal_init,
+};
+
+static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
+	{ .compatible = "renesas,r8a7795-thermal", .data = &r8a7795_data},
+	{ .compatible = "renesas,r8a7796-thermal", .data = &r8a7796_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
+
+static int rcar_gen3_thermal_probe(struct platform_device *pdev)
+{
+	struct rcar_gen3_thermal_priv *priv;
+	struct device *dev = &pdev->dev;
+	struct resource *res, *irq;
+	int ret = -ENODEV;
+	int idle;
+	struct device_node *tz_nd, *tmp_nd;
+	struct thermal_zone_device *zone;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->dev = dev;
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	priv->data = of_device_get_match_data(dev);
+	if (!priv->data)
+		goto error_unregister;
+
+	priv->irq = 0;
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq) {
+		priv->irq = 1;
+		for_each_node_with_property(tz_nd, "polling-delay") {
+			tmp_nd = of_parse_phandle(tz_nd,
+					"thermal-sensors", 0);
+			if (tmp_nd && !strcmp(tmp_nd->full_name,
+					dev->of_node->full_name)) {
+				of_property_read_u32(tz_nd, "polling-delay",
+					&idle);
+				if (idle > 0)
+					priv->irq = 0;
+				break;
+			}
+		}
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto error_unregister;
+
+	priv->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->base)) {
+		ret = PTR_ERR(priv->base);
+		goto error_unregister;
+	}
+
+	spin_lock_init(&priv->lock);
+	INIT_DELAYED_WORK(&priv->work, rcar_gen3_thermal_work);
+
+	priv->id = of_alias_get_id(dev->of_node, "tsc");
+	if (priv->id < 0) {
+		dev_err(dev, "Failed to get alias id (%d)\n", priv->id);
+		ret = priv->id;
+		goto error_unregister;
+	}
+
+	zone = devm_thermal_zone_of_sensor_register(dev, 0, priv,
+				&rcar_gen3_tz_of_ops);
+
+	if (IS_ERR(zone)) {
+		dev_err(dev, "Can't register thermal zone\n");
+		ret = PTR_ERR(zone);
+		goto error_unregister;
+	}
+	priv->zone = zone;
+
+	priv->data->thermal_init(priv);
+
+	ret = _read_fuse_factor(priv);
+	if (ret)
+		goto error_unregister;
+
+	_linear_coefficient_calculation(priv);
+
+	ret = rcar_gen3_thermal_update_temp(priv);
+
+	if (ret < 0)
+		goto error_unregister;
+
+
+	rcar_gen3_thermal_irq_enable(priv);
+
+	/* Interrupt */
+	if (irq) {
+		ret = devm_request_irq(dev, irq->start,
+					rcar_gen3_thermal_irq, 0,
+				       dev_name(dev), priv);
+		if (ret) {
+			dev_err(dev, "IRQ request failed\n ");
+			goto error_unregister;
+		}
+	}
+
+	dev_info(dev, "probed\n");
+
+	return 0;
+
+error_unregister:
+	rcar_gen3_thermal_remove(pdev);
+
+	return ret;
+}
+
+static struct platform_driver rcar_gen3_thermal_driver = {
+	.driver	= {
+		.name	= "rcar_gen3_thermal",
+		.of_match_table = rcar_gen3_thermal_dt_ids,
+	},
+	.probe		= rcar_gen3_thermal_probe,
+	.remove		= rcar_gen3_thermal_remove,
+};
+module_platform_driver(rcar_gen3_thermal_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver");
+MODULE_AUTHOR("Khiem Nguyen <khiem.nguyen.xt@renesas.com>");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-03  5:25 [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver Khiem Nguyen
@ 2016-09-05  1:09 ` Kuninori Morimoto
  2016-09-05 10:01 ` Geert Uytterhoeven
  2016-09-06  0:51 ` Zhang Rui
  2 siblings, 0 replies; 7+ messages in thread
From: Kuninori Morimoto @ 2016-09-05  1:09 UTC (permalink / raw)
  To: Khiem Nguyen
  Cc: Wolfram Sang, Geert Uytterhoeven, Magnus Damm, Zhang Rui,
	Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
	devicetree, linux-kernel, Thao Phuong Le. Nguyen, Hien Dang,
	Toru Oishi


Hi

> Khiem Nguyen (5):
>  thermal: rcar_gen3_thermal: Document the R-Car Gen3 thermal bindings
>  thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver support
>  arm64: dts: r8a7795: Add R-Car Gen3 thermal support
>  arm64: dts: r8a7796: Add R-Car Gen3 thermal support
>  arm64: defconfig: Enable R-Car Gen3 thermal support

For all patches

Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

> +static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
> +{
> +	struct rcar_gen3_thermal_priv *priv = devdata;
> +	int ctemp;
> +	unsigned long flags;
> +
> +	rcar_gen3_thermal_update_temp(priv);
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +	ctemp = _linear_temp_converter(priv->coef, priv->ctemp);
> +	spin_unlock_irqrestore(&priv->lock, flags);

This is not a big deal, but, as I mentioned in v1 patch,
having pointer for _linear_temp_converter() parameter is good idea.
	_linear_temp_converter(&priv->coef, xxx);

or
	_linear_temp_converter(priv);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-03  5:25 [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver Khiem Nguyen
  2016-09-05  1:09 ` Kuninori Morimoto
@ 2016-09-05 10:01 ` Geert Uytterhoeven
  2016-09-06 12:19   ` Khiem Nguyen
  2016-09-06  0:51 ` Zhang Rui
  2 siblings, 1 reply; 7+ messages in thread
From: Geert Uytterhoeven @ 2016-09-05 10:01 UTC (permalink / raw)
  To: Khiem Nguyen
  Cc: Kuninori Morimoto, Wolfram Sang, Geert Uytterhoeven, Magnus Damm,
	Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
	devicetree, linux-kernel, Thao Phuong Le. Nguyen, Hien Dang,
	Toru Oishi

Hi Khiem

On Sat, Sep 3, 2016 at 7:25 AM, Khiem Nguyen
<khiem.nguyen.xt@renesas.com> wrote:
> --- /dev/null
> +++ b/drivers/thermal/rcar_gen3_thermal.c

> +static int rcar_gen3_thermal_probe(struct platform_device *pdev)
> +{

> +       priv->id = of_alias_get_id(dev->of_node, "tsc");
> +       if (priv->id < 0) {
> +               dev_err(dev, "Failed to get alias id (%d)\n", priv->id);
> +               ret = priv->id;
> +               goto error_unregister;
> +       }

In v1, Morimoto-san wondered whether the alias is really needed, but you
haven't addressed his question.

While aliases can be useful in DT source files, using aliases like this imposes
hardcoded instance numbers, which is something we try to avoid these days.
Also, this puts a hard requirement on the presence of the alias in DT, which
should be documented in the DT bindings.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-03  5:25 [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver Khiem Nguyen
  2016-09-05  1:09 ` Kuninori Morimoto
  2016-09-05 10:01 ` Geert Uytterhoeven
@ 2016-09-06  0:51 ` Zhang Rui
  2016-09-08 16:08   ` Khiem Nguyen
  2 siblings, 1 reply; 7+ messages in thread
From: Zhang Rui @ 2016-09-06  0:51 UTC (permalink / raw)
  To: Khiem Nguyen, Kuninori Morimoto
  Cc: Wolfram Sang, Geert Uytterhoeven, Magnus Damm, Eduardo Valentin,
	Rob Herring, Mark Rutland, linux-pm, devicetree, linux-kernel,
	Thao Phuong Le. Nguyen, Hien Dang, Toru Oishi

On 六, 2016-09-03 at 05:25 +0000, Khiem Nguyen wrote:
> Signed-off-by: Hien Dang <hien.dang.eb@renesas.com>
> Signed-off-by: Thao Nguyen <thao.nguyen.yb@rvc.renesas.com>
> Signed-off-by: Khiem Nguyen <khiem.nguyen.xt@renesas.com>

Well, I can only see patch 4/5, 5/5 in patchwork but I can not see this
one....

thanks,
rui
> ---
> 
> v2:
>  * Set static function for _linear_temp_converter().
>  * Update the compatible string following new format.
>  * Add newline to improve readability.
>  * Change thermal_init callbacks to void functions.
>  * Improve the processing to register thermal_zones.
>  
>  drivers/thermal/Kconfig             |   9 +
>  drivers/thermal/Makefile            |   1 +
>  drivers/thermal/rcar_gen3_thermal.c | 539
> ++++++++++++++++++++++++++++++++++++
>  3 files changed, 549 insertions(+)
>  create mode 100644 drivers/thermal/rcar_gen3_thermal.c
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 900d505..8500a0a 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -233,6 +233,15 @@ config RCAR_THERMAL
>  	  Enable this to plug the R-Car thermal sensor driver into
> the Linux
>  	  thermal framework.
>  
> +config RCAR_GEN3_THERMAL
> +	tristate "Renesas R-Car Gen3 thermal driver"
> +	depends on ARCH_RENESAS || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	depends on OF
> +	help
> +	  Enable this to plug the R-Car Gen3 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 d091134..b7e7082 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -31,6 +31,7 @@ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM)	+= qcom-
> spmi-temp-alarm.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_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_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
>  obj-y				+= samsung/
>  obj-$(CONFIG_DOVE_THERMAL)  	+= dove_thermal.o
> diff --git a/drivers/thermal/rcar_gen3_thermal.c
> b/drivers/thermal/rcar_gen3_thermal.c
> new file mode 100644
> index 0000000..cdaaa75
> --- /dev/null
> +++ b/drivers/thermal/rcar_gen3_thermal.c
> @@ -0,0 +1,539 @@
> +/*
> + *  R-Car Gen3 THS thermal sensor driver
> + *  Based on drivers/thermal/rcar_thermal.c
> + *
> + * Copyright (C) 2016 Renesas Electronics Corporation.
> + *
> + *  This program is free software; you can redistribute it and/or
> modify
> + *  it under the terms of the GNU General Public License as
> published by
> + *  the Free Software Foundation; version 2 of the License.
> + *
> + *  This program is distributed in the hope that it will be useful,
> but
> + *  WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> GNU
> + *  General Public License for more details.
> + *
> + */
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/spinlock.h>
> +#include <linux/thermal.h>
> +
> +/* Register offset */
> +#define REG_GEN3_CTSR		0x20
> +#define REG_GEN3_THCTR		0x20
> +#define REG_GEN3_IRQSTR		0x04
> +#define REG_GEN3_IRQMSK		0x08
> +#define REG_GEN3_IRQCTL		0x0C
> +#define REG_GEN3_IRQEN		0x10
> +#define REG_GEN3_IRQTEMP1	0x14
> +#define REG_GEN3_IRQTEMP2	0x18
> +#define REG_GEN3_IRQTEMP3	0x1C
> +#define REG_GEN3_TEMP		0x28
> +#define REG_GEN3_THCODE1	0x50
> +#define REG_GEN3_THCODE2	0x54
> +#define REG_GEN3_THCODE3	0x58
> +
> +#define PTAT_BASE		0xE6198000
> +#define REG_GEN3_PTAT1		0x5C
> +#define REG_GEN3_PTAT2		0x60
> +#define REG_GEN3_PTAT3		0x64
> +#define PTAT_SIZE		REG_GEN3_PTAT3
> +
> +/* CTSR bit */
> +#define PONM            (0x1 << 8)
> +#define AOUT            (0x1 << 7)
> +#define THBGR           (0x1 << 5)
> +#define VMEN            (0x1 << 4)
> +#define VMST            (0x1 << 1)
> +#define THSST           (0x1 << 0)
> +
> +/* THCTR bit */
> +#define CTCTL		(0x1 << 24)
> +#define THCNTSEN(x)	(x << 16)
> +
> +#define BIT_LEN_12	0x1
> +
> +#define CTEMP_MASK	0xFFF
> +
> +#define MCELSIUS(temp)			((temp) * 1000)
> +#define TEMP_IRQ_SHIFT(tsc_id)	(0x1 << tsc_id)
> +#define TEMPD_IRQ_SHIFT(tsc_id)	(0x1 << (tsc_id + 3))
> +#define GEN3_FUSE_MASK	0xFFF
> +
> +/* Structure for thermal temperature calculation */
> +struct equation_coefs {
> +	long a1;
> +	long b1;
> +	long a2;
> +	long b2;
> +};
> +
> +struct fuse_factors {
> +	int thcode_1;
> +	int thcode_2;
> +	int thcode_3;
> +	int ptat_1;
> +	int ptat_2;
> +	int ptat_3;
> +};
> +
> +struct rcar_gen3_thermal_priv {
> +	void __iomem *base;
> +	struct device *dev;
> +	struct thermal_zone_device *zone;
> +	struct delayed_work work;
> +	struct fuse_factors factor;
> +	struct equation_coefs coef;
> +	spinlock_t lock;
> +	int id;
> +	int irq;
> +	u32 ctemp;
> +	const struct rcar_gen3_thermal_data *data;
> +};
> +
> +struct rcar_gen3_thermal_data {
> +	void (*thermal_init)(struct rcar_gen3_thermal_priv *priv);
> +};
> +
> +#define rcar_priv_to_dev(priv)		((priv)->dev)
> +#define rcar_has_irq_support(priv)	((priv)->irq)
> +
> +/* Temperature calculation  */
> +#define CODETSD(x)		((x) * 1000)
> +#define TJ_1 96000L
> +#define TJ_3 (-41000L)
> +#define PW2(x) ((x)*(x))
> +
> +static u32 thermal_reg_read(struct rcar_gen3_thermal_priv *priv, u32
> reg)
> +{
> +	return ioread32(priv->base + reg);
> +}
> +
> +static void thermal_reg_write(struct rcar_gen3_thermal_priv *priv,
> +				u32 reg, u32 data)
> +{
> +	iowrite32(data, priv->base + reg);
> +}
> +
> +static int _round_temp(int temp)
> +{
> +	int tmp1, tmp2;
> +	int result = 0;
> +
> +	tmp1 = abs(temp) % 1000;
> +	tmp2 = abs(temp) / 1000;
> +
> +	if (tmp1 < 250)
> +		result = CODETSD(tmp2);
> +	else if (tmp1 < 750 && tmp1 >= 250)
> +		result = CODETSD(tmp2) + 500;
> +	else
> +		result = CODETSD(tmp2) + 1000;
> +
> +	return ((temp < 0) ? (result * (-1)) : result);
> +}
> +
> +static int _read_fuse_factor(struct rcar_gen3_thermal_priv *priv)
> +{
> +	/*
> +	 * FIXME: The value should be read from some FUSE registers.
> +	 * For available SoC, these registers have not been
> supported yet.
> +	 * The pre-defined value will be applied for now.
> +	 */
> +	priv->factor.ptat_1 = 2351;
> +	priv->factor.ptat_2 = 1509;
> +	priv->factor.ptat_3 = 435;
> +	switch (priv->id) {
> +	case 0:
> +		priv->factor.thcode_1 = 3248;
> +		priv->factor.thcode_2 = 2800;
> +		priv->factor.thcode_3 = 2221;
> +		break;
> +	case 1:
> +		priv->factor.thcode_1 = 3245;
> +		priv->factor.thcode_2 = 2795;
> +		priv->factor.thcode_3 = 2216;
> +		break;
> +	case 2:
> +		priv->factor.thcode_1 = 3250;
> +		priv->factor.thcode_2 = 2805;
> +		priv->factor.thcode_3 = 2237;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static void _linear_coefficient_calculation(struct
> rcar_gen3_thermal_priv *priv)
> +{
> +	int tj_2 = 0;
> +	long a1, b1;
> +	long a2, b2;
> +	long a1_num, a1_den;
> +	long a2_num, a2_den;
> +
> +	tj_2 = (CODETSD((priv->factor.ptat_2 - priv->factor.ptat_3)
> * 137)
> +		/ (priv->factor.ptat_1 - priv->factor.ptat_3)) -
> CODETSD(41);
> +
> +	/*
> +	 * The following code is to calculate coefficients for
> linear equation.
> +	 */
> +	/* Coefficient a1 and b1 */
> +	a1_num = CODETSD(priv->factor.thcode_2 - priv-
> >factor.thcode_3);
> +	a1_den = tj_2 - TJ_3;
> +	a1 = (10000 * a1_num) / a1_den;
> +	b1 = (10000 * priv->factor.thcode_3) - ((a1 * TJ_3) / 1000);
> +
> +	/* Coefficient a2 and b2 */
> +	a2_num = CODETSD(priv->factor.thcode_2 - priv-
> >factor.thcode_1);
> +	a2_den = tj_2 - TJ_1;
> +	a2 = (10000 * a2_num) / a2_den;
> +	b2 = (10000 * priv->factor.thcode_1) - ((a2 * TJ_1) / 1000);
> +
> +	priv->coef.a1 = DIV_ROUND_CLOSEST(a1, 10);
> +	priv->coef.b1 = DIV_ROUND_CLOSEST(b1, 10);
> +	priv->coef.a2 = DIV_ROUND_CLOSEST(a2, 10);
> +	priv->coef.b2 = DIV_ROUND_CLOSEST(b2, 10);
> +}
> +
> +static int _linear_temp_converter(struct equation_coefs coef,
> +					int temp_code)
> +{
> +	int temp, temp1, temp2;
> +
> +	temp1 = MCELSIUS((CODETSD(temp_code) - coef.b1)) / coef.a1;
> +	temp2 = MCELSIUS((CODETSD(temp_code) - coef.b2)) / coef.a2;
> +	temp = (temp1 + temp2) / 2;
> +
> +	return _round_temp(temp);
> +}
> +
> +/*
> + *		Zone device functions
> + */
> +static int rcar_gen3_thermal_update_temp(struct
> rcar_gen3_thermal_priv *priv)
> +{
> +	u32 ctemp;
> +	int i;
> +	unsigned long flags;
> +	u32 reg = REG_GEN3_IRQTEMP1 + (priv->id * 4);
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	for (i = 0; i < 256; i++) {
> +		ctemp = thermal_reg_read(priv, REG_GEN3_TEMP) &
> CTEMP_MASK;
> +
> +		if (rcar_has_irq_support(priv)) {
> +			thermal_reg_write(priv, reg, ctemp);
> +
> +			if (thermal_reg_read(priv, REG_GEN3_IRQSTR)
> != 0)
> +				break;
> +		} else
> +			break;
> +
> +		udelay(150);
> +	}
> +
> +	priv->ctemp = ctemp;
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
> +{
> +	struct rcar_gen3_thermal_priv *priv = devdata;
> +	int ctemp;
> +	unsigned long flags;
> +
> +	rcar_gen3_thermal_update_temp(priv);
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +	ctemp = _linear_temp_converter(priv->coef, priv->ctemp);
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	if ((ctemp < MCELSIUS(-40)) || (ctemp > MCELSIUS(125))) {
> +		struct device *dev = rcar_priv_to_dev(priv);
> +
> +		dev_dbg(dev, "Temperature is not measured
> correctly!\n");
> +		return -EIO;
> +	}
> +
> +	*temp = ctemp;
> +
> +	return 0;
> +}
> +
> +static void r8a7795_thermal_init(struct rcar_gen3_thermal_priv
> *priv)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	thermal_reg_write(priv, REG_GEN3_CTSR,  THBGR);
> +	thermal_reg_write(priv, REG_GEN3_CTSR,  0x0);
> +
> +	udelay(1000);
> +
> +	thermal_reg_write(priv, REG_GEN3_CTSR, PONM);
> +	thermal_reg_write(priv, REG_GEN3_IRQCTL, 0x3F);
> +	thermal_reg_write(priv, REG_GEN3_IRQEN, TEMP_IRQ_SHIFT(priv-
> >id) |
> +						TEMPD_IRQ_SHIFT(priv
> ->id));
> +	thermal_reg_write(priv, REG_GEN3_CTSR,
> +			PONM | AOUT | THBGR | VMEN);
> +
> +	udelay(100);
> +
> +	thermal_reg_write(priv, REG_GEN3_CTSR,
> +			PONM | AOUT | THBGR | VMEN | VMST | THSST);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void r8a7796_thermal_init(struct rcar_gen3_thermal_priv
> *priv)
> +{
> +	unsigned long flags;
> +	unsigned long reg_val;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	thermal_reg_write(priv, REG_GEN3_THCTR,  0x0);
> +
> +	udelay(1000);
> +
> +	thermal_reg_write(priv, REG_GEN3_IRQCTL, 0x3F);
> +	thermal_reg_write(priv, REG_GEN3_IRQEN, TEMP_IRQ_SHIFT(priv-
> >id) |
> +						TEMPD_IRQ_SHIFT(priv
> ->id));
> +	thermal_reg_write(priv, REG_GEN3_THCTR,
> +						CTCTL |
> THCNTSEN(BIT_LEN_12));
> +	reg_val = thermal_reg_read(priv, REG_GEN3_THCTR);
> +	reg_val &= ~CTCTL;
> +	reg_val |= THSST;
> +	thermal_reg_write(priv, REG_GEN3_THCTR, reg_val);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +/*
> + *		Interrupt
> + */
> +#define rcar_gen3_thermal_irq_enable(p)		_thermal_irq_
> ctrl(p, 1)
> +#define rcar_gen3_thermal_irq_disable(p)	_thermal_irq_ctrl(p,
> 0)
> +static void _thermal_irq_ctrl(struct rcar_gen3_thermal_priv *priv,
> int enable)
> +{
> +	unsigned long flags;
> +
> +	if (!rcar_has_irq_support(priv))
> +		return;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	thermal_reg_write(priv, REG_GEN3_IRQMSK,
> +		enable ? (TEMP_IRQ_SHIFT(priv->id) |
> +			TEMPD_IRQ_SHIFT(priv->id)) : 0);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +}
> +
> +static void rcar_gen3_thermal_work(struct work_struct *work)
> +{
> +	struct rcar_gen3_thermal_priv *priv;
> +
> +	priv = container_of(work, struct rcar_gen3_thermal_priv,
> work.work);
> +
> +	thermal_zone_device_update(priv->zone);
> +
> +	rcar_gen3_thermal_irq_enable(priv);
> +}
> +
> +static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
> +{
> +	struct rcar_gen3_thermal_priv *priv = data;
> +	unsigned long flags;
> +	int status;
> +
> +	spin_lock_irqsave(&priv->lock, flags);
> +
> +	status = thermal_reg_read(priv, REG_GEN3_IRQSTR);
> +	thermal_reg_write(priv, REG_GEN3_IRQSTR, 0);
> +
> +	spin_unlock_irqrestore(&priv->lock, flags);
> +
> +	if ((status & TEMP_IRQ_SHIFT(priv->id)) ||
> +		(status & TEMPD_IRQ_SHIFT(priv->id))) {
> +		rcar_gen3_thermal_irq_disable(priv);
> +		schedule_delayed_work(&priv->work,
> +				      msecs_to_jiffies(300));
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
> +	.get_temp	= rcar_gen3_thermal_get_temp,
> +};
> +
> +/*
> + *		Platform functions
> + */
> +static int rcar_gen3_thermal_remove(struct platform_device *pdev)
> +{
> +	struct rcar_gen3_thermal_priv *priv =
> platform_get_drvdata(pdev);
> +	struct device *dev = &pdev->dev;
> +
> +	rcar_gen3_thermal_irq_disable(priv);
> +	thermal_zone_of_sensor_unregister(dev, priv->zone);
> +
> +	pm_runtime_put(dev);
> +	pm_runtime_disable(dev);
> +
> +	return 0;
> +}
> +
> +static const struct rcar_gen3_thermal_data r8a7795_data = {
> +	.thermal_init = r8a7795_thermal_init,
> +};
> +
> +static const struct rcar_gen3_thermal_data r8a7796_data = {
> +	.thermal_init = r8a7796_thermal_init,
> +};
> +
> +static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
> +	{ .compatible = "renesas,r8a7795-thermal", .data =
> &r8a7795_data},
> +	{ .compatible = "renesas,r8a7796-thermal", .data =
> &r8a7796_data},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
> +
> +static int rcar_gen3_thermal_probe(struct platform_device *pdev)
> +{
> +	struct rcar_gen3_thermal_priv *priv;
> +	struct device *dev = &pdev->dev;
> +	struct resource *res, *irq;
> +	int ret = -ENODEV;
> +	int idle;
> +	struct device_node *tz_nd, *tmp_nd;
> +	struct thermal_zone_device *zone;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	priv->dev = dev;
> +
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
> +
> +	priv->data = of_device_get_match_data(dev);
> +	if (!priv->data)
> +		goto error_unregister;
> +
> +	priv->irq = 0;
> +
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (irq) {
> +		priv->irq = 1;
> +		for_each_node_with_property(tz_nd, "polling-delay")
> {
> +			tmp_nd = of_parse_phandle(tz_nd,
> +					"thermal-sensors", 0);
> +			if (tmp_nd && !strcmp(tmp_nd->full_name,
> +					dev->of_node->full_name)) {
> +				of_property_read_u32(tz_nd,
> "polling-delay",
> +					&idle);
> +				if (idle > 0)
> +					priv->irq = 0;
> +				break;
> +			}
> +		}
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		goto error_unregister;
> +
> +	priv->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(priv->base)) {
> +		ret = PTR_ERR(priv->base);
> +		goto error_unregister;
> +	}
> +
> +	spin_lock_init(&priv->lock);
> +	INIT_DELAYED_WORK(&priv->work, rcar_gen3_thermal_work);
> +
> +	priv->id = of_alias_get_id(dev->of_node, "tsc");
> +	if (priv->id < 0) {
> +		dev_err(dev, "Failed to get alias id (%d)\n", priv-
> >id);
> +		ret = priv->id;
> +		goto error_unregister;
> +	}
> +
> +	zone = devm_thermal_zone_of_sensor_register(dev, 0, priv,
> +				&rcar_gen3_tz_of_ops);
> +
> +	if (IS_ERR(zone)) {
> +		dev_err(dev, "Can't register thermal zone\n");
> +		ret = PTR_ERR(zone);
> +		goto error_unregister;
> +	}
> +	priv->zone = zone;
> +
> +	priv->data->thermal_init(priv);
> +
> +	ret = _read_fuse_factor(priv);
> +	if (ret)
> +		goto error_unregister;
> +
> +	_linear_coefficient_calculation(priv);
> +
> +	ret = rcar_gen3_thermal_update_temp(priv);
> +
> +	if (ret < 0)
> +		goto error_unregister;
> +
> +
> +	rcar_gen3_thermal_irq_enable(priv);
> +
> +	/* Interrupt */
> +	if (irq) {
> +		ret = devm_request_irq(dev, irq->start,
> +					rcar_gen3_thermal_irq, 0,
> +				       dev_name(dev), priv);
> +		if (ret) {
> +			dev_err(dev, "IRQ request failed\n ");
> +			goto error_unregister;
> +		}
> +	}
> +
> +	dev_info(dev, "probed\n");
> +
> +	return 0;
> +
> +error_unregister:
> +	rcar_gen3_thermal_remove(pdev);
> +
> +	return ret;
> +}
> +
> +static struct platform_driver rcar_gen3_thermal_driver = {
> +	.driver	= {
> +		.name	= "rcar_gen3_thermal",
> +		.of_match_table = rcar_gen3_thermal_dt_ids,
> +	},
> +	.probe		= rcar_gen3_thermal_probe,
> +	.remove		= rcar_gen3_thermal_remove,
> +};
> +module_platform_driver(rcar_gen3_thermal_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("R-Car Gen3 THS thermal sensor driver");
> +MODULE_AUTHOR("Khiem Nguyen <khiem.nguyen.xt@renesas.com>");
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-05 10:01 ` Geert Uytterhoeven
@ 2016-09-06 12:19   ` Khiem Nguyen
  2016-09-06 12:24     ` Geert Uytterhoeven
  0 siblings, 1 reply; 7+ messages in thread
From: Khiem Nguyen @ 2016-09-06 12:19 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Kuninori Morimoto, Wolfram Sang, Geert Uytterhoeven, Magnus Damm,
	Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
	devicetree, linux-kernel, Thao Phuong Le. Nguyen, Hien Dang,
	Toru Oishi, Khiem Nguyen

Hi Geert,

Thanks for your comment.

> > +static int rcar_gen3_thermal_probe(struct platform_device *pdev) {
> 
> > +       priv->id = of_alias_get_id(dev->of_node, "tsc");
> > +       if (priv->id < 0) {
> > +               dev_err(dev, "Failed to get alias id (%d)\n", priv->id);
> > +               ret = priv->id;
> > +               goto error_unregister;
> > +       }
> 
> In v1, Morimoto-san wondered whether the alias is really needed, but you haven't
> addressed his question.
> 
> While aliases can be useful in DT source files, using aliases like this imposes
> hardcoded instance numbers, which is something we try to avoid these days.
> Also, this puts a hard requirement on the presence of the alias in DT, which should
> be documented in the DT bindings.

OK.
I prefer updating DT binding to describe alias.

There is requirement about coefficient to calculate temperature,
and the coefficient value (fixed value) is different among thermal sensors.

Thanks.

Best regards,
KHIEM Nguyen

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-06 12:19   ` Khiem Nguyen
@ 2016-09-06 12:24     ` Geert Uytterhoeven
  0 siblings, 0 replies; 7+ messages in thread
From: Geert Uytterhoeven @ 2016-09-06 12:24 UTC (permalink / raw)
  To: Khiem Nguyen
  Cc: Kuninori Morimoto, Wolfram Sang, Geert Uytterhoeven, Magnus Damm,
	Zhang Rui, Eduardo Valentin, Rob Herring, Mark Rutland, linux-pm,
	devicetree, linux-kernel, Thao Phuong Le. Nguyen, Hien Dang,
	Toru Oishi

Hi Khiem,

On Tue, Sep 6, 2016 at 2:19 PM, Khiem Nguyen
<khiem.nguyen.xt@renesas.com> wrote:
>> > +static int rcar_gen3_thermal_probe(struct platform_device *pdev) {
>>
>> > +       priv->id = of_alias_get_id(dev->of_node, "tsc");
>> > +       if (priv->id < 0) {
>> > +               dev_err(dev, "Failed to get alias id (%d)\n", priv->id);
>> > +               ret = priv->id;
>> > +               goto error_unregister;
>> > +       }
>>
>> In v1, Morimoto-san wondered whether the alias is really needed, but you haven't
>> addressed his question.
>>
>> While aliases can be useful in DT source files, using aliases like this imposes
>> hardcoded instance numbers, which is something we try to avoid these days.
>> Also, this puts a hard requirement on the presence of the alias in DT, which should
>> be documented in the DT bindings.
>
> OK.
> I prefer updating DT binding to describe alias.
>
> There is requirement about coefficient to calculate temperature,
> and the coefficient value (fixed value) is different among thermal sensors.

>From DT, you can still refer to a specific instance using a phandle to a label.
You do not need aliases for that.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver
  2016-09-06  0:51 ` Zhang Rui
@ 2016-09-08 16:08   ` Khiem Nguyen
  0 siblings, 0 replies; 7+ messages in thread
From: Khiem Nguyen @ 2016-09-08 16:08 UTC (permalink / raw)
  To: Zhang Rui, Kuninori Morimoto
  Cc: Wolfram Sang, Geert Uytterhoeven, Magnus Damm, Eduardo Valentin,
	Rob Herring, Mark Rutland, linux-pm, devicetree, linux-kernel,
	Thao Phuong Le. Nguyen, Hien Dang, Toru Oishi, Khiem Nguyen

Hi Zhang,

> On 六, 2016-09-03 at 05:25 +0000, Khiem Nguyen wrote:
> > Signed-off-by: Hien Dang <hien.dang.eb@renesas.com>
> > Signed-off-by: Thao Nguyen <thao.nguyen.yb@rvc.renesas.com>
> > Signed-off-by: Khiem Nguyen <khiem.nguyen.xt@renesas.com>
> 
> Well, I can only see patch 4/5, 5/5 in patchwork but I can not see this one....

Thanks for your information.
Will try to send another version soon.

Thanks.

Best regards,
KHIEM Nguyen

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-09-08 16:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-03  5:25 [PATCH 2/5 v2] thermal: rcar_gen3_thermal: Add R-Car Gen3 thermal driver Khiem Nguyen
2016-09-05  1:09 ` Kuninori Morimoto
2016-09-05 10:01 ` Geert Uytterhoeven
2016-09-06 12:19   ` Khiem Nguyen
2016-09-06 12:24     ` Geert Uytterhoeven
2016-09-06  0:51 ` Zhang Rui
2016-09-08 16:08   ` Khiem Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).