[PATCH 05/11] pwm: rcar: Parametrize cycle counter field size
Geert Uytterhoeven
geert+renesas at glider.be
Mon Oct 26 07:55:21 PDT 2026
Prepare for the advent of PWM blocks with output cycle and high-level
period fields larger than 10 bits by parametrizing the field size.
Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
drivers/pwm/pwm-rcar.c | 51 +++++++++++++++++++++++++++---------------
1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index f1f68bfe016f729f..3813094c601efc8c 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -22,7 +22,7 @@
#include <linux/slab.h>
#define RCAR_PWM_MAX_DIVISION 24
-#define RCAR_PWM_MAX_CYCLE 1023
+#define RCAR_PWM_MAX_CYCLE(rp) GENMASK(rp->cycle_bits - 1, 0)
#define RCAR_PWMCR 0x00
#define RCAR_PWMCR_CC0_MASK GENMASK(19, 16)
@@ -32,14 +32,17 @@
#define RCAR_PWMCR_EN0 BIT(0)
#define RCAR_PWMCNT 0x04
-#define RCAR_PWMCNT_CYC0_MASK 0x03ff0000
-#define RCAR_PWMCNT_CYC0_SHIFT 16
-#define RCAR_PWMCNT_PH0_MASK 0x000003ff
-#define RCAR_PWMCNT_PH0_SHIFT 0
+#define RCAR_PWMCNT_CYC0_MASK GENMASK(31, 16)
+#define RCAR_PWMCNT_PH0_MASK GENMASK(15, 0)
struct rcar_pwm_chip {
void __iomem *base;
struct clk *clk;
+ unsigned int cycle_bits;
+};
+
+struct rcar_pwm_info {
+ unsigned int cycle_bits;
};
static inline struct rcar_pwm_chip *to_rcar_pwm_chip(struct pwm_chip *chip)
@@ -77,7 +80,7 @@ static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
if (clk_rate == 0)
return -EINVAL;
- div = (u64)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE;
+ div = mul_u32_u32(NSEC_PER_SEC, RCAR_PWM_MAX_CYCLE(rp));
tmp = (u64)period_ns * clk_rate + div - 1;
tmp = div64_u64(tmp, div);
div = ilog2(tmp - 1) + 1;
@@ -111,21 +114,19 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, u64 duty_ns,
/* div <= 24 == RCAR_PWM_MAX_DIVISION, so the shift doesn't overflow. */
tmp = mul_u64_u64_div_u64(period_ns, clk_rate, (u64)NSEC_PER_SEC << div);
- if (tmp > FIELD_MAX(RCAR_PWMCNT_CYC0_MASK))
- tmp = FIELD_MAX(RCAR_PWMCNT_CYC0_MASK);
-
- cyc = FIELD_PREP(RCAR_PWMCNT_CYC0_MASK, tmp);
+ cyc = min(tmp, RCAR_PWM_MAX_CYCLE(rp));
tmp = mul_u64_u64_div_u64(duty_ns, clk_rate, (u64)NSEC_PER_SEC << div);
- if (tmp > FIELD_MAX(RCAR_PWMCNT_PH0_MASK))
- tmp = FIELD_MAX(RCAR_PWMCNT_PH0_MASK);
- ph = FIELD_PREP(RCAR_PWMCNT_PH0_MASK, tmp);
+ ph = min(tmp, RCAR_PWM_MAX_CYCLE(rp));
/* Avoid prohibited setting */
if (cyc == 0 || ph == 0)
return -EINVAL;
- rcar_pwm_write(rp, cyc | ph, RCAR_PWMCNT);
+ rcar_pwm_write(rp,
+ FIELD_PREP(RCAR_PWMCNT_CYC0_MASK, cyc) |
+ FIELD_PREP(RCAR_PWMCNT_PH0_MASK, ph),
+ RCAR_PWMCNT);
return 0;
}
@@ -142,12 +143,15 @@ static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
static int rcar_pwm_enable(struct rcar_pwm_chip *rp)
{
- u32 value;
+ u32 value, cyc, ph;
/* Don't enable the PWM device if CYC0 or PH0 is 0 */
value = rcar_pwm_read(rp, RCAR_PWMCNT);
- if ((value & RCAR_PWMCNT_CYC0_MASK) == 0 ||
- (value & RCAR_PWMCNT_PH0_MASK) == 0)
+ cyc = FIELD_GET(RCAR_PWMCNT_CYC0_MASK, value);
+ ph = FIELD_GET(RCAR_PWMCNT_PH0_MASK, value);
+
+ if ((cyc & RCAR_PWM_MAX_CYCLE(rp)) == 0 ||
+ (ph & RCAR_PWM_MAX_CYCLE(rp)) == 0)
return -EINVAL;
rcar_pwm_update(rp, RCAR_PWMCR_EN0, RCAR_PWMCR_EN0, RCAR_PWMCR);
@@ -202,11 +206,16 @@ static const struct pwm_ops rcar_pwm_ops = {
static int rcar_pwm_probe(struct platform_device *pdev)
{
+ const struct rcar_pwm_info *info;
struct device *dev = &pdev->dev;
struct rcar_pwm_chip *rcar_pwm;
struct pwm_chip *chip;
int ret;
+ info = of_device_get_match_data(dev);
+ if (!info)
+ return -ENODEV;
+
chip = devm_pwmchip_alloc(dev, 1, sizeof(*rcar_pwm));
if (IS_ERR(chip))
return PTR_ERR(chip);
@@ -222,6 +231,8 @@ static int rcar_pwm_probe(struct platform_device *pdev)
return PTR_ERR(rcar_pwm->clk);
}
+ rcar_pwm->cycle_bits = info->cycle_bits;
+
chip->ops = &rcar_pwm_ops;
platform_set_drvdata(pdev, chip);
@@ -247,8 +258,12 @@ static void rcar_pwm_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
+static const struct rcar_pwm_info rcar_pwm_info = {
+ .cycle_bits = 10,
+};
+
static const struct of_device_id rcar_pwm_of_table[] = {
- { .compatible = "renesas,pwm-rcar" },
+ { .compatible = "renesas,pwm-rcar", .data = &rcar_pwm_info },
{ }
};
MODULE_DEVICE_TABLE(of, rcar_pwm_of_table);
--
2.43.0
More information about the linux-arm-kernel
mailing list