[PATCH RFC/RFT] pwm: meson: make full use of common clock framework
Heiner Kallweit
hkallweit1 at gmail.com
Wed Apr 5 13:43:54 PDT 2023
On 03.04.2023 23:01, Martin Blumenstingl wrote:
> Hello Heiner,
>
> On Tue, Mar 28, 2023 at 10:59 PM Heiner Kallweit <hkallweit1 at gmail.com> wrote:
>>
>> Newer versions of the PWM block use a core clock with external mux,
>> divider, and gate. These components either don't exist any longer in
>> the PWM block, or they are bypassed.
>> To minimize needed changes for supporting the new version, the internal
>> divider and gate should be handled by CCF too.
> That sounds like a good way forward to me
>
>> I didn't see a good way to split the patch, therefore it's somewhat
>> bigger. What it does:
>>
>> - The internal mux is handled by CCF already. Register also internal
>> divider and gate with CCF, so that we have one representation of the
>> input clock: [mux] parent of [divider] parent of [gate]
>>
>> - Now that CCF selects an appropriate mux parent, we don't need the
>> DT-provided default parent any longer. Accordingly we can also omit
>> setting the mux parent directly in the driver.
>>
>> - Instead of manually handling the pre-div divider value, let CCF
>> set the input clock. Targeted input clock frequency is
>> 0xffff * 1/period for best precision.
>>
>> - For the "inverted pwm disabled" scenario target an input clock
>> frequency of 1GHz. This ensures that the remaining low pulses
>> have minimum length.
> Unfortunately I didn't have much time today so I didn't get to reviewing this.
>
>> I don't have hw with the old PWM block, therefore I couldn't test this
>> patch. With the not yet included extension for the new PWM block
>> (channel->clock directly coming from get_clk(external_clk)) I didn't
>> notice any problem. My system uses PWM for the CPU voltage regulator
>> and for the SDIO 32kHz clock.
>>
>> Note: The clock gate in the old PWM block is permanently disabled.
>> This seems to indicate that it's not used by the new PWM block.
>>
>> I'd appreciate testing on the different platforms using the old
>> PWM block.
> I have tested basic functionality on a X96 Air (SM1 SoC, the version
> with Gbit/s PHY) where the VDDCPU regulator is PWM based and the 32kHz
> clock for wifi is generated by the PWM controller.
> The RTL8822CS SDIO wifi card is still working (firmware download,
> basic connectivity and connecting to an AP) and the system survived a
> minute of 100% CPU usage without hanging.
>
> For reference:
> # cat /sys/kernel/debug/pwm
> platform/ffd19000.pwm, 2 PWM devices
> pwm-0 (wifi32k ): requested enabled period: 30518 ns
> duty: 15259 ns polarity: normal
> pwm-1 ((null) ): period: 0 ns duty: 0 ns polarity: normal
>
> platform/ff807000.pwm, 2 PWM devices
> pwm-0 ((null) ): period: 0 ns duty: 0 ns polarity: normal
> pwm-1 ((null) ): period: 0 ns duty: 0 ns polarity: normal
>
> platform/ff802000.pwm, 2 PWM devices
> pwm-0 ((null) ): period: 0 ns duty: 0 ns polarity: normal
> pwm-1 (regulator-vddcpu ): requested enabled period: 1500 ns
> duty: 1125 ns polarity: normal
>
> # grep \.pwm /sys/kernel/debug/clk/clk_summary
> ffd19000.pwm#mux0 1 1 0 648999985
> 0 0 50000 Y
> ffd19000.pwm#div0 1 1 0
> 648999985 0 0 50000 Y
> ffd19000.pwm#gate0 1 1 0
> 648999985 0 0 50000 Y
> ffd19000.pwm#mux1 0 0 0 24000000
> 0 0 50000 Y
> ffd19000.pwm#div1 0 0 0 24000000
> 0 0 50000 Y
> ffd19000.pwm#gate1 0 0 0 24000000
> 0 0 50000 N
> ff807000.pwm#mux1 0 0 0 24000000
> 0 0 50000 Y
> ff807000.pwm#div1 0 0 0 24000000
> 0 0 50000 Y
> ff807000.pwm#gate1 0 0 0 24000000
> 0 0 50000 N
> ff807000.pwm#mux0 0 0 0 24000000
> 0 0 50000 Y
> ff807000.pwm#div0 0 0 0 24000000
> 0 0 50000 Y
> ff807000.pwm#gate0 0 0 0 24000000
> 0 0 50000 N
> ff802000.pwm#mux1 1 1 0 24000000
> 0 0 50000 Y
> ff802000.pwm#div1 1 1 0 24000000
> 0 0 50000 Y
> ff802000.pwm#gate1 1 1 0 24000000
> 0 0 50000 Y
> ff802000.pwm#mux0 0 0 0 24000000
> 0 0 50000 Y
> ff802000.pwm#div0 0 0 0 24000000
> 0 0 50000 Y
> ff802000.pwm#gate0 0 0 0 24000000
> 0 0 50000 N
>
> hdmi_pll is the parent of ffd19000.pwm#mux0 - before it was using the
> 24MHz XTAL.
> I haven't tested what happens when I change the video mode (that board
> is currently not connected to any HDMI screen).
>
That's a good point. AFAICS drivers/gpu/drm/meson/meson_vclk.c fiddles
with the hdmi clock registers. So we may want to avoid using hdmi_pll
or vid_pll as pwm parent. Below is a quick (and hopefully not too dirty)
follow-up patch disabling the hdmi/video clock parent.
Would be great if you can test this patch on top.
> Later this week I can also try this e.g. on my Odroid-C1 (with 32-bit
> Meson8b SoC) to verify that we don't have any 32-bit compatibility
> issues.
>
>
> Best regards,
> Martin
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 2b1debda4..81900e03a 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -348,7 +348,7 @@ static const struct pwm_ops meson_pwm_ops = {
};
static const char * const pwm_meson8b_parent_names[] = {
- "xtal", "vid_pll", "fclk_div4", "fclk_div3"
+ "xtal", "fclk_div4", "fclk_div3"
};
static const struct meson_pwm_data pwm_meson8b_data = {
@@ -357,7 +357,7 @@ static const struct meson_pwm_data pwm_meson8b_data = {
};
static const char * const pwm_gxbb_parent_names[] = {
- "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
+ "xtal", "fclk_div4", "fclk_div3"
};
static const struct meson_pwm_data pwm_gxbb_data = {
@@ -415,7 +415,7 @@ static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
};
static const char * const pwm_g12a_ee_parent_names[] = {
- "xtal", "hdmi_pll", "fclk_div4", "fclk_div3"
+ "xtal", "fclk_div4", "fclk_div3"
};
static const struct meson_pwm_data pwm_g12a_ee_data = {
@@ -470,6 +470,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
for (i = 0; i < meson->chip.npwm; i++) {
struct meson_pwm_channel *channel = &meson->channels[i];
+ static const u32 mux_parents_wo_vid[] = {0, 2, 3};
const char *clk_parent[1];
struct clk *mux_clk, *div_clk;
@@ -490,6 +491,10 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
channel->mux.table = NULL;
channel->mux.hw.init = &init;
+ /* 3 parents indicates that video clock parent should be omitted */
+ if (init.num_parents == 3)
+ channel->mux.table = mux_parents_wo_vid;
+
mux_clk = devm_clk_register(dev, &channel->mux.hw);
if (IS_ERR(mux_clk)) {
err = PTR_ERR(mux_clk);
--
2.40.0
More information about the linux-amlogic
mailing list