Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1605837 > unrolled thread
| Started by | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| First post | 2017-03-21 18:20 +0100 |
| Last post | 2017-03-21 20:40 +0100 |
| Articles | 11 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH v3 00/11] add thermal throttling to Allwinner A33 SoC Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 18:20 +0100
[PATCH v3 09/11] ARM: dtsi: sun8i: a33: add CPU thermal throttling Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 18:40 +0100
[PATCH v3 10/11] ARM: sun8i: a33: Add devfreq-based GPU cooling Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 19:00 +0100
[PATCH v3 11/11] ARM: sun8i: sina33: add highest OPP of CPUs Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 19:10 +0100
[PATCH v3 08/11] ARM: dtsi: sun8i: a33: add thermal sensor Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 19:40 +0100
[PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 19:40 +0100
Re: [PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply Chen-Yu Tsai <wens@csie.org> - 2017-03-22 05:00 +0100
Re: [PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-03-22 09:20 +0100
[PATCH v3 07/11] iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 20:10 +0100
Re: [PATCH v3 07/11] iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor Jonathan Cameron <jic23@kernel.org> - 2017-03-25 19:00 +0100
[PATCH v3 06/11] iio: adc: sun4i-gpadc-iio: move code used in MFD probing to new function Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-03-21 20:40 +0100
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 18:20 +0100 |
| Subject | [PATCH v3 00/11] add thermal throttling to Allwinner A33 SoC |
| Message-ID | <tnu38-5ee-13@gated-at.bofh.it> |
The Allwinner SoCs all have an ADC that can also act as a touchscreen
controller and a thermal sensor. The first four channels can be used
either for the ADC or the touchscreen and the fifth channel is used for
the thermal sensor. We currently have a driver for the two latter
functions in drivers/input/touchscreen/sun4i-ts.c but we don't have
access to the ADC feature at all. It is meant to replace the current
driver by using MFD and subdrivers for existing bindings.
The Allwinner A33 only has a thermal sensor present in the GPADC. In
addition, there is not an existing DT binding for the GPADC. Thus, we do
not need the sun4i-gpadc MFD driver which was made to keep DT compatibility
and probe subdrivers without the need to add DT subnodes.
This series of patch adds the thermal sensor for the A33 and GPU/CPU
thermal throttling. It also adds the cpu-supply property to the CPU node
needed by the Sinlinx SinA33 and Olinuxino A33 to adapt their CPU regulator
voltage depending on the currently used OPP. The other A33 boards all have
their cpu-supply property set.
This series also fixes the missing operating-points-v2 property in cpu DT
nodes. Finally, it also adds all remaining OPPs which can be found in
Allwinner 3.4 linux and fex files of all A33 boards.
This series of patch is based on this[1] series of patch.
v3:
- fixed compatible name in DT and in documentation,
- fixed DT node name and label,
- added explanations in commit logs,
- moved frequencies that need overvolting to board DTS instead of A33 DTSI,
- fixed a typo in if is_enabled condition,
- removed all patches concerning Olimex Olinuxino (no HW to test on),
[1] https://lkml.org/lkml/2016/12/13/298 : "[PATCH v9] add support for Allwinner
SoCs ADC"
Thanks,
Quentin
Maxime Ripard (1):
ARM: sun8i: a33: Add devfreq-based GPU cooling
Quentin Schulz (10):
ARM: sun8i: a33: add operating-points-v2 property to all nodes
ARM: sun8i: a33: add all operating points
ARM: dts: sun8i: sina33: add cpu-supply
Documentation: DT: bindings: mfd: add A33 GPADC binding
Documentation: DT: bindings: input: touschcreen: remove sun4i
documentation
iio: adc: sun4i-gpadc-iio: move code used in MFD probing to new
function
iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor
ARM: dtsi: sun8i: a33: add thermal sensor
ARM: dtsi: sun8i: a33: add CPU thermal throttling
ARM: sun8i: sina33: add highest OPP of CPUs
.../touchscreen/sun4i.txt => mfd/sun4i-gpadc.txt} | 21 +++
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 1 +
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts | 18 +++
arch/arm/boot/dts/sun8i-a33.dtsi | 141 +++++++++++++++++
drivers/iio/adc/Kconfig | 2 +-
drivers/iio/adc/sun4i-gpadc-iio.c | 170 +++++++++++++++++----
include/linux/mfd/sun4i-gpadc.h | 4 +
7 files changed, 324 insertions(+), 33 deletions(-)
rename Documentation/devicetree/bindings/{input/touchscreen/sun4i.txt => mfd/sun4i-gpadc.txt} (64%)
--
2.9.3
[toc] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 18:40 +0100 |
| Subject | [PATCH v3 09/11] ARM: dtsi: sun8i: a33: add CPU thermal throttling |
| Message-ID | <tnvVg-6v1-9@gated-at.bofh.it> |
| In reply to | #1605837 |
This adds CPU thermal throttling for the Allwinner A33. It uses the
thermal sensor present in the SoC's GPADC.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
v3:
- switched to new phandle because of modified DT node name for the GPADC
(named THS),
- got rid of cooling-min-level and cooling-max-level as it's not used in any
code in the kernel,
v2:
- updated cooling-max-level to reflect newly added OPPs,
arch/arm/boot/dts/sun8i-a33.dtsi | 45 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index f391f71..73552bb 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -43,6 +43,7 @@
*/
#include "sun8i-a23-a33.dtsi"
+#include <dt-bindings/thermal/thermal.h>
/ {
cpu0_opp_table: opp_table0 {
@@ -127,6 +128,7 @@
clocks = <&ccu CLK_CPUX>;
clock-names = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
+ #cooling-cells = <2>;
};
cpu@1 {
@@ -170,6 +172,49 @@
};
};
+ thermal-zones {
+ cpu_thermal {
+ /* milliseconds */
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&ths>;
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert0>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ map1 {
+ trip = <&cpu_alert1>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+
+ trips {
+ cpu_alert0: cpu_alert0 {
+ /* milliCelsius */
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_alert1: cpu_alert1 {
+ /* milliCelsius */
+ temperature = <90000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
+ cpu_crit: cpu_crit {
+ /* milliCelsius */
+ temperature = <110000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
memory {
reg = <0x40000000 0x80000000>;
};
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 19:00 +0100 |
| Subject | [PATCH v3 10/11] ARM: sun8i: a33: Add devfreq-based GPU cooling |
| Message-ID | <tnweC-6BQ-5@gated-at.bofh.it> |
| In reply to | #1605837 |
From: Maxime Ripard <maxime.ripard@free-electrons.com>
This adds GPU thermal throttling for the Allwinner A33.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
v3:
- got rid of cooling-min-level and cooling-max-level as it's not used in any
code in the kernel,
added in v2
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 1 +
arch/arm/boot/dts/sun8i-a33.dtsi | 24 ++++++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
index 5e8725d..6d81a6d 100644
--- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
@@ -495,6 +495,7 @@
assigned-clocks = <&ccu CLK_GPU>;
assigned-clock-rates = <384000000>;
+ #cooling-cells = <2>;
};
gic: interrupt-controller@01c81000 {
diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index 73552bb..a2c6077 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -188,6 +188,16 @@
trip = <&cpu_alert1>;
cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
+
+ map2 {
+ trip = <&gpu_alert0>;
+ cooling-device = <&mali 1 THERMAL_NO_LIMIT>;
+ };
+
+ map3 {
+ trip = <&gpu_alert1>;
+ cooling-device = <&mali 2 THERMAL_NO_LIMIT>;
+ };
};
trips {
@@ -198,6 +208,13 @@
type = "passive";
};
+ gpu_alert0: gpu_alert0 {
+ /* milliCelsius */
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
cpu_alert1: cpu_alert1 {
/* milliCelsius */
temperature = <90000>;
@@ -205,6 +222,13 @@
type = "hot";
};
+ gpu_alert1: gpu_alert1 {
+ /* milliCelsius */
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+
cpu_crit: cpu_crit {
/* milliCelsius */
temperature = <110000>;
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 19:10 +0100 |
| Subject | [PATCH v3 11/11] ARM: sun8i: sina33: add highest OPP of CPUs |
| Message-ID | <tnwoi-6UG-17@gated-at.bofh.it> |
| In reply to | #1605837 |
The A33 supports 1.1GHz and 1.2GHz frequencies at 1.32V and the Sinlinx
SinA33 has its cpu-supply property set in the cpu DT node.
Therefore, CPUfreq knows how to handle the regulator in charge of the
CPU and can adjust its voltage to match the OPP.
Add these two CPU frequencies to the CPU OPP table of the Sinlinx
SinA33.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
added in v3
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
index d84f1bd..a92dee1 100644
--- a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
+++ b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
@@ -87,6 +87,20 @@
cpu-supply = <®_dcdc3>;
};
+&cpu0_opp_table {
+ opp@1104000000 {
+ opp-hz = /bits/ 64 <1104000000>;
+ opp-microvolt = <1320000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ };
+
+ opp@1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1320000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ };
+};
+
&de {
status = "okay";
};
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 19:40 +0100 |
| Subject | [PATCH v3 08/11] ARM: dtsi: sun8i: a33: add thermal sensor |
| Message-ID | <tnwRk-779-31@gated-at.bofh.it> |
| In reply to | #1605837 |
This adds the DT node for the thermal sensor present in the Allwinner
A33 GPADC.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
v3:
- switched compatible to allwinner,sun8i-a33-ths,
- renamed DT node name and label to ths to better match datasheet's name,
arch/arm/boot/dts/sun8i-a33.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index b1cdff66..f391f71 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -266,6 +266,13 @@
status = "disabled";
};
+ ths: ths@01c25000 {
+ compatible = "allwinner,sun8i-a33-ths";
+ reg = <0x01c25000 0x100>;
+ #thermal-sensor-cells = <0>;
+ #io-channel-cells = <0>;
+ };
+
fe0: display-frontend@01e00000 {
compatible = "allwinner,sun8i-a33-display-frontend";
reg = <0x01e00000 0x20000>;
@@ -376,6 +383,11 @@
};
};
};
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&ths>;
+ };
};
&ccu {
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 19:40 +0100 |
| Subject | [PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply |
| Message-ID | <tnwRk-779-39@gated-at.bofh.it> |
| In reply to | #1605837 |
This adds the cpu-supply DT property to the cpu0 DT node needed by
the board to adapt the regulator voltage depending on the currently used
OPP.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
index cde14b3..d84f1bd 100644
--- a/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
+++ b/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
@@ -83,6 +83,10 @@
status = "okay";
};
+&cpu0 {
+ cpu-supply = <®_dcdc3>;
+};
+
&de {
status = "okay";
};
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Chen-Yu Tsai <wens@csie.org> |
|---|---|
| Date | 2017-03-22 05:00 +0100 |
| Subject | Re: [PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply |
| Message-ID | <tnFBf-4Kk-5@gated-at.bofh.it> |
| In reply to | #1605899 |
On Tue, Mar 21, 2017 at 11:36 PM, Quentin Schulz <quentin.schulz@free-electrons.com> wrote: > This adds the cpu-supply DT property to the cpu0 DT node needed by > the board to adapt the regulator voltage depending on the currently used > OPP. > > Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com> Acked-by: Chen-Yu Tsai <wens@csie.org>
[toc] | [prev] | [next] | [standalone]
| From | Maxime Ripard <maxime.ripard@free-electrons.com> |
|---|---|
| Date | 2017-03-22 09:20 +0100 |
| Subject | Re: [PATCH v3 03/11] ARM: dts: sun8i: sina33: add cpu-supply |
| Message-ID | <tnJES-7PW-1@gated-at.bofh.it> |
| In reply to | #1606194 |
[Multipart message — attachments visible in raw view] — view raw
On Wed, Mar 22, 2017 at 11:33:15AM +0800, Chen-Yu Tsai wrote: > On Tue, Mar 21, 2017 at 11:36 PM, Quentin Schulz > <quentin.schulz@free-electrons.com> wrote: > > This adds the cpu-supply DT property to the cpu0 DT node needed by > > the board to adapt the regulator voltage depending on the currently used > > OPP. > > > > Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com> > > Acked-by: Chen-Yu Tsai <wens@csie.org> Applied, thanks! Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 20:10 +0100 |
| Subject | [PATCH v3 07/11] iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor |
| Message-ID | <tnxkl-7xz-3@gated-at.bofh.it> |
| In reply to | #1605837 |
This adds support for the Allwinner A33 thermal sensor.
Unlike the A10, A13 and A31, the Allwinner A33 only has one channel
which is dedicated to the thermal sensor. Moreover, its thermal sensor
does not generate interruptions, thus we only need to directly read the
register storing the temperature value.
The MFD used by the A10, A13 and A31, was created to avoid breaking the
DT binding, but since the nodes for the ADC weren't there for the A33,
it is not needed.
Though the A33 does not have an internal ADC, it has a thermal sensor
which shares the same registers with GPADC of the already supported SoCs
and almost the same bits, for the same purpose (thermal sensor).
The thermal sensor behaves exactly the same (except the presence of
interrupts or not) on the different SoCs.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
v3:
- switched compatible from allwinner,sun8i-a33-gpadc-iio to
allwinner,sun8i-a33-ths to better reflect the datasheet's name,
- fixed the non-working if (!IS_ENABLED(THERMAL_OF)) by prefixing it with
CONFIG,
v2:
- removed added comments in Kconfig,
- simplified Kconfig depends on condition,
- removed THERMAL_OF requirement for sun8i,
- renamed sun8i_gpadc_channels to sun8i_a33_gpadc_channels,
- renamed use_dt boolean in no_irq as it reflects better why we need it,
- removed spurious/unneeded modifications done in v1,
drivers/iio/adc/Kconfig | 2 +-
drivers/iio/adc/sun4i-gpadc-iio.c | 100 ++++++++++++++++++++++++++++++++++++--
include/linux/mfd/sun4i-gpadc.h | 4 ++
3 files changed, 102 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9f8b4b1..8c8ead6 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -562,7 +562,7 @@ config STX104
config SUN4I_GPADC
tristate "Support for the Allwinner SoCs GPADC"
depends on IIO
- depends on MFD_SUN4I_GPADC
+ depends on MFD_SUN4I_GPADC || MACH_SUN8I
help
Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
GPADC. This ADC provides 4 channels which can be used as an ADC or as
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 7cb997a..74705aa 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -85,6 +85,12 @@ static const struct gpadc_data sun6i_gpadc_data = {
.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,
+};
+
struct sun4i_gpadc_iio {
struct iio_dev *indio_dev;
struct completion completion;
@@ -96,6 +102,7 @@ struct sun4i_gpadc_iio {
unsigned int temp_data_irq;
atomic_t ignore_temp_data_irq;
const struct gpadc_data *data;
+ bool no_irq;
/* prevents concurrent reads of temperature and ADC */
struct mutex mutex;
};
@@ -138,6 +145,23 @@ static const struct iio_chan_spec sun4i_gpadc_channels_no_temp[] = {
SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),
};
+static const struct iio_chan_spec sun8i_a33_gpadc_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .datasheet_name = "temp_adc",
+ },
+};
+
+static const struct regmap_config sun4i_gpadc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .fast_io = true,
+};
+
static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel,
unsigned int irq)
{
@@ -247,6 +271,17 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
{
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+ if (info->no_irq) {
+ pm_runtime_get_sync(indio_dev->dev.parent);
+
+ regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
+
+ pm_runtime_mark_last_busy(indio_dev->dev.parent);
+ pm_runtime_put_autosuspend(indio_dev->dev.parent);
+
+ return 0;
+ }
+
return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq);
}
@@ -454,6 +489,58 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
return 0;
}
+static const struct of_device_id sun4i_gpadc_of_id[] = {
+ {
+ .compatible = "allwinner,sun8i-a33-ths",
+ .data = &sun8i_a33_gpadc_data,
+ },
+ { /* sentinel */ }
+};
+
+static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
+ struct iio_dev *indio_dev)
+{
+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+ const struct of_device_id *of_dev;
+ struct thermal_zone_device *tzd;
+ struct resource *mem;
+ void __iomem *base;
+ int ret;
+
+ of_dev = of_match_device(sun4i_gpadc_of_id, &pdev->dev);
+ if (!of_dev)
+ return -ENODEV;
+
+ info->no_irq = true;
+ info->data = (struct gpadc_data *)of_dev->data;
+ indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
+ indio_dev->channels = sun8i_a33_gpadc_channels;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ info->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sun4i_gpadc_regmap_config);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
+ if (!IS_ENABLED(CONFIG_THERMAL_OF))
+ return 0;
+
+ tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
+ &sun4i_ts_tz_ops);
+ if (IS_ERR(tzd))
+ dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
+ PTR_ERR(tzd));
+
+ return PTR_ERR_OR_ZERO(tzd);
+}
+
static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
struct iio_dev *indio_dev)
{
@@ -462,6 +549,7 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
dev_get_drvdata(pdev->dev.parent);
int ret;
+ info->no_irq = false;
info->regmap = sun4i_gpadc_dev->regmap;
indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);
@@ -561,7 +649,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
indio_dev->info = &sun4i_gpadc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
+ if (pdev->dev.of_node)
+ ret = sun4i_gpadc_probe_dt(pdev, indio_dev);
+ else
+ ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
+
if (ret)
return ret;
@@ -580,7 +672,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
return 0;
err_map:
- if (IS_ENABLED(CONFIG_THERMAL_OF))
+ if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
iio_map_array_unregister(indio_dev);
pm_runtime_put(&pdev->dev);
@@ -592,10 +684,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
static int sun4i_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- if (IS_ENABLED(CONFIG_THERMAL_OF))
+ if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
iio_map_array_unregister(indio_dev);
return 0;
@@ -611,6 +704,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = {
static struct platform_driver sun4i_gpadc_driver = {
.driver = {
.name = "sun4i-gpadc-iio",
+ .of_match_table = sun4i_gpadc_of_id,
.pm = &sun4i_gpadc_pm_ops,
},
.id_table = sun4i_gpadc_id,
diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
index 509e736..139872c 100644
--- a/include/linux/mfd/sun4i-gpadc.h
+++ b/include/linux/mfd/sun4i-gpadc.h
@@ -38,6 +38,10 @@
#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)
+
#define SUN4I_GPADC_CTRL2 0x08
#define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x) ((GENMASK(3, 0) & (x)) << 28)
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Jonathan Cameron <jic23@kernel.org> |
|---|---|
| Date | 2017-03-25 19:00 +0100 |
| Subject | Re: [PATCH v3 07/11] iio: adc: sun4i-gpadc-iio: add support for A33 thermal sensor |
| Message-ID | <toY8N-4ez-1@gated-at.bofh.it> |
| In reply to | #1605921 |
On 21/03/17 15:36, Quentin Schulz wrote:
> This adds support for the Allwinner A33 thermal sensor.
>
> Unlike the A10, A13 and A31, the Allwinner A33 only has one channel
> which is dedicated to the thermal sensor. Moreover, its thermal sensor
> does not generate interruptions, thus we only need to directly read the
> register storing the temperature value.
>
> The MFD used by the A10, A13 and A31, was created to avoid breaking the
> DT binding, but since the nodes for the ADC weren't there for the A33,
> it is not needed.
>
> Though the A33 does not have an internal ADC, it has a thermal sensor
> which shares the same registers with GPADC of the already supported SoCs
> and almost the same bits, for the same purpose (thermal sensor).
>
> The thermal sensor behaves exactly the same (except the presence of
> interrupts or not) on the different SoCs.
>
> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
> Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Jonathan Cameron <jic23@kernel.org>
I'm assuming this is going through your tree Lee, let me know if you want
to do it differently.
Jonathan
> ---
>
> v3:
> - switched compatible from allwinner,sun8i-a33-gpadc-iio to
> allwinner,sun8i-a33-ths to better reflect the datasheet's name,
> - fixed the non-working if (!IS_ENABLED(THERMAL_OF)) by prefixing it with
> CONFIG,
>
> v2:
> - removed added comments in Kconfig,
> - simplified Kconfig depends on condition,
> - removed THERMAL_OF requirement for sun8i,
> - renamed sun8i_gpadc_channels to sun8i_a33_gpadc_channels,
> - renamed use_dt boolean in no_irq as it reflects better why we need it,
> - removed spurious/unneeded modifications done in v1,
>
> drivers/iio/adc/Kconfig | 2 +-
> drivers/iio/adc/sun4i-gpadc-iio.c | 100 ++++++++++++++++++++++++++++++++++++--
> include/linux/mfd/sun4i-gpadc.h | 4 ++
> 3 files changed, 102 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 9f8b4b1..8c8ead6 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -562,7 +562,7 @@ config STX104
> config SUN4I_GPADC
> tristate "Support for the Allwinner SoCs GPADC"
> depends on IIO
> - depends on MFD_SUN4I_GPADC
> + depends on MFD_SUN4I_GPADC || MACH_SUN8I
> help
> Say yes here to build support for Allwinner (A10, A13 and A31) SoCs
> GPADC. This ADC provides 4 channels which can be used as an ADC or as
> diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
> index 7cb997a..74705aa 100644
> --- a/drivers/iio/adc/sun4i-gpadc-iio.c
> +++ b/drivers/iio/adc/sun4i-gpadc-iio.c
> @@ -85,6 +85,12 @@ static const struct gpadc_data sun6i_gpadc_data = {
> .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,
> +};
> +
> struct sun4i_gpadc_iio {
> struct iio_dev *indio_dev;
> struct completion completion;
> @@ -96,6 +102,7 @@ struct sun4i_gpadc_iio {
> unsigned int temp_data_irq;
> atomic_t ignore_temp_data_irq;
> const struct gpadc_data *data;
> + bool no_irq;
> /* prevents concurrent reads of temperature and ADC */
> struct mutex mutex;
> };
> @@ -138,6 +145,23 @@ static const struct iio_chan_spec sun4i_gpadc_channels_no_temp[] = {
> SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),
> };
>
> +static const struct iio_chan_spec sun8i_a33_gpadc_channels[] = {
> + {
> + .type = IIO_TEMP,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> + BIT(IIO_CHAN_INFO_SCALE) |
> + BIT(IIO_CHAN_INFO_OFFSET),
> + .datasheet_name = "temp_adc",
> + },
> +};
> +
> +static const struct regmap_config sun4i_gpadc_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .fast_io = true,
> +};
> +
> static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel,
> unsigned int irq)
> {
> @@ -247,6 +271,17 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)
> {
> struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
>
> + if (info->no_irq) {
> + pm_runtime_get_sync(indio_dev->dev.parent);
> +
> + regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
> +
> + pm_runtime_mark_last_busy(indio_dev->dev.parent);
> + pm_runtime_put_autosuspend(indio_dev->dev.parent);
> +
> + return 0;
> + }
> +
> return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq);
> }
>
> @@ -454,6 +489,58 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
> return 0;
> }
>
> +static const struct of_device_id sun4i_gpadc_of_id[] = {
> + {
> + .compatible = "allwinner,sun8i-a33-ths",
> + .data = &sun8i_a33_gpadc_data,
> + },
> + { /* sentinel */ }
> +};
> +
> +static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
> + struct iio_dev *indio_dev)
> +{
> + struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
> + const struct of_device_id *of_dev;
> + struct thermal_zone_device *tzd;
> + struct resource *mem;
> + void __iomem *base;
> + int ret;
> +
> + of_dev = of_match_device(sun4i_gpadc_of_id, &pdev->dev);
> + if (!of_dev)
> + return -ENODEV;
> +
> + info->no_irq = true;
> + info->data = (struct gpadc_data *)of_dev->data;
> + indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
> + indio_dev->channels = sun8i_a33_gpadc_channels;
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap_resource(&pdev->dev, mem);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + info->regmap = devm_regmap_init_mmio(&pdev->dev, base,
> + &sun4i_gpadc_regmap_config);
> + if (IS_ERR(info->regmap)) {
> + ret = PTR_ERR(info->regmap);
> + dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
> + return ret;
> + }
> +
> + if (!IS_ENABLED(CONFIG_THERMAL_OF))
> + return 0;
> +
> + tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
> + &sun4i_ts_tz_ops);
> + if (IS_ERR(tzd))
> + dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
> + PTR_ERR(tzd));
> +
> + return PTR_ERR_OR_ZERO(tzd);
> +}
> +
> static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
> struct iio_dev *indio_dev)
> {
> @@ -462,6 +549,7 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
> dev_get_drvdata(pdev->dev.parent);
> int ret;
>
> + info->no_irq = false;
> info->regmap = sun4i_gpadc_dev->regmap;
>
> indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);
> @@ -561,7 +649,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
> indio_dev->info = &sun4i_gpadc_iio_info;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> - ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
> + if (pdev->dev.of_node)
> + ret = sun4i_gpadc_probe_dt(pdev, indio_dev);
> + else
> + ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
> +
> if (ret)
> return ret;
>
> @@ -580,7 +672,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
> return 0;
>
> err_map:
> - if (IS_ENABLED(CONFIG_THERMAL_OF))
> + if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
> iio_map_array_unregister(indio_dev);
>
> pm_runtime_put(&pdev->dev);
> @@ -592,10 +684,11 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
> static int sun4i_gpadc_remove(struct platform_device *pdev)
> {
> struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> + struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
>
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> - if (IS_ENABLED(CONFIG_THERMAL_OF))
> + if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
> iio_map_array_unregister(indio_dev);
>
> return 0;
> @@ -611,6 +704,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = {
> static struct platform_driver sun4i_gpadc_driver = {
> .driver = {
> .name = "sun4i-gpadc-iio",
> + .of_match_table = sun4i_gpadc_of_id,
> .pm = &sun4i_gpadc_pm_ops,
> },
> .id_table = sun4i_gpadc_id,
> diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
> index 509e736..139872c 100644
> --- a/include/linux/mfd/sun4i-gpadc.h
> +++ b/include/linux/mfd/sun4i-gpadc.h
> @@ -38,6 +38,10 @@
> #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)
> +
> #define SUN4I_GPADC_CTRL2 0x08
>
> #define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x) ((GENMASK(3, 0) & (x)) << 28)
>
[toc] | [prev] | [next] | [standalone]
| From | Quentin Schulz <quentin.schulz@free-electrons.com> |
|---|---|
| Date | 2017-03-21 20:40 +0100 |
| Subject | [PATCH v3 06/11] iio: adc: sun4i-gpadc-iio: move code used in MFD probing to new function |
| Message-ID | <tnxNo-7LG-15@gated-at.bofh.it> |
| In reply to | #1605837 |
This moves code used in MFD probing to a new sun4i_gpadc_probe_mfd
function.
This driver was initially written for A10, A13 and A31 SoCs which
already had a DT binding for this IP, thus we needed to use an MFD to
probe the different drivers without changing the DT binding of these
SoCs.
For SoCs that will require to create a DT binding for this IP, we can
avoid using an MFD, thus we need two separate functions: one for probing
via MFD and one for probing without MFD.
This split the code specific to MFD probing in a function separated from
the driver probe function.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Jonathan Cameron <jic23@kernel.org>
---
v3:
- updated commit log,
added in v2
drivers/iio/adc/sun4i-gpadc-iio.c | 78 ++++++++++++++++++++++-----------------
1 file changed, 45 insertions(+), 33 deletions(-)
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index a8e134f..7cb997a 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -454,31 +454,16 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
return 0;
}
-static int sun4i_gpadc_probe(struct platform_device *pdev)
+static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
+ struct iio_dev *indio_dev)
{
- struct sun4i_gpadc_iio *info;
- struct iio_dev *indio_dev;
+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
+ struct sun4i_gpadc_dev *sun4i_gpadc_dev =
+ dev_get_drvdata(pdev->dev.parent);
int ret;
- struct sun4i_gpadc_dev *sun4i_gpadc_dev;
-
- sun4i_gpadc_dev = dev_get_drvdata(pdev->dev.parent);
-
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
- if (!indio_dev)
- return -ENOMEM;
- info = iio_priv(indio_dev);
- platform_set_drvdata(pdev, indio_dev);
-
- mutex_init(&info->mutex);
info->regmap = sun4i_gpadc_dev->regmap;
- info->indio_dev = indio_dev;
- init_completion(&info->completion);
- indio_dev->name = dev_name(&pdev->dev);
- indio_dev->dev.parent = &pdev->dev;
- indio_dev->dev.of_node = pdev->dev.of_node;
- indio_dev->info = &sun4i_gpadc_iio_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
+
indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);
indio_dev->channels = sun4i_gpadc_channels;
@@ -519,8 +504,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"could not register thermal sensor: %ld\n",
PTR_ERR(tzd));
- ret = PTR_ERR(tzd);
- goto err;
+ return PTR_ERR(tzd);
}
} else {
indio_dev->num_channels =
@@ -528,36 +512,65 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
indio_dev->channels = sun4i_gpadc_channels_no_temp;
}
- pm_runtime_set_autosuspend_delay(&pdev->dev,
- SUN4I_GPADC_AUTOSUSPEND_DELAY);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
if (IS_ENABLED(CONFIG_THERMAL_OF)) {
ret = sun4i_irq_init(pdev, "TEMP_DATA_PENDING",
sun4i_gpadc_temp_data_irq_handler,
"temp_data", &info->temp_data_irq,
&info->ignore_temp_data_irq);
if (ret < 0)
- goto err;
+ return ret;
}
ret = sun4i_irq_init(pdev, "FIFO_DATA_PENDING",
sun4i_gpadc_fifo_data_irq_handler, "fifo_data",
&info->fifo_data_irq, &info->ignore_fifo_data_irq);
if (ret < 0)
- goto err;
+ return ret;
if (IS_ENABLED(CONFIG_THERMAL_OF)) {
ret = iio_map_array_register(indio_dev, sun4i_gpadc_hwmon_maps);
if (ret < 0) {
dev_err(&pdev->dev,
"failed to register iio map array\n");
- goto err;
+ return ret;
}
}
+ return 0;
+}
+
+static int sun4i_gpadc_probe(struct platform_device *pdev)
+{
+ struct sun4i_gpadc_iio *info;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ info = iio_priv(indio_dev);
+ platform_set_drvdata(pdev, indio_dev);
+
+ mutex_init(&info->mutex);
+ info->indio_dev = indio_dev;
+ init_completion(&info->completion);
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->dev.of_node = pdev->dev.of_node;
+ indio_dev->info = &sun4i_gpadc_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ SUN4I_GPADC_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = devm_iio_device_register(&pdev->dev, indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "could not register the device\n");
@@ -570,7 +583,6 @@ static int sun4i_gpadc_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_THERMAL_OF))
iio_map_array_unregister(indio_dev);
-err:
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
--
2.9.3
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web