linux-hwmon.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] AXI FAN new features and improvements
@ 2021-08-11 11:48 Nuno Sá
  2021-08-11 11:48 ` [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled Nuno Sá
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Nuno Sá @ 2021-08-11 11:48 UTC (permalink / raw)
  To: linux-hwmon; +Cc: Guenter Roeck, Jean Delvare

This is the result of the RFC [1] previously sent. The main differences
from the RFC are:

* Dropped the tacho evaluation stuff as that will be done differently
(the core will just expose a minimum fan speed below which faults are
asserted).
* Converted half of the auto points to hysteresis points as suggested by
Guenter.

[1]: https://www.spinics.net/lists/linux-hwmon/msg12015.html

Nuno Sá (3):
  hwmon: axi-fan-control: make sure the clock is enabled
  hwmon: axi-fan-control: handle irqs in natural order
  hwmon: axi-fan-control: support temperature vs pwm points

 drivers/hwmon/axi-fan-control.c | 117 +++++++++++++++++++++++++++-----
 1 file changed, 101 insertions(+), 16 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled
  2021-08-11 11:48 [PATCH 0/3] AXI FAN new features and improvements Nuno Sá
@ 2021-08-11 11:48 ` Nuno Sá
  2021-08-12  4:37   ` Guenter Roeck
  2021-08-11 11:48 ` [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order Nuno Sá
  2021-08-11 11:48 ` [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points Nuno Sá
  2 siblings, 1 reply; 7+ messages in thread
From: Nuno Sá @ 2021-08-11 11:48 UTC (permalink / raw)
  To: linux-hwmon; +Cc: Guenter Roeck, Jean Delvare

The core will only work if it's clock is enabled. This patch is a
minor enhancement to make sure that's the case.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/hwmon/axi-fan-control.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
index e3f6b03e6764..901d1588234d 100644
--- a/drivers/hwmon/axi-fan-control.c
+++ b/drivers/hwmon/axi-fan-control.c
@@ -351,6 +351,11 @@ static int axi_fan_control_init(struct axi_fan_control_data *ctl,
 	return ret;
 }
 
+static void axi_fan_control_clk_disable(void *clk)
+{
+	clk_disable_unprepare(clk);
+}
+
 static const struct hwmon_channel_info *axi_fan_control_info[] = {
 	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT),
 	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_LABEL),
@@ -406,6 +411,14 @@ static int axi_fan_control_probe(struct platform_device *pdev)
 		return PTR_ERR(clk);
 	}
 
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return ret;
+
+	ret = devm_add_action_or_reset(&pdev->dev, axi_fan_control_clk_disable, clk);
+	if (ret)
+		return ret;
+
 	ctl->clk_rate = clk_get_rate(clk);
 	if (!ctl->clk_rate)
 		return -EINVAL;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order
  2021-08-11 11:48 [PATCH 0/3] AXI FAN new features and improvements Nuno Sá
  2021-08-11 11:48 ` [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled Nuno Sá
@ 2021-08-11 11:48 ` Nuno Sá
  2021-08-12  4:38   ` Guenter Roeck
  2021-08-11 11:48 ` [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points Nuno Sá
  2 siblings, 1 reply; 7+ messages in thread
From: Nuno Sá @ 2021-08-11 11:48 UTC (permalink / raw)
  To: linux-hwmon; +Cc: Guenter Roeck, Jean Delvare

The core will now start out of reset at boot as soon as clocking is
available. Hence, by the time we unmask the interrupts we already might
have some of them set. Thus, it's important to handle them in the
natural order the core generates them. Otherwise, we could process
'ADI_IRQ_SRC_PWM_CHANGED' before 'ADI_IRQ_SRC_TEMP_INCREASE' and
erroneously set 'update_tacho_params' to true.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/hwmon/axi-fan-control.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
index 901d1588234d..c898ad121dc7 100644
--- a/drivers/hwmon/axi-fan-control.c
+++ b/drivers/hwmon/axi-fan-control.c
@@ -283,18 +283,9 @@ static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
 	u32 irq_pending = axi_ioread(ADI_REG_IRQ_PENDING, ctl);
 	u32 clear_mask;
 
-	if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) {
-		if (ctl->update_tacho_params) {
-			u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
-
-			/* get 25% tolerance */
-			u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100);
-			/* set new tacho parameters */
-			axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl);
-			axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl);
-			ctl->update_tacho_params = false;
-		}
-	}
+	if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE)
+		/* hardware requested a new pwm */
+		ctl->hw_pwm_req = true;
 
 	if (irq_pending & ADI_IRQ_SRC_PWM_CHANGED) {
 		/*
@@ -310,9 +301,18 @@ static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
 		}
 	}
 
-	if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE)
-		/* hardware requested a new pwm */
-		ctl->hw_pwm_req = true;
+	if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) {
+		if (ctl->update_tacho_params) {
+			u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
+			/* get 25% tolerance */
+			u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100);
+
+			/* set new tacho parameters */
+			axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl);
+			axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl);
+			ctl->update_tacho_params = false;
+		}
+	}
 
 	if (irq_pending & ADI_IRQ_SRC_TACH_ERR)
 		ctl->fan_fault = 1;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points
  2021-08-11 11:48 [PATCH 0/3] AXI FAN new features and improvements Nuno Sá
  2021-08-11 11:48 ` [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled Nuno Sá
  2021-08-11 11:48 ` [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order Nuno Sá
@ 2021-08-11 11:48 ` Nuno Sá
  2021-08-12  4:39   ` Guenter Roeck
  2 siblings, 1 reply; 7+ messages in thread
From: Nuno Sá @ 2021-08-11 11:48 UTC (permalink / raw)
  To: linux-hwmon; +Cc: Guenter Roeck, Jean Delvare

The HW has some predefined points where it will associate a PWM value.
However some users might want to better set these points to their
usecases. This patch exposes these points as pwm auto_points:

 * pwm1_auto_point1_temp_hyst: temperature threshold below which PWM should
   be 0%;
 * pwm1_auto_point1_temp: temperature threshold above which PWM should be
   25%;
 * pwm1_auto_point2_temp_hyst: temperature threshold below which PWM should
   be 25%;
 * pwm1_auto_point2_temp: temperature threshold above which PWM should be
   50%;
 * pwm1_auto_point3_temp_hyst: temperature threshold below which PWM should
   be 50%;
 * pwm1_auto_point3_temp: temperature threshold above which PWM should be
   75%;
 * pwm1_auto_point4_temp_hyst: temperature threshold below which PWM should
   be 75%;
 * pwm1_auto_point4_temp: temperature threshold above which PWM should be
   100%;

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/hwmon/axi-fan-control.c | 74 ++++++++++++++++++++++++++++++++-
 1 file changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
index c898ad121dc7..d2092c17d993 100644
--- a/drivers/hwmon/axi-fan-control.c
+++ b/drivers/hwmon/axi-fan-control.c
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/fpga/adi-axi-common.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -23,6 +24,14 @@
 #define ADI_REG_PWM_PERIOD	0x00c0
 #define ADI_REG_TACH_MEASUR	0x00c4
 #define ADI_REG_TEMPERATURE	0x00c8
+#define ADI_REG_TEMP_00_H	0x0100
+#define ADI_REG_TEMP_25_L	0x0104
+#define ADI_REG_TEMP_25_H	0x0108
+#define ADI_REG_TEMP_50_L	0x010c
+#define ADI_REG_TEMP_50_H	0x0110
+#define ADI_REG_TEMP_75_L	0x0114
+#define ADI_REG_TEMP_75_H	0x0118
+#define ADI_REG_TEMP_100_L	0x011c
 
 #define ADI_REG_IRQ_MASK	0x0040
 #define ADI_REG_IRQ_PENDING	0x0044
@@ -62,6 +71,39 @@ static inline u32 axi_ioread(const u32 reg,
 	return ioread32(ctl->base + reg);
 }
 
+/*
+ * The core calculates the temperature as:
+ *	T = /raw * 509.3140064 / 65535) - 280.2308787
+ */
+static ssize_t axi_fan_control_show(struct device *dev, struct device_attribute *da, char *buf)
+{
+	struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	u32 temp = axi_ioread(attr->index, ctl);
+
+	temp = DIV_ROUND_CLOSEST_ULL(temp * 509314ULL, 65535) - 280230;
+
+	return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t axi_fan_control_store(struct device *dev, struct device_attribute *da,
+				     const char *buf, size_t count)
+{
+	struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	u32 temp;
+	int ret;
+
+	ret = kstrtou32(buf, 10, &temp);
+	if (ret)
+		return ret;
+
+	temp = DIV_ROUND_CLOSEST_ULL((temp + 280230) * 65535ULL, 509314);
+	axi_iowrite(temp, attr->index, ctl);
+
+	return count;
+}
+
 static long axi_fan_control_get_pwm_duty(const struct axi_fan_control_data *ctl)
 {
 	u32 pwm_width = axi_ioread(ADI_REG_PWM_WIDTH, ctl);
@@ -375,6 +417,36 @@ static const struct hwmon_chip_info axi_chip_info = {
 	.info = axi_fan_control_info,
 };
 
+/* temperature threshold below which PWM should be 0% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp_hyst, axi_fan_control, ADI_REG_TEMP_00_H);
+/* temperature threshold above which PWM should be 25% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, axi_fan_control, ADI_REG_TEMP_25_L);
+/* temperature threshold below which PWM should be 25% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp_hyst, axi_fan_control, ADI_REG_TEMP_25_H);
+/* temperature threshold above which PWM should be 50% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, axi_fan_control, ADI_REG_TEMP_50_L);
+/* temperature threshold below which PWM should be 50% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp_hyst, axi_fan_control, ADI_REG_TEMP_50_H);
+/* temperature threshold above which PWM should be 75% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, axi_fan_control, ADI_REG_TEMP_75_L);
+/* temperature threshold below which PWM should be 75% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp_hyst, axi_fan_control, ADI_REG_TEMP_75_H);
+/* temperature threshold above which PWM should be 100% */
+static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, axi_fan_control, ADI_REG_TEMP_100_L);
+
+static struct attribute *axi_fan_control_attrs[] = {
+	&sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(axi_fan_control);
+
 static const u32 version_1_0_0 = ADI_AXI_PCORE_VER(1, 0, 'a');
 
 static const struct of_device_id axi_fan_control_of_match[] = {
@@ -459,7 +531,7 @@ static int axi_fan_control_probe(struct platform_device *pdev)
 							 name,
 							 ctl,
 							 &axi_chip_info,
-							 NULL);
+							 axi_fan_control_groups);
 
 	return PTR_ERR_OR_ZERO(ctl->hdev);
 }
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled
  2021-08-11 11:48 ` [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled Nuno Sá
@ 2021-08-12  4:37   ` Guenter Roeck
  0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2021-08-12  4:37 UTC (permalink / raw)
  To: Nuno Sá; +Cc: linux-hwmon, Jean Delvare

On Wed, Aug 11, 2021 at 01:48:51PM +0200, Nuno Sá wrote:
> The core will only work if it's clock is enabled. This patch is a
> minor enhancement to make sure that's the case.
> 
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>

Applied.

Thanks,
Guenter

> ---
>  drivers/hwmon/axi-fan-control.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
> index e3f6b03e6764..901d1588234d 100644
> --- a/drivers/hwmon/axi-fan-control.c
> +++ b/drivers/hwmon/axi-fan-control.c
> @@ -351,6 +351,11 @@ static int axi_fan_control_init(struct axi_fan_control_data *ctl,
>  	return ret;
>  }
>  
> +static void axi_fan_control_clk_disable(void *clk)
> +{
> +	clk_disable_unprepare(clk);
> +}
> +
>  static const struct hwmon_channel_info *axi_fan_control_info[] = {
>  	HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT),
>  	HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_LABEL),
> @@ -406,6 +411,14 @@ static int axi_fan_control_probe(struct platform_device *pdev)
>  		return PTR_ERR(clk);
>  	}
>  
> +	ret = clk_prepare_enable(clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = devm_add_action_or_reset(&pdev->dev, axi_fan_control_clk_disable, clk);
> +	if (ret)
> +		return ret;
> +
>  	ctl->clk_rate = clk_get_rate(clk);
>  	if (!ctl->clk_rate)
>  		return -EINVAL;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order
  2021-08-11 11:48 ` [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order Nuno Sá
@ 2021-08-12  4:38   ` Guenter Roeck
  0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2021-08-12  4:38 UTC (permalink / raw)
  To: Nuno Sá; +Cc: linux-hwmon, Jean Delvare

On Wed, Aug 11, 2021 at 01:48:52PM +0200, Nuno Sá wrote:
> The core will now start out of reset at boot as soon as clocking is
> available. Hence, by the time we unmask the interrupts we already might
> have some of them set. Thus, it's important to handle them in the
> natural order the core generates them. Otherwise, we could process
> 'ADI_IRQ_SRC_PWM_CHANGED' before 'ADI_IRQ_SRC_TEMP_INCREASE' and
> erroneously set 'update_tacho_params' to true.
> 
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>

Applied.

Thanks,
Guenter

> ---
>  drivers/hwmon/axi-fan-control.c | 30 +++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
> index 901d1588234d..c898ad121dc7 100644
> --- a/drivers/hwmon/axi-fan-control.c
> +++ b/drivers/hwmon/axi-fan-control.c
> @@ -283,18 +283,9 @@ static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
>  	u32 irq_pending = axi_ioread(ADI_REG_IRQ_PENDING, ctl);
>  	u32 clear_mask;
>  
> -	if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) {
> -		if (ctl->update_tacho_params) {
> -			u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
> -
> -			/* get 25% tolerance */
> -			u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100);
> -			/* set new tacho parameters */
> -			axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl);
> -			axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl);
> -			ctl->update_tacho_params = false;
> -		}
> -	}
> +	if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE)
> +		/* hardware requested a new pwm */
> +		ctl->hw_pwm_req = true;
>  
>  	if (irq_pending & ADI_IRQ_SRC_PWM_CHANGED) {
>  		/*
> @@ -310,9 +301,18 @@ static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
>  		}
>  	}
>  
> -	if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE)
> -		/* hardware requested a new pwm */
> -		ctl->hw_pwm_req = true;
> +	if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) {
> +		if (ctl->update_tacho_params) {
> +			u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
> +			/* get 25% tolerance */
> +			u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100);
> +
> +			/* set new tacho parameters */
> +			axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl);
> +			axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl);
> +			ctl->update_tacho_params = false;
> +		}
> +	}
>  
>  	if (irq_pending & ADI_IRQ_SRC_TACH_ERR)
>  		ctl->fan_fault = 1;

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points
  2021-08-11 11:48 ` [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points Nuno Sá
@ 2021-08-12  4:39   ` Guenter Roeck
  0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2021-08-12  4:39 UTC (permalink / raw)
  To: Nuno Sá; +Cc: linux-hwmon, Jean Delvare

On Wed, Aug 11, 2021 at 01:48:53PM +0200, Nuno Sá wrote:
> The HW has some predefined points where it will associate a PWM value.
> However some users might want to better set these points to their
> usecases. This patch exposes these points as pwm auto_points:
> 
>  * pwm1_auto_point1_temp_hyst: temperature threshold below which PWM should
>    be 0%;
>  * pwm1_auto_point1_temp: temperature threshold above which PWM should be
>    25%;
>  * pwm1_auto_point2_temp_hyst: temperature threshold below which PWM should
>    be 25%;
>  * pwm1_auto_point2_temp: temperature threshold above which PWM should be
>    50%;
>  * pwm1_auto_point3_temp_hyst: temperature threshold below which PWM should
>    be 50%;
>  * pwm1_auto_point3_temp: temperature threshold above which PWM should be
>    75%;
>  * pwm1_auto_point4_temp_hyst: temperature threshold below which PWM should
>    be 75%;
>  * pwm1_auto_point4_temp: temperature threshold above which PWM should be
>    100%;
> 
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>

Applied.

Thanks,
Guenter

> ---
>  drivers/hwmon/axi-fan-control.c | 74 ++++++++++++++++++++++++++++++++-
>  1 file changed, 73 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
> index c898ad121dc7..d2092c17d993 100644
> --- a/drivers/hwmon/axi-fan-control.c
> +++ b/drivers/hwmon/axi-fan-control.c
> @@ -8,6 +8,7 @@
>  #include <linux/clk.h>
>  #include <linux/fpga/adi-axi-common.h>
>  #include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
> @@ -23,6 +24,14 @@
>  #define ADI_REG_PWM_PERIOD	0x00c0
>  #define ADI_REG_TACH_MEASUR	0x00c4
>  #define ADI_REG_TEMPERATURE	0x00c8
> +#define ADI_REG_TEMP_00_H	0x0100
> +#define ADI_REG_TEMP_25_L	0x0104
> +#define ADI_REG_TEMP_25_H	0x0108
> +#define ADI_REG_TEMP_50_L	0x010c
> +#define ADI_REG_TEMP_50_H	0x0110
> +#define ADI_REG_TEMP_75_L	0x0114
> +#define ADI_REG_TEMP_75_H	0x0118
> +#define ADI_REG_TEMP_100_L	0x011c
>  
>  #define ADI_REG_IRQ_MASK	0x0040
>  #define ADI_REG_IRQ_PENDING	0x0044
> @@ -62,6 +71,39 @@ static inline u32 axi_ioread(const u32 reg,
>  	return ioread32(ctl->base + reg);
>  }
>  
> +/*
> + * The core calculates the temperature as:
> + *	T = /raw * 509.3140064 / 65535) - 280.2308787
> + */
> +static ssize_t axi_fan_control_show(struct device *dev, struct device_attribute *da, char *buf)
> +{
> +	struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
> +	u32 temp = axi_ioread(attr->index, ctl);
> +
> +	temp = DIV_ROUND_CLOSEST_ULL(temp * 509314ULL, 65535) - 280230;
> +
> +	return sprintf(buf, "%u\n", temp);
> +}
> +
> +static ssize_t axi_fan_control_store(struct device *dev, struct device_attribute *da,
> +				     const char *buf, size_t count)
> +{
> +	struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
> +	u32 temp;
> +	int ret;
> +
> +	ret = kstrtou32(buf, 10, &temp);
> +	if (ret)
> +		return ret;
> +
> +	temp = DIV_ROUND_CLOSEST_ULL((temp + 280230) * 65535ULL, 509314);
> +	axi_iowrite(temp, attr->index, ctl);
> +
> +	return count;
> +}
> +
>  static long axi_fan_control_get_pwm_duty(const struct axi_fan_control_data *ctl)
>  {
>  	u32 pwm_width = axi_ioread(ADI_REG_PWM_WIDTH, ctl);
> @@ -375,6 +417,36 @@ static const struct hwmon_chip_info axi_chip_info = {
>  	.info = axi_fan_control_info,
>  };
>  
> +/* temperature threshold below which PWM should be 0% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp_hyst, axi_fan_control, ADI_REG_TEMP_00_H);
> +/* temperature threshold above which PWM should be 25% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, axi_fan_control, ADI_REG_TEMP_25_L);
> +/* temperature threshold below which PWM should be 25% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp_hyst, axi_fan_control, ADI_REG_TEMP_25_H);
> +/* temperature threshold above which PWM should be 50% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, axi_fan_control, ADI_REG_TEMP_50_L);
> +/* temperature threshold below which PWM should be 50% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp_hyst, axi_fan_control, ADI_REG_TEMP_50_H);
> +/* temperature threshold above which PWM should be 75% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, axi_fan_control, ADI_REG_TEMP_75_L);
> +/* temperature threshold below which PWM should be 75% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp_hyst, axi_fan_control, ADI_REG_TEMP_75_H);
> +/* temperature threshold above which PWM should be 100% */
> +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, axi_fan_control, ADI_REG_TEMP_100_L);
> +
> +static struct attribute *axi_fan_control_attrs[] = {
> +	&sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
> +	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
> +	NULL,
> +};
> +ATTRIBUTE_GROUPS(axi_fan_control);
> +
>  static const u32 version_1_0_0 = ADI_AXI_PCORE_VER(1, 0, 'a');
>  
>  static const struct of_device_id axi_fan_control_of_match[] = {
> @@ -459,7 +531,7 @@ static int axi_fan_control_probe(struct platform_device *pdev)
>  							 name,
>  							 ctl,
>  							 &axi_chip_info,
> -							 NULL);
> +							 axi_fan_control_groups);
>  
>  	return PTR_ERR_OR_ZERO(ctl->hdev);
>  }

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-08-12  4:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-11 11:48 [PATCH 0/3] AXI FAN new features and improvements Nuno Sá
2021-08-11 11:48 ` [PATCH 1/3] hwmon: axi-fan-control: make sure the clock is enabled Nuno Sá
2021-08-12  4:37   ` Guenter Roeck
2021-08-11 11:48 ` [PATCH 2/3] hwmon: axi-fan-control: handle irqs in natural order Nuno Sá
2021-08-12  4:38   ` Guenter Roeck
2021-08-11 11:48 ` [PATCH 3/3] hwmon: axi-fan-control: support temperature vs pwm points Nuno Sá
2021-08-12  4:39   ` Guenter Roeck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).