Re: [PATCH 3/3] pwm: argon-fan-hat: Add Argon40 Fan HAT support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Marek,

I wonder how this device works in rpios, I didn't find a matching driver
(but I also didn't try more than two minutes).

On Wed, Jun 11, 2025 at 12:07:27AM +0200, Marek Vasut wrote:
> diff --git a/drivers/pwm/pwm-argon-fan-hat.c b/drivers/pwm/pwm-argon-fan-hat.c
> new file mode 100644
> index 000000000000..3d04abdbd349
> --- /dev/null
> +++ b/drivers/pwm/pwm-argon-fan-hat.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2025 Marek Vasut
> + */

 * Limitations:
 * - fixed period (which?)
 * - no support for offset/polarity

If you can find out if it completes a period when reconfigured that
would also be nice to document.

This device is really trivial, but for completeness' sake: If there is a
data sheet publicly available, please add a link here.

> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/pwm.h>
> +
> +static int argon_fan_hat_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +				   const struct pwm_state *state)

Can you please implement the new-style callbacks?

> +{
> +	struct i2c_client *i2c = pwmchip_get_drvdata(chip);
> +	u8 tx[2] = { 0x80, state->enabled ? pwm_get_relative_duty_cycle(state, 100) : 0 };

This is too simple. I won't go into details about the right algorithm
for .apply() as I want you to implement .round_waveform_tohw() +
.round_waveform_fromhw() + .read_waveform() + .write_waveform() anyhow.

For .round_waveform_tohw() you have to know the actual period length and
then use something like:

	duty = wf->duty_length_ns;

	if (duty > ARGON_FAN_HAT_PERIOD)
		duty = ARGON_FAN_HAT_PERIOD;

	duty_percent = 100 * duty / ARGON_FAN_HAT_PERIOD;
	

> +	struct i2c_msg msg = {
> +		.addr = i2c->addr,
> +		.len = 2,
> +		.buf = tx,
> +	};
> +
> +	if (state->polarity != PWM_POLARITY_NORMAL)
> +		return -EINVAL;
> +
> +	return (i2c_transfer(i2c->adapter, &msg, 1) == 1) ? 0 : -EINVAL;
> +}
> +
> +static const struct pwm_ops argon_fan_hat_pwm_ops = {
> +	.apply = argon_fan_hat_pwm_apply,

Can you read back the configuration? If yes then please implement
.read_waveform().

> +};
> +
> +static int argon_fan_hat_i2c_probe(struct i2c_client *i2c)
> +{
> +	struct pwm_chip *pc = devm_pwmchip_alloc(&i2c->dev, 1, 0);
> +
> +	if (IS_ERR(pc))
> +		return PTR_ERR(pc);
> +
> +	pc->ops = &argon_fan_hat_pwm_ops;
> +	pwmchip_set_drvdata(pc, i2c);
> +
> +	return devm_pwmchip_add(&i2c->dev, pc);

Error message on failure please. (-> dev_err_probe())

> +}
> +
> +static const struct of_device_id argon_fan_hat_dt_ids[] = {
> +	{ .compatible = "argon40,fan-hat" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, argon_fan_hat_dt_ids);
> +
> +static struct i2c_driver argon_fan_hat_driver = {
> +	.driver = {
> +		.name = "argon-fan-hat",
> +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
> +		.of_match_table = argon_fan_hat_dt_ids,
> +	},
> +	.probe = argon_fan_hat_i2c_probe,
> +};

TIL about PROBE_PREFER_ASYNCHRONOUS.

Best regards
Uwe

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux