pwm: axi-pwmgen: Fix handling of external clock

The pwm-axi-pwmgen device is backed by an FPGA and can be synthesized in
 different ways. Relevant here is that it can use one or two external
 clock signals. The changes included here fix clock handling for the two
 clocks case.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEP4GsaTp6HlmJrf7Tj4D7WH0S/k4FAmhCto0ACgkQj4D7WH0S
 /k5EawgAk3EcnDZyL+8VwymzF0xHxDjgNKaf7NDVErqt/kwfDhidDNqb8ABo7mKN
 cn5BeuVzngH00mCQuHzvT8vRu7YMOhbOJHaZmXPaMtGUIEe+rZn7+x2i/cW5aHSU
 nbx+TtzSvQufI13FWF+IbLP+2r+hbEbPLqFKnkVSxIZOBOig1IthpejWvurPdze0
 1k3kvoRoQTN7ic50iCvjR7rqwFgBkpzRDOUyK/JFFocCYqgSEAVV9ykAcocoWNVQ
 ZbxTOQ6erSotlkjLFWTCfsEc4S3CJSCTlgPfTXwh13Gvl+3Gi9x8P3E9UrS0I6fj
 qnVCOuwF3EfOlmIfC4YcDeMBSho8fg==
 =41HV
 -----END PGP SIGNATURE-----

Merge tag 'pwm/for-6.16-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux

Pull pwm fixes from Uwe Kleine-König:
 "axi-pwmgen: Fix handling of external clock

  The pwm-axi-pwmgen device is backed by an FPGA and can be synthesized
  in different ways. Relevant here is that it can use one or two
  external clock signals. These fix clock handling for the two clocks
  case"

* tag 'pwm/for-6.16-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux:
  pwm: axi-pwmgen: fix missing separate external clock
  dt-bindings: pwm: adi,axi-pwmgen: Fix clocks
This commit is contained in:
Linus Torvalds 2025-06-06 13:16:50 -07:00
commit 8a2ba6f8ee
2 changed files with 31 additions and 5 deletions

View file

@ -30,11 +30,19 @@ properties:
const: 3
clocks:
maxItems: 1
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: axi
- const: ext
required:
- reg
- clocks
- clock-names
unevaluatedProperties: false
@ -43,6 +51,7 @@ examples:
pwm@44b00000 {
compatible = "adi,axi-pwmgen-2.00.a";
reg = <0x44b00000 0x1000>;
clocks = <&spi_clk>;
clocks = <&fpga_clk>, <&spi_clk>;
clock-names = "axi", "ext";
#pwm-cells = <3>;
};

View file

@ -257,7 +257,7 @@ static int axi_pwmgen_probe(struct platform_device *pdev)
struct regmap *regmap;
struct pwm_chip *chip;
struct axi_pwmgen_ddata *ddata;
struct clk *clk;
struct clk *axi_clk, *clk;
void __iomem *io_base;
int ret;
@ -280,9 +280,26 @@ static int axi_pwmgen_probe(struct platform_device *pdev)
ddata = pwmchip_get_drvdata(chip);
ddata->regmap = regmap;
clk = devm_clk_get_enabled(dev, NULL);
/*
* Using NULL here instead of "axi" for backwards compatibility. There
* are some dtbs that don't give clock-names and have the "ext" clock
* as the one and only clock (due to mistake in the original bindings).
*/
axi_clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(axi_clk))
return dev_err_probe(dev, PTR_ERR(axi_clk), "failed to get axi clock\n");
clk = devm_clk_get_optional_enabled(dev, "ext");
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n");
return dev_err_probe(dev, PTR_ERR(clk), "failed to get ext clock\n");
/*
* If there is no "ext" clock, it means the HDL was compiled with
* ASYNC_CLK_EN=0. In this case, the AXI clock is also used for the
* PWM output clock.
*/
if (!clk)
clk = axi_clk;
ret = devm_clk_rate_exclusive_get(dev, clk);
if (ret)