[PATCH v7 2/3] pwm: rp1: Add RP1 PWM controller driver
Christophe JAILLET
christophe.jaillet at wanadoo.fr
Thu Sep 3 13:36:57 PDT 2026
Le 20/07/2026 à 11:44, Andrea della Porta a écrit :
> From: Naushir Patuck <naush at raspberrypi.com>
>
> The Raspberry Pi RP1 southbridge features an embedded PWM
> controller with 4 output channels, alongside an RPM interface
> to read the fan speed on the Raspberry Pi 5.
>
> Add the supporting driver.
>
> Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
> Co-developed-by: Stanimir Varbanov <svarbanov at suse.de>
> Signed-off-by: Stanimir Varbanov <svarbanov at suse.de>
> Signed-off-by: Andrea della Porta <andrea.porta at suse.com>
Hi,
...
> +static int rp1_pwm_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + unsigned long clk_rate;
> + struct pwm_chip *chip;
> + void __iomem *base;
> + struct rp1_pwm *rp1;
> + int ret;
> +
> + chip = devm_pwmchip_alloc(dev, RP1_PWM_NUM_PWMS, sizeof(*rp1));
> + if (IS_ERR(chip))
> + return PTR_ERR(chip);
> +
> + rp1 = pwmchip_get_drvdata(chip);
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + rp1->regmap = devm_regmap_init_mmio(dev, base, &rp1_pwm_regmap_config);
> + if (IS_ERR(rp1->regmap))
> + return dev_err_probe(dev, PTR_ERR(rp1->regmap), "Cannot initialize regmap\n");
> +
> + rp1->clk = devm_clk_get(dev, NULL);
Could it be devm_clk_get_enabled() to simplify the error handling path
as done above with other devm function?
...
> + if (IS_ERR(rp1->clk))
> + return dev_err_probe(dev, PTR_ERR(rp1->clk), "Clock not found\n");
> +
> + ret = clk_prepare_enable(rp1->clk);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to enable clock\n");
... this also saves these 3 lines.
> + rp1->clk_enabled = true;
> +
> + ret = devm_clk_rate_exclusive_get(dev, rp1->clk);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to get exclusive rate\n");
> + goto err_disable_clk;
> + }
> +
> + clk_rate = clk_get_rate(rp1->clk);
> + if (!clk_rate) {
> + ret = dev_err_probe(dev, -EINVAL, "Failed to get clock rate\n");
> + goto err_disable_clk;
> + }
> + /*
> + * To prevent u64 overflow in period calculations:
> + * mul_u64_u64_div_u64(period_ns, clk_rate, NSEC_PER_SEC)
> + * If clk_rate > 1 GHz, the result can overflow.
> + */
> + if (clk_rate > HZ_PER_GHZ) {
> + ret = dev_err_probe(dev, -EINVAL, "Clock rate > 1 GHz is not supported\n");
> + goto err_disable_clk;
> + }
> + rp1->clk_rate = clk_rate;
> +
> + chip->ops = &rp1_pwm_ops;
> + chip->atomic = true;
> +
> + platform_set_drvdata(pdev, chip);
> +
> + ret = pwmchip_add(chip);
Could it be devm_pwmchip_add() to simplify the error handling path as
done above with other devm function?
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to register PWM chip\n");
> + goto err_disable_clk;
> + }
> +
> + ret = of_syscon_register_regmap(np, rp1->regmap);
> + if (ret) {
> + dev_err_probe(dev, ret, "Failed to register syscon\n");
> + goto err_remove_chip;
> + }
> +
> + return 0;
> +
> +err_remove_chip:
> + pwmchip_remove(chip);
> +err_disable_clk:
> + clk_disable_unprepare(rp1->clk);
> +
> + return ret;
> +}
...
CJ
More information about the linux-arm-kernel
mailing list