RE: [PATCH v3 2/4] pwm: Add support for RZ/V2M PWM driver

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

 



Hi Uwe,

> Subject: RE: [PATCH v3 2/4] pwm: Add support for RZ/V2M PWM driver
> 
> Hi Uwe,
> 
> Thanks for the feedback.
> 
> > Subject: Re: [PATCH v3 2/4] pwm: Add support for RZ/V2M PWM driver
> >
> > Hello,
> >
> > now I come around to review your driver. Sorry that it took so long, I
> > was busy with other stuff.
> >
> > On Tue, Dec 13, 2022 at 06:58:25PM +0000, Biju Das wrote:
> > > The RZ/V2{M, MA} PWM Timer supports the following functions:
> > >
> > >  * The PWM has 24-bit counters which operate at PWM_CLK (48 MHz).
> > >  * The frequency division ratio for internal counter operation is
> > >    selectable as PWM_CLK divided by 1, 16, 256, or 2048.
> > >  * The period as well as the duty cycle is adjustable.
> > >  * The low-level and high-level order of the PWM signals can be
> > >    inverted.
> > >  * The duty cycle of the PWM signal is selectable in the range from
> > >    0 to 100%.
> > >  * The minimum resolution is 20.83 ns.
> > >  * Three interrupt sources: Rising and falling edges of the PWM signal
> > >    and clearing of the counter
> > >  * Counter operation and the bus interface are asynchronous and both
> > >    can operate independently of the magnitude relationship of the
> > >    respective clock periods.
> > >
> > > Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
> > > ---
> > > v2->v3:
> > >  * Added return code for rzv2m_pwm_get_state()
> > >  * Added comment in rzv2m_pwm_reset_assert_pm_disable()
> > > v1->v2:
> > >  * Replaced
> > > devm_reset_control_get_optional_shared->devm_reset_control_get_share
> > > d
> > > ---
> > >  drivers/pwm/Kconfig     |  11 ++
> > >  drivers/pwm/Makefile    |   1 +
> > >  drivers/pwm/pwm-rzv2m.c | 398
> > > ++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 410 insertions(+)
> > >  create mode 100644 drivers/pwm/pwm-rzv2m.c
> > >
> > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index
> > > dae023d783a2..31cdc9dae3c5 100644
> > > --- a/drivers/pwm/Kconfig
> > > +++ b/drivers/pwm/Kconfig
> > > @@ -473,6 +473,17 @@ config PWM_RENESAS_TPU
> > >  	  To compile this driver as a module, choose M here: the module
> > >  	  will be called pwm-renesas-tpu.
> > >
> > > +config PWM_RZV2M
> > > +       tristate "Renesas RZ/V2M PWM support"
> > > +       depends on ARCH_R9A09G011 || COMPILE_TEST
> > > +       depends on HAS_IOMEM
> > > +       help
> > > +         This driver exposes the PWM controller found in Renesas
> > > +         RZ/V2M like chips through the PWM API.
> > > +
> > > +         To compile this driver as a module, choose M here: the module
> > > +         will be called pwm-rzv2m.
> > > +
> > >  config PWM_ROCKCHIP
> > >  	tristate "Rockchip PWM support"
> > >  	depends on ARCH_ROCKCHIP || COMPILE_TEST diff --git
> > > a/drivers/pwm/Makefile b/drivers/pwm/Makefile index
> > > 7bf1a29f02b8..a95aabae9115 100644
> > > --- a/drivers/pwm/Makefile
> > > +++ b/drivers/pwm/Makefile
> > > @@ -43,6 +43,7 @@ obj-$(CONFIG_PWM_PXA)		+= pwm-pxa.o
> > >  obj-$(CONFIG_PWM_RASPBERRYPI_POE)	+= pwm-raspberrypi-poe.o
> > >  obj-$(CONFIG_PWM_RCAR)		+= pwm-rcar.o
> > >  obj-$(CONFIG_PWM_RENESAS_TPU)	+= pwm-renesas-tpu.o
> > > +obj-$(CONFIG_PWM_RZV2M)		+= pwm-rzv2m.o
> > >  obj-$(CONFIG_PWM_ROCKCHIP)	+= pwm-rockchip.o
> > >  obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
> > >  obj-$(CONFIG_PWM_SIFIVE)	+= pwm-sifive.o
> > > diff --git a/drivers/pwm/pwm-rzv2m.c b/drivers/pwm/pwm-rzv2m.c new
> > > file mode 100644 index 000000000000..80fb3523026d
> > > --- /dev/null
> > > +++ b/drivers/pwm/pwm-rzv2m.c
> > > @@ -0,0 +1,398 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Renesas RZ/V2M PWM Timer (PWM) driver
> > > + *
> > > + * Copyright (C) 2022 Renesas Electronics Corporation
> > > + *
> > > + * Hardware manual for this IP can be found here
> > > + *
> > > +https://www.renesas.com/in/en/document/mah/rzv2m-users-manual-hardw
> > > +ar
> > > +e?language=en
> > > + *
> > Please document the hardware properties here in a "Limitations"
> > paragraph similar to e.g. pwm-sl28cpld.c. The idea is to get the
> > information about how the hardware behaves on .apply (are there
> > glitches? Can a mixed period happen that has the previous period but
> > the new duty_cycle? Or maybe duty_cycle and period are shadowed until
> > the currently running period ends, but polarity takes effect immediately?
> > etc. pp) when doing
> >
> > 	sed -rn '/Limitations:/,/\*\/?$/p' drivers/pwm/pwm-rzv2m.c
> 
> I have added below limitations now
> 
> * Limitations:
>  * - If the PWMLOW value is changed during PWM operation, the changed
>  *   value is reflected in the next PWM cycle.
>  * - The duty cycle can be changed only by modifying the PWMLOW register
>  *   value and changing the pulse width at low level. The duty cycle becomes
>  *   0% for the low width when the value of the PWMLOW register is 0x0h
>  *   and 100% for the low width when the value of the PWMLOW > PWMCYC.
>  * - To change the setting value of the PWM cycle setting register
>  *   (PWMm_PWMCYC), set the PWME bit of the PWM control register
> (PWMm_PWMCTR)
>  *   to 0b and stop the counter operation. If it is changed during counter
>  *   operation, PWM output may not be performed correctly.
>  * - The registers other than the PWM interrupt register (PWMINT) are always
>  *   synchronized with PWM_CLK at regular intervals. It takes some time
>  *   (Min: 2 × PCLK + 4 × PWM_CLK to Max: 6 × PCLK + 9 × PWM_CLK) for the
>  *   value set in the register to be reflected in the PWM circuit because
>  *   there is a synchronizer between the register and the PWM circuit.
> 
> > > +	rzv2m_pwm->chip.dev = &pdev->dev;
> > > +	rzv2m_pwm->chip.ops = &rzv2m_pwm_ops;
> > > +	rzv2m_pwm->chip.npwm = 1;
> > > +	ret = devm_pwmchip_add(&pdev->dev, &rzv2m_pwm->chip);
> > > +	if (ret) {
> > > +		dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
> > > +		goto clk_disable;
> >
> > If you fail here, rzv2m_pwm_reset_assert_pm_disable is called which
> > calls pm_runtime_set_suspended(). I assume that results in
> > rzv2m_pwm_pm_runtime_suspend() being called and to the clks are
> > already disabled?

I have restructured the probe() as below and tested various scenarios, It looks ok to me.
Please let me know, if you have any suggestions.

static int rzv2m_pwm_probe(struct platform_device *pdev)
{
...
...
	pm_runtime_enable(&pdev->dev);
	ret = reset_control_deassert(rzv2m_pwm->rstc);
	if (ret) {
		dev_err_probe(&pdev->dev, ret,
			      "cannot deassert reset control\n");
		goto pm_clk_disable;
	}

	rzv2m_pwm->chip.dev = &pdev->dev;
	/*
	 *  We need to keep the clock on, in case the bootloader has enabled the
	 *  PWM and is running during probe().
	 */
	if (rzv2m_pwm_is_ch_enabled(rzv2m_pwm))
		pm_runtime_get_sync(&pdev->dev);

	ret = devm_add_action_or_reset(&pdev->dev,
				       rzv2m_pwm_reset_assert_pm_disable,
				       rzv2m_pwm);
	ret = -EINVAL;
	if (ret < 0)
		goto channel_disable;

	rzv2m_pwm->chip.ops = &rzv2m_pwm_ops;
	rzv2m_pwm->chip.npwm = 1;
	ret = devm_pwmchip_add(&pdev->dev, &rzv2m_pwm->chip);
	if (ret) {
		dev_err_probe(&pdev->dev, ret, "failed to add PWM chip\n");
		goto channel_disable;
	}

	return 0;

pm_clk_disable:
	pm_runtime_disable(&pdev->dev);
	pm_runtime_set_suspended(&pdev->dev);
channel_disable:
	if (rzv2m_pwm_is_ch_enabled(rzv2m_pwm))
		rzv2m_pwm_modify(rzv2m_pwm, RZV2M_PWMCTR, RZV2M_PWMCTR_PWME, 0);

	clk_disable_unprepare(rzv2m_pwm->pwm_clk);
	clk_disable_unprepare(rzv2m_pwm->apb_clk);
	return ret;
}

Test cases:

1) PWM-disabled by bootloader on case
----------------------------------
root@rzv2m:~# dmesg | grep pwm8
[    3.739239] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.747804] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
root@rzv2m:~# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffb55b6434): 0x00000801 --> BIT5 PWM8 clk
Read at address  0xA4010400 (0xffff98c3f400): 0x00000000 --> BIT2 PWM8 Channel enable

root@rzv2m:~# cd /sys/bus/platform/drivers/pwm-rzv2m
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# echo a4010400.pwm > unbind
[   84.025155] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[   84.039214] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
[   84.060958] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[   84.074759] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffbbd5e434): 0x00000801
Read at address  0xA4010400 (0xffff8a796400): 0x00000000
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m#

root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# echo a4010400.pwm > bind
[  139.273250] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[  139.299582] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffa0f28434): 0x00000801
Read at address  0xA4010400 (0xffffa1b66400): 0x00000000
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m#

2) PWM-enabled by bootloader on case
---------------------------------
root@rzv2m:~# dmesg | grep pwm8
[    3.738742] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
root@rzv2m:~# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffa68de434): 0x00000811
Read at address  0xA4010400 (0xffff9eaad400): 0x00000003

root@rzv2m:~# cd /sys/bus/platform/drivers/pwm-rzv2m
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# echo a4010400.pwm > unbind
[  125.579970] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffbb4db434): 0x00000801
Read at address  0xA4010400 (0xffffa7194400): 0x00000000

root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# echo a4010400.pwm > bind
[  170.837264] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[  170.863046] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffff91fd4434): 0x00000801
Read at address  0xA4010400 (0xffff91010400): 0x00000000
root@rzv2m:/sys/bus/platform/drivers/pwm-rzv2m#

3) Error case 1:
---------------
        ret = reset_control_deassert(rzv2m_pwm->rstc);
+       ret = -EINVAL;

PWM off/ON during boot:
[    3.709913] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.716953] pwm-rzv2m a4010400.pwm: error -EINVAL: cannot deassert reset control
[    3.725186] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
[    3.732425] pwm-rzv2m: probe of a4010400.pwm failed with error -22

root@rzv2m:~# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffffa5ddc434): 0x00000801
Read at address  0xA3500614 (0xffffb5800614): 0x00000000

4) Error case 2:
---------------
	ret = devm_add_action_or_reset(&pdev->dev,
				       rzv2m_pwm_reset_assert_pm_disable,
				       rzv2m_pwm);
+	ret = -EINVAL;

PWM on/off during boot:
[    3.714182] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.721798] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
[    3.730662] pwm-rzv2m: probe of a4010400.pwm failed with error -22
[    3.739956] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.755238] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF

root@rzv2m:~# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffff92dfc434): 0x00000801
Read at address  0xA4010400 (0xffffa7021400): 0x00000000

5) Error case 3:
----------------
	ret = devm_pwmchip_add(&pdev->dev, &rzv2m_pwm->chip);
+	ret = -EINVAL;
	
PWM on/off during boot:
[    3.712732] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.720408] pwm-rzv2m a4010400.pwm: error -EINVAL: failed to add PWM chip
[    3.731991] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF
[    3.739237] pwm-rzv2m: probe of a4010400.pwm failed with error -22
[    3.754369] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk ON
[    3.761684] rzg2l-cpg a3500000.clock-controller: CLK_ON 1076/pwm8_clk OFF

root@rzv2m:~# /pwm-clk-dump.sh
Read at address  0xA3500434 (0xffff92dfc434): 0x00000801
Read at address  0xA4010400 (0xffffa7021400): 0x00000000

Cheers,
Biju




[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux