From d93ab4b67d4051470a942fc8026bfb7ed178b3f4 Mon Sep 17 00:00:00 2001 From: Shenwei Wang Date: Tue, 22 May 2018 11:46:16 -0500 Subject: [PATCH] MLK-18379 pwm: fsl-tpm: updates to support i.mx8qm The TPM IP block on i.MX8QM has the following changes: 1) The IPG clock has to be enabled before access any registers 2) The extra bits in FTM_SC register are added to enable the PWM mode. This patch updates the driver according to these changes, and it can support the TPM PWM module on i.MX8QM. Signed-off-by: Shenwei Wang --- drivers/pwm/pwm-fsl-ftm.c | 49 ++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index 557b4ea16796..96fa304caca0 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c @@ -86,7 +86,9 @@ struct fsl_pwm_chip { struct regmap *regmap; int period_ns; + bool has_pwmen; + struct clk *ipg_clk; struct clk *clk[FSL_PWM_CLK_MAX]; }; @@ -95,18 +97,39 @@ static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip) return container_of(chip, struct fsl_pwm_chip, chip); } +static inline int fsl_pwm_mode_enable(struct fsl_pwm_chip *fpc) +{ + if (!fpc) + return -ENODEV; + + if (fpc->ipg_clk) + clk_prepare_enable(fpc->ipg_clk); + + return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); +} + +static inline void fsl_pwm_mode_disable(struct fsl_pwm_chip *fpc) +{ + if (!fpc) + return; + + clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); + if (fpc->ipg_clk) + clk_disable_unprepare(fpc->ipg_clk); +} + static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct fsl_pwm_chip *fpc = to_fsl_chip(chip); - return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); + return fsl_pwm_mode_enable(fpc); } static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { struct fsl_pwm_chip *fpc = to_fsl_chip(chip); - clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); + fsl_pwm_mode_disable(fpc); } static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc, @@ -323,6 +346,9 @@ static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) mutex_lock(&fpc->lock); regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0); + if (fpc->has_pwmen) + regmap_update_bits(fpc->regmap, FTM_SC, + BIT(pwm->hwpwm + 16), BIT(pwm->hwpwm + 16)); ret = fsl_counter_clock_enable(fpc); mutex_unlock(&fpc->lock); @@ -336,6 +362,10 @@ static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) u32 val; mutex_lock(&fpc->lock); + + if (fpc->has_pwmen) + regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16), 0); + regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), BIT(pwm->hwpwm)); @@ -363,7 +393,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc) { int ret; - ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); + ret = fsl_pwm_mode_enable(fpc); if (ret) return ret; @@ -371,7 +401,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc) regmap_write(fpc->regmap, FTM_OUTINIT, 0x00); regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF); - clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); + fsl_pwm_mode_disable(fpc); return 0; } @@ -422,7 +452,12 @@ static int fsl_pwm_probe(struct platform_device *pdev) return PTR_ERR(fpc->regmap); } + fpc->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(fpc->ipg_clk)) + fpc->ipg_clk = 0; + fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys"); + if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) { dev_err(&pdev->dev, "failed to get \"ftm_sys\" clock\n"); return PTR_ERR(fpc->clk[FSL_PWM_CLK_SYS]); @@ -446,6 +481,8 @@ static int fsl_pwm_probe(struct platform_device *pdev) fpc->chip.of_pwm_n_cells = 3; fpc->chip.base = -1; fpc->chip.npwm = 8; + fpc->has_pwmen = of_property_read_bool(pdev->dev.of_node, + "ftm-has-pwmen-bits"); ret = pwmchip_add(&fpc->chip); if (ret < 0) { @@ -480,7 +517,7 @@ static int fsl_pwm_suspend(struct device *dev) if (!test_bit(PWMF_REQUESTED, &pwm->flags)) continue; - clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); + fsl_pwm_mode_disable(fpc); if (!pwm_is_enabled(pwm)) continue; @@ -503,7 +540,7 @@ static int fsl_pwm_resume(struct device *dev) if (!test_bit(PWMF_REQUESTED, &pwm->flags)) continue; - clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); + fsl_pwm_mode_enable(fpc); if (!pwm_is_enabled(pwm)) continue;