Thermals: use sunxi's GP-ADC to read SoC temp

takes 21, 23, 24, 25 from "safe-needs-more-inspection" and 22 from "unresolved" to (re-) activate Sunxi's SoC temp sensor.
This commit is contained in:
Karabek 2018-06-02 12:50:26 +02:00 committed by GitHub
parent 033c18581c
commit 87af831187
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 577 additions and 0 deletions

View File

@ -0,0 +1,30 @@
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 81d4c39e414a..41769bc6a429 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -88,7 +88,7 @@ static const struct gpadc_data sun6i_gpadc_data = {
static const struct gpadc_data sun8i_a33_gpadc_data = {
.temp_offset = -1662,
.temp_scale = 162,
- .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
+ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
};
struct sun4i_gpadc_iio {
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index 139872c2e0fe..d31d962bb7d8 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -38,9 +38,9 @@
#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)
#define SUN4I_GPADC_CTRL2 0x08

View File

@ -0,0 +1,392 @@
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 75cb089..d7089b7 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/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 <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -31,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/thermal.h>
#include <linux/delay.h>
@@ -49,6 +51,8 @@ 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;
@@ -56,39 +60,12 @@ struct gpadc_data {
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_A23_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 +80,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 +257,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);
@@ -385,10 +365,8 @@ out:
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 */
@@ -397,10 +375,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) |
@@ -418,6 +409,29 @@ 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);
+}
+
static int sun4i_gpadc_get_temp(void *data, int *temp)
{
struct sun4i_gpadc_iio *info = data;
@@ -492,11 +506,78 @@ 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,
+ .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,
+ .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,
+ .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,
+ .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_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,
+ },
{ /* sentinel */ }
};
@@ -529,10 +610,72 @@ 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))
info->sensor_device = &pdev->dev;
+ 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 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 +841,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/mfd2/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h
index d31d962..f794a29 100644
--- a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h
@@ -42,6 +42,9 @@
#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
#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

View File

@ -0,0 +1,28 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index a0cee17fe44b..efe3a8e4f2af 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -108,6 +108,23 @@
};
};
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&ths>;
+ };
+
+ soc {
+ ths: thermal-sensor@1c25000 {
+ compatible = "allwinner,sun8i-h3-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>;
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,

View File

@ -0,0 +1,93 @@
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index b36f9f423..0ad8e3e80 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -41,6 +41,7 @@
*/
#include "sunxi-h3-h5.dtsi"
+#include <dt-bindings/thermal/thermal.h>
/ {
cpus {
@@ -72,6 +73,80 @@
};
};
+ thermal-zones {
+ cpu-thermal {
+ /* milliseconds */
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&ths>;
+
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot_pre: cpu_hot_pre {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_hot: cpu_hot {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_very_hot_pre: cpu_very_hot_pre {
+ temperature = <85000>;
+ 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_pre_limit_cpu {
+ trip = <&cpu_hot_pre>;
+ cooling-device = <&cpu0 2 3>;
+ };
+
+ cpu_hot_limit_cpu {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 3 4>;
+ };
+
+ cpu_very_hot_pre_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 5 6>;
+ };
+
+ cpu_very_hot_limit_cpu {
+ trip = <&cpu_very_hot>;
+ cooling-device = <&cpu0 7 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,

View File

@ -0,0 +1,34 @@
From e42ea77a5f2b389eed2c9004eab80bf6589ebf5a Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Tue, 1 Aug 2017 23:42:12 +0800
Subject: [PATCH] iio: adc: sun4i-gpadc: workaroud bogus THS raw value 0
readout
When booting the system, the THS may read out a bogus false value which
is raw value 0.
On H3 it represents a extremely high temperature and can shutdown the
system immediately.
Workaround it by make it return -EINVAL when the raw value is 0 (which
is unlikely to happen).
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
drivers/iio/adc/sun4i-gpadc-iio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index f378ca0bc0b30..a89dcb6fba4ec 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -262,6 +262,9 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
pm_runtime_mark_last_busy(indio_dev->dev.parent);
pm_runtime_put_autosuspend(indio_dev->dev.parent);
+ if (!*val)
+ return -EINVAL;
+
return 0;
}