From: Biju Das <biju.das.jz@bp.renesas.com>
To: Thierry Reding <thierry.reding@gmail.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Philipp Zabel <p.zabel@pengutronix.de>
Cc: "Biju Das" <biju.das.jz@bp.renesas.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
linux-pwm@vger.kernel.org, devicetree@vger.kernel.org,
"Geert Uytterhoeven" <geert+renesas@glider.be>,
"Chris Paterson" <Chris.Paterson2@renesas.com>,
"Biju Das" <biju.das@bp.renesas.com>,
"Fabrizio Castro" <fabrizio.castro.jz@renesas.com>,
"Prabhakar Mahadev Lad" <prabhakar.mahadev-lad.rj@bp.renesas.com>,
linux-renesas-soc@vger.kernel.org
Subject: [PATCH v18 0/4] Add support for RZ/G2L GPT
Date: Tue, 20 Feb 2024 19:43:14 +0000 [thread overview]
Message-ID: <20240220194318.672443-1-biju.das.jz@bp.renesas.com> (raw)
RZ/G2L General PWM Timer (GPT) composed of 8 channels with 32-bit timer
(GPT32E). It supports the following functions
* 32 bits × 8 channels
* Up-counting or down-counting (saw waves) or up/down-counting
(triangle waves) for each counter.
* Clock sources independently selectable for each channel
* Two I/O pins per channel
* Two output compare/input capture registers per channel
* For the two output compare/input capture registers of each channel,
four registers are provided as buffer registers and are capable of
operating as comparison registers when buffering is not in use.
* In output compare operation, buffer switching can be at crests or
troughs, enabling the generation of laterally asymmetric PWM waveforms.
* Registers for setting up frame cycles in each channel (with capability
for generating interrupts at overflow or underflow)
* Generation of dead times in PWM operation
* Synchronous starting, stopping and clearing counters for arbitrary
channels
* Starting, stopping, clearing and up/down counters in response to input
level comparison
* Starting, clearing, stopping and up/down counters in response to a
maximum of four external triggers
* Output pin disable function by dead time error and detected
short-circuits between output pins
* A/D converter start triggers can be generated (GPT32E0 to GPT32E3)
* Enables the noise filter for input capture and external trigger
operation
This patch series aims to add basic pwm support for RZ/G2L GPT driver
by creating separate logical channels for each IOs.
v17->v18:
* Added units.h for KILO macro.
* Replaced RZG2L_GTCCR{A,B}->RZG2L_GTCCR(i)
* Introduced macros RZG2L_GTIOR_{GTIOx,OxE} to handle subchannels.
* Replaced RZG2L_IS_IOB()->rzg2l_gpt_subchannel()
* Replaced the cache period->period_cycles.
* Updated rzg2l_gpt_is_ch_enabled() to return early if counter is not
running.
* Updated calculate_period_or_duty() for avoiding overflows.
* Updated rzg2l_gpt_calculate_pv_or_dc() with simplified calculation for
DIV64_U64_ROUND_UP() and dropped the cast for U32_MAX in min_t.
* Replaced mul_u64_u32_div->rzg2l_gpt_mul_u64_u64_div_u64() helper.
* Dropped pm pointer from struct rzg2l_gpt_driver() and simplified clk
handling in probe().
* Updated copyright from 2023->2024.
* Moved bitpos near to the user in patch#4.
v16->v17:
* Added ret = dev_err_probe() to avoid return success in probe().
* Dropped unneeded MODULE_ALIAS().
* Dropped .owner from struct rzg2l_gpt_ops.
* Fixed build issue reported by kernel test robot <lkp@intel.com> by
replacing DIV_ROUND_UP()->DIV64_U64_ROUND_UP() in
rzg2l_gpt_calculate_pv_or_dc().
* Added max_val to struct rzg2l_gpt_chip to compute maximum period
supported by the HW in probe() and limit its value in apply() to
avoid 64-bit overflow with computation.
* Added helper function calculate_period_or_duty() to avoid losing
precision for smaller period/duty cycle values
((2^32 * 10^9 << 2) < 2^64), by not processing the rounded values.
* Replaced mul_u64_u64_div_u64()->mul_u64_u32_div() as the former is
giving warnings with CONFIG_PWM_DEBUG enabled for very high values.
eg:
echo "###### Medium setting 11000 sec = 3hours ##"
echo 11000000000000 > /sys/class/pwm/$PWMCHIP/pwm${IO_1}/period
echo 5500000000000 > /sys/class/pwm/$PWMCHIP/pwm${IO_1}/duty_cycle
dumpgptreg
echo "###### High setting##"
echo 43980465100800 > /sys/class/pwm/$PWMCHIP/pwm${IO_1}/period
echo 23980465100800 > /sys/class/pwm/$PWMCHIP/pwm${IO_1}/duty_cycle
dumpgptreg
with mul_u64_u32_div():
###### Medium setting 11000 sec = 3hours ##
Read at address 0x10048464 (0xffffb9426464): 0x400746FE
Read at address 0x1004844C (0xffff8fdfb44c): 0x2003A37F
Read at address 0x1004842C (0xffff9855b42c): 0x05000001
###### High setting##
Read at address 0x10048464 (0xffff9101b464): 0xFFFFFFFF
Read at address 0x1004844C (0xffffaee0544c): 0x8B95AD77
Read at address 0x1004842C (0xffffbbc8a42c): 0x05000001
with mul_u64_u64_div_u64():
###### Medium setting 11000 sec = 3hours ##
Read at address 0x10048464 (0xffffb3185464): 0x400746FE
Read at address 0x1004844C (0xffff81ebb44c): 0x2003A37F
Read at address 0x1004842C (0xffff904fd42c): 0x05000001
######[ 304.213944] pwm-rzg2l-gpt 10048000.pwm: .apply is not idempotent (ena=1 pol=0 5500000000000/43980352512000) -> (ena=1 pol=0 5500000000000/43980239923200)
High setting##
[ 304.230854] pwm-rzg2l-gpt 10048000.pwm: .apply is not idempotent (ena=1 pol=0 23980465100800/43980352512000) -> (ena=1 pol=0 23980465100800/43980239923200)
Read at address 0x10048464 (0xffffb5bb3464): 0xFFFFAA19
Read at address 0x1004844C (0xffff99b8c44c): 0x8B95AD77
Read at address 0x1004842C (0xffffbba2342c): 0x05000001
v15->v16:
* Replaced the macro DIV_ROUND_UP_ULL->DIV64_U64_ROUND_UP
* Added DIV_ROUND_UP in rzg2l_gpt_calculate_pv_or_dc() to avoid loss of
precision.
* Replaced min->min_t() in rzg2l_gpt_calculate_pv_or_dc().
* Added a comment for rzg2l_gpt_config()
* Replaced mul_u64_u32_div()->mul_u64_u64_div_u64() in rzg2l_gpt_config()
* Fixed the logical condition related to counter stop in
rzg2l_gpt_config().
* Dropped pm_runtime_resume_*() from rzg2l_gpt_config() as it is managed
by rzg2l_gpt_apply().
* Moved pm_runtime_resume_*() from rzg2l_gpt_{en,dis}able() to
rzg2l_gpt_apply().
v14->v15:
* Added enable_count and ch_en_bits variables to struct rzg2l_gpt_chip
based on feedback for pwm_mtu3 driver.
* Updated copyright header and commit description by replacing "This patch
adds"-> "Add"
* Replaced macro RZG2L_GET_CH_INDEX->RZG2L_GET_CH and replaced ch_index->ch
throughout
* rzg2l_gpt_{enable,disable}() enables/disables PWM based on the
enable_count.
* Replaced pm_runtime_get_sync->pm_runtime_resume_and_get and propogated
the error in rzg2l_gpt_get_state() and rzg2l_gpt_config()
* Reduced variable scope in rzg2l_gpt_get_state() by moving most of variables
inside the if statement.
* Updated rzg2l_gpt_get_state() by moving duty > period check
inside the top if block.
* Added helper functions rzg2l_gpt_calculate_pv_or_dc()to simplify config.
Also Improved the logic in rzg2l_gpt_calculate_pv_or_dc() by using
min(period_or_duty_cycle >> (2 * prescale), (u64)U32_MAX);
* Updated rzg2l_gpt_get_state() by moving duty > period check
inside the top if block.
* Simplified rzg2l_gpt_config() for updating registers
* Dropped pm_runtime_get_sync() and used bitmap variable "ch_en_bits"
to make balanced PM usage count in rzg2l_gpt_reset_assert_pm_disable()
For case were unbind is called before apply where pwm is enabled by
bootloader.
* Added error check for clk_rate_exclusive_get() and clk_get_rate() in
probe().
* Dropped prescale from struct rzg2l_gpt_chip.
* Replaced of_match_ptr(rzg2l_gpt_of_table)->rzg2l_gpt_of_table in struct
rzg2l_gpt_driver
* Updated commit description of patch#4 by replacing "This patch add"->
"Add".
v13->v14:
* Moved the patch from series[1] to here.
[1] https://lore.kernel.org/linux-renesas-soc/20221215205843.4074504-1-biju.das.jz@bp.renesas.com/T/#t
* Add Rb tag from Rob for patch#2
* Removed parenthesis for RZG2L_MAX_HW_CHANNELS and RZG2L_CHANNELS_PER_IO
* Removed duty_cycle variable from struct rzg2l_gpt_chip and added comment
for cache for prescale variable.
* Fixed a bug in rzg2l_gpt_cntr_need_stop().
* Reordered rzg2l_gpt_config() just above apply()
* Replaced pwm_is_enabled()->pwm->state.enabled in config
* Replaced pm_runtime_resume_and_get with unconditional pm_runtime_get_sync()
in config().
* Restored duty_cycle > period check in rzg2l_gpt_get_state().
* Added error check for clk_prepare_enable() in probe() and propagating error
to the caller for pm_runtime_resume()
* clk_get_rate() is called after enabling the clock and clk_rate_exclusive_get()
* Simplified rzg2l_gpt_probe() by removing bitmap variables.
* Added pm_runtime_idle() to suspend the device during probe.
* Moved overflow condition check from config->probe().
* Simplified rzg2l_gpt_reset_assert_pm_disable().
* Removed the parenthesis for RZG2L_MAX_POEG_GROUPS.
* Renamed rzg2l_gpt_parse_properties()->rzg2l_gpt_poeg_init() as it not only parse
the properties but also implements the needed register writes.
* Added acomment here about the purpose of the function rzg2l_gpt_poeg_init()
* Removed magic numbers from rzg2l_gpt_poeg_init()
* Fixed resource leak in rzg2l_gpt_poeg_init().
v12->v13:
* Added test logs in [1] below
* Replaced Kconfig dependency from ARCH_RENESAS->ARCH_RZG2L
* Sorted #include <linux/limits.h> alphabetically
* Added a comment for mutex_lock to fix check patch warning
* Replaced data type of duty_cycle from unsigned int->u32 as
the maximum value stored is U32_MAX.
* Improved rzg2l_gpt_config() by removing unwanted duty_cycle related code.
* Improved rzg2l_gpt_get_state() by setting "val = rzg2l_gpt->duty_cycle[pwm->hwpwm];",
and factor "tmp = NSEC_PER_SEC * (u64)val;" out of the if-statement.
* Started using DEFINE_RUNTIME_DEV_PM_OPS(), and dropped __maybe_unused
from the callbacks.
v11->v12:
* Added return code for get_state()
* Cache duty cycle/prescale as the driver cannot read the current duty
cycle/prescale from the hardware if the hardware is disabled. Cache the
last programmed duty cycle/prescale value to return in that case.
* Updated rzg2l_gpt_enable to enable the clocks.
* Updated rzg2l_gpt_disable to disable the clocks.
* Updated rzg2l_gpt_config() to cache duty cucle/prescale value
* Updated rzg2l_gpt_get_state to use cached value of duty cycle/prescale,If the PWM
is disabled.
* Simplified rzg2l_gpt_apply()
* Added comments in rzg2l_gpt_reset_assert_pm_disable()
v10->v11:
* Used bitmap_zero for initializing bitmap varable.
* Fixed clock imbalance during remove for the case bootloader turning
on PWM and module unload is called just after the boot.
* Fixed over flow condition in get_state() for a prescale value of 2 & more.
* Improved rzg2l_gpt_cntr_need_stop() based on prescale as it is the
only runtime variable.
* Added array for Cache variables state_period and prescale
* Probe caches the prescale value set by the bootloader.
* Updated rzg2l_gpt_config() to make use of array variables.
v9->v10:
* Updated the example gpt4: pwm@10048400-> gpt: pwm@10048000
* Keep Rb tag from Rob as the above change is trivial one.
* Updated the error handling in probe(), clk_disable_unprepare called
on the error path.
* Removed ch_en array and started using bitmask instead.
v8->v9:
* Added Rb tag from Rob.
* deassert after devm_clk_get() to avoid reset stays deasserted,in case
clk_get() fails.
* Removed ch_offs from struct rzg2l_gpt_chip and use macro instead.
* Updated error handling in probe()
v7->v8:
* Removed Rb tags from Rob and Geert as it modelled as single GPT
device handling multiple channels.
* Updated description
* Updated interrupts and interrupt-names properties
* Updated binding example
* Modelled as single PWM device handling multiple channels
* Replaced shared reset->devm_reset_control_get_exclusive()
* Added PM runtime callbacks
* Updated PM handling and removed "pwm_enabled_by_bootloader" variable
* Replaced iowrite32->writel and ioread32->readl
* Updated prescale calculation
* Introduced rzg2l_gpt_is_ch_enabled for checking enable status on both
IO's
* Moved enable/disable output pins from config->enable/disable.
* Added rzg2l_gpt_cntr_need_stop() for caching prescalar/mode values.
v6->v7:
* Added the comment for cacheing rzg2l_gpt->state_period.
* Fixed boundary values for pv and dc.
* Added comment for modifying mode, prescaler, timer counter and buffer enable
registers.
* Fixed buffer overflow in get_state()
* Removed unnecessary assignment of state->period value in get_state().
* Fixed state->duty_cycle value in get_state().
* Added a limitation for disabling the channels, when both channels used
v5->v6:
* Updated macros RZG2L_GTIOR_GTIOB_OUT_HI_END_TOGGLE_CMP_MATCH and
RZG2L_GTIOR_GTIOB_OUT_LO_END_TOGGLE_CMP_MATCH with computation
involving FIELD_PREP macro.
* Removed struct rzg2l_gpt_phase and started using RZG2L_GTCCR macro
for duty_offset.
* replaced misnomer real_period->state_period.
* Added handling for values >= (1024 << 32) for both period
and duty cycle.
* Added comments for pwm {en,dis}abled by bootloader during probe.
v4->v5:
* Added Hardware manual details
* Replaced the comment GTCNT->Counter
* Removed the macros RZG2L_GPT_IO_PER_CHANNEL and chip.npwm directly
used in probe.
* Removed the unsed macro RZG2L_GTPR_MAX_VALUE
* Added driver prefix for the type name and the variable.
* Initialization of per_channel data moved from request->probe.
* Updated clr parameter for rzg2l_gpt_modify for Start count.
* Started using mutex and usage_count for handling shared
period and prescalar for the 2 channels.
* Updated the comment cycle->period.
* Removed clk_disable from rzg2l_gpt_reset_assert_pm_disable()
* Replaced pc->rzg2l_gpt.
* Updated prescale calculation.
* Moved pm_runtime_{get_sync,put} from {request,free}->{enable,disable}
* Removed platform_set_drvdata as it is unused
* Removed the variable pwm_enabled_by_bootloader
* Added dev_err_probe in various probe error path.
* Added an error message, if devm_pwmchip_add fails.
v3->v4:
* Changed the local variable type i from u16->u8 and prescaled_period_
cycles from u64->u32 in calculate_prescale().
* Replaced mul_u64_u64_div_u64()->mul_u64_u32_div()
* Dropped the comma after the sentinel.
* Add a variable to track pwm enabled by bootloader and added comments
in probe().
* Removed unnecessary rzg2l_gpt_reset_assert_pm_disable() from probe.
* Replaced devm_clk_get()->devm_clk_get_prepared()
* Removed devm_clk_get_optional_enabled()
v2->v3:
* Added Rb tag from Rob for the bindings.
* Updated limitation section
* Added prefix "RZG2L_" for all macros
* Modified prescale calculation
* Removed pwm_set_chip_data
* Updated comment related to modifying Mode and Prescaler
* Updated setting of prescale value in rzg2l_gpt_config()
* Removed else branch from rzg2l_gpt_get_state()
* removed the err label from rzg2l_gpt_apply()
* Added devm_clk_get_optional_enabled() to retain clk on status,
in case bootloader turns on the clk of pwm.
* Replaced devm_reset_control_get_exclusive->devm_reset_control_get_shared
as single reset shared between 8 channels.
v1->v2:
* Added '|' after 'description:' to preserve formatting.
* Removed description for pwm_cells as it is common property.
* Changed the reg size in example from 0xa4->0x100
* Added Rb tag from Geert for bindings.
* Added Limitations section
* dropped "_MASK" from the define names.
* used named initializer for struct phase
* Added gpt_pwm_device into a flexible array member in rzg2l_gpt_chip
* Revised the logic for prescale
* Added .get_state callback
* Improved error handling in rzg2l_gpt_apply
* Removed .remove callback
* Tested the driver with PWM_DEBUG enabled.
RFC->v1:
* Added Description in binding patch
* Removed comments from reg and clock
* replaced rzg2l_gpt_write_mask()->rzg2l_gpt_modify()
* Added rzg2l_gpt_read() and updated macros
* Removed dtsi patches, will send it separately
RFC:
* https://lore.kernel.org/linux-renesas-soc/20220430075915.5036-1-biju.das.jz@bp.renesas.com/T/#t
Biju Das (4):
dt-bindings: pwm: Add RZ/G2L GPT binding
dt-bindings: pwm: rzg2l-gpt: Document renesas,poegs property
pwm: Add support for RZ/G2L GPT
pwm: rzg2l-gpt: Add support for gpt linking with poeg
.../bindings/pwm/renesas,rzg2l-gpt.yaml | 401 +++++++++++
drivers/pwm/Kconfig | 11 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-rzg2l-gpt.c | 641 ++++++++++++++++++
4 files changed, 1054 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/renesas,rzg2l-gpt.yaml
create mode 100644 drivers/pwm/pwm-rzg2l-gpt.c
base-commit: a4aebe936554dac6a91e5d091179c934f8325708
--
2.25.1
next reply other threads:[~2024-02-20 19:43 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-20 19:43 Biju Das [this message]
2024-02-20 19:43 ` [PATCH v18 1/4] dt-bindings: pwm: Add RZ/G2L GPT binding Biju Das
2024-02-20 19:43 ` [PATCH v18 2/4] dt-bindings: pwm: rzg2l-gpt: Document renesas,poegs property Biju Das
2024-02-20 19:43 ` [PATCH v18 3/4] pwm: Add support for RZ/G2L GPT Biju Das
2024-03-12 7:20 ` Uwe Kleine-König
2024-03-12 8:11 ` Geert Uytterhoeven
2024-03-12 9:27 ` Uwe Kleine-König
2024-03-14 18:10 ` Biju Das
2024-03-14 22:33 ` Uwe Kleine-König
2024-03-15 7:19 ` Biju Das
2024-02-20 19:43 ` [PATCH v18 4/4] pwm: rzg2l-gpt: Add support for gpt linking with poeg Biju Das
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=20240220194318.672443-1-biju.das.jz@bp.renesas.com \
--to=biju.das.jz@bp.renesas.com \
--cc=Chris.Paterson2@renesas.com \
--cc=biju.das@bp.renesas.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fabrizio.castro.jz@renesas.com \
--cc=geert+renesas@glider.be \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=p.zabel@pengutronix.de \
--cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
--cc=robh+dt@kernel.org \
--cc=thierry.reding@gmail.com \
--cc=u.kleine-koenig@pengutronix.de \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.