From: Jernej Skrabec <jernej.skrabec@xxxxxxxx> H6 PWM core needs bus clock to be enabled in order to work. Add an optional probe for it and a fallback for previous bindings without name on module clock. Signed-off-by: Jernej Skrabec <jernej.skrabec@xxxxxxxx> Signed-off-by: Clément Péron <peron.clem@xxxxxxxxx> --- drivers/pwm/pwm-sun4i.c | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c index 9ba83769a478..54e19fa56a4e 100644 --- a/drivers/pwm/pwm-sun4i.c +++ b/drivers/pwm/pwm-sun4i.c @@ -78,6 +78,7 @@ struct sun4i_pwm_data { struct sun4i_pwm_chip { struct pwm_chip chip; + struct clk *bus_clk; struct clk *clk; struct reset_control *rst; void __iomem *base; @@ -363,9 +364,35 @@ static int sun4i_pwm_probe(struct platform_device *pdev) if (IS_ERR(pwm->base)) return PTR_ERR(pwm->base); - pwm->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) + /* Get all clocks and reset line */ + pwm->clk = devm_clk_get_optional(&pdev->dev, "mod"); + if (IS_ERR(pwm->clk)) { + dev_err(&pdev->dev, "get clock failed %ld\n", + PTR_ERR(pwm->clk)); return PTR_ERR(pwm->clk); + } + + /* + * Fallback for old dtbs with a single clock and no name. + * If a parent has a clock-name called "mod" whereas the + * current node is unnamed the clock reference will be + * incorrectly obtained and will not go into this fallback. + */ + if (!pwm->clk) { + pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pwm->clk)) { + dev_err(&pdev->dev, "get clock failed %ld\n", + PTR_ERR(pwm->clk)); + return PTR_ERR(pwm->clk); + } + } + + pwm->bus_clk = devm_clk_get_optional(&pdev->dev, "bus"); + if (IS_ERR(pwm->bus_clk)) { + dev_err(&pdev->dev, "get bus_clock failed %ld\n", + PTR_ERR(pwm->bus_clk)); + return PTR_ERR(pwm->bus_clk); + } pwm->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); if (IS_ERR(pwm->rst)) { @@ -382,6 +409,17 @@ static int sun4i_pwm_probe(struct platform_device *pdev) return ret; } + /* + * We're keeping the bus clock on for the sake of simplicity. + * Actually it only needs to be on for hardware register + * accesses. + */ + ret = clk_prepare_enable(pwm->bus_clk); + if (ret) { + dev_err(&pdev->dev, "Cannot prepare and enable bus_clk\n"); + goto err_bus; + } + pwm->chip.dev = &pdev->dev; pwm->chip.ops = &sun4i_pwm_ops; pwm->chip.base = -1; @@ -402,6 +440,8 @@ static int sun4i_pwm_probe(struct platform_device *pdev) return 0; err_pwm_add: + clk_disable_unprepare(pwm->bus_clk); +err_bus: reset_control_assert(pwm->rst); return ret; @@ -416,6 +456,7 @@ static int sun4i_pwm_remove(struct platform_device *pdev) if (ret) return ret; + clk_disable_unprepare(pwm->bus_clk); reset_control_assert(pwm->rst); return 0; -- 2.20.1