Re: [PATCH] hwmon: (max6639) : Allow setting target RPM

From: Naresh Solanki
Date: Wed Mar 26 2025 - 14:08:11 EST


Hi Guenter,

On Wed, 26 Mar 2025 at 23:12, Guenter Roeck <linux@xxxxxxxxxxxx> wrote:
>
> On 3/26/25 09:59, Naresh Solanki wrote:
> > Hi Guenter,
> >
> > On Wed, 26 Mar 2025 at 22:19, Guenter Roeck <linux@xxxxxxxxxxxx> wrote:
> >>
> >> On 3/26/25 09:36, Naresh Solanki wrote:
> >>> Hi Guenter,
> >>>
> >>> On Tue, 25 Mar 2025 at 05:00, Guenter Roeck <linux@xxxxxxxxxxxx> wrote:
> >>>>
> >>>> On 3/24/25 11:57, Your Name wrote:
> >>>>> From: Naresh Solanki <naresh.solanki@xxxxxxxxxxxxx>
> >>>>>
> >>>>> Currently, during startup, the fan is set to its maximum RPM by default,
> >>>>> which may not be suitable for all use cases.
> >>>>> This patch introduces support for specifying a target RPM via the Device
> >>>>> Tree property "target-rpm".
> >>>>>
> >>>>> Changes:
> >>>>> - Added `target_rpm` field to `max6639_data` structure to store the
> >>>>> target RPM for each fan channel.
> >>>>> - Modified `max6639_probe_child_from_dt()` to read the `"target-rpm"`
> >>>>> property from the Device Tree and set `target_rpm` accordingly.
> >>>>> - Updated `max6639_init_client()` to use `target_rpm` to compute the
> >>>>> initial PWM duty cycle instead of defaulting to full speed (120/120).
> >>>>>
> >>>>> Behavior:
> >>>>> - If `"target-rpm"` is specified, the fan speed is set accordingly.
> >>>>> - If `"target-rpm"` is not specified, the previous behavior (full speed
> >>>>> at startup) is retained.
> >>>>>
> >>>>
> >>>> Unless I am missing something, that is not really correct. See below.
> >>>>
> >>>>> This allows better control over fan speed during system initialization.
> >>>>>
> >>>>> Signed-off-by: Naresh Solanki <naresh.solanki@xxxxxxxxxxxxx>
> >>>>> ---
> >>>>> drivers/hwmon/max6639.c | 15 ++++++++++++---
> >>>>> 1 file changed, 12 insertions(+), 3 deletions(-)
> >>>>>
> >>>>> diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
> >>>>> index 32b4d54b2076..ca8a8f58d133 100644
> >>>>> --- a/drivers/hwmon/max6639.c
> >>>>> +++ b/drivers/hwmon/max6639.c
> >>>>> @@ -80,6 +80,7 @@ struct max6639_data {
> >>>>> /* Register values initialized only once */
> >>>>> u8 ppr[MAX6639_NUM_CHANNELS]; /* Pulses per rotation 0..3 for 1..4 ppr */
> >>>>> u8 rpm_range[MAX6639_NUM_CHANNELS]; /* Index in above rpm_ranges table */
> >>>>> + u32 target_rpm[MAX6639_NUM_CHANNELS];
> >>>>>
> >>>>> /* Optional regulator for FAN supply */
> >>>>> struct regulator *reg;
> >>>>> @@ -560,8 +561,14 @@ static int max6639_probe_child_from_dt(struct i2c_client *client,
> >>>>> }
> >>>>>
> >>>>
> >>>> target_rpm[] is 0 here.
> >>>>
> >>>>> err = of_property_read_u32(child, "max-rpm", &val);
> >>>>> - if (!err)
> >>>>> + if (!err) {
> >>>>> data->rpm_range[i] = rpm_range_to_reg(val);
> >>>>> + data->target_rpm[i] = val;
> >>>>> + }
> >>>>
> >>>> If there is no max-rpm property, or if there is no devicetree support,
> >>>> target_rpm[i] is still 0.
> >>>>
> >>>>> +
> >>>>> + err = of_property_read_u32(child, "target-rpm", &val);
> >>>>> + if (!err)
> >>>>> + data->target_rpm[i] = val;
> >>>>
> >>>> If there is neither max-rpm nor target-rpm, target_rpm[i] is still 0.
> >>>>
> >>>>>
> >>>>> return 0;
> >>>>> }
> >>>>> @@ -573,6 +580,7 @@ static int max6639_init_client(struct i2c_client *client,
> >>>>> const struct device_node *np = dev->of_node;
> >>>>> struct device_node *child;
> >>>>> int i, err;
> >>>>> + u8 target_duty;
> >>>>>
> >>>>> /* Reset chip to default values, see below for GCONFIG setup */
> >>>>> err = regmap_write(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR);
> >>>>> @@ -639,8 +647,9 @@ static int max6639_init_client(struct i2c_client *client,
> >>>>> if (err)
> >>>>> return err;
> >>>>>
> >>>>> - /* PWM 120/120 (i.e. 100%) */
> >>>>> - err = regmap_write(data->regmap, MAX6639_REG_TARGTDUTY(i), 120);
> >>>>> + /* Set PWM based on target RPM if specified */
> >>>>> + target_duty = 120 * data->target_rpm[i] / rpm_ranges[data->rpm_range[i]];
> >>>>
> >>>> If there is no devicetree support, or if neither max-rpm nor target-rpm are
> >>>> provided, target_duty will be 0, and the fans will stop.
> >>>>
> >>>> Maybe my interpretation is wrong, but I think both target_rpm[] and rpm_range[]
> >>>> will need to be initialized. Also, it seems to me that there will need to be an
> >>>> upper bound for target_rpm[]; without it, it is possible that target_duty > 120,
> >>>> which would probably not be a good idea.
> >>> Yes you're right. I missed it in my analysis.
> >>>
> >>> Here is the logic that would address:
> >>> target_rpm = 120;
> >>> /* Set PWM based on target RPM if specified */
> >>> if (data->target_rpm[i] != 0 &&
> >>> data->target_rpm[i] <= rpm_ranges[data->rpm_range[i]]) {
> >>>
> >>> target_duty = 120 * data->target_rpm[i] /
> >>> rpm_ranges[data->rpm_range[i]];
> >>> }
> >>>
> >>> Please let me know your thoughts & suggestions.
> >>>
> >>
> >> I would prefer if target_rpm[] and rpm_range[] were pre-initialized with default
> >> values in the probe function. That would avoid runtime checks.
> > rpm_range is pre-initialized to 4000 RPM [1]
> > I can also init target_rpm[] to 4000 RPM as default along with above init.
> >
> Yes.
>
> > But still there might be a case wherein DT doesn't provide max-rpm but
> > target-rpm is set to greater than 4000 RPM
> > Thus there will be a need to check to cover this kind of scenario.
> >
> > Please let me know your thoughts & will implement that.
> >
>
> You'll need to validate target_rpm against max-rpm either way,
> to make sure that target_rpm <= max_rpm.
Will update in V2 accordingly.
Thanks for your inputs.

Regards,
Naresh
>
> Thanks,
> Guenter
>