Lines Matching +full:clk +full:- +full:pwm
1 // SPDX-License-Identifier: GPL-2.0
3 * Clock based PWM controller
7 * This is an "adapter" driver that allows PWM consumers to use
8 * system clocks with duty cycle control as PWM outputs.
11 * - Due to the fact that exact behavior depends on the underlying
13 * - Underlying clock may not be able to give 0% or 100% duty cycle
15 * - When the PWM is disabled, the clock will be disabled as well,
17 * - The clk API doesn't expose the necessary calls to implement
27 #include <linux/clk.h>
28 #include <linux/pwm.h>
32 struct clk *clk; member
38 static int pwm_clk_apply(struct pwm_chip *chip, struct pwm_device *pwm, in pwm_clk_apply() argument
44 u64 period = state->period; in pwm_clk_apply()
45 u64 duty_cycle = state->duty_cycle; in pwm_clk_apply()
47 if (!state->enabled) { in pwm_clk_apply()
48 if (pwm->state.enabled) { in pwm_clk_apply()
49 clk_disable(pcchip->clk); in pwm_clk_apply()
50 pcchip->clk_enabled = false; in pwm_clk_apply()
53 } else if (!pwm->state.enabled) { in pwm_clk_apply()
54 ret = clk_enable(pcchip->clk); in pwm_clk_apply()
57 pcchip->clk_enabled = true; in pwm_clk_apply()
61 * We have to enable the clk before setting the rate and duty_cycle, in pwm_clk_apply()
62 * that however results in a window where the clk is on with a in pwm_clk_apply()
68 ret = clk_set_rate(pcchip->clk, rate); in pwm_clk_apply()
72 if (state->polarity == PWM_POLARITY_INVERSED) in pwm_clk_apply()
73 duty_cycle = period - duty_cycle; in pwm_clk_apply()
75 return clk_set_duty_cycle(pcchip->clk, duty_cycle, period); in pwm_clk_apply()
88 pcchip = devm_kzalloc(&pdev->dev, sizeof(*pcchip), GFP_KERNEL); in pwm_clk_probe()
90 return -ENOMEM; in pwm_clk_probe()
92 pcchip->clk = devm_clk_get_prepared(&pdev->dev, NULL); in pwm_clk_probe()
93 if (IS_ERR(pcchip->clk)) in pwm_clk_probe()
94 return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk), in pwm_clk_probe()
97 pcchip->chip.dev = &pdev->dev; in pwm_clk_probe()
98 pcchip->chip.ops = &pwm_clk_ops; in pwm_clk_probe()
99 pcchip->chip.npwm = 1; in pwm_clk_probe()
101 ret = pwmchip_add(&pcchip->chip); in pwm_clk_probe()
103 return dev_err_probe(&pdev->dev, ret, "Failed to add pwm chip\n"); in pwm_clk_probe()
113 pwmchip_remove(&pcchip->chip); in pwm_clk_remove()
115 if (pcchip->clk_enabled) in pwm_clk_remove()
116 clk_disable(pcchip->clk); in pwm_clk_remove()
120 { .compatible = "clk-pwm", },
127 .name = "pwm-clk",
135 MODULE_ALIAS("platform:pwm-clk");
137 MODULE_DESCRIPTION("Clock based PWM driver");