Lines Matching +full:fu540 +full:- +full:c000 +full:- +full:v1

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017-2018 SiFive
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
11 * - The hardware cannot generate a 100% duty cycle.
12 * - The hardware generates only inverted output.
65 mutex_lock(&ddata->lock); in pwm_sifive_request()
66 ddata->user_count++; in pwm_sifive_request()
67 mutex_unlock(&ddata->lock); in pwm_sifive_request()
76 mutex_lock(&ddata->lock); in pwm_sifive_free()
77 ddata->user_count--; in pwm_sifive_free()
78 mutex_unlock(&ddata->lock); in pwm_sifive_free()
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()
115 duty = readl(ddata->regs + PWM_SIFIVE_PWMCMP0 + in pwm_sifive_get_state()
116 pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP); in pwm_sifive_get_state()
118 state->enabled = duty > 0; in pwm_sifive_get_state()
120 val = readl(ddata->regs + PWM_SIFIVE_PWMCFG); in pwm_sifive_get_state()
122 state->enabled = false; in pwm_sifive_get_state()
124 state->period = ddata->real_period; in pwm_sifive_get_state()
125 state->duty_cycle = in pwm_sifive_get_state()
126 (u64)duty * ddata->real_period >> PWM_SIFIVE_CMPWIDTH; in pwm_sifive_get_state()
127 state->polarity = PWM_POLARITY_INVERSED; in pwm_sifive_get_state()
136 ret = clk_enable(ddata->clk); in pwm_sifive_enable()
138 dev_err(ddata->chip.dev, "Enable clk failed\n"); in pwm_sifive_enable()
144 clk_disable(ddata->clk); in pwm_sifive_enable()
160 if (state->polarity != PWM_POLARITY_INVERSED) in pwm_sifive_apply()
161 return -EINVAL; in pwm_sifive_apply()
163 ret = clk_enable(ddata->clk); in pwm_sifive_apply()
165 dev_err(ddata->chip.dev, "Enable clk failed\n"); in pwm_sifive_apply()
169 mutex_lock(&ddata->lock); in pwm_sifive_apply()
170 cur_state = pwm->state; in pwm_sifive_apply()
173 duty_cycle = state->duty_cycle; in pwm_sifive_apply()
174 if (!state->enabled) in pwm_sifive_apply()
184 frac = DIV64_U64_ROUND_CLOSEST(num, state->period); in pwm_sifive_apply()
186 frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1); in pwm_sifive_apply()
188 if (state->period != ddata->approx_period) { in pwm_sifive_apply()
189 if (ddata->user_count != 1) { in pwm_sifive_apply()
190 ret = -EBUSY; in pwm_sifive_apply()
193 ddata->approx_period = state->period; in pwm_sifive_apply()
194 pwm_sifive_update_clock(ddata, clk_get_rate(ddata->clk)); in pwm_sifive_apply()
197 writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP0 + in pwm_sifive_apply()
198 pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP); in pwm_sifive_apply()
200 if (state->enabled != enabled) in pwm_sifive_apply()
201 pwm_sifive_enable(chip, state->enabled); in pwm_sifive_apply()
204 clk_disable(ddata->clk); in pwm_sifive_apply()
205 mutex_unlock(&ddata->lock); in pwm_sifive_apply()
225 pwm_sifive_update_clock(ddata, ndata->new_rate); in pwm_sifive_clock_notifier()
232 struct device *dev = &pdev->dev; in pwm_sifive_probe()
240 return -ENOMEM; in pwm_sifive_probe()
242 mutex_init(&ddata->lock); in pwm_sifive_probe()
243 chip = &ddata->chip; in pwm_sifive_probe()
244 chip->dev = dev; in pwm_sifive_probe()
245 chip->ops = &pwm_sifive_ops; in pwm_sifive_probe()
246 chip->of_xlate = of_pwm_xlate_with_flags; in pwm_sifive_probe()
247 chip->of_pwm_n_cells = 3; in pwm_sifive_probe()
248 chip->base = -1; in pwm_sifive_probe()
249 chip->npwm = 4; in pwm_sifive_probe()
252 ddata->regs = devm_ioremap_resource(dev, res); in pwm_sifive_probe()
253 if (IS_ERR(ddata->regs)) in pwm_sifive_probe()
254 return PTR_ERR(ddata->regs); in pwm_sifive_probe()
256 ddata->clk = devm_clk_get(dev, NULL); in pwm_sifive_probe()
257 if (IS_ERR(ddata->clk)) in pwm_sifive_probe()
258 return dev_err_probe(dev, PTR_ERR(ddata->clk), in pwm_sifive_probe()
261 ret = clk_prepare_enable(ddata->clk); in pwm_sifive_probe()
268 ddata->notifier.notifier_call = pwm_sifive_clock_notifier; in pwm_sifive_probe()
269 ret = clk_notifier_register(ddata->clk, &ddata->notifier); in pwm_sifive_probe()
282 dev_dbg(dev, "SiFive PWM chip registered %d PWMs\n", chip->npwm); in pwm_sifive_probe()
287 clk_notifier_unregister(ddata->clk, &ddata->notifier); in pwm_sifive_probe()
289 clk_disable_unprepare(ddata->clk); in pwm_sifive_probe()
301 for (ch = 0; ch < ddata->chip.npwm; ch++) { in pwm_sifive_remove()
302 pwm = &ddata->chip.pwms[ch]; in pwm_sifive_remove()
303 if (pwm->state.enabled) { in pwm_sifive_remove()
309 clk_disable(ddata->clk); in pwm_sifive_remove()
311 clk_disable_unprepare(ddata->clk); in pwm_sifive_remove()
312 ret = pwmchip_remove(&ddata->chip); in pwm_sifive_remove()
313 clk_notifier_unregister(ddata->clk, &ddata->notifier); in pwm_sifive_remove()
328 .name = "pwm-sifive",