262 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * STM32 Low-Power Timer PWM driver4 *5 * Copyright (C) STMicroelectronics 20176 *7 * Author: Gerald Baeza <gerald.baeza@st.com>8 *9 * Inspired by Gerald Baeza's pwm-stm32 driver10 */11 12#include <linux/bitfield.h>13#include <linux/mfd/stm32-lptimer.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/pinctrl/consumer.h>17#include <linux/platform_device.h>18#include <linux/pwm.h>19 20struct stm32_pwm_lp {21 struct clk *clk;22 struct regmap *regmap;23};24 25static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip)26{27 return pwmchip_get_drvdata(chip);28}29 30/* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */31#define STM32_LPTIM_MAX_PRESCALER 12832 33static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,34 const struct pwm_state *state)35{36 struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);37 unsigned long long prd, div, dty;38 struct pwm_state cstate;39 u32 val, mask, cfgr, presc = 0;40 bool reenable;41 int ret;42 43 pwm_get_state(pwm, &cstate);44 reenable = !cstate.enabled;45 46 if (!state->enabled) {47 if (cstate.enabled) {48 /* Disable LP timer */49 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);50 if (ret)51 return ret;52 /* disable clock to PWM counter */53 clk_disable(priv->clk);54 }55 return 0;56 }57 58 /* Calculate the period and prescaler value */59 div = (unsigned long long)clk_get_rate(priv->clk) * state->period;60 do_div(div, NSEC_PER_SEC);61 if (!div) {62 /* Clock is too slow to achieve requested period. */63 dev_dbg(pwmchip_parent(chip), "Can't reach %llu ns\n", state->period);64 return -EINVAL;65 }66 67 prd = div;68 while (div > STM32_LPTIM_MAX_ARR) {69 presc++;70 if ((1 << presc) > STM32_LPTIM_MAX_PRESCALER) {71 dev_err(pwmchip_parent(chip), "max prescaler exceeded\n");72 return -EINVAL;73 }74 div = prd >> presc;75 }76 prd = div;77 78 /* Calculate the duty cycle */79 dty = prd * state->duty_cycle;80 do_div(dty, state->period);81 82 if (!cstate.enabled) {83 /* enable clock to drive PWM counter */84 ret = clk_enable(priv->clk);85 if (ret)86 return ret;87 }88 89 ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr);90 if (ret)91 goto err;92 93 if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) ||94 (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) {95 val = FIELD_PREP(STM32_LPTIM_PRESC, presc);96 val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity);97 mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL;98 99 /* Must disable LP timer to modify CFGR */100 reenable = true;101 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0);102 if (ret)103 goto err;104 105 ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask,106 val);107 if (ret)108 goto err;109 }110 111 if (reenable) {112 /* Must (re)enable LP timer to modify CMP & ARR */113 ret = regmap_write(priv->regmap, STM32_LPTIM_CR,114 STM32_LPTIM_ENABLE);115 if (ret)116 goto err;117 }118 119 ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, prd - 1);120 if (ret)121 goto err;122 123 ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty));124 if (ret)125 goto err;126 127 /* ensure CMP & ARR registers are properly written */128 ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,129 (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,130 100, 1000);131 if (ret) {132 dev_err(pwmchip_parent(chip), "ARR/CMP registers write issue\n");133 goto err;134 }135 ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,136 STM32_LPTIM_CMPOKCF_ARROKCF);137 if (ret)138 goto err;139 140 if (reenable) {141 /* Start LP timer in continuous mode */142 ret = regmap_set_bits(priv->regmap, STM32_LPTIM_CR,143 STM32_LPTIM_CNTSTRT);144 if (ret) {145 regmap_write(priv->regmap, STM32_LPTIM_CR, 0);146 goto err;147 }148 }149 150 return 0;151err:152 if (!cstate.enabled)153 clk_disable(priv->clk);154 155 return ret;156}157 158static int stm32_pwm_lp_get_state(struct pwm_chip *chip,159 struct pwm_device *pwm,160 struct pwm_state *state)161{162 struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip);163 unsigned long rate = clk_get_rate(priv->clk);164 u32 val, presc, prd;165 u64 tmp;166 167 regmap_read(priv->regmap, STM32_LPTIM_CR, &val);168 state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val);169 /* Keep PWM counter clock refcount in sync with PWM initial state */170 if (state->enabled)171 clk_enable(priv->clk);172 173 regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val);174 presc = FIELD_GET(STM32_LPTIM_PRESC, val);175 state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val);176 177 regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd);178 tmp = prd + 1;179 tmp = (tmp << presc) * NSEC_PER_SEC;180 state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);181 182 regmap_read(priv->regmap, STM32_LPTIM_CMP, &val);183 tmp = prd - val;184 tmp = (tmp << presc) * NSEC_PER_SEC;185 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);186 187 return 0;188}189 190static const struct pwm_ops stm32_pwm_lp_ops = {191 .apply = stm32_pwm_lp_apply,192 .get_state = stm32_pwm_lp_get_state,193};194 195static int stm32_pwm_lp_probe(struct platform_device *pdev)196{197 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent);198 struct stm32_pwm_lp *priv;199 struct pwm_chip *chip;200 int ret;201 202 chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*priv));203 if (IS_ERR(chip))204 return PTR_ERR(chip);205 priv = to_stm32_pwm_lp(chip);206 207 priv->regmap = ddata->regmap;208 priv->clk = ddata->clk;209 chip->ops = &stm32_pwm_lp_ops;210 211 ret = devm_pwmchip_add(&pdev->dev, chip);212 if (ret < 0)213 return ret;214 215 platform_set_drvdata(pdev, chip);216 217 return 0;218}219 220static int stm32_pwm_lp_suspend(struct device *dev)221{222 struct pwm_chip *chip = dev_get_drvdata(dev);223 struct pwm_state state;224 225 pwm_get_state(&chip->pwms[0], &state);226 if (state.enabled) {227 dev_err(dev, "The consumer didn't stop us (%s)\n",228 chip->pwms[0].label);229 return -EBUSY;230 }231 232 return pinctrl_pm_select_sleep_state(dev);233}234 235static int stm32_pwm_lp_resume(struct device *dev)236{237 return pinctrl_pm_select_default_state(dev);238}239 240static DEFINE_SIMPLE_DEV_PM_OPS(stm32_pwm_lp_pm_ops, stm32_pwm_lp_suspend,241 stm32_pwm_lp_resume);242 243static const struct of_device_id stm32_pwm_lp_of_match[] = {244 { .compatible = "st,stm32-pwm-lp", },245 {},246};247MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match);248 249static struct platform_driver stm32_pwm_lp_driver = {250 .probe = stm32_pwm_lp_probe,251 .driver = {252 .name = "stm32-pwm-lp",253 .of_match_table = stm32_pwm_lp_of_match,254 .pm = pm_ptr(&stm32_pwm_lp_pm_ops),255 },256};257module_platform_driver(stm32_pwm_lp_driver);258 259MODULE_ALIAS("platform:stm32-pwm-lp");260MODULE_DESCRIPTION("STMicroelectronics STM32 PWM LP driver");261MODULE_LICENSE("GPL v2");262