in pwm-sun4i.c [391:482]
static int sun4i_pwm_probe(struct platform_device *pdev)
{
struct sun4i_pwm_chip *pwm;
int ret;
pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
if (!pwm)
return -ENOMEM;
pwm->data = of_device_get_match_data(&pdev->dev);
if (!pwm->data)
return -ENODEV;
pwm->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pwm->base))
return PTR_ERR(pwm->base);
/*
* All hardware variants need a source clock that is divided and
* then feeds the counter that defines the output wave form. In the
* device tree this clock is either unnamed or called "mod".
* Some variants (e.g. H6) need another clock to access the
* hardware registers; this is called "bus".
* So we request "mod" first (and ignore the corner case that a
* parent provides a "mod" clock while the right one would be the
* unnamed one of the PWM device) and if this is not found we fall
* back to the first clock of the PWM.
*/
pwm->clk = devm_clk_get_optional(&pdev->dev, "mod");
if (IS_ERR(pwm->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk),
"get mod clock failed\n");
if (!pwm->clk) {
pwm->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pwm->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->clk),
"get unnamed clock failed\n");
}
pwm->bus_clk = devm_clk_get_optional(&pdev->dev, "bus");
if (IS_ERR(pwm->bus_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->bus_clk),
"get bus clock failed\n");
pwm->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
if (IS_ERR(pwm->rst))
return dev_err_probe(&pdev->dev, PTR_ERR(pwm->rst),
"get reset failed\n");
/* Deassert reset */
ret = reset_control_deassert(pwm->rst);
if (ret) {
dev_err(&pdev->dev, "cannot deassert reset control: %pe\n",
ERR_PTR(ret));
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 %pe\n",
ERR_PTR(ret));
goto err_bus;
}
pwm->chip.dev = &pdev->dev;
pwm->chip.ops = &sun4i_pwm_ops;
pwm->chip.npwm = pwm->data->npwm;
spin_lock_init(&pwm->ctrl_lock);
ret = pwmchip_add(&pwm->chip);
if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
goto err_pwm_add;
}
platform_set_drvdata(pdev, pwm);
return 0;
err_pwm_add:
clk_disable_unprepare(pwm->bus_clk);
err_bus:
reset_control_assert(pwm->rst);
return ret;
}