diff mbox

[v4,4/6] iio: adc: sun4i-gpadc-iio: add support for H3 thermal sensor

Message ID 20170914145251.21784-5-icenowy@aosc.io (mailing list archive)
State New, archived
Headers show

Commit Message

Icenowy Zheng Sept. 14, 2017, 2:52 p.m. UTC
This adds support for the Allwinner H3 thermal sensor.

Allwinner H3 has a thermal sensor like the one in A33, but have its
registers nearly all re-arranged, sample clock moved to CCU and a pair
of bus clock and reset added. It's also the base of newer SoCs' thermal
sensors.

The thermal sensors on A64 and H5 is like the one on H3, but with of
course different formula factors.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Changes in v4:
- Splitted out some code refactors.
- Code sequence changed back. (The gpadc_data went back to the start of
  the source file)

 drivers/iio/adc/sun4i-gpadc-iio.c | 48 +++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/sun4i-gpadc.h   | 27 ++++++++++++++++++++++
 2 files changed, 75 insertions(+)

Comments

Quentin Schulz Sept. 16, 2017, 9:45 a.m. UTC | #1
Hi Icenowy,

On 14/09/2017 16:52, Icenowy Zheng wrote:
> This adds support for the Allwinner H3 thermal sensor.
> 
> Allwinner H3 has a thermal sensor like the one in A33, but have its
> registers nearly all re-arranged, sample clock moved to CCU and a pair
> of bus clock and reset added. It's also the base of newer SoCs' thermal
> sensors.
> 
> The thermal sensors on A64 and H5 is like the one on H3, but with of
> course different formula factors.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Changes in v4:
> - Splitted out some code refactors.
> - Code sequence changed back. (The gpadc_data went back to the start of
>   the source file)
> 
>  drivers/iio/adc/sun4i-gpadc-iio.c | 48 +++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/sun4i-gpadc.h   | 27 ++++++++++++++++++++++
>  2 files changed, 75 insertions(+)
[...]
> diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
> index 78d31984a222..5c2a12101052 100644
> --- a/include/linux/mfd/sun4i-gpadc.h
> +++ b/include/linux/mfd/sun4i-gpadc.h
[...]
> +#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x)			((GENMASK(15, 0) * (x)) << 16)
> +

You want to replace * by &.

((GENMASK(15, 0) & (x)) << 16)

Would ((GENMASK(31, 16) & ((x) << 16)) make the bits you set even more
obvious?

>  #define SUN4I_GPADC_CTRL3				0x0c
> +/*
> + * This register is named "Average filter Control Register" in H3 Datasheet,
> + * but the register's definition is the same as the old CTRL3 register.
> + */
> +#define SUN8I_H3_GPADC_CTRL3				0x70
>  

I would name it as it is in the documentation:
SUN8I_H3_THS_FILTER

No need for comments then.

>  #define SUN4I_GPADC_CTRL3_FILTER_EN			BIT(2)
>  #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
> @@ -71,6 +84,13 @@
>  #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN		BIT(1)
>  #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN		BIT(0)
>  
> +#define SUN8I_H3_GPADC_INTC				0x44
> +
> +#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
> +#define SUN8I_H3_GPADC_INTC_TEMP_DATA			BIT(8)
> +#define SUN8I_H3_GPADC_INTC_TEMP_SHUT			BIT(4)
> +#define SUN8I_H3_GPADC_INTC_TEMP_ALARM			BIT(0)
> +

Since it isn't an ADC anymore but rather just a THS, why don't you use
SUN8I_H3_THS instead of SUN8I_H3_GPADC? That way, it also matches the
datasheet.

>  #define SUN4I_GPADC_INT_FIFOS				0x14
>  
>  #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING		BIT(18)
> @@ -80,9 +100,16 @@
>  #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING		BIT(1)
>  #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING		BIT(0)
>  
> +#define SUN8I_H3_GPADC_INTS				0x44

0x48

[...]

1) You're not using irqs, why would you define registers that will never
be used?

2) Why aren't you using irqs? I remember we discussed on IRC that you
had some problems with the H3 when resuming or when probing the driver.
The register would have a zero in it until you have a first sample that
arrived (i.e. after the sample rate you set with T_ACQ) that would make
the thermal framework panic since the thermal sensor would return
something way too hot and shutdown your board?

The H3 apparently supports IRQs, why do you not support them for the
temperature? They might be broken as it is on A33 but then it might be a
good idea to write it down in a comment in the driver (and not adding
the unused registers in the header file) or at least in the commit log.

3) Now that you have support for clocks, wouldn't it be a good idea to
disable them during suspend?

Thanks,
Quentin
Icenowy Zheng Sept. 16, 2017, 10:14 a.m. UTC | #2
在 2017-09-16 17:45,Quentin Schulz 写道:
> Hi Icenowy,
> 
> On 14/09/2017 16:52, Icenowy Zheng wrote:
>> This adds support for the Allwinner H3 thermal sensor.
>> 
>> Allwinner H3 has a thermal sensor like the one in A33, but have its
>> registers nearly all re-arranged, sample clock moved to CCU and a pair
>> of bus clock and reset added. It's also the base of newer SoCs' 
>> thermal
>> sensors.
>> 
>> The thermal sensors on A64 and H5 is like the one on H3, but with of
>> course different formula factors.
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> ---
>> Changes in v4:
>> - Splitted out some code refactors.
>> - Code sequence changed back. (The gpadc_data went back to the start 
>> of
>>   the source file)
>> 
>>  drivers/iio/adc/sun4i-gpadc-iio.c | 48 
>> +++++++++++++++++++++++++++++++++++++++
>>  include/linux/mfd/sun4i-gpadc.h   | 27 ++++++++++++++++++++++
>>  2 files changed, 75 insertions(+)
> [...]
>> diff --git a/include/linux/mfd/sun4i-gpadc.h 
>> b/include/linux/mfd/sun4i-gpadc.h
>> index 78d31984a222..5c2a12101052 100644
>> --- a/include/linux/mfd/sun4i-gpadc.h
>> +++ b/include/linux/mfd/sun4i-gpadc.h
> [...]
>> +#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x)			((GENMASK(15, 0) * (x)) << 
>> 16)
>> +
> 
> You want to replace * by &.
> 
> ((GENMASK(15, 0) & (x)) << 16)
> 
> Would ((GENMASK(31, 16) & ((x) << 16)) make the bits you set even more
> obvious?
> 
>>  #define SUN4I_GPADC_CTRL3				0x0c
>> +/*
>> + * This register is named "Average filter Control Register" in H3 
>> Datasheet,
>> + * but the register's definition is the same as the old CTRL3 
>> register.
>> + */
>> +#define SUN8I_H3_GPADC_CTRL3				0x70
>> 
> 
> I would name it as it is in the documentation:
> SUN8I_H3_THS_FILTER

The definition of this register is the same as the CTRL3.

Maybe this name is better, but the similarity between them still needs
to be documented, as the SUN4I_GPADC_CTRL3_XXX macros will be used to
populate this register.

> 
> No need for comments then.
> 
>>  #define SUN4I_GPADC_CTRL3_FILTER_EN			BIT(2)
>>  #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
>> @@ -71,6 +84,13 @@
>>  #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN		BIT(1)
>>  #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN		BIT(0)
>> 
>> +#define SUN8I_H3_GPADC_INTC				0x44
>> +
>> +#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) 
>> << 12)
>> +#define SUN8I_H3_GPADC_INTC_TEMP_DATA			BIT(8)
>> +#define SUN8I_H3_GPADC_INTC_TEMP_SHUT			BIT(4)
>> +#define SUN8I_H3_GPADC_INTC_TEMP_ALARM			BIT(0)
>> +
> 
> Since it isn't an ADC anymore but rather just a THS, why don't you use
> SUN8I_H3_THS instead of SUN8I_H3_GPADC? That way, it also matches the
> datasheet.
> 
>>  #define SUN4I_GPADC_INT_FIFOS				0x14
>> 
>>  #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING		BIT(18)
>> @@ -80,9 +100,16 @@
>>  #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING		BIT(1)
>>  #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING		BIT(0)
>> 
>> +#define SUN8I_H3_GPADC_INTS				0x44
> 
> 0x48
> 
> [...]
> 
> 1) You're not using irqs, why would you define registers that will 
> never
> be used?

I will then rework it to use IRQs, but not now.

Maybe I should add it when I use them?

> 
> 2) Why aren't you using irqs? I remember we discussed on IRC that you
> had some problems with the H3 when resuming or when probing the driver.
> The register would have a zero in it until you have a first sample that
> arrived (i.e. after the sample rate you set with T_ACQ) that would make
> the thermal framework panic since the thermal sensor would return
> something way too hot and shutdown your board?

Nope, it's another problem -- the runtime resume function is even not
called before the first sample, and the first sample will happen when
the THS is still suspended.

> 
> The H3 apparently supports IRQs, why do you not support them for the
> temperature? They might be broken as it is on A33 but then it might be 
> a
> good idea to write it down in a comment in the driver (and not adding
> the unused registers in the header file) or at least in the commit log.
> 
> 3) Now that you have support for clocks, wouldn't it be a good idea to
> disable them during suspend?

Interesting... It's meaningful to disable the mod clock during suspend.

> 
> Thanks,
> Quentin
Quentin Schulz Sept. 16, 2017, 10:35 a.m. UTC | #3
Hi Icenowy,

On 16/09/2017 12:14, icenowy@aosc.io wrote:
> 在 2017-09-16 17:45,Quentin Schulz 写道:
>> Hi Icenowy,
>>
>> On 14/09/2017 16:52, Icenowy Zheng wrote:
>>> This adds support for the Allwinner H3 thermal sensor.
>>>
>>> Allwinner H3 has a thermal sensor like the one in A33, but have its
>>> registers nearly all re-arranged, sample clock moved to CCU and a pair
>>> of bus clock and reset added. It's also the base of newer SoCs' thermal
>>> sensors.
>>>
>>> The thermal sensors on A64 and H5 is like the one on H3, but with of
>>> course different formula factors.
>>>
>>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>> ---
>>> Changes in v4:
>>> - Splitted out some code refactors.
>>> - Code sequence changed back. (The gpadc_data went back to the start of
>>>   the source file)
>>>
>>>  drivers/iio/adc/sun4i-gpadc-iio.c | 48
>>> +++++++++++++++++++++++++++++++++++++++
>>>  include/linux/mfd/sun4i-gpadc.h   | 27 ++++++++++++++++++++++
>>>  2 files changed, 75 insertions(+)
[...]
>>>  #define SUN4I_GPADC_CTRL3                0x0c
>>> +/*
>>> + * This register is named "Average filter Control Register" in H3
>>> Datasheet,
>>> + * but the register's definition is the same as the old CTRL3 register.
>>> + */
>>> +#define SUN8I_H3_GPADC_CTRL3                0x70
>>>
>>
>> I would name it as it is in the documentation:
>> SUN8I_H3_THS_FILTER
> 
> The definition of this register is the same as the CTRL3.
> 
> Maybe this name is better, but the similarity between them still needs
> to be documented, as the SUN4I_GPADC_CTRL3_XXX macros will be used to
> populate this register.
> 
>>
>> No need for comments then.
>>
>>>  #define SUN4I_GPADC_CTRL3_FILTER_EN            BIT(2)
>>>  #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)        (GENMASK(1, 0) & (x))

They have _FILTER_ in their name, isn't it enough?

Just a matter of taste for me.

>>> @@ -71,6 +84,13 @@
>>>  #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN        BIT(1)
>>>  #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN        BIT(0)
>>>
>>> +#define SUN8I_H3_GPADC_INTC                0x44
>>> +
>>> +#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x)        ((GENMASK(19, 0) &
>>> (x)) << 12)
>>> +#define SUN8I_H3_GPADC_INTC_TEMP_DATA            BIT(8)
>>> +#define SUN8I_H3_GPADC_INTC_TEMP_SHUT            BIT(4)
>>> +#define SUN8I_H3_GPADC_INTC_TEMP_ALARM            BIT(0)
>>> +
>>
>> Since it isn't an ADC anymore but rather just a THS, why don't you use
>> SUN8I_H3_THS instead of SUN8I_H3_GPADC? That way, it also matches the
>> datasheet.
>>
>>>  #define SUN4I_GPADC_INT_FIFOS                0x14
>>>
>>>  #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING        BIT(18)
>>> @@ -80,9 +100,16 @@
>>>  #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING        BIT(1)
>>>  #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING        BIT(0)
>>>
>>> +#define SUN8I_H3_GPADC_INTS                0x44
>>
>> 0x48
>>
>> [...]
>>
>> 1) You're not using irqs, why would you define registers that will never
>> be used?
> 
> I will then rework it to use IRQs, but not now.
> 
> Maybe I should add it when I use them?
> 

Why not make it work right away the way we want :)?

>>
>> 2) Why aren't you using irqs? I remember we discussed on IRC that you
>> had some problems with the H3 when resuming or when probing the driver.
>> The register would have a zero in it until you have a first sample that
>> arrived (i.e. after the sample rate you set with T_ACQ) that would make
>> the thermal framework panic since the thermal sensor would return
>> something way too hot and shutdown your board?
> 
> Nope, it's another problem -- the runtime resume function is even not
> called before the first sample, and the first sample will happen when
> the THS is still suspended.
> 

As discussed on IRC (a long time ago :) ), it's a combination of two
problems:
1) get_temp (used by thermal framework) uses pm_runtime function that
isn't ready yet <= I will send a patch for registering thermal framework
after pm_runtime to you, hopefully in the upcoming hour or tomorrow,

2) The A33 (and H3 in your implementation) does not wait for an
interrupt to read the TEMP_DATA register which resets to 0 when the
sensor is disabled (or until a first sample arrives) i.e. when probing
or when resuming. Using IRQs would get rid of 2). It isn't critical for
A33 as the formula for temp returns something really cold so thermal
does not care. But for the H3, it's critically hot and shuts down your
board. To make it work on the H3, we would have to use a delay in the
pm_resume function equal to the sensor sampling rate and I don't really
like that. If we could use IRQs, it'd be better IMHO (but they aren't
working on A33).

Thanks,
Quentin

>>
>> The H3 apparently supports IRQs, why do you not support them for the
>> temperature? They might be broken as it is on A33 but then it might be a
>> good idea to write it down in a comment in the driver (and not adding
>> the unused registers in the header file) or at least in the commit log.
>>
>> 3) Now that you have support for clocks, wouldn't it be a good idea to
>> disable them during suspend?
> 
> Interesting... It's meaningful to disable the mod clock during suspend.
> 
>>
>> Thanks,
>> Quentin
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Jonathan Cameron Sept. 16, 2017, 10:16 p.m. UTC | #4
On Sat, 16 Sep 2017 11:45:47 +0200
Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> Hi Icenowy,
> 
> On 14/09/2017 16:52, Icenowy Zheng wrote:
> > This adds support for the Allwinner H3 thermal sensor.
> > 
> > Allwinner H3 has a thermal sensor like the one in A33, but have its
> > registers nearly all re-arranged, sample clock moved to CCU and a pair
> > of bus clock and reset added. It's also the base of newer SoCs' thermal
> > sensors.
> > 
> > The thermal sensors on A64 and H5 is like the one on H3, but with of
> > course different formula factors.
> > 
> > Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> > ---
> > Changes in v4:
> > - Splitted out some code refactors.
> > - Code sequence changed back. (The gpadc_data went back to the start of
> >   the source file)
> > 
> >  drivers/iio/adc/sun4i-gpadc-iio.c | 48 +++++++++++++++++++++++++++++++++++++++
> >  include/linux/mfd/sun4i-gpadc.h   | 27 ++++++++++++++++++++++
> >  2 files changed, 75 insertions(+)  
> [...]
> > diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
> > index 78d31984a222..5c2a12101052 100644
> > --- a/include/linux/mfd/sun4i-gpadc.h
> > +++ b/include/linux/mfd/sun4i-gpadc.h  
> [...]
> > +#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x)			((GENMASK(15, 0) * (x)) << 16)
> > +  
> 
> You want to replace * by &.
> 
> ((GENMASK(15, 0) & (x)) << 16)
> 
> Would ((GENMASK(31, 16) & ((x) << 16)) make the bits you set even more
> obvious?

Agreed. Would act as better 'documentation'.

Jonathan
> 
> >  #define SUN4I_GPADC_CTRL3				0x0c
> > +/*
> > + * This register is named "Average filter Control Register" in H3 Datasheet,
> > + * but the register's definition is the same as the old CTRL3 register.
> > + */
> > +#define SUN8I_H3_GPADC_CTRL3				0x70
> >    
> 
> I would name it as it is in the documentation:
> SUN8I_H3_THS_FILTER
> 
> No need for comments then.
> 
> >  #define SUN4I_GPADC_CTRL3_FILTER_EN			BIT(2)
> >  #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
> > @@ -71,6 +84,13 @@
> >  #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN		BIT(1)
> >  #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN		BIT(0)
> >  
> > +#define SUN8I_H3_GPADC_INTC				0x44
> > +
> > +#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
> > +#define SUN8I_H3_GPADC_INTC_TEMP_DATA			BIT(8)
> > +#define SUN8I_H3_GPADC_INTC_TEMP_SHUT			BIT(4)
> > +#define SUN8I_H3_GPADC_INTC_TEMP_ALARM			BIT(0)
> > +  
> 
> Since it isn't an ADC anymore but rather just a THS, why don't you use
> SUN8I_H3_THS instead of SUN8I_H3_GPADC? That way, it also matches the
> datasheet.
> 
> >  #define SUN4I_GPADC_INT_FIFOS				0x14
> >  
> >  #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING		BIT(18)
> > @@ -80,9 +100,16 @@
> >  #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING		BIT(1)
> >  #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING		BIT(0)
> >  
> > +#define SUN8I_H3_GPADC_INTS				0x44  
> 
> 0x48
> 
> [...]
> 
> 1) You're not using irqs, why would you define registers that will never
> be used?
> 
> 2) Why aren't you using irqs? I remember we discussed on IRC that you
> had some problems with the H3 when resuming or when probing the driver.
> The register would have a zero in it until you have a first sample that
> arrived (i.e. after the sample rate you set with T_ACQ) that would make
> the thermal framework panic since the thermal sensor would return
> something way too hot and shutdown your board?
> 
> The H3 apparently supports IRQs, why do you not support them for the
> temperature? They might be broken as it is on A33 but then it might be a
> good idea to write it down in a comment in the driver (and not adding
> the unused registers in the header file) or at least in the commit log.
> 
> 3) Now that you have support for clocks, wouldn't it be a good idea to
> disable them during suspend?
> 
> Thanks,
> Quentin
Maxime Ripard Sept. 18, 2017, 8:24 a.m. UTC | #5
On Sat, Sep 16, 2017 at 06:14:08PM +0800, icenowy@aosc.io wrote:
> > The H3 apparently supports IRQs, why do you not support them for the
> > temperature? They might be broken as it is on A33 but then it might be a
> > good idea to write it down in a comment in the driver (and not adding
> > the unused registers in the header file) or at least in the commit log.
> > 
> > 3) Now that you have support for clocks, wouldn't it be a good idea to
> > disable them during suspend?
> 
> Interesting... It's meaningful to disable the mod clock during suspend.

All clocks, actually. And put the device back into reset.

Maxime
diff mbox

Patch

diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 97845982d050..f7e4df6bd17a 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -59,6 +59,8 @@  struct sun4i_gpadc_iio;
  */
 static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info);
 static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info);
+static int sun8i_h3_gpadc_sample_start(struct sun4i_gpadc_iio *info);
+static int sun8i_h3_gpadc_sample_end(struct sun4i_gpadc_iio *info);
 
 struct gpadc_data {
 	int		temp_offset;
@@ -120,6 +122,24 @@  static const struct gpadc_data sun8i_a33_gpadc_data = {
 	.sample_end = sun4i_gpadc_sample_end,
 };
 
+static const struct gpadc_data sun8i_h3_gpadc_data = {
+	/*
+	 * The original formula on the datasheet seems to be wrong.
+	 * These factors are calculated based on the formula in the BSP
+	 * kernel, which is originally Tem = 217 - (T / 8.253), in which Tem
+	 * is the temperature in Celsius degree and T is the raw value
+	 * from the sensor.
+	 */
+	.temp_offset = -1791,
+	.temp_scale = -121,
+	.temp_data = SUN8I_H3_GPADC_TEMP_DATA,
+	.sample_start = sun8i_h3_gpadc_sample_start,
+	.sample_end = sun8i_h3_gpadc_sample_end,
+	.has_bus_clk = true,
+	.has_bus_rst = true,
+	.has_mod_clk = true,
+};
+
 struct sun4i_gpadc_iio {
 	struct iio_dev			*indio_dev;
 	struct completion		completion;
@@ -425,6 +445,14 @@  static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info)
 	return 0;
 }
 
+static int sun8i_h3_gpadc_sample_end(struct sun4i_gpadc_iio *info)
+{
+	/* Disable temperature sensor */
+	regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2, 0);
+
+	return 0;
+}
+
 static int sun4i_gpadc_runtime_suspend(struct device *dev)
 {
 	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
@@ -451,6 +479,22 @@  static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info)
 	return 0;
 }
 
+static int sun8i_h3_gpadc_sample_start(struct sun4i_gpadc_iio *info)
+{
+	regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2,
+		     SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN |
+		     SUN8I_H3_GPADC_CTRL2_T_ACQ1(31));
+	regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
+		     SUN4I_GPADC_CTRL0_T_ACQ(31));
+	regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL3,
+		     SUN4I_GPADC_CTRL3_FILTER_EN |
+		     SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
+	regmap_write(info->regmap, SUN8I_H3_GPADC_INTC,
+		     SUN8I_H3_GPADC_INTC_TEMP_PERIOD(800));
+
+	return 0;
+}
+
 static int sun4i_gpadc_runtime_resume(struct device *dev)
 {
 	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));
@@ -537,6 +581,10 @@  static const struct of_device_id sun4i_gpadc_of_id[] = {
 		.compatible = "allwinner,sun8i-a33-ths",
 		.data = &sun8i_a33_gpadc_data,
 	},
+	{
+		.compatible = "allwinner,sun8i-h3-ths",
+		.data = &sun8i_h3_gpadc_data,
+	},
 	{ /* sentinel */ }
 };
 
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index 78d31984a222..5c2a12101052 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -42,6 +42,9 @@ 
 #define SUN8I_A33_GPADC_CTRL1_CHOP_TEMP_EN		BIT(8)
 #define SUN8I_A33_GPADC_CTRL1_GPADC_CALI_EN		BIT(7)
 
+/* TP_CTRL1 bits for SoCs after H3 */
+#define SUN8I_H3_GPADC_CTRL1_GPADC_CALI_EN		BIT(17)
+
 #define SUN4I_GPADC_CTRL2				0x08
 
 #define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x)	((GENMASK(3, 0) & (x)) << 28)
@@ -49,7 +52,17 @@ 
 #define SUN4I_GPADC_CTRL2_PRE_MEA_EN			BIT(24)
 #define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x)		(GENMASK(23, 0) & (x))
 
+#define SUN8I_H3_GPADC_CTRL2				0x40
+
+#define SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN		BIT(0)
+#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x)			((GENMASK(15, 0) * (x)) << 16)
+
 #define SUN4I_GPADC_CTRL3				0x0c
+/*
+ * This register is named "Average filter Control Register" in H3 Datasheet,
+ * but the register's definition is the same as the old CTRL3 register.
+ */
+#define SUN8I_H3_GPADC_CTRL3				0x70
 
 #define SUN4I_GPADC_CTRL3_FILTER_EN			BIT(2)
 #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
@@ -71,6 +84,13 @@ 
 #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN		BIT(1)
 #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN		BIT(0)
 
+#define SUN8I_H3_GPADC_INTC				0x44
+
+#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
+#define SUN8I_H3_GPADC_INTC_TEMP_DATA			BIT(8)
+#define SUN8I_H3_GPADC_INTC_TEMP_SHUT			BIT(4)
+#define SUN8I_H3_GPADC_INTC_TEMP_ALARM			BIT(0)
+
 #define SUN4I_GPADC_INT_FIFOS				0x14
 
 #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING		BIT(18)
@@ -80,9 +100,16 @@ 
 #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING		BIT(1)
 #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING		BIT(0)
 
+#define SUN8I_H3_GPADC_INTS				0x44
+
+#define SUN8I_H3_GPADC_INTS_TEMP_DATA			BIT(8)
+#define SUN8I_H3_GPADC_INTS_TEMP_SHUT			BIT(4)
+#define SUN8I_H3_GPADC_INTS_TEMP_ALARM			BIT(0)
+
 #define SUN4I_GPADC_CDAT				0x1c
 #define SUN4I_GPADC_TEMP_DATA				0x20
 #define SUN4I_GPADC_DATA				0x24
+#define SUN8I_H3_GPADC_TEMP_DATA			0x80
 
 #define SUN4I_GPADC_IRQ_FIFO_DATA			0
 #define SUN4I_GPADC_IRQ_TEMP_DATA			1