1597f55e3SFabrice Gasnier // SPDX-License-Identifier: GPL-2.0 2597f55e3SFabrice Gasnier /* 3597f55e3SFabrice Gasnier * STM32 Low-Power Timer Encoder and Counter driver 4597f55e3SFabrice Gasnier * 5597f55e3SFabrice Gasnier * Copyright (C) STMicroelectronics 2017 6597f55e3SFabrice Gasnier * 7597f55e3SFabrice Gasnier * Author: Fabrice Gasnier <fabrice.gasnier@st.com> 8597f55e3SFabrice Gasnier * 9597f55e3SFabrice Gasnier * Inspired by 104-quad-8 and stm32-timer-trigger drivers. 10597f55e3SFabrice Gasnier * 11597f55e3SFabrice Gasnier */ 12597f55e3SFabrice Gasnier 13597f55e3SFabrice Gasnier #include <linux/bitfield.h> 14597f55e3SFabrice Gasnier #include <linux/counter.h> 15597f55e3SFabrice Gasnier #include <linux/mfd/stm32-lptimer.h> 1601f68f06SFabrice Gasnier #include <linux/mod_devicetable.h> 17597f55e3SFabrice Gasnier #include <linux/module.h> 18597f55e3SFabrice Gasnier #include <linux/pinctrl/consumer.h> 19597f55e3SFabrice Gasnier #include <linux/platform_device.h> 20aaec1a0fSWilliam Breathitt Gray #include <linux/types.h> 21597f55e3SFabrice Gasnier 22597f55e3SFabrice Gasnier struct stm32_lptim_cnt { 23597f55e3SFabrice Gasnier struct device *dev; 24597f55e3SFabrice Gasnier struct regmap *regmap; 25597f55e3SFabrice Gasnier struct clk *clk; 26597f55e3SFabrice Gasnier u32 ceiling; 27597f55e3SFabrice Gasnier u32 polarity; 28597f55e3SFabrice Gasnier u32 quadrature_mode; 29597f55e3SFabrice Gasnier bool enabled; 30597f55e3SFabrice Gasnier }; 31597f55e3SFabrice Gasnier 32597f55e3SFabrice Gasnier static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv) 33597f55e3SFabrice Gasnier { 34597f55e3SFabrice Gasnier u32 val; 35597f55e3SFabrice Gasnier int ret; 36597f55e3SFabrice Gasnier 37597f55e3SFabrice Gasnier ret = regmap_read(priv->regmap, STM32_LPTIM_CR, &val); 38597f55e3SFabrice Gasnier if (ret) 39597f55e3SFabrice Gasnier return ret; 40597f55e3SFabrice Gasnier 41597f55e3SFabrice Gasnier return FIELD_GET(STM32_LPTIM_ENABLE, val); 42597f55e3SFabrice Gasnier } 43597f55e3SFabrice Gasnier 44597f55e3SFabrice Gasnier static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, 45597f55e3SFabrice Gasnier int enable) 46597f55e3SFabrice Gasnier { 47597f55e3SFabrice Gasnier int ret; 48597f55e3SFabrice Gasnier u32 val; 49597f55e3SFabrice Gasnier 50597f55e3SFabrice Gasnier val = FIELD_PREP(STM32_LPTIM_ENABLE, enable); 51597f55e3SFabrice Gasnier ret = regmap_write(priv->regmap, STM32_LPTIM_CR, val); 52597f55e3SFabrice Gasnier if (ret) 53597f55e3SFabrice Gasnier return ret; 54597f55e3SFabrice Gasnier 55597f55e3SFabrice Gasnier if (!enable) { 56597f55e3SFabrice Gasnier clk_disable(priv->clk); 57597f55e3SFabrice Gasnier priv->enabled = false; 58597f55e3SFabrice Gasnier return 0; 59597f55e3SFabrice Gasnier } 60597f55e3SFabrice Gasnier 61597f55e3SFabrice Gasnier /* LP timer must be enabled before writing CMP & ARR */ 62597f55e3SFabrice Gasnier ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling); 63597f55e3SFabrice Gasnier if (ret) 64597f55e3SFabrice Gasnier return ret; 65597f55e3SFabrice Gasnier 66597f55e3SFabrice Gasnier ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0); 67597f55e3SFabrice Gasnier if (ret) 68597f55e3SFabrice Gasnier return ret; 69597f55e3SFabrice Gasnier 70597f55e3SFabrice Gasnier /* ensure CMP & ARR registers are properly written */ 71597f55e3SFabrice Gasnier ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, 72597f55e3SFabrice Gasnier (val & STM32_LPTIM_CMPOK_ARROK), 73597f55e3SFabrice Gasnier 100, 1000); 74597f55e3SFabrice Gasnier if (ret) 75597f55e3SFabrice Gasnier return ret; 76597f55e3SFabrice Gasnier 77597f55e3SFabrice Gasnier ret = regmap_write(priv->regmap, STM32_LPTIM_ICR, 78597f55e3SFabrice Gasnier STM32_LPTIM_CMPOKCF_ARROKCF); 79597f55e3SFabrice Gasnier if (ret) 80597f55e3SFabrice Gasnier return ret; 81597f55e3SFabrice Gasnier 82597f55e3SFabrice Gasnier ret = clk_enable(priv->clk); 83597f55e3SFabrice Gasnier if (ret) { 84597f55e3SFabrice Gasnier regmap_write(priv->regmap, STM32_LPTIM_CR, 0); 85597f55e3SFabrice Gasnier return ret; 86597f55e3SFabrice Gasnier } 87597f55e3SFabrice Gasnier priv->enabled = true; 88597f55e3SFabrice Gasnier 89597f55e3SFabrice Gasnier /* Start LP timer in continuous mode */ 90597f55e3SFabrice Gasnier return regmap_update_bits(priv->regmap, STM32_LPTIM_CR, 91597f55e3SFabrice Gasnier STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT); 92597f55e3SFabrice Gasnier } 93597f55e3SFabrice Gasnier 94597f55e3SFabrice Gasnier static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable) 95597f55e3SFabrice Gasnier { 96597f55e3SFabrice Gasnier u32 mask = STM32_LPTIM_ENC | STM32_LPTIM_COUNTMODE | 97597f55e3SFabrice Gasnier STM32_LPTIM_CKPOL | STM32_LPTIM_PRESC; 98597f55e3SFabrice Gasnier u32 val; 99597f55e3SFabrice Gasnier 100597f55e3SFabrice Gasnier /* Setup LP timer encoder/counter and polarity, without prescaler */ 101597f55e3SFabrice Gasnier if (priv->quadrature_mode) 102597f55e3SFabrice Gasnier val = enable ? STM32_LPTIM_ENC : 0; 103597f55e3SFabrice Gasnier else 104597f55e3SFabrice Gasnier val = enable ? STM32_LPTIM_COUNTMODE : 0; 105597f55e3SFabrice Gasnier val |= FIELD_PREP(STM32_LPTIM_CKPOL, enable ? priv->polarity : 0); 106597f55e3SFabrice Gasnier 107597f55e3SFabrice Gasnier return regmap_update_bits(priv->regmap, STM32_LPTIM_CFGR, mask, val); 108597f55e3SFabrice Gasnier } 109597f55e3SFabrice Gasnier 110aaec1a0fSWilliam Breathitt Gray /* 11101f68f06SFabrice Gasnier * In non-quadrature mode, device counts up on active edge. 11201f68f06SFabrice Gasnier * In quadrature mode, encoder counting scenarios are as follows: 11301f68f06SFabrice Gasnier * +---------+----------+--------------------+--------------------+ 11401f68f06SFabrice Gasnier * | Active | Level on | IN1 signal | IN2 signal | 11501f68f06SFabrice Gasnier * | edge | opposite +----------+---------+----------+---------+ 11601f68f06SFabrice Gasnier * | | signal | Rising | Falling | Rising | Falling | 11701f68f06SFabrice Gasnier * +---------+----------+----------+---------+----------+---------+ 11801f68f06SFabrice Gasnier * | Rising | High -> | Down | - | Up | - | 11901f68f06SFabrice Gasnier * | edge | Low -> | Up | - | Down | - | 12001f68f06SFabrice Gasnier * +---------+----------+----------+---------+----------+---------+ 12101f68f06SFabrice Gasnier * | Falling | High -> | - | Up | - | Down | 12201f68f06SFabrice Gasnier * | edge | Low -> | - | Down | - | Up | 12301f68f06SFabrice Gasnier * +---------+----------+----------+---------+----------+---------+ 12401f68f06SFabrice Gasnier * | Both | High -> | Down | Up | Up | Down | 12501f68f06SFabrice Gasnier * | edges | Low -> | Up | Down | Down | Up | 12601f68f06SFabrice Gasnier * +---------+----------+----------+---------+----------+---------+ 127597f55e3SFabrice Gasnier */ 128394a0150SWilliam Breathitt Gray static const enum counter_function stm32_lptim_cnt_functions[] = { 129aaec1a0fSWilliam Breathitt Gray COUNTER_FUNCTION_INCREASE, 130aaec1a0fSWilliam Breathitt Gray COUNTER_FUNCTION_QUADRATURE_X4, 131597f55e3SFabrice Gasnier }; 132597f55e3SFabrice Gasnier 133f83e6e59SWilliam Breathitt Gray static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { 134aaec1a0fSWilliam Breathitt Gray COUNTER_SYNAPSE_ACTION_RISING_EDGE, 135aaec1a0fSWilliam Breathitt Gray COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 136aaec1a0fSWilliam Breathitt Gray COUNTER_SYNAPSE_ACTION_BOTH_EDGES, 137aaec1a0fSWilliam Breathitt Gray COUNTER_SYNAPSE_ACTION_NONE, 138597f55e3SFabrice Gasnier }; 139597f55e3SFabrice Gasnier 140597f55e3SFabrice Gasnier static int stm32_lptim_cnt_read(struct counter_device *counter, 141aaec1a0fSWilliam Breathitt Gray struct counter_count *count, u64 *val) 142597f55e3SFabrice Gasnier { 143e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 144597f55e3SFabrice Gasnier u32 cnt; 145597f55e3SFabrice Gasnier int ret; 146597f55e3SFabrice Gasnier 147597f55e3SFabrice Gasnier ret = regmap_read(priv->regmap, STM32_LPTIM_CNT, &cnt); 148597f55e3SFabrice Gasnier if (ret) 149597f55e3SFabrice Gasnier return ret; 150597f55e3SFabrice Gasnier 151d49e6ee2SWilliam Breathitt Gray *val = cnt; 152597f55e3SFabrice Gasnier 153597f55e3SFabrice Gasnier return 0; 154597f55e3SFabrice Gasnier } 155597f55e3SFabrice Gasnier 156aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_function_read(struct counter_device *counter, 157597f55e3SFabrice Gasnier struct counter_count *count, 158aaec1a0fSWilliam Breathitt Gray enum counter_function *function) 159597f55e3SFabrice Gasnier { 160e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 161597f55e3SFabrice Gasnier 162597f55e3SFabrice Gasnier if (!priv->quadrature_mode) { 163aaec1a0fSWilliam Breathitt Gray *function = COUNTER_FUNCTION_INCREASE; 164597f55e3SFabrice Gasnier return 0; 165597f55e3SFabrice Gasnier } 166597f55e3SFabrice Gasnier 167aaec1a0fSWilliam Breathitt Gray if (priv->polarity == STM32_LPTIM_CKPOL_BOTH_EDGES) { 168aaec1a0fSWilliam Breathitt Gray *function = COUNTER_FUNCTION_QUADRATURE_X4; 169597f55e3SFabrice Gasnier return 0; 170597f55e3SFabrice Gasnier } 171597f55e3SFabrice Gasnier 172597f55e3SFabrice Gasnier return -EINVAL; 173597f55e3SFabrice Gasnier } 174597f55e3SFabrice Gasnier 175aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_function_write(struct counter_device *counter, 176597f55e3SFabrice Gasnier struct counter_count *count, 177aaec1a0fSWilliam Breathitt Gray enum counter_function function) 178597f55e3SFabrice Gasnier { 179e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 180597f55e3SFabrice Gasnier 181597f55e3SFabrice Gasnier if (stm32_lptim_is_enabled(priv)) 182597f55e3SFabrice Gasnier return -EBUSY; 183597f55e3SFabrice Gasnier 184597f55e3SFabrice Gasnier switch (function) { 185aaec1a0fSWilliam Breathitt Gray case COUNTER_FUNCTION_INCREASE: 186597f55e3SFabrice Gasnier priv->quadrature_mode = 0; 187597f55e3SFabrice Gasnier return 0; 188aaec1a0fSWilliam Breathitt Gray case COUNTER_FUNCTION_QUADRATURE_X4: 189597f55e3SFabrice Gasnier priv->quadrature_mode = 1; 190aaec1a0fSWilliam Breathitt Gray priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; 191597f55e3SFabrice Gasnier return 0; 192b11eed15SWilliam Breathitt Gray default: 193b11eed15SWilliam Breathitt Gray /* should never reach this path */ 194597f55e3SFabrice Gasnier return -EINVAL; 195597f55e3SFabrice Gasnier } 196b11eed15SWilliam Breathitt Gray } 197597f55e3SFabrice Gasnier 198aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_enable_read(struct counter_device *counter, 199597f55e3SFabrice Gasnier struct counter_count *count, 200aaec1a0fSWilliam Breathitt Gray u8 *enable) 201597f55e3SFabrice Gasnier { 202e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 203597f55e3SFabrice Gasnier int ret; 204597f55e3SFabrice Gasnier 205597f55e3SFabrice Gasnier ret = stm32_lptim_is_enabled(priv); 206597f55e3SFabrice Gasnier if (ret < 0) 207597f55e3SFabrice Gasnier return ret; 208597f55e3SFabrice Gasnier 209aaec1a0fSWilliam Breathitt Gray *enable = ret; 210aaec1a0fSWilliam Breathitt Gray 211aaec1a0fSWilliam Breathitt Gray return 0; 212597f55e3SFabrice Gasnier } 213597f55e3SFabrice Gasnier 214aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_enable_write(struct counter_device *counter, 215597f55e3SFabrice Gasnier struct counter_count *count, 216aaec1a0fSWilliam Breathitt Gray u8 enable) 217597f55e3SFabrice Gasnier { 218e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 219597f55e3SFabrice Gasnier int ret; 220597f55e3SFabrice Gasnier 221597f55e3SFabrice Gasnier /* Check nobody uses the timer, or already disabled/enabled */ 222597f55e3SFabrice Gasnier ret = stm32_lptim_is_enabled(priv); 223597f55e3SFabrice Gasnier if ((ret < 0) || (!ret && !enable)) 224597f55e3SFabrice Gasnier return ret; 225597f55e3SFabrice Gasnier if (enable && ret) 226597f55e3SFabrice Gasnier return -EBUSY; 227597f55e3SFabrice Gasnier 228597f55e3SFabrice Gasnier ret = stm32_lptim_setup(priv, enable); 229597f55e3SFabrice Gasnier if (ret) 230597f55e3SFabrice Gasnier return ret; 231597f55e3SFabrice Gasnier 232597f55e3SFabrice Gasnier ret = stm32_lptim_set_enable_state(priv, enable); 233597f55e3SFabrice Gasnier if (ret) 234597f55e3SFabrice Gasnier return ret; 235597f55e3SFabrice Gasnier 236aaec1a0fSWilliam Breathitt Gray return 0; 237597f55e3SFabrice Gasnier } 238597f55e3SFabrice Gasnier 239aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_ceiling_read(struct counter_device *counter, 240597f55e3SFabrice Gasnier struct counter_count *count, 241aaec1a0fSWilliam Breathitt Gray u64 *ceiling) 242597f55e3SFabrice Gasnier { 243e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 244597f55e3SFabrice Gasnier 245aaec1a0fSWilliam Breathitt Gray *ceiling = priv->ceiling; 246aaec1a0fSWilliam Breathitt Gray 247aaec1a0fSWilliam Breathitt Gray return 0; 248597f55e3SFabrice Gasnier } 249597f55e3SFabrice Gasnier 250aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_ceiling_write(struct counter_device *counter, 251597f55e3SFabrice Gasnier struct counter_count *count, 252aaec1a0fSWilliam Breathitt Gray u64 ceiling) 253597f55e3SFabrice Gasnier { 254e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 255597f55e3SFabrice Gasnier 25601f68f06SFabrice Gasnier if (stm32_lptim_is_enabled(priv)) 25701f68f06SFabrice Gasnier return -EBUSY; 25801f68f06SFabrice Gasnier 25901f68f06SFabrice Gasnier if (ceiling > STM32_LPTIM_MAX_ARR) 260e2ff3198SWilliam Breathitt Gray return -ERANGE; 26101f68f06SFabrice Gasnier 26201f68f06SFabrice Gasnier priv->ceiling = ceiling; 26301f68f06SFabrice Gasnier 264aaec1a0fSWilliam Breathitt Gray return 0; 265597f55e3SFabrice Gasnier } 266597f55e3SFabrice Gasnier 267aaec1a0fSWilliam Breathitt Gray static struct counter_comp stm32_lptim_cnt_ext[] = { 268aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_ENABLE(stm32_lptim_cnt_enable_read, 269aaec1a0fSWilliam Breathitt Gray stm32_lptim_cnt_enable_write), 270aaec1a0fSWilliam Breathitt Gray COUNTER_COMP_CEILING(stm32_lptim_cnt_ceiling_read, 271aaec1a0fSWilliam Breathitt Gray stm32_lptim_cnt_ceiling_write), 272597f55e3SFabrice Gasnier }; 273597f55e3SFabrice Gasnier 274aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_action_read(struct counter_device *counter, 275597f55e3SFabrice Gasnier struct counter_count *count, 276597f55e3SFabrice Gasnier struct counter_synapse *synapse, 277aaec1a0fSWilliam Breathitt Gray enum counter_synapse_action *action) 278597f55e3SFabrice Gasnier { 279e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 280aaec1a0fSWilliam Breathitt Gray enum counter_function function; 281597f55e3SFabrice Gasnier int err; 282597f55e3SFabrice Gasnier 283aaec1a0fSWilliam Breathitt Gray err = stm32_lptim_cnt_function_read(counter, count, &function); 284597f55e3SFabrice Gasnier if (err) 285597f55e3SFabrice Gasnier return err; 286597f55e3SFabrice Gasnier 287597f55e3SFabrice Gasnier switch (function) { 288aaec1a0fSWilliam Breathitt Gray case COUNTER_FUNCTION_INCREASE: 289597f55e3SFabrice Gasnier /* LP Timer acts as up-counter on input 1 */ 290aaec1a0fSWilliam Breathitt Gray if (synapse->signal->id != count->synapses[0].signal->id) { 291aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_NONE; 292597f55e3SFabrice Gasnier return 0; 293aaec1a0fSWilliam Breathitt Gray } 294aaec1a0fSWilliam Breathitt Gray 295aaec1a0fSWilliam Breathitt Gray switch (priv->polarity) { 296aaec1a0fSWilliam Breathitt Gray case STM32_LPTIM_CKPOL_RISING_EDGE: 297aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 298aaec1a0fSWilliam Breathitt Gray return 0; 299aaec1a0fSWilliam Breathitt Gray case STM32_LPTIM_CKPOL_FALLING_EDGE: 300aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 301aaec1a0fSWilliam Breathitt Gray return 0; 302aaec1a0fSWilliam Breathitt Gray case STM32_LPTIM_CKPOL_BOTH_EDGES: 303aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 304aaec1a0fSWilliam Breathitt Gray return 0; 305aaec1a0fSWilliam Breathitt Gray default: 306aaec1a0fSWilliam Breathitt Gray /* should never reach this path */ 307aaec1a0fSWilliam Breathitt Gray return -EINVAL; 308aaec1a0fSWilliam Breathitt Gray } 309aaec1a0fSWilliam Breathitt Gray case COUNTER_FUNCTION_QUADRATURE_X4: 310aaec1a0fSWilliam Breathitt Gray *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES; 311597f55e3SFabrice Gasnier return 0; 312b11eed15SWilliam Breathitt Gray default: 313b11eed15SWilliam Breathitt Gray /* should never reach this path */ 314597f55e3SFabrice Gasnier return -EINVAL; 315597f55e3SFabrice Gasnier } 316b11eed15SWilliam Breathitt Gray } 317597f55e3SFabrice Gasnier 318aaec1a0fSWilliam Breathitt Gray static int stm32_lptim_cnt_action_write(struct counter_device *counter, 319597f55e3SFabrice Gasnier struct counter_count *count, 320597f55e3SFabrice Gasnier struct counter_synapse *synapse, 321aaec1a0fSWilliam Breathitt Gray enum counter_synapse_action action) 322597f55e3SFabrice Gasnier { 323e98ea385SUwe Kleine-König struct stm32_lptim_cnt *const priv = counter_priv(counter); 324aaec1a0fSWilliam Breathitt Gray enum counter_function function; 325597f55e3SFabrice Gasnier int err; 326597f55e3SFabrice Gasnier 327597f55e3SFabrice Gasnier if (stm32_lptim_is_enabled(priv)) 328597f55e3SFabrice Gasnier return -EBUSY; 329597f55e3SFabrice Gasnier 330aaec1a0fSWilliam Breathitt Gray err = stm32_lptim_cnt_function_read(counter, count, &function); 331597f55e3SFabrice Gasnier if (err) 332597f55e3SFabrice Gasnier return err; 333597f55e3SFabrice Gasnier 334597f55e3SFabrice Gasnier /* only set polarity when in counter mode (on input 1) */ 335aaec1a0fSWilliam Breathitt Gray if (function != COUNTER_FUNCTION_INCREASE 336aaec1a0fSWilliam Breathitt Gray || synapse->signal->id != count->synapses[0].signal->id) 337597f55e3SFabrice Gasnier return -EINVAL; 338aaec1a0fSWilliam Breathitt Gray 339aaec1a0fSWilliam Breathitt Gray switch (action) { 340aaec1a0fSWilliam Breathitt Gray case COUNTER_SYNAPSE_ACTION_RISING_EDGE: 341aaec1a0fSWilliam Breathitt Gray priv->polarity = STM32_LPTIM_CKPOL_RISING_EDGE; 342aaec1a0fSWilliam Breathitt Gray return 0; 343aaec1a0fSWilliam Breathitt Gray case COUNTER_SYNAPSE_ACTION_FALLING_EDGE: 344aaec1a0fSWilliam Breathitt Gray priv->polarity = STM32_LPTIM_CKPOL_FALLING_EDGE; 345aaec1a0fSWilliam Breathitt Gray return 0; 346aaec1a0fSWilliam Breathitt Gray case COUNTER_SYNAPSE_ACTION_BOTH_EDGES: 347aaec1a0fSWilliam Breathitt Gray priv->polarity = STM32_LPTIM_CKPOL_BOTH_EDGES; 348aaec1a0fSWilliam Breathitt Gray return 0; 349aaec1a0fSWilliam Breathitt Gray default: 350aaec1a0fSWilliam Breathitt Gray return -EINVAL; 351aaec1a0fSWilliam Breathitt Gray } 352597f55e3SFabrice Gasnier } 353597f55e3SFabrice Gasnier 354597f55e3SFabrice Gasnier static const struct counter_ops stm32_lptim_cnt_ops = { 355597f55e3SFabrice Gasnier .count_read = stm32_lptim_cnt_read, 356aaec1a0fSWilliam Breathitt Gray .function_read = stm32_lptim_cnt_function_read, 357aaec1a0fSWilliam Breathitt Gray .function_write = stm32_lptim_cnt_function_write, 358aaec1a0fSWilliam Breathitt Gray .action_read = stm32_lptim_cnt_action_read, 359aaec1a0fSWilliam Breathitt Gray .action_write = stm32_lptim_cnt_action_write, 360597f55e3SFabrice Gasnier }; 361597f55e3SFabrice Gasnier 362597f55e3SFabrice Gasnier static struct counter_signal stm32_lptim_cnt_signals[] = { 363597f55e3SFabrice Gasnier { 364597f55e3SFabrice Gasnier .id = 0, 365597f55e3SFabrice Gasnier .name = "Channel 1 Quadrature A" 366597f55e3SFabrice Gasnier }, 367597f55e3SFabrice Gasnier { 368597f55e3SFabrice Gasnier .id = 1, 369597f55e3SFabrice Gasnier .name = "Channel 1 Quadrature B" 370597f55e3SFabrice Gasnier } 371597f55e3SFabrice Gasnier }; 372597f55e3SFabrice Gasnier 373597f55e3SFabrice Gasnier static struct counter_synapse stm32_lptim_cnt_synapses[] = { 374597f55e3SFabrice Gasnier { 375597f55e3SFabrice Gasnier .actions_list = stm32_lptim_cnt_synapse_actions, 376597f55e3SFabrice Gasnier .num_actions = ARRAY_SIZE(stm32_lptim_cnt_synapse_actions), 377597f55e3SFabrice Gasnier .signal = &stm32_lptim_cnt_signals[0] 378597f55e3SFabrice Gasnier }, 379597f55e3SFabrice Gasnier { 380597f55e3SFabrice Gasnier .actions_list = stm32_lptim_cnt_synapse_actions, 381597f55e3SFabrice Gasnier .num_actions = ARRAY_SIZE(stm32_lptim_cnt_synapse_actions), 382597f55e3SFabrice Gasnier .signal = &stm32_lptim_cnt_signals[1] 383597f55e3SFabrice Gasnier } 384597f55e3SFabrice Gasnier }; 385597f55e3SFabrice Gasnier 386597f55e3SFabrice Gasnier /* LP timer with encoder */ 387597f55e3SFabrice Gasnier static struct counter_count stm32_lptim_enc_counts = { 388597f55e3SFabrice Gasnier .id = 0, 389597f55e3SFabrice Gasnier .name = "LPTimer Count", 390597f55e3SFabrice Gasnier .functions_list = stm32_lptim_cnt_functions, 391597f55e3SFabrice Gasnier .num_functions = ARRAY_SIZE(stm32_lptim_cnt_functions), 392597f55e3SFabrice Gasnier .synapses = stm32_lptim_cnt_synapses, 393597f55e3SFabrice Gasnier .num_synapses = ARRAY_SIZE(stm32_lptim_cnt_synapses), 394597f55e3SFabrice Gasnier .ext = stm32_lptim_cnt_ext, 395597f55e3SFabrice Gasnier .num_ext = ARRAY_SIZE(stm32_lptim_cnt_ext) 396597f55e3SFabrice Gasnier }; 397597f55e3SFabrice Gasnier 398597f55e3SFabrice Gasnier /* LP timer without encoder (counter only) */ 399597f55e3SFabrice Gasnier static struct counter_count stm32_lptim_in1_counts = { 400597f55e3SFabrice Gasnier .id = 0, 401597f55e3SFabrice Gasnier .name = "LPTimer Count", 402597f55e3SFabrice Gasnier .functions_list = stm32_lptim_cnt_functions, 403597f55e3SFabrice Gasnier .num_functions = 1, 404597f55e3SFabrice Gasnier .synapses = stm32_lptim_cnt_synapses, 405597f55e3SFabrice Gasnier .num_synapses = 1, 406597f55e3SFabrice Gasnier .ext = stm32_lptim_cnt_ext, 407597f55e3SFabrice Gasnier .num_ext = ARRAY_SIZE(stm32_lptim_cnt_ext) 408597f55e3SFabrice Gasnier }; 409597f55e3SFabrice Gasnier 410597f55e3SFabrice Gasnier static int stm32_lptim_cnt_probe(struct platform_device *pdev) 411597f55e3SFabrice Gasnier { 412597f55e3SFabrice Gasnier struct stm32_lptimer *ddata = dev_get_drvdata(pdev->dev.parent); 413*e75d678dSUwe Kleine-König struct counter_device *counter; 414597f55e3SFabrice Gasnier struct stm32_lptim_cnt *priv; 415*e75d678dSUwe Kleine-König int ret; 416597f55e3SFabrice Gasnier 417597f55e3SFabrice Gasnier if (IS_ERR_OR_NULL(ddata)) 418597f55e3SFabrice Gasnier return -EINVAL; 419597f55e3SFabrice Gasnier 420*e75d678dSUwe Kleine-König counter = devm_counter_alloc(&pdev->dev, sizeof(*priv)); 421*e75d678dSUwe Kleine-König if (!counter) 422597f55e3SFabrice Gasnier return -ENOMEM; 423*e75d678dSUwe Kleine-König priv = counter_priv(counter); 424597f55e3SFabrice Gasnier 425597f55e3SFabrice Gasnier priv->dev = &pdev->dev; 426597f55e3SFabrice Gasnier priv->regmap = ddata->regmap; 427597f55e3SFabrice Gasnier priv->clk = ddata->clk; 428597f55e3SFabrice Gasnier priv->ceiling = STM32_LPTIM_MAX_ARR; 429597f55e3SFabrice Gasnier 430597f55e3SFabrice Gasnier /* Initialize Counter device */ 431*e75d678dSUwe Kleine-König counter->name = dev_name(&pdev->dev); 432*e75d678dSUwe Kleine-König counter->parent = &pdev->dev; 433*e75d678dSUwe Kleine-König counter->ops = &stm32_lptim_cnt_ops; 434597f55e3SFabrice Gasnier if (ddata->has_encoder) { 435*e75d678dSUwe Kleine-König counter->counts = &stm32_lptim_enc_counts; 436*e75d678dSUwe Kleine-König counter->num_signals = ARRAY_SIZE(stm32_lptim_cnt_signals); 437597f55e3SFabrice Gasnier } else { 438*e75d678dSUwe Kleine-König counter->counts = &stm32_lptim_in1_counts; 439*e75d678dSUwe Kleine-König counter->num_signals = 1; 440597f55e3SFabrice Gasnier } 441*e75d678dSUwe Kleine-König counter->num_counts = 1; 442*e75d678dSUwe Kleine-König counter->signals = stm32_lptim_cnt_signals; 443597f55e3SFabrice Gasnier 444597f55e3SFabrice Gasnier platform_set_drvdata(pdev, priv); 445597f55e3SFabrice Gasnier 446*e75d678dSUwe Kleine-König ret = devm_counter_add(&pdev->dev, counter); 447*e75d678dSUwe Kleine-König if (ret < 0) 448*e75d678dSUwe Kleine-König return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n"); 449*e75d678dSUwe Kleine-König 450*e75d678dSUwe Kleine-König return 0; 451597f55e3SFabrice Gasnier } 452597f55e3SFabrice Gasnier 453597f55e3SFabrice Gasnier #ifdef CONFIG_PM_SLEEP 454597f55e3SFabrice Gasnier static int stm32_lptim_cnt_suspend(struct device *dev) 455597f55e3SFabrice Gasnier { 456597f55e3SFabrice Gasnier struct stm32_lptim_cnt *priv = dev_get_drvdata(dev); 457597f55e3SFabrice Gasnier int ret; 458597f55e3SFabrice Gasnier 459597f55e3SFabrice Gasnier /* Only take care of enabled counter: don't disturb other MFD child */ 460597f55e3SFabrice Gasnier if (priv->enabled) { 461597f55e3SFabrice Gasnier ret = stm32_lptim_setup(priv, 0); 462597f55e3SFabrice Gasnier if (ret) 463597f55e3SFabrice Gasnier return ret; 464597f55e3SFabrice Gasnier 465597f55e3SFabrice Gasnier ret = stm32_lptim_set_enable_state(priv, 0); 466597f55e3SFabrice Gasnier if (ret) 467597f55e3SFabrice Gasnier return ret; 468597f55e3SFabrice Gasnier 469597f55e3SFabrice Gasnier /* Force enable state for later resume */ 470597f55e3SFabrice Gasnier priv->enabled = true; 471597f55e3SFabrice Gasnier } 472597f55e3SFabrice Gasnier 473597f55e3SFabrice Gasnier return pinctrl_pm_select_sleep_state(dev); 474597f55e3SFabrice Gasnier } 475597f55e3SFabrice Gasnier 476597f55e3SFabrice Gasnier static int stm32_lptim_cnt_resume(struct device *dev) 477597f55e3SFabrice Gasnier { 478597f55e3SFabrice Gasnier struct stm32_lptim_cnt *priv = dev_get_drvdata(dev); 479597f55e3SFabrice Gasnier int ret; 480597f55e3SFabrice Gasnier 481597f55e3SFabrice Gasnier ret = pinctrl_pm_select_default_state(dev); 482597f55e3SFabrice Gasnier if (ret) 483597f55e3SFabrice Gasnier return ret; 484597f55e3SFabrice Gasnier 485597f55e3SFabrice Gasnier if (priv->enabled) { 486597f55e3SFabrice Gasnier priv->enabled = false; 487597f55e3SFabrice Gasnier ret = stm32_lptim_setup(priv, 1); 488597f55e3SFabrice Gasnier if (ret) 489597f55e3SFabrice Gasnier return ret; 490597f55e3SFabrice Gasnier 491597f55e3SFabrice Gasnier ret = stm32_lptim_set_enable_state(priv, 1); 492597f55e3SFabrice Gasnier if (ret) 493597f55e3SFabrice Gasnier return ret; 494597f55e3SFabrice Gasnier } 495597f55e3SFabrice Gasnier 496597f55e3SFabrice Gasnier return 0; 497597f55e3SFabrice Gasnier } 498597f55e3SFabrice Gasnier #endif 499597f55e3SFabrice Gasnier 500597f55e3SFabrice Gasnier static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops, stm32_lptim_cnt_suspend, 501597f55e3SFabrice Gasnier stm32_lptim_cnt_resume); 502597f55e3SFabrice Gasnier 503597f55e3SFabrice Gasnier static const struct of_device_id stm32_lptim_cnt_of_match[] = { 504597f55e3SFabrice Gasnier { .compatible = "st,stm32-lptimer-counter", }, 505597f55e3SFabrice Gasnier {}, 506597f55e3SFabrice Gasnier }; 507597f55e3SFabrice Gasnier MODULE_DEVICE_TABLE(of, stm32_lptim_cnt_of_match); 508597f55e3SFabrice Gasnier 509597f55e3SFabrice Gasnier static struct platform_driver stm32_lptim_cnt_driver = { 510597f55e3SFabrice Gasnier .probe = stm32_lptim_cnt_probe, 511597f55e3SFabrice Gasnier .driver = { 512597f55e3SFabrice Gasnier .name = "stm32-lptimer-counter", 513597f55e3SFabrice Gasnier .of_match_table = stm32_lptim_cnt_of_match, 514597f55e3SFabrice Gasnier .pm = &stm32_lptim_cnt_pm_ops, 515597f55e3SFabrice Gasnier }, 516597f55e3SFabrice Gasnier }; 517597f55e3SFabrice Gasnier module_platform_driver(stm32_lptim_cnt_driver); 518597f55e3SFabrice Gasnier 519597f55e3SFabrice Gasnier MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); 520597f55e3SFabrice Gasnier MODULE_ALIAS("platform:stm32-lptimer-counter"); 521597f55e3SFabrice Gasnier MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver"); 522597f55e3SFabrice Gasnier MODULE_LICENSE("GPL v2"); 523