summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-stm32.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:50:03 +0000
commit01a69402cf9d38ff180345d55c2ee51c7e89fbc7 (patch)
treeb406c5242a088c4f59c6e4b719b783f43aca6ae9 /drivers/pwm/pwm-stm32.c
parentAdding upstream version 6.7.12. (diff)
downloadlinux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.tar.xz
linux-01a69402cf9d38ff180345d55c2ee51c7e89fbc7.zip
Adding upstream version 6.8.9.upstream/6.8.9
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/pwm/pwm-stm32.c')
-rw-r--r--drivers/pwm/pwm-stm32.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 58ece15ef..5f10cba49 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -52,21 +52,6 @@ static u32 active_channels(struct stm32_pwm *dev)
return ccer & TIM_CCER_CCXE;
}
-static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value)
-{
- switch (ch) {
- case 0:
- return regmap_write(dev->regmap, TIM_CCR1, value);
- case 1:
- return regmap_write(dev->regmap, TIM_CCR2, value);
- case 2:
- return regmap_write(dev->regmap, TIM_CCR3, value);
- case 3:
- return regmap_write(dev->regmap, TIM_CCR4, value);
- }
- return -EINVAL;
-}
-
#define TIM_CCER_CC12P (TIM_CCER_CC1P | TIM_CCER_CC2P)
#define TIM_CCER_CC12E (TIM_CCER_CC1E | TIM_CCER_CC2E)
#define TIM_CCER_CC34P (TIM_CCER_CC3P | TIM_CCER_CC4P)
@@ -323,7 +308,7 @@ unlock:
return ret;
}
-static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
+static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
int duty_ns, int period_ns)
{
unsigned long long prd, div, dty;
@@ -369,7 +354,7 @@ static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
dty = prd * duty_ns;
do_div(dty, period_ns);
- write_ccrx(priv, ch, dty);
+ regmap_write(priv->regmap, TIM_CCR1 + 4 * ch, dty);
/* Configure output mode */
shift = (ch & 0x1) * CCMR_CHANNEL_SHIFT;
@@ -386,7 +371,7 @@ static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
return 0;
}
-static int stm32_pwm_set_polarity(struct stm32_pwm *priv, int ch,
+static int stm32_pwm_set_polarity(struct stm32_pwm *priv, unsigned int ch,
enum pwm_polarity polarity)
{
u32 mask;
@@ -401,7 +386,7 @@ static int stm32_pwm_set_polarity(struct stm32_pwm *priv, int ch,
return 0;
}
-static int stm32_pwm_enable(struct stm32_pwm *priv, int ch)
+static int stm32_pwm_enable(struct stm32_pwm *priv, unsigned int ch)
{
u32 mask;
int ret;
@@ -426,7 +411,7 @@ static int stm32_pwm_enable(struct stm32_pwm *priv, int ch)
return 0;
}
-static void stm32_pwm_disable(struct stm32_pwm *priv, int ch)
+static void stm32_pwm_disable(struct stm32_pwm *priv, unsigned int ch)
{
u32 mask;
@@ -486,8 +471,50 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}
+static int stm32_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm, struct pwm_state *state)
+{
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
+ int ch = pwm->hwpwm;
+ unsigned long rate;
+ u32 ccer, psc, arr, ccr;
+ u64 dty, prd;
+ int ret;
+
+ mutex_lock(&priv->lock);
+
+ ret = regmap_read(priv->regmap, TIM_CCER, &ccer);
+ if (ret)
+ goto out;
+
+ state->enabled = ccer & (TIM_CCER_CC1E << (ch * 4));
+ state->polarity = (ccer & (TIM_CCER_CC1P << (ch * 4))) ?
+ PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
+ ret = regmap_read(priv->regmap, TIM_PSC, &psc);
+ if (ret)
+ goto out;
+ ret = regmap_read(priv->regmap, TIM_ARR, &arr);
+ if (ret)
+ goto out;
+ ret = regmap_read(priv->regmap, TIM_CCR1 + 4 * ch, &ccr);
+ if (ret)
+ goto out;
+
+ rate = clk_get_rate(priv->clk);
+
+ prd = (u64)NSEC_PER_SEC * (psc + 1) * (arr + 1);
+ state->period = DIV_ROUND_UP_ULL(prd, rate);
+ dty = (u64)NSEC_PER_SEC * (psc + 1) * ccr;
+ state->duty_cycle = DIV_ROUND_UP_ULL(dty, rate);
+
+out:
+ mutex_unlock(&priv->lock);
+ return ret;
+}
+
static const struct pwm_ops stm32pwm_ops = {
.apply = stm32_pwm_apply_locked,
+ .get_state = stm32_pwm_get_state,
.capture = IS_ENABLED(CONFIG_DMA_ENGINE) ? stm32_pwm_capture : NULL,
};
@@ -642,7 +669,7 @@ static int stm32_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused stm32_pwm_suspend(struct device *dev)
+static int stm32_pwm_suspend(struct device *dev)
{
struct stm32_pwm *priv = dev_get_drvdata(dev);
unsigned int i;
@@ -663,7 +690,7 @@ static int __maybe_unused stm32_pwm_suspend(struct device *dev)
return pinctrl_pm_select_sleep_state(dev);
}
-static int __maybe_unused stm32_pwm_resume(struct device *dev)
+static int stm32_pwm_resume(struct device *dev)
{
struct stm32_pwm *priv = dev_get_drvdata(dev);
int ret;
@@ -676,7 +703,7 @@ static int __maybe_unused stm32_pwm_resume(struct device *dev)
return stm32_pwm_apply_breakinputs(priv);
}
-static SIMPLE_DEV_PM_OPS(stm32_pwm_pm_ops, stm32_pwm_suspend, stm32_pwm_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(stm32_pwm_pm_ops, stm32_pwm_suspend, stm32_pwm_resume);
static const struct of_device_id stm32_pwm_of_match[] = {
{ .compatible = "st,stm32-pwm", },
@@ -689,7 +716,7 @@ static struct platform_driver stm32_pwm_driver = {
.driver = {
.name = "stm32-pwm",
.of_match_table = stm32_pwm_of_match,
- .pm = &stm32_pwm_pm_ops,
+ .pm = pm_ptr(&stm32_pwm_pm_ops),
},
};
module_platform_driver(stm32_pwm_driver);