1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * STM32 Low-Power Timer PWM driver 4 * 5 * Copyright (C) STMicroelectronics 2017 6 * 7 * Author: Gerald Baeza <gerald.baeza@st.com> 8 * 9 * Inspired by Gerald Baeza's pwm-stm32 driver 10 */ 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/platform_device.h> 17 #include <linux/pwm.h> 18 19 struct stm32_pwm_lp { 20 struct pwm_chip chip; 21 struct clk *clk; 22 struct regmap *regmap; 23 }; 24 25 static inline struct stm32_pwm_lp *to_stm32_pwm_lp(struct pwm_chip *chip) 26 { 27 return container_of(chip, struct stm32_pwm_lp, chip); 28 } 29 30 /* STM32 Low-Power Timer is preceded by a configurable power-of-2 prescaler */ 31 #define STM32_LPTIM_MAX_PRESCALER 128 32 33 static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm, 34 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 prd = div; 62 while (div > STM32_LPTIM_MAX_ARR) { 63 presc++; 64 if ((1 << presc) > STM32_LPTIM_MAX_PRESCALER) { 65 dev_err(priv->chip.dev, "max prescaler exceeded\n"); 66 return -EINVAL; 67 } 68 div = prd >> presc; 69 } 70 prd = div; 71 72 /* Calculate the duty cycle */ 73 dty = prd * state->duty_cycle; 74 do_div(dty, state->period); 75 76 if (!cstate.enabled) { 77 /* enable clock to drive PWM counter */ 78 ret = clk_enable(priv->clk); 79 if (ret) 80 return ret; 81 } 82 83 ret = regmap_read(priv->regmap, STM32_LPTIM_CFGR, &cfgr); 84 if (ret) 85 goto err; 86 87 if ((FIELD_GET(STM32_LPTIM_PRESC, cfgr) != presc) || 88 (FIELD_GET(STM32_LPTIM_WAVPOL, cfgr) != state->polarity)) { 89 val = FIELD_PREP(STM32_LPTIM_PRESC, presc); 90 val |= FIELD_PREP(STM32_LPTIM_WAVPOL, state->polarity); 91 mask = STM32_LPTIM_PRESC | STM32_LPTIM_WAVPOL; 92 93 /* Must disable LP timer to modify CFGR */ 94 reenable = true; 95 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 0); 96 if (ret) 97 goto err; 98 99 ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, 100 val); 101 if (ret) 102 goto err; 103 } 104 105 if (reenable) { 106 /* Must (re)enable LP timer to modify CMP & ARR */ 107 ret = regmap_write(priv->regmap, STM32_LPTIM_CR, 108 STM32_LPTIM_ENABLE); 109 if (ret) 110 goto err; 111 } 112 113 ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, prd - 1); 114 if (ret) 115 goto err; 116 117 ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, prd - (1 + dty)); 118 if (ret) 119 goto err; 120 121 /* ensure CMP & ARR registers are properly written */ 122 ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, 123 (val & STM32_LPTIM_CMPOK_ARROK), 124 100, 1000); 125 if (ret) { 126 dev_err(priv->chip.dev, "ARR/CMP registers write issue\n"); 127 goto err; 128 } 129 ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, 130 STM32_LPTIM_CMPOKCF_ARROKCF); 131 if (ret) 132 goto err; 133 134 if (reenable) { 135 /* Start LP timer in continuous mode */ 136 ret = regmap_update_bits(priv->regmap, STM32_LPTIM_CR, 137 STM32_LPTIM_CNTSTRT, 138 STM32_LPTIM_CNTSTRT); 139 if (ret) { 140 regmap_write(priv->regmap, STM32_LPTIM_CR, 0); 141 goto err; 142 } 143 } 144 145 return 0; 146 err: 147 if (!cstate.enabled) 148 clk_disable(priv->clk); 149 150 return ret; 151 } 152 153 static void stm32_pwm_lp_get_state(struct pwm_chip *chip, 154 struct pwm_device *pwm, 155 struct pwm_state *state) 156 { 157 struct stm32_pwm_lp *priv = to_stm32_pwm_lp(chip); 158 unsigned long rate = clk_get_rate(priv->clk); 159 u32 val, presc, prd; 160 u64 tmp; 161 162 regmap_read(priv->regmap, STM32_LPTIM_CR, &val); 163 state->enabled = !!FIELD_GET(STM32_LPTIM_ENABLE, val); 164 /* Keep PWM counter clock refcount in sync with PWM initial state */ 165 if (state->enabled) 166 clk_enable(priv->clk); 167 168 regmap_read(priv->regmap, STM32_LPTIM_CFGR, &val); 169 presc = FIELD_GET(STM32_LPTIM_PRESC, val); 170 state->polarity = FIELD_GET(STM32_LPTIM_WAVPOL, val); 171 172 regmap_read(priv->regmap, STM32_LPTIM_ARR, &prd); 173 tmp = prd + 1; 174 tmp = (tmp << presc) * NSEC_PER_SEC; 175 state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate); 176 177 regmap_read(priv->regmap, STM32_LPTIM_CMP, &val); 178 tmp = prd - val; 179 tmp = (tmp << presc) * NSEC_PER_SEC; 180 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate); 181 } 182 183 static const struct pwm_ops stm32_pwm_lp_ops = { 184 .owner = THIS_MODULE, 185 .apply = stm32_pwm_lp_apply, 186 .get_state = stm32_pwm_lp_get_state, 187 }; 188 189 static int stm32_pwm_lp_probe(struct platform_device *pdev) 190 { 191 struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); 192 struct stm32_pwm_lp *priv; 193 int ret; 194 195 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 196 if (!priv) 197 return -ENOMEM; 198 199 priv->regmap = ddata->regmap; 200 priv->clk = ddata->clk; 201 priv->chip.base = -1; 202 priv->chip.dev = &pdev->dev; 203 priv->chip.ops = &stm32_pwm_lp_ops; 204 priv->chip.npwm = 1; 205 priv->chip.of_xlate = of_pwm_xlate_with_flags; 206 priv->chip.of_pwm_n_cells = 3; 207 208 ret = pwmchip_add(&priv->chip); 209 if (ret < 0) 210 return ret; 211 212 platform_set_drvdata(pdev, priv); 213 214 return 0; 215 } 216 217 static int stm32_pwm_lp_remove(struct platform_device *pdev) 218 { 219 struct stm32_pwm_lp *priv = platform_get_drvdata(pdev); 220 221 pwm_disable(&priv->chip.pwms[0]); 222 223 return pwmchip_remove(&priv->chip); 224 } 225 226 static const struct of_device_id stm32_pwm_lp_of_match[] = { 227 { .compatible = "st,stm32-pwm-lp", }, 228 {}, 229 }; 230 MODULE_DEVICE_TABLE(of, stm32_pwm_lp_of_match); 231 232 static struct platform_driver stm32_pwm_lp_driver = { 233 .probe = stm32_pwm_lp_probe, 234 .remove = stm32_pwm_lp_remove, 235 .driver = { 236 .name = "stm32-pwm-lp", 237 .of_match_table = of_match_ptr(stm32_pwm_lp_of_match), 238 }, 239 }; 240 module_platform_driver(stm32_pwm_lp_driver); 241 242 MODULE_ALIAS("platform:stm32-pwm-lp"); 243 MODULE_DESCRIPTION("STMicroelectronics STM32 PWM LP driver"); 244 MODULE_LICENSE("GPL v2"); 245