From: William Breathitt Gray <wbg@kernel.org>
To: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Cc: "William Breathitt Gray" <wbg@kernel.org>,
"Uwe Kleine-König" <ukleinek@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Heiko Stuebner" <heiko@sntech.de>, "Lee Jones" <lee@kernel.org>,
"Damon Ding" <damon.ding@rock-chips.com>,
kernel@collabora.com, "Jonas Karlman" <jonas@kwiboo.se>,
"Alexey Charkov" <alchark@gmail.com>,
linux-rockchip@lists.infradead.org, linux-pwm@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org
Subject: Re: [PATCH v5 4/6] counter: Add rockchip-pwm-capture driver
Date: Sun, 3 May 2026 19:46:23 +0900 [thread overview]
Message-ID: <20260503104624.459765-1-wbg@kernel.org> (raw)
In-Reply-To: <20260420-rk3576-pwm-v5-4-ae7cfbbe5427@collabora.com>
On Mon, Apr 20, 2026 at 03:52:41PM +0200, Nicolas Frattaroli wrote:
> Among many other things, Rockchip's new PWMv4 IP in the RK3576 supports
> PWM capture functionality.
>
> Add a basic driver for this that works to expose HPC/LPC counts and
> state change events to userspace through the counter framework. It's
> quite basic, but works well enough to demonstrate the device function
> exclusion stuff that mfpwm does, in order to eventually support all the
> functions of this device in drivers within their appropriate subsystems,
> without them interfering with each other.
>
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Hi Nicolas,
Forgive me if I asked this before, but I'm having trouble finding it
online: do you have a link to a publicly available RK357 technical
reference manual? I think that will help me better understand how this
PWMv4 IP works.
Regardless, some comments inline below from my current understanding.
> +static struct counter_signal rkpwmc_signals[] = {
> + {
> + .id = 0,
> + .name = "PWM Clock"
> + },
> +};
If the capture mode is used to measure the duty cycle of the PWM input,
then we actually have two Signals to define here: "PWM Clock" and "PWM
Input".
I imagine the capture mode waveforms look something like this:
__ __ __ __ __ __ __
clk __| |__| |__| |__| |__| |__| |__| |__
__________________ LPC: 2 edges ____
pwm_in _________| HPC: 3 edges |____________|
So the level of the pwm_in signal is counted each rising edge of clk;
the number of clk edges while pwm_in is high is the HPC count, whereas
the number of clk edges while pwm_in is low is the LPC count.
In the Generic Counter paradigm, this would look like the following:
Signals Synapses Counts
======= ======== ======
+-----------+ _______________________
| | <---- "Rising Edge" ---+---> / \
|"PWM Clock"| | |"High Polarity Capture"|
| | +---|---> \ /
+-----------+ | | -----------------------
| |
+-----------+ | | _______________________
| | | +---> / \
|"PWM Input"| | | "Low Polarity Capture |
| | <---- "None" ------+-------> \ /
+-----------+ -----------------------
The key idea is that the clock and PWM input Signals are associated to
both Counts (HPC and LPC) through their respective Synapses. However,
while the clock Synapse ("Rising Edge") indicates the clock Signal
state triggers updates in the Counts, the PWM input Synapse ("None")
indicates the PWM input Signal state does not trigger but is simply
evaluated to determine the new Count value.
> +static const enum counter_synapse_action rkpwmc_hpc_lpc_actions[] = {
> + COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
> + COUNTER_SYNAPSE_ACTION_NONE,
> +};
To simplify my above example, I assumed that the HPC and LPC counts are
only updated on rising edges of the clock Signal. If the Count values
actually update on both edges, then you don't need to make a change
here. Otherwise, change the "both edges" enum constant to "rising edge"
or "falling edge" as required.
> +static struct counter_synapse rkpwmc_pwm_synapses[] = {
> + {
> + .actions_list = rkpwmc_hpc_lpc_actions,
> + .num_actions = ARRAY_SIZE(rkpwmc_hpc_lpc_actions),
> + .signal = &rkpwmc_signals[0]
> + },
> +};
Add a Synapse here for the "PWM Input" Signal.
You should also implement an action_read() callback. Check the value of
synapse->signal->id to determine which Signal is associated to the
Synapse and set the respective action; i.e. for the PWM clock set
COUNTER_SYNAPSE_ACTION_BOTH_EDGES, while for the PWM input set
COUNTER_SYNAPSE_ACTION_NONE.
> +static const enum counter_function rkpwmc_functions[] = {
> + COUNTER_FUNCTION_INCREASE,
> +};
I wonder if we need a new enum counter_function constant to express
what's happening in this driver. In theory, the
COUNTER_FUNCTION_INCREASE represent a Count whose value only increases,
but what we're describing here is more of a duty cycle sample, right?
I haven't made up my mind on this, so for now you can stick with
COUNTER_FUNCTION_INCREASE. I'll reconsider it in the next revision.
> +static int rkpwmc_enable_write(struct counter_device *counter,
> + struct counter_count *count,
> + u8 enable)
> +{
> + struct rockchip_pwm_capture *pc = counter_priv(counter);
> + int ret;
> +
> + ret = mfpwm_acquire(pc->pwmf);
> + if (ret)
> + return ret;
> +
> + if (!!enable != rkpwmc_is_enabled(pc->pwmf)) {
The Counter subsystem gurantees enable is a boolean value so there's no
need for the double negation here in the conditional.
Also, instead of checking if the enable value is different from
rkpwm_is_enabled(), check if it is the same and exit early. That will
avoid the large conditional block as what you have inside can now move
outside after the conditional check.
> + if (enable) {
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_ENABLE,
> + PWMV4_EN(false));
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_CTRL,
> + PWMV4_CTRL_CAP_FLAGS);
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_INT_EN,
> + PWMV4_INT_LPC_W(true) |
> + PWMV4_INT_HPC_W(true));
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_ENABLE,
> + PWMV4_EN(true) | PWMV4_CLK_EN(true));
> +
> + ret = clk_enable(pc->pwmf->core);
> + if (ret)
> + goto err_release;
> +
> + ret = clk_rate_exclusive_get(pc->pwmf->core);
> + if (ret)
> + goto err_disable_pwm_clk;
> +
> + ret = mfpwm_acquire(pc->pwmf);
> + if (ret)
> + goto err_unprotect_pwm_clk;
> + } else {
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_INT_EN,
> + PWMV4_INT_LPC_W(false) |
> + PWMV4_INT_HPC_W(false));
> + mfpwm_reg_write(pc->pwmf->base, PWMV4_REG_ENABLE,
> + PWMV4_EN(false) | PWMV4_CLK_EN(false));
> + clk_rate_exclusive_put(pc->pwmf->core);
> + clk_disable(pc->pwmf->core);
> + mfpwm_release(pc->pwmf);
> + }
> + }
> +
> + mfpwm_release(pc->pwmf);
The call to mfpwm_release() in the else block is redundant because it is
called immediately again here.
William Breathitt Gray
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
next prev parent reply other threads:[~2026-05-03 10:47 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 13:52 [PATCH v5 0/6] Add Rockchip RK3576 PWM Support Through MFPWM Nicolas Frattaroli
2026-04-20 13:52 ` [PATCH v5 1/6] dt-bindings: pwm: Add a new binding for rockchip,rk3576-pwm Nicolas Frattaroli
2026-04-20 13:52 ` [PATCH v5 2/6] mfd: Add Rockchip mfpwm driver Nicolas Frattaroli
2026-04-20 13:52 ` [PATCH v5 3/6] pwm: Add rockchip PWMv4 driver Nicolas Frattaroli
2026-04-26 9:44 ` Damon Ding
2026-04-26 13:06 ` Uwe Kleine-König
2026-04-27 1:20 ` Damon Ding
2026-04-26 10:09 ` Damon Ding
2026-04-20 13:52 ` [PATCH v5 4/6] counter: Add rockchip-pwm-capture driver Nicolas Frattaroli
2026-04-26 10:55 ` Damon Ding
2026-04-27 17:35 ` Nicolas Frattaroli
2026-05-03 11:06 ` William Breathitt Gray
2026-05-03 10:46 ` William Breathitt Gray [this message]
2026-04-20 13:52 ` [PATCH v5 5/6] arm64: dts: rockchip: add PWM nodes to RK3576 SoC dtsi Nicolas Frattaroli
2026-04-26 7:30 ` Damon Ding
2026-04-20 13:52 ` [PATCH v5 6/6] arm64: dts: rockchip: Add cooling fan to ROCK 4D Nicolas Frattaroli
2026-04-26 7:23 ` Damon Ding
2026-04-27 17:17 ` Nicolas Frattaroli
2026-04-21 15:56 ` [PATCH v5 0/6] Add Rockchip RK3576 PWM Support Through MFPWM Jonathan Cameron
2026-04-22 11:31 ` Nicolas Frattaroli
2026-04-24 10:43 ` Uwe Kleine-König
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260503104624.459765-1-wbg@kernel.org \
--to=wbg@kernel.org \
--cc=alchark@gmail.com \
--cc=conor+dt@kernel.org \
--cc=damon.ding@rock-chips.com \
--cc=devicetree@vger.kernel.org \
--cc=heiko@sntech.de \
--cc=jonas@kwiboo.se \
--cc=kernel@collabora.com \
--cc=krzk+dt@kernel.org \
--cc=lee@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=nicolas.frattaroli@collabora.com \
--cc=robh@kernel.org \
--cc=ukleinek@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox