summaryrefslogtreecommitdiff
path: root/drivers/pwm/pwm-fsl-ftm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-fsl-ftm.c')
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index fad968eb75f6..7a800b02be94 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]);
@@ -447,6 +482,8 @@ static int fsl_pwm_probe(struct platform_device *pdev)
fpc->chip.base = -1;
fpc->chip.npwm = 8;
fpc->chip.can_sleep = true;
+ fpc->has_pwmen = of_property_read_bool(pdev->dev.of_node,
+ "ftm-has-pwmen-bits");
ret = pwmchip_add(&fpc->chip);
if (ret < 0) {
@@ -481,7 +518,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;
@@ -504,7 +541,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;