Skip to contentSkip to conversation

Add multi-channel support to Armada thermal driver

PATCH Superseded Miquel Raynal 4 participants 44 messages Jun 25, 2018 – Jul 16, 2018

Subsystems (4)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Miquel Raynal

author maintainer
#0 lore raw

v2 cover Add multi-channel support to Armada thermal driver

The only capability of the Armada thermal driver is currently just to read one sensor (the default one) per AP and one per CP. Actually, there is one sensor per core in the AP806 plus one sensor in the thermal IP itself. The CP110 just features one thermal sensor in its own thermal IP.

This series first improves the readability of this driver, then adds support for multi-channel thermal IPs. The bindings and the device-trees are updated accordingly.

Eduardo, this is a barely modified version of my previous series adding overheat interrupt support. All the interrupt-related patches have been dropped for now. It is now only rewording, reorganization and multi-sensor support being added here; there is no more dependency. As I did not receive any feedback since April, 24th I would like it to be merged for 4.19.

Thank you,
Miqu?l

Changes since v1:
=================
* Added register ranges in the thermal nodes.
* Added these ranges in the documentation also.
* In the bindings, used the "Must be one of" formula before listing the compatibles.
* Removed the overheat interrupt support that depends on another series. This work is independent.
* Rebased on top of v4.18-rc1.

Miquel Raynal (23):
thermal: armada: remove useless register accesses
thermal: armada: remove misleading comments
thermal: armada: rename the initialization routine
thermal: armada: dissociate a380 and cp110 ->init() hooks
thermal: armada: average over samples to avoid glitches
thermal: armada: convert driver to syscon register accesses
thermal: armada: use the resource managed registration helper
alternative
thermal: armada: add multi-channel sensors support
thermal: armada: remove sensors validity from the IP initialization
thermal: armada: move validity check out of the read function
thermal: armada: get rid of the ->is_valid() pointer
dt-bindings: cp110: rename cp110 syscon file
dt-bindings: ap806: prepare the syscon file to list other syscons
nodes
dt-bindings: cp110: prepare the syscon file to list other syscons
nodes
dt-bindings: ap806: add the thermal node in the syscon file
dt-bindings: cp110: update documentation since DT de-duplication
dt-bindings: cp110: add the thermal node in the syscon file
dt-bindings: thermal: armada: add reference to new bindings
arm64: dts: marvell: rename ap806 syscon node
arm64: dts: marvell: move AP806/CP110 thermal nodes into a new syscon
arm64: dts: marvell: add thermal-zone node in ap806 DTSI file
arm64: dts: marvell: add macro to make distinction between node names
arm64: dts: marvell: add thermal-zone node in cp110 DTSI file

 .../arm/marvell/ap806-system-controller.txt        |  50 +-
 ...controller0.txt => cp110-system-controller.txt} |  61 ++-
 .../devicetree/bindings/thermal/armada-thermal.txt |   5 +
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi      |  76 ++-
 arch/arm64/boot/dts/marvell/armada-common.dtsi     |   1 +
 arch/arm64/boot/dts/marvell/armada-cp110.dtsi      |  37 +-
 drivers/thermal/armada_thermal.c                   | 510 +++++++++++++++------
 7 files changed, 583 insertions(+), 157 deletions(-)
 rename Documentation/devicetree/bindings/arm/marvell/{cp110-system-controller0.txt => cp110-system-controller.txt} (85%)
Signature · 1 line
2.14.1
author maintainer
#1 lore raw

PATCH v2 1/23 thermal: armada: remove useless register accesses

Prepare the migration to use regmaps by first simplifying the initialization functions: avoid unnecessary write/read cycles on configuration registers.

---
 drivers/thermal/armada_thermal.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/thermal/armada_thermal.c +2 -6
index 077e8e562306..6fdb90b3c001 100644
@@ -103,16 +103,13 @@ static void armadaxp_init_sensor(struct platform_device *pdev,
 
 	reg = readl_relaxed(priv->control1);
 	reg |= PMU_TDC0_OTF_CAL_MASK;
-	writel(reg, priv->control1);
 
 	/* Reference calibration value */
 	reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
 	reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
-	writel(reg, priv->control1);
 
 	/* Reset the sensor */
-	reg = readl_relaxed(priv->control1);
-	writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1);
+	reg |= PMU_TDC0_SW_RST_MASK;
 
 	writel(reg, priv->control1);
 
@@ -129,14 +126,13 @@ static void armada370_init_sensor(struct platform_device *pdev,
 
 	reg = readl_relaxed(priv->control1);
 	reg |= PMU_TDC0_OTF_CAL_MASK;
-	writel(reg, priv->control1);
 
 	/* Reference calibration value */
 	reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
 	reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
-	writel(reg, priv->control1);
 
 	reg &= ~PMU_TDC0_START_CAL_MASK;
+
 	writel(reg, priv->control1);
 
 	msleep(10);
Signature · 1 line
2.14.1
author maintainer
#2 lore raw

PATCH v2 2/23 thermal: armada: remove misleading comments

In reply to Miquel Raynal

On older versions of this thermal IP, TSEN referred as the internal sensor in the thermal IP while EXT_TSEN referred as sensors outside of this IP, ie in the CPUs most of the time. The bit names in the specifications do not follow this rule anymore, so remove these comments that are misleading.

---
 drivers/thermal/armada_thermal.c | 2 --
 1 file changed, 2 deletions(-)
drivers/thermal/armada_thermal.c +0 -2
index 6fdb90b3c001..18155e43e67f 100644
@@ -51,12 +51,10 @@
 #define CONTROL0_TSEN_TC_TRIM_MASK	0x7
 #define CONTROL0_TSEN_TC_TRIM_VAL	0x3
 
-/* TSEN refers to the temperature sensors within the AP */
 #define CONTROL0_TSEN_START		BIT(0)
 #define CONTROL0_TSEN_RESET		BIT(1)
 #define CONTROL0_TSEN_ENABLE		BIT(2)
 
-/* EXT_TSEN refers to the external temperature sensors, out of the AP */
 #define CONTROL1_EXT_TSEN_SW_RESET	BIT(7)
 #define CONTROL1_EXT_TSEN_HW_RESETn	BIT(8)
 
Signature · 1 line
2.14.1
author maintainer
#3 lore raw

PATCH v2 3/23 thermal: armada: rename the initialization routine

In reply to Miquel Raynal

Calling a hook ->init_sensor() while what is initialized is the IP itself and not the sensors is misleading. Rename the hook ->init() to avoid any confusion in later work bringing multi-sensors support.

---
 drivers/thermal/armada_thermal.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)
drivers/thermal/armada_thermal.c +20 -20
index 18155e43e67f..3d22a6016b04 100644
@@ -73,9 +73,9 @@ struct armada_thermal_priv {
 };
 
 struct armada_thermal_data {
-	/* Initialize the sensor */
-	void (*init_sensor)(struct platform_device *pdev,
-			    struct armada_thermal_priv *);
+	/* Initialize the thermal IC */
+	void (*init)(struct platform_device *pdev,
+		     struct armada_thermal_priv *priv);
 
 	/* Test for a valid sensor value (optional) */
 	bool (*is_valid)(struct armada_thermal_priv *);
@@ -94,8 +94,8 @@ struct armada_thermal_data {
 	bool needs_control0;
 };
 
-static void armadaxp_init_sensor(struct platform_device *pdev,
-				 struct armada_thermal_priv *priv)
+static void armadaxp_init(struct platform_device *pdev,
+			  struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
@@ -117,8 +117,8 @@ static void armadaxp_init_sensor(struct platform_device *pdev,
 	writel(reg, priv->status);
 }
 
-static void armada370_init_sensor(struct platform_device *pdev,
-				  struct armada_thermal_priv *priv)
+static void armada370_init(struct platform_device *pdev,
+			   struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
@@ -136,8 +136,8 @@ static void armada370_init_sensor(struct platform_device *pdev,
 	msleep(10);
 }
 
-static void armada375_init_sensor(struct platform_device *pdev,
-				  struct armada_thermal_priv *priv)
+static void armada375_init(struct platform_device *pdev,
+			   struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
@@ -164,8 +164,8 @@ static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
 				   STATUS_POLL_TIMEOUT_US);
 }
 
-static void armada380_init_sensor(struct platform_device *pdev,
-				  struct armada_thermal_priv *priv)
+static void armada380_init(struct platform_device *pdev,
+			   struct armada_thermal_priv *priv)
 {
 	u32 reg = readl_relaxed(priv->control1);
 
@@ -186,8 +186,8 @@ static void armada380_init_sensor(struct platform_device *pdev,
 	armada_wait_sensor_validity(priv);
 }
 
-static void armada_ap806_init_sensor(struct platform_device *pdev,
-				     struct armada_thermal_priv *priv)
+static void armada_ap806_init(struct platform_device *pdev,
+			      struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
@@ -247,7 +247,7 @@ static struct thermal_zone_device_ops ops = {
 };
 
 static const struct armada_thermal_data armadaxp_data = {
-	.init_sensor = armadaxp_init_sensor,
+	.init = armadaxp_init,
 	.temp_shift = 10,
 	.temp_mask = 0x1ff,
 	.coef_b = 3153000000ULL,
@@ -257,7 +257,7 @@ static const struct armada_thermal_data armadaxp_data = {
 
 static const struct armada_thermal_data armada370_data = {
 	.is_valid = armada_is_valid,
-	.init_sensor = armada370_init_sensor,
+	.init = armada370_init,
 	.is_valid_bit = BIT(9),
 	.temp_shift = 10,
 	.temp_mask = 0x1ff,
@@ -268,7 +268,7 @@ static const struct armada_thermal_data armada370_data = {
 
 static const struct armada_thermal_data armada375_data = {
 	.is_valid = armada_is_valid,
-	.init_sensor = armada375_init_sensor,
+	.init = armada375_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
 	.temp_mask = 0x1ff,
@@ -280,7 +280,7 @@ static const struct armada_thermal_data armada375_data = {
 
 static const struct armada_thermal_data armada380_data = {
 	.is_valid = armada_is_valid,
-	.init_sensor = armada380_init_sensor,
+	.init = armada380_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
 	.temp_mask = 0x3ff,
@@ -292,7 +292,7 @@ static const struct armada_thermal_data armada380_data = {
 
 static const struct armada_thermal_data armada_ap806_data = {
 	.is_valid = armada_is_valid,
-	.init_sensor = armada_ap806_init_sensor,
+	.init = armada_ap806_init,
 	.is_valid_bit = BIT(16),
 	.temp_shift = 0,
 	.temp_mask = 0x3ff,
@@ -306,7 +306,7 @@ static const struct armada_thermal_data armada_ap806_data = {
 
 static const struct armada_thermal_data armada_cp110_data = {
 	.is_valid = armada_is_valid,
-	.init_sensor = armada380_init_sensor,
+	.init = armada380_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
 	.temp_mask = 0x3ff,
@@ -428,7 +428,7 @@ static int armada_thermal_probe(struct platform_device *pdev)
 		priv->control1 = control + CONTROL1_OFFSET;
 	}
 
-	priv->data->init_sensor(pdev, priv);
+	priv->data->init(pdev, priv);
 
 	thermal = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
 					       &ops, NULL, 0, 0);
Signature · 1 line
2.14.1
author maintainer
#4 lore raw

PATCH v2 4/23 thermal: armada: dissociate a380 and cp110 ->init() hooks

In reply to Miquel Raynal

Until now, Armada 380 and CP110 could share the same ->init() function because their use was identical.

Prepare the support of multi-sensors support and overheat interrupt feature by separating the initialization paths before they actually diverge.

---
 drivers/thermal/armada_thermal.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/thermal/armada_thermal.c +7 -1
index 3d22a6016b04..9291ea3ad2f7 100644
@@ -200,6 +200,12 @@ static void armada_ap806_init(struct platform_device *pdev,
 	armada_wait_sensor_validity(priv);
 }
 
+static void armada_cp110_init(struct platform_device *pdev,
+			      struct armada_thermal_priv *priv)
+{
+	armada380_init(pdev, priv);
+}
+
 static bool armada_is_valid(struct armada_thermal_priv *priv)
 {
 	u32 reg = readl_relaxed(priv->status);
@@ -306,7 +312,7 @@ static const struct armada_thermal_data armada_ap806_data = {
 
 static const struct armada_thermal_data armada_cp110_data = {
 	.is_valid = armada_is_valid,
-	.init = armada380_init,
+	.init = armada_cp110_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
 	.temp_mask = 0x3ff,
Signature · 1 line
2.14.1
author maintainer
#5 lore raw

PATCH v2 5/23 thermal: armada: average over samples to avoid glitches

In reply to Miquel Raynal

Configure the sample frequency and number of averaged samples.

This is needed for two reasons:
1/ To be bootloader independent.
2/ To prepare the introduction of multi-sensors support by preventing
inconsistencies when reading temperatures that could be a mean of samples took from different sensors.

---
 drivers/thermal/armada_thermal.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
drivers/thermal/armada_thermal.c +25 -0
index 9291ea3ad2f7..1f9706d96a0d 100644
@@ -54,7 +54,12 @@
 #define CONTROL0_TSEN_START		BIT(0)
 #define CONTROL0_TSEN_RESET		BIT(1)
 #define CONTROL0_TSEN_ENABLE		BIT(2)
+#define CONTROL0_TSEN_AVG_BYPASS	BIT(6)
+#define CONTROL0_TSEN_OSR_SHIFT		24
+#define CONTROL0_TSEN_OSR_MAX		0x3
 
+#define CONTROL1_TSEN_AVG_SHIFT		0
+#define CONTROL1_TSEN_AVG_MASK		0x7
 #define CONTROL1_EXT_TSEN_SW_RESET	BIT(7)
 #define CONTROL1_EXT_TSEN_HW_RESETn	BIT(8)
 
@@ -194,6 +199,13 @@ static void armada_ap806_init(struct platform_device *pdev,
 	reg = readl_relaxed(priv->control0);
 	reg &= ~CONTROL0_TSEN_RESET;
 	reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
+
+	/* Sample every ~2ms */
+	reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
+
+	/* Enable average (2 samples by default) */
+	reg &= ~CONTROL0_TSEN_AVG_BYPASS;
+
 	writel(reg, priv->control0);
 
 	/* Wait the sensors to be valid or the core will warn the user */
@@ -203,7 +215,20 @@ static void armada_ap806_init(struct platform_device *pdev,
 static void armada_cp110_init(struct platform_device *pdev,
 			      struct armada_thermal_priv *priv)
 {
+	u32 reg;
+
 	armada380_init(pdev, priv);
+
+	/* Sample every ~2ms */
+	reg = readl_relaxed(priv->control0);
+	reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
+	writel(reg, priv->control0);
+
+	/* Average the output value over 2^1 = 2 samples */
+	reg = readl_relaxed(priv->control1);
+	reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT;
+	reg |= 1 << CONTROL1_TSEN_AVG_SHIFT;
+	writel(reg, priv->control1);
 }
 
 static bool armada_is_valid(struct armada_thermal_priv *priv)
Signature · 1 line
2.14.1
author maintainer
#6 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

In reply to Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward compatibility), move the thermal node into a wider syscon from which it will be possible to also configure the thermal interrupt.

---
 drivers/thermal/armada_thermal.c | 197 +++++++++++++++++++++++++--------------
 1 file changed, 128 insertions(+), 69 deletions(-)
drivers/thermal/armada_thermal.c +128 -69
index 1f9706d96a0d..be346c6afde2 100644
@@ -24,6 +24,8 @@
 #include <linux/of_device.h>
 #include <linux/thermal.h>
 #include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 /* Thermal Manager Control and Status Register */
 #define PMU_TDC0_SW_RST_MASK		(0x1 << 1)
@@ -39,14 +41,6 @@
 #define A375_READOUT_INVERT		BIT(15)
 #define A375_HW_RESETn			BIT(8)
 
-/* Legacy bindings */
-#define LEGACY_CONTROL_MEM_LEN		0x4
-
-/* Current bindings with the 2 control registers under the same memory area */
-#define LEGACY_CONTROL1_OFFSET		0x0
-#define CONTROL0_OFFSET			0x0
-#define CONTROL1_OFFSET			0x4
-
 /* Errata fields */
 #define CONTROL0_TSEN_TC_TRIM_MASK	0x7
 #define CONTROL0_TSEN_TC_TRIM_VAL	0x3
@@ -70,9 +64,7 @@ struct armada_thermal_data;
 
 /* Marvell EBU Thermal Sensor Dev Structure */
 struct armada_thermal_priv {
-	void __iomem *status;
-	void __iomem *control0;
-	void __iomem *control1;
+	struct regmap *syscon;
 	char zone_name[THERMAL_NAME_LENGTH];
 	struct armada_thermal_data *data;
 };
@@ -96,15 +88,20 @@ struct armada_thermal_data {
 	unsigned int temp_shift;
 	unsigned int temp_mask;
 	u32 is_valid_bit;
-	bool needs_control0;
+
+	/* Syscon access */
+	unsigned int syscon_control0_off;
+	unsigned int syscon_control1_off;
+	unsigned int syscon_status_off;
 };
 
 static void armadaxp_init(struct platform_device *pdev,
 			  struct armada_thermal_priv *priv)
 {
+	struct armada_thermal_data *data = priv->data;
 	u32 reg;
 
-	reg = readl_relaxed(priv->control1);
+	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 	reg |= PMU_TDC0_OTF_CAL_MASK;
 
 	/* Reference calibration value */
@@ -114,29 +111,31 @@ static void armadaxp_init(struct platform_device *pdev,
 	/* Reset the sensor */
 	reg |= PMU_TDC0_SW_RST_MASK;
 
-	writel(reg, priv->control1);
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
 
 	/* Enable the sensor */
-	reg = readl_relaxed(priv->status);
+	regmap_read(priv->syscon, data->syscon_status_off, &reg);
 	reg &= ~PMU_TM_DISABLE_MASK;
-	writel(reg, priv->status);
+	regmap_write(priv->syscon, data->syscon_status_off, reg);
 }
 
 static void armada370_init(struct platform_device *pdev,
 			   struct armada_thermal_priv *priv)
 {
+	struct armada_thermal_data *data = priv->data;
 	u32 reg;
 
-	reg = readl_relaxed(priv->control1);
+	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 	reg |= PMU_TDC0_OTF_CAL_MASK;
 
 	/* Reference calibration value */
 	reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
 	reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
 
+	/* Reset the sensor */
 	reg &= ~PMU_TDC0_START_CAL_MASK;
 
-	writel(reg, priv->control1);
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
 
 	msleep(10);
 }
@@ -144,18 +143,20 @@ static void armada370_init(struct platform_device *pdev,
 static void armada375_init(struct platform_device *pdev,
 			   struct armada_thermal_priv *priv)
 {
+	struct armada_thermal_data *data = priv->data;
 	u32 reg;
 
-	reg = readl(priv->control1);
+	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 	reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
 	reg &= ~A375_READOUT_INVERT;
 	reg &= ~A375_HW_RESETn;
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
 
-	writel(reg, priv->control1);
 	msleep(20);
 
 	reg |= A375_HW_RESETn;
-	writel(reg, priv->control1);
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
+
 	msleep(50);
 }
 
@@ -163,29 +164,29 @@ static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
-	readl_relaxed_poll_timeout(priv->status, reg,
-				   reg & priv->data->is_valid_bit,
-				   STATUS_POLL_PERIOD_US,
-				   STATUS_POLL_TIMEOUT_US);
+	regmap_read_poll_timeout(priv->syscon, priv->data->syscon_status_off,
+				 reg, reg & priv->data->is_valid_bit,
+				 STATUS_POLL_PERIOD_US,
+				 STATUS_POLL_TIMEOUT_US);
 }
 
 static void armada380_init(struct platform_device *pdev,
 			   struct armada_thermal_priv *priv)
 {
-	u32 reg = readl_relaxed(priv->control1);
+	struct armada_thermal_data *data = priv->data;
+	u32 reg;
 
 	/* Disable the HW/SW reset */
+	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 	reg |= CONTROL1_EXT_TSEN_HW_RESETn;
 	reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
-	writel(reg, priv->control1);
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
 
 	/* Set Tsen Tc Trim to correct default value (errata #132698) */
-	if (priv->control0) {
-		reg = readl_relaxed(priv->control0);
-		reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
-		reg |= CONTROL0_TSEN_TC_TRIM_VAL;
-		writel(reg, priv->control0);
-	}
+	regmap_read(priv->syscon, data->syscon_control0_off, &reg);
+	reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
+	reg |= CONTROL0_TSEN_TC_TRIM_VAL;
+	regmap_write(priv->syscon, data->syscon_control0_off, reg);
 
 	/* Wait the sensors to be valid or the core will warn the user */
 	armada_wait_sensor_validity(priv);
@@ -194,9 +195,10 @@ static void armada380_init(struct platform_device *pdev,
 static void armada_ap806_init(struct platform_device *pdev,
 			      struct armada_thermal_priv *priv)
 {
+	struct armada_thermal_data *data = priv->data;
 	u32 reg;
 
-	reg = readl_relaxed(priv->control0);
+	regmap_read(priv->syscon, data->syscon_control0_off, &reg);
 	reg &= ~CONTROL0_TSEN_RESET;
 	reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
 
@@ -206,7 +208,7 @@ static void armada_ap806_init(struct platform_device *pdev,
 	/* Enable average (2 samples by default) */
 	reg &= ~CONTROL0_TSEN_AVG_BYPASS;
 
-	writel(reg, priv->control0);
+	regmap_write(priv->syscon, data->syscon_control0_off, reg);
 
 	/* Wait the sensors to be valid or the core will warn the user */
 	armada_wait_sensor_validity(priv);
@@ -215,25 +217,28 @@ static void armada_ap806_init(struct platform_device *pdev,
 static void armada_cp110_init(struct platform_device *pdev,
 			      struct armada_thermal_priv *priv)
 {
+	struct armada_thermal_data *data = priv->data;
 	u32 reg;
 
 	armada380_init(pdev, priv);
 
 	/* Sample every ~2ms */
-	reg = readl_relaxed(priv->control0);
+	regmap_read(priv->syscon, data->syscon_control0_off, &reg);
 	reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
-	writel(reg, priv->control0);
+	regmap_write(priv->syscon, data->syscon_control0_off, reg);
 
 	/* Average the output value over 2^1 = 2 samples */
-	reg = readl_relaxed(priv->control1);
+	regmap_read(priv->syscon, data->syscon_control1_off, &reg);
 	reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT;
 	reg |= 1 << CONTROL1_TSEN_AVG_SHIFT;
-	writel(reg, priv->control1);
+	regmap_write(priv->syscon, data->syscon_control1_off, reg);
 }
 
 static bool armada_is_valid(struct armada_thermal_priv *priv)
 {
-	u32 reg = readl_relaxed(priv->status);
+	u32 reg;
+
+	regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 
 	return reg & priv->data->is_valid_bit;
 }
@@ -252,7 +257,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
 		return -EIO;
 	}
 
-	reg = readl_relaxed(priv->status);
+	regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 	reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
 	if (priv->data->signed_sample)
 		/* The most significant bit is the sign bit */
@@ -284,6 +289,8 @@ static const struct armada_thermal_data armadaxp_data = {
 	.coef_b = 3153000000ULL,
 	.coef_m = 10000000ULL,
 	.coef_div = 13825,
+	.syscon_status_off = 0xb0,
+	.syscon_control1_off = 0xd0,
 };
 
 static const struct armada_thermal_data armada370_data = {
@@ -295,6 +302,8 @@ static const struct armada_thermal_data armada370_data = {
 	.coef_b = 3153000000ULL,
 	.coef_m = 10000000ULL,
 	.coef_div = 13825,
+	.syscon_status_off = 0x0,
+	.syscon_control1_off = 0x4,
 };
 
 static const struct armada_thermal_data armada375_data = {
@@ -306,7 +315,9 @@ static const struct armada_thermal_data armada375_data = {
 	.coef_b = 3171900000ULL,
 	.coef_m = 10000000ULL,
 	.coef_div = 13616,
-	.needs_control0 = true,
+	.syscon_status_off = 0x78,
+	.syscon_control0_off = 0x7c,
+	.syscon_control1_off = 0x80,
 };
 
 static const struct armada_thermal_data armada380_data = {
@@ -319,6 +330,9 @@ static const struct armada_thermal_data armada380_data = {
 	.coef_m = 2000096ULL,
 	.coef_div = 4201,
 	.inverted = true,
+	.syscon_control0_off = 0x70,
+	.syscon_control1_off = 0x74,
+	.syscon_status_off = 0x78,
 };
 
 static const struct armada_thermal_data armada_ap806_data = {
@@ -332,7 +346,9 @@ static const struct armada_thermal_data armada_ap806_data = {
 	.coef_div = 1,
 	.inverted = true,
 	.signed_sample = true,
-	.needs_control0 = true,
+	.syscon_control0_off = 0x84,
+	.syscon_control1_off = 0x88,
+	.syscon_status_off = 0x8C,
 };
 
 static const struct armada_thermal_data armada_cp110_data = {
@@ -345,7 +361,9 @@ static const struct armada_thermal_data armada_cp110_data = {
 	.coef_m = 2000096ULL,
 	.coef_div = 4201,
 	.inverted = true,
-	.needs_control0 = true,
+	.syscon_control0_off = 0x70,
+	.syscon_control1_off = 0x74,
+	.syscon_status_off = 0x78,
 };
 
 static const struct of_device_id armada_thermal_id_table[] = {
@@ -379,6 +397,57 @@ static const struct of_device_id armada_thermal_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
 
+static const struct regmap_config armada_thermal_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.fast_io = true,
+};
+
+static int armada_thermal_probe_legacy(struct platform_device *pdev,
+				       struct armada_thermal_priv *priv)
+{
+	struct armada_thermal_data *data = priv->data;
+	struct resource *res;
+	void __iomem *base;
+
+	/* First memory region points towards the status register */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (IS_ERR(res))
+		return PTR_ERR(res);
+
+	/*
+	 * Edit the resource start address and length to map over all the
+	 * registers, instead of pointing at them one by one.
+	 */
+	res->start -= data->syscon_status_off;
+	res->end = res->start + max(data->syscon_status_off,
+				    max(data->syscon_control0_off,
+					data->syscon_control1_off)) +
+		   sizeof(unsigned int) - 1;
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
+					     &armada_thermal_regmap_config);
+	if (IS_ERR(priv->syscon))
+		return PTR_ERR(priv->syscon);
+
+	return 0;
+}
+
+static int armada_thermal_probe_syscon(struct platform_device *pdev,
+				       struct armada_thermal_priv *priv)
+{
+	priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node);
+	if (IS_ERR(priv->syscon))
+		return PTR_ERR(priv->syscon);
+
+	return 0;
+}
+
 static void armada_set_sane_name(struct platform_device *pdev,
 				 struct armada_thermal_priv *priv)
 {
@@ -411,11 +480,10 @@ static void armada_set_sane_name(struct platform_device *pdev,
 
 static int armada_thermal_probe(struct platform_device *pdev)
 {
-	void __iomem *control = NULL;
 	struct thermal_zone_device *thermal;
 	const struct of_device_id *match;
 	struct armada_thermal_priv *priv;
-	struct resource *res;
+	int ret;
 
 	match = of_match_device(armada_thermal_id_table, &pdev->dev);
 	if (!match)
@@ -425,16 +493,6 @@ static int armada_thermal_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	priv->status = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(priv->status))
-		return PTR_ERR(priv->status);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	control = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(control))
-		return PTR_ERR(control);
-
 	priv->data = (struct armada_thermal_data *)match->data;
 
 	/* Ensure device name is correct for the thermal core */
@@ -442,22 +500,23 @@ static int armada_thermal_probe(struct platform_device *pdev)
 
 	/*
 	 * Legacy DT bindings only described "control1" register (also referred
-	 * as "control MSB" on old documentation). New bindings cover
+	 * as "control MSB" on old documentation). Then, bindings moved to cover
 	 * "control0/control LSB" and "control1/control MSB" registers within
-	 * the same resource, which is then of size 8 instead of 4.
+	 * the same resource, which was then of size 8 instead of 4.
+	 *
+	 * The logic of defining sporadic registers is broken. For instance, it
+	 * blocked the addition of the overheat interrupt feature that needed
+	 * another resource somewhere else in the same memory area. One solution
+	 * is to define an overall system controller and put the thermal node
+	 * into it, which requires the use of regmaps across all the driver.
 	 */
-	if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) {
-		/* ->control0 unavailable in this configuration */
-		if (priv->data->needs_control0) {
-			dev_err(&pdev->dev, "No access to control0 register\n");
-			return -EINVAL;
-		}
+	if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node)))
+		ret = armada_thermal_probe_legacy(pdev, priv);
+	else
+		ret = armada_thermal_probe_syscon(pdev, priv);
 
-		priv->control1 = control + LEGACY_CONTROL1_OFFSET;
-	} else {
-		priv->control0 = control + CONTROL0_OFFSET;
-		priv->control1 = control + CONTROL1_OFFSET;
-	}
+	if (ret)
+		return ret;
 
 	priv->data->init(pdev, priv);
 
Signature · 1 line
2.14.1
#7 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

Hi Miquel,

Quoted 9 lines · Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward

s/de/the/

Quoted 4 lines

compatibility), move the thermal node into a wider syscon from which it will be possible to also configure the thermal interrupt.

baruch

Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -
author maintainer
#8 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

Hi Baruch,

Quoted 10 lines · Baruch Siach

Hi Miquel,

Quoted 7 lines · Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

Quoted 4 lines
Quoted 2 lines

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward

s/de/the/

Oh and s/intead/instead/ too.

Thanks for pointing it,
Miqu?l

#9 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

Miquel,

Quoted 15 lines · Miquel Raynal

Hi Baruch,

Quoted 10 lines · Baruch Siach

Hi Miquel,

Quoted 7 lines · Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward

s/de/the/

Oh and s/intead/instead/ too.

Can you please fix the minor above and also refresh against linus master branch? Patch does not apply clean anymore.
checking file drivers/thermal/armada_thermal.c
Hunk #3 FAILED at 64.
Hunk #4 succeeded at 89 (offset -1 lines).
Hunk #5 succeeded at 112 (offset -1 lines).
Hunk #6 succeeded at 144 (offset -1 lines).
Hunk #7 succeeded at 165 (offset -1 lines).
Hunk #8 succeeded at 196 (offset -1 lines).
Hunk #9 succeeded at 209 (offset -1 lines).
Hunk #10 succeeded at 218 (offset -1 lines).
Hunk #11 succeeded at 258 (offset -1 lines).
Hunk #12 succeeded at 290 (offset -1 lines).
Hunk #13 succeeded at 303 (offset -1 lines).
Hunk #14 succeeded at 316 (offset -1 lines).
Hunk #15 succeeded at 331 (offset -1 lines).
Hunk #16 succeeded at 347 (offset -1 lines).
Hunk #17 succeeded at 362 (offset -1 lines).
Hunk #18 FAILED at 399.
Hunk #19 succeeded at 400 (offset -31 lines).
Hunk #20 succeeded at 413 with fuzz 1 (offset -31 lines). Hunk #21 succeeded at 417 (offset -34 lines).
2 out of 21 hunks FAILED

I get the above after applying the first 5 patches of your series.

Quoted 3 lines

Thanks for pointing it,
Miqu?l

author maintainer
#10 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

Hi Eduardo,

Eduardo Valentin <[email protected]> wrote on Mon, 2 Jul 2018 10:29:19 -0700:

Quoted 21 lines

Miquel,

Quoted 18 lines · Miquel Raynal

Hi Baruch,

Quoted 13 lines · Baruch Siach

Hi Miquel,

Quoted 9 lines · Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward

Quoted 6 lines
Quoted 3 lines
Quoted 1 line

s/de/the/

Oh and s/intead/instead/ too.

Can you please fix the minor above and also refresh against linus master branch? Patch does not apply clean anymore.

Sure, I'll send a new version rebased on top of Linus's master branch.

Thanks for taking the time to check the series,
Miqu?l

author maintainer
#11 lore raw

PATCH v2 6/23 thermal: armada: convert driver to syscon register accesses

Hi Eduardo,

Miquel Raynal <[email protected]> wrote on Thu, 5 Jul 2018 14:43:33 +0200:

Quoted 26 lines

Hi Eduardo,

Eduardo Valentin <[email protected]> wrote on Mon, 2 Jul 2018 10:29:19 -0700:

Quoted 21 lines

Miquel,

Quoted 18 lines · Miquel Raynal

Hi Baruch,

Quoted 13 lines · Baruch Siach

Hi Miquel,

Quoted 9 lines · Miquel Raynal

Until recently, only one register was referenced in MVEBU thermal IP node. Recent changes added a second entry pointing to another register right next to it. We cannot know for sure that we will not have to access other registers. That will be actually the case when overheat interrupt feature will come, where it will be needed to access DFX registers in the same area.

This approach is not scalable so intead of adding consinuously memory areas in the DT (and change de DT bindings, while keeping backward

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line

s/de/the/

Oh and s/intead/instead/ too.

Can you please fix the minor above and also refresh against linus master branch? Patch does not apply clean anymore.

Sure, I'll send a new version rebased on top of Linus's master branch.

Actually this series was based on v4.18-rc1. When I rebased on top of Linus's master branch I had no conflicts to fix. I will repost a v3 but if the problem persists you might want to share the conflicts or give me a branch on top of which I should base this work.

Thanks,
Miqu?l

author maintainer
#12 lore raw

PATCH v2 7/23 thermal: armada: use the resource managed registration helper alternative

In reply to Miquel Raynal

Current use of thermal_zone_device_register() triggers a warning at boot and should be replaced by devm_thermal_zone_of_sensor_register(). This allows better handling of multiple thermal zones for later multi-sensors support.

Also change the driver data to embed a new structure to make the difference between legacy data (which needs to be cleaned) and syscon-related data.

---
 drivers/thermal/armada_thermal.c | 128 ++++++++++++++++++++++++++++++++-------
 1 file changed, 107 insertions(+), 21 deletions(-)
drivers/thermal/armada_thermal.c +107 -21
index be346c6afde2..8a734264ecdd 100644
@@ -64,6 +64,7 @@ struct armada_thermal_data;
 
 /* Marvell EBU Thermal Sensor Dev Structure */
 struct armada_thermal_priv {
+	struct device *dev;
 	struct regmap *syscon;
 	char zone_name[THERMAL_NAME_LENGTH];
 	struct armada_thermal_data *data;
@@ -95,6 +96,26 @@ struct armada_thermal_data {
 	unsigned int syscon_status_off;
 };
 
+struct armada_drvdata {
+	enum drvtype {
+		LEGACY,
+		SYSCON
+	} type;
+	union {
+		struct armada_thermal_priv *priv;
+		struct thermal_zone_device *tz;
+	} data;
+};
+
+/*
+ * struct armada_thermal_sensor - hold the information of one thermal sensor
+ * @thermal: pointer to the local private structure
+ * @tzd: pointer to the thermal zone device
+ */
+struct armada_thermal_sensor {
+	struct armada_thermal_priv *priv;
+};
+
 static void armadaxp_init(struct platform_device *pdev,
 			  struct armada_thermal_priv *priv)
 {
@@ -243,16 +264,14 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
 	return reg & priv->data->is_valid_bit;
 }
 
-static int armada_get_temp(struct thermal_zone_device *thermal,
-			   int *temp)
+static int armada_read_sensor(struct armada_thermal_priv *priv, long *temp)
 {
-	struct armada_thermal_priv *priv = thermal->devdata;
 	u32 reg, div;
 	s64 sample, b, m;
 
 	/* Valid check */
 	if (priv->data->is_valid && !priv->data->is_valid(priv)) {
-		dev_err(&thermal->device,
+		dev_err(priv->dev,
 			"Temperature sensor reading not valid\n");
 		return -EIO;
 	}
@@ -278,7 +297,39 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
 	return 0;
 }
 
-static struct thermal_zone_device_ops ops = {
+static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
+				  int *temp)
+{
+	struct armada_thermal_priv *priv = thermal->devdata;
+	long temperature;
+	int ret;
+
+	/* Do the actual reading */
+	ret = armada_read_sensor(priv, &temperature);
+	*temp = temperature;
+
+	return ret;
+}
+
+static struct thermal_zone_device_ops legacy_ops = {
+	.get_temp = armada_get_temp_legacy,
+};
+
+static int armada_get_temp(void *_sensor, int *temp)
+{
+	struct armada_thermal_sensor *sensor = _sensor;
+	struct armada_thermal_priv *priv = sensor->priv;
+	long temperature;
+	int ret;
+
+	/* Do the actual reading */
+	ret = armada_read_sensor(priv, &temperature);
+	*temp = temperature;
+
+	return ret;
+}
+
+static struct thermal_zone_of_device_ops of_ops = {
 	.get_temp = armada_get_temp,
 };
 
@@ -480,7 +531,9 @@ static void armada_set_sane_name(struct platform_device *pdev,
 
 static int armada_thermal_probe(struct platform_device *pdev)
 {
-	struct thermal_zone_device *thermal;
+	struct thermal_zone_device *tz;
+	struct armada_thermal_sensor *sensors;
+	struct armada_drvdata *drvdata;
 	const struct of_device_id *match;
 	struct armada_thermal_priv *priv;
 	int ret;
@@ -493,11 +546,13 @@ static int armada_thermal_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = &pdev->dev;
 	priv->data = (struct armada_thermal_data *)match->data;
 
-	/* Ensure device name is correct for the thermal core */
-	armada_set_sane_name(pdev, priv);
-
 	/*
 	 * Legacy DT bindings only described "control1" register (also referred
 	 * as "control MSB" on old documentation). Then, bindings moved to cover
@@ -510,35 +565,66 @@ static int armada_thermal_probe(struct platform_device *pdev)
 	 * is to define an overall system controller and put the thermal node
 	 * into it, which requires the use of regmaps across all the driver.
 	 */
-	if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node)))
+	if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) {
+		/* Ensure device name is correct for the thermal core */
+		armada_set_sane_name(pdev, priv);
+
 		ret = armada_thermal_probe_legacy(pdev, priv);
-	else
-		ret = armada_thermal_probe_syscon(pdev, priv);
+		if (ret)
+			return ret;
 
+		priv->data->init(pdev, priv);
+
+		tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
+						  &legacy_ops, NULL, 0, 0);
+		if (IS_ERR(tz)) {
+			dev_err(&pdev->dev,
+				"Failed to register thermal zone device\n");
+			return PTR_ERR(tz);
+		}
+
+		drvdata->type = LEGACY;
+		drvdata->data.tz = tz;
+		platform_set_drvdata(pdev, drvdata);
+
+		return 0;
+	}
+
+	ret = armada_thermal_probe_syscon(pdev, priv);
 	if (ret)
 		return ret;
 
 	priv->data->init(pdev, priv);
 
-	thermal = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
-					       &ops, NULL, 0, 0);
-	if (IS_ERR(thermal)) {
+	sensors = devm_kzalloc(&pdev->dev, sizeof(struct armada_thermal_sensor),
+			       GFP_KERNEL);
+	if (!sensors)
+		return -ENOMEM;
+
+	sensors->priv = priv;
+
+	tz = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, sensors,
+						  &of_ops);
+	if (IS_ERR(tz)) {
 		dev_err(&pdev->dev,
-			"Failed to register thermal zone device\n");
-		return PTR_ERR(thermal);
+			"Failed to register thermal sensor (err: %ld)\n",
+			PTR_ERR(tz));
+		return PTR_ERR(tz);
 	}
 
-	platform_set_drvdata(pdev, thermal);
+	drvdata->type = SYSCON;
+	drvdata->data.priv = priv;
+	platform_set_drvdata(pdev, drvdata);
 
 	return 0;
 }
 
 static int armada_thermal_exit(struct platform_device *pdev)
 {
-	struct thermal_zone_device *armada_thermal =
-		platform_get_drvdata(pdev);
+	struct armada_drvdata *drvdata = platform_get_drvdata(pdev);
 
-	thermal_zone_device_unregister(armada_thermal);
+	if (drvdata->type == LEGACY)
+		thermal_zone_device_unregister(drvdata->data.tz);
 
 	return 0;
 }
Signature · 1 line
2.14.1
author maintainer
#13 lore raw

PATCH v2 8/23 thermal: armada: add multi-channel sensors support

In reply to Miquel Raynal

MVEBU thermal IP supports multiple channels. Each channel may have several sensors but for now each channel is wired to only one thermal sensor. The first channel always points to the so called internal sensor, within the thermal IP. There is usually one more channel (with one sensor each time) per CPU. The code has been written to support possible evolutions of the ap806 IP that would embed more CPUs and thus more channels to select. Each channel should be referenced in the device tree as an independent thermal zone.

Add the possibility to read each of these sensors through sysfs by registering all the sensors (translated in "thermal_zone"). Also add a mutex on these accesses to avoid read conflicts (only one channel/sensor may be selected and read at a time).

---
 drivers/thermal/armada_thermal.c | 130 +++++++++++++++++++++++++++++++++------
 1 file changed, 111 insertions(+), 19 deletions(-)
drivers/thermal/armada_thermal.c +111 -19
index 8a734264ecdd..2b11bf929b64 100644
@@ -49,8 +49,13 @@
 #define CONTROL0_TSEN_RESET		BIT(1)
 #define CONTROL0_TSEN_ENABLE		BIT(2)
 #define CONTROL0_TSEN_AVG_BYPASS	BIT(6)
+#define CONTROL0_TSEN_CHAN_SHIFT	13
+#define CONTROL0_TSEN_CHAN_MASK		0xF
 #define CONTROL0_TSEN_OSR_SHIFT		24
 #define CONTROL0_TSEN_OSR_MAX		0x3
+#define CONTROL0_TSEN_MODE_SHIFT	30
+#define CONTROL0_TSEN_MODE_EXTERNAL	0x2
+#define CONTROL0_TSEN_MODE_MASK		0x3
 
 #define CONTROL1_TSEN_AVG_SHIFT		0
 #define CONTROL1_TSEN_AVG_MASK		0x7
@@ -67,7 +72,9 @@ struct armada_thermal_priv {
 	struct device *dev;
 	struct regmap *syscon;
 	char zone_name[THERMAL_NAME_LENGTH];
+	struct mutex update_lock;
 	struct armada_thermal_data *data;
+	int current_channel;
 };
 
 struct armada_thermal_data {
@@ -94,6 +101,9 @@ struct armada_thermal_data {
 	unsigned int syscon_control0_off;
 	unsigned int syscon_control1_off;
 	unsigned int syscon_status_off;
+
+	/* One sensor is in the thermal IC, the others are in the CPUs if any */
+	unsigned int cpu_nr;
 };
 
 struct armada_drvdata {
@@ -111,9 +121,11 @@ struct armada_drvdata {
  * struct armada_thermal_sensor - hold the information of one thermal sensor
  * @thermal: pointer to the local private structure
  * @tzd: pointer to the thermal zone device
+ * @id: identifier of the thermal sensor
  */
 struct armada_thermal_sensor {
 	struct armada_thermal_priv *priv;
+	int id;
 };
 
 static void armadaxp_init(struct platform_device *pdev,
@@ -181,14 +193,15 @@ static void armada375_init(struct platform_device *pdev,
 	msleep(50);
 }
 
-static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
+static int armada_wait_sensor_validity(struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
-	regmap_read_poll_timeout(priv->syscon, priv->data->syscon_status_off,
-				 reg, reg & priv->data->is_valid_bit,
-				 STATUS_POLL_PERIOD_US,
-				 STATUS_POLL_TIMEOUT_US);
+	return regmap_read_poll_timeout(priv->syscon,
+					priv->data->syscon_status_off, reg,
+					reg & priv->data->is_valid_bit,
+					STATUS_POLL_PERIOD_US,
+					STATUS_POLL_TIMEOUT_US);
 }
 
 static void armada380_init(struct platform_device *pdev,
@@ -264,6 +277,58 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
 	return reg & priv->data->is_valid_bit;
 }
 
+/* There is currently no board with more than one sensor per channel */
+static int armada_select_channel(struct armada_thermal_priv *priv, int channel)
+{
+	struct armada_thermal_data *data = priv->data;
+	u32 ctrl0;
+
+	if (channel < 0 || channel > priv->data->cpu_nr)
+		return -EINVAL;
+
+	if (priv->current_channel == channel)
+		return 0;
+
+	/* Stop the measurements */
+	regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0);
+	ctrl0 &= ~CONTROL0_TSEN_START;
+	regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
+
+	/* Reset the mode, internal sensor will be automatically selected */
+	ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT);
+
+	/* Other channels are external and should be selected accordingly */
+	if (channel) {
+		/* Change the mode to external */
+		ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL <<
+			 CONTROL0_TSEN_MODE_SHIFT;
+		/* Select the sensor */
+		ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT);
+		ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT;
+	}
+
+	/* Actually set the mode/channel */
+	regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
+	priv->current_channel = channel;
+
+	/* Re-start the measurements */
+	ctrl0 |= CONTROL0_TSEN_START;
+	regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
+
+	/*
+	 * The IP has a latency of ~15ms, so after updating the selected source,
+	 * we must absolutely wait for the sensor validity bit to ensure we read
+	 * actual data.
+	 */
+	if (armada_wait_sensor_validity(priv)) {
+		dev_err(priv->dev,
+			"Temperature sensor reading not valid\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int armada_read_sensor(struct armada_thermal_priv *priv, long *temp)
 {
 	u32 reg, div;
@@ -322,10 +387,23 @@ static int armada_get_temp(void *_sensor, int *temp)
 	long temperature;
 	int ret;
 
+	mutex_lock(&priv->update_lock);
+
+	/* Select the desired channel */
+	ret = armada_select_channel(priv, sensor->id);
+	if (ret)
+		goto unlock_mutex;
+
 	/* Do the actual reading */
 	ret = armada_read_sensor(priv, &temperature);
+	if (ret)
+		goto unlock_mutex;
+
 	*temp = temperature;
 
+unlock_mutex:
+	mutex_unlock(&priv->update_lock);
+
 	return ret;
 }
 
@@ -400,6 +478,7 @@ static const struct armada_thermal_data armada_ap806_data = {
 	.syscon_control0_off = 0x84,
 	.syscon_control1_off = 0x88,
 	.syscon_status_off = 0x8C,
+	.cpu_nr = 4,
 };
 
 static const struct armada_thermal_data armada_cp110_data = {
@@ -532,10 +611,11 @@ static void armada_set_sane_name(struct platform_device *pdev,
 static int armada_thermal_probe(struct platform_device *pdev)
 {
 	struct thermal_zone_device *tz;
-	struct armada_thermal_sensor *sensors;
+	struct armada_thermal_sensor *sensor;
 	struct armada_drvdata *drvdata;
 	const struct of_device_id *match;
 	struct armada_thermal_priv *priv;
+	int sensor_id;
 	int ret;
 
 	match = of_match_device(armada_thermal_id_table, &pdev->dev);
@@ -553,6 +633,8 @@ static int armada_thermal_probe(struct platform_device *pdev)
 	priv->dev = &pdev->dev;
 	priv->data = (struct armada_thermal_data *)match->data;
 
+	mutex_init(&priv->update_lock);
+
 	/*
 	 * Legacy DT bindings only described "control1" register (also referred
 	 * as "control MSB" on old documentation). Then, bindings moved to cover
@@ -594,22 +676,32 @@ static int armada_thermal_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	priv->current_channel = -1;
 	priv->data->init(pdev, priv);
 
-	sensors = devm_kzalloc(&pdev->dev, sizeof(struct armada_thermal_sensor),
-			       GFP_KERNEL);
-	if (!sensors)
-		return -ENOMEM;
+	/*
+	 * There is one channel for the IC and one per CPU (if any), each
+	 * channel has one sensor.
+	 */
+	for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) {
+		sensor = devm_kzalloc(&pdev->dev,
+				      sizeof(struct armada_thermal_sensor),
+				      GFP_KERNEL);
+		if (!sensor)
+			return -ENOMEM;
 
-	sensors->priv = priv;
-
-	tz = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, sensors,
-						  &of_ops);
-	if (IS_ERR(tz)) {
-		dev_err(&pdev->dev,
-			"Failed to register thermal sensor (err: %ld)\n",
-			PTR_ERR(tz));
-		return PTR_ERR(tz);
+		/* Register the sensor */
+		sensor->priv = priv;
+		sensor->id = sensor_id;
+		tz = devm_thermal_zone_of_sensor_register(&pdev->dev,
+							  sensor->id, sensor,
+							  &of_ops);
+		if (IS_ERR(tz)) {
+			dev_info(&pdev->dev, "Thermal sensor %d unavailable\n",
+				 sensor_id);
+			devm_kfree(&pdev->dev, sensor);
+			continue;
+		}
 	}
 
 	drvdata->type = SYSCON;
Signature · 1 line
2.14.1
author maintainer
#14 lore raw

PATCH v2 9/23 thermal: armada: remove sensors validity from the IP initialization

In reply to Miquel Raynal

When using new bindings with multiple sensors, sensor validity is checked twice because sensor selection also checks for the validity.

Remove the redundant call from the IP initialization helper and move it to the legacy probe section where it is still needed.

---
 drivers/thermal/armada_thermal.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)
drivers/thermal/armada_thermal.c +3 -6
index 2b11bf929b64..3d5b29133d3a 100644
@@ -221,9 +221,6 @@ static void armada380_init(struct platform_device *pdev,
 	reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
 	reg |= CONTROL0_TSEN_TC_TRIM_VAL;
 	regmap_write(priv->syscon, data->syscon_control0_off, reg);
-
-	/* Wait the sensors to be valid or the core will warn the user */
-	armada_wait_sensor_validity(priv);
 }
 
 static void armada_ap806_init(struct platform_device *pdev,
@@ -243,9 +240,6 @@ static void armada_ap806_init(struct platform_device *pdev,
 	reg &= ~CONTROL0_TSEN_AVG_BYPASS;
 
 	regmap_write(priv->syscon, data->syscon_control0_off, reg);
-
-	/* Wait the sensors to be valid or the core will warn the user */
-	armada_wait_sensor_validity(priv);
 }
 
 static void armada_cp110_init(struct platform_device *pdev,
@@ -657,6 +651,9 @@ static int armada_thermal_probe(struct platform_device *pdev)
 
 		priv->data->init(pdev, priv);
 
+		/* Wait the sensors to be valid */
+		armada_wait_sensor_validity(priv);
+
 		tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
 						  &legacy_ops, NULL, 0, 0);
 		if (IS_ERR(tz)) {
Signature · 1 line
2.14.1
author maintainer
#15 lore raw

PATCH v2 10/23 thermal: armada: move validity check out of the read function

In reply to Miquel Raynal

Sensor selection when using multiple sensors already checks for the sensor validity. Move it to the legacy ->get_temp() hook, where it is still needed.

---
 drivers/thermal/armada_thermal.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/thermal/armada_thermal.c +7 -7
index 3d5b29133d3a..4e9f947a0f5f 100644
@@ -328,13 +328,6 @@ static int armada_read_sensor(struct armada_thermal_priv *priv, long *temp)
 	u32 reg, div;
 	s64 sample, b, m;
 
-	/* Valid check */
-	if (priv->data->is_valid && !priv->data->is_valid(priv)) {
-		dev_err(priv->dev,
-			"Temperature sensor reading not valid\n");
-		return -EIO;
-	}
-
 	regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 	reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
 	if (priv->data->signed_sample)
@@ -363,6 +356,13 @@ static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
 	long temperature;
 	int ret;
 
+	/* Valid check */
+	if (priv->data->is_valid && !priv->data->is_valid(priv)) {
+		dev_err(priv->dev,
+			"Temperature sensor reading not valid\n");
+		return -EIO;
+	}
+
 	/* Do the actual reading */
 	ret = armada_read_sensor(priv, &temperature);
 	*temp = temperature;
Signature · 1 line
2.14.1
author maintainer
#16 lore raw

PATCH v2 11/23 thermal: armada: get rid of the ->is_valid() pointer

In reply to Miquel Raynal

The implementation of armada_is_valid() is very simple and is the same across all the versions of the IP since the ->is_valid_bit has been introduced. Simplify the structure by getting rid of the function pointer and calling directly the function.

---
 drivers/thermal/armada_thermal.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
drivers/thermal/armada_thermal.c +4 -9
index 4e9f947a0f5f..66324fc853a3 100644
@@ -82,9 +82,6 @@ struct armada_thermal_data {
 	void (*init)(struct platform_device *pdev,
 		     struct armada_thermal_priv *priv);
 
-	/* Test for a valid sensor value (optional) */
-	bool (*is_valid)(struct armada_thermal_priv *);
-
 	/* Formula coeficients: temp = (b - m * reg) / div */
 	s64 coef_b;
 	s64 coef_m;
@@ -266,6 +263,9 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
 {
 	u32 reg;
 
+	if (!priv->data->is_valid_bit)
+		return true;
+
 	regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
 
 	return reg & priv->data->is_valid_bit;
@@ -357,7 +357,7 @@ static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
 	int ret;
 
 	/* Valid check */
-	if (priv->data->is_valid && !priv->data->is_valid(priv)) {
+	if (armada_is_valid(priv)) {
 		dev_err(priv->dev,
 			"Temperature sensor reading not valid\n");
 		return -EIO;
@@ -417,7 +417,6 @@ static const struct armada_thermal_data armadaxp_data = {
 };
 
 static const struct armada_thermal_data armada370_data = {
-	.is_valid = armada_is_valid,
 	.init = armada370_init,
 	.is_valid_bit = BIT(9),
 	.temp_shift = 10,
@@ -430,7 +429,6 @@ static const struct armada_thermal_data armada370_data = {
 };
 
 static const struct armada_thermal_data armada375_data = {
-	.is_valid = armada_is_valid,
 	.init = armada375_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
@@ -444,7 +442,6 @@ static const struct armada_thermal_data armada375_data = {
 };
 
 static const struct armada_thermal_data armada380_data = {
-	.is_valid = armada_is_valid,
 	.init = armada380_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
@@ -459,7 +456,6 @@ static const struct armada_thermal_data armada380_data = {
 };
 
 static const struct armada_thermal_data armada_ap806_data = {
-	.is_valid = armada_is_valid,
 	.init = armada_ap806_init,
 	.is_valid_bit = BIT(16),
 	.temp_shift = 0,
@@ -476,7 +472,6 @@ static const struct armada_thermal_data armada_ap806_data = {
 };
 
 static const struct armada_thermal_data armada_cp110_data = {
-	.is_valid = armada_is_valid,
 	.init = armada_cp110_init,
 	.is_valid_bit = BIT(10),
 	.temp_shift = 0,
Signature · 1 line
2.14.1
author maintainer
#17 lore raw

PATCH v2 12/23 dt-bindings: cp110: rename cp110 syscon file

In reply to Miquel Raynal

There is no need to give numbers to system controllers inside the documentation as the syscons use the same compatibles. Furthermore, this approach does not scale very well and would force the creation of a new file each time a new syscon is added in the device tree.

---
 .../marvell/{cp110-system-controller0.txt => cp110-system-controller.txt} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/arm/marvell/{cp110-system-controller0.txt => cp110-system-controller.txt} (100%)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt renamed from Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt +0 -0
similarity index 100%
rename from Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
rename to Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
Signature · 1 line
2.14.1
author maintainer
#18 lore raw

PATCH v2 13/23 dt-bindings: ap806: prepare the syscon file to list other syscons nodes

In reply to Miquel Raynal

There are multiple system controllers in AP806. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic.

---
 .../bindings/arm/marvell/ap806-system-controller.txt           | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +5 -5
index 0b887440e08a..a856eb9a4e05 100644
@@ -2,14 +2,14 @@ Marvell Armada AP806 System Controller
 ======================================
 
 The AP806 is one of the two core HW blocks of the Marvell Armada 7K/8K
-SoCs. It contains a system controller, which provides a number
-registers giving access to numerous features: clocks, pin-muxing and
-many other SoC configuration items. This DT binding allows to describe
-this system controller.
+SoCs. It contains system controllers, which provide several registers
+giving access to numerous features: clocks, pin-muxing and many other
+SoC configuration items. This DT binding allows to describe these
+system controllers.
 
 For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
-  - reg: register area of the AP806 system controller
+ - reg: register area of the AP806 system controller
 
 Clocks:
 -------
Signature · 1 line
2.14.1
maintainer
#19 lore raw

PATCH v2 13/23 dt-bindings: ap806: prepare the syscon file to list other syscons nodes

Quoted 8 lines · Miquel Raynal

There are multiple system controllers in AP806. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic.

---
 .../bindings/arm/marvell/ap806-system-controller.txt           | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
author maintainer
#20 lore raw

PATCH v2 14/23 dt-bindings: cp110: prepare the syscon file to list other syscons nodes

In reply to Miquel Raynal

There are multiple system controllers in CP110. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic, and align with AP806 file.

---
 .../bindings/arm/marvell/cp110-system-controller.txt       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +7 -7
index 29cdbae6c5ac..56e7fb1153e7 100644
@@ -1,15 +1,15 @@
-Marvell Armada CP110 System Controller 0
-========================================
+Marvell Armada CP110 System Controller
+======================================
 
 The CP110 is one of the two core HW blocks of the Marvell Armada 7K/8K
-SoCs. It contains two sets of system control registers, System
-Controller 0 and System Controller 1. This Device Tree binding allows
-to describe the first system controller, which provides registers to
-configure various aspects of the SoC.
+SoCs. It contains system controllers, which provide several registers
+giving access to numerous features: clocks, pin-muxing and many other
+SoC configuration items. This DT binding allows to describe these
+system controllers.
 
 For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
- - reg: register area of the CP110 system controller 0
+ - reg: register area of the CP110 system controller
 
 Clocks:
 -------
Signature · 1 line
2.14.1
#21 lore raw

PATCH v2 14/23 dt-bindings: cp110: prepare the syscon file to list other syscons nodes

Hi Miquel,

Quoted 6 lines · Miquel Raynal

There are multiple system controllers in CP110. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic, and align with AP806 file.

This patch and the file rename in patch #12 should be squashed together, I think.

baruch

Quoted 31 lines
---
 .../bindings/arm/marvell/cp110-system-controller.txt       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +7 -7
index 29cdbae6c5ac..56e7fb1153e7 100644
@@ -1,15 +1,15 @@
-Marvell Armada CP110 System Controller 0
-========================================
+Marvell Armada CP110 System Controller
+======================================
 
 The CP110 is one of the two core HW blocks of the Marvell Armada 7K/8K
-SoCs. It contains two sets of system control registers, System
-Controller 0 and System Controller 1. This Device Tree binding allows
-to describe the first system controller, which provides registers to
-configure various aspects of the SoC.
+SoCs. It contains system controllers, which provide several registers
+giving access to numerous features: clocks, pin-muxing and many other
+SoC configuration items. This DT binding allows to describe these
+system controllers.
 
 For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
- - reg: register area of the CP110 system controller 0
+ - reg: register area of the CP110 system controller
 
 Clocks:
 -------
Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -
author maintainer
#22 lore raw

PATCH v2 14/23 dt-bindings: cp110: prepare the syscon file to list other syscons nodes

Hi Baruch,

Quoted 8 lines · Baruch Siach

Hi Miquel,

Quoted 5 lines · Miquel Raynal

There are multiple system controllers in CP110. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic, and align with AP806 file.

Quoted 4 lines
Quoted 1 line

This patch and the file rename in patch #12 should be squashed together, I think.

I was asked multiple times to clearly separate any kind of file renaming with internal changes because otherwise the reviewing process is way more complicated. I do agree the changes could be squashed but now I prefer to let them as is unless I'm explicitly told to do so after the reviewing process.

Regards,
Miqu?l

maintainer
#23 lore raw

PATCH v2 14/23 dt-bindings: cp110: prepare the syscon file to list other syscons nodes

In reply to Miquel Raynal
Quoted 9 lines · Miquel Raynal

There are multiple system controllers in CP110. Because all syscon nodes use the same compatible, it is pertinent to use this same file to list IPs inside it. Thus, change the header to be more generic, and align with AP806 file.

---
 .../bindings/arm/marvell/cp110-system-controller.txt       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
author maintainer
#24 lore raw

PATCH v2 15/23 dt-bindings: ap806: add the thermal node in the syscon file

In reply to Miquel Raynal

Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node.

---
 .../arm/marvell/ap806-system-controller.txt        | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +38 -0
index a856eb9a4e05..a265f1628f36 100644
@@ -11,6 +11,9 @@ For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
  - reg: register area of the AP806 system controller
 
+SYSTEM CONTROLLER 0
+===================
+
 Clocks:
 -------
 
@@ -98,3 +101,38 @@ ap_syscon: system-controller at 6f4000 {
 		gpio-ranges = <&ap_pinctrl 0 0 19>;
 	};
 };
+
+SYSTEM CONTROLLER 1
+===================
+
+Thermal:
+--------
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/thermal/thermal.txt
+
+The thermal IP can probe the temperature all around the processor. It
+may feature several channels, each of them wired to one sensor.
+
+Required properties:
+- compatible: must be one of:
+  * marvell,armada-ap806-thermal
+- reg: register range associated with the thermal functions.
+
+Optional properties:
+- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer
+  to this IP and represents the channel ID. There is one sensor per
+  channel. O refers to the thermal IP internal channel, while positive
+  IDs refer to each CPU.
+
+Example:
+ap_syscon1: system-controller at 6f8000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x6f8000 0x1000>;
+
+	ap_thermal: ap-thermal at 80 {
+		compatible = "marvell,armada-ap806-thermal";
+		reg = <0x80 0x10>;
+		#thermal-sensor-cells = <1>;
+	};
+};
Signature · 1 line
2.14.1
maintainer
#25 lore raw

PATCH v2 15/23 dt-bindings: ap806: add the thermal node in the syscon file

Quoted 46 lines · Miquel Raynal

Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node.

---
 .../arm/marvell/ap806-system-controller.txt        | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +23 -0
index a856eb9a4e05..a265f1628f36 100644
@@ -11,6 +11,9 @@ For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
  - reg: register area of the AP806 system controller
 
+SYSTEM CONTROLLER 0
+===================
+
 Clocks:
 -------
 
@@ -98,3 +101,38 @@ ap_syscon: system-controller at 6f4000 {
 		gpio-ranges = <&ap_pinctrl 0 0 19>;
 	};
 };
+
+SYSTEM CONTROLLER 1
+===================
+
+Thermal:
+--------
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/thermal/thermal.txt
+
+The thermal IP can probe the temperature all around the processor. It
+may feature several channels, each of them wired to one sensor.
+
+Required properties:
+- compatible: must be one of:
+  * marvell,armada-ap806-thermal
+- reg: register range associated with the thermal functions.
+
+Optional properties:
+- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer

Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt ap_syscon: system-controller at 6f4000 { · line 133

Quoted 10 lines
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +10 -0
+  to this IP and represents the channel ID. There is one sensor per
+  channel. O refers to the thermal IP internal channel, while positive
+  IDs refer to each CPU.
+
+Example:
+ap_syscon1: system-controller at 6f8000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x6f8000 0x1000>;
+
+	ap_thermal: ap-thermal at 80 {

thermal-sensor at ...

With that,

Quoted 8 lines
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +5 -0
+		compatible = "marvell,armada-ap806-thermal";
+		reg = <0x80 0x10>;
+		#thermal-sensor-cells = <1>;
+	};
+};
Signature · 1 line
2.14.1
author maintainer
#26 lore raw

PATCH v2 16/23 dt-bindings: cp110: update documentation since DT de-duplication

In reply to Miquel Raynal

CP110 master/slave DT files have been merged in a DT de-duplication work merged in v4.16. Update the syscon documentation accordingly to match the current state of the DT nodes.

---
 .../bindings/arm/marvell/cp110-system-controller.txt           | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +5 -5
index 56e7fb1153e7..54b0d64ce819 100644
@@ -163,26 +163,26 @@ Required properties:
 
 Example:
 
-cpm_syscon0: system-controller at 440000 {
+CP110_LABEL(syscon0): system-controller at 440000 {
 	compatible = "syscon", "simple-mfd";
 	reg = <0x440000 0x1000>;
 
-	cpm_clk: clock {
+	CP110_LABEL(clk): clock {
 		compatible = "marvell,cp110-clock";
 		#clock-cells = <2>;
 	};
 
-	cpm_pinctrl: pinctrl {
+	CP110_LABEL(pinctrl): pinctrl {
 		compatible = "marvell,armada-8k-cpm-pinctrl";
 	};
 
-	cpm_gpio1: gpio at 100 {
+	CP110_LABEL(gpio1): gpio at 100 {
 		compatible = "marvell,armada-8k-gpio";
 		offset = <0x100>;
 		ngpios = <32>;
 		gpio-controller;
 		#gpio-cells = <2>;
-		gpio-ranges = <&cpm_pinctrl 0 0 32>;
+		gpio-ranges = <&CP110_LABEL(pinctrl) 0 0 32>;
 	};
 
 };
Signature · 1 line
2.14.1
author maintainer
#27 lore raw

PATCH v2 17/23 dt-bindings: cp110: add the thermal node in the syscon file

In reply to Miquel Raynal

Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node.

---
 .../arm/marvell/cp110-system-controller.txt        | 37 ++++++++++++++++++++++
 1 file changed, 37 insertions(+)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +37 -0
index 54b0d64ce819..cd4a7a57491e 100644
@@ -11,6 +11,9 @@ For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
  - reg: register area of the CP110 system controller
 
+SYSTEM CONTROLLER 0
+===================
+
 Clocks:
 -------
 
@@ -186,3 +189,37 @@ CP110_LABEL(syscon0): system-controller at 440000 {
 	};
 
 };
+
+SYSTEM CONTROLLER 1
+===================
+
+Thermal:
+--------
+
+The thermal IP can probe the temperature all around the processor. It
+may feature several channels, each of them wired to one sensor.
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/thermal/thermal.txt
+
+Required properties:
+- compatible: must be one of:
+  * marvell,armada-cp110-thermal
+- reg: register range associated with the thermal functions.
+
+Optional properties:
+- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer
+  to this IP and represents the channel ID. There is one sensor per
+  channel. O refers to the thermal IP internal channel.
+
+Example:
+CP110_LABEL(syscon1): system-controller at 6f8000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x6f8000 0x1000>;
+
+	CP110_LABEL(thermal): ap-thermal at 70 {
+		compatible = "marvell,armada-cp110-thermal";
+		reg = <0x70 0x10>;
+		#thermal-sensor-cells = <1>;
+	};
+};
Signature · 1 line
2.14.1
maintainer
#28 lore raw

PATCH v2 17/23 dt-bindings: cp110: add the thermal node in the syscon file

Quoted 45 lines · Miquel Raynal

Explain the thermal bindings now that the thermal IP is described being inside of a system controller. Add a reference to the thermal-zone node.

---
 .../arm/marvell/cp110-system-controller.txt        | 37 ++++++++++++++++++++++
 1 file changed, 37 insertions(+)
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +22 -0
index 54b0d64ce819..cd4a7a57491e 100644
@@ -11,6 +11,9 @@ For the top level node:
  - compatible: must be: "syscon", "simple-mfd";
  - reg: register area of the CP110 system controller
 
+SYSTEM CONTROLLER 0
+===================
+
 Clocks:
 -------
 
@@ -186,3 +189,37 @@ CP110_LABEL(syscon0): system-controller at 440000 {
 	};
 
 };
+
+SYSTEM CONTROLLER 1
+===================
+
+Thermal:
+--------
+
+The thermal IP can probe the temperature all around the processor. It
+may feature several channels, each of them wired to one sensor.
+
+For common binding part and usage, refer to
+Documentation/devicetree/bindings/thermal/thermal.txt
+
+Required properties:
+- compatible: must be one of:
+  * marvell,armada-cp110-thermal
+- reg: register range associated with the thermal functions.
+
+Optional properties:

Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt CP110_LABEL(syscon0): system-controller at 440000 { · line 220

Quoted 10 lines
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +10 -0
+- #thermal-sensor-cells: shall be <1> when thermal-zones subnodes refer
+  to this IP and represents the channel ID. There is one sensor per
+  channel. O refers to the thermal IP internal channel.
+
+Example:
+CP110_LABEL(syscon1): system-controller at 6f8000 {
+	compatible = "syscon", "simple-mfd";
+	reg = <0x6f8000 0x1000>;
+
+	CP110_LABEL(thermal): ap-thermal at 70 {

thermal-sensor at ...

With that,

Quoted 8 lines
Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt +5 -0
+		compatible = "marvell,armada-cp110-thermal";
+		reg = <0x70 0x10>;
+		#thermal-sensor-cells = <1>;
+	};
+};
Signature · 1 line
2.14.1
author maintainer
#29 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

In reply to Miquel Raynal

New bindings (with the syscon and the overheat interrupt) are available for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +5 -0
index e0d013a2e66d..f3b441100890 100644
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal
 
+Note: these bindings are deprecated for AP806/CP110 and should instead
+follow the rules described in:
+Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
+Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
+
 - reg: Device's register space.
   Two entries are expected, see the examples below. The first one points
   to the status register (4B). The second one points to the control
Signature · 1 line
2.14.1
maintainer
#30 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Quoted 1 line · Miquel Raynal

New bindings (with the syscon and the overheat interrupt) are available

What interrupt? It's not in your new binding.

Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Can't you make this a child of the syscon without breaking the binding?

Quoted 12 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +5 -0
+Note: these bindings are deprecated for AP806/CP110 and should instead
+follow the rules described in:
+Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
+Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
+
 - reg: Device's register space.
   Two entries are expected, see the examples below. The first one points
   to the status register (4B). The second one points to the control
Signature · 1 line
2.14.1
author maintainer
#31 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Hi Rob,

Rob Herring <[email protected]> wrote on Tue, 3 Jul 2018 15:30:11 -0600:

Quoted 24 lines · Miquel Raynal
Quoted 1 line

New bindings (with the syscon and the overheat interrupt) are available

What interrupt? It's not in your new binding.

Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal  

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Quoted 1 line

Can't you make this a child of the syscon without breaking the binding?

We are talking about only 1 driver here, so I'm not sure how I should understand your last sentence. Do you want me to add a second compatible (for the same piece of hardware) for thermal node declared as a child of the syscon?

I could handle this situation in the driver by creating the missing regmap in case we are using the old compatible. If this is the solution you prefer, how should I name the new compatibles ?

Quoted 13 lines
Quoted 13 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +5 -0
+Note: these bindings are deprecated for AP806/CP110 and should instead
+follow the rules described in:
+Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
+Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
+
 - reg: Device's register space.
   Two entries are expected, see the examples below. The first one points
   to the status register (4B). The second one points to the control
Signature · 1 line
2.14.1

Thanks,
Miqu?l

maintainer
#32 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Quoted 9 lines · Miquel Raynal

Hi Rob,

Rob Herring <[email protected]> wrote on Tue, 3 Jul 2018 15:30:11 -0600:

Quoted 4 lines · Miquel Raynal
Quoted 1 line

New bindings (with the syscon and the overheat interrupt) are available

What interrupt? It's not in your new binding.

???

Quoted 19 lines
Quoted 19 lines
Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Quoted 6 lines
Quoted 1 line

Can't you make this a child of the syscon without breaking the binding?

We are talking about only 1 driver here, so I'm not sure how I should understand your last sentence. Do you want me to add a second compatible (for the same piece of hardware) for thermal node declared as a child of the syscon?

I don't know what I'm suggesting. Your changes look like they break compatibility to me. What happens if you use this new binding without any kernel change?

Quoted 20 lines

I could handle this situation in the driver by creating the missing regmap in case we are using the old compatible. If this is the solution you prefer, how should I name the new compatibles ?

Quoted 13 lines
Quoted 11 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +5 -1
+Note: these bindings are deprecated for AP806/CP110 and should instead
+follow the rules described in:
+Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
+Documentation/devicetree/bindings/arm/marvell/cp110-system-controller.txt
+
 - reg: Device's register space.
   Two entries are expected, see the examples below. The first one points
   to the status register (4B). The second one points to the control
--
Quoted 2 lines

2.14.1

Thanks,
Miqu?l

author maintainer
#33 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Hi Rob,

Rob Herring <[email protected]> wrote on Thu, 5 Jul 2018 12:03:04 -0600:

Quoted 12 lines · Miquel Raynal
Quoted 9 lines

Hi Rob,

Rob Herring <[email protected]> wrote on Tue, 3 Jul 2018 15:30:11 -0600:

Quoted 4 lines · Miquel Raynal
Quoted 1 line

New bindings (with the syscon and the overheat interrupt) are available

What interrupt? It's not in your new binding.

???

I forgot that point, my bad.

Initially this series introduced an overheat interrupt. Due to some dependencies I split the original series in two: this one and another one just to add support for the interrupt.

This is a stale comment I forgot to remove (again in the v3), sorry.

I'll wait for Eduardo's feedback and repost eventually without the parenthesis.

Thanks,
Miqu?l

maintainer
#34 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Quoted 16 lines · Miquel Raynal

Hi Rob,

Rob Herring <[email protected]> wrote on Thu, 5 Jul 2018 12:03:04 -0600:

Quoted 11 lines · Miquel Raynal
Quoted 9 lines

Hi Rob,

Rob Herring <[email protected]> wrote on Tue, 3 Jul 2018 15:30:11 -0600:

Quoted 4 lines · Miquel Raynal
Quoted 1 line

New bindings (with the syscon and the overheat interrupt) are available

What interrupt? It's not in your new binding.

Quoted 7 lines
Quoted 1 line

???

I forgot that point, my bad.

Initially this series introduced an overheat interrupt. Due to some dependencies I split the original series in two: this one and another one just to add support for the interrupt.

You can split up the driver support, but please make the binding complete as possible.

Rob

author maintainer
#35 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

In reply to Rob Herring

Hi Rob,

[...]

Quoted 21 lines
Quoted 21 lines
Quoted 20 lines
Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal  

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Can't you make this a child of the syscon without breaking the binding?

Quoted 7 lines
Quoted 4 lines

We are talking about only 1 driver here, so I'm not sure how I should understand your last sentence. Do you want me to add a second compatible (for the same piece of hardware) for thermal node declared as a child of the syscon?

I don't know what I'm suggesting. Your changes look like they break compatibility to me.

There is code in the driver to handle the legacy non-syscon-ish thermal node ("armada_thermal_probe_legacy()"). An old DT with a new kernel would work fine.

Quoted 1 line

What happens if you use this new binding without any kernel change?

I suppose you mean "during the merge window"? In this case the driver of the thermal IP will not probe (and spawn an error in the dmesg) with ap806/cp110 IPs. As the support is pretty new for them, this is maybe not a huge issue. Also, before the DT changes adding thermal zones, just retrieving the temperature might be pretty useless. However, it is always possible to merge the driver changes in 4.19 and the DT changes in 4.20.

Thanks,
Miqu?l

maintainer
#36 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Quoted 31 lines · Miquel Raynal

Hi Rob,

[...]

Quoted 26 lines
Quoted 25 lines
Quoted 19 lines
Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Quoted 1 line

Can't you make this a child of the syscon without breaking the binding?

We are talking about only 1 driver here, so I'm not sure how I should understand your last sentence. Do you want me to add a second compatible (for the same piece of hardware) for thermal node declared as a child of the syscon?

Quoted 6 lines
Quoted 2 lines

I don't know what I'm suggesting. Your changes look like they break compatibility to me.

There is code in the driver to handle the legacy non-syscon-ish thermal node ("armada_thermal_probe_legacy()"). An old DT with a new kernel would work fine.

Okay, that's good.

Quoted 9 lines
Quoted 1 line

What happens if you use this new binding without any kernel change?

I suppose you mean "during the merge window"? In this case the driver of the thermal IP will not probe (and spawn an error in the dmesg) with ap806/cp110 IPs. As the support is pretty new for them, this is maybe not a huge issue. Also, before the DT changes adding thermal zones, just retrieving the temperature might be pretty useless. However, it is always possible to merge the driver changes in 4.19 and the DT changes in 4.20.

Not the merge window, but distros (SUSE at least) want to be able to boot with current DTs and their distro (old) kernel. Maybe for this platform you don't care.

Rob

author maintainer
#37 lore raw

PATCH v2 18/23 dt-bindings: thermal: armada: add reference to new bindings

Hi Rob,

Quoted 45 lines
Quoted 26 lines
Quoted 26 lines
Quoted 25 lines
Quoted 19 lines
Quoted 13 lines

for AP806 and CP110 compatibles. Add a reference to these files from the original documentation.

---
 Documentation/devicetree/bindings/thermal/armada-thermal.txt | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
index e0d013a2e66d..f3b441100890 100644

Documentation/devicetree/bindings/thermal/armada-thermal.txt Required properties: · line 11

Quoted 2 lines
Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 -0
@@ -10,6 +10,11 @@ Required properties:
     * marvell,armada-ap806-thermal
     * marvell,armada-cp110-thermal  

Really you should not be using the same compatible for both. Now you have 2 drivers matching to same compatibles.

Quoted 1 line

Can't you make this a child of the syscon without breaking the binding?

We are talking about only 1 driver here, so I'm not sure how I should understand your last sentence. Do you want me to add a second compatible (for the same piece of hardware) for thermal node declared as a child of the syscon?

Quoted 6 lines
Quoted 2 lines

I don't know what I'm suggesting. Your changes look like they break compatibility to me.

There is code in the driver to handle the legacy non-syscon-ish thermal node ("armada_thermal_probe_legacy()"). An old DT with a new kernel would work fine.

Okay, that's good.

Quoted 9 lines
Quoted 1 line

What happens if you use this new binding without any kernel change?

I suppose you mean "during the merge window"? In this case the driver of the thermal IP will not probe (and spawn an error in the dmesg) with ap806/cp110 IPs. As the support is pretty new for them, this is maybe not a huge issue. Also, before the DT changes adding thermal zones, just retrieving the temperature might be pretty useless. However, it is always possible to merge the driver changes in 4.19 and the DT changes in 4.20.

Quoted 3 lines

Not the merge window, but distros (SUSE at least) want to be able to boot with current DTs and their distro (old) kernel. Maybe for this platform you don't care.

Indeed, I think we don't care that much for this platform.

Let me resend the series with the 'interrupt' reference removed as I think it was the last thing to address.

Thanks,
Miqu?l

author maintainer
#38 lore raw

PATCH v2 19/23 arm64: dts: marvell: rename ap806 syscon node

In reply to Miquel Raynal

In CP files, the syscons are called CP110_LABEL(syscon<x>) in case of future additions. Use the same logic here to prepare the addition of a second syscon to access both the thermal IP, the DFX server registers and later probably other registers within this same memory area.

---
 .../devicetree/bindings/arm/marvell/ap806-system-controller.txt         | 2 +-
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi                           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +1 -1
index a265f1628f36..108e8da600e4 100644
@@ -79,7 +79,7 @@ Required properties:
 - offset: offset address inside the syscon block
 
 Example:
-ap_syscon: system-controller at 6f4000 {
+ap_syscon0: system-controller at 6f4000 {
 	compatible = "syscon", "simple-mfd";
 	reg = <0x6f4000 0x1000>;
 
arch/arm64/boot/dts/marvell/armada-ap806.dtsi +1 -1
index 4f2a704615b0..550f03b8c96f 100644
@@ -230,7 +230,7 @@
 				status = "disabled";
 			};
 
-			ap_syscon: system-controller at 6f4000 {
+			ap_syscon0: system-controller at 6f4000 {
 				compatible = "syscon", "simple-mfd";
 				reg = <0x6f4000 0x2000>;
 
Signature · 1 line
2.14.1
maintainer
#39 lore raw

PATCH v2 19/23 arm64: dts: marvell: rename ap806 syscon node

Quoted 4 lines · Miquel Raynal

In CP files, the syscons are called CP110_LABEL(syscon<x>) in case of future additions. Use the same logic here to prepare the addition of a second syscon to access both the thermal IP, the DFX server registers and later probably other registers within this same memory area.

You are renaming labels, not nodes.

The example is just an example. Drop that change as it is not necessary.

Quoted 36 lines
---
 .../devicetree/bindings/arm/marvell/ap806-system-controller.txt         | 2 +-
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi                           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +1 -1
index a265f1628f36..108e8da600e4 100644
@@ -79,7 +79,7 @@ Required properties:
 - offset: offset address inside the syscon block
 
 Example:
-ap_syscon: system-controller at 6f4000 {
+ap_syscon0: system-controller at 6f4000 {
 	compatible = "syscon", "simple-mfd";
 	reg = <0x6f4000 0x1000>;
 
arch/arm64/boot/dts/marvell/armada-ap806.dtsi +1 -1
index 4f2a704615b0..550f03b8c96f 100644
@@ -230,7 +230,7 @@
 				status = "disabled";
 			};
 
-			ap_syscon: system-controller at 6f4000 {
+			ap_syscon0: system-controller at 6f4000 {
 				compatible = "syscon", "simple-mfd";
 				reg = <0x6f4000 0x2000>;
 
Signature · 1 line
2.14.1
author maintainer
#40 lore raw

PATCH v2 20/23 arm64: dts: marvell: move AP806/CP110 thermal nodes into a new syscon

In reply to Miquel Raynal

New bindings impose to declare the thermal IP from within a new syscon.

---
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 14 ++++++++++----
 arch/arm64/boot/dts/marvell/armada-cp110.dtsi | 18 ++++++++++++------
 2 files changed, 22 insertions(+), 10 deletions(-)
arch/arm64/boot/dts/marvell/armada-ap806.dtsi +10 -4
index 550f03b8c96f..3c6896fb96e6 100644
@@ -258,10 +258,16 @@
 				};
 			};
 
-			ap_thermal: thermal at 6f808c {
-				compatible = "marvell,armada-ap806-thermal";
-				reg = <0x6f808c 0x4>,
-				      <0x6f8084 0x8>;
+			ap_syscon1: system-controller at 6f8000 {
+				compatible = "syscon", "simple-mfd";
+				reg = <0x6f8000 0x1000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				ap_thermal: ap-thermal at 80 {
+					compatible = "marvell,armada-ap806-thermal";
+					reg = <0x80 0x10>;
+				};
 			};
 		};
 	};
arch/arm64/boot/dts/marvell/armada-cp110.dtsi +12 -6
index ab31ba20aa2a..65039292b398 100644
@@ -177,12 +177,6 @@
 			interrupts = <77 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
-		CP110_LABEL(thermal): thermal at 400078 {
-			compatible = "marvell,armada-cp110-thermal";
-			reg = <0x400078 0x4>,
-			<0x400070 0x8>;
-		};
-
 		CP110_LABEL(syscon0): system-controller at 440000 {
 			compatible = "syscon", "simple-mfd";
 			reg = <0x440000 0x2000>;
@@ -223,6 +217,18 @@
 			};
 		};
 
+		CP110_LABEL(syscon1): system-controller at 400000 {
+			compatible = "syscon", "simple-mfd";
+			reg = <0x400000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			CP110_LABEL(thermal): thermal at 70 {
+				compatible = "marvell,armada-cp110-thermal";
+				reg = <0x70 0x10>;
+			};
+		};
+
 		CP110_LABEL(usb3_0): usb3 at 500000 {
 			compatible = "marvell,armada-8k-xhci",
 			"generic-xhci";
Signature · 1 line
2.14.1
author maintainer
#41 lore raw

PATCH v2 21/23 arm64: dts: marvell: add thermal-zone node in ap806 DTSI file

In reply to Miquel Raynal

Add a thermal-zone node and fill in all the sensors available in an ap806 (one in the IC plus one per CPU).

---
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 60 +++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
arch/arm64/boot/dts/marvell/armada-ap806.dtsi +60 -0
index 3c6896fb96e6..575171f89dd5 100644
@@ -6,6 +6,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
 
 /dts-v1/;
 
@@ -267,8 +268,67 @@
 				ap_thermal: ap-thermal at 80 {
 					compatible = "marvell,armada-ap806-thermal";
 					reg = <0x80 0x10>;
+					#thermal-sensor-cells = <1>;
 				};
 			};
 		};
 	};
+
+	/*
+	 * The thermal IP features one internal sensor plus, if applicable, one
+	 * remote channel wired to one sensor per CPU.
+	 *
+	 * The cooling maps are always empty as there are no cooling devices.
+	 */
+	thermal-zones {
+		ap_thermal_ic: ap-thermal-ic {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&ap_thermal 0>;
+
+			trips {	};
+			cooling-maps { };
+		};
+
+		ap_thermal_cpu1: ap-thermal-cpu1 {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&ap_thermal 1>;
+
+			trips { };
+			cooling-maps { };
+		};
+
+		ap_thermal_cpu2: ap-thermal-cpu2 {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&ap_thermal 2>;
+
+			trips { };
+			cooling-maps { };
+		};
+
+		ap_thermal_cpu3: ap-thermal-cpu3 {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&ap_thermal 3>;
+
+			trips { };
+			cooling-maps { };
+		};
+
+		ap_thermal_cpu4: ap-thermal-cpu4 {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&ap_thermal 4>;
+
+			trips { };
+			cooling-maps { };
+		};
+	};
 };
Signature · 1 line
2.14.1
author maintainer
#42 lore raw

PATCH v2 22/23 arm64: dts: marvell: add macro to make distinction between node names

In reply to Miquel Raynal

Because the label is different between CPs, the full path of a node is unique. However, when referring to the end of the path only (the node name), this name is not unique anymore.

The *thermal_zone_of_sensor_register() functions of the thermal core present this limitation and prevent having a thermal-zone per CP.

Add a macro to make the distinction between node names to solve this situation.

---
 arch/arm64/boot/dts/marvell/armada-common.dtsi | 1 +
 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/marvell/armada-common.dtsi +1 -0
index d5e8aedec188..b29c6405d214 100644
@@ -7,4 +7,5 @@
 #define PASTER(x, y) x ## y
 #define EVALUATOR(x, y) PASTER(x, y)
 #define CP110_LABEL(name) EVALUATOR(CP110_NAME, EVALUATOR(_, name))
+#define CP110_NODE_NAME(name) EVALUATOR(CP110_NAME, EVALUATOR(-, name))
 #define ADDRESSIFY(addr) EVALUATOR(0x, addr)
Signature · 1 line
2.14.1
author maintainer
#43 lore raw

PATCH v2 23/23 arm64: dts: marvell: add thermal-zone node in cp110 DTSI file

In reply to Miquel Raynal

Add a thermal-zone node and fill in all the sensors available in a cp110 (only one in the thermal IP).

---
 arch/arm64/boot/dts/marvell/armada-cp110.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
arch/arm64/boot/dts/marvell/armada-cp110.dtsi +19 -0
index 65039292b398..6d42efebba0d 100644
@@ -6,6 +6,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/mvebu-icu.h>
+#include <dt-bindings/thermal/thermal.h>
 
 #include "armada-common.dtsi"
 
@@ -19,6 +20,23 @@
 	 * save one indentation level
 	 */
 	CP110_NAME: CP110_NAME { };
+
+	/*
+	 * CPs only have one sensor in the thermal IC.
+	 *
+	 * The cooling maps are empty as there are no cooling devices.
+	 */
+	thermal-zones {
+		CP110_LABEL(thermal_ic): CP110_NODE_NAME(thermal-ic) {
+			polling-delay-passive = <1000>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&CP110_LABEL(thermal) 0>;
+
+			trips {	};
+			cooling-maps { };
+		};
+	};
 };
 
 &CP110_NAME {
@@ -226,6 +244,7 @@
 			CP110_LABEL(thermal): thermal at 70 {
 				compatible = "marvell,armada-cp110-thermal";
 				reg = <0x70 0x10>;
+				#thermal-sensor-cells = <1>;
 			};
 		};
 
Signature · 1 line
2.14.1