Message ID | 20210811114853.159298-4-nuno.sa@analog.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | AXI FAN new features and improvements | expand |
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); > }
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); }
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(-)