* [PATCH 1/2] hwmon: (max6650) Allow fan shutdown and initial rpm target
[not found] ` <5f14ba10-60dd-0e0a-dcd0-f8bbbed33510@roeck-us.net>
@ 2016-08-24 8:13 ` Mike Looijmans
[not found] ` <1472026407-3448-1-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Mike Looijmans @ 2016-08-24 8:13 UTC (permalink / raw)
To: linux-hwmon, devicetree; +Cc: linux, linux-kernel, Mike Looijmans
The fan can be stopped by writing "3" to pwm1_enable in sysfs.
Add devicetree property for early initialization of the fan controller
to prevent overheating, for example when resetting the board while the
fan was completely turned off.
Also improve error reporting, I2C failures were ignored while writing
new values.
Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
---
Documentation/hwmon/max6650 | 1 +
drivers/hwmon/max6650.c | 108 +++++++++++++++++++++++++++-----------------
2 files changed, 68 insertions(+), 41 deletions(-)
diff --git a/Documentation/hwmon/max6650 b/Documentation/hwmon/max6650
index 58d9644..dff1d29 100644
--- a/Documentation/hwmon/max6650
+++ b/Documentation/hwmon/max6650
@@ -34,6 +34,7 @@ fan3_input ro "
fan4_input ro "
fan1_target rw desired fan speed in RPM (closed loop mode only)
pwm1_enable rw regulator mode, 0=full on, 1=open loop, 2=closed loop
+ 3=off
pwm1 rw relative speed (0-255), 255=max. speed.
Used in open loop mode only.
fan1_div rw sets the speed range the inputs can handle. Legal
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index c87517a..a993b44 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -185,6 +185,30 @@ static struct max6650_data *max6650_update_device(struct device *dev)
return data;
}
+/*
+ * Change the operating mode of the chip (if needed).
+ * mode is one of the MAX6650_CFG_MODE_* values.
+ */
+static int max6650_set_operating_mode(struct max6650_data *data, u8 mode)
+{
+ int result;
+ u8 config = data->config;
+
+ if (mode == (config & MAX6650_CFG_MODE_MASK))
+ return 0;
+
+ config = (config & ~MAX6650_CFG_MODE_MASK) | mode;
+
+ result = i2c_smbus_write_byte_data(data->client, MAX6650_REG_CONFIG,
+ config);
+ if (result < 0)
+ return result;
+
+ data->config = config;
+
+ return 0;
+}
+
static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
char *buf)
{
@@ -266,18 +290,12 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", rpm);
}
-static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static int max6650_set_target(struct max6650_data *data, unsigned long rpm)
{
- struct max6650_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
int kscale, ktach;
- unsigned long rpm;
- int err;
- err = kstrtoul(buf, 10, &rpm);
- if (err)
- return err;
+ if (rpm == 0)
+ return max6650_set_operating_mode(data, MAX6650_CFG_MODE_OFF);
rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
@@ -288,8 +306,6 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
* KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1
*/
- mutex_lock(&data->update_lock);
-
kscale = DIV_FROM_REG(data->config);
ktach = ((clock * kscale) / (256 * rpm / 60)) - 1;
if (ktach < 0)
@@ -298,10 +314,30 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
ktach = 255;
data->speed = ktach;
- i2c_smbus_write_byte_data(client, MAX6650_REG_SPEED, data->speed);
+ return i2c_smbus_write_byte_data(data->client, MAX6650_REG_SPEED,
+ data->speed);
+}
+
+static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct max6650_data *data = dev_get_drvdata(dev);
+ unsigned long rpm;
+ int err;
+
+ err = kstrtoul(buf, 10, &rpm);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+
+ err = max6650_set_target(data, rpm);
mutex_unlock(&data->update_lock);
+ if (err < 0)
+ return err;
+
return count;
}
@@ -355,12 +391,11 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
data->dac = 180 - (180 * pwm)/255;
else
data->dac = 76 - (76 * pwm)/255;
-
- i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac);
+ err = i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac);
mutex_unlock(&data->update_lock);
- return count;
+ return err < 0 ? err : count;
}
/*
@@ -369,14 +404,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
* 0 = Fan always on
* 1 = Open loop, Voltage is set according to speed, not regulated.
* 2 = Closed loop, RPM for all fans regulated by fan1 tachometer
+ * 3 = Fan off
*/
-
static ssize_t get_enable(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct max6650_data *data = max6650_update_device(dev);
int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4;
- int sysfs_modes[4] = {0, 1, 2, 1};
+ int sysfs_modes[4] = {0, 3, 2, 1};
return sprintf(buf, "%d\n", sysfs_modes[mode]);
}
@@ -385,25 +420,25 @@ static ssize_t set_enable(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct max6650_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- int max6650_modes[3] = {0, 3, 2};
unsigned long mode;
int err;
+ const u8 max6650_modes[] = {
+ MAX6650_CFG_MODE_ON,
+ MAX6650_CFG_MODE_OPEN_LOOP,
+ MAX6650_CFG_MODE_CLOSED_LOOP,
+ MAX6650_CFG_MODE_OFF,
+ };
err = kstrtoul(buf, 10, &mode);
if (err)
return err;
- if (mode > 2)
+ if (mode >= ARRAY_SIZE(max6650_modes))
return -EINVAL;
mutex_lock(&data->update_lock);
- data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG);
- data->config = (data->config & ~MAX6650_CFG_MODE_MASK)
- | (max6650_modes[mode] << 4);
-
- i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, data->config);
+ max6650_set_operating_mode(data, max6650_modes[mode]);
mutex_unlock(&data->update_lock);
@@ -582,6 +617,7 @@ static int max6650_init_client(struct max6650_data *data,
int err = -EIO;
u32 voltage;
u32 prescale;
+ u32 target_rpm;
if (of_property_read_u32(dev->of_node, "maxim,fan-microvolt",
&voltage))
@@ -642,22 +678,6 @@ static int max6650_init_client(struct max6650_data *data,
(config & MAX6650_CFG_V12) ? 12 : 5,
1 << (config & MAX6650_CFG_PRESCALER_MASK));
- /*
- * If mode is set to "full off", we change it to "open loop" and
- * set DAC to 255, which has the same effect. We do this because
- * there's no "full off" mode defined in hwmon specifications.
- */
-
- if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
- dev_dbg(dev, "Change mode to open loop, full off.\n");
- config = (config & ~MAX6650_CFG_MODE_MASK)
- | MAX6650_CFG_MODE_OPEN_LOOP;
- if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) {
- dev_err(dev, "DAC write error, aborting.\n");
- return err;
- }
- }
-
if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) {
dev_err(dev, "Config write error, aborting.\n");
return err;
@@ -666,6 +686,12 @@ static int max6650_init_client(struct max6650_data *data,
data->config = config;
data->count = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT);
+ if (!of_property_read_u32(client->dev.of_node, "maxim,fan-target-rpm",
+ &target_rpm)) {
+ max6650_set_target(data, target_rpm);
+ max6650_set_operating_mode(data, MAX6650_CFG_MODE_CLOSED_LOOP);
+ }
+
return 0;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] hwmon: (max6650) Add initial rpm target devicetree documentation
[not found] ` <5f14ba10-60dd-0e0a-dcd0-f8bbbed33510-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
@ 2016-08-24 8:13 ` Mike Looijmans
[not found] ` <1472026407-3448-2-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Mike Looijmans @ 2016-08-24 8:13 UTC (permalink / raw)
To: linux-hwmon-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: linux-0h96xk9xTtrk1uMJSBkQmQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Mike Looijmans
Add devicetree property for early initialization of the fan controller
to prevent overheating, for example when resetting the board while the
fan was completely turned off.
Signed-off-by: Mike Looijmans <mike.looijmans-Oq418RWZeHk@public.gmane.org>
---
Documentation/devicetree/bindings/hwmon/max6650.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/hwmon/max6650.txt b/Documentation/devicetree/bindings/hwmon/max6650.txt
index d6c10e3..f6bd87d 100644
--- a/Documentation/devicetree/bindings/hwmon/max6650.txt
+++ b/Documentation/devicetree/bindings/hwmon/max6650.txt
@@ -13,6 +13,10 @@ Optional properties, default is to retain the chip's current setting:
- maxim,fan-prescale : Pre-scaling value, as per datasheet [1]. Lower values
allow more fine-grained control of slower fans.
Valid: 1, 2, 4, 8, 16.
+- maxim,fan-target-rpm: Initial requested fan rotation speed. If specified, the
+ driver selects closed-loop mode and the requested speed.
+ This ensures the fan is already running before userspace
+ takes over.
Example:
fan-max6650: max6650@1b {
@@ -20,4 +24,5 @@ Example:
compatible = "maxim,max6650";
maxim,fan-microvolt = <12000000>;
maxim,fan-prescale = <4>;
+ maxim,fan-target-rpm = <1200>;
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] hwmon: (max6650) Add initial rpm target devicetree documentation
[not found] ` <1472026407-3448-2-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
@ 2016-08-30 16:38 ` Rob Herring
2016-08-30 16:56 ` Mike Looijmans
0 siblings, 1 reply; 5+ messages in thread
From: Rob Herring @ 2016-08-30 16:38 UTC (permalink / raw)
To: Mike Looijmans
Cc: linux-hwmon-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, linux-0h96xk9xTtrk1uMJSBkQmQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Wed, Aug 24, 2016 at 10:13:27AM +0200, Mike Looijmans wrote:
> Add devicetree property for early initialization of the fan controller
> to prevent overheating, for example when resetting the board while the
> fan was completely turned off.
>
> Signed-off-by: Mike Looijmans <mike.looijmans-Oq418RWZeHk@public.gmane.org>
> ---
> Documentation/devicetree/bindings/hwmon/max6650.txt | 5 +++++
> 1 file changed, 5 insertions(+)
The kernel boot seems kind of late to ensure your fan is running, but
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] hwmon: (max6650) Add initial rpm target devicetree documentation
2016-08-30 16:38 ` Rob Herring
@ 2016-08-30 16:56 ` Mike Looijmans
0 siblings, 0 replies; 5+ messages in thread
From: Mike Looijmans @ 2016-08-30 16:56 UTC (permalink / raw)
To: Rob Herring; +Cc: linux-hwmon, devicetree, linux, linux-kernel
On 30-08-16 18:38, Rob Herring wrote:
> On Wed, Aug 24, 2016 at 10:13:27AM +0200, Mike Looijmans wrote:
>> Add devicetree property for early initialization of the fan controller
>> to prevent overheating, for example when resetting the board while the
>> fan was completely turned off.
>>
>> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
>> ---
>> Documentation/devicetree/bindings/hwmon/max6650.txt | 5 +++++
>> 1 file changed, 5 insertions(+)
>
> The kernel boot seems kind of late to ensure your fan is running, but
>
> Acked-by: Rob Herring <robh@kernel.org>
Thanks!
Well, "late's better than never," my grandma used to say when we visited :)
To put your mind at ease, the particular platform I'm using this for is
an xc7z045 (Zynq) where the ARMs running the Linux kernel will only
account for 0.5W, but once the logic awakens the chip can dissipate up
to 30W. The logic bitstream is usually on the rootfs, so kernel boot is
early enough for the fan to start spinning. And with the logic asleep,
it need not spin at all.
--
Mike Looijmans
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] hwmon: (max6650) Allow fan shutdown and initial rpm target
[not found] ` <1472026407-3448-1-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
[not found] ` <5f14ba10-60dd-0e0a-dcd0-f8bbbed33510-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
@ 2016-09-09 4:18 ` Guenter Roeck
1 sibling, 0 replies; 5+ messages in thread
From: Guenter Roeck @ 2016-09-09 4:18 UTC (permalink / raw)
To: Mike Looijmans, linux-hwmon-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 08/24/2016 01:13 AM, Mike Looijmans wrote:
> The fan can be stopped by writing "3" to pwm1_enable in sysfs.
>
> Add devicetree property for early initialization of the fan controller
> to prevent overheating, for example when resetting the board while the
> fan was completely turned off.
>
> Also improve error reporting, I2C failures were ignored while writing
> new values.
>
> Signed-off-by: Mike Looijmans <mike.looijmans-Oq418RWZeHk@public.gmane.org>
Applied to hwmon-next.
Thanks,
Guenter
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-09-09 4:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1471334034-14894-1-git-send-email-mike.looijmans@topic.nl>
[not found] ` <c47e4482-a8e0-6a38-cccb-062b667587ac@roeck-us.net>
[not found] ` <57B6A8BF.2080508@topic.nl>
[not found] ` <5f14ba10-60dd-0e0a-dcd0-f8bbbed33510@roeck-us.net>
2016-08-24 8:13 ` [PATCH 1/2] hwmon: (max6650) Allow fan shutdown and initial rpm target Mike Looijmans
[not found] ` <1472026407-3448-1-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
[not found] ` <5f14ba10-60dd-0e0a-dcd0-f8bbbed33510-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
2016-08-24 8:13 ` [PATCH 2/2] hwmon: (max6650) Add initial rpm target devicetree documentation Mike Looijmans
[not found] ` <1472026407-3448-2-git-send-email-mike.looijmans-Oq418RWZeHk@public.gmane.org>
2016-08-30 16:38 ` Rob Herring
2016-08-30 16:56 ` Mike Looijmans
2016-09-09 4:18 ` [PATCH 1/2] hwmon: (max6650) Allow fan shutdown and initial rpm target 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).