Re: [PATCH v5 2/2] pwm: Add Loongson PWM controller support

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

 



Hello,

On Wed, Jul 10, 2024 at 10:04:07AM +0800, Binbin Zhou wrote:
> diff --git a/drivers/pwm/pwm-loongson.c b/drivers/pwm/pwm-loongson.c
> new file mode 100644
> index 000000000000..17ab2a2f48ad
> --- /dev/null
> +++ b/drivers/pwm/pwm-loongson.c
> @@ -0,0 +1,285 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Loongson PWM driver
> + *
> + * Author: Juxin Gao <gaojuxin@xxxxxxxxxxx>
> + * Further cleanup and restructuring by:
> + *         Binbin Zhou <zhoubinbin@xxxxxxxxxxx>
> + *
> + * Copyright (C) 2017-2024 Loongson Technology Corporation Limited.
> + *
> + * Limitations:
> + * - The buffer register value should be written before the CTRL register.
> + * - When disabled the output is driven to 0 independent of the configured
> + *   polarity.

An info about possible glitches and if a period is completed on
reconfiguration or when the PWM is disabled would be great.

Also if there is a publically available manual, please add a link here.

> + */
> +
> [...]
> +static int pwm_loongson_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +			      const struct pwm_state *state)
> +{
> +	int ret;
> +	u64 period, duty_cycle;
> +	bool enabled = pwm->state.enabled;
> +
> +	if (enabled && !state->enabled) {
> +		pwm_loongson_disable(chip, pwm);
> +		return 0;
> +	}

You can also shortcut if !pwm->state.enabled. Something like:

	if (!state->enabled) {
		if (enabled)
			pwm_loongson_disable(chip, pwm);
		return 0;
	}

> +	if (state->polarity != pwm->state.polarity) {
> +		ret = pwm_loongson_set_polarity(chip, pwm, state->polarity);
> +		if (ret)
> +			return ret;
> +	}

Together with the shortcut above this is buggy. Consider:

	pwm_apply_might_sleep(mypwm, &(struct pwm_state){
			.period = A,
			.duty_cycle = B,
			.polarity = PWM_POLARITY_NORMAL,
			.enabled = true});
	pwm_apply_might_sleep(mypwm, &(struct pwm_state){
			.period = A,
			.duty_cycle = B,
			.polarity = PWM_POLARITY_INVERSED,
			.enabled = false});
	pwm_apply_might_sleep(mypwm, &(struct pwm_state){
			.period = A,
			.duty_cycle = B,
			.polarity = PWM_POLARITY_INVERSED,
			.enabled = true});

After the 2nd call you left pwm_loongson_apply() early without writing
the inversed polarity to the register space. In the 3rd call you have
state->polarity == pwm->state.polarity and so skip configuring the
polarity again.

I suggest to just do pwm_loongson_set_polarity() unconditionally if
state->enabled = true.

> +	period = min(state->period, NANOHZ_PER_HZ);
> +	duty_cycle = min(state->duty_cycle, NANOHZ_PER_HZ);
> +
> +	ret = pwm_loongson_config(chip, pwm, duty_cycle, period);
> +	if (ret)
> +		return ret;
> +
> +	if (!enabled && state->enabled)
> +		ret = pwm_loongson_enable(chip, pwm);
> +
> +	return ret;
> +}

Best regards
Uwe

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux