Rockchip introduced a new PWM controller version (v4) in the RK3576. The downstream kernel carries roughly 1000-2000 lines of code to add support for it (also includes some general improvements to the driver).
Designs
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related.
Learn more.
After looking at the downstream bits and what's in upstream, I've decided that the new hardware, especially once all the features are implemented, is sufficiently different enough from previous versions that it warrants a new driver.
So I'm currently in the process of writing a new basic PWM driver specifically for the PWM v4 IP on the RK3576, and got it to spin the fan today. I'll improve on it a bit more until I submit it upstream, since PWM drivers can be surprisingly non-trivial to get right, but I won't bother with all the things the hardware can do just yet (e.g. one-shot mode, waveform capture (???), etc.).
I implemented capture today, and during the process asked ukleinek (the pwm maintainer) a question on IRC:
<CounterPillow> ukleinek: does a pwmchip's atomic member make a claim about both output and capture? The docstring makes it sound like just apply() has to be atomic.<ukleinek> CounterPillow: don't do capture<ukleinek> CounterPillow: that's what the counter framework is there for.<CounterPillow> Counter framework?<ukleinek> drivers/counter/
Oops. So the entire capture code is now in a local git stash.
I think the proper solution here is to implement the RK3576 PWM as a MFD, which exposes the pwm output functionality (compatible implemented by PWM driver), the capture functionality (compatible implemented by counter driver) and all the other things it does (biphasic counter, frequency metering, etc.)
EDIT: As pointed out by Sebastian, having the different functionalities as child nodes isn't something the DT bindings maintainers would want. So we'll just have one compatible, no children.
I'd like to do this because it saves us upstream's paddling when we inevitably need to retrofit an MFD into the existing PWM compatible later down the line. Considering I implemented capture once in ~5 hours while fighting with the hardware's peculiarities, I think an additional full day or two should be reasonable to get an MFD driver with pwm output and counter functionality into an upstreamable shape.
I think instead of MFD, an auxiliary bus device would be better, as these are not physically separate devices; it's the same device implemented in different subsystem drivers.
Current progress (all on my local checkout atm): implemented an auxiliary bus driver that binds to the OF compatible, and then registers a new pwm output (I call this a "device function") driver that is written as an auxiliary device driver.
The auxiliary bus driver, which I'll call "mfpwm" for now, is in charge of guaranteeing that only one device function at a time can be active, race-free. It is also in charge of making sure critical resources for the device, suck as clocks, are not changed out from under it. This is implemented with a reentrant _acquire and _release pattern where device function drivers _acquire the mfpwm whenever they want to be "the active device", which internally increases its usage count by 1 if successful. If the device is in use by a device function driver other than the calling driver, it'll return -EBUSY instead. This is then balanced by _release calls, which decrease the usage count by 1, and if it hits 0, it will allow another device function driver to subsequently _acquire it.
The refactored PWM output driver is working great. Tomorrow, I'll add a counter driver, and also add back the sysfs interface for switching between the PLL and crystal clock, but this time in the mfpwm driver, as it is in charge of the clocks.