[PATCH v7 4/9] pwm: rzg2l-gpt: Add prescale_mult variable to struct rzg2l_gpt_info

From: Biju

Date: Mon Aug 24 2026 - 09:01:04 EST


From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>

RZ/G3E GPT IP has prescale factor power of 2 where as that of RZ/G2L is 4.
Add prescale_mult variable to struct rzg2l_gpt_info for handling this
difference.

Reviewed-by: Tommaso Merciai <tommaso.merciai.xr@xxxxxxxxxxxxxx>
Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
---
v6->v7:
* No change.
v5->v6:
* Dropped extra parameter rzg2l_gpt from rzg2l_gpt_calculate_prescale()
in rzg2l_gpt_round_waveform_tohw().
* Updated comment in rzg2l_gpt_calculate_period_or_duty().
v4->v5:
* No change.
v3->v4:
* Updated commit header and description
* Renamed prescale_pow_of_two_mult_factor->prescale_mult
v2->v3:
* No change.
v1->v2:
* Collected tag.
---
drivers/pwm/pwm-rzg2l-gpt.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/pwm/pwm-rzg2l-gpt.c b/drivers/pwm/pwm-rzg2l-gpt.c
index da2645a42608..fc77c27f0a97 100644
--- a/drivers/pwm/pwm-rzg2l-gpt.c
+++ b/drivers/pwm/pwm-rzg2l-gpt.c
@@ -79,6 +79,7 @@

struct rzg2l_gpt_info {
u32 gtcr_tpcs;
+ u8 prescale_mult;
};

struct rzg2l_gpt_chip {
@@ -220,24 +221,29 @@ static void rzg2l_gpt_disable(struct rzg2l_gpt_chip *rzg2l_gpt,
static u64 rzg2l_gpt_calculate_period_or_duty(struct rzg2l_gpt_chip *rzg2l_gpt,
u32 val, u8 prescale)
{
+ const struct rzg2l_gpt_info *info = rzg2l_gpt->info;
u64 tmp;

/*
- * The calculation doesn't overflow an u64 because prescale ≤ 5 and so
- * tmp = val << (2 * prescale) * NSEC_PER_MSEC
+ * The calculation doesn't overflow a u64 because,
+ * prescale ≤ 5 for info->prescale_mult = 2 and so
+ * tmp = val << (info->prescale_mult * prescale) * NSEC_PER_MSEC
* < 2^32 * 2^10 * 10^6
* < 2^32 * 2^10 * 2^20
* = 2^62
*/
- tmp = (u64)val << (2 * prescale);
+ tmp = (u64)val << (info->prescale_mult * prescale);
tmp *= NSEC_PER_MSEC;

return DIV64_U64_ROUND_UP(tmp, rzg2l_gpt->rate_khz);
}

-static u32 rzg2l_gpt_calculate_pv_or_dc(u64 period_or_duty_cycle, u8 prescale)
+static u32 rzg2l_gpt_calculate_pv_or_dc(const struct rzg2l_gpt_info *info,
+ u64 period_or_duty_cycle, u8 prescale)
{
- return min_t(u64, DIV_ROUND_DOWN_ULL(period_or_duty_cycle, 1 << (2 * prescale)),
+ return min_t(u64,
+ DIV_ROUND_DOWN_ULL(period_or_duty_cycle,
+ 1 << (info->prescale_mult * prescale)),
U32_MAX);
}

@@ -247,6 +253,7 @@ static int rzg2l_gpt_round_waveform_tohw(struct pwm_chip *chip,
void *_wfhw)
{
struct rzg2l_gpt_chip *rzg2l_gpt = to_rzg2l_gpt_chip(chip);
+ const struct rzg2l_gpt_info *info = rzg2l_gpt->info;
struct rzg2l_gpt_waveform *wfhw = _wfhw;
bool is_small_second_period = false;
u8 ch = RZG2L_GET_CH(pwm->hwpwm);
@@ -287,7 +294,7 @@ static int rzg2l_gpt_round_waveform_tohw(struct pwm_chip *chip,
wfhw->prescale = rzg2l_gpt_calculate_prescale(period_ticks);
}

- wfhw->gtpr = rzg2l_gpt_calculate_pv_or_dc(period_ticks, wfhw->prescale);
+ wfhw->gtpr = rzg2l_gpt_calculate_pv_or_dc(info, period_ticks, wfhw->prescale);
if (is_small_second_period) {
wfhw->gtccr = 0;
return 1;
@@ -296,7 +303,7 @@ static int rzg2l_gpt_round_waveform_tohw(struct pwm_chip *chip,
duty_ticks = mul_u64_u64_div_u64(wf->duty_length_ns, rzg2l_gpt->rate_khz, NSEC_PER_MSEC);
if (duty_ticks > period_ticks)
duty_ticks = period_ticks;
- wfhw->gtccr = rzg2l_gpt_calculate_pv_or_dc(duty_ticks, wfhw->prescale);
+ wfhw->gtccr = rzg2l_gpt_calculate_pv_or_dc(info, duty_ticks, wfhw->prescale);

return 0;
}
@@ -342,9 +349,9 @@ static int rzg2l_gpt_read_waveform(struct pwm_chip *chip,
return 0;
}

-static u64 rzg2l_gpt_calculate_cycles(u32 value, u8 prescale)
+static u64 rzg2l_gpt_calculate_cycles(u32 value, u8 mult, u8 prescale)
{
- return (u64)value << (2 * prescale);
+ return (u64)value << (mult * prescale);
}

static int rzg2l_gpt_write_waveform(struct pwm_chip *chip,
@@ -352,6 +359,7 @@ static int rzg2l_gpt_write_waveform(struct pwm_chip *chip,
const void *_wfhw)
{
struct rzg2l_gpt_chip *rzg2l_gpt = to_rzg2l_gpt_chip(chip);
+ const struct rzg2l_gpt_info *info = rzg2l_gpt->info;
const struct rzg2l_gpt_waveform *wfhw = _wfhw;
u8 sub_ch = rzg2l_gpt_subchannel(pwm->hwpwm);
u8 ch = RZG2L_GET_CH(pwm->hwpwm);
@@ -407,6 +415,7 @@ static int rzg2l_gpt_write_waveform(struct pwm_chip *chip,
* value for both channels.
*/
rzg2l_gpt->period_ticks[ch] = rzg2l_gpt_calculate_cycles(wfhw->gtpr,
+ info->prescale_mult,
wfhw->prescale);
} else if (!wfhw->gtpr && rzg2l_gpt_is_ch_enabled(rzg2l_gpt, pwm->hwpwm, NULL)) {
rzg2l_gpt_disable(rzg2l_gpt, pwm);
@@ -490,6 +499,7 @@ static int rzg2l_gpt_probe(struct platform_device *pdev)

static const struct rzg2l_gpt_info rzg2l_data = {
.gtcr_tpcs = RZG2L_GTCR_TPCS,
+ .prescale_mult = 2,
};

static const struct of_device_id rzg2l_gpt_of_table[] = {
--
2.43.0