diff --git a/config/kernel/linux-sun50i-dev.config b/config/kernel/linux-sun50i-dev.config index e8779234d7..4d90b61fad 100644 --- a/config/kernel/linux-sun50i-dev.config +++ b/config/kernel/linux-sun50i-dev.config @@ -2613,7 +2613,7 @@ CONFIG_SENSORS_ARM_SCPI=y # CONFIG_SENSORS_G762 is not set # CONFIG_SENSORS_GPIO_FAN is not set # CONFIG_SENSORS_HIH6130 is not set -# CONFIG_SENSORS_IIO_HWMON is not set +CONFIG_SENSORS_IIO_HWMON=m # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_JC42 is not set # CONFIG_SENSORS_POWR1220 is not set @@ -2665,7 +2665,7 @@ CONFIG_SENSORS_LM90=m # CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set -# CONFIG_SENSORS_PWM_FAN is not set +CONFIG_SENSORS_PWM_FAN=m CONFIG_SENSORS_SHT15=m CONFIG_SENSORS_SHT21=m CONFIG_SENSORS_SHT3x=m @@ -2723,7 +2723,7 @@ CONFIG_THERMAL_GOV_USER_SPACE=y CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_CLOCK_THERMAL=y -# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y CONFIG_THERMAL_EMULATION=y # CONFIG_QORIQ_THERMAL is not set diff --git a/patch/atf/atf-sun50iw1/set-rsb-to-nonsec.patch b/patch/atf/atf-sun50iw1/set-rsb-to-nonsec.patch new file mode 100644 index 0000000000..9a8df6285b --- /dev/null +++ b/patch/atf/atf-sun50iw1/set-rsb-to-nonsec.patch @@ -0,0 +1,15 @@ +diff --git a/plat/sun50iw1p1/sunxi_security.c b/plat/sun50iw1p1/sunxi_security.c +index c0036c12..76d296bd 100644 +--- a/plat/sun50iw1p1/sunxi_security.c ++++ b/plat/sun50iw1p1/sunxi_security.c +@@ -58,8 +58,9 @@ void sunxi_security_setup(void) + for (i = 0; i < 6; i++) + mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff); + +- /* switch RSB to secure */ ++ /* switch RSB to secure + mmio_write_32(SPC_DECPORT_CLR_REG(3), 0x08); ++ */ + + /* set CCMU mbus_sec, bus_sec, pll_sec to non-secure */ + mmio_write_32(0x01c20000+0x2f0, 0x7); diff --git a/patch/kernel/sun50i-dev/a64-DT-DVFS.patch b/patch/kernel/sun50i-dev/a64-DT-DVFS.patch index 13f00b9c9f..64a033bdf9 100644 --- a/patch/kernel/sun50i-dev/a64-DT-DVFS.patch +++ b/patch/kernel/sun50i-dev/a64-DT-DVFS.patch @@ -1,5 +1,5 @@ diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -index c8e7afa0..435e8f62 100644 +index c8e7afa0..dc36bc38 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -50,12 +50,72 @@ @@ -88,27 +88,30 @@ index c8e7afa0..435e8f62 100644 }; cpu1: cpu@1 { -@@ -72,6 +138,7 @@ +@@ -72,6 +138,8 @@ device_type = "cpu"; reg = <1>; enable-method = "psci"; + clocks = <&ccu 21>; ++ operating-points-v2 = <&cpu0_opp_table>; }; cpu2: cpu@2 { -@@ -79,6 +146,7 @@ +@@ -79,6 +147,8 @@ device_type = "cpu"; reg = <2>; enable-method = "psci"; + clocks = <&ccu 21>; ++ operating-points-v2 = <&cpu0_opp_table>; }; cpu3: cpu@3 { -@@ -86,6 +154,58 @@ +@@ -86,6 +156,59 @@ device_type = "cpu"; reg = <3>; enable-method = "psci"; + clocks = <&ccu 21>; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + }; + @@ -116,7 +119,7 @@ index c8e7afa0..435e8f62 100644 + cpu_thermal: cpu_thermal { + polling-delay-passive = <330>; + polling-delay = <1000>; -+ thermal-sensors = <&scpi_cpu_thermal 0>; ++ thermal-sensors = <&ths>; + + trips { + cpu_warm: cpu_warm { @@ -163,50 +166,32 @@ index c8e7afa0..435e8f62 100644 }; }; -@@ -149,6 +269,37 @@ +@@ -149,6 +272,11 @@ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; }; -+ mailbox: mbox@0 { -+ compatible = "arm,smc-mbox"; -+ #mbox-cells = <1>; -+ arm,smc-func-ids = <0x82000001>; -+ }; -+ -+ sram: sram@10000{ -+ compatible = "mmio-sram"; -+ reg = <0x10000 0x8000>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 0x10000 0x8000>; -+ -+ cpu_scp_mem: scp-shmem@7e00 { -+ compatible = "mmio-sram"; -+ reg = <0x7e00 0x200>; -+ }; -+ }; -+ -+ scpi { -+ compatible = "arm,scpi"; -+ mboxes = <&mailbox 0>; -+ shmem = <&cpu_scp_mem>; -+ -+ scpi_cpu_thermal: sensors { -+ compatible = "arm,scpi-sensors"; -+ #thermal-sensor-cells = <1>; -+ }; ++ iio-hwmon { ++ compatible = "iio-hwmon"; ++ io-channels = <&ths>; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; -@@ -477,6 +628,8 @@ - clock-names = "hosc", "losc"; - #clock-cells = <1>; - #reset-cells = <1>; -+ assigned-clocks = <&ccu CLK_THS>; -+ assigned-clock-rates = <4000000>; +@@ -594,6 +722,16 @@ + status = "disabled"; }; - pio: pinctrl@1c20800 { ++ ths: thermal-sensor@1c25000 { ++ compatible = "allwinner,sun50i-a64-ths"; ++ reg = <0x01c25000 0x100>; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; ++ clock-names = "bus", "mod"; ++ resets = <&ccu RST_BUS_THS>; ++ #thermal-sensor-cells = <0>; ++ #io-channel-cells = <0>; ++ }; ++ + uart0: serial@1c28000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28000 0x400>; diff --git a/patch/kernel/sun50i-dev/a64-DT-DVFS.patch.old b/patch/kernel/sun50i-dev/a64-DT-DVFS.patch.old new file mode 100644 index 0000000000..13f00b9c9f --- /dev/null +++ b/patch/kernel/sun50i-dev/a64-DT-DVFS.patch.old @@ -0,0 +1,212 @@ +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index c8e7afa0..435e8f62 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -50,12 +50,72 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <1000000 1000000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@648000000 { ++ opp-hz = /bits/ 64 <648000000>; ++ opp-microvolt = <1040000 1040000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <1080000 1080000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@912000000 { ++ opp-hz = /bits/ 64 <912000000>; ++ opp-microvolt = <1120000 1120000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@960000000 { ++ opp-hz = /bits/ 64 <960000000>; ++ opp-microvolt = <1160000 1160000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <1200000 1200000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1240000 1240000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@1104000000 { ++ opp-hz = /bits/ 64 <1104000000>; ++ opp-microvolt = <1260000 1260000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ ++ opp@1152000000 { ++ opp-hz = /bits/ 64 <1152000000>; ++ opp-microvolt = <1300000 1300000 1300000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -65,6 +125,12 @@ + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; ++ clocks = <&ccu 21>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ #cooling-cells = <2>; ++ cooling-min-level = <0>; ++ cooling-max-level = <8>; + }; + + cpu1: cpu@1 { +@@ -72,6 +138,7 @@ + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; ++ clocks = <&ccu 21>; + }; + + cpu2: cpu@2 { +@@ -79,6 +146,7 @@ + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; ++ clocks = <&ccu 21>; + }; + + cpu3: cpu@3 { +@@ -86,6 +154,58 @@ + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; ++ clocks = <&ccu 21>; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu_thermal: cpu_thermal { ++ polling-delay-passive = <330>; ++ polling-delay = <1000>; ++ thermal-sensors = <&scpi_cpu_thermal 0>; ++ ++ trips { ++ cpu_warm: cpu_warm { ++ temperature = <65000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_hot: cpu_hot { ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_very_hot: cpu_very_hot { ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_crit: cpu_crit { ++ temperature = <105000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ cpu_warm_limit_cpu { ++ trip = <&cpu_warm>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT 2>; ++ }; ++ ++ cpu_hot_limit_cpu { ++ trip = <&cpu_hot>; ++ cooling-device = <&cpu0 3 5>; ++ }; ++ ++ cpu_very_hot_limit_cpu { ++ trip = <&cpu_very_hot>; ++ cooling-device = <&cpu0 6 THERMAL_NO_LIMIT>; ++ }; ++ }; + }; + }; + +@@ -149,6 +269,37 @@ + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + ++ mailbox: mbox@0 { ++ compatible = "arm,smc-mbox"; ++ #mbox-cells = <1>; ++ arm,smc-func-ids = <0x82000001>; ++ }; ++ ++ sram: sram@10000{ ++ compatible = "mmio-sram"; ++ reg = <0x10000 0x8000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x10000 0x8000>; ++ ++ cpu_scp_mem: scp-shmem@7e00 { ++ compatible = "mmio-sram"; ++ reg = <0x7e00 0x200>; ++ }; ++ }; ++ ++ scpi { ++ compatible = "arm,scpi"; ++ mboxes = <&mailbox 0>; ++ shmem = <&cpu_scp_mem>; ++ ++ scpi_cpu_thermal: sensors { ++ compatible = "arm,scpi-sensors"; ++ #thermal-sensor-cells = <1>; ++ }; ++ }; ++ + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -477,6 +628,8 @@ + clock-names = "hosc", "losc"; + #clock-cells = <1>; + #reset-cells = <1>; ++ assigned-clocks = <&ccu CLK_THS>; ++ assigned-clock-rates = <4000000>; + }; + + pio: pinctrl@1c20800 { diff --git a/patch/kernel/sun50i-dev/add-sun50i-ths.patch b/patch/kernel/sun50i-dev/add-sun50i-ths.patch new file mode 100644 index 0000000000..f0377cd502 --- /dev/null +++ b/patch/kernel/sun50i-dev/add-sun50i-ths.patch @@ -0,0 +1,483 @@ +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 137f577d..b0b231da 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -22,6 +22,7 @@ + * shutdown for not being used. + */ + ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -49,46 +51,22 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan) + return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan); + } + ++struct sun4i_gpadc_iio; ++ + struct gpadc_data { + int temp_offset; + int temp_scale; ++ int temp_divider; + unsigned int tp_mode_en; + unsigned int tp_adc_select; + unsigned int (*adc_chan_select)(unsigned int chan); + unsigned int adc_chan_mask; +-}; +- +-static const struct gpadc_data sun4i_gpadc_data = { +- .temp_offset = -1932, +- .temp_scale = 133, +- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, +- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, +- .adc_chan_select = &sun4i_gpadc_chan_select, +- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, +-}; +- +-static const struct gpadc_data sun5i_gpadc_data = { +- .temp_offset = -1447, +- .temp_scale = 100, +- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, +- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, +- .adc_chan_select = &sun4i_gpadc_chan_select, +- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, +-}; +- +-static const struct gpadc_data sun6i_gpadc_data = { +- .temp_offset = -1623, +- .temp_scale = 167, +- .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN, +- .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, +- .adc_chan_select = &sun6i_gpadc_chan_select, +- .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, +-}; +- +-static const struct gpadc_data sun8i_a33_gpadc_data = { +- .temp_offset = -1662, +- .temp_scale = 162, +- .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, ++ unsigned int temp_data; ++ int (*sample_start)(struct sun4i_gpadc_iio *info); ++ int (*sample_end)(struct sun4i_gpadc_iio *info); ++ bool has_bus_clk; ++ bool has_bus_rst; ++ bool has_mod_clk; + }; + + struct sun4i_gpadc_iio { +@@ -103,6 +81,9 @@ struct sun4i_gpadc_iio { + atomic_t ignore_temp_data_irq; + const struct gpadc_data *data; + bool no_irq; ++ struct clk *ths_bus_clk; ++ struct clk *mod_clk; ++ struct reset_control *reset; + /* prevents concurrent reads of temperature and ADC */ + struct mutex mutex; + struct thermal_zone_device *tzd; +@@ -277,7 +258,7 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) + if (info->no_irq) { + pm_runtime_get_sync(indio_dev->dev.parent); + +- regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); ++ regmap_read(info->regmap, info->data->temp_data, val); + + pm_runtime_mark_last_busy(indio_dev->dev.parent); + pm_runtime_put_autosuspend(indio_dev->dev.parent); +@@ -306,6 +287,15 @@ static int sun4i_gpadc_temp_scale(struct iio_dev *indio_dev, int *val) + return 0; + } + ++static int sun4i_gpadc_temp_divider(struct iio_dev *indio_dev, int *val) ++{ ++ struct sun4i_gpadc_iio *info = iio_priv(indio_dev); ++ ++ *val = info->data->temp_divider; ++ ++ return 0; ++} ++ + static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +@@ -383,10 +373,8 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) + return IRQ_HANDLED; + } + +-static int sun4i_gpadc_runtime_suspend(struct device *dev) ++static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info) + { +- struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); +- + /* Disable the ADC on IP */ + regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); + /* Disable temperature sensor on IP */ +@@ -395,10 +383,23 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) + return 0; + } + +-static int sun4i_gpadc_runtime_resume(struct device *dev) ++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)); + ++ return info->data->sample_end(info); ++} ++ ++static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info) ++{ + /* clkin = 6MHz */ + regmap_write(info->regmap, SUN4I_GPADC_CTRL0, + SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) | +@@ -416,18 +417,52 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) + 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)); ++ ++ return info->data->sample_start(info); ++} ++ ++/* temperature = ( MINUPA - reg * MULPA) / DIVPA ++#define MULPA 25000 ++#define DIVPA 214 ++#define MINUPA 2170 ++static int sun50_th_reg_to_temp(uint32_t reg_data) ++{ ++ return ((MINUPA - (int)reg_data) * MULPA) / DIVPA; ++} ++*/ ++ + static int sun4i_gpadc_get_temp(void *data, int *temp) + { + struct sun4i_gpadc_iio *info = data; +- int val, scale, offset; ++ int val, scale, offset, divider; + + if (sun4i_gpadc_temp_read(info->indio_dev, &val)) + return -ETIMEDOUT; + + sun4i_gpadc_temp_scale(info->indio_dev, &scale); + sun4i_gpadc_temp_offset(info->indio_dev, &offset); ++ sun4i_gpadc_temp_divider(info->indio_dev, ÷r); + +- *temp = (val + offset) * scale; ++ *temp = ((val + offset) * scale) / divider; + + return 0; + } +@@ -490,11 +525,116 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, + return 0; + } + ++static const struct gpadc_data sun4i_gpadc_data = { ++ .temp_offset = -1932, ++ .temp_scale = 133, ++ .temp_divider = 1, ++ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, ++ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, ++ .adc_chan_select = &sun4i_gpadc_chan_select, ++ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, ++}; ++ ++static const struct gpadc_data sun5i_gpadc_data = { ++ .temp_offset = -1447, ++ .temp_scale = 100, ++ .temp_divider = 1, ++ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, ++ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, ++ .adc_chan_select = &sun4i_gpadc_chan_select, ++ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, ++}; ++ ++static const struct gpadc_data sun6i_gpadc_data = { ++ .temp_offset = -1623, ++ .temp_scale = 167, ++ .temp_divider = 1, ++ .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN, ++ .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, ++ .adc_chan_select = &sun6i_gpadc_chan_select, ++ .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, ++}; ++ ++static const struct gpadc_data sun8i_a33_gpadc_data = { ++ .temp_offset = -1662, ++ .temp_scale = 162, ++ .temp_divider = 1, ++ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .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_divider = 1, ++ .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, ++}; ++ ++static const struct gpadc_data sun50i_a64_gpadc_data = { ++ .temp_offset = -2170, ++ .temp_scale = -1000, ++ .temp_divider = 8560, ++ .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, ++}; ++ ++static const struct gpadc_data sun50i_h5_gpadc_data = { ++ /* Not done for now since requires 2 sets of offset+scale */ ++ .temp_offset = -1321, ++ .temp_scale = -121, ++ .temp_divider = 1, ++ .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, ++}; ++ + 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, ++ }, ++ { ++ .compatible = "allwinner,sun50i-a64-ths", ++ .data = &sun50i_a64_gpadc_data, ++ }, ++ { ++ .compatible = "allwinner,sun50i-h5-ths", ++ .data = &sun50i_h5_gpadc_data, ++ }, + { /* sentinel */ } + }; + +@@ -529,17 +669,75 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, + return ret; + } + ++ if (info->data->has_bus_rst) { ++ info->reset = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(info->reset)) { ++ ret = PTR_ERR(info->reset); ++ return ret; ++ } ++ ++ ret = reset_control_deassert(info->reset); ++ if (ret) ++ return ret; ++ } ++ ++ if (info->data->has_bus_clk) { ++ info->ths_bus_clk = devm_clk_get(&pdev->dev, "bus"); ++ if (IS_ERR(info->ths_bus_clk)) { ++ ret = PTR_ERR(info->ths_bus_clk); ++ goto assert_reset; ++ } ++ ++ ret = clk_prepare_enable(info->ths_bus_clk); ++ if (ret) ++ goto assert_reset; ++ } ++ ++ if (info->data->has_mod_clk) { ++ info->mod_clk = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(info->mod_clk)) { ++ ret = PTR_ERR(info->mod_clk); ++ goto disable_bus_clk; ++ } ++ ++ /* Running at 6MHz */ ++ ret = clk_set_rate(info->mod_clk, 6000000); ++ if (ret) ++ goto disable_bus_clk; ++ ++ ret = clk_prepare_enable(info->mod_clk); ++ if (ret) ++ goto disable_bus_clk; ++ } ++ + if (!IS_ENABLED(CONFIG_THERMAL_OF)) + return 0; + + info->sensor_device = &pdev->dev; + info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0, + info, &sun4i_ts_tz_ops); +- if (IS_ERR(info->tzd)) ++ if (IS_ERR(info->tzd)) { + dev_err(&pdev->dev, "could not register thermal sensor: %ld\n", + PTR_ERR(info->tzd)); ++ ret = PTR_ERR(info->tzd); ++ goto disable_mod_clk; ++ } + +- return PTR_ERR_OR_ZERO(info->tzd); ++ return 0; ++ ++disable_mod_clk: ++ if (info->data->has_mod_clk) ++ clk_disable_unprepare(info->mod_clk); ++ ++disable_bus_clk: ++ if (info->data->has_bus_clk) ++ clk_disable_unprepare(info->ths_bus_clk); ++ ++assert_reset: ++ if (info->data->has_bus_rst) ++ reset_control_assert(info->reset); ++ ++ return ret; + } + + static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, +@@ -698,6 +896,15 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) + if (!info->no_irq) + iio_map_array_unregister(indio_dev); + ++ if (info->data->has_mod_clk) ++ clk_disable_unprepare(info->mod_clk); ++ ++ if (info->data->has_bus_clk) ++ clk_disable_unprepare(info->ths_bus_clk); ++ ++ if (info->data->has_bus_rst) ++ reset_control_assert(info->reset); ++ + return 0; + } + +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index 139872c2..f794a298 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -38,9 +38,12 @@ + #define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x)) + #define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0) + +-/* TP_CTRL1 bits for sun8i SoCs */ +-#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) +-#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7) ++/* TP_CTRL1 bits for sun8i A23/A33 SoCs */ ++#define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) ++#define SUN8I_A23_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 + +@@ -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