Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PWM waveform, axi-pwmgen backport #2640

Open
wants to merge 397 commits into
base: main
Choose a base branch
from

Conversation

threexc
Copy link
Collaborator

@threexc threexc commented Oct 30, 2024

PR Description

This PR includes several backports from upstream v6.12 and v6.13 branches around new PWM consumer APIs and waveform support, in preparation for the subsequent backport of the upstream ad7625 driver. Highlights:

  • cherry-pick and cleanup rename of pwm_apply_state() to pwm_apply_might_sleep()
  • backport v6.12 versions of pwm/core.c, include/linux/pwm.h, include/trace/events/pwm.h
  • remove drivers/pwm/sysfs.c (now incorporated in drivers/pwm/core.c)
  • cherry-pick devm_clk_rate_exclusive_get() addition
  • backport v6.12 version of drivers/pwm/pwm-axi-pwmgen.c
  • Cherry-pick the following from v6.13:
    • Improved pwm locking
    • PWM waveform abstractions, consumer APIs
    • PWM waveform tracing
    • axi-pwmgen driver implementation using PWM waveforms
    • pwm/core.c symbol reordering
    • kernel doc additions for new pwm_ops
    • chardev support for PWM devices

This has been tested locally using a Zedboard with a customized BOOT.BIN to route PWM signals to a PMOD header and the libpwm tooling found at https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/libpwm.git/, which allows setting PWM waveform properties via the newly-added character device interface.

PR Type

  • Bug fix (a change that fixes an issue)
  • New feature (a change that adds new functionality)
  • Breaking change (a change that affects other repos or cause CIs to fail)

PR Checklist

  • I have conducted a self-review of my own code changes
  • I have tested the changes on the relevant hardware
  • I have updated the documentation outside this repo accordingly (if there is the case)

@threexc threexc changed the title PWM waveform, rounding backport PWM waveform, axi-pwmgen backport Oct 30, 2024
@nunojsa
Copy link
Collaborator

nunojsa commented Oct 31, 2024

The backport broke the pulsar driver. These amount of backports in subsystems is a bit unsettling but I'll keep an open mind (also because a lot of the new stuff we have in the pipeline depend on the new PWM stuff). Oh well, hopefully this does not bring too much churn in my next merge.

@threexc
Copy link
Collaborator Author

threexc commented Oct 31, 2024

Sorry about that. I'll see if I can fix it up, since I have some cleanup to do in the commit messages anyway.

@threexc threexc force-pushed the pwm_waveform_backport branch from 49dec64 to 5bb9ba4 Compare October 31, 2024 16:39
@threexc
Copy link
Collaborator Author

threexc commented Oct 31, 2024

Updated the PR with:

  • List of extra drivers modified in the ADI tree in commit 5c2cc67
  • Cherry-pick of patch adding axi_pwmgen_ddata_from_chip()
  • Cherry-picks of David's patches tweaking the axi-pwmgen driver's default alignment behaviors and register numbering
  • Clarification in each cherry-picked patch stating the branch and commit ID it was taken from
  • New patch adding the phase property back to struct pwm_state to make ltc2387.c and ad_pulsar.c compile, with a comment about the change

For the last point, I can confirm they both build OK, but I don't have the specific hardware to test them on.

@dlech
Copy link
Collaborator

dlech commented Nov 7, 2024

  • chardev support for PWM devices

This isn't finalized upstream yet, so probably best to not backport (unless we really need it?).

  • to make ltc2387.c

IIRC, this one should be similar to ad7625 that you worked on? So should be easy to convert to use the new waveform stuff.

  • and ad_pulsar.c

Having worked on similar chips (ad7944, ad4000), I have strong doubts that this actually is using the phase feature. There is only one PWM used by the driver, so it doesn't seem like phase is actually doing anything there. Likely we can just delete that line.

@dlech
Copy link
Collaborator

dlech commented Nov 7, 2024

Found one more driver using phase: ad4630. That one uses 2 PWMs so we should convert it to the waveform APIs.

@threexc
Copy link
Collaborator Author

threexc commented Nov 11, 2024

FYI: Will be returning to this shortly, just getting some patches for the ad4695 driver ready to go upstream first.

@threexc threexc force-pushed the pwm_waveform_backport branch from 5bb9ba4 to b10a8f8 Compare November 11, 2024 17:13
@threexc
Copy link
Collaborator Author

threexc commented Nov 11, 2024

Rebased, not ready for review again yet.

@threexc threexc marked this pull request as draft November 11, 2024 17:14
@threexc threexc force-pushed the pwm_waveform_backport branch 2 times, most recently from f68d9d3 to 928f828 Compare November 14, 2024 19:22
@threexc
Copy link
Collaborator Author

threexc commented Nov 14, 2024

Rebased again, removed the old patch that preserved the phase field, and added three new patches to adjust the ad_pulsar.c, ltc2387.c, and ad4630.c drivers. Still need to test the latter, then I will make this ready for review (everything compiles OK).

@threexc
Copy link
Collaborator Author

threexc commented Nov 14, 2024

  • chardev support for PWM devices

This isn't finalized upstream yet, so probably best to not backport (unless we really need it?).

You're right, this probably isn't needed, but I was using it to test the basic PWM functionality. I'll remove it before marking this as ready for review again.

@threexc threexc force-pushed the pwm_waveform_backport branch 4 times, most recently from d547156 to 37f8442 Compare November 21, 2024 14:31
andy-shev and others added 5 commits January 8, 2025 10:02
Use the dedicated helper for comparing device names against strings.

Note, the current code has a check for the dev_name() against NULL.
With the current implementations of the device_add() and dev_set_name()
it most likely a theoretical assumption that that might happen, while
I don't see how. Hence, that check has simply been removed.

Signed-off-by: Andy Shevchenko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Uwe Kleine-König <[email protected]>
Origin: v6.13-rc1~157^2~2, commit:fdb62922ae89c17963f80abdd14b4d9f053bc962
Export the pwm_get_state_hw() function. This is useful in cases where
we want to know what the hardware is actually doing, rather than what
what we requested it should do.

Locking had to be rearranged to ensure that the chip is still
operational before trying to access ops now that this can be called
from outside the pwm core.

Signed-off-by: David Lechner <[email protected]>
Link: https://lore.kernel.org/r/20241029-pwm-export-pwm_get_state_hw-v2-1-03ba063a3230@baylibre.com
[ukleinek: Add dummy for !CONFIG_PWM]
Signed-off-by: Uwe Kleine-König <[email protected]>
Origin: v6.13-rc1~157^2~1, commit:2ea25aab938a250bdf3148acd15359b56b91b40e
Some PWM hardwares (e.g. MC33XS2410) cannot implement a zero duty cycle
but can instead disable the hardware which also results in a constant
inactive output.

There are some checks (enabled with CONFIG_PWM_DEBUG) to help
implementing a driver without violating the normal rounding rules. Make
them less strict to let above described hardware pass without warning.

Reported-by: Dimitri Fedrau <[email protected]>
Link: https://lore.kernel.org/r/20241103205215.GA509903@debian
Fixes: 3ad1f3a ("pwm: Implement some checks for lowlevel drivers")
Signed-off-by: Uwe Kleine-König <[email protected]>
Reviewed-by: Dimitri Fedrau <[email protected]>
Tested-by: Dimitri Fedrau <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Uwe Kleine-König <[email protected]>
Origin: v6.13-rc1~157^2, commit:b2eaa1170e45dc18eb09dcc9abafbe9a7502e960
When the timer supports complementary output, the CCxNE bit must be set
additionally to the CCxE bit. So to not overwrite the latter use |=
instead of = to set the former.

Fixes: deaba9c ("pwm: stm32: Implementation of the waveform callbacks")
Signed-off-by: Fabrice Gasnier <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ukleinek: Slightly improve commit log]
Signed-off-by: Uwe Kleine-König <[email protected]>
Origin: v6.13-rc4~27^2, commit:edc19bd0e571c732cd01c8da62f904e6d2a29a48
It is being set but likely isn't used, so remove it to avoid build
errors now that the new PWM waveform API is included.

Signed-off-by: Trevor Gamblin <[email protected]>
@threexc threexc force-pushed the pwm_waveform_backport branch from c105786 to 4ef143b Compare January 8, 2025 15:02
@threexc
Copy link
Collaborator Author

threexc commented Jan 8, 2025

@ukleinek was kind enough to help put together a more extensive PWM backport from upstream in December, which I've now pushed and thrown my last few phase-related customizations on top of. This solves a bunch of build issues we saw with my previous version, which worked for the PWM drivers but broke a lot of other things. I've tested this with an ad4630-24 again and it works, and I haven't seen any build issues either.

Copy link
Collaborator

@dlech dlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume everything other than the last 3 commits is cherry-picked from upstream?

drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
@threexc threexc force-pushed the pwm_waveform_backport branch from 4ef143b to 6d1fd27 Compare January 8, 2025 22:49
@threexc
Copy link
Collaborator Author

threexc commented Jan 8, 2025

Pushed review-based updates to the ad4630 driver. No other changes.

drivers/iio/adc/ad4630.c Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
@nunojsa
Copy link
Collaborator

nunojsa commented Jan 9, 2025

@ukleinek was kind enough to help put together a more extensive PWM backport from upstream in December, which I've now pushed and thrown my last few phase-related customizations on top of. This solves a bunch of build issues we saw with my previous version, which worked for the PWM drivers but broke a lot of other things. I've tested this with an ad4630-24 again and it works, and I haven't seen any build issues either.

I have to be honest... this is a bit concerning. We have now 250 patches in the backport. Was there any major/blocker issue with the previous approach that justifies this? I'm foreseeing lot's of pain and conflicts next time we merge to another kernel (even more if the next version we go happens to not include the waveform API).

@threexc threexc force-pushed the pwm_waveform_backport branch from 6d1fd27 to 6a6b7f1 Compare January 9, 2025 16:32
@threexc
Copy link
Collaborator Author

threexc commented Jan 9, 2025

@ukleinek was kind enough to help put together a more extensive PWM backport from upstream in December, which I've now pushed and thrown my last few phase-related customizations on top of. This solves a bunch of build issues we saw with my previous version, which worked for the PWM drivers but broke a lot of other things. I've tested this with an ad4630-24 again and it works, and I haven't seen any build issues either.

I have to be honest... this is a bit concerning. We have now 250 patches in the backport. Was there any major/blocker issue with the previous approach that justifies this? I'm foreseeing lot's of pain and conflicts next time we merge to another kernel (even more if the next version we go happens to not include the waveform API).

The main motivating issue was that with a minimal port of only the axi-pwmgen driver and the core all other drivers are broken. So if a user of the ADI vendor tree wants to use a PWM for a non-ADI related purpose, they have to fix this driver first. This is an experience we don't want a user to suffer from.

For the record, the failures seen when trying to run make drivers/pwm/ with the original backport tend to look like:

drivers/pwm/pwm-crc.c: In function 'crc_pwm_apply':
drivers/pwm/pwm-crc.c:58:30: error: incompatible types when initializing type 'struct device *' using type 'struct device'
   58 |         struct device *dev = crc_pwm->chip.dev;
      |                              ^~~~~~~
drivers/pwm/pwm-crc.c: In function 'crc_pwm_get_state':
drivers/pwm/pwm-crc.c:128:30: error: incompatible types when initializing type 'struct device *' using type 'struct device'
  128 |         struct device *dev = crc_pwm->chip.dev;
      |                              ^~~~~~~
drivers/pwm/pwm-crc.c: In function 'crystalcove_pwm_probe':
drivers/pwm/pwm-crc.c:171:25: error: incompatible types when assigning to type 'struct device' from type 'struct device *'
  171 |         pwm->chip.dev = &pdev->dev;
      |                         ^

Additionally there are some conflicts that are not detected by git and only break at compile time or even at runtime only.

Further we (=@threexc and @ukleinek) expect that an update to a newer kernel will be smooth as the commits pretty much match mainline and so most of them just drop out cleanly (or are kept cleanly if they are newer in mainline than the new base version) and so yields less friction than a custom partial port even.
If the next update will be to something older than 6.13, there is a trick to reduce conflicts for merges (a rebase should be fine as described above). If you're interested we can elaborate. And we gladly support you when the time has come and you need a helping hand with conflict resolution.

So even if the patch count is big, we're convinced this is the right balance between effort and benefit for ADI and value for ADI's customers.

@nunojsa
Copy link
Collaborator

nunojsa commented Jan 10, 2025

The main motivating issue was that with a minimal port of only the axi-pwmgen driver and the core all other drivers are broken. So if a user of the ADI vendor tree wants to use a PWM for a non-ADI related purpose, they have to fix this driver first. This is an experience we don't want a user to suffer from.

Agreed... The other drivers should still build even if we do not use them and we had a recent case (on pwm-cadence) in the 2023_R2 release.

If the next update will be to something older than 6.13, there is a trick to reduce conflicts for merges (a rebase should be fine as described above). If you're interested we can elaborate

That's what I fear... Yeah, we can't really rebase on main but I do normally have a rebased branch which needs to have a NULL diff with main and can be used to make sure git merge did not silently broke any driver. On the other hand, there are good chances we'll go to something higher or equal as 6.13 as there's still no longterm version after 6.6 (and xilinx typically uses longterm).

Alright, let's see how this works out. Will wait from an ack from David ou Uwe since they were the most active (together with you) in these process.

Copy link
Collaborator

@dlech dlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"iio: adc: ltc2387.c: update to use PWM waveforms" could use a commit description.

I only looked at the last 3 patches that aren't backports since I assume that Uwe has already looked at the others that are being backported.

drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
Now that the PWM waveform functionality is backported from upstream, use
it to handle duty offsets instead of the legacy phase code, which is
removed.

Signed-off-by: Trevor Gamblin <[email protected]>
@threexc threexc force-pushed the pwm_waveform_backport branch from 6a6b7f1 to 7db6787 Compare January 10, 2025 17:30
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
@threexc threexc force-pushed the pwm_waveform_backport branch 3 times, most recently from e26748a to b953c70 Compare January 10, 2025 18:24
drivers/iio/adc/ad4630.c Outdated Show resolved Hide resolved
@threexc threexc force-pushed the pwm_waveform_backport branch 2 times, most recently from 95ff279 to 930e7a0 Compare January 10, 2025 19:15
Copy link
Collaborator

@nunojsa nunojsa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it seems this is mostly ready t go. Just one minor thing I'd like to be fixed...


spi_engine_ex_offload_enable(st->spi, false);
spi_bus_unlock(st->spi->master);

spi_unoptimize_message(&st->offload_msg);
ret = regmap_read(st->regmap, AD4630_REG_ACCESS, &dummy);
out_error:
if (ret)
pr_warn("%s:%d: couldn't reenter register configuration mode\n", __func__, __LINE__);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why pr_warn() and not dev_warn()?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I use pr_warn() for debug but dev_warn() is preferred when a dev object is available. Pushed a change for that.

Reserve setting of PWMs for ad4630_buffer_preenable(), and
ad4630_update_sample_fetch_trigger(). Disable them with pwm_disable() in
two places: ad4630_pwm_get() (so that the PWM outputs aren't on after
initialization) and ad4630_buffer_postdisable(). Some instances of the
driver state had the const qualifiers removed since they now actually
need to be modified.

Since the PWM rounding API outputs may vary depending on the reference
clock used, add a loop to continually try rounding the conversion
waveform until an appropriate duty_length_ns value is obtained. Change
AD4630_TQUIET_CNV_DELAY_PS to AD4630_TQUIET_CNV_DELAY_NS and the nearest
appropriate value, so that we don't have to round when calculating PWM
offsets now. Do the same rounding process for the fetch waveform's
duty_offset_ns as for the conv waveform's duty_length_ns.

Also add a bit more logic to buffer_preenable() to  properly handle
error unwinding, similar to how it's done in buffer_postdisable().

Signed-off-by: Trevor Gamblin <[email protected]>
@threexc threexc force-pushed the pwm_waveform_backport branch from 930e7a0 to b9f1141 Compare January 13, 2025 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.