Lines Matching +full:pwm +full:- +full:period

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017-2018 SiFive
4 * For SiFive's PWM IP block documentation please refer Chapter 14 of
5 * Reference Manual : https://static.dev.sifive.com/FU540-C000-v1.0.pdf
8 * - When changing both duty cycle and period, we cannot prevent in
9 * software that the output might produce a period with mixed
10 * settings (new period length and old duty cycle).
11 * - The hardware cannot generate a 100% duty cycle.
12 * - The hardware generates only inverted output.
19 #include <linux/pwm.h>
60 static int pwm_sifive_request(struct pwm_chip *chip, struct pwm_device *pwm) in pwm_sifive_request() argument
64 mutex_lock(&ddata->lock); in pwm_sifive_request()
65 ddata->user_count++; in pwm_sifive_request()
66 mutex_unlock(&ddata->lock); in pwm_sifive_request()
71 static void pwm_sifive_free(struct pwm_chip *chip, struct pwm_device *pwm) in pwm_sifive_free() argument
75 mutex_lock(&ddata->lock); in pwm_sifive_free()
76 ddata->user_count--; in pwm_sifive_free()
77 mutex_unlock(&ddata->lock); in pwm_sifive_free()
80 /* Called holding ddata->lock */
89 * The PWM unit is used with pwmzerocmp=0, so the only way to modify the in pwm_sifive_update_clock()
90 * period length is using pwmscale which provides the number of bits the in pwm_sifive_update_clock()
91 * counter is shifted before being feed to the comparators. A period in pwm_sifive_update_clock()
93 * (1 << (PWM_SIFIVE_CMPWIDTH + scale)) * 10^9/rate = period in pwm_sifive_update_clock()
95 scale_pow = div64_ul(ddata->approx_period * (u64)rate, NSEC_PER_SEC); in pwm_sifive_update_clock()
96 scale = clamp(ilog2(scale_pow) - PWM_SIFIVE_CMPWIDTH, 0, 0xf); in pwm_sifive_update_clock()
100 writel(val, ddata->regs + PWM_SIFIVE_PWMCFG); in pwm_sifive_update_clock()
104 ddata->real_period = div64_ul(num, rate); in pwm_sifive_update_clock()
105 dev_dbg(ddata->chip.dev, in pwm_sifive_update_clock()
106 "New real_period = %u ns\n", ddata->real_period); in pwm_sifive_update_clock()
109 static int pwm_sifive_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in pwm_sifive_get_state() argument
115 duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm)); in pwm_sifive_get_state()
117 state->enabled = duty > 0; in pwm_sifive_get_state()
119 val = readl(ddata->regs + PWM_SIFIVE_PWMCFG); in pwm_sifive_get_state()
121 state->enabled = false; in pwm_sifive_get_state()
123 state->period = ddata->real_period; in pwm_sifive_get_state()
124 state->duty_cycle = in pwm_sifive_get_state()
125 (u64)duty * ddata->real_period >> PWM_SIFIVE_CMPWIDTH; in pwm_sifive_get_state()
126 state->polarity = PWM_POLARITY_INVERSED; in pwm_sifive_get_state()
131 static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm, in pwm_sifive_apply() argument
142 if (state->polarity != PWM_POLARITY_INVERSED) in pwm_sifive_apply()
143 return -EINVAL; in pwm_sifive_apply()
145 cur_state = pwm->state; in pwm_sifive_apply()
148 duty_cycle = state->duty_cycle; in pwm_sifive_apply()
149 if (!state->enabled) in pwm_sifive_apply()
159 frac = DIV64_U64_ROUND_CLOSEST(num, state->period); in pwm_sifive_apply()
161 frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1); in pwm_sifive_apply()
163 mutex_lock(&ddata->lock); in pwm_sifive_apply()
164 if (state->period != ddata->approx_period) { in pwm_sifive_apply()
166 * Don't let a 2nd user change the period underneath the 1st user. in pwm_sifive_apply()
167 * However if ddate->approx_period == 0 this is the first time we set in pwm_sifive_apply()
168 * any period, so let whoever gets here first set the period so other in pwm_sifive_apply()
169 * users who agree on the period won't fail. in pwm_sifive_apply()
171 if (ddata->user_count != 1 && ddata->approx_period) { in pwm_sifive_apply()
172 mutex_unlock(&ddata->lock); in pwm_sifive_apply()
173 return -EBUSY; in pwm_sifive_apply()
175 ddata->approx_period = state->period; in pwm_sifive_apply()
176 pwm_sifive_update_clock(ddata, clk_get_rate(ddata->clk)); in pwm_sifive_apply()
178 mutex_unlock(&ddata->lock); in pwm_sifive_apply()
181 * If the PWM is enabled the clk is already on. So only enable it in pwm_sifive_apply()
183 * the PWM state. in pwm_sifive_apply()
186 ret = clk_enable(ddata->clk); in pwm_sifive_apply()
188 dev_err(ddata->chip.dev, "Enable clk failed\n"); in pwm_sifive_apply()
193 writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP(pwm->hwpwm)); in pwm_sifive_apply()
195 if (!state->enabled) in pwm_sifive_apply()
196 clk_disable(ddata->clk); in pwm_sifive_apply()
217 mutex_lock(&ddata->lock); in pwm_sifive_clock_notifier()
218 pwm_sifive_update_clock(ddata, ndata->new_rate); in pwm_sifive_clock_notifier()
219 mutex_unlock(&ddata->lock); in pwm_sifive_clock_notifier()
227 struct device *dev = &pdev->dev; in pwm_sifive_probe()
236 return -ENOMEM; in pwm_sifive_probe()
238 mutex_init(&ddata->lock); in pwm_sifive_probe()
239 chip = &ddata->chip; in pwm_sifive_probe()
240 chip->dev = dev; in pwm_sifive_probe()
241 chip->ops = &pwm_sifive_ops; in pwm_sifive_probe()
242 chip->npwm = 4; in pwm_sifive_probe()
244 ddata->regs = devm_platform_ioremap_resource(pdev, 0); in pwm_sifive_probe()
245 if (IS_ERR(ddata->regs)) in pwm_sifive_probe()
246 return PTR_ERR(ddata->regs); in pwm_sifive_probe()
248 ddata->clk = devm_clk_get_prepared(dev, NULL); in pwm_sifive_probe()
249 if (IS_ERR(ddata->clk)) in pwm_sifive_probe()
250 return dev_err_probe(dev, PTR_ERR(ddata->clk), in pwm_sifive_probe()
253 ret = clk_enable(ddata->clk); in pwm_sifive_probe()
255 dev_err(dev, "failed to enable clock for pwm: %d\n", ret); in pwm_sifive_probe()
259 val = readl(ddata->regs + PWM_SIFIVE_PWMCFG); in pwm_sifive_probe()
263 for (i = 0; i < chip->npwm; ++i) { in pwm_sifive_probe()
264 val = readl(ddata->regs + PWM_SIFIVE_PWMCMP(i)); in pwm_sifive_probe()
270 /* The clk should be on once for each running PWM. */ in pwm_sifive_probe()
274 ret = clk_enable(ddata->clk); in pwm_sifive_probe()
282 clk_disable(ddata->clk); in pwm_sifive_probe()
287 ddata->notifier.notifier_call = pwm_sifive_clock_notifier; in pwm_sifive_probe()
288 ret = clk_notifier_register(ddata->clk, &ddata->notifier); in pwm_sifive_probe()
296 dev_err(dev, "cannot register PWM: %d\n", ret); in pwm_sifive_probe()
301 dev_dbg(dev, "SiFive PWM chip registered %d PWMs\n", chip->npwm); in pwm_sifive_probe()
306 clk_notifier_unregister(ddata->clk, &ddata->notifier); in pwm_sifive_probe()
309 clk_disable(ddata->clk); in pwm_sifive_probe()
310 --enabled_clks; in pwm_sifive_probe()
319 struct pwm_device *pwm; in pwm_sifive_remove() local
322 pwmchip_remove(&ddata->chip); in pwm_sifive_remove()
323 clk_notifier_unregister(ddata->clk, &ddata->notifier); in pwm_sifive_remove()
325 for (ch = 0; ch < ddata->chip.npwm; ch++) { in pwm_sifive_remove()
326 pwm = &ddata->chip.pwms[ch]; in pwm_sifive_remove()
327 if (pwm->state.enabled) in pwm_sifive_remove()
328 clk_disable(ddata->clk); in pwm_sifive_remove()
342 .name = "pwm-sifive",
348 MODULE_DESCRIPTION("SiFive PWM driver");