diff mbox

[V11,6/6] thermal: bcm2835: add thermal driver for bcm2835 SoC

Message ID 1489356665-3175-7-git-send-email-stefan.wahren@i2se.com (mailing list archive)
State Changes Requested
Delegated to: Eduardo Valentin
Headers show

Commit Message

Stefan Wahren March 12, 2017, 10:11 p.m. UTC
Add basic thermal driver for bcm2835 SoC.

This driver currently make sure that tsense HW block is set up
correctly.

Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Acked-by: Eric Anholt <eric@anholt.net>
---
 drivers/thermal/Kconfig           |    8 +
 drivers/thermal/Makefile          |    1 +
 drivers/thermal/bcm2835_thermal.c |  315 +++++++++++++++++++++++++++++++++++++
 3 files changed, 324 insertions(+)
 create mode 100644 drivers/thermal/bcm2835_thermal.c

Comments

Nobuhiro Iwamatsu March 23, 2017, 4:53 p.m. UTC | #1
Hi, Stefan.

2017-03-13 7:11 GMT+09:00 Stefan Wahren <stefan.wahren@i2se.com>:
> Add basic thermal driver for bcm2835 SoC.
>
> This driver currently make sure that tsense HW block is set up
> correctly.
>
> Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> Acked-by: Eric Anholt <eric@anholt.net>
> ---
>  drivers/thermal/Kconfig           |    8 +
>  drivers/thermal/Makefile          |    1 +
>  drivers/thermal/bcm2835_thermal.c |  315 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 324 insertions(+)
>  create mode 100644 drivers/thermal/bcm2835_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 776b343..3bd2406 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -453,4 +453,12 @@ config ZX2967_THERMAL
>           the primitive temperature sensor embedded in zx2967 SoCs.
>           This sensor generates the real time die temperature.
>
> +config BCM2835_THERMAL
> +       tristate "Thermal sensors on bcm2835 SoC"
> +       depends on ARCH_BCM2835 || COMPILE_TEST
> +       depends on HAS_IOMEM
> +       depends on THERMAL_OF
> +       help
> +         Support for thermal sensors on Broadcom bcm2835 SoCs.
> +
>  endif
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 7adae20..f23cde0 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -58,3 +58,4 @@ obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
>  obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
>  obj-$(CONFIG_GENERIC_ADC_THERMAL)      += thermal-generic-adc.o
>  obj-$(CONFIG_ZX2967_THERMAL)   += zx2967_thermal.o
> +obj-$(CONFIG_BCM2835_THERMAL)  += bcm2835_thermal.o
> diff --git a/drivers/thermal/bcm2835_thermal.c b/drivers/thermal/bcm2835_thermal.c
> new file mode 100644
> index 0000000..a9768f1
> --- /dev/null
> +++ b/drivers/thermal/bcm2835_thermal.c

<snip>

> +static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
> +       .get_temp = bcm2835_thermal_get_temp,
> +};
> +
> +static const struct of_device_id bcm2835_thermal_of_match_table[];

bcm2835_thermal_of_match_table has been defined twice.
I think that it is better to define bcm2835_thermal_of_match_table below
or move bcm2835_thermal_probe to bottom.

Best regards,
  Nobuhiro
Stefan Wahren March 23, 2017, 6:52 p.m. UTC | #2
Hi Nobuhiro,

> Nobuhiro Iwamatsu <iwamatsu@nigauri.org> hat am 23. März 2017 um 17:53 geschrieben:
> 
> 
> Hi, Stefan.
> 
> 2017-03-13 7:11 GMT+09:00 Stefan Wahren <stefan.wahren@i2se.com>:
> > Add basic thermal driver for bcm2835 SoC.
> >
> > This driver currently make sure that tsense HW block is set up
> > correctly.
> >
> > Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> > Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> > Acked-by: Eric Anholt <eric@anholt.net>
> > ---
> >  drivers/thermal/Kconfig           |    8 +
> >  drivers/thermal/Makefile          |    1 +
> >  drivers/thermal/bcm2835_thermal.c |  315 +++++++++++++++++++++++++++++++++++++
> >  3 files changed, 324 insertions(+)
> >  create mode 100644 drivers/thermal/bcm2835_thermal.c
> >
> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> > index 776b343..3bd2406 100644
> > --- a/drivers/thermal/Kconfig
> > +++ b/drivers/thermal/Kconfig
> > @@ -453,4 +453,12 @@ config ZX2967_THERMAL
> >           the primitive temperature sensor embedded in zx2967 SoCs.
> >           This sensor generates the real time die temperature.
> >
> > +config BCM2835_THERMAL
> > +       tristate "Thermal sensors on bcm2835 SoC"
> > +       depends on ARCH_BCM2835 || COMPILE_TEST
> > +       depends on HAS_IOMEM
> > +       depends on THERMAL_OF
> > +       help
> > +         Support for thermal sensors on Broadcom bcm2835 SoCs.
> > +
> >  endif
> > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> > index 7adae20..f23cde0 100644
> > --- a/drivers/thermal/Makefile
> > +++ b/drivers/thermal/Makefile
> > @@ -58,3 +58,4 @@ obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> >  obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
> >  obj-$(CONFIG_GENERIC_ADC_THERMAL)      += thermal-generic-adc.o
> >  obj-$(CONFIG_ZX2967_THERMAL)   += zx2967_thermal.o
> > +obj-$(CONFIG_BCM2835_THERMAL)  += bcm2835_thermal.o
> > diff --git a/drivers/thermal/bcm2835_thermal.c b/drivers/thermal/bcm2835_thermal.c
> > new file mode 100644
> > index 0000000..a9768f1
> > --- /dev/null
> > +++ b/drivers/thermal/bcm2835_thermal.c
> 
> <snip>
> 
> > +static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
> > +       .get_temp = bcm2835_thermal_get_temp,
> > +};
> > +
> > +static const struct of_device_id bcm2835_thermal_of_match_table[];
> 
> bcm2835_thermal_of_match_table has been defined twice.
> I think that it is better to define bcm2835_thermal_of_match_table below
> or move bcm2835_thermal_probe to bottom.

thanks for catching. I'm currently waiting for feedback from Eduardo and Rob before sending a new version.

Stefan

> 
> Best regards,
>   Nobuhiro
> 
> -- 
> Nobuhiro Iwamatsu
>    iwamatsu at {nigauri.org / debian.org}
>    GPG ID: 40AD1FA6
Eduardo Valentin March 29, 2017, 4:58 a.m. UTC | #3
On Sun, Mar 12, 2017 at 10:11:05PM +0000, Stefan Wahren wrote:
> Add basic thermal driver for bcm2835 SoC.
> 
> This driver currently make sure that tsense HW block is set up
> correctly.
> 
> Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> Acked-by: Eric Anholt <eric@anholt.net>

I see no issue with this driver at this point.

As I mentioned, the full series needs to go together. You either get an
Ack from OF maintainers, and I take the series, or you can add my

Acked-by: Eduardo Valentin <edubezval@gmail.com>

after fixing the small comment from Nobuhiro.

> ---
>  drivers/thermal/Kconfig           |    8 +
>  drivers/thermal/Makefile          |    1 +
>  drivers/thermal/bcm2835_thermal.c |  315 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 324 insertions(+)
>  create mode 100644 drivers/thermal/bcm2835_thermal.c
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 776b343..3bd2406 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -453,4 +453,12 @@ config ZX2967_THERMAL
>  	  the primitive temperature sensor embedded in zx2967 SoCs.
>  	  This sensor generates the real time die temperature.
>  
> +config BCM2835_THERMAL
> +	tristate "Thermal sensors on bcm2835 SoC"
> +	depends on ARCH_BCM2835 || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	depends on THERMAL_OF
> +	help
> +	  Support for thermal sensors on Broadcom bcm2835 SoCs.

small suggestion here:

-If you are sending a new version fixing Nobuhiro comment, you could take
the opportunity to improve the driver Kconfig help description.
Eduardo Valentin March 30, 2017, 4:57 a.m. UTC | #4
On Tue, Mar 28, 2017 at 09:58:09PM -0700, Eduardo Valentin wrote:
> On Sun, Mar 12, 2017 at 10:11:05PM +0000, Stefan Wahren wrote:
> > Add basic thermal driver for bcm2835 SoC.
> > 
> > This driver currently make sure that tsense HW block is set up
> > correctly.
> > 
> > Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> > Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> > Acked-by: Eric Anholt <eric@anholt.net>
> 
> I see no issue with this driver at this point.
> 
> As I mentioned, the full series needs to go together. You either get an
> Ack from OF maintainers, and I take the series, or you can add my
> 
> Acked-by: Eduardo Valentin <edubezval@gmail.com>
> 
> after fixing the small comment from Nobuhiro.
> 

Based on other drivers that require negative values, I assume patches 1
and 2 of these series are needed, but more for enforcing the API, given
that the current of-thermal driver still retrieves the negative values
from DTB [1].

A third option on top of what I suggested above is to split the series.
Given that you could still get the proper coefficients
with current of-thermal, I would suggest you to split this series into
two (patches 1-2, 3-6) in your next version, so we avoid futher delays
on the driver, while patches 1-2 waits for acks from OF side.

[1] - https://patchwork.kernel.org/patch/9612613/
Stefan Wahren March 30, 2017, 6:30 a.m. UTC | #5
> Eduardo Valentin <edubezval@gmail.com> hat am 30. März 2017 um 06:57 geschrieben:
> 
> 
> On Tue, Mar 28, 2017 at 09:58:09PM -0700, Eduardo Valentin wrote:
> > On Sun, Mar 12, 2017 at 10:11:05PM +0000, Stefan Wahren wrote:
> > > Add basic thermal driver for bcm2835 SoC.
> > > 
> > > This driver currently make sure that tsense HW block is set up
> > > correctly.
> > > 
> > > Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> > > Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> > > Acked-by: Eric Anholt <eric@anholt.net>
> > 
> > I see no issue with this driver at this point.
> > 
> > As I mentioned, the full series needs to go together. You either get an
> > Ack from OF maintainers, and I take the series, or you can add my
> > 
> > Acked-by: Eduardo Valentin <edubezval@gmail.com>
> > 
> > after fixing the small comment from Nobuhiro.
> > 
> 
> Based on other drivers that require negative values, I assume patches 1
> and 2 of these series are needed, but more for enforcing the API, given
> that the current of-thermal driver still retrieves the negative values
> from DTB [1].
> 
> [1] - https://patchwork.kernel.org/patch/9612613/

I can't see that the OMAP5 thermal driver is using thermal_zone_get_slope() [2]. I got the wrong values without patch 1 and 2. So i wouldn't rely on that statement. But i will doublecheck it.

[2] - http://elixir.free-electrons.com/ident?v=4.11-rc4&i=thermal_zone_get_slope
Stefan Wahren March 30, 2017, 7:11 p.m. UTC | #6
Hi Eduardo,

> Eduardo Valentin <edubezval@gmail.com> hat am 30. März 2017 um 06:57 geschrieben:
> 
> 
> On Tue, Mar 28, 2017 at 09:58:09PM -0700, Eduardo Valentin wrote:
> > On Sun, Mar 12, 2017 at 10:11:05PM +0000, Stefan Wahren wrote:
> > > Add basic thermal driver for bcm2835 SoC.
> > > 
> > > This driver currently make sure that tsense HW block is set up
> > > correctly.
> > > 
> > > Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> > > Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> > > Acked-by: Eric Anholt <eric@anholt.net>
> > 
> > I see no issue with this driver at this point.
> > 
> > As I mentioned, the full series needs to go together. You either get an
> > Ack from OF maintainers, and I take the series, or you can add my
> > 
> > Acked-by: Eduardo Valentin <edubezval@gmail.com>
> > 
> > after fixing the small comment from Nobuhiro.
> > 
> 
> Based on other drivers that require negative values, I assume patches 1
> and 2 of these series are needed, but more for enforcing the API, given
> that the current of-thermal driver still retrieves the negative values
> from DTB [1].
> 
> A third option on top of what I suggested above is to split the series.
> Given that you could still get the proper coefficients
> with current of-thermal, I would suggest you to split this series into
> two (patches 1-2, 3-6) in your next version, so we avoid futher delays
> on the driver, while patches 1-2 waits for acks from OF side.

i revert patches #1, #2 and the slope value was still correct. So i will choose the third option and split the series.

Thanks
Stefan

> 
> [1] - https://patchwork.kernel.org/patch/9612613/
Eduardo Valentin March 31, 2017, 1:06 a.m. UTC | #7
Hello,
On Thu, Mar 30, 2017 at 09:11:41PM +0200, Stefan Wahren wrote:
> Hi Eduardo,
> 
> > Eduardo Valentin <edubezval@gmail.com> hat am 30. März 2017 um 06:57 geschrieben:
> > 
> > 

<cut>

> > A third option on top of what I suggested above is to split the series.
> > Given that you could still get the proper coefficients
> > with current of-thermal, I would suggest you to split this series into
> > two (patches 1-2, 3-6) in your next version, so we avoid futher delays
> > on the driver, while patches 1-2 waits for acks from OF side.
> 
> i revert patches #1, #2 and the slope value was still correct. So i will choose the third option and split the series.

Sounds good to me.

> 
> Thanks
> Stefan
> 
> > 
> > [1] - https://patchwork.kernel.org/patch/9612613/
Eduardo Valentin March 31, 2017, 1:08 a.m. UTC | #8
Hello,

On Thu, Mar 30, 2017 at 08:30:29AM +0200, Stefan Wahren wrote:
> 
> > Eduardo Valentin <edubezval@gmail.com> hat am 30. März 2017 um 06:57 geschrieben:
> > 
> > 
> > On Tue, Mar 28, 2017 at 09:58:09PM -0700, Eduardo Valentin wrote:
> > > On Sun, Mar 12, 2017 at 10:11:05PM +0000, Stefan Wahren wrote:
> > > > Add basic thermal driver for bcm2835 SoC.
> > > > 
> > > > This driver currently make sure that tsense HW block is set up
> > > > correctly.
> > > > 
> > > > Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
> > > > Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> > > > Acked-by: Eric Anholt <eric@anholt.net>
> > > 
> > > I see no issue with this driver at this point.
> > > 
> > > As I mentioned, the full series needs to go together. You either get an
> > > Ack from OF maintainers, and I take the series, or you can add my
> > > 
> > > Acked-by: Eduardo Valentin <edubezval@gmail.com>
> > > 
> > > after fixing the small comment from Nobuhiro.
> > > 
> > 
> > Based on other drivers that require negative values, I assume patches 1
> > and 2 of these series are needed, but more for enforcing the API, given
> > that the current of-thermal driver still retrieves the negative values
> > from DTB [1].
> > 
> > [1] - https://patchwork.kernel.org/patch/9612613/
> 
> I can't see that the OMAP5 thermal driver is using thermal_zone_get_slope() [2]. I got the wrong values without patch 1 and 2. So i wouldn't rely on that statement. But i will doublecheck it.

The TI-SoC driver is not currently using the slope and offset from DT.
But on my -linus branch I have added three patches from Keerthy that
adds that support.

Anyways, I am assuming you are also getting correct values at your end,
based on your other email.

BR,

> 
> [2] - http://elixir.free-electrons.com/ident?v=4.11-rc4&i=thermal_zone_get_slope
diff mbox

Patch

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 776b343..3bd2406 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -453,4 +453,12 @@  config ZX2967_THERMAL
 	  the primitive temperature sensor embedded in zx2967 SoCs.
 	  This sensor generates the real time die temperature.
 
+config BCM2835_THERMAL
+	tristate "Thermal sensors on bcm2835 SoC"
+	depends on ARCH_BCM2835 || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on THERMAL_OF
+	help
+	  Support for thermal sensors on Broadcom bcm2835 SoCs.
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 7adae20..f23cde0 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -58,3 +58,4 @@  obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
 obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o
+obj-$(CONFIG_BCM2835_THERMAL)	+= bcm2835_thermal.o
diff --git a/drivers/thermal/bcm2835_thermal.c b/drivers/thermal/bcm2835_thermal.c
new file mode 100644
index 0000000..a9768f1
--- /dev/null
+++ b/drivers/thermal/bcm2835_thermal.c
@@ -0,0 +1,315 @@ 
+/*
+ * Driver for Broadcom BCM2835 SoC temperature sensor
+ *
+ * Copyright (C) 2016 Martin Sperl
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/clk.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define BCM2835_TS_TSENSCTL			0x00
+#define BCM2835_TS_TSENSSTAT			0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW		BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB		BIT(1)
+
+/*
+ * bandgap reference voltage in 6 mV increments
+ * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
+ */
+#define BCM2835_TS_TSENSCTL_CTRL_BITS		3
+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT		2
+#define BCM2835_TS_TSENSCTL_CTRL_MASK		    \
+	GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS +     \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT)
+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT	1
+#define BCM2835_TS_TSENSCTL_EN_INT		BIT(5)
+#define BCM2835_TS_TSENSCTL_DIRECT		BIT(6)
+#define BCM2835_TS_TSENSCTL_CLR_INT		BIT(7)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT		8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS		10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK		     \
+	GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+/*
+ * time how long the block to be asserted in reset
+ * which based on a clock counter (TSENS clock assumed)
+ */
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT	18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS	8
+#define BCM2835_TS_TSENSCTL_REGULEN		BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS		10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT		0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK		     \
+	GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID		BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT		BIT(11)
+
+struct bcm2835_thermal_data {
+	struct thermal_zone_device *tz;
+	void __iomem *regs;
+	struct clk *clk;
+	struct dentry *debugfsdir;
+};
+
+static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
+{
+	return offset + slope * adc;
+}
+
+static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
+{
+	temp -= offset;
+	temp /= slope;
+
+	if (temp < 0)
+		temp = 0;
+	if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
+		temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
+
+	return temp;
+}
+
+static int bcm2835_thermal_get_temp(void *d, int *temp)
+{
+	struct bcm2835_thermal_data *data = d;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
+
+	if (!(val & BCM2835_TS_TSENSSTAT_VALID))
+		return -EIO;
+
+	val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+
+	*temp = bcm2835_thermal_adc2temp(
+		val,
+		thermal_zone_get_offset(data->tz),
+		thermal_zone_get_slope(data->tz));
+
+	return 0;
+}
+
+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
+	{
+		.name = "ctl",
+		.offset = 0
+	},
+	{
+		.name = "stat",
+		.offset = 4
+	}
+};
+
+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+	struct debugfs_regset32 *regset;
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = bcm2835_thermal_regs;
+	regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
+	regset->base = data->regs;
+
+	debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
+}
+
+static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
+	.get_temp = bcm2835_thermal_get_temp,
+};
+
+static const struct of_device_id bcm2835_thermal_of_match_table[];
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct thermal_zone_device *tz;
+	struct bcm2835_thermal_data *data;
+	struct resource *res;
+	int err = 0;
+	u32 val;
+	unsigned long rate;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	match = of_match_device(bcm2835_thermal_of_match_table,
+				&pdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->regs)) {
+		err = PTR_ERR(data->regs);
+		dev_err(&pdev->dev, "Could not get registers: %d\n", err);
+		return err;
+	}
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		err = PTR_ERR(data->clk);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Could not get clk: %d\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(data->clk);
+	if (err)
+		return err;
+
+	rate = clk_get_rate(data->clk);
+	if ((rate < 1920000) || (rate > 5000000))
+		dev_warn(&pdev->dev,
+			 "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
+			 data->clk, data->clk);
+
+	/* register of thermal sensor and get info from DT */
+	tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
+					     &bcm2835_thermal_ops);
+	if (IS_ERR(tz)) {
+		err = PTR_ERR(tz);
+		dev_err(&pdev->dev,
+			"Failed to register the thermal device: %d\n",
+			err);
+		goto err_clk;
+	}
+
+	/*
+	 * right now the FW does set up the HW-block, so we are not
+	 * touching the configuration registers.
+	 * But if the HW is not enabled, then set it up
+	 * using "sane" values used by the firmware right now.
+	 */
+	val = readl(data->regs + BCM2835_TS_TSENSCTL);
+	if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
+		int trip_temp, offset, slope;
+
+		slope = thermal_zone_get_slope(tz);
+		offset = thermal_zone_get_offset(tz);
+		/*
+		 * For now we deal only with critical, otherwise
+		 * would need to iterate
+		 */
+		err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
+		if (err < 0) {
+			err = PTR_ERR(tz);
+			dev_err(&pdev->dev,
+				"Not able to read trip_temp: %d\n",
+				err);
+			goto err_tz;
+		}
+
+		/* set bandgap reference voltage and enable voltage regulator */
+		val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
+		       BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
+		      BCM2835_TS_TSENSCTL_REGULEN;
+
+		/* use the recommended reset duration */
+		val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
+
+		/*  trip_adc value from info */
+		val |= bcm2835_thermal_temp2adc(trip_temp,
+						offset,
+						slope)
+			<< BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+		/* write the value back to the register as 2 steps */
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+		val |= BCM2835_TS_TSENSCTL_RSTB;
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+	}
+
+	data->tz = tz;
+
+	platform_set_drvdata(pdev, tz);
+
+	bcm2835_thermal_debugfs(pdev);
+
+	return 0;
+err_tz:
+	thermal_zone_of_sensor_unregister(&pdev->dev, tz);
+err_clk:
+	clk_disable_unprepare(data->clk);
+
+	return err;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+
+	debugfs_remove_recursive(data->debugfsdir);
+	thermal_zone_of_sensor_unregister(&pdev->dev, tz);
+	clk_disable_unprepare(data->clk);
+
+	return 0;
+}
+
+/*
+ * Note: as per Raspberry Foundation FAQ
+ * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
+ * the recommended temperature range for the SoC -40C to +85C
+ * so the trip limit is set to 80C.
+ * this applies to all the BCM283X SoC
+ */
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+	{
+		.compatible = "brcm,bcm2835-thermal",
+	},
+	{
+		.compatible = "brcm,bcm2836-thermal",
+	},
+	{
+		.compatible = "brcm,bcm2837-thermal",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static struct platform_driver bcm2835_thermal_driver = {
+	.probe = bcm2835_thermal_probe,
+	.remove = bcm2835_thermal_remove,
+	.driver = {
+		.name = "bcm2835_thermal",
+		.of_match_table = bcm2835_thermal_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");