• Home
  • Raw
  • Download

Lines Matching +full:clk +full:- +full:pwm

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Freescale FlexTimer Module (FTM) PWM Driver
5 * Copyright 2012-2013 Freescale Semiconductor, Inc.
8 #include <linux/clk.h>
18 #include <linux/pwm.h>
48 /* This value is valid iff a pwm is running */
51 struct clk *ipg_clk;
52 struct clk *clk[FSL_PWM_CLK_MAX]; member
66 regmap_read(fpc->regmap, FTM_FMS, &val); in ftm_clear_write_protection()
68 regmap_update_bits(fpc->regmap, FTM_MODE, FTM_MODE_WPDIS, in ftm_clear_write_protection()
74 regmap_update_bits(fpc->regmap, FTM_FMS, FTM_FMS_WPEN, FTM_FMS_WPEN); in ftm_set_write_protection()
80 if (a->clk_select != b->clk_select) in fsl_pwm_periodcfg_are_equal()
82 if (a->clk_ps != b->clk_ps) in fsl_pwm_periodcfg_are_equal()
84 if (a->mod_period != b->mod_period) in fsl_pwm_periodcfg_are_equal()
89 static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) in fsl_pwm_request() argument
94 ret = clk_prepare_enable(fpc->ipg_clk); in fsl_pwm_request()
95 if (!ret && fpc->soc->has_enable_bits) { in fsl_pwm_request()
96 mutex_lock(&fpc->lock); in fsl_pwm_request()
97 regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16), in fsl_pwm_request()
98 BIT(pwm->hwpwm + 16)); in fsl_pwm_request()
99 mutex_unlock(&fpc->lock); in fsl_pwm_request()
105 static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) in fsl_pwm_free() argument
109 if (fpc->soc->has_enable_bits) { in fsl_pwm_free()
110 mutex_lock(&fpc->lock); in fsl_pwm_free()
111 regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16), in fsl_pwm_free()
113 mutex_unlock(&fpc->lock); in fsl_pwm_free()
116 clk_disable_unprepare(fpc->ipg_clk); in fsl_pwm_free()
125 rate = clk_get_rate(fpc->clk[fpc->period.clk_select]); in fsl_pwm_ticks_to_ns()
128 do_div(exval, rate >> fpc->period.clk_ps); in fsl_pwm_ticks_to_ns()
141 c = clk_get_rate(fpc->clk[index]); in fsl_pwm_calculate_period_clk()
150 periodcfg->clk_select = index; in fsl_pwm_calculate_period_clk()
151 periodcfg->clk_ps = ps; in fsl_pwm_calculate_period_clk()
152 periodcfg->mod_period = c - 1; in fsl_pwm_calculate_period_clk()
172 fix_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_FIX]); in fsl_pwm_calculate_period()
173 ext_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_EXT]); in fsl_pwm_calculate_period()
195 unsigned int period = fpc->period.mod_period + 1; in fsl_pwm_calculate_duty()
205 struct pwm_device *pwm) in fsl_pwm_is_any_pwm_enabled() argument
209 regmap_read(fpc->regmap, FTM_OUTMASK, &val); in fsl_pwm_is_any_pwm_enabled()
217 struct pwm_device *pwm) in fsl_pwm_is_other_pwm_enabled() argument
221 regmap_read(fpc->regmap, FTM_OUTMASK, &val); in fsl_pwm_is_other_pwm_enabled()
222 if (~(val | BIT(pwm->hwpwm)) & 0xFF) in fsl_pwm_is_other_pwm_enabled()
229 struct pwm_device *pwm, in fsl_pwm_apply_config() argument
238 if (!fsl_pwm_calculate_period(fpc, newstate->period, &periodcfg)) { in fsl_pwm_apply_config()
239 dev_err(fpc->chip.dev, "failed to calculate new period\n"); in fsl_pwm_apply_config()
240 return -EINVAL; in fsl_pwm_apply_config()
243 if (!fsl_pwm_is_any_pwm_enabled(fpc, pwm)) in fsl_pwm_apply_config()
247 * all PWM channels, therefore verify if the newly computed period in fsl_pwm_apply_config()
249 * we allow to change the period only if no other pwm is running. in fsl_pwm_apply_config()
251 else if (!fsl_pwm_periodcfg_are_equal(&fpc->period, &periodcfg)) { in fsl_pwm_apply_config()
252 if (fsl_pwm_is_other_pwm_enabled(fpc, pwm)) { in fsl_pwm_apply_config()
253 dev_err(fpc->chip.dev, in fsl_pwm_apply_config()
254 "Cannot change period for PWM %u, disable other PWMs first\n", in fsl_pwm_apply_config()
255 pwm->hwpwm); in fsl_pwm_apply_config()
256 return -EBUSY; in fsl_pwm_apply_config()
258 if (fpc->period.clk_select != periodcfg.clk_select) { in fsl_pwm_apply_config()
260 enum fsl_pwm_clk oldclk = fpc->period.clk_select; in fsl_pwm_apply_config()
263 ret = clk_prepare_enable(fpc->clk[newclk]); in fsl_pwm_apply_config()
266 clk_disable_unprepare(fpc->clk[oldclk]); in fsl_pwm_apply_config()
274 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK, in fsl_pwm_apply_config()
276 regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK, in fsl_pwm_apply_config()
278 regmap_write(fpc->regmap, FTM_MOD, periodcfg.mod_period); in fsl_pwm_apply_config()
280 fpc->period = periodcfg; in fsl_pwm_apply_config()
283 duty = fsl_pwm_calculate_duty(fpc, newstate->duty_cycle); in fsl_pwm_apply_config()
285 regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm), in fsl_pwm_apply_config()
287 regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty); in fsl_pwm_apply_config()
290 if (newstate->polarity == PWM_POLARITY_INVERSED) in fsl_pwm_apply_config()
291 reg_polarity = BIT(pwm->hwpwm); in fsl_pwm_apply_config()
293 regmap_update_bits(fpc->regmap, FTM_POL, BIT(pwm->hwpwm), reg_polarity); in fsl_pwm_apply_config()
300 static int fsl_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in fsl_pwm_apply() argument
304 struct pwm_state *oldstate = &pwm->state; in fsl_pwm_apply()
316 mutex_lock(&fpc->lock); in fsl_pwm_apply()
318 if (!newstate->enabled) { in fsl_pwm_apply()
319 if (oldstate->enabled) { in fsl_pwm_apply()
320 regmap_update_bits(fpc->regmap, FTM_OUTMASK, in fsl_pwm_apply()
321 BIT(pwm->hwpwm), BIT(pwm->hwpwm)); in fsl_pwm_apply()
322 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]); in fsl_pwm_apply()
323 clk_disable_unprepare(fpc->clk[fpc->period.clk_select]); in fsl_pwm_apply()
329 ret = fsl_pwm_apply_config(fpc, pwm, newstate); in fsl_pwm_apply()
334 if (!oldstate->enabled) { in fsl_pwm_apply()
335 ret = clk_prepare_enable(fpc->clk[fpc->period.clk_select]); in fsl_pwm_apply()
339 ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]); in fsl_pwm_apply()
341 clk_disable_unprepare(fpc->clk[fpc->period.clk_select]); in fsl_pwm_apply()
345 regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), in fsl_pwm_apply()
350 mutex_unlock(&fpc->lock); in fsl_pwm_apply()
365 ret = clk_prepare_enable(fpc->ipg_clk); in fsl_pwm_init()
369 regmap_write(fpc->regmap, FTM_CNTIN, 0x00); in fsl_pwm_init()
370 regmap_write(fpc->regmap, FTM_OUTINIT, 0x00); in fsl_pwm_init()
371 regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF); in fsl_pwm_init()
373 clk_disable_unprepare(fpc->ipg_clk); in fsl_pwm_init()
406 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL); in fsl_pwm_probe()
408 return -ENOMEM; in fsl_pwm_probe()
410 mutex_init(&fpc->lock); in fsl_pwm_probe()
412 fpc->soc = of_device_get_match_data(&pdev->dev); in fsl_pwm_probe()
413 fpc->chip.dev = &pdev->dev; in fsl_pwm_probe()
416 base = devm_ioremap_resource(&pdev->dev, res); in fsl_pwm_probe()
420 fpc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "ftm_sys", base, in fsl_pwm_probe()
422 if (IS_ERR(fpc->regmap)) { in fsl_pwm_probe()
423 dev_err(&pdev->dev, "regmap init failed\n"); in fsl_pwm_probe()
424 return PTR_ERR(fpc->regmap); in fsl_pwm_probe()
427 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys"); in fsl_pwm_probe()
428 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) { in fsl_pwm_probe()
429 dev_err(&pdev->dev, "failed to get \"ftm_sys\" clock\n"); in fsl_pwm_probe()
430 return PTR_ERR(fpc->clk[FSL_PWM_CLK_SYS]); in fsl_pwm_probe()
433 fpc->clk[FSL_PWM_CLK_FIX] = devm_clk_get(fpc->chip.dev, "ftm_fix"); in fsl_pwm_probe()
434 if (IS_ERR(fpc->clk[FSL_PWM_CLK_FIX])) in fsl_pwm_probe()
435 return PTR_ERR(fpc->clk[FSL_PWM_CLK_FIX]); in fsl_pwm_probe()
437 fpc->clk[FSL_PWM_CLK_EXT] = devm_clk_get(fpc->chip.dev, "ftm_ext"); in fsl_pwm_probe()
438 if (IS_ERR(fpc->clk[FSL_PWM_CLK_EXT])) in fsl_pwm_probe()
439 return PTR_ERR(fpc->clk[FSL_PWM_CLK_EXT]); in fsl_pwm_probe()
441 fpc->clk[FSL_PWM_CLK_CNTEN] = in fsl_pwm_probe()
442 devm_clk_get(fpc->chip.dev, "ftm_cnt_clk_en"); in fsl_pwm_probe()
443 if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN])) in fsl_pwm_probe()
444 return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]); in fsl_pwm_probe()
450 fpc->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); in fsl_pwm_probe()
451 if (IS_ERR(fpc->ipg_clk)) in fsl_pwm_probe()
452 fpc->ipg_clk = fpc->clk[FSL_PWM_CLK_SYS]; in fsl_pwm_probe()
455 fpc->chip.ops = &fsl_pwm_ops; in fsl_pwm_probe()
456 fpc->chip.of_xlate = of_pwm_xlate_with_flags; in fsl_pwm_probe()
457 fpc->chip.of_pwm_n_cells = 3; in fsl_pwm_probe()
458 fpc->chip.base = -1; in fsl_pwm_probe()
459 fpc->chip.npwm = 8; in fsl_pwm_probe()
461 ret = pwmchip_add(&fpc->chip); in fsl_pwm_probe()
463 dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); in fsl_pwm_probe()
476 return pwmchip_remove(&fpc->chip); in fsl_pwm_remove()
485 regcache_cache_only(fpc->regmap, true); in fsl_pwm_suspend()
486 regcache_mark_dirty(fpc->regmap); in fsl_pwm_suspend()
488 for (i = 0; i < fpc->chip.npwm; i++) { in fsl_pwm_suspend()
489 struct pwm_device *pwm = &fpc->chip.pwms[i]; in fsl_pwm_suspend() local
491 if (!test_bit(PWMF_REQUESTED, &pwm->flags)) in fsl_pwm_suspend()
494 clk_disable_unprepare(fpc->ipg_clk); in fsl_pwm_suspend()
496 if (!pwm_is_enabled(pwm)) in fsl_pwm_suspend()
499 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]); in fsl_pwm_suspend()
500 clk_disable_unprepare(fpc->clk[fpc->period.clk_select]); in fsl_pwm_suspend()
511 for (i = 0; i < fpc->chip.npwm; i++) { in fsl_pwm_resume()
512 struct pwm_device *pwm = &fpc->chip.pwms[i]; in fsl_pwm_resume() local
514 if (!test_bit(PWMF_REQUESTED, &pwm->flags)) in fsl_pwm_resume()
517 clk_prepare_enable(fpc->ipg_clk); in fsl_pwm_resume()
519 if (!pwm_is_enabled(pwm)) in fsl_pwm_resume()
522 clk_prepare_enable(fpc->clk[fpc->period.clk_select]); in fsl_pwm_resume()
523 clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]); in fsl_pwm_resume()
527 regcache_cache_only(fpc->regmap, false); in fsl_pwm_resume()
528 regcache_sync(fpc->regmap); in fsl_pwm_resume()
547 { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm },
548 { .compatible = "fsl,imx8qm-ftm-pwm", .data = &imx8qm_ftm_pwm },
555 .name = "fsl-ftm-pwm",
564 MODULE_DESCRIPTION("Freescale FlexTimer Module PWM Driver");
566 MODULE_ALIAS("platform:fsl-ftm-pwm");