Commit cd175872 authored by Francesco Dolcini's avatar Francesco Dolcini Committed by Guenter Roeck
Browse files

hwmon: (amc6821) Add PWM polarity configuration with OF



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: default avatarFrancesco Dolcini <francesco.dolcini@toradex.com>
Link: https://lore.kernel.org/r/20250402102146.65406-3-francesco@dolcini.it


Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent ce664221
Loading
Loading
Loading
Loading
+45 −5
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@
#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;