]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (amc6821) Add PWM polarity configuration with OF
authorFrancesco Dolcini <francesco.dolcini@toradex.com>
Wed, 2 Apr 2025 10:21:46 +0000 (12:21 +0200)
committerGuenter Roeck <linux@roeck-us.net>
Wed, 23 Apr 2025 14:18:27 +0000 (07:18 -0700)
Add support to configure the PWM-Out pin polarity based on the device
tree. The binding would allow also to configure the PWM period, this is
currently not implemented by the driver.

The driver has a module option to set the PWM polarity (normal=0,
inverted=1), when specified it always takes the precedence over the DT.

Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Link: https://lore.kernel.org/r/20250402102146.65406-3-francesco@dolcini.it
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/amc6821.c

index 1e3c6acd89740f281f90d149838ddd6d2048bce4..13a789cc85d24da282430eb2d4edf0003617fe6b 100644 (file)
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of_platform.h>
+#include <linux/pwm.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
+#include <dt-bindings/pwm/pwm.h>
+
 /*
  * Addresses to scan.
  */
@@ -37,7 +40,7 @@ static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
  * Insmod parameters
  */
 
-static int pwminv;     /*Inverted PWM output. */
+static int pwminv = -1; /*Inverted PWM output. */
 module_param(pwminv, int, 0444);
 
 static int init = 1; /*Power-on initialization.*/
@@ -845,9 +848,43 @@ static int amc6821_detect(struct i2c_client *client, struct i2c_board_info *info
        return 0;
 }
 
-static int amc6821_init_client(struct amc6821_data *data)
+static enum pwm_polarity amc6821_pwm_polarity(struct i2c_client *client)
+{
+       enum pwm_polarity polarity = PWM_POLARITY_NORMAL;
+       struct of_phandle_args args;
+       struct device_node *fan_np;
+
+       /*
+        * For backward compatibility, the pwminv module parameter takes
+        * always the precedence over any other device description
+        */
+       if (pwminv == 0)
+               return PWM_POLARITY_NORMAL;
+       if (pwminv > 0)
+               return PWM_POLARITY_INVERSED;
+
+       fan_np = of_get_child_by_name(client->dev.of_node, "fan");
+       if (!fan_np)
+               return PWM_POLARITY_NORMAL;
+
+       if (of_parse_phandle_with_args(fan_np, "pwms", "#pwm-cells", 0, &args))
+               goto out;
+       of_node_put(args.np);
+
+       if (args.args_count != 2)
+               goto out;
+
+       if (args.args[1] & PWM_POLARITY_INVERTED)
+               polarity = PWM_POLARITY_INVERSED;
+out:
+       of_node_put(fan_np);
+       return polarity;
+}
+
+static int amc6821_init_client(struct i2c_client *client, struct amc6821_data *data)
 {
        struct regmap *regmap = data->regmap;
+       u32 regval;
        int err;
 
        if (init) {
@@ -864,11 +901,14 @@ static int amc6821_init_client(struct amc6821_data *data)
                if (err)
                        return err;
 
+               regval = AMC6821_CONF1_START;
+               if (amc6821_pwm_polarity(client) == PWM_POLARITY_INVERSED)
+                       regval |= AMC6821_CONF1_PWMINV;
+
                err = regmap_update_bits(regmap, AMC6821_REG_CONF1,
                                         AMC6821_CONF1_THERMOVIE | AMC6821_CONF1_FANIE |
                                         AMC6821_CONF1_START | AMC6821_CONF1_PWMINV,
-                                        AMC6821_CONF1_START |
-                                        (pwminv ? AMC6821_CONF1_PWMINV : 0));
+                                        regval);
                if (err)
                        return err;
        }
@@ -916,7 +956,7 @@ static int amc6821_probe(struct i2c_client *client)
                                     "Failed to initialize regmap\n");
        data->regmap = regmap;
 
-       err = amc6821_init_client(data);
+       err = amc6821_init_client(client, data);
        if (err)
                return err;