Lines Matching +full:stm32 +full:- +full:timer +full:- +full:counter

1 // SPDX-License-Identifier: GPL-2.0
3 * STM32 Low-Power Timer PWM driver
9 * Inspired by Gerald Baeza's pwm-stm32 driver
13 #include <linux/mfd/stm32-lptimer.h>
30 /* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */
46 if (!state->enabled) { in stm32_pwm_lp_apply()
48 /* Disable LP timer */ in stm32_pwm_lp_apply()
49 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0); in stm32_pwm_lp_apply()
52 /* disable clock to PWM counter */ in stm32_pwm_lp_apply()
53 clk_disable(priv->clk); in stm32_pwm_lp_apply()
59 div = (unsigned long long)clk_get_rate(priv->clk) * state->period; in stm32_pwm_lp_apply()
63 dev_dbg(pwmchip_parent(chip), "Can't reach %llu ns\n", state->period); in stm32_pwm_lp_apply()
64 return -EINVAL; in stm32_pwm_lp_apply()
72 return -EINVAL; in stm32_pwm_lp_apply()
79 dty = prd * state->duty_cycle; in stm32_pwm_lp_apply()
80 do_div(dty, state->period); in stm32_pwm_lp_apply()
83 /* enable clock to drive PWM counter */ in stm32_pwm_lp_apply()
84 ret = clk_enable(priv->clk); in stm32_pwm_lp_apply()
89 ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr); in stm32_pwm_lp_apply()
94 (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) { in stm32_pwm_lp_apply()
96 val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity); in stm32_pwm_lp_apply()
99 /* Must disable LP timer to modify CFGR */ in stm32_pwm_lp_apply()
101 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0); in stm32_pwm_lp_apply()
105 ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, in stm32_pwm_lp_apply()
112 /* Must (re)enable LP timer to modify CMP & ARR */ in stm32_pwm_lp_apply()
113 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, in stm32_pwm_lp_apply()
119 ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, prd - 1); in stm32_pwm_lp_apply()
123 ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty)); in stm32_pwm_lp_apply()
128 ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, in stm32_pwm_lp_apply()
135 ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, in stm32_pwm_lp_apply()
141 /* Start LP timer in continuous mode */ in stm32_pwm_lp_apply()
142 ret = regmap_set_bits(priv->regmap, STM32_LPTIM_CR, in stm32_pwm_lp_apply()
145 regmap_write(priv->regmap, STM32_LPTIM_CR, 0); in stm32_pwm_lp_apply()
153 clk_disable(priv->clk); in stm32_pwm_lp_apply()
163 unsigned long rate = clk_get_rate(priv->clk); in stm32_pwm_lp_get_state()
167 regmap_read(priv->regmap, STM32_LPTIM_CR, &val); in stm32_pwm_lp_get_state()
168 state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val); in stm32_pwm_lp_get_state()
169 /* Keep PWM counter clock refcount in sync with PWM initial state */ in stm32_pwm_lp_get_state()
170 if (state->enabled) in stm32_pwm_lp_get_state()
171 clk_enable(priv->clk); in stm32_pwm_lp_get_state()
173 regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val); in stm32_pwm_lp_get_state()
175 state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val); in stm32_pwm_lp_get_state()
177 regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd); in stm32_pwm_lp_get_state()
180 state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate); in stm32_pwm_lp_get_state()
182 regmap_read(priv->regmap, STM32_LPTIM_CMP, &val); in stm32_pwm_lp_get_state()
183 tmp = prd - val; in stm32_pwm_lp_get_state()
185 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate); in stm32_pwm_lp_get_state()
197 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); in stm32_pwm_lp_probe()
202 chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv)); in stm32_pwm_lp_probe()
207 priv->regmap = ddata->regmap; in stm32_pwm_lp_probe()
208 priv->clk = ddata->clk; in stm32_pwm_lp_probe()
209 chip->ops = &stm32_pwm_lp_ops; in stm32_pwm_lp_probe()
211 ret = devm_pwmchip_add(&pdev->dev, chip); in stm32_pwm_lp_probe()
225 pwm_get_state(&chip->pwms[0], &state); in stm32_pwm_lp_suspend()
228 chip->pwms[0].label); in stm32_pwm_lp_suspend()
229 return -EBUSY; in stm32_pwm_lp_suspend()
244 { .compatible = "st,stm32-pwm-lp", },
252 .name = "stm32-pwm-lp",
259 MODULE_ALIAS("platform:stm32-pwm-lp");
260 MODULE_DESCRIPTION("STMicroelectronics STM32 PWM LP driver");